Imposters
After a few weeks of being mostly occupied by applying certain interpersonal design patterns on real life, I've finally gotten the goddamn imposters to behave as required today >.<
Speaking of an application that renders a point cloud consisting of 100.000 vertices as shown by the screenshot above: When only small / slow local area movement is performed - which means only few imposters need to be updated every frame - the framerate stays stable around 400 FPS on a GeForce GTX 260 - To be precisely, this value is mostly affected not by the actual number of vertices, but by the number of octtree nodes being drawn. When moving much faster, it drops to a value between 100 and 150 FPS.
LOD Octtree Implementation
Just a few not much saying
screenshots from the debugging of a work-in-progress level-of-detail based implementation of the octtree algorithm I've presented a few weeks ago:
Anyone who can guess what screenshot #3 precisely shows..? Winner is gonna receive a cookie
Anyway, took me 'bout 48 hours to figure out that **** to work properly. A Grooveshark playlist mostly dominated by blink-182, Offspring and good ole Milk Inc. mixed up by some rock classics from Queen & Co. playing looped for a damn long time did a great service
So now the sun is arising I can finally go to sleep after a -finally- very successful day of work.
Alpha 2 & Resource Organization
Today I finished the last tasks I had queued for alpha 2. Furthermore I've put a snapshot of the recent version online accomplished by some documentation. By doing so I decided to share some thoughts on the organization of resources by contexts and I'd like to draw your attention to it: What's your opinion on my solution, how do you handle it?
I've also written a roadmap for the project:
- Alpha 1 (5. February 2010)
- First usable version with a basic implementation of all the most important features, those are:
- Post Processing Pipeline: Satisfying the demand on being easy to use, effects like blooming can be activated by up to three lines of code.
- Object oriented encapsulation of most important OpenGL elements like textures, frame buffer objects and many more, providing the paradigm of orthogonality while satisfying the demand on being flexible & robust.
- First usable version with a basic implementation of all the most important features, those are:
- Alpha 2 (23. July 2010)
- Countless bug-fixes & increased robustness
- Widely improved GL encapsulation
- Straightforward user-oriented design
- API completely re-organized by layers
← Here we are
- Alpha 3
- Implementation of per-object motion- & usual blurring
- Material property for specular highlighting
- GL/gl.h dependency removal from vertexbuffer.hpp
- Lazy state changes to avoid redundancy
- Major API changes
- Renderer class merged into RenderTarget
- Materials organized by resource contexts
- Potentially some kind of a shader abstraction:
- Stack-like organization of shader states
- Automatized shader generation
Z-Fighting Problem Solved
Thanks to an user named kRogue on the OpenGL forums the problem mentioned here is finally solved:
glTexParameteri( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_ALPHA );is not part of GL3 core... though it is there in a compatible context. Try taking that call out and use the .r component of the depth texture in your shader... this should NOT make a difference, but you never know.
- kRogue
Furthermore I've been notified that the problem didn't occur on a GF GTX260.
One more important aspect to notice that you should check if you should ever happen to run into the same problem as I did: The GL_MIN_FILTER and GL_MAG_FILTER properties of the depth texture object must be set to GL_NEAREST. At least they are not allowed to be set to GL_LINEAR. Don't ask me for the reason. Otherwise you will experience the same Z-Fighting as I did.
Update: Mess with depth textures
I've been stuck at a problem for a week now without making any progress. My goal was to draw some cubes into a framebuffer object, draw the result back into the default framebuffer and finally draw something more (a single quad) into the default framebuffer that correctly overlaps with the stuff drawn before. In order to achieve this I need to re-use the z-data from the framebuffer object. I have a depth-texture attached to the framebuffer object and when drawing back to the default framebuffer, I'm using a simple shader to write the z-data.
The following screenshot shows the result:

As you can see, the overlapping doesn't work properly.
I have written a minimal application which reproduces the problem, more on that later. Yesterday I've been playing around with the code and noticed that if I make the range between the near clipping plane and the far clipping plane smaller, the 'effect' shown above becomes smaller. The following screenshot shows the same scene with the near clipping plane moved from 0.1f to 1.f and the the far clipping plane from 100.f to 50.f:

So I believe the depth values are somehow quantized far too much. But why? It cannot be the precision of my depth texture which is 24 bit since if I change it to 32 bit the 'effect' stays exactly the same. If it would be caused by a too low precision of the depth texture, I would have expected the 'effect' to become less.
I can think of two possible reasons though I'm not able to explain either of them. So either the projection matrix is getting messed up somehow so that the quotient of the clipping planes becomes superdimensional. Or the quantization is caused by the "gl_FragDepth = texture2D( depthtex, gl_TexCoord[0].xy ).a" instruction in the fragment shader.
Vertex shader:
void main() { gl_Position = ftransform(); gl_TexCoord[0] = gl_MultiTexCoord0; }
Fragment shader:
#version 120 uniform sampler2D texture0; uniform sampler2D depthtex; void main() { gl_FragColor = vec4( texture2D( texture0, gl_TexCoord[0].xy ).xyz, 1.0 ); gl_FragDepth = texture2D( depthtex, gl_TexCoord[0].xy ).a; }
The minimal application can be found here:
http://pastebin.com/UctqYW33
If you have SFML2, you can use the following code for running the application:
http://pastebin.com/yJgvQpnK
Otherwise you could use the library of your choice for creating the GL context, like glut or freeglut or whatever.
I've already posted on several forums without getting any further leading advices.
Update + Thoughts of Quad- & Octtrees
Even though I didn't update that blog during the past few months, the work proceeded quite well. A countless amount of bugs has been fixed, the abstraction from OpenGL improved a lot and the API itself completely revised. I've outlined a road map of what still has to be done 'til Alpha 2 and it's not that much:
- Implement DefaultMesh::CreateSphere
- Implement DefaultMesh::CreateCylinder
- Implement DefaultMesh::CreateCone
- Solve Bloom-zBuffer-Problem
- Clean up some header files
So #1 was an ease and now I'm still almost done with #4 which is the last greater task. The problem here was that rendering with bloom worked like a charm but when rendering in combination with objects that should have been not affected by the bloom effect, the depth-buffer information messed up. The bad thing about it is that I finally reached the limits of the possibilities of my GeForce 6600 and am not able to proceed right now, for I also don't have the money to buy me a new card. So it's fairly probable that I won't continue work on this task until September, when I expect to get a new notebook bought by the institute I will start working at, namely the Institute for Medical Engineering as an appliance.
So I spent a few thoughts on the later organization of the world data in octtrees recently when I was bored. The following short article will describe a way of organizing the nodes of a quadtree (for the sake of clarity) in a certain way which allows a very easy and straightforward traversal of the tree. It is trivial to expend this technique to work with octtrees.
Debug Features & Fixed Bump Mapping
The recently published screenshots of my bump mapping implementation contained some bugs caused by wrong computation of texture coordinates:

It was an ease to solve them after finishing the implementation of some debug-features. These mainly include the visualization of texture coordinates, face tangents and face normals, but also the visualization of per-pixel normals, realized by false-color rendering.
A scene rendered with some extra mesh debugging information:

The yellow line represents the first tangent space base vector, whereas the bold blue line represents the second one and the tiny blue line represents the second tangent space base vector multiplied by -1. The numbers show the texture coordinates for every vertex. The red line in the face's center stands for the face's normal and the green line for it's tangent. Of course it is possible to toggle all the different debug modes during the application is running.
The same scene with the normal vectors of the G-buffer rendered to the color channel for every fragment:

Of course it is also possible to visualize only a certain normal vector component, as shown here for the x-component:

Deferred Lighting
Some days ago I finished implementing a deferred lighting system. That's a shader driven lighting system that scales very well with lots of light sources because redundant vertex transformations are being avoided and was used in recent top-seller games like S.T.A.L.K.E.R. or Crysis. This is achieved by rendering the whole scene into a so called G-Buffer, where the 'G' stands for 'geometry', in a first pre-pass. Currently I'm using MRT with three 16 bit floating point RGBA textures which means that I have 12 channels for every fragment in my G-Buffer. I would prefer using two 32 bit floating point textures instead, so I would have 16 channels by packing two 16 bit values into one 32 bit field, but my ancient GeForce 6600 doesn't support Shader Model 3.0 which is required for bit-wise operators.
Current Project (yet unnamed) Update
The basic material functionalities, like browsing available materials and assigning them to the material slots of instantiated tiles, are finally implemented now. Actually I wanted to to implement bump mapping next, and that's still the thing I'm going to do, but I noticed that I will have to completely rewrite the way tiles are loaded first and introduce a different tile definition format.




