nonsensation
nonsensation

Reputation: 303

OpenGL: Framebuffer - draw to texture - glClearColor

I have implemented a simple deferred renderer, using a FrameBuffer and a Texture.
The drawing looks like this:

The code (C#):

        private void Setup()
        {
            {
                _shader = new Shader();
                _shader.AddShader( ShaderType.VertexShader , vertShaderSource );
                _shader.AddShader( ShaderType.FragmentShader , fragShaderSource );
                _shader.CompileAndLink();

                _vertexArray = new VertexArray();
                _vertexArray.Bind();

                _vertexBuffer = new VertexBuffer();
                _vertexBuffer.SetLayout<float>();
                _vertexBuffer.Bind();
                _vertexBuffer.Update( ObjectData );

                _indexBuffer = new IndexBuffer();
                _indexBuffer.SetLayout<int>();
                _indexBuffer.Bind();
                _indexBuffer.Update( ObjectIndices );

                GL.VertexAttribPointer( index: 0 , size: 3 , VertexAttribPointerType.Float , normalized: false ,
                    stride: sizeof( float ) * 3 , offset: 0 );
                GL.EnableVertexAttribArray( 0 );

                _uniformBuffer = new UniformBuffer();
                _uniformBuffer.SetLayout<uUniformBlock>();
                _uniformBuffer.Bind();
                _uniformBuffer.Reserve( 1 );

                _shader.BindUniformBuffer( _uniformBuffer , nameof( uUniformBlock ) , UNIFORM_BLOCK_BINDING_uUniformBlock );

                _vertexArray.Unbind();
                _vertexBuffer.Unbind();
                _uniformBuffer.Unbind();
            }

            // Quad
            {
                _frameBuffer = new FrameBuffer();
                _frameBuffer.Bind();

                _quadTexture = new Texture( TextureTarget.Texture2D , this.Width , this.Height );
                _quadTexture.Bind();

                GL.GenerateMipmap( GenerateMipmapTarget.Texture2D );

                _frameBuffer.Attach( FramebufferAttachment.ColorAttachment0 , _quadTexture );
                _frameBuffer.CheckStatus();

                _quadShader = new Shader();
                _quadShader.AddShader( ShaderType.VertexShader , quadVertShaderSource );
                _quadShader.AddShader( ShaderType.FragmentShader , quadFragShaderSource );
                _quadShader.CompileAndLink();

                _quadVertexArray = new VertexArray();
                _quadVertexArray.Bind();

                _quadVertexBuffer = new VertexBuffer();
                _quadVertexBuffer.SetLayout<float>();
                _quadVertexBuffer.Bind();
                _quadVertexBuffer.Update( QuadData );

                // Pos X Y
                GL.VertexAttribPointer( index: 0 , size: 2 , VertexAttribPointerType.Float , normalized: false ,
                    stride: sizeof( float ) * 4 , offset: sizeof( float ) * 0 );
                GL.EnableVertexAttribArray( 0 );
                // TexCoord U V
                GL.VertexAttribPointer( index: 1 , size: 2 , VertexAttribPointerType.Float , normalized: false ,
                    stride: sizeof( float ) * 4 , offset: sizeof( float ) * 2 );
                GL.EnableVertexAttribArray( 1 );

                _quadVertexArray.Unbind();
                _quadVertexBuffer.Unbind();
                _quadTexture.Unbind();
            }
        }

        private double _totalTime = 0.0;

        protected override void OnRenderFrame( FrameEventArgs args )
        {
            base.OnRenderFrame( args );

            GL.Clear( ClearBufferMask.ColorBufferBit );

            _totalTime += args.Time;

            var color = new Vector3( (float)Math.Sin( _totalTime * 2.0 ) ,
                                     (float)Math.Cos( _totalTime * 3.0 ) ,
                                     (float)Math.Tan( _totalTime * 1.0 ) );

            var uniformBlackData = new uUniformBlock() {
                uR = color.X ,
                uG = color.Y ,
                uB = color.Z ,
            };

            // first pass
            {
                _frameBuffer.Bind();

                GL.Clear( ClearBufferMask.ColorBufferBit );
                GL.ClearColor( 0.2f , 0.3f , 0.3f , 1.0f );

                _shader.Activate();
                // _shader.SetUniform( "uColor" , color );

                _vertexArray.Bind();
                _uniformBuffer.Bind(); // TODO: is this needed?
                _uniformBuffer.Update( uniformBlackData );

                GL.DrawElements( PrimitiveType.Triangles , count: ObjectIndices.Length ,
                    DrawElementsType.UnsignedInt , IntPtr.Zero );

                _vertexArray.Unbind();
            }

            // second pass
            {
                FrameBuffer.BindDefaultFrameBuffer();

                GL.Clear( ClearBufferMask.ColorBufferBit );
                GL.ClearColor( 1.0f , 0.0f , 1.0f , 1.0f );

                _quadShader.Activate();
                GL.ActiveTexture( TextureUnit.Texture0 + 0 );
                _quadShader.SetUniform( "uTexture0" , 0 );

                _quadVertexArray.Bind();
                _quadTexture.Bind();

                GL.DrawArrays( PrimitiveType.Triangles , 0 , 6 );

                _quadVertexArray.Unbind();
            }

            base.SwapBuffers();
        }

It looks like this:

enter image description here

However, I expected the result to be the other way around - the greyish and magenta color swapped. Shouldn't the texture that was rendered to have the grey background, and the 2nd phase quad texture be surrounded with magenta (as its slightly smaller than windowsize)?
Is this image correct or my understanding not quite accurate?

Upvotes: 1

Views: 786

Answers (1)

Rabbid76
Rabbid76

Reputation: 211278

You have to set the clear color before you clear the buffer:

GL.Clear( ClearBufferMask.ColorBufferBit );
GL.ClearColor( 0.2f , 0.3f , 0.3f , 1.0f );

GL.ClearColor( 0.2f , 0.3f , 0.3f , 1.0f );
GL.Clear( ClearBufferMask.ColorBufferBit );

GL.ClearColor specifies the color that GL.Clear( ClearBufferMask.ColorBufferBit ) uses to fill the pixel in the framebuffer.

See the OpenGL wiki page glClear:

glClear sets the bitplane area of the window to values previously selected by glClearColor, glClearDepth, and glClearStencil. [...]

Upvotes: 1

Related Questions