예제 #1
0
        private void WorkerMain()
        {
            if (!Initialized)
            {
                throw new InvalidOperationException("The OpenGL Library bindings are not initialized.");
            }

            if (TargetWindow == null)
            {
                CreateMainWindow(WindowTitle);
            }

            _systemTimer.Start();

            TargetWindow.MakeCurrent();

            ViewportSize = new Size(TargetWindow.ClientSize.X, TargetWindow.ClientSize.Y);

            if (WireframeMode)
            {
                WireframeMode = true; // Recall
            }
            if (AutoSetViewport)
            {
                Gl.Viewport(0, 0, ViewportSize.Width, ViewportSize.Height);
            }


            if (VerticalSync)
            {
                TargetWindow.SwapInterval = 1;
            }
            else
            {
                TargetWindow.SwapInterval = 0;
            }

            if (AutoEnableCaps.HasFlag(AutoEnableCapabilitiesFlags.Blend))
            {
                Gl.Enable(EnableCap.Blend);
            }

            OnContextCreated();

            _lastFrameTimeValue = 0;
            _timeSinceLastFrame = 0;
            _frameIndex         = 0;

            _currFrameTimerValue = _lastFrameTimeValue;

            if (Asynchronous)
            {
                while (!TargetWindow.IsExiting && !AbortFlag)
                {
                    AdvanceFrame();
                }

                AbortFlag = true;
            }
        }
예제 #2
0
        public void SetUniform(string name, float v1, float?v2 = null, float?v3 = null, float?v4 = null)
        {
            if (ActiveShaderProgram == null)
            {
                throw new InvalidOperationException("No shader program is loaded. Cannot set uniforms.");
            }

            int uniformLocation = Gl.GetUniformLocation(ActiveShaderProgram.ProgramId, name);

            if (uniformLocation < 0)
            {
                throw new KeyNotFoundException(string.Format("The specified uniform '{0}' cannot be found for program '{1}'.", name, ActiveShaderProgram.ProgramId));
            }

            if (v4 != null && v4.HasValue)
            {
                Gl.Uniform4(uniformLocation, v1, v2.Value, v3.Value, v4.Value);
                return;
            }

            if (v3 != null && v3.HasValue)
            {
                Gl.Uniform3(uniformLocation, v1, v2.Value, v3.Value);
                return;
            }

            if (v2 != null && v2.HasValue)
            {
                Gl.Uniform2(uniformLocation, v1, v2.Value);
                return;
            }

            Gl.Uniform1(uniformLocation, v1);
            return;
        }
예제 #3
0
        public static void CheckGlErrors(string stage)
        {
            ErrorCode code = Gl.GetError();

            if (code != ErrorCode.NoError)
            {
                throw new Exception(string.Format("OpenGL Draw error on stage {0}: {1}", stage, code.ToString()));
            }
        }
예제 #4
0
        protected virtual void Renderer_ContextCreated_Wrap(RenderThread sender)
        {
            GlVersion ver = GlVersion.Parse(Gl.GetString(StringName.Version));
            ContextCreationEventArgs args = new ContextCreationEventArgs(ver.Api, ver.Version, ver.ToString(), ver.Profile, Gl.GetString(StringName.Vendor));

            Gl.GetError();

            Renderer_ContextCreated(sender, args);
        }
예제 #5
0
        public void SelectShader(ShaderProgram program)
        {
            if (!FrameStarted)
            {
                throw new InvalidOperationException("Cannot select a Shader program when no frame is currently started on the GPU.");
            }

            ActiveShaderProgram = program;
            Gl.UseProgram(program.ProgramId);
        }
예제 #6
0
        public void Unload()
        {
            if (!Compiled)
            {
                throw new InvalidOperationException("Cannot unload shader because its not loaded into the GPU.");
            }

            Compiled = false;
            Gl.DeleteProgram(ProgramId);
        }
        protected int LoadTexture(Bitmap data, TextureWrapMode mode)
        {
            BitmapData lockedBitmap = data.LockBits(new Rectangle(Point.Empty, data.Size), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            byte[] buffer = new byte[lockedBitmap.Width * lockedBitmap.Height * 4];

            for (int i = 0; i < buffer.Length; i += 4)
            {
                byte r, g, b, a;
                a = Marshal.ReadByte(lockedBitmap.Scan0 + i);
                r = Marshal.ReadByte(lockedBitmap.Scan0 + i + 1);
                g = Marshal.ReadByte(lockedBitmap.Scan0 + i + 2);
                b = Marshal.ReadByte(lockedBitmap.Scan0 + i + 3);

                buffer[i]     = r;
                buffer[i + 1] = g;
                buffer[i + 2] = b;
                buffer[i + 3] = a;
            }

            data.UnlockBits(lockedBitmap);

            CheckGlErrors("pre-texture-gen");
            int textureId = Gl.GenTexture();

            Gl.ActiveTexture(TextureUnit.Texture0);
            Gl.BindTexture(TextureTarget.Texture2D, textureId);
            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)mode);
            Gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)mode);
            CheckGlErrors("pre-texture-upload");

            Gl.TexImage2D(TextureTarget.Texture2D,
                          0,
                          PixelInternalFormat.Rgba8,
                          data.Width, data.Height,
                          0,
                          PixelFormat.Rgba,
                          PixelType.UnsignedByte,
                          buffer);
            CheckGlErrors("post-texture-upload");

            if (mode == TextureWrapMode.ClampToBorder)
            {
                float[] borderColor = new float[] { 0xff, 0x14, 0x93 };
                Gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, borderColor);
            }

            CheckGlErrors("ok-texture-gen");

            return(textureId);
        }
        protected override void Renderer_DrawPrepare(RenderThread sender, FrameStageControllerEventArgs args)
        {
            CheckGlErrors("pre-program");
            sender.SelectShader(glyphShader);
            CheckGlErrors("post-program");

            sender.SelectShader(glyphShader);
            sender.SetUniform("resolution", 0, 0, sender.InternalResolution.Width, sender.InternalResolution.Height);
            sender.SetUniform("atlasSize", fontAtlas.AtlasTextureSize.Width, fontAtlas.AtlasTextureSize.Height);
            Gl.Uniform1(Gl.GetUniformLocation(glyphShader.ProgramId, "atlasTexture"), 0);
            CheckGlErrors("post-uniforms");
        }
        protected override void Renderer_ContextCreated(RenderThread sender, ContextCreationEventArgs args)
        {
            Log.WriteLine("Context created. Using: " + Gl.GetString(StringName.Renderer) + Gl.GetString(StringName.Version));

            Log.WriteLine("Renderer_ContextCreated");

            Renderer.TargetWindow.Resize += TargetWindow_Resize;

            // Load Shaders
            string vertex   = File.ReadAllText("./shaders/hello.vert".Replace('/', Path.DirectorySeparatorChar));
            string fragment = File.ReadAllText("./shaders/hello.frag".Replace('/', Path.DirectorySeparatorChar));

            // Compile shaders
            Log.WriteLine("Compiling shader 'hello'...");
            shader = new ShaderProgram(vertex, fragment);
            shader.Compile();
            Log.WriteLine("Compiled shader index: %@", LogLevel.Message, shader.ProgramId);

            // Load vertices and indices
            vertices = new float[] {
                0.0f, 0.5f, 0.0f,    // top
                0.5f, -0.5f, 0.0f,   // bottom right
                -0.5f, -0.5f, 0.0f,  // bottom left
            };

            // Setup global VAO
            VAO = Gl.GenVertexArray();
            Gl.BindVertexArray(VAO);

            CheckGlErrors("Renderer_ContextCreated:AfterVAO");

            // Setup VBO (vertices)
            VBO = Gl.GenBuffer();
            Gl.BindBuffer(BufferTarget.ArrayBuffer, VBO);

            int size = (sizeof(float) * vertices.Length); // size must be 36

            Gl.BufferData(BufferTarget.ArrayBuffer, size, vertices, BufferUsageHint.StaticDraw);
            CheckGlErrors("Renderer_ContextCreated:AfterBufferDataVBO");

            Gl.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), 0);
            CheckGlErrors("Renderer_ContextCreated:AfterVAP_VBO");

            Gl.EnableVertexAttribArray(0);

            CheckGlErrors("Renderer_ContextCreated:AfterVBO");

            // Unbind
            Gl.BindVertexArray(0);

            CheckGlErrors("Renderer_ContextCreated:End");
        }
예제 #10
0
        protected override void Renderer_ContextCreated(RenderThread sender, ContextCreationEventArgs args)
        {
            Log.WriteLine("Render context created. Continuing initialization...");

            Log.WriteLine("Running on OpenGL: %@", LogLevel.Message, Gl.GetString(StringName.Renderer) + Gl.GetString(StringName.Version));

            Renderer.TargetWindow.KeyDown += TargetWindow_KeyDown;
            Renderer.TargetWindow.KeyUp   += TargetWindow_KeyUp;

            CompileShaders();

            LoadTextures();

            Gl.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);

            VAO = Gl.GenVertexArray();
            Gl.BindVertexArray(VAO);

            CheckGlErrors("pre-texture");

            Gl.ActiveTexture(TextureUnit.Texture0);
            Gl.BindTexture(TextureTarget.Texture2D, fontAtlasTexture);

            CheckGlErrors("post-texture");

            VBO = Gl.GenBuffer();
            Gl.BindBuffer(BufferTarget.ArrayBuffer, VBO);

            EBO = Gl.GenBuffer();
            Gl.BindBuffer(BufferTarget.ElementArrayBuffer, EBO);

            CheckGlErrors("pre_va_pointer");

            Gl.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 12 * sizeof(float), 0 * sizeof(float));
            CheckGlErrors("post-va-pointer-0-set");
            Gl.EnableVertexAttribArray(0);
            CheckGlErrors("post-va-pointer-0-enable");

            Gl.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 12 * sizeof(float), 2 * sizeof(float));
            Gl.EnableVertexAttribArray(1);
            CheckGlErrors("post-va-pointer-1");

            Gl.VertexAttribPointer(2, 4, VertexAttribPointerType.Float, false, 12 * sizeof(float), 4 * sizeof(float));
            Gl.EnableVertexAttribArray(2);
            CheckGlErrors("post-va-pointer-2");

            Gl.VertexAttribPointer(3, 4, VertexAttribPointerType.Float, false, 12 * sizeof(float), 8 * sizeof(float));
            Gl.EnableVertexAttribArray(3);
        }
        protected override void Renderer_Draw(RenderThread sender, FrameStageEventArgs args)
        {
            Log.WriteLine("Renderer_Draw(%@)", LogLevel.Message, args.CurrentTime.FrameIndex);

            Gl.BindVertexArray(VAO);
            CheckGlErrors("Renderer_Draw:BindVAO");

            Gl.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);
            Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            CheckGlErrors("Renderer_Draw:Clear");

            Gl.UseProgram(shader.ProgramId);
            CheckGlErrors("Renderer_Draw:UseProgram");

            Gl.DrawElements(PrimitiveType.Triangles, 6, DrawElementsType.UnsignedInt, 0);
            CheckGlErrors("Renderer_Draw:DrawElements");
        }
예제 #12
0
        protected int LinkShaderProgram(int vertexId, int fragmentId)
        {
            int programId = Gl.CreateProgram();

            Gl.AttachShader(programId, vertexId);
            Gl.AttachShader(programId, fragmentId);
            Gl.LinkProgram(programId);

            Gl.GetProgram(programId, GetProgramParameterName.LinkStatus, out int success);
            if (success < 1)
            {
                string infoLog = null;
                Gl.GetProgram(programId, GetProgramParameterName.InfoLogLength, out int loglen);
                if (loglen > 0)
                {
                    string log;
                    Gl.GetProgramInfoLog(programId, loglen, out _, out log);
                    infoLog = log;
                }
                throw new ShaderException(this, "Program Link failed.", infoLog);
            }

            //Gl.ValidateProgram(programId);
            //Gl.GetProgram(programId, ProgramProperty.ValidateStatus, out success);
            //if (success < 1)
            //{
            //    string infoLog = null;
            //    Gl.GetProgram(programId, ProgramProperty.InfoLogLength, out int loglen);
            //    if (loglen > 0)
            //    {
            //        StringBuilder log = new StringBuilder(loglen);
            //        Gl.GetProgramInfoLog(programId, loglen, out _, log);
            //        infoLog = log.ToString();
            //    }
            //    throw new ShaderException(this, "Program Validation failed.", infoLog);
            //}

            return(programId);
        }
예제 #13
0
        protected int CompileShaderSource(ShaderType t, string code)
        {
            int shaderId = Gl.CreateShader(t);

            Gl.ShaderSource(shaderId, code);
            Gl.CompileShader(shaderId);
            Gl.GetShader(shaderId, ShaderParameter.CompileStatus, out int success);
            if (success < 1)
            {
                string infoLog = null;
                Gl.GetShader(shaderId, ShaderParameter.InfoLogLength, out int loglen);
                if (loglen > 0)
                {
                    string log;
                    Gl.GetShaderInfoLog(shaderId, loglen, out _, out log);
                    infoLog = log;
                }
                throw new ShaderException(this, "Shader compilation failed. Type:" + t.ToString(), infoLog);
            }

            return(shaderId);
        }
예제 #14
0
 private void ClearBuffer()
 {
     Gl.ClearColor(ClearColor.R / 255.0f, ClearColor.G / 255.0f, ClearColor.B / 255.0f, 0.5f);
     Gl.Clear(ClearBufferMask.ColorBufferBit);
 }
 private void TargetWindow_Resize(OpenToolkit.Windowing.Common.ResizeEventArgs obj)
 {
     Gl.Viewport(0, 0, obj.Width, obj.Height);
 }
예제 #16
0
 protected void DestroyShader(int shaderId)
 {
     Gl.DeleteShader(shaderId);
 }
예제 #17
0
        protected override void Renderer_Draw(RenderThread sender, FrameStageEventArgs args)
        {
            if (!sender.IsMainThread() && !sender.Asynchronous)
            {
                throw new InvalidOperationException("Draw operation initiated from secondary thread when supposed to run in Sync mode.");
            }

            float cellX = sender.InternalResolution.Width / (float)ConsoleSize.Width;
            float cellY = sender.InternalResolution.Height / (float)ConsoleSize.Height;

            List <float> vertices = new List <float>(4096);
            List <uint>  indices  = new List <uint>(4096);

            float[] db = ColorToFloatArray(DefaultBackColor);
            float[] df = ColorToFloatArray(DefaultForeColor);

            int vertexCount = 0;

            for (int xi = 0; xi < ConsoleSize.Width; xi++)
            {
                float x = xi * cellX;
                for (int yi = 0; yi < ConsoleSize.Height; yi++)
                {
                    RenderGlyph glyphData = GetGlyph(xi, yi);

                    if (ShowCursor && xi == Cursor.X && yi == Cursor.Y && glyphData == null)
                    {
                        int val = (int)((args.CurrentTime.TotalRuntime / 1000.0f) / BlinkInterval);
                        if (val % 2 == 0 || BlinkInterval == 0)
                        {
                            glyphData = new RenderGlyph('_');
                        }
                    }

                    float     y       = yi * cellY;
                    Rectangle texRec  = Rectangle.Empty;
                    int       glyphId = (int)(glyphData?.Glyph ?? ' ');
                    if (fontAtlas.ContainsId(glyphId))
                    {
                        texRec = fontAtlas.GetPointerById(glyphId).Bounds;
                    }
                    else if (fontAtlas.ContainsId(0x558))
                    {
                        texRec = fontAtlas.GetPointerById(0x558).Bounds;
                    }
                    else
                    {
                        texRec = fontAtlas.GetPointerById((int)'?').Bounds;
                    }

                    float[] b = glyphData == null || !glyphData.Background.HasValue ? db : ColorToFloatArray(glyphData.Background.Value);
                    float[] f = glyphData == null || !glyphData.Foreground.HasValue ? df : ColorToFloatArray(glyphData.Foreground.Value);

                    int qi = vertexCount;

                    vertices.AddRange(new float[] {  // Add vertices
                        x, y,                        // 0,0 (A)
                        texRec.X, texRec.Y,          // Texture X,Y
                        b[0], b[1], b[2], b[3],      // Back
                        f[0], f[1], f[2], f[3],      // Fore

                        x + cellX, y,                // 1,0 (B)
                        texRec.Right, texRec.Y,      // Texture X,Y
                        b[0], b[1], b[2], b[3],      // Back
                        f[0], f[1], f[2], f[3],      // Fore

                        x + cellX, y + cellY,        // 1,1 (C)
                        texRec.Right, texRec.Bottom, // Texture X,Y
                        b[0], b[1], b[2], b[3],      // Back
                        f[0], f[1], f[2], f[3],      // Fore

                        x, y + cellY,                //0,1 (D)
                        texRec.X, texRec.Bottom,     // Texture X,Y
                        b[0], b[1], b[2], b[3],      // Back
                        f[0], f[1], f[2], f[3],      // Fore
                    });

                    indices.AddRange(new uint[]
                    {
                        (uint)(qi + 1), // B
                        (uint)(qi + 3), // D
                        (uint)(qi),     // A
                        (uint)(qi + 1), // B
                        (uint)(qi + 2), // C
                        (uint)(qi + 3), // D
                    });

                    vertexCount += 4;
                }
            }

            Gl.BindVertexArray(VAO);
            Gl.BindBuffer(BufferTarget.ArrayBuffer, VBO);

            float[] fvertices = vertices.ToArray();
            vertices.Clear();

            uint[] iindices = indices.ToArray();
            indices.Clear();

            CheckGlErrors("pre-vab");
            GCHandle buffAddress = GCHandle.Alloc(fvertices, GCHandleType.Pinned);

            Gl.BufferData(BufferTarget.ArrayBuffer, fvertices.Length * sizeof(float), buffAddress.AddrOfPinnedObject(), BufferUsageHint.StreamDraw);
            buffAddress.Free();

            CheckGlErrors("pre-eab");
            buffAddress = GCHandle.Alloc(iindices, GCHandleType.Pinned);
            Gl.BufferData(BufferTarget.ElementArrayBuffer, iindices.Length * sizeof(float), buffAddress.AddrOfPinnedObject(), BufferUsageHint.StreamDraw);
            buffAddress.Free();

            CheckGlErrors("predraw");
            Gl.DrawElements(BeginMode.Triangles, iindices.Length, DrawElementsType.UnsignedInt, 0);

            CheckGlErrors("final");
            Gl.BindVertexArray(0);
            CheckGlErrors("unbind");
        }