Skip to content

Commit 7aab06e

Browse files
author
LoneWandererProductions
committed
sync renderengine
1 parent a04c607 commit 7aab06e

5 files changed

Lines changed: 165 additions & 12 deletions

File tree

‎RenderEngine/GpuMesh.cs‎

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ public sealed class GpuMesh : IDisposable
2929
/// </summary>
3030
private bool _isSolidLayoutConfigured;
3131

32+
/// <summary>
33+
/// The is translucent layout configured
34+
/// </summary>
35+
private bool _isTranslucentLayoutConfigured;
36+
3237
/// <summary>
3338
/// Gets the textured VAO handle.
3439
/// </summary>
@@ -54,6 +59,21 @@ public sealed class GpuMesh : IDisposable
5459
/// </summary>
5560
public int SolidVertexCount { get; private set; }
5661

62+
/// <summary>
63+
/// Gets the VAO handle of the translucent solid geometry (glass, water): drawn in a separate blended pass.
64+
/// </summary>
65+
public int TranslucentVao { get; private set; }
66+
67+
/// <summary>
68+
/// Gets the VBO handle of the translucent solid geometry.
69+
/// </summary>
70+
public int TranslucentVbo { get; private set; }
71+
72+
/// <summary>
73+
/// Gets the translucent vertex count.
74+
/// </summary>
75+
public int TranslucentVertexCount { get; private set; }
76+
5777
/// <summary>
5878
/// Gets the sub-mesh ranges for multi-textured rendering.
5979
/// </summary>
@@ -163,11 +183,47 @@ public void UploadSolid(IntPtr dataPointer, int floatCount, bool isDynamic = fal
163183
GL.BindVertexArray(0);
164184
}
165185

186+
/// <summary>
187+
/// Uploads translucent untextured geometry (7 floats/vertex: X,Y,Z,R,G,B,A). It is kept apart from the opaque
188+
/// solid part so the renderer can draw it after everything opaque, with blending on and depth writes off.
189+
/// </summary>
190+
/// <param name="dataPointer">The data pointer.</param>
191+
/// <param name="floatCount">The float count.</param>
192+
/// <param name="isDynamic">if set to <c>true</c> [is dynamic].</param>
193+
public void UploadTranslucent(IntPtr dataPointer, int floatCount, bool isDynamic = false)
194+
{
195+
TranslucentVertexCount = floatCount / 7;
196+
if (floatCount == 0) return;
197+
198+
if (TranslucentVao == 0) TranslucentVao = GL.GenVertexArray();
199+
if (TranslucentVbo == 0) TranslucentVbo = GL.GenBuffer();
200+
201+
GL.BindVertexArray(TranslucentVao);
202+
GL.BindBuffer(BufferTarget.ArrayBuffer, TranslucentVbo);
203+
204+
var usage = isDynamic ? BufferUsageHint.DynamicDraw : BufferUsageHint.StaticDraw;
205+
GL.BufferData(BufferTarget.ArrayBuffer, floatCount * sizeof(float), dataPointer, usage);
206+
207+
if (!_isTranslucentLayoutConfigured)
208+
{
209+
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 7 * sizeof(float), 0);
210+
GL.EnableVertexAttribArray(0);
211+
GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, 7 * sizeof(float),
212+
3 * sizeof(float));
213+
GL.EnableVertexAttribArray(1);
214+
215+
_isTranslucentLayoutConfigured = true;
216+
}
217+
218+
GL.BindVertexArray(0);
219+
}
220+
166221
/// <summary>
167222
/// Resets this instance.
168223
/// </summary>
169224
public void Reset()
170225
{
226+
TranslucentVertexCount = 0;
171227
SolidVertexCount = 0;
172228
Ranges.Clear();
173229
}
@@ -199,8 +255,21 @@ public void Dispose()
199255
SolidVao = 0;
200256
}
201257

258+
if (TranslucentVbo != 0)
259+
{
260+
GL.DeleteBuffer(TranslucentVbo);
261+
TranslucentVbo = 0;
262+
}
263+
264+
if (TranslucentVao != 0)
265+
{
266+
GL.DeleteVertexArray(TranslucentVao);
267+
TranslucentVao = 0;
268+
}
269+
202270
_isTexturedLayoutConfigured = false;
203271
_isSolidLayoutConfigured = false;
272+
_isTranslucentLayoutConfigured = false;
204273
Ranges.Clear();
205274
}
206275
}

‎RenderEngine/ProceduralEntry.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ namespace RenderEngine
1818
internal readonly record struct ProceduralEntry(
1919
string Name,
2020
string Description,
21-
Func<int, int, object, RawTextureBuffer?> Generator
21+
Func<int, int, object?, RawTextureBuffer?> Generator
2222
);
2323
}

‎RenderEngine/RenderBatch.cs‎

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ public sealed class RenderBatch
4242
/// </summary>
4343
public readonly UnmanagedList<float> Solid3DVertices = new(16384);
4444

45+
/// <summary>
46+
/// The translucent solid 3D vertices (any vertex alpha below 255: glass, water). Same layout as
47+
/// <see cref="Solid3DVertices"/>, but drawn in a later blended pass instead of with the opaque geometry.
48+
/// </summary>
49+
public readonly UnmanagedList<float> Translucent3DVertices = new(2048);
50+
4551
/// <summary>
4652
/// The textured 3D batches
4753
/// Layout: X, Y, Z, U, V, R, G, B, A (9 floats) - Grouped by TextureId
@@ -158,9 +164,10 @@ public void AddTexturedTriangle((int x, int y) p1, (int x, int y) p2, (int x, in
158164
/// <param name="color">The color.</param>
159165
public void AddSolid3DTriangle(Vector3 v1, Vector3 v2, Vector3 v3, (int r, int g, int b, int a) color)
160166
{
161-
AddColoredVertex3D(v1, color, Solid3DVertices);
162-
AddColoredVertex3D(v2, color, Solid3DVertices);
163-
AddColoredVertex3D(v3, color, Solid3DVertices);
167+
var target = color.a < 255 ? Translucent3DVertices : Solid3DVertices;
168+
AddColoredVertex3D(v1, color, target);
169+
AddColoredVertex3D(v2, color, target);
170+
AddColoredVertex3D(v3, color, target);
164171
}
165172

166173
/// <summary>
@@ -170,9 +177,10 @@ public void AddSolid3DTriangle(
170177
Vector3 v1, Vector3 v2, Vector3 v3,
171178
(int r, int g, int b, int a) c1, (int r, int g, int b, int a) c2, (int r, int g, int b, int a) c3)
172179
{
173-
AddColoredVertex3D(v1, c1, Solid3DVertices);
174-
AddColoredVertex3D(v2, c2, Solid3DVertices);
175-
AddColoredVertex3D(v3, c3, Solid3DVertices);
180+
var target = c1.a < 255 || c2.a < 255 || c3.a < 255 ? Translucent3DVertices : Solid3DVertices;
181+
AddColoredVertex3D(v1, c1, target);
182+
AddColoredVertex3D(v2, c2, target);
183+
AddColoredVertex3D(v3, c3, target);
176184
}
177185

178186
/// <summary>
@@ -324,6 +332,7 @@ public void Clear()
324332
SolidLineVertices.Clear();
325333
SolidTriangleVertices.Clear();
326334
Solid3DVertices.Clear();
335+
Translucent3DVertices.Clear();
327336

328337
foreach (var list in TexturedBatches.Values)
329338
{

‎RenderEngine/Simple2DRenderer.cs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public sealed class Simple2DRenderer : IDisposable
4949
/// <summary>
5050
/// The resources
5151
/// </summary>
52-
private readonly GlResourceManager _resources;
52+
private readonly GlResourceManager? _resources;
5353

5454
// --- Solid VAO/VBO ---
5555

@@ -152,7 +152,7 @@ public void Resize(int width, int height)
152152
/// <param name="width">Width of the render viewport in pixels.</param>
153153
/// <param name="height">Height of the render viewport in pixels.</param>
154154
/// <param name="resources">The GL resource manager instance.</param>
155-
public Simple2DRenderer(int width, int height, GlResourceManager resources)
155+
public Simple2DRenderer(int width, int height, GlResourceManager? resources)
156156
{
157157
Width = width;
158158
Height = height;
@@ -1073,4 +1073,4 @@ public void Dispose()
10731073
}
10741074
}
10751075
}
1076-
}
1076+
}

‎RenderEngine/Simple3DRenderer.cs‎

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public sealed class Simple3DRenderer : IDisposable
5050
/// <summary>
5151
/// Reference tracker managing engine-level compiled shader assets and texture definitions.
5252
/// </summary>
53-
private readonly GlResourceManager _resources;
53+
private readonly GlResourceManager? _resources;
5454

5555
/// <summary>
5656
/// Hardware layout buffer markers tracking active states
@@ -87,6 +87,12 @@ public sealed class Simple3DRenderer : IDisposable
8787
/// <summary>
8888
/// The active program
8989
/// </summary>
90+
/// <summary>
91+
/// Baked meshes that carry translucent geometry (glass, water) drawn this frame. They are drawn once the opaque
92+
/// world is complete, in <see cref="DrawTranslucentMeshes"/>, so they blend with what lies behind them.
93+
/// </summary>
94+
private readonly List<GpuMesh> _translucentMeshes = new();
95+
9096
private int _activeProgram = -1;
9197

9298
/// <summary>
@@ -220,7 +226,7 @@ public sealed class Simple3DRenderer : IDisposable
220226
/// <param name="width">The target canvas width.</param>
221227
/// <param name="height">The target canvas height.</param>
222228
/// <param name="resources">The shared unmanaged resource coordinator.</param>
223-
public Simple3DRenderer(int width, int height, GlResourceManager resources)
229+
public Simple3DRenderer(int width, int height, GlResourceManager? resources)
224230
{
225231
_resources = resources;
226232
UpdateProjection(width, height);
@@ -539,6 +545,7 @@ public void BeginFrame()
539545
_activeProgram = -1;
540546
_activeVao = -1;
541547
_activeTexture = -1;
548+
_translucentMeshes.Clear();
542549

543550
ApplyFrameState();
544551

@@ -590,6 +597,9 @@ public void BeginFrame()
590597
/// </summary>
591598
public void EndFrame()
592599
{
600+
// Everything opaque is in the depth buffer by now: blend the glass and the water over it.
601+
DrawTranslucentMeshes();
602+
593603
if (!_framePostProcessed || !_fboInitialized) return;
594604

595605
// 1. Restore GLWpfControl's target FBO and Viewport
@@ -808,6 +818,22 @@ public unsafe void Flush(RenderBatch batch)
808818
GL.DrawArrays(PrimitiveType.Triangles, 0, batch.Solid3DVertices.Length / 7);
809819
}
810820

821+
if (batch.Translucent3DVertices.Length > 0)
822+
{
823+
BindProgram(_shaderSolid);
824+
BindVao(_vaoSolid);
825+
EnsureSolidMatrices();
826+
827+
EnsureBufferCapacity(_vboSolid, ref _vboSolidCapacity, batch.Translucent3DVertices.Length);
828+
GL.BindBuffer(BufferTarget.ArrayBuffer, _vboSolid);
829+
GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero,
830+
batch.Translucent3DVertices.Length * sizeof(float), (IntPtr)batch.Translucent3DVertices.Pointer);
831+
832+
BeginBlendedPass();
833+
GL.DrawArrays(PrimitiveType.Triangles, 0, batch.Translucent3DVertices.Length / 7);
834+
EndBlendedPass();
835+
}
836+
811837
if (batch.Textured3DBatches.Count > 0)
812838
{
813839
BindProgram(_shaderTex);
@@ -844,6 +870,53 @@ public unsafe void Flush(RenderBatch batch)
844870
BindVao(0);
845871
}
846872

873+
/// <summary>
874+
/// Switches to alpha blending without depth writes: translucent surfaces still hide behind opaque ones (depth
875+
/// test on) but do not hide each other or what is drawn after them.
876+
/// </summary>
877+
private static void BeginBlendedPass()
878+
{
879+
GL.Enable(EnableCap.Blend);
880+
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
881+
GL.DepthMask(false);
882+
}
883+
884+
/// <summary>
885+
/// Back to the opaque state set by <see cref="ApplyFrameState"/>.
886+
/// </summary>
887+
private static void EndBlendedPass()
888+
{
889+
GL.DepthMask(true);
890+
GL.Disable(EnableCap.Blend);
891+
}
892+
893+
/// <summary>
894+
/// Draws the translucent part (glass, water) of every mesh drawn this frame, after all opaque geometry.
895+
/// </summary>
896+
private void DrawTranslucentMeshes()
897+
{
898+
if (_translucentMeshes.Count == 0) return;
899+
900+
EnsureInitialized();
901+
902+
BindProgram(_shaderSolid);
903+
EnsureSolidMatrices();
904+
BeginBlendedPass();
905+
906+
for (var i = 0; i < _translucentMeshes.Count; i++)
907+
{
908+
var mesh = _translucentMeshes[i];
909+
if (mesh.TranslucentVao == 0 || mesh.TranslucentVertexCount <= 0) continue;
910+
911+
BindVao(mesh.TranslucentVao);
912+
GL.DrawArrays(PrimitiveType.Triangles, 0, mesh.TranslucentVertexCount);
913+
}
914+
915+
EndBlendedPass();
916+
BindVao(0);
917+
_translucentMeshes.Clear();
918+
}
919+
847920
/// <summary>
848921
/// Renders a persistent mesh directly from GPU VRAM with zero PCIe memory transfers.
849922
/// </summary>
@@ -861,6 +934,8 @@ public void DrawStaticMesh(GpuMesh mesh)
861934
GL.DrawArrays(PrimitiveType.Triangles, 0, mesh.SolidVertexCount);
862935
}
863936

937+
if (mesh.TranslucentVertexCount > 0) _translucentMeshes.Add(mesh);
938+
864939
if (mesh.Ranges.Count == 0) return;
865940

866941
BindProgram(_shaderTex);

0 commit comments

Comments
 (0)