opengl glsl shader pyopengl

¿Por qué mi sombreador OpenGL Phong se comporta como un sombreador plano?



glsl shader (2)

Como una adición a esta respuesta, aquí hay un sombreador de geometría simple que te permitirá visualizar tus normales. Modifique el sombreado de vértices que lo acompaña según sea necesario según las ubicaciones de sus atributos y la forma en que envía sus matrices.

¡Pero primero, una imagen de una cabeza de conejito gigante de nuestro amigo el conejito de Stanford como un ejemplo del resultado!

Advertencia importante: tenga en cuenta que me salgo con la transformación de las normales con la matriz modelview en lugar de una matriz normal adecuada. Esto no funcionará correctamente si su vista de modelo contiene escalas no uniformes. Además, la longitud de tus normales no será correcta, pero eso importa poco si solo quieres verificar su dirección.

Vertex shader:

#version 330 layout(location = 0) in vec4 position; layout(location = 1) in vec4 normal; layout(location = 2) in mat4 mv; out Data { vec4 position; vec4 normal; vec4 color; mat4 mvp; } vdata; uniform mat4 projection; void main() { vdata.mvp = projection * mv; vdata.position = position; vdata.normal = normal; }

Sombreador de geometría:

#version 330 layout(triangles) in; layout(line_strip, max_vertices = 6) out; in Data { vec4 position; vec4 normal; vec4 color; mat4 mvp; } vdata[3]; out Data { vec4 color; } gdata; void main() { const vec4 green = vec4(0.0f, 1.0f, 0.0f, 1.0f); const vec4 blue = vec4(0.0f, 0.0f, 1.0f, 1.0f); for (int i = 0; i < 3; i++) { gl_Position = vdata[i].mvp * vdata[i].position; gdata.color = green; EmitVertex(); gl_Position = vdata[i].mvp * (vdata[i].position + vdata[i].normal); gdata.color = blue; EmitVertex(); EndPrimitive(); } }

Fragmento shader:

#version 330 in Data { vec4 color; } gdata; out vec4 outputColor; void main() { outputColor = gdata.color; }

He estado aprendiendo OpenGL durante las últimas semanas y me he encontrado con algunos problemas para implementar un sombreador Phong. Parece que no interpola entre vértices a pesar de mi uso del calificador smooth . ¿Me estoy perdiendo de algo? Para dar crédito donde se debe crédito, el código para los shaders de vértices y fragmentos se basa en gran medida en OpenGL SuperBible Fifth Edition. ¡Recomiendo mucho este libro!

Vertex Shader:

#version 330 in vec4 vVertex; in vec3 vNormal; uniform mat4 mvpMatrix; // mvp = ModelViewProjection uniform mat4 mvMatrix; // mv = ModelView uniform mat3 normalMatrix; uniform vec3 vLightPosition; smooth out vec3 vVaryingNormal; smooth out vec3 vVaryingLightDir; void main(void) { vVaryingNormal = normalMatrix * vNormal; vec4 vPosition4 = mvMatrix * vVertex; vec3 vPosition3 = vPosition4.xyz / vPosition4.w; vVaryingLightDir = normalize(vLightPosition - vPosition3); gl_Position = mvpMatrix * vVertex; }

Fragmento Shader:

#version 330 out vec4 vFragColor; uniform vec4 ambientColor; uniform vec4 diffuseColor; uniform vec4 specularColor; smooth in vec3 vVaryingNormal; smooth in vec3 vVaryingLightDir; void main(void) { float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir))); vFragColor = diff * diffuseColor; vFragColor += ambientColor; vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir),normalize(vVaryingNormal))); float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection)); if(diff != 0) { float fSpec = pow(spec, 32.0); vFragColor.rgb += vec3(fSpec, fSpec, fSpec); } }

Esta imagen (de dominio público) de Wikipedia muestra exactamente qué tipo de imagen obtengo y a qué me refiero: obtengo la imagen "plana" pero quiero la imagen "Phong".

Cualquier ayuda sería muy apreciada. ¡Gracias!

editar: si hace una diferencia, estoy usando PyOpenGL 3.0.1 y Python 2.6.

edit2:

Solución

Resultó que el problema estaba con mi geometría; Kos estaba en lo cierto. Para cualquier otra persona que tenga este problema con los modelos de Blender, Kos señaló que hacer Edit->Faces->Set Smooth hace el truco. Descubrí que Wings 3D funcionaba "de fábrica".


Hmm ... Estás interpolando lo normal como una varying variable, por lo que el sombreador de fragmentos debería recibir la normal por píxel correcta.

La única explicación (se me ocurre) del hecho de que estás obteniendo el resultado, como en tu imagen de la izquierda, es que cada fragmento de una cara dada finalmente recibe la misma normalidad . Puedes confirmarlo con un sombreador de fragmentos como:

void main() { vFragColor = normalize(vVaryingNormal); }

Si es el caso, la pregunta sigue siendo: ¿por qué? El sombreador de vértices se ve bien.

Entonces, ¿hay algo mal en tu geometría ? ¿Cuál es la información que envía al sombreador? ¿Estás seguro de que has calculado correctamente las normales por vértice, no solo las normales por cara?

Las líneas naranjas son normales en la cara diagonal, las líneas rojas son normales en la cara horizontal.

Si sus datos se parecen a la imagen de arriba, incluso con un sombreador correcto obtendrá sombreado plano. Asegúrese de tener las normales correctas por vértice como en la imagen inferior. (Son realmente simples de calcular para una esfera).