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


He estado aprendiendo OpenGL durante las últimas semanas y me he encontrado con algunos problemas para implementar un sombreador Phong. Parece no hacer interpolación entre vértices a pesar de mi uso del calificador smooth. Me estoy perdiendo algo aquí? Para dar crédito donde se debe, el código para los sombreadores de vértices y fragmentos se extrae en gran medida de la OpenGL SuperBible Quinta Edición. Recomiendo encarecidamente este libro!

Sombreador de vértices:

#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 estoy obteniendo y lo que estoy buscando getting Estoy obteniendo 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

Resulta que el problema era con mi geometría; Kos tenía razón. Para cualquier otra persona que está teniendo este problema con los modelos de Blender, Kos señaló que hacer Edit->Faces->Set Smooth hace el truco. Descubrí que Wings 3D funcionó " fuera de la caja."

Author: Jonba, 2011-01-16

2 answers

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

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

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

Si es así, la pregunta sigue siendo: ¿Por qué? El sombreador de vértices se ve bien.

Así que tal vez ¿hay algo mal en tu geometría ? ¿Cuáles son los datos que envía al sombreador? ¿Está seguro de haber calculado correctamente las normales por vértice, no solo las normales por cara?

normal

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

Si tus datos se parecen a la imagen de arriba, incluso con un sombreado correcto obtendrás un sombreado plano. Asegúrese de que tiene normales por vértice correctos como en la parte inferior imagen. (Son realmente simples de calcular para una esfera.)

 48
Author: Kos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-16 14:00:38

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

Pero primero, una foto de una cabeza de conejo gigante de nuestro amigo el conejo de Stanford como un ejemplo del resultado !

normales para el conejo de Stanford

Advertencia importante: tenga en cuenta que me salgo con la transformación de las normales con la matriz modelview en lugar de un matriz normal adecuada. Esto no funcionará correctamente si su modelview contiene escala no uniforme. Además, la longitud de sus normales no será correcta, pero eso importa poco si solo desea verificar su dirección.

Sombreador de vértices:

#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();
    }
}

Sombreador de fragmentos:

#version 330

in Data
{
    vec4 color;
} gdata;

out vec4 outputColor;

void main()
{
    outputColor = gdata.color;
}
 64
Author: Nicolas Lefebvre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-28 14:18:34