I have implemented a simple deferred renderer, using a FrameBuffer and a Texture.
The drawing looks like this:
- first phase
- bind the framebuffer
- create and attach a color texture to the framebuffer
- clear color bit & set glClearColor to this darkish blue/grey
- draw a quad with changing colors (inner green quad)
- second phase
- set default framebuffer
- clear color bit & set glClearColor to magenta
- draw an (almost) fullscreen quad and use the color texture
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?