Instancing
This tutorial requires a GF8.
As first create a Node with script, vertex and fragment shader and a buffer.
Node = World.addNode();
Node.addScript();
Node.addVertexShader();
Node.addFragmentShader();
Node.addBuffer();
Then create a Sphere mesh (Test Objects in Nodes context menu) and write some code:
Script:
shader = gl.Shader(Vertexshader,Fragmentshader);
function render(){
shader.Bind();
Sphere.Vertex.Bind();
Sphere.Normal.Bind();
Sphere.Index.DrawInstanced(1);
shader.Unbind();
}
Vertexshader:
varying vec3 N;
void main (void){
gl_Position = gl_ModelViewProjectionMatrix *gl_Vertex;
N = gl_NormalMatrix * gl_Normal;
}
Fragmentshader:
varying vec3 N;
void main (void){
float light = max(0.0,dot(normalize(N), vec3(0.0, 0.0, 1.0)));
gl_FragColor = vec4(1.0, 0.0, 0.0, 0.0) * light;
}
This will draw a single instance of a red sphere. Except for "DrawInstanced(1)"
instead "Draw()" there is no difference to previous rendering scripts. Now the number of
instances have to set to 10 and modify the vertex shader:
#extension GL_EXT_gpu_shader4 : enable
varying vec3 N;
void main (void){
vec4 vert = gl_Vertex + vec4(0.0, 1.0, 0.0, 0.0) * gl_InstanceID;
gl_Position = gl_ModelViewProjectionMatrix * vert;
N = gl_NormalMatrix * gl_Normal;
}
Now a line of spheres should be rendered.
For a more usefully version the "gl_InstanceID" should be used to index a uniform array,
that holds the positions or matrices. As next the buffer should be formated and filled
with data (paste the code to the console):
Node.Buffer.setDim(3, 100, 1, gl.FLOAT);
for ( i = 0; i < 100 ; i++){
Node.Buffer.set(i , Math.random()*10 - 5, Math.random()*10 - 5, Math.random()*10 -
5);
}
A small modification for the vertex shader:
#extension GL_EXT_gpu_shader4 : enable
uniform vec3 pos[100];
varying vec3 N;
void main (void){
vec4 vert = gl_Vertex + vec4(pos[gl_InstanceID], 0.0);
gl_Position = gl_ModelViewProjectionMatrix * vert;
N = gl_NormalMatrix * gl_Normal;
}
and a new line for the script:
shader = gl.Shader(Vertexshader,Fragmentshader);
function render(){
shader.Bind();
gl.Translate(0.0, 0.0, -5.0);
Buffer.Uniform(shader,"pos");
Sphere.Vertex.Bind();
Sphere.Normal.Bind();
Sphere.Index.DrawInstanced(100);
shader.Unbind();
}
|