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:
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?
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 byglClearColor
,glClearDepth
, andglClearStencil
. [...]