2012-06-13 9 views
7

Tengo un programa que genera un mapa de alturas y luego lo muestra como una malla con OpenGL. Cuando trato de agregar iluminación, termina con formas cuadradas extrañas que cubren la malla. Son más notables en algunas áreas que en otras, pero siempre están ahí.Extraños artefactos de iluminación cuadrada en OpenGL

Estaba usando una malla cuádruple, pero nada cambió después de cambiar a una malla triangular. He utilizado al menos tres métodos diferentes para calcular las normales de los vértices, todos con el mismo efecto. Estaba haciendo la iluminación manualmente con sombreadores, pero nada cambia cuando se usa el sistema de iluminación OpenGL incorporado.

Mi último código de generación de la normalidad (se enfrenta a una gran variedad de índices en verts, el conjunto de vértices):

int i; 
for (i = 0; i < NINDEX; i += 3) { 
    vec v[3]; 
    v[0] = verts[faces[i + 0]]; 
    v[1] = verts[faces[i + 1]]; 
    v[2] = verts[faces[i + 2]]; 

    vec v1 = vec_sub(v[1], v[0]); 
    vec v2 = vec_sub(v[2], v[0]); 

    vec n = vec_norm(vec_cross(v2, v1)); 

    norms[faces[i + 0]] = vec_add(norms[faces[i + 0]], n); 
    norms[faces[i + 1]] = vec_add(norms[faces[i + 1]], n); 
    norms[faces[i + 2]] = vec_add(norms[faces[i + 2]], n); 
} 

for (i = 0; i < NVERTS; i++) { 
    norms[i] = vec_norm(norms[i]); 
} 

A pesar de que no es el único código que he usado, así que dudo que es la causa del problema

trazo la malla con:

y no estoy usando actualmente cualquiera shaders.

¿Qué podría estar causando esto?

EDIT: Un conjunto más amplio de las capturas:

Para el último, el código de sombreado es

Vertex:

varying vec3 lightvec, normal; 

void main() { 
    vec3 lightpos = vec3(0, 0, 100); 
    vec3 v = vec3(gl_ModelViewMatrix * gl_Vertex); 
    normal = gl_NormalMatrix * gl_Normal; 

    lightvec = normalize(lightpos - v); 

    gl_Position = ftransform(); 
} 

Fragmento:

varying vec3 lightvec, normal; 

void main(void) { 
    float l = dot(lightvec, normal); 
    gl_FragColor = vec4(l, l, l, 1); 
} 
+0

¿Podría publicar dos capturas de pantalla de la misma escena, una con una estructura alámbrica y otra sin ella? –

+0

¿'Normas' inicializa cero? Estás acumulando tus vectores en él sin ponerlo en cero primero, aunque si se pone a cero en otro lugar del programa, eso no debería ser un problema. – genpfault

+0

¿está utilizando una interpolación uniforme para atributos normales en el sombreado? Quizás cambiar a 'plano 'por un momento podría ayudar a localizar el problema. Además, la iluminación OpenGL tiende a ser muy defectuosa para mí; por lo general, estoy más seguro del código que me escribí. –

Respuesta

1

que no tienen una respuesta definitiva para las versiones que no son de sombreado, pero quería añadir que si estás haciendo iluminación por píxel en su sombreador de fragmentos, probablemente debería estar normalizando el brillo normal y el brillo dentro del sombreador de fragmentos.

Si no lo haces, no tienen longitud unitaria (una interpolación lineal entre dos vectores normalizados no está necesariamente normalizada). Esto podría explicar algunos de los artefactos que se ven en la versión de sombreado, ya que la magnitud del producto de punto podría variar en función de la distancia de los vértices, que se parece a lo que está viendo.

EDITAR: Otra idea, ¿está haciendo una escala no uniforme (diferentes x, y, z) de la malla al representar la versión sin sombreado? Si lo escala, entonces necesita modificar las normales por el factor de escala inverso o establecer glEnable(GL_NORMALIZE).Ve aquí para más: http://www.lighthouse3d.com/tutorials/glsl-tutorial/normalization-issues/

2

Es necesario ya sea normalizar la normal en el fragment shader, así:

varying vec3 lightvec, normal; 

void main(void) { 
    vec3 normalNormed = normalize(normal); 
    float l = dot(lightvec, normalNormed); 
    gl_FragColor = vec4(l, l, l, 1); 
} 

Esto puede ser caro. Lo que también funcionará en este caso, con luces direccionales, es usar iluminación de vértice. Así calcular el valor de la luz en el vertex shader

varying float lightItensity; 

void main() { 
    vec3 lightpos = vec3(0, 0, 100); 
    vec3 v = vec3(gl_ModelViewMatrix * gl_Vertex); 
    normal = gl_NormalMatrix * gl_Normal; 

    lightvec = normalize(lightpos - v); 

    lightItensity = dot(normal, lightvec); 

    gl_Position = ftransform(); 
} 

y utilizarlo en el fragment shader,

varying float light; 

void main(void) { 
    float l = light; 
    gl_FragColor = vec4(l, l, l, 1); 
} 

espero que esto lo arregla, que me haga saber si no lo hace.

EDIT: Aquí está un pequeño diagrama que explica lo que es más probable que ocurra

enter image description here

Edit2:

Si eso no ayuda, añadir más triángulos. Interpola los valores de tu heightmap y agrega algunos vértices en el medio.

Alternativamente, intente cambiar su esquema de tesselación. Por ejemplo, una malla de triángulos equiláteros como esta podría hacer que los artefactos sean menos prominentes.

enter image description here

Vas a tener que hacer un poco de interpolación en el mapa de altura.

De lo contrario, no tengo ni idea ... ¡Buena suerte!

+0

Gracias, pero desafortunadamente ya he intentado hacer algo como esto. Estoy comenzando a preguntarme si el problema está en mi tarjeta gráfica (un chip integrado Intel de 1.5 años). – sigill

+0

Lo dudo mucho. El código Shader debería ejecutarse de la misma manera en cualquier tarjeta gráfica que lo admita. – Hannesh

Cuestiones relacionadas