private void ApplyStateCore(GraphicsContext ctx, ShaderProgram program, BlendState currentState) { if (Enabled) { // Enable blending if (currentState.Enabled == false) { Gl.Enable(EnableCap.Blend); } // Set blending equation if (ctx.Extensions.BlendMinmax_EXT) { if (EquationSeparated) { if (currentState.RgbEquation != RgbEquation || currentState.AlphaEquation != AlphaEquation) { Gl.BlendEquationSeparate(RgbEquation, AlphaEquation); } } else { if (currentState.RgbEquation != RgbEquation) { Gl.BlendEquation(RgbEquation); } } } // Set blending function if (FunctionSeparated) { if (currentState._RgbSrcFactor != _RgbSrcFactor || currentState._RgbDstFactor != _RgbDstFactor || currentState._AlphaSrcFactor != _AlphaSrcFactor || currentState._AlphaDstFactor != _AlphaDstFactor) { Gl.BlendFuncSeparate(_RgbSrcFactor, _RgbDstFactor, _AlphaSrcFactor, _AlphaDstFactor); } } else { if (currentState._RgbSrcFactor != _RgbSrcFactor || currentState._RgbDstFactor != _RgbDstFactor) { Gl.BlendFunc(_RgbSrcFactor, _RgbDstFactor); } } // Set blend color, if required if (RequiresConstColor(_RgbSrcFactor) || RequiresConstColor(_AlphaSrcFactor) || RequiresConstColor(_RgbDstFactor) || RequiresConstColor(_AlphaDstFactor)) { Gl.BlendColor(_BlendColor.r, _BlendColor.g, _BlendColor.b, _BlendColor.a); } } else { // Disable blending if (currentState.Enabled == true) { Gl.Disable(EnableCap.Blend); } } }
/// <summary> /// Set ShaderProgram state. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> which has defined the shader program <paramref name="sProgram"/>. /// </param> /// <param name="sProgram"> /// The <see cref="ShaderProgram"/> which has the state set. /// </param> public override void ApplyState(GraphicsContext ctx, ShaderProgram sProgram) { if (ctx == null) { throw new ArgumentNullException("ctx"); } BlendState currentState = null; // (BlendState)ctx.CurrentState[StateId]; if (Enabled) { // Enable blending if (currentState == null || !currentState.Enabled) { Gl.Enable(EnableCap.Blend); } // Set blending equation if (ctx.Caps.GlExtensions.BlendMinmax_EXT) { if (EquationSeparated) { Gl.BlendEquationSeparate(RgbEquation, AlphaEquation); } else { Gl.BlendEquation((int)RgbEquation); } } // Set blending function if (FunctionSeparated) { Gl.BlendFuncSeparate((int)mRgbSrcFactor, (int)mRgbDstFactor, (int)mAlphaSrcFactor, (int)mAlphaDstFactor); } else { Gl.BlendFunc(mRgbSrcFactor, mRgbDstFactor); } // Set blend color, if required if (RequiresConstColor(mRgbSrcFactor) || RequiresConstColor(mAlphaSrcFactor) || RequiresConstColor(mRgbDstFactor) || RequiresConstColor(mAlphaDstFactor)) { Gl.BlendColor(mBlendColor.Red, mBlendColor.Green, mBlendColor.Blue, mBlendColor.Alpha); } } else { // Disable blending if (currentState == null || currentState.Enabled) { Gl.Disable(EnableCap.Blend); } } }
static void SetupState() { Gl.Enable(EnableCap.DepthTest); Gl.DepthMask(true); Gl.Enable(EnableCap.CullFace); Gl.CullFace(CullFaceMode.Back); Gl.Enable(EnableCap.Blend); Gl.BlendEquationSeparate(BlendEquationMode.FuncAdd, BlendEquationMode.FuncAdd); Gl.BlendFuncSeparate(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha, BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); }
private void ApplyStateCore(GraphicsContext ctx, ShaderProgram program) { if (Enabled) { // Enable blending Gl.Enable(EnableCap.Blend); // Set blending equation if (ctx.Extensions.BlendMinmax_EXT) { if (EquationSeparated) { Gl.BlendEquationSeparate(RgbEquation, AlphaEquation); } else { Gl.BlendEquation((int)RgbEquation); } } // Set blending function if (FunctionSeparated) { Gl.BlendFuncSeparate((int)_RgbSrcFactor, (int)_RgbDstFactor, (int)_AlphaSrcFactor, (int)_AlphaDstFactor); } else { Gl.BlendFunc(_RgbSrcFactor, _RgbDstFactor); } // Set blend color, if required if (RequiresConstColor(_RgbSrcFactor) || RequiresConstColor(_AlphaSrcFactor) || RequiresConstColor(_RgbDstFactor) || RequiresConstColor(_AlphaDstFactor)) { Gl.BlendColor(_BlendColor.Red, _BlendColor.Green, _BlendColor.Blue, _BlendColor.Alpha); } } else { // Disable blending Gl.Disable(EnableCap.Blend); } }
static void CreateContext(/*params string[] RequiredExtensions*/) { GConsole.WriteLine("Initializing OpenGL"); #if DEBUG Khronos.KhronosApi.Log += (S, E) => { if (E.Name == "glGetError") { return; } Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("OpenGL> {0}", string.Format("{0}({1}) = {2}", E.Name, string.Join(", ", E.Args), E.ReturnValue ?? "null")); Console.ResetColor(); }; Khronos.KhronosApi.LogEnabled = false; //*/ #endif GConsole.WriteLine("Initializing GLFW"); Glfw.ConfigureNativesDirectory("native/glfw3_64"); if (!Glfw.Init()) { FatalError("Could not initialize GLFW"); } Glfw.SetErrorCallback((Err, Msg) => { FatalError("GLFW({0}) {1}", Err, Msg); }); Width = CVar.GetInt("width", 800); Height = CVar.GetInt("height", 600); Glfw.WindowHint(Glfw.Hint.Resizable, CVar.GetBool("resizable")); //Glfw.WindowHint(Glfw.Hint.ClientApi, Glfw.ClientApi.None); Glfw.WindowHint(Glfw.Hint.ClientApi, Glfw.ClientApi.OpenGL); Glfw.WindowHint(Glfw.Hint.ContextCreationApi, Glfw.ContextApi.Native); Glfw.WindowHint(Glfw.Hint.Doublebuffer, CVar.GetBool("gl_doublebuffer")); Glfw.WindowHint(Glfw.Hint.ContextVersionMajor, CVar.GetInt("gl_major")); Glfw.WindowHint(Glfw.Hint.ContextVersionMinor, CVar.GetInt("gl_minor")); Glfw.WindowHint(Glfw.Hint.Samples, CVar.GetInt("gl_samples")); Glfw.WindowHint(Glfw.Hint.OpenglForwardCompat, CVar.GetBool("gl_forwardcompat")); Glfw.WindowHint(Glfw.Hint.OpenglProfile, Glfw.OpenGLProfile.Core); #if DEBUG Glfw.WindowHint(Glfw.Hint.OpenglDebugContext, true); #endif GConsole.WriteLine("Creating window"); Window = Glfw.CreateWindow(Width, Height, "libTech"); if (!Window) { FatalError("Could not create window({0}x{1})", Width, Height); } Gl.Initialize(); Glfw.MakeContextCurrent(Window); /*bool AllSupported = true; * * for (int i = 0; i < RequiredExtensions.Length; i++) { * if (!Glfw.ExtensionSupported(RequiredExtensions[i])) { * GConsole.WriteLine("{0} not supported", RequiredExtensions[i]); * AllSupported = false; * } * } * * if (!AllSupported) * while (true) * Thread.Sleep(10);*/ #if DEBUG Gl.DebugMessageCallback((Src, DbgType, ID, Severity, Len, Buffer, UserPtr) => { if (Severity == Gl.DebugSeverity.Notification) { return; } GConsole.WriteLine("OpenGL {0} {1} {2}, {3}", Src, DbgType, ID, Severity); GConsole.WriteLine(Encoding.ASCII.GetString((byte *)Buffer, Len)); if ((/*Severity == Gl.DebugSeverity.Medium ||*/ Severity == Gl.DebugSeverity.High) && Debugger.IsAttached) { Debugger.Break(); } }, IntPtr.Zero); Gl.Enable((EnableCap)Gl.DEBUG_OUTPUT); Gl.Enable((EnableCap)Gl.DEBUG_OUTPUT_SYNCHRONOUS); #endif GConsole.WriteLine("{0}, {1}", Gl.GetString(StringName.Vendor), Gl.GetString(StringName.Renderer)); GConsole.WriteLine("OpenGL {0}", Gl.GetString(StringName.Version)); GConsole.WriteLine("GLSL {0}", Gl.GetString(StringName.ShadingLanguageVersion)); Gl.ClearColor(69 / 255.0f, 112 / 255.0f, 56 / 255.0f, 1.0f); // F**k the police Gl.Enable((EnableCap)Gl.DEPTH_CLAMP); Gl.Enable(EnableCap.Blend); //Gl.VERTEX_PROGRAM_POINT_SIZE; Gl.Enable((EnableCap)Gl.VERTEX_PROGRAM_POINT_SIZE); //Gl.Enable((EnableCap)Gl.SAMPLE_SHADING); //Gl.Enable(EnableCap.FramebufferSrgb); Gl.BlendEquationSeparate(BlendEquationMode.FuncAdd, BlendEquationMode.FuncAdd); Gl.BlendFuncSeparate(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha, BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); //Gl.BlendEquation(BlendEquationMode.FuncAdd); //Gl.BlendFunc(BlendingFactor.One, BlendingFactor.One); ShaderProgram.LoadDefaultShaders(); }
public void RenderDrawData(ImDrawDataPtr drawData) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) var fbWidth = drawData.DisplaySize.X * drawData.FramebufferScale.X; var fbHeight = drawData.DisplaySize.Y * drawData.FramebufferScale.Y; if (fbWidth < 0 || fbHeight < 0) { return; } if (!drawData.Valid || drawData.CmdListsCount == 0) { return; } // Backup GL state // The vast majority of this probably is not necessary, and ideally should be handled by the main render application // with a state cache if actually required. // At the very least, however, it appears that SDL does not maintain/reset its own state perfectly when using opengl // and the scissor rect will break things. Since I'm not sure if anything else would also break, and since this backup // is not nearly as terrible as the DX11 version was, I am leaving this in place for now. Gl.GetInteger(GetPName.ActiveTexture, out int lastActiveTexture); Gl.GetInteger(GetPName.CurrentProgram, out int lastProgram); Gl.GetInteger(GetPName.TextureBinding2d, out int lastTexture); Gl.GetInteger(GetPName.ArrayBufferBinding, out int lastArrayBuffer); Gl.GetInteger(GetPName.VertexArrayBinding, out int lastVertexArrayObject); Gl.GetInteger(GetPName.PolygonMode, out int lastPolygonMode); var lastViewport = new int[4]; Gl.Get(GetPName.Viewport, lastViewport); var lastScissorBox = new int[4]; Gl.Get(GetPName.ScissorBox, lastScissorBox); Gl.GetInteger(GetPName.BlendSrcRgb, out int lastBlendSrcRgb); Gl.GetInteger(GetPName.BlendDstRgb, out int lastBlendDstRgb); Gl.GetInteger(GetPName.BlendSrcAlpha, out int lastBlendSrcAlpha); Gl.GetInteger(GetPName.BlendDstAlpha, out int lastBlendDstAlpha); Gl.GetInteger(GetPName.BlendEquationRgb, out int lastBlendEquationRgb); Gl.GetInteger(GetPName.BlendEquationAlpha, out int lastBlendEquationAlpha); var lastEnableBlend = Gl.IsEnabled(EnableCap.Blend); var lastEnableCullFace = Gl.IsEnabled(EnableCap.CullFace); var lastEnableDepthTest = Gl.IsEnabled(EnableCap.DepthTest); var lastEnableScissorTest = Gl.IsEnabled(EnableCap.ScissorTest); // Setup desired GL state Gl.ActiveTexture(TextureUnit.Texture0); // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts) // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound. _vertexArrayObject = Gl.GenVertexArray(); SetupRenderState(drawData); // Will project scissor/clipping rectangles into framebuffer space var clipOff = drawData.DisplayPos; // (0,0) unless using multi-viewports var clipScale = drawData.FramebufferScale; // (1,1) unless using retina display which are often (2,2) // Render command lists for (var n = 0; n < drawData.CmdListsCount; n++) { var cmdList = drawData.CmdListsRange[n]; // Upload vertex/index buffers // TODO: this is *awful* Gl.BufferData(BufferTarget.ArrayBuffer, (uint)(cmdList.VtxBuffer.Size * Unsafe.SizeOf <ImDrawVert>()), cmdList.VtxBuffer.Data, BufferUsage.StreamDraw); Gl.BufferData(BufferTarget.ElementArrayBuffer, (uint)(cmdList.IdxBuffer.Size * sizeof(ushort)), cmdList.IdxBuffer.Data, BufferUsage.StreamDraw); for (var i = 0; i < cmdList.CmdBuffer.Size; i++) { var pcmd = cmdList.CmdBuffer[i]; if (pcmd.UserCallback != IntPtr.Zero) { // TODO throw new NotImplementedException(); } else { // Project scissor/clipping rectangles into framebuffer space var clipRect = new Vector4 { X = (pcmd.ClipRect.X - clipOff.X) * clipScale.X, Y = (pcmd.ClipRect.Y - clipOff.Y) * clipScale.Y, Z = (pcmd.ClipRect.Z - clipOff.X) * clipScale.X, W = (pcmd.ClipRect.W - clipOff.Y) * clipScale.Y, }; if (clipRect.X < fbWidth && clipRect.Y < fbHeight && clipRect.Z >= 0 && clipRect.W >= 0) { // Apply scissor/clipping rectangle Gl.Scissor((int)clipRect.X, (int)(fbHeight - clipRect.W), (int)(clipRect.Z - clipRect.X), (int)(clipRect.W - clipRect.Y)); // Bind texture, Draw Gl.BindTexture(TextureTarget.Texture2d, (uint)pcmd.TextureId); Gl.DrawElementsBaseVertex(PrimitiveType.Triangles, (int)pcmd.ElemCount, DrawElementsType.UnsignedShort, (IntPtr)(pcmd.IdxOffset * sizeof(short)), (int)pcmd.VtxOffset); } } } } // Destroy the temporary VAO Gl.DeleteVertexArrays(_vertexArrayObject); // Restore modified GL state Gl.UseProgram((uint)lastProgram); Gl.BindTexture(TextureTarget.Texture2d, (uint)lastTexture); Gl.ActiveTexture((TextureUnit)lastActiveTexture); Gl.BindVertexArray((uint)lastVertexArrayObject); Gl.BindBuffer(BufferTarget.ArrayBuffer, (uint)lastArrayBuffer); Gl.BlendEquationSeparate((BlendEquationMode)lastBlendEquationRgb, (BlendEquationMode)lastBlendEquationAlpha); Gl.BlendFuncSeparate((BlendingFactor)lastBlendSrcRgb, (BlendingFactor)lastBlendDstRgb, (BlendingFactor)lastBlendSrcAlpha, (BlendingFactor)lastBlendDstAlpha); if (lastEnableBlend) { Gl.Enable(EnableCap.Blend); } else { Gl.Disable(EnableCap.Blend); } if (lastEnableCullFace) { Gl.Enable(EnableCap.CullFace); } else { Gl.Disable(EnableCap.CullFace); } if (lastEnableDepthTest) { Gl.Enable(EnableCap.DepthTest); } else { Gl.Disable(EnableCap.DepthTest); } if (lastEnableScissorTest) { Gl.Enable(EnableCap.ScissorTest); } else { Gl.Disable(EnableCap.ScissorTest); } Gl.PolygonMode(MaterialFace.FrontAndBack, (PolygonMode)lastPolygonMode); Gl.Viewport(lastViewport[0], lastViewport[1], lastViewport[2], lastViewport[3]); Gl.Scissor(lastScissorBox[0], lastScissorBox[1], lastScissorBox[2], lastScissorBox[3]); }