gl viewport

This commit is contained in:
bird_egop
2026-06-05 20:33:21 +03:00
parent 97dc14c36c
commit 195e6d71bd
13 changed files with 1140 additions and 0 deletions
@@ -0,0 +1,150 @@
using Silk.NET.OpenGL;
namespace NResUI.Rendering.Viewport.OpenGL;
public sealed class MsaaFramebuffer
{
private readonly GL _gl;
private readonly uint _samples;
private uint _msaaFramebuffer;
private uint _msaaColorRenderbuffer;
private uint _msaaDepthStencilRenderbuffer;
private uint _resolveFramebuffer;
private uint _resolveColorTexture;
private int _width;
private int _height;
public uint ColorTexture => _resolveColorTexture;
public MsaaFramebuffer(GL gl, uint samples = 4)
{
_gl = gl;
_samples = samples;
}
public void EnsureSize(int width, int height)
{
width = Math.Max(1, width);
height = Math.Max(1, height);
if (_msaaFramebuffer != 0 && _width == width && _height == height)
return;
_width = width;
_height = height;
if (_msaaFramebuffer == 0)
{
_msaaFramebuffer = _gl.GenFramebuffer();
_msaaColorRenderbuffer = _gl.GenRenderbuffer();
_msaaDepthStencilRenderbuffer = _gl.GenRenderbuffer();
_resolveFramebuffer = _gl.GenFramebuffer();
_resolveColorTexture = _gl.GenTexture();
}
_gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, _msaaColorRenderbuffer);
_gl.RenderbufferStorageMultisample(
RenderbufferTarget.Renderbuffer,
_samples,
InternalFormat.Rgba8,
(uint)width,
(uint)height);
_gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, _msaaDepthStencilRenderbuffer);
_gl.RenderbufferStorageMultisample(
RenderbufferTarget.Renderbuffer,
_samples,
InternalFormat.Depth24Stencil8,
(uint)width,
(uint)height);
_gl.BindFramebuffer(FramebufferTarget.Framebuffer, _msaaFramebuffer);
_gl.FramebufferRenderbuffer(
FramebufferTarget.Framebuffer,
FramebufferAttachment.ColorAttachment0,
RenderbufferTarget.Renderbuffer,
_msaaColorRenderbuffer);
_gl.FramebufferRenderbuffer(
FramebufferTarget.Framebuffer,
FramebufferAttachment.DepthStencilAttachment,
RenderbufferTarget.Renderbuffer,
_msaaDepthStencilRenderbuffer);
var msaaStatus = _gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
if (msaaStatus != GLEnum.FramebufferComplete)
throw new InvalidOperationException($"MSAA viewport framebuffer is incomplete: {msaaStatus}");
_gl.BindTexture(TextureTarget.Texture2D, _resolveColorTexture);
_gl.TexImage2D(
TextureTarget.Texture2D,
0,
InternalFormat.Rgba8,
(uint)width,
(uint)height,
0,
PixelFormat.Rgba,
PixelType.UnsignedByte,
null);
_gl.TexParameter(
TextureTarget.Texture2D,
TextureParameterName.TextureMinFilter,
(int)TextureMinFilter.Linear);
_gl.TexParameter(
TextureTarget.Texture2D,
TextureParameterName.TextureMagFilter,
(int)TextureMagFilter.Linear);
_gl.TexParameter(
TextureTarget.Texture2D,
TextureParameterName.TextureWrapS,
(int)TextureWrapMode.ClampToEdge);
_gl.TexParameter(
TextureTarget.Texture2D,
TextureParameterName.TextureWrapT,
(int)TextureWrapMode.ClampToEdge);
_gl.BindFramebuffer(FramebufferTarget.Framebuffer, _resolveFramebuffer);
_gl.FramebufferTexture2D(
FramebufferTarget.Framebuffer,
FramebufferAttachment.ColorAttachment0,
TextureTarget.Texture2D,
_resolveColorTexture,
0);
var resolveStatus = _gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
if (resolveStatus != GLEnum.FramebufferComplete)
throw new InvalidOperationException($"Resolve viewport framebuffer is incomplete: {resolveStatus}");
_gl.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
_gl.BindTexture(TextureTarget.Texture2D, 0);
_gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0);
}
public void BindForRender()
{
_gl.BindFramebuffer(FramebufferTarget.Framebuffer, _msaaFramebuffer);
_gl.Viewport(0, 0, (uint)_width, (uint)_height);
}
public void Resolve()
{
_gl.BindFramebuffer(FramebufferTarget.ReadFramebuffer, _msaaFramebuffer);
_gl.BindFramebuffer(FramebufferTarget.DrawFramebuffer, _resolveFramebuffer);
_gl.BlitFramebuffer(
0, 0, _width, _height,
0, 0, _width, _height,
ClearBufferMask.ColorBufferBit,
BlitFramebufferFilter.Nearest);
}
}
@@ -0,0 +1,72 @@
using System.Numerics;
using Silk.NET.OpenGL;
namespace NResUI.Rendering.Viewport.OpenGL;
public sealed unsafe class ShaderProgram
{
private readonly GL _gl;
public uint Handle { get; }
public ShaderProgram(GL gl, string vertexShaderSource, string fragmentShaderSource, string debugName)
{
_gl = gl;
var vertexShader = CompileShader(ShaderType.VertexShader, vertexShaderSource, debugName);
var fragmentShader = CompileShader(ShaderType.FragmentShader, fragmentShaderSource, debugName);
Handle = _gl.CreateProgram();
_gl.AttachShader(Handle, vertexShader);
_gl.AttachShader(Handle, fragmentShader);
_gl.LinkProgram(Handle);
_gl.GetProgram(Handle, ProgramPropertyARB.LinkStatus, out var linked);
if (linked == 0)
{
var log = _gl.GetProgramInfoLog(Handle);
throw new InvalidOperationException($"{debugName} shader link failed: {log}");
}
_gl.DetachShader(Handle, vertexShader);
_gl.DetachShader(Handle, fragmentShader);
_gl.DeleteShader(vertexShader);
_gl.DeleteShader(fragmentShader);
}
public void Use()
{
_gl.UseProgram(Handle);
}
public int GetUniformLocation(string name)
{
return _gl.GetUniformLocation(Handle, name);
}
public void SetMatrix4(int location, Matrix4x4 matrix)
{
_gl.UniformMatrix4(location, 1, false, (float*)&matrix);
}
public void SetVector4(int location, Vector4 value)
{
_gl.Uniform4(location, value.X, value.Y, value.Z, value.W);
}
private uint CompileShader(ShaderType type, string source, string debugName)
{
var shader = _gl.CreateShader(type);
_gl.ShaderSource(shader, source);
_gl.CompileShader(shader);
_gl.GetShader(shader, ShaderParameterName.CompileStatus, out var compiled);
if (compiled == 0)
{
var log = _gl.GetShaderInfoLog(shader);
throw new InvalidOperationException($"{debugName} {type} compile failed: {log}");
}
return shader;
}
}