In this post, I would like to document my experiences in developing deferred renderer, transparency and a pseudo approach to translucency.
Deferred Rendering
I have implemented deferred rendering which has geometry buffers of world position, world normal, diffuse color, and specularity.
#version 440 core
layout(location = 0) out vec3 position_GBuffer;
layout(location = 1) out vec4 normal_GBuffer;
layout(location = 2) out vec3 diffuse_GBuffer;
layout(location = 3) out vec4 specularAndPhong_GBuffer;
uniform vec4 diffuseReflectance;
uniform vec3 specularReflectance;
uniform float phongExponent;
uniform float translucency;
in vec4 fragmentPositionWorldSpace;
in vec3 vertexNormal;
void main()
{
diffuse_GBuffer = diffuseReflectance.xyz;
specularAndPhong_GBuffer = vec4(specularReflectance, translucency);
position_GBuffer = fragmentPositionWorldSpace.xyz;
normal_GBuffer = vec4(vertexNormal, phongExponent);
}
After rendering these geometry buffers, they are rendered to a screen mesh by calculating light intensity with these geometry buffers with corresponding pixel indices.
void DeferredRenderingData::Init()
{
deferredRenderingMesh = new StaticMesh();
deferredRenderingMesh->AddVertex(Vector3{ -1.f, -1.f, 0.f });
deferredRenderingMesh->AddVertex(Vector3{ 3.f, -1.f, 0.f });
deferredRenderingMesh->AddVertex(Vector3{ -1.f, 3.f, 0.f });
deferredRenderingMesh->AddFace(Face{ 0, 1, 2 });
deferredRenderingMesh->PreInit();
deferredRenderingMeshShader = new Shader();
deferredRenderingMeshShader->SetVertexShaderScript(ShaderBuilder::GetInstance()->GetVertexShaderScript_DeferredPass());
deferredRenderingMeshShader->SetFragmentShaderScript(ShaderBuilder::GetInstance()->GetFragmentShaderScript_DeferredPass());
#if defined(GOKNAR_BUILD_DEBUG)
IOManager::WriteFile("./DeferredRendering.vert", deferredRenderingMeshShader->GetVertexShaderScript().c_str());
IOManager::WriteFile("./DeferredRendering.frag", deferredRenderingMeshShader->GetFragmentShaderScript().c_str());
#endif
deferredRenderingMeshShader->PreInit();
deferredRenderingMeshShader->Init();
deferredRenderingMeshShader->PostInit();
engine->GetRenderer()->BindShadowTextures(deferredRenderingMeshShader);
geometryBufferData = new GeometryBufferData();
geometryBufferData->Init();
engine->GetWindowManager()->AddWindowSizeCallback(Delegate<void(int, int)>::create<DeferredRenderingData, &DeferredRenderingData::OnWindowSizeChange>(this));
}
void DeferredRenderingData::Render()
{
engine->GetRenderer()->BindStaticVBO();
deferredRenderingMeshShader->Use();
deferredRenderingMeshShader->SetInt(SHADER_VARIABLE_NAMES::GBUFFER::OUT_POSITION, geometryBufferData->worldPositionTexture->GetRendererTextureId());
deferredRenderingMeshShader->SetInt(SHADER_VARIABLE_NAMES::GBUFFER::OUT_NORMAL, geometryBufferData->worldNormalTexture->GetRendererTextureId());
deferredRenderingMeshShader->SetInt(SHADER_VARIABLE_NAMES::GBUFFER::OUT_DIFFUSE, geometryBufferData->diffuseTexture->GetRendererTextureId());
deferredRenderingMeshShader->SetInt(SHADER_VARIABLE_NAMES::GBUFFER::OUT_SPECULAR_PHONG, geometryBufferData->specularTexture->GetRendererTextureId());
engine->GetRenderer()->SetLightUniforms(deferredRenderingMeshShader);
int facePointCount = deferredRenderingMesh->GetFaceCount() * 3;
glDrawElementsBaseVertex(GL_TRIANGLES, facePointCount, GL_UNSIGNED_INT, (void*)(unsigned long long)deferredRenderingMesh->GetVertexStartingIndex(), deferredRenderingMesh->GetBaseVertex());
}
Transparency
Transparent objects are sorted by distance to the camera, and after deferred render pass, they are rendered with forward rendering.
Translucency
I have implemented a pseudo translucency by inverting fragment normal by translucency value if the normal is in opposite direction of the light source used to calculate the intensity.
I call it pseudo because it is not a real translucencty calculation but an imitation of it. Subsurface Scattering is the best approach but this one will do the trick for now.
The reason I needed to implement translucency is to have grass with color in each direction. Otherwise, behind sides of it becomes absolute dark and it does not look good.
Without translucency:
With translucency: