Global Illumination via Voxel Cone Tracing in LWJGL

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!

This is really cool!

Are you using sparse textures? What memory usage are you getting? How are you voxelizing the game world? Are you revoxelizing dynamic objects each frame? Performance at different resolutions?

No update? =<

Mind uploading you program to shared code or JGO files?

OpenGL Insights has some very nice paper about the general algorithm: http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-SparseVoxelization.pdf

Is there any news from the thread creator? :slight_smile: I would like to see more stuff, especially videos from your demo app or even an executable, since I’m going to implement VCT soon with LWJGL, too.

I found the gamedev.net thread with a simple google search on the IMG url used in this thread xD
You can find it here.

I implemented this with LWJGL too, but used a 256256256 3d texture. The (automatic) mipmapping takes unbelievable 500ms on my GTX 770 and therefore destroys the whole approach. I’m using

GL11.glTexParameteri(GL12.GL_TEXTURE_3D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR);
GL11.glTexParameteri(GL12.GL_TEXTURE_3D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);

Can anyone share a similar experience - or give me some info about how to speed things up a bit (different filters?)? I would implement compute shader based mipmapping otherwise.

Automatic mipmapping is slow. Also, 256^3 is 8x the pixels of 1920x1080, so generating the first mipmap (the 128^3 one) is a huge amount of work: around 2 million pixels reading 128MBs of data assuming GL_RGB16F.

I’d try using GL_R11F_G11F_B10F to halve the bandwidth and memory cost and do the downsampling of mipmaps in a shader instead.

Ok, limiting the bandwidth is the next thing i will try but i wonder how everyone is talking about voxel cone tracing with 256 * 256 * 256 3d textures if it isn’t even possible to mipmap it automatically… I’m pretty sure i can mipmap 8 fullhd textures per frame, but i may be wrong. More results coming.

Doing it manually is easy. Just render a fullscreen quad to each layer of the mipmap and do a single GL_LINEAR texture sample to sample all 8 parent texels with one sample.

Yes, its Not the Problem, did it often, the Problem is that i have to do it :smiley: and of course its a pity that automatic mipmapping Performance is so poor.

A pity that there is so little time to work on private projects. I managed to implement a basic voxel cone tracing approach with LWJGL with compute shader based mipmapping, so that it can be done in realtime now. Very unoptimized, very ugly, some parts are actually WRONG and overall far from completed, but I thought you guys like to see something done with Java.

pure specular tracing

http://s18.postimg.org/om8vj5yq1/vct_spec.jpg

emmissive material applied to have arealight

http://s14.postimg.org/e6sqkla3z/vct_arealight.jpg

The second image isn’t loading, but… Damn! Looks good!

It loads if you copy the URL directly into the browser.

Damn. What really gets me is the colored reflection on the arcs…

More love for you

pretty cool results so far.

Daaaaaaamn…

How dynamic is this? Are you voxelizing the world every frame or using a precomputed voxel world?

Completely dynamic: voxelization is done every frame, lighting is done every frame, filtering is done every frame. I’m not yet using a sparse data structure so that won’t change in the near future.

What’s strange for me is that none of these pictures are showing up and there isn’t even any indication that there’s anything I’m missing (no empty box or anything…just whitespace like a text only post)