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: