We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I wonder why the vertexes for shapes that was drawn direct on the sketch instead of creating an PShape, sends other vertexes to the shader then the one that was drawn on a PShape. For example, when I change the per pixel lightning example from http://www.processing.org/tutorials/pshader/ and change the the filter:
void main() {
gl_Position = transform * vertex;
vec3 ecVertex = vec3(modelview * vertex);
ecNormal = normalize(normalMatrix * normal);
lightDir = normalize(lightPosition.xyz - ecVertex);
vertColor = sin(vertex);
}
so the color is generated by the position. This works as expected. But when I change the sketch so it draws the can in every draw call like this:
void createCan(float r, float h, int detail) {
beginShape(QUAD_STRIP);
noStroke();
for (int i = 0; i <= detail; i++) {
float angle = TWO_PI / detail;
float x = sin(i * angle);
float z = cos(i * angle);
float u = float(i) / detail;
vertex(x * r, -h/2, z * r, u, 0);
vertex(x * r, +h/2, z * r, u, 1);
}
endShape();
}
the colors start to flicker and change in every loop step. Can someone explain this?
Answers
Hi, before going into the flickering issue, I'd suggest to add to the immediate mode code the normal(x, 0, z) call, otherwise the renderer will auto-compute the normals per each triangle, which won't give accurate lighting results for a cylinder.
About the flickering: this is a bit tricky but not the result of a bug... it is in fact due to the way the renderer optimizes geometry buffers in the immediate mode. In order to pack as much geometry in a single VBO as possible, the geometry transformations are applied on the CPU side before copying the VBO to the video memory, and so the transform matrix (more specifically the modelview component) only contains the camera transformations (but none of the rotation and translation components you apply in the draw function). When drawing a PShape, the vertex coordinates are sent to the GPU as they are fed through the Processing API.
This optimization is disabled when you need to draw strokes in 3D so they look correct when you stack flat geometry, by using hint(DISABLE_OPTIMIZED_STROKE), so that a side effect of this hint is that the flickering in your code goes away. All of this is a bit tricky, and a consequence of the all the things going on behind the scenes to make rendering fast, maybe this sketch helps understanding the different settings (same shader code as you posted):
Thanks for the explanation.
This was tricky indeed!
I just gave a workshop on shaders and left scratching my head about why creating shader patterns that only depend on vertex positions are not anchored to the object, but rotate in strange ways if the object rotates.
It is solved with
hint(DISABLE_OPTIMIZED_STROKE);
Here you can see a working example online.
Here the program that fails to work properly without the hint:
Vertex
Fragment