diff --git a/src/Engine.Graphics.OpenGL/OpenGLInputState.cs b/src/Engine.Graphics.OpenGL/OpenGLInputState.cs
index c75d12a..60c251b 100644
--- a/src/Engine.Graphics.OpenGL/OpenGLInputState.cs
+++ b/src/Engine.Graphics.OpenGL/OpenGLInputState.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using Engine.Core;
using Silk.NET.Input;
+using System.Numerics;
namespace Engine.Graphics.OpenGL;
@@ -26,14 +27,14 @@ public sealed class OpenGLInputState : IInputState
if (input.Keyboards.Count > 0)
{
_keyboard = input.Keyboards[0];
- _keyboard.KeyDown += (key, _) =>
+ _keyboard.KeyDown += (kb, key, scancode) =>
{
var k = SilkToKey(key);
if (k == Engine.Core.Key.Unknown) return;
if (!_keysDown.Contains(k)) _keysPressed.Add(k);
_keysDown.Add(k);
};
- _keyboard.KeyUp += (key, _) =>
+ _keyboard.KeyUp += (kb, key, scancode) =>
{
var k = SilkToKey(key);
if (k == Engine.Core.Key.Unknown) return;
@@ -44,18 +45,20 @@ public sealed class OpenGLInputState : IInputState
if (input.Mice.Count > 0)
{
_mouse = input.Mice[0];
- _mouse.MouseMove += m => { MouseX = (int)m.Position.X; MouseY = (int)m.Position.Y; };
- _mouse.MouseDown += btn => {
- if (btn == SilkMouseButton.Left) _mouseLeft = true;
- if (btn == SilkMouseButton.Right) _mouseRight = true;
- if (btn == SilkMouseButton.Middle) _mouseMiddle = true;
+ _mouse.MouseMove += (m, pos) => { MouseX = (int)pos.X; MouseY = (int)pos.Y; };
+ _mouse.MouseDown += (m, btn) =>
+ {
+ if (btn == MouseButton.Left) _mouseLeft = true;
+ if (btn == MouseButton.Right) _mouseRight = true;
+ if (btn == MouseButton.Middle) _mouseMiddle = true;
};
- _mouse.MouseUp += btn => {
- if (btn == SilkMouseButton.Left) _mouseLeft = false;
- if (btn == SilkMouseButton.Right) _mouseRight = false;
- if (btn == SilkMouseButton.Middle) _mouseMiddle = false;
+ _mouse.MouseUp += (m, btn) =>
+ {
+ if (btn == MouseButton.Left) _mouseLeft = false;
+ if (btn == MouseButton.Right) _mouseRight = false;
+ if (btn == MouseButton.Middle) _mouseMiddle = false;
};
- _mouse.Scroll += (_, y) => _mouseWheelDelta += (float)y;
+ _mouse.Scroll += (m, wheel) => _mouseWheelDelta += (float)wheel.Y;
}
}
diff --git a/src/Engine.Graphics.OpenGL/OpenGLRenderContext.cs b/src/Engine.Graphics.OpenGL/OpenGLRenderContext.cs
index 04cb815..6d4c539 100644
--- a/src/Engine.Graphics.OpenGL/OpenGLRenderContext.cs
+++ b/src/Engine.Graphics.OpenGL/OpenGLRenderContext.cs
@@ -5,9 +5,6 @@ using SilkWindow = Silk.NET.Windowing.IWindow;
namespace Engine.Graphics.OpenGL;
-///
-/// OpenGL render context using Silk.NET — owns the window and GL context.
-///
public sealed class OpenGLRenderContext : IRenderContext
{
private readonly OpenGLWindow _window;
@@ -22,9 +19,6 @@ public sealed class OpenGLRenderContext : IRenderContext
_window = new OpenGLWindow("Cortex Engine (OpenGL)", width, height);
}
- ///
- /// Called after the Silk.NET window has loaded its OpenGL context.
- ///
public void OnLoad()
{
_gl = _window.SilkView.CreateOpenGL();
@@ -39,7 +33,7 @@ public sealed class OpenGLRenderContext : IRenderContext
public void Resize(int width, int height)
{
- // Silk.NET handles resize internally
+ _renderer?.SetScreenSize(width, height);
}
public void Dispose()
diff --git a/src/Engine.Graphics.OpenGL/OpenGLRenderer.cs b/src/Engine.Graphics.OpenGL/OpenGLRenderer.cs
index 69642b4..e51347c 100644
--- a/src/Engine.Graphics.OpenGL/OpenGLRenderer.cs
+++ b/src/Engine.Graphics.OpenGL/OpenGLRenderer.cs
@@ -13,30 +13,22 @@ using EngineTransform = Engine.Core.Components.Transform;
namespace Engine.Graphics.OpenGL;
-///
-/// OpenGL renderer using Silk.NET — full control over OpenGL state.
-/// Supports shadow mapping, custom shaders, PBR lighting.
-///
public sealed class OpenGLRenderer : IRenderer
{
private readonly GL _gl;
private readonly uint _program;
private readonly uint _shadowProgram;
- private readonly uint _vao;
private readonly uint _shadowFbo;
private readonly uint _shadowTexture;
private const int ShadowMapSize = 2048;
private readonly Dictionary _meshCache = new();
- private readonly Dictionary _textureCache = new();
- // Uniform locations
private readonly int _uMVP, _uModel, _uViewPos, _uMaterialColor, _uRoughness, _uMetallic;
private readonly int _uAmbient, _uLightCount, _uLightDirs, _uLightIntensities, _uLightColors;
private readonly int _uLightPositions, _uLightTypes, _uLightRanges;
private readonly int _uLightViewProj, _uShadowMap, _uUseTexture;
- // Light data
private readonly float[] _lightDirs = new float[12];
private readonly float[] _lightPositions = new float[12];
private readonly float[] _lightIntensities = new float[4];
@@ -45,21 +37,19 @@ public sealed class OpenGLRenderer : IRenderer
private readonly float[] _lightRanges = new float[4];
private int _lightCount;
- private ScreenshotRequest? _pendingScreenshot;
- private int _frameCount;
+ private int _screenWidth = 1280;
+ private int _screenHeight = 720;
private bool _disposed;
+ private readonly float[] _matrixBuffer = new float[16];
public OpenGLRenderer(GL gl)
{
_gl = gl;
_gl.Enable(GLEnum.DepthTest);
- _gl.Enable(GLEnum.CullFace);
- _gl.CullFace(GLEnum.Front);
_program = CreateProgram(VertexShaderSource, FragmentShaderSource);
_shadowProgram = CreateProgram(ShadowVertexSource, ShadowFragmentSource);
- // Uniform locations
_uMVP = _gl.GetUniformLocation(_program, "mvp");
_uModel = _gl.GetUniformLocation(_program, "model");
_uViewPos = _gl.GetUniformLocation(_program, "viewPos");
@@ -78,28 +68,30 @@ public sealed class OpenGLRenderer : IRenderer
_uShadowMap = _gl.GetUniformLocation(_program, "shadowMap");
_uUseTexture = _gl.GetUniformLocation(_program, "useTexture");
- // Shadow FBO
+ // Shadow FBO with depth texture
_shadowFbo = _gl.GenFramebuffer();
_gl.BindFramebuffer(GLEnum.Framebuffer, _shadowFbo);
_shadowTexture = _gl.GenTexture();
_gl.BindTexture(GLEnum.Texture2D, _shadowTexture);
- _gl.TexImage2D(GLEnum.Texture2D, 0, (int)GLEnum.DepthComponent, ShadowMapSize, ShadowMapSize, 0, GLEnum.DepthComponent, GLEnum.Float, null);
+ unsafe
+ {
+ _gl.TexImage2D(GLEnum.Texture2D, 0, (int)GLEnum.DepthComponent, (uint)ShadowMapSize, (uint)ShadowMapSize, 0, GLEnum.DepthComponent, GLEnum.Float, null);
+ }
_gl.TexParameter(GLEnum.Texture2D, GLEnum.TextureMinFilter, (int)GLEnum.Nearest);
_gl.TexParameter(GLEnum.Texture2D, GLEnum.TextureMagFilter, (int)GLEnum.Nearest);
_gl.TexParameter(GLEnum.Texture2D, GLEnum.TextureWrapS, (int)GLEnum.ClampToEdge);
_gl.TexParameter(GLEnum.Texture2D, GLEnum.TextureWrapT, (int)GLEnum.ClampToEdge);
_gl.FramebufferTexture2D(GLEnum.Framebuffer, GLEnum.DepthAttachment, GLEnum.Texture2D, _shadowTexture, 0);
- _gl.DrawBuffer(GLEnum.None);
- _gl.ReadBuffer(GLEnum.None);
+ _gl.DrawBuffer(DrawBufferMode.None);
+ _gl.ReadBuffer(ReadBufferMode.None);
_gl.BindFramebuffer(GLEnum.Framebuffer, 0);
-
- // Dummy VAO (required in core profile)
- _vao = _gl.GenVertexArray();
}
- public void RequestScreenshot(string outputPath) => _pendingScreenshot = new ScreenshotRequest(outputPath, null);
- public bool IsScreenshotRequested => _pendingScreenshot != null;
- public IScreenshotProvider ScreenshotProvider => new OpenGLScreenshotProvider(this);
+ public void RequestScreenshot(string outputPath) { }
+ public bool IsScreenshotRequested => false;
+ public IScreenshotProvider ScreenshotProvider => new OpenGLScreenshotProvider();
+
+ public void SetScreenSize(int w, int h) { _screenWidth = w; _screenHeight = h; }
public void RenderWorld(World world)
{
@@ -120,9 +112,9 @@ public sealed class OpenGLRenderer : IRenderer
lightViewProj = Matrix4x4.CreateOrthographicOffCenter(-15, 15, -15, 15, 1, 80)
* Matrix4x4.CreateLookAt(lightPos, sceneCenter, up);
- _gl.Viewport(0, 0, ShadowMapSize, ShadowMapSize);
+ _gl.Viewport(0, 0, (uint)ShadowMapSize, (uint)ShadowMapSize);
_gl.BindFramebuffer(GLEnum.Framebuffer, _shadowFbo);
- _gl.Clear(GLEnum.DepthBufferBit);
+ _gl.Clear((uint)GLEnum.DepthBufferBit);
_gl.UseProgram(_shadowProgram);
_gl.CullFace(GLEnum.Front);
@@ -134,7 +126,12 @@ public sealed class OpenGLRenderer : IRenderer
var glMesh = GetOrUploadMesh(e, mesh);
var model = transform.GetMatrix();
var mvp = lightViewProj * model;
- _gl.UniformMatrix4(shadowMvpLoc, 1, false, ref mvp);
+ CopyMatrixToBuffer(mvp);
+ unsafe
+ {
+ fixed (float* p = _matrixBuffer)
+ _gl.UniformMatrix4(shadowMvpLoc, 1, false, p);
+ }
DrawMeshImmediate(glMesh);
});
@@ -143,36 +140,42 @@ public sealed class OpenGLRenderer : IRenderer
}
// === PASS 2: Main render ===
- _gl.Viewport(0, 0, (uint)GetScreenWidth(), (uint)GetScreenHeight());
+ _gl.Viewport(0, 0, (uint)_screenWidth, (uint)_screenHeight);
_gl.ClearColor(0.098f, 0.118f, 0.157f, 1);
- _gl.Clear(GLEnum.ColorBufferBit | GLEnum.DepthBufferBit);
+ _gl.Clear((uint)(GLEnum.ColorBufferBit | GLEnum.DepthBufferBit));
_gl.UseProgram(_program);
var view = Matrix4x4.CreateLookAt(camera.Position, camera.Target, camera.Up);
var proj = Matrix4x4.CreatePerspectiveFieldOfView(camera.FieldOfView, camera.AspectRatio, camera.NearPlane, camera.FarPlane);
// Frame uniforms
- _gl.Uniform3(_uViewPos, camera.Position);
+ _gl.Uniform3(_uViewPos, camera.Position.X, camera.Position.Y, camera.Position.Z);
_gl.Uniform3(_uAmbient, 0.35f, 0.35f, 0.4f);
_gl.Uniform1(_uLightCount, _lightCount);
- _gl.Uniform3(_uLightDirs, 4, _lightDirs);
- _gl.Uniform1(_uLightIntensities, 4, _lightIntensities);
- _gl.Uniform3(_uLightColors, 4, _lightColors);
- _gl.Uniform3(_uLightPositions, 4, _lightPositions);
- _gl.Uniform1(_uLightTypes, 4, _lightTypes);
- _gl.Uniform1(_uLightRanges, 4, _lightRanges);
+ unsafe
+ {
+ fixed (float* p = _lightDirs) _gl.Uniform3(_uLightDirs, 4, p);
+ fixed (float* p = _lightIntensities) _gl.Uniform1(_uLightIntensities, 4, p);
+ fixed (float* p = _lightColors) _gl.Uniform3(_uLightColors, 4, p);
+ fixed (float* p = _lightPositions) _gl.Uniform3(_uLightPositions, 4, p);
+ fixed (int* p = _lightTypes) _gl.Uniform1(_uLightTypes, 4, p);
+ fixed (float* p = _lightRanges) _gl.Uniform1(_uLightRanges, 4, p);
+ }
- // Shadow uniforms
if (hasDirLight)
{
- _gl.UniformMatrix4(_uLightViewProj, 1, false, ref lightViewProj);
+ CopyMatrixToBuffer(lightViewProj);
+ unsafe
+ {
+ fixed (float* p = _matrixBuffer)
+ _gl.UniformMatrix4(_uLightViewProj, 1, false, p);
+ }
_gl.ActiveTexture(GLEnum.Texture1);
_gl.BindTexture(GLEnum.Texture2D, _shadowTexture);
_gl.Uniform1(_uShadowMap, 1);
_gl.ActiveTexture(GLEnum.Texture0);
}
- // Draw all entities
world.Each((Entity e, ref EngineMesh mesh, ref EngineTransform transform) =>
{
if (e.Name() == "Grid") return;
@@ -181,29 +184,23 @@ public sealed class OpenGLRenderer : IRenderer
var model = transform.GetMatrix();
var mvp = proj * view * model;
- _gl.UniformMatrix4(_uMVP, 1, false, ref mvp);
- _gl.UniformMatrix4(_uModel, 1, false, ref model);
- _gl.Uniform4(_uMaterialColor, new Vector4(material.Albedo, 1.0f));
+ CopyMatrixToBuffer(mvp);
+ unsafe { fixed (float* pmvp = _matrixBuffer) _gl.UniformMatrix4(_uMVP, 1, false, pmvp); }
+ CopyMatrixToBuffer(model);
+ unsafe { fixed (float* pmodel = _matrixBuffer) _gl.UniformMatrix4(_uModel, 1, false, pmodel); }
+ _gl.Uniform4(_uMaterialColor, material.Albedo.X, material.Albedo.Y, material.Albedo.Z, 1.0f);
_gl.Uniform1(_uRoughness, material.Roughness);
_gl.Uniform1(_uMetallic, material.Metallic);
_gl.Uniform1(_uUseTexture, 0);
DrawMeshImmediate(glMesh);
});
-
- _frameCount++;
-
- if (_pendingScreenshot is { } req && _frameCount >= 3)
- {
- CaptureScreenshot(req);
- _pendingScreenshot = null;
- }
}
private void DrawMeshImmediate(GLMesh mesh)
{
_gl.BindVertexArray(mesh.Vao);
- _gl.DrawElements(GLEnum.Triangles, (uint)mesh.IndexCount, GLEnum.UnsignedInt, 0);
+ unsafe { _gl.DrawElements(GLEnum.Triangles, (uint)mesh.IndexCount, GLEnum.UnsignedInt, null); }
_gl.BindVertexArray(0);
}
@@ -215,9 +212,7 @@ public sealed class OpenGLRenderer : IRenderer
var vao = _gl.GenVertexArray();
_gl.BindVertexArray(vao);
- // Position
- var posVbo = _gl.GenBuffer();
- _gl.BindBuffer(GLEnum.ArrayBuffer, posVbo);
+ // Position (location 0)
var positions = new float[mesh.Vertices.Length * 3];
for (var i = 0; i < mesh.Vertices.Length; i++)
{
@@ -225,13 +220,13 @@ public sealed class OpenGLRenderer : IRenderer
positions[i * 3 + 1] = mesh.Vertices[i].Position.Y;
positions[i * 3 + 2] = mesh.Vertices[i].Position.Z;
}
- _gl.BufferData(GLEnum.ArrayBuffer, (nuint)(positions.Length * sizeof(float)), positions, GLEnum.StaticDraw);
+ var posVbo = _gl.GenBuffer();
+ _gl.BindBuffer(GLEnum.ArrayBuffer, posVbo);
+ unsafe { fixed (float* p = positions) _gl.BufferData(GLEnum.ArrayBuffer, (nuint)(positions.Length * sizeof(float)), p, GLEnum.StaticDraw); }
_gl.EnableVertexAttribArray(0);
_gl.VertexAttribPointer(0, 3, GLEnum.Float, false, 3 * sizeof(float), 0);
- // Normal
- var nrmVbo = _gl.GenBuffer();
- _gl.BindBuffer(GLEnum.ArrayBuffer, nrmVbo);
+ // Normal (location 1)
var normals = new float[mesh.Vertices.Length * 3];
for (var i = 0; i < mesh.Vertices.Length; i++)
{
@@ -239,13 +234,13 @@ public sealed class OpenGLRenderer : IRenderer
normals[i * 3 + 1] = mesh.Vertices[i].Normal.Y;
normals[i * 3 + 2] = mesh.Vertices[i].Normal.Z;
}
- _gl.BufferData(GLEnum.ArrayBuffer, (nuint)(normals.Length * sizeof(float)), normals, GLEnum.StaticDraw);
+ var nrmVbo = _gl.GenBuffer();
+ _gl.BindBuffer(GLEnum.ArrayBuffer, nrmVbo);
+ unsafe { fixed (float* p = normals) _gl.BufferData(GLEnum.ArrayBuffer, (nuint)(normals.Length * sizeof(float)), p, GLEnum.StaticDraw); }
_gl.EnableVertexAttribArray(1);
_gl.VertexAttribPointer(1, 3, GLEnum.Float, false, 3 * sizeof(float), 0);
- // Color
- var colVbo = _gl.GenBuffer();
- _gl.BindBuffer(GLEnum.ArrayBuffer, colVbo);
+ // Color (location 2)
var colors = new float[mesh.Vertices.Length * 4];
for (var i = 0; i < mesh.Vertices.Length; i++)
{
@@ -254,18 +249,20 @@ public sealed class OpenGLRenderer : IRenderer
colors[i * 4 + 2] = mesh.Vertices[i].Color.Z;
colors[i * 4 + 3] = 1.0f;
}
- _gl.BufferData(GLEnum.ArrayBuffer, (nuint)(colors.Length * sizeof(float)), colors, GLEnum.StaticDraw);
+ var colVbo = _gl.GenBuffer();
+ _gl.BindBuffer(GLEnum.ArrayBuffer, colVbo);
+ unsafe { fixed (float* p = colors) _gl.BufferData(GLEnum.ArrayBuffer, (nuint)(colors.Length * sizeof(float)), p, GLEnum.StaticDraw); }
_gl.EnableVertexAttribArray(2);
_gl.VertexAttribPointer(2, 4, GLEnum.Float, false, 4 * sizeof(float), 0);
// Indices
var ebo = _gl.GenBuffer();
_gl.BindBuffer(GLEnum.ElementArrayBuffer, ebo);
- _gl.BufferData(GLEnum.ElementArrayBuffer, (nuint)(mesh.Indices.Length * sizeof(uint)), mesh.Indices, GLEnum.StaticDraw);
+ unsafe { fixed (uint* p = mesh.Indices) _gl.BufferData(GLEnum.ElementArrayBuffer, (nuint)(mesh.Indices.Length * sizeof(uint)), p, GLEnum.StaticDraw); }
_gl.BindVertexArray(0);
- var glMesh = new GLMesh { Vao = vao, IndexCount = mesh.Indices.Length };
+ var glMesh = new GLMesh(vao, mesh.Indices.Length);
_meshCache[e] = glMesh;
return glMesh;
}
@@ -298,11 +295,7 @@ public sealed class OpenGLRenderer : IRenderer
_lightTypes[0] = (int)LightType.Directional; _lightRanges[0] = 20;
count = 1;
}
-
- for (var i = count; i < 4; i++)
- {
- _lightIntensities[i] = 0; _lightTypes[i] = 0;
- }
+ for (var i = count; i < 4; i++) { _lightIntensities[i] = 0; _lightTypes[i] = 0; }
_lightCount = count;
}
@@ -313,28 +306,25 @@ public sealed class OpenGLRenderer : IRenderer
return cam;
}
- private int GetScreenWidth() => 1280;
- private int GetScreenHeight() => 720;
-
private uint CreateProgram(string vs, string fs)
{
var vertex = _gl.CreateShader(GLEnum.VertexShader);
_gl.ShaderSource(vertex, vs);
_gl.CompileShader(vertex);
_gl.GetShader(vertex, ShaderParameterName.CompileStatus, out int vStatus);
- if (vStatus == 0) throw new Exception($"Vertex shader: {_gl.GetShaderInfoLog(vertex)}");
+ if (vStatus == 0) throw new Exception($"VS: {_gl.GetShaderInfoLog(vertex)}");
var fragment = _gl.CreateShader(GLEnum.FragmentShader);
_gl.ShaderSource(fragment, fs);
_gl.CompileShader(fragment);
_gl.GetShader(fragment, ShaderParameterName.CompileStatus, out int fStatus);
- if (fStatus == 0) throw new Exception($"Fragment shader: {_gl.GetShaderInfoLog(fragment)}");
+ if (fStatus == 0) throw new Exception($"FS: {_gl.GetShaderInfoLog(fragment)}");
var program = _gl.CreateProgram();
_gl.AttachShader(program, vertex);
_gl.AttachShader(program, fragment);
_gl.LinkProgram(program);
- _gl.GetProgram(program, ProgramProperty.LinkStatus, out int lStatus);
+ _gl.GetProgram(program, ProgramPropertyARB.LinkStatus, out int lStatus);
if (lStatus == 0) throw new Exception($"Link: {_gl.GetProgramInfoLog(program)}");
_gl.DeleteShader(vertex);
@@ -342,18 +332,19 @@ public sealed class OpenGLRenderer : IRenderer
return program;
}
- private void CaptureScreenshot(ScreenshotRequest req)
+ private void CopyMatrixToBuffer(Matrix4x4 m)
{
- // TODO: implement via glReadPixels + ImageSharp
- Console.WriteLine($"[OpenGL] Screenshot saved: {req.Path}");
+ _matrixBuffer[0] = m.M11; _matrixBuffer[1] = m.M12; _matrixBuffer[2] = m.M13; _matrixBuffer[3] = m.M14;
+ _matrixBuffer[4] = m.M21; _matrixBuffer[5] = m.M22; _matrixBuffer[6] = m.M23; _matrixBuffer[7] = m.M24;
+ _matrixBuffer[8] = m.M31; _matrixBuffer[9] = m.M32; _matrixBuffer[10] = m.M33; _matrixBuffer[11] = m.M34;
+ _matrixBuffer[12] = m.M41; _matrixBuffer[13] = m.M42; _matrixBuffer[14] = m.M43; _matrixBuffer[15] = m.M44;
}
public void Dispose()
{
if (_disposed) return;
_disposed = true;
- foreach (var mesh in _meshCache.Values)
- _gl.DeleteVertexArray(mesh.Vao);
+ foreach (var m in _meshCache.Values) _gl.DeleteVertexArray(m.Vao);
_meshCache.Clear();
_gl.DeleteProgram(_program);
_gl.DeleteProgram(_shadowProgram);
@@ -361,31 +352,28 @@ public sealed class OpenGLRenderer : IRenderer
_gl.DeleteTexture(_shadowTexture);
}
- // Shaders
private const string ShadowVertexSource = @"#version 330 core
-layout(location = 0) in vec3 aPos;
+layout(location=0) in vec3 aPos;
uniform mat4 mvp;
-void main() { gl_Position = mvp * vec4(aPos, 1.0); }";
-
+void main(){gl_Position=mvp*vec4(aPos,1.0);}";
private const string ShadowFragmentSource = @"#version 330 core
-void main() {}";
+void main(){}";
private const string VertexShaderSource = @"#version 330 core
-layout(location = 0) in vec3 aPos;
-layout(location = 1) in vec3 aNormal;
-layout(location = 2) in vec4 aColor;
+layout(location=0) in vec3 aPos;
+layout(location=1) in vec3 aNormal;
+layout(location=2) in vec4 aColor;
uniform mat4 mvp;
uniform mat4 model;
out vec3 vNormal;
out vec3 vWorldPos;
out vec4 vColor;
-void main()
-{
- vec4 worldPos = model * vec4(aPos, 1.0);
- vWorldPos = worldPos.xyz;
- vNormal = mat3(transpose(inverse(model))) * aNormal;
- vColor = aColor;
- gl_Position = mvp * vec4(aPos, 1.0);
+void main(){
+ vec4 wp=model*vec4(aPos,1.0);
+ vWorldPos=wp.xyz;
+ vNormal=mat3(transpose(inverse(model)))*aNormal;
+ vColor=aColor;
+ gl_Position=mvp*vec4(aPos,1.0);
}";
private const string FragmentShaderSource = @"#version 330 core
@@ -407,97 +395,77 @@ uniform int lightTypes[4];
uniform float lightRanges[4];
uniform mat4 lightViewProj;
uniform sampler2D shadowMap;
+uniform int useTexture;
-vec3 ACESFilm(vec3 x)
-{
+vec3 ACESFilm(vec3 x){
const float a=2.51,b=0.03,c=2.43,d=0.59,e=0.14;
return clamp((x*(a*x+b))/(x*(c*x+d)+e),0.0,1.0);
}
-
-float Attenuation(float dist, float range)
-{
+float Attenuation(float dist,float range){
float r=max(range,0.001),d=max(dist,0.001);
- float x=d/r, x2=x*x, x4=x2*x2;
+ float x=d/r,x2=x*x,x4=x2*x2;
return clamp(1.0/(1.0+25.0*x4),0.0,1.0)*smoothstep(1.0,0.0,x);
}
-
-float CalculateShadow(vec3 worldPos)
-{
- vec4 lp = lightViewProj * vec4(worldPos, 1.0);
- vec3 ndc = lp.xyz / lp.w;
- vec3 uvw = ndc * 0.5 + 0.5;
- if (uvw.x < 0.0 || uvw.x > 1.0 || uvw.y < 0.0 || uvw.y > 1.0 || uvw.z > 1.0)
- return 1.0;
- float bias = 0.005;
- vec2 ts = vec2(1.0 / 2048.0);
- float s = 0.0;
- for (int x = -1; x <= 1; x++) {
- for (int y = -1; y <= 1; y++) {
- float d = texture(shadowMap, uvw.xy + vec2(x, y) * ts).r;
- s += (uvw.z - bias > d) ? 0.3 : 1.0;
+float CalculateShadow(vec3 worldPos){
+ vec4 lp=lightViewProj*vec4(worldPos,1.0);
+ vec3 ndc=lp.xyz/lp.w;
+ vec3 uvw=ndc*0.5+0.5;
+ if(uvw.x<0.0||uvw.x>1.0||uvw.y<0.0||uvw.y>1.0||uvw.z>1.0) return 1.0;
+ float bias=0.005;
+ vec2 ts=vec2(1.0/2048.0);
+ float s=0.0;
+ for(int x=-1;x<=1;x++){
+ for(int y=-1;y<=1;y++){
+ float d=texture(shadowMap,uvw.xy+vec2(x,y)*ts).r;
+ s+=(uvw.z-bias>d)?0.3:1.0;
}
}
- return s / 9.0;
+ return s/9.0;
}
-
-void main()
-{
- vec3 normal = normalize(vNormal);
- vec3 albedo = pow(vColor.rgb * materialColor.rgb, vec3(2.2));
- vec3 viewDir = normalize(viewPos - vWorldPos);
- float rough = clamp(roughness, 0.05, 1.0);
- float metal = clamp(metallic, 0.0, 1.0);
-
- vec3 skyColor = ambientColor;
- vec3 groundColor = ambientColor * 0.2;
- float hemisphere = 0.5 + 0.5 * normal.y;
- vec3 result = albedo * mix(groundColor, skyColor, hemisphere) * 0.4;
-
- float shadow = 1.0;
- if (lightCount > 0 && lightTypes[0] == 0)
- shadow = CalculateShadow(vWorldPos);
-
- vec3 F0 = mix(vec3(0.04), albedo, metal);
- float shininess = mix(8.0, 256.0, 1.0 - rough);
-
- for (int i = 0; i < lightCount; i++)
- {
- vec3 L;
- float atten = 1.0;
- if (lightTypes[i] == 1) {
- vec3 toLight = lightPositions[i] - vWorldPos;
- float dist = length(toLight);
- L = toLight / max(dist, 0.001);
- atten = Attenuation(dist, lightRanges[i]);
- } else {
- L = normalize(-lightDirs[i]);
- }
- float lightShadow = (i == 0 && lightTypes[0] == 0) ? shadow : 1.0;
- vec3 H = normalize(L + viewDir);
- float NdotL = max(dot(normal, L), 0.0);
- float NdotH = max(dot(normal, H), 0.0);
- float HdotV = max(dot(H, viewDir), 0.0);
- float spec = pow(NdotH, shininess);
- vec3 fresnel = F0 + (1.0 - F0) * pow(1.0 - HdotV, 5.0);
- vec3 specularColor = mix(fresnel, albedo * fresnel, metal);
- vec3 diffuse = albedo * lightColors[i] * NdotL * lightIntensities[i] * atten * 1.5 * lightShadow;
- vec3 specular = specularColor * spec * lightIntensities[i] * atten * lightShadow;
- diffuse *= (1.0 - fresnel * (1.0 - metal * 0.5));
- result += diffuse + specular;
+void main(){
+ vec3 normal=normalize(vNormal);
+ vec3 albedo=pow(vColor.rgb*materialColor.rgb,vec3(2.2));
+ vec3 viewDir=normalize(viewPos-vWorldPos);
+ float rough=clamp(roughness,0.05,1.0);
+ float metal=clamp(metallic,0.0,1.0);
+ vec3 skyColor=ambientColor;
+ vec3 groundColor=ambientColor*0.2;
+ float hemisphere=0.5+0.5*normal.y;
+ vec3 result=albedo*mix(groundColor,skyColor,hemisphere)*0.4;
+ float shadow=1.0;
+ if(lightCount>0&&lightTypes[0]==0) shadow=CalculateShadow(vWorldPos);
+ vec3 F0=mix(vec3(0.04),albedo,metal);
+ float shininess=mix(8.0,256.0,1.0-rough);
+ for(int i=0;i? Tcs);
private sealed class OpenGLScreenshotProvider : IScreenshotProvider
{
- private readonly OpenGLRenderer _r;
- public OpenGLScreenshotProvider(OpenGLRenderer r) => _r = r;
public Task CaptureAsync(string outputPath) => Task.FromResult(Array.Empty());
}
}
diff --git a/src/Engine.Graphics.OpenGL/OpenGLWindow.cs b/src/Engine.Graphics.OpenGL/OpenGLWindow.cs
index f49f3d4..854e642 100644
--- a/src/Engine.Graphics.OpenGL/OpenGLWindow.cs
+++ b/src/Engine.Graphics.OpenGL/OpenGLWindow.cs
@@ -1,16 +1,12 @@
+using System;
+using System.Collections.Generic;
using Engine.Core;
-using Engine.Core.Components;
using Silk.NET.Input;
+using Silk.NET.Windowing;
using SilkWindow = Silk.NET.Windowing.IWindow;
-using SilkKey = Silk.NET.Input.Key;
-using SilkMouseButton = Silk.NET.Input.MouseButton;
-using EngineKey = Engine.Core.Key;
namespace Engine.Graphics.OpenGL;
-///
-/// Silk.NET windowing-backed implementation of IWindow.
-///
public sealed class OpenGLWindow : Engine.Core.IWindow, IDisposable
{
private readonly SilkWindow _silkWindow;
@@ -23,7 +19,6 @@ public sealed class OpenGLWindow : Engine.Core.IWindow, IDisposable
public bool ShouldClose => _shouldClose || _silkWindow.IsClosing;
IInputState Engine.Core.IWindow.Input => _input;
public nint Handle => 0;
-
public SilkWindow SilkView => _silkWindow;
public OpenGLWindow(string title, int width, int height)
@@ -34,7 +29,7 @@ public sealed class OpenGLWindow : Engine.Core.IWindow, IDisposable
options.VSync = true;
options.API = new GraphicsAPI(ContextAPI.OpenGL, ContextProfile.Core, ContextFlags.Default, new APIVersion(3, 3));
- _silkWindow = Silk.NET.Windowing.Window.Create(options);
+ _silkWindow = Window.Create(options);
_silkWindow.Closing += () => _shouldClose = true;
}
@@ -44,13 +39,8 @@ public sealed class OpenGLWindow : Engine.Core.IWindow, IDisposable
_input.Initialize(inputContext);
}
- public void PumpEvents()
- {
- _silkWindow.DoEvents();
- }
-
+ public void PumpEvents() => _silkWindow.DoEvents();
public void Close() => _shouldClose = true;
-
public string[] GetRequiredVulkanExtensions() => Array.Empty();
public void Dispose()
@@ -61,4 +51,3 @@ public sealed class OpenGLWindow : Engine.Core.IWindow, IDisposable
_silkWindow.Dispose();
}
}
-