internal GL_FrameBuffer(GL_Graphics graphics, int width, int height, TextureFormat[] attachments) { this.graphics = graphics; for (int i = 0; i < attachments.Length; i++) { var attachment = new Texture(graphics, width, height, attachments[i]); var glTexture = (GL_Texture)attachment.Implementation; glTexture.isRenderTexture = true; Attachments.Add(attachment); } }
static void Clear(GL_Graphics graphics, ISystemOpenGL.Context context, RenderTarget target, Clear flags, Color color, float depth, int stencil, RectInt viewport) { // update the viewport var meta = graphics.GetContextMeta(context); { viewport.Y = target.RenderHeight - viewport.Y - viewport.Height; if (meta.Viewport != viewport) { GL.Viewport(viewport.X, viewport.Y, viewport.Width, viewport.Height); meta.Viewport = viewport; } } // we disable the scissor for clearing meta.ForceScissorUpdate = true; GL.Disable(GLEnum.SCISSOR_TEST); // clear var mask = GLEnum.ZERO; if (flags.HasFlag(Framework.Clear.Color)) { GL.ClearColor(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f); mask |= GLEnum.COLOR_BUFFER_BIT; } if (flags.HasFlag(Framework.Clear.Depth)) { GL.ClearDepth(depth); mask |= GLEnum.DEPTH_BUFFER_BIT; } if (flags.HasFlag(Framework.Clear.Stencil)) { GL.ClearStencil(stencil); mask |= GLEnum.STENCIL_BUFFER_BIT; } GL.Clear(mask); GL.BindFramebuffer(GLEnum.FRAMEBUFFER, 0); }
internal GL_Shader(GL_Graphics graphics, ShaderSource source) { this.graphics = graphics; if (graphics.MainThreadId != Thread.CurrentThread.ManagedThreadId) { lock (graphics.BackgroundContext) { graphics.System.SetCurrentGLContext(graphics.BackgroundContext); Create(); GL.Flush(); graphics.System.SetCurrentGLContext(null); } } else { Create(); } void Create() { ID = GL.CreateProgram(); Span <uint> shaders = stackalloc uint[2]; // vertex shader if (source.Vertex != null) { uint shaderId = GL.CreateShader(GLEnum.VERTEX_SHADER); shaders[0] = shaderId; string glsl = Encoding.UTF8.GetString(source.Vertex); GL.ShaderSource(shaderId, 1, new[] { glsl }, new int[] { glsl.Length }); GL.CompileShader(shaderId); string?errorMessage = GL.GetShaderInfoLog(shaderId); if (!string.IsNullOrEmpty(errorMessage)) { throw new Exception(errorMessage); } GL.AttachShader(ID, shaderId); } // fragment shader if (source.Fragment != null) { uint shaderId = GL.CreateShader(GLEnum.FRAGMENT_SHADER); shaders[1] = shaderId; string glsl = Encoding.UTF8.GetString(source.Fragment); GL.ShaderSource(shaderId, 1, new[] { glsl }, new int[] { glsl.Length }); GL.CompileShader(shaderId); string?errorMessage = GL.GetShaderInfoLog(shaderId); if (!string.IsNullOrEmpty(errorMessage)) { throw new Exception(errorMessage); } GL.AttachShader(ID, shaderId); } GL.LinkProgram(ID); string?programError = GL.GetProgramInfoLog(ID); if (!string.IsNullOrEmpty(programError)) { throw new Exception(programError); } // get attributes GL.GetProgramiv(ID, GLEnum.ACTIVE_ATTRIBUTES, out int attributeCount); for (int i = 0; i < attributeCount; i++) { GL.GetActiveAttrib(ID, (uint)i, out _, out _, out string name); int location = GL.GetAttribLocation(ID, name); if (location >= 0) { Attributes.Add(name, new ShaderAttribute(name, (uint)location)); } } // get uniforms GL.GetProgramiv(ID, GLEnum.ACTIVE_UNIFORMS, out int uniformCount); for (int i = 0; i < uniformCount; i++) { GL.GetActiveUniform(ID, (uint)i, out int size, out GLEnum type, out string name); int location = GL.GetUniformLocation(ID, name); if (location >= 0) { if (size > 1 && name.EndsWith("[0]")) { name = name.Substring(0, name.Length - 3); } Uniforms.Add(name, new GL_Uniform(this, name, size, location, type)); } } // dispose shaders for (int i = 0; i < shaders.Length; i++) { if (shaders[i] != 0) { GL.DetachShader(ID, shaders[i]); GL.DeleteShader(shaders[i]); } } } }
internal GL_Mesh(GL_Graphics graphics) { this.graphics = graphics; }
#pragma warning restore CS8618 public static void Init(GL_Graphics graphics, ISystemOpenGL system) { bindings = new GL_Bindings(system); GetIntegerv((GLEnum)0x821B, out MajorVersion); GetIntegerv((GLEnum)0x821C, out MinorVersion); GetIntegerv((GLEnum)0x8CDF, out MaxColorAttachments); GetIntegerv((GLEnum)0x851C, out MaxCubeMapTextureSize); GetIntegerv((GLEnum)0x8824, out MaxDrawBuffers); GetIntegerv((GLEnum)0x80E9, out MaxElementIndices); GetIntegerv((GLEnum)0x80E8, out MaxElementVertices); GetIntegerv((GLEnum)0x84E8, out MaxRenderbufferSize); GetIntegerv((GLEnum)0x8D57, out MaxSamples); GetIntegerv((GLEnum)0x8872, out MaxTextureImageUnits); GetIntegerv((GLEnum)0x0D33, out MaxTextureSize); #if DEBUG if (bindings.glDebugMessageCallback != null) { Enable(GLEnum.DEBUG_OUTPUT); Enable(GLEnum.DEBUG_OUTPUT_SYNCHRONOUS); DebugMessageCallback(Marshal.GetFunctionPointerForDelegate(onErrorRef = new OnError((source, type, id, severity, length, message, userParam) => { string typeName; string severityName; string output = Marshal.PtrToStringAnsi(message, (int)length); switch (type) { case GLEnum.DEBUG_TYPE_ERROR: typeName = "ERROR"; break; case GLEnum.DEBUG_TYPE_DEPRECATED_BEHAVIOR: typeName = "DEPRECATED BEHAVIOR"; break; case GLEnum.DEBUG_TYPE_MARKER: typeName = "MARKER"; break; case GLEnum.DEBUG_TYPE_OTHER: typeName = "OTHER"; break; case GLEnum.DEBUG_TYPE_PERFORMANCE: typeName = "PEROFRMANCE"; break; case GLEnum.DEBUG_TYPE_POP_GROUP: typeName = "POP GROUP"; break; case GLEnum.DEBUG_TYPE_PORTABILITY: typeName = "PORTABILITY"; break; case GLEnum.DEBUG_TYPE_PUSH_GROUP: typeName = "PUSH GROUP"; break; default: case GLEnum.DEBUG_TYPE_UNDEFINED_BEHAVIOR: typeName = "UNDEFINED BEHAVIOR"; break; } switch (severity) { case GLEnum.DEBUG_SEVERITY_HIGH: severityName = "HIGH"; break; case GLEnum.DEBUG_SEVERITY_MEDIUM: severityName = "MEDIUM"; break; case GLEnum.DEBUG_SEVERITY_LOW: severityName = "LOW"; break; // skip notifications default: case GLEnum.DEBUG_SEVERITY_NOTIFICATION: return; } if (type == GLEnum.DEBUG_TYPE_ERROR) { throw new Exception(output); } Log.Warning(graphics.Name, $"{typeName}, {severityName}: {output}"); })), IntPtr.Zero); } #endif }
internal GL_Texture(GL_Graphics graphics) { this.graphics = graphics; texture = null !; }