A long presentation…

June 10th, 2008

The professor of the computer graphics course at my university was continuosly annoyed by my protests and comments during her lectures..

I’m sorry but I just couldn’t stand some claims like: “Phong shading is never used in interactive applications because of it being computationally too heavy”… :)
Fortunately she gave me the opportunity to give everyone a small technological update. :D
After about a month, my presentation was born.
Made entirely with LaTeX Beamer, VIM, Dia and GIMP, it deals about what modern GPU are capable of, showing some GPGPU applications, along with traditional ones (videogames :D ), and some shader examples together with commented code.

I discussed it yesterday in a couple of hours, I was all shook up at first but then I advanced smooth and plain. ;)
It is in Italian, of course, but I published it anyway: Le Moderne GPU.

Let there be light!

April 28th, 2008

I started exploring deferred shading rendering to display multiple light sources and ended writing a demo featuring eight different lighting techniques and a PyOpenGL class library. :)

glsl_multilight

The whole story is more than a month old, just after releasing the first depth of field demo I began studying deferred shading, but I extended my purpose to include other lighting methods, like single and multi-pass fixed-pipeline lighting, per-vertex and per-pixel single and multi-pass shader lighting and, of course, deferred one.

While writing the C code, I thought it was going to be fun to also port it to Python, this way I could have also have a look to the “new” (ArchLinux adopted it quite late :) ) ctypes PyOpenGL, aka PyOpenGL 3.

Unfortunately, many little but annoying issues delayed me until today:

  • not setting explicitely glDepthFunc(GL_LEQUAL) (or, alternatively, not clearing the depth buffer at each pass) for multi-pass scene rendering made every pass to be discarded excepting the first one.
  • trying to make a buggy Python glDrawBuffers() wrapper work.
    Actually I had no luck with this and give up on MRTs support in PyOpenGL.
  • trying to figure out why VBOs didn’t work on PyOpenGL, I give up on this too. :)
  • using a uniform variable to index the gl_LightSource structure array, which prevented the shader from running on Shader Model 3.0 cards
  • exploring all the possibilities that could ever lead to “the brick room is very dark in fixed-pipeline mode” issue, only to discover today that this was a mere scaled normals problem.
    It was easily solved enabling GL_RESCALE_NORMAL

At last I made it, I have made a multi light demo that includes deferred lighting (although very rough and not optimized at all) and shows coherent lighting in all rendering modes.
The PyOpenGL class library almost works, no MRTs and VBOs, but it is functional enough to sport a complete DoF2 and multilight (without deferred mode, which relies on MRTs, of course) demo conversions.

It’s not a news anymore that you can view it in action on my YouTube Channel, or in a high definition 720p version hosted on my Vimeo page.

All’s well that ends well. :)

Depth of field reloaded

April 15th, 2008

Lately I’ve been really disappointed by the poor performances of my first depth of field implementation, thus I decided to do something about it…

glsl_dof2

The most natural step to do was to give a look to the second Direct3D example from the same paper I used for the first one, as I was sure it would have led to more satisfactory results.
I spent the two last nights converting, correcting and fine tuning it, but I was rewarded by the fact that I was right: even if it is a five passes algorithm which is using four different Frame Buffer Objects, it is about 2.5 times faster than my previous implementation!

I think the speed boost depends on the two following:

  1. image blurring is achieved by a gaussian filter which is calculated separating the X from the Y axis, it is an approximation of a standard 2D kernel but it also means that the convolution matrix calculation complexity decreases from a quadratic to a linear factor.
  2. this filter operates only on a downsampled (1/4th of the screen resolution actually) FBO

Another nice note about this new implementation is that there are only two focal parameters, focus depth and focus range, which really help to setup a correct scene.

Now let’s review the five passes in detail:

  1. Render the scene normally while calculating a blur amount per-vertex, then store the interpolated value per-pixel inside the alpha component of the fragment.
    The calculation at the vertex shader is just:

    
    Blur = clamp(abs(-PosWV.z - focalDistance) / focalRange, 0.0, 1.0);
    
  2. Downsample the scene rendered at the previous pass storing it in a smaller FBO
  3. Apply the gaussian filter along the X axis on the downsampled scene and store it in a new FBO
  4. Apply the gaussian filter along the Y axis on the already X blurred scene and store it in a new FBO
  5. Calculate a linear interpolation between the first full resolution FBO and the XY downsampled blurred one
    This is performed in the fragment shader as:

    
    gl_FragColor = Fullres + Fullres.a * (Blurred - Fullres);
    

Again, you can view it in action on my YouTube Channel, or in a high definition 720p version hosted on my Vimeo page. ;)

I love depth of field

March 23rd, 2008

I consider depth of field as one of the most beautiful post-processing effects of the “next-gen” games.
It was natural for me to choose it as the first shader demo to implement after months of inactivity, as a matter of fact GLSL_impgro was really just a testbed for post-processing basic techniques, like Frame Buffer Objects.

GLSL_DoF

I have studied the theory from an ATI paper included in the ShaderX2 book, titled Real-Time Depth of Field Simulation, I have choosen the first of the two different implementation and converted it from Direct3D and HLSL to OpenGL and GLSL.

Of course, being a post-processing effect, the rendering is actually divided in two pass:

  1. Rendering the scene storing the depth of every vertex and calculating the amount of blur per fragment
  2. Applying the blur per fragment based on the value from the previous step

The second pass fragment shader, the one which is really applying the blur effect, is slow even on my 8600GT, because it performs several calculations for every one of the twelve fragments that are contributing to the blur of the center one.

Another interesting aspect is that, in order to calculate a correct approximation of the circular blur needed for circles of confusion simulation, these twelve pixel are sampled around the center based on a poissonian disc distribution, thus creating much less artifacts than a small convolution matrix scaled too much in order to sample from far away the center.

Just like the previous demo you can view it in action on my YouTube Channel, but I really suggest you to give a look to the high definition 720p version instead, hosted together with the other ones on my Vimeo page. ;)

glUniform1f() is working!

March 17th, 2008

I faced this problem for the first time a year ago, while working for my parallax mapping demo, and I met it again these days, in which I’m busy to fine tune my depth of field demo to permit keyboard driven parameters tweaking.

Bug

The issue I’m talking about is quite seriuos, on my machine it is impossible to pass a float uniform variable to a shader, and I’m not the only one reporting it:

The first link is a forum thread from GameDev written by a guy whose applications suffer from this annoying issue, he has written a proof of concept which works perfectly on my box, i.e. float uniforms are NOT passed. :)
But it has been the third one which made me think about how to fix the problem: it has been reported that, after calling glewInit(), glUniform*f() functions work again.

The first thing I did, of course, was to download and investigate inside GLEW sources to see what was happening inside that magic function. What it does, actually, is redefining all the GL function pointers calling glXGetProcAddress() for everyone of them, I thought it would have been a good thing to try to replicate this behaviour in my programs, and I was right! :D

This is what I added to my sources for the incriminated function to work:


PFNGLUNIFORM1FPROC glUniform1f = NULL;
glUniform1f = (PFNGLUNIFORM1FPROC)glXGetProcAddress((const GLubyte*)"glUniform1f");

This also seems to explain why my Python shader demo didn’t suffer from all of this, I think that PyOpenGL initializes itself retrieving the addresses for all the GL functions it needs.

IMPORTANT UPDATE
M3xican, the shader master came with THE solution, just add -DGL_GLEXT_PROTOTYPES to CFLAGS.
Hail to the master! :D

Image post-processing with shaders

March 13th, 2008

I’m back to work after many months, university exams take really a lot of time…
For I am a bit rusty on GLSL programming, but willing to learn new things anyway, I have decided to begin with a simple yet interesting topic, image processing.

GLSL_imgpro

The whole thing, actually, needs two rendering passes and relies heavily on Frame Buffer Objects because:

  1. You render the scene to an off-screen texture.
  2. You render a quad covering the entire screen and binded to the previously written texture.
  3. You make a shader process the fragments resulted from rendering this textured quad, i.e. post-processing the original scene.

In this program post-processing is demanded to convolution matrices calculated with these kernels:


GLfloat kernels[7][9] = {
    { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* Identity */
    { 0.0f,-1.0f, 0.0f,-1.0f, 5.0f,-1.0f, 0.0f,-1.0f, 0.0f}, /* Sharpen */
    { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}, /* Blur */
    { 1.0f, 2.0f, 1.0f, 2.0f, 4.0f, 2.0f, 1.0f, 2.0f, 1.0f}, /* Gaussian blur */
    { 0.0f, 0.0f, 0.0f,-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* Edge enhance */
    { 1.0f, 1.0f, 1.0f, 1.0f, 8.0f, 1.0f, 1.0f, 1.0f, 1.0f}, /* Edge detect */
    { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,-1.0f}  /* Emboss */
};

The final fragment color is calculated by a simple shader which, at the core, just performs the following:


for(i = -1; i <= 1; i++)
    for(j = -1; j <= 1; j++) {
        coord = gl_TexCoord[0].st + vec2(float(i) * (1.0/float(Width)) * float(Dist), float(j) * (1.0/float(Height)) * float(Dist));
        sum += Kernel[i+1][j+1] * texture2D(Tex0, coord.xy);
        contrib += Kernel[i+1][j+1];
    }

    gl_FragColor = sum/contrib;

When the user chooses a filter, the application updates the kernel currently in use with a call to:


loc = glGetUniformLocation(sh.p2, "Dist");
glUniform1i(loc, dist);
loc = glGetUniformLocation(sh.p2, "Kernel");
glUniformMatrix3fv(loc, 1, GL_FALSE, &kernels[curker]);

Dist is a user defined parameter (you can change it using arrows) that defines the distance in pixels from the center to the contributing sample.

Since a month I have created a YouTube Channel, now you can have an idea of how this demo works without downloading and compiling the source code: have a look at this link! ;)

GameCon 2007

December 10th, 2007

GameCon is the only game and videogame showroom in Italy, and, fortunately for me, it is held in my city. ;)
Last year it changed its name from N-joy to the current one and received much more advertising and public visibility, therefore me and M3xican decided to attend it. ;)

GameCon Logo

We had the possibility to view, and what is more important, to test next-gen consoles the way they deserved, on huge LCDs! :D
There were a lot of XBox 360 running the most recent games, like the first UE3 engine powered one, the stunning Gears of War, some Nintendo Wii made their first Italian apparition at the show and, last but not least, I have heard that the last day a Playstation 3 was previewed!
You could play with many Nintendo DS and some powerful PCs, subscribe to rewarded tournaments in many games, admire original BenoĆ®t Sokal illustrations (which unfortunately couldn’t be there as scheduled), moreover some space had been dedicated to a lot of different board games and somebody was enjoying cosplaying.
However, something more interesting happened some weeks before the event, when I got in touch with its Cultural Director.
Our emails shared the common vision to evolve the current target of attendees to include game developers too, for example organizing interesting conferences and gathering the most influential Italian exponents of the industry.

This was what happened this very year, with the announce of Game in Italy 2007, thus on Saturday me and M3xican went there, loaded with great expectations (like the hope to assist to a little GDC wannabe ;) )!
Even if a lot of important Italian software houses were invited, even if Rasmus Poulsen (a concept artist working for IO Interactive) was present as a guest star, it has been a disappointment.
The event was too modest to even feature a fair-sized room, it was not only so small that just a dozen guys could sit inside, but so hot (damned lamps!) that you couldn’t stand at the entrance, ignoring for a while the fact that there was only one speaker and that you could barely hear what it was said by the participants.
It was interesting to notice that outside the room there was a big LCD showing what was happening inside, but we were surprised to discover that nothing was audible, it was mute! 8O
I only hope they have recorded the speeches…

To draw a conclusion, it failed to meet our expectations, we couldn’t attend the conferences while the rest of the show wasn’t so extraordinary, it has been less interesting than the previous year, maybe because next-generation gaming is now current-generation… ;)
I only hope that next year Game in Italy gains the space, the attention and the visibility it deserves!

Back in blog

December 1st, 2007

My blog is back, at last!
I was starting to lose the hope for a data rescue and beginning from scratch (as a matter of fact I wrote the Photon post before this one), but, fortunately, it was not the case…

WordPress Logo

Our marsnomercy.org server has been down since the 31st of July for a stupid fan problem, the Mars site/wiki/bug tracker and my little blog have followed it. :(
On that server, in my mailbox, I used to collect blog backups… yes, I’ve been so stupid to weekly archive database backups on the same machine running the DBMS… :)
But now, thanks to Dekki, our great 3d artist and sysadmin, we have all the data back on a replacement server!

But, as you have probably noticed, the blog is now hosted on Netsons, a reliable and feature rich free hosting solution, which is also the home of my new Encelo’s Projectz site, now running on Drupal.

Today I’ve been busy with xml imports/exports, ftp uploads and tons of manual phpmyadmin updates, but it has been worth the effort.
I have installed the latest WordPress from scratch (welcome integrated tagging! ;)), updated all the plugins, imported the access statistics and made a Last.fm and a Ohloh widget.

The blog is back and it is here to stay! ;)

Hail to the Photon

November 26th, 2007

On Thursday I assembled Photon, my brand new workstation, the day after I received also the surround speakers set and the fantastic wide monitor.

For the detailed configuration you can have a look at the page written for this purpose. :)

Photon

The specifications are not extraordinary (except for the monitor, maybe, which is a bit larger than usual, but you all know that the display area of a monitor is never enough ;) ), Photon was built with the aim to be cheap but effective, no bells and whistles, but a solid and balanced platform.
Moreover, buying from the entry level segment avoid the situation when you wake up a morning and discover that your hardware is worth 25% less than the previous day…

With Photon I have the possibility to be part of the next-gen gaming era, to exploit multi-threaded programming with a real performance gain, to explore the Shader Model 4 and OpenAL benefits… and to run a heavy Compiz Fusion configuration at 1680×1050! ;)

PySoy, a month after

July 1st, 2007

A bit more than a month of SoC work has passed now, PySoy is alive and getting better day after day, and since some days you can even get a taste of it!
After the release of the GPLv3 our SVN repository has been opened to the public, read more on Arc’s blog.

Textured Pyramid

About the point of view of my application the project is proceeding well and we can show you a textured pyramid at last (as usual I have to thank Arc for the huge help ;) )! :)

I’ve left my normal mapping experiments behind for a moment (after having discovered how to create correct object space normal maps in Blender with the “six colored lights” hack :D ), and I’m now working on the lighting system which will represent the base for every non trivial texturing technique.

Much more is yet to come, stay tuned!