Geometry shaders part 2

In this part we will be doing a bit of simple geometry instancing with a minecraft twist, basically what we are going to do is first generate a volumetric landscape of sorts, then render it using cubes, but not the usual way, we are going to do it as a particle system, which is i guess a little bit more than usual as it involves other stuff than strictly openGL, and since there are a few things i want to try out in this field you will be seeing more of it.
This tutorial assumes that you have all the stuff needed for part 1 and in addition texturing available.
So first we need our volumetric function
[stextbox id=”grey”]

bool volume_evaluator(float x, float y, float z)
{
float acc=1.0,tmp=0;

//get some perlin noise
tmp+=noise3((x*8.04*scale),(z*8.04*scale),y*8.04)*12.5;
tmp+=noise3((x*4.07*scale),(z*4.07*scale),y*4.07)*25;
tmp+=noise3((x*1.91*scale),(z*1.91*scale),y*1.91)*50;
tmp+=noise3((x*1.01*scale),(z*1.01*scale),y*1.01)*100;
tmp*=0.1;
acc+=tmp;

tmp=-((y-2)/2);//now a grad
acc+=tmp;

if (acc<0.5) return true;
else return false;
}

[/stextbox]
The way this works is simple, first it uses the noise3 function, which is just plain and simple perlin noise which you can find just by googling “perlin noise”, here i combine several octaves to create a more interesting  landscape, In the game Minecraft they use interpolation as well to achieve smoother hills and flatter areas along with a host of other interesting/secret methods to make it nicer, though the basic principle still applies.
The line tmp=-((y-2)/2); produces a density gradient that makes it less dense from y=2 and up and more dense under it, or simply put it creates land instead of floating islands.
Finally the function returns if there is land at a the coordinates or not.

Next up is a function that hides unseen cubes, essentially it just checks if there are cubes all around it, if so it deletes it, it’s a way for us to render less with the same visual result.
[stextbox id=”grey”]

bool volume(float x, float y, float z)
{

 if(!volume_evaluator(x,y,z)) return false;

 int i=0;
 if(volume_evaluator(x+1,y,z)) i++;
 if(volume_evaluator(x-1,y,z)) i++;
 if(volume_evaluator(x,y+1,z)) i++;
 if(volume_evaluator(x,y-1,z)) i++;
 if(volume_evaluator(x,y,z+1)) i++;
 if(volume_evaluator(x,y,z-1)) i++;
 if(i==6) return false;
 else return true;
}

[/stextbox]
the final function we need to add is just a function that scans trough a block of cubes and then feeds the resulting particle array in a VBO, you can download and check the code on exactly how this is done but it’s just a bunch of loops basically.

Next we need to move on to the shaders, i wont show either the fragment or vertex shader as their simple enough, and really the only addition is texturing for the fragment shader so i am only going to show the geometry shader, and really it’s the one you came from
[stextbox id=”grey”]

#version 150

layout(points) in;
layout(triangle_strip , max_vertices=32) out;

in vec4 pos[];
uniform mat4 projMat;
out vec4 posx;
out vec2 tc;

[/stextbox]
the first bit defines all the inputs and outputs, nothing to exiting but note how it’s easy it is to define your geometry inputs and outputs, here we only use tri-strips and frankly it’s really the only thing you would need as you can make quads triangles and strips with it at the same time, interestingly enough it’s also the only thing you can make along with points and line-strips, so if you need to output individual triangles, quads or lines then just call EndPrimitive for each segment and it just works.
[stextbox id=”grey”]

void main( void ) {

posx=pos[0].xyzw;

//left
tc=vec2(1.0,0.0);
gl_Position = projMat*(pos[0].xyzw+vec4(0.5,-0.5,0.5,0.0));
EmitVertex();
tc=vec2(01.0,1.0);
gl_Position = projMat*(pos[0].xyzw+vec4(0.5,0.5,0.5,0.0));
EmitVertex();
tc=vec2(0.0,0.0);
gl_Position = projMat*(pos[0].xyzw+vec4(-0.5,-0.5,0.5,0.0));
EmitVertex();
tc=vec2(0.0,1.0);
gl_Position = projMat*(pos[0].xyzw+vec4(-0.5,0.5,0.5,0.0));
EmitVertex();
EndPrimitive();

[/stextbox]
this is the first face of six, again download and check the code to see the whole thing, because we are doing some texturing we need to transfer texture coordinates, we also need to do the matrix transformation here instead of the vertex shader as before, the way all this works is that all out variables defined previously gets the last values set for it feed to the rasteriser, not totally unlike the now deprecated glBegin/glEnd paradigm.
The result is this if all is done correctly, now remember all these cubes are just particles, but if you’re really clever you could use this method to do simple instancing of simple debris, dust, leaves by just rendering a simple particle system and using the geometry shader to enhance that.
Koch curves and other fun stuff are next.

Generating cubes from a particle system

Generating cubes from a particle system

 

 

 

 

 

 

 

 

Download the source for MS Visual C++ 6 here
Download the source for MS Visual C++ 2008 here

Part 1 | Part 3


No Comments

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment


WordPress Themes