Update ModernOpenGLDraw.cs

(cherry picked from commit 6fb44cc3ce47be2c724d6093ef4b3168aacf9480)
This commit is contained in:
Sarofc 2024-07-06 20:44:49 +08:00 committed by ikpil
parent 7ffda46c2f
commit ab04256cdf
3 changed files with 81 additions and 85 deletions

View File

@ -1,4 +1,4 @@
using System; using System;
using DotRecast.Core; using DotRecast.Core;
namespace DotRecast.Recast.Demo.Draw; namespace DotRecast.Recast.Demo.Draw;
@ -9,19 +9,19 @@ public class ArrayBuffer<T>
private T[] _items; private T[] _items;
public int Count => _size; public int Count => _size;
public ArrayBuffer() public ArrayBuffer() : this(512) { }
public ArrayBuffer(int capacity)
{ {
if (capacity <= 0)
throw new ArgumentOutOfRangeException();
_size = 0; _size = 0;
_items = Array.Empty<T>(); _items = new T[capacity];
} }
public void Add(T item) public void Add(T item)
{ {
if (0 >= _items.Length)
{
_items = new T[256];
}
if (_items.Length <= _size) if (_items.Length <= _size)
{ {
var temp = new T[(int)(_size * 1.5)]; var temp = new T[(int)(_size * 1.5)];
@ -37,8 +37,8 @@ public class ArrayBuffer<T>
_size = 0; _size = 0;
} }
public T[] AsArray() public Span<T> AsArray()
{ {
return _items; return _items.AsSpan(0, _size);
} }
} }

View File

@ -1,3 +1,4 @@
using System.Numerics;
using DotRecast.Core.Numerics; using DotRecast.Core.Numerics;
namespace DotRecast.Recast.Demo.Draw; namespace DotRecast.Recast.Demo.Draw;

View File

@ -1,10 +1,11 @@
using System; using System;
using System.IO;
using Silk.NET.OpenGL; using Silk.NET.OpenGL;
using DotRecast.Core.Numerics; using DotRecast.Core.Numerics;
namespace DotRecast.Recast.Demo.Draw; namespace DotRecast.Recast.Demo.Draw;
// TODO use a lot of Memory, 2GB+
public class ModernOpenGLDraw : IOpenGLDraw public class ModernOpenGLDraw : IOpenGLDraw
{ {
private GL _gl; private GL _gl;
@ -19,8 +20,8 @@ public class ModernOpenGLDraw : IOpenGLDraw
private float fogEnd; private float fogEnd;
private bool fogEnabled; private bool fogEnabled;
private int uniformViewMatrix; private int uniformViewMatrix;
private readonly ArrayBuffer<OpenGLVertex> vertices = new(); private readonly ArrayBuffer<OpenGLVertex> vertices = new(512);
private readonly ArrayBuffer<int> elements = new(); private readonly ArrayBuffer<int> elements = new(512);
private GLCheckerTexture _texture; private GLCheckerTexture _texture;
private readonly float[] _viewMatrix = new float[16]; private readonly float[] _viewMatrix = new float[16];
private readonly float[] _projectionMatrix = new float[16]; private readonly float[] _projectionMatrix = new float[16];
@ -36,36 +37,42 @@ public class ModernOpenGLDraw : IOpenGLDraw
public unsafe void Init() public unsafe void Init()
{ {
string SHADER_VERSION = "#version 400\n"; const string SHADER_VERSION = "#version 400\n";
string vertex_shader = SHADER_VERSION + "uniform mat4 ProjMtx;\n" // const string vertex_shader = $@"
+ "uniform mat4 ViewMtx;\n" // {SHADER_VERSION}
+ "in vec3 Position;\n" // uniform mat4 ProjMtx;
+ "in vec2 TexCoord;\n" // uniform mat4 ViewMtx;
+ "in vec4 Color;\n" // in vec3 Position;
+ "out vec2 Frag_UV;\n" // in vec2 TexCoord;
+ "out vec4 Frag_Color;\n" // in vec4 Color;
+ "out float Frag_Depth;\n" // out vec2 Frag_UV;
+ "void main() {\n" // out vec4 Frag_Color;
+ " Frag_UV = TexCoord;\n" // out float Frag_Depth;
+ " Frag_Color = Color;\n" // void main() {{
+ " vec4 VSPosition = ViewMtx * vec4(Position, 1);\n" // Frag_UV = TexCoord;
+ " Frag_Depth = -VSPosition.z;\n" // Frag_Color = Color;
+ " gl_Position = ProjMtx * VSPosition;\n" // vec4 VSPosition = ViewMtx * vec4(Position, 1);
+ "}\n"; Frag_Depth = -VSPosition.z;
string fragment_shader = SHADER_VERSION + "precision mediump float;\n" // gl_Position = ProjMtx * VSPosition;
+ "uniform sampler2D Texture;\n" // }}
+ "uniform float UseTexture;\n" // ";
+ "uniform float EnableFog;\n" // const string fragment_shader = $@"
+ "uniform float FogStart;\n" // {SHADER_VERSION}
+ "uniform float FogEnd;\n" // precision mediump float;
+ "const vec4 FogColor = vec4(0.3f, 0.3f, 0.32f, 1.0f);\n" // uniform sampler2D Texture;
+ "in vec2 Frag_UV;\n" // uniform float UseTexture;
+ "in vec4 Frag_Color;\n" // uniform float EnableFog;
+ "in float Frag_Depth;\n" // uniform float FogStart;
+ "out vec4 Out_Color;\n" // uniform float FogEnd;
+ "void main(){\n" // const vec4 FogColor = vec4(0.3f, 0.3f, 0.32f, 1.0f);
+ " Out_Color = mix(FogColor, Frag_Color * mix(vec4(1), texture(Texture, Frag_UV.st), UseTexture), 1.0 - EnableFog * clamp( (Frag_Depth - FogStart) / (FogEnd - FogStart), 0.0, 1.0) );\n" // in vec2 Frag_UV;
+ "}\n"; in vec4 Frag_Color;
in float Frag_Depth;
out vec4 Out_Color;
void main(){{
Out_Color = mix(FogColor, Frag_Color * mix(vec4(1), texture(Texture, Frag_UV.st), UseTexture), 1.0 - EnableFog * clamp( (Frag_Depth - FogStart) / (FogEnd - FogStart), 0.0, 1.0) );
}}
";
program = _gl.CreateProgram(); program = _gl.CreateProgram();
uint vert_shdr = _gl.CreateShader(GLEnum.VertexShader); uint vert_shdr = _gl.CreateShader(GLEnum.VertexShader);
@ -150,6 +157,10 @@ public class ModernOpenGLDraw : IOpenGLDraw
_gl.BindVertexArray(0); _gl.BindVertexArray(0);
_gl.BindBuffer(GLEnum.ArrayBuffer, 0); _gl.BindBuffer(GLEnum.ArrayBuffer, 0);
_gl.BindBuffer(GLEnum.ElementArrayBuffer, 0); _gl.BindBuffer(GLEnum.ElementArrayBuffer, 0);
//int* range = stackalloc int[2];
//_gl.GetInteger(GetPName.LineWidthRange, range);
//Console.WriteLine($"\nLineWidthRange: {range[0]} {range[1]}");
} }
public void Clear() public void Clear()
@ -191,53 +202,30 @@ public class ModernOpenGLDraw : IOpenGLDraw
// GlBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_BUFFER, GL_STREAM_DRAW); // GlBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_BUFFER, GL_STREAM_DRAW);
// GlBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_BUFFER, GL_STREAM_DRAW); // GlBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_BUFFER, GL_STREAM_DRAW);
uint vboSize = (uint)vertices.Count * 24; _gl.BufferData<OpenGLVertex>(GLEnum.ArrayBuffer, vertices.AsArray(), GLEnum.DynamicDraw);
uint eboSize = currentPrim == DebugDrawPrimitives.QUADS ? (uint)vertices.Count * 6 : (uint)vertices.Count * 4;
_gl.BufferData(GLEnum.ArrayBuffer, vboSize, null, GLEnum.StreamDraw);
_gl.BufferData(GLEnum.ElementArrayBuffer, eboSize, null, GLEnum.StreamDraw);
// load draw vertices & elements directly into vertex + element buffer
if (currentPrim == DebugDrawPrimitives.QUADS)
{ {
byte* pVerts = (byte*)_gl.MapBuffer(GLEnum.ArrayBuffer, GLEnum.WriteOnly); for (int i = 0; i < vertices.Count; i += 4)
byte* pElems = (byte*)_gl.MapBuffer(GLEnum.ElementArrayBuffer, GLEnum.WriteOnly);
//vertices.ForEach(v => v.Store(verts));
fixed (void* v = vertices.AsArray())
{ {
System.Buffer.MemoryCopy(v, pVerts, vboSize, vboSize); elements.Add(i);
elements.Add(i + 1);
elements.Add(i + 2);
elements.Add(i);
elements.Add(i + 2);
elements.Add(i + 3);
} }
if (currentPrim == DebugDrawPrimitives.QUADS)
{
using var unmanagedElems = new UnmanagedMemoryStream(pElems, eboSize, eboSize, FileAccess.Write);
using var bw = new BinaryWriter(unmanagedElems);
for (int i = 0; i < vertices.Count; i += 4)
{
bw.Write(i);
bw.Write(i + 1);
bw.Write(i + 2);
bw.Write(i);
bw.Write(i + 2);
bw.Write(i + 3);
}
}
else
{
for (int i = elements.Count; i < vertices.Count; i++)
{
elements.Add(i);
}
fixed (void* e = elements.AsArray())
{
System.Buffer.MemoryCopy(e, pElems, eboSize, eboSize);
}
}
_gl.UnmapBuffer(GLEnum.ElementArrayBuffer);
_gl.UnmapBuffer(GLEnum.ArrayBuffer);
} }
else
{
for (int i = elements.Count; i < vertices.Count; i++)
{
elements.Add(i);
}
}
_gl.BufferData<int>(GLEnum.ElementArrayBuffer, elements.AsArray(), GLEnum.DynamicDraw);
if (_texture != null) if (_texture != null)
{ {
_texture.Bind(); _texture.Bind();
@ -271,15 +259,22 @@ public class ModernOpenGLDraw : IOpenGLDraw
_gl.BindBuffer(GLEnum.ArrayBuffer, 0); _gl.BindBuffer(GLEnum.ArrayBuffer, 0);
_gl.BindBuffer(GLEnum.ElementArrayBuffer, 0); _gl.BindBuffer(GLEnum.ElementArrayBuffer, 0);
vertices.Clear(); vertices.Clear();
elements.Clear();
_gl.LineWidth(1.0f); _gl.LineWidth(1.0f);
_gl.PointSize(1.0f); _gl.PointSize(1.0f);
} }
public void Vertex(float x, float y, float z, int color) public void Vertex(float x, float y, float z, int color)
{ {
vertices.Add(new OpenGLVertex(x, y, z, color)); vertices.Add(new OpenGLVertex(x, y, z, color));
} }
public unsafe void Vertex(float* pos, int color)
{
vertices.Add(new OpenGLVertex(pos[0], pos[1], pos[2], color));
}
public void Vertex(float[] pos, int color) public void Vertex(float[] pos, int color)
{ {
vertices.Add(new OpenGLVertex(pos, color)); vertices.Add(new OpenGLVertex(pos, color));