Hi all - I’ve already posted this on gamedev.net today, but I figured I may as well post to JGO as well, seeing as I implemented this in LWJGL! ;D
I was inspired to implement this into my game engine after watching Unreal Engine footage.
After finding some sample code for OpenGL in C++, I was more intrigued and decided to implement my own version.
Here are some screenshots to show off the effect:
Here is some of my code for building the textures:
for (int i = 0; i < 2; i++) {
textures[i] = GL11.glGenTextures();
glBindTexture(GL_TEXTURE_3D, textures[i]);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, TextureFilter.LinearMipMapLinear);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, TextureFilter.LinearMipMapLinear);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGBA32F, 128, 128, 128);
GL30.glGenerateMipmap(GL_TEXTURE_3D);
glBindTexture(GL_TEXTURE_3D, 0);
gilight[i] = new GIRenderer(rm, textures, voxelShader, i, viewCam, camDir[i]);
gilight[i].init();
}
This is where I set up the two (for now) 3D textures. I have a camera facing one side of the scene, and another facing the opposite side of the scene.
When the scene is rendered for each camera, the pixels that are rendered are stored into it’s respective 3D texture.
I then bind the 3D textures to the forward lighting shader, here is what this looks like.
uniform sampler3D tex[2];
I then trace a cone into the 3D texture to retrieve reflections. (Credit to Alex Nankervis, found this code on Geeks3D)
vec4 voxelTraceCone(float minVoxelDiameter, vec3 origin, vec3 dir, float coneRatio, float maxDist)
{
float minVoxelDiameterInv = 1.0/minVoxelDiameter;
vec3 samplePos = origin;
vec4 accum = vec4(0.0);
float minDiameter = minVoxelDiameter;
float startDist = minDiameter;
float dist = startDist;
vec4 fadeCol = ambientLight.color*0.2;
while (dist <= maxDist && accum.w < 1.0)
{
float sampleDiameter = max(minDiameter, coneRatio * dist);
float sampleLOD = log2(sampleDiameter * minVoxelDiameterInv);
vec3 samplePos = origin + dir * dist;
vec4 sampleValue = voxelFetch(samplePos, -dir, sampleLOD);
sampleValue = mix(sampleValue,fadeCol, clamp(dist/maxDist-0.25, 0.0, 1.0));
float sampleWeight = (1.0 - accum.w);
accum += sampleValue * sampleWeight;
dist += sampleDiameter;
}
return accum;
}
I hope this helped some people understand how voxel cone tracing works in some more simpler terms. It was a real task to implement this and I still have some work to do, but as you can see from my screenshots, it works well so far!