2012-06-13 11 views
7

Ich habe ein Programm, das eine Heightmap generiert und zeigt es dann als ein Netz mit OpenGL. Wenn ich versuche, Beleuchtung hinzuzufügen, endet es mit seltsamen quadratischen Formen, die das Netz abdecken. Sie sind in einigen Bereichen stärker als andere, sind aber immer da.Seltsame quadratische Beleuchtung Artefakte in OpenGL

Ich benutzte ein Quad-Mesh, aber nach dem Wechsel zu einem Dreiecksnetz änderte sich nichts. Ich habe mindestens drei verschiedene Methoden verwendet, um die Eckennormalen zu berechnen, alle mit demselben Effekt. Ich habe die Beleuchtung manuell mit Shadern gemacht, aber nichts ändert sich, wenn ich das integrierte OpenGL-Beleuchtungssystem verwende.

Mein letzter normale erzeugenden Code (Flächen ist ein Array von Indizes in verts, die Vertex-Array):

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]); 
} 

Obwohl das nicht der einzige Code, die ich verwendet habe, so dass ich bezweifle, dass es ist die Ursache des Problems.

Ich zeichne das Netz mit:

Und ich bin zur Zeit keine Shadern verwenden.

Was könnte das verursachen?

EDIT: Eine umfassende Reihe von Screenshots:

Für die letzte ist der Shader-Code

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

Fragment:

varying vec3 lightvec, normal; 

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

Könnten Sie zwei Screenshots derselben Szene posten, eine mit einem Drahtmodell und eine ohne? –

+0

Werden 'Normen' initialisiert? Sie sammeln Ihre Vektoren hinein, ohne sie vorher auf Null zu setzen. Wenn sie jedoch an einer anderen Stelle im Programm auf Null gesetzt werden, sollte das kein Problem sein. – genpfault

+0

verwenden Sie glatte Interpolation für normale Attribute im Shader? Vielleicht kann es ein bisschen "flat" werden, um das Problem zu lokalisieren. Auch OpenGL-Beleuchtung neigt dazu, für mich sehr fehlerhaft zu sein - ich bin normalerweise sicherer über den Code, den ich selbst geschrieben habe. –

Antwort

1

Ich habe keine definitive Antwort auf die Nicht-Shader-Versionen haben, aber ich wollte, dass hinzufügen, wenn Sie pro Pixel Beleuchtung tun in Ihr Fragment-Shader, sollten Sie wahrscheinlich normal und Lightvec innerhalb des Fragment-Shaders normalisieren.

Wenn Sie dies nicht tun, sind sie keine Einheitslänge (eine lineare Interpolation zwischen zwei normalisierten Vektoren ist nicht notwendigerweise normalisiert). Dies könnte einige der Artefakte erklären, die Sie in der Shader-Version sehen, da die Größe des Skalarprodukts als Funktion der Entfernung von den Scheitelpunkten variieren würde, welche Art wie das, was Sie sehen, aussieht.

EDIT: Ein weiterer Gedanke, machst du eine nicht-einheitliche Skalierung (verschiedene x, y, z) des Netzes beim Rendern der Nicht-Shader-Version? Wenn Sie es skalieren, müssen Sie entweder die Normalen mit dem inversen Skalierungsfaktor ändern oder glEnable(GL_NORMALIZE) festlegen.Sehen Sie hier für mehr: http://www.lighthouse3d.com/tutorials/glsl-tutorial/normalization-issues/

2

Sie müssen den normalen im Fragment Shader entweder normalisieren, etwa so:

varying vec3 lightvec, normal; 

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

Dies kann jedoch teuer sein. Was auch in diesem Fall mit gerichteten Lichtern funktioniert, ist die Verwendung von Scheitelpunktbeleuchtung. So berechnen Sie den Lichtwert in der 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(); 
} 

und verwenden Sie es in der Fragment-Shader,

varying float light; 

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

Ich hoffe, dies behebt es, lassen Sie mich wissen, wenn es nicht der Fall ist.

EDIT: Hier ist ein kleines Diagramm, das erklärt, was am ehesten geschieht, ist

enter image description here

EDIT2:

Wenn das nicht hilft, mehr Dreiecke hinzufügen. Interpolieren Sie die Werte Ihrer Höhenkarte und fügen Sie dazwischen einige Eckpunkte hinzu.

Alternativ können Sie Ihr Tesselationsschema ändern. Zum Beispiel könnte ein Gitter aus gleichseitigen Dreiecken die Artefakte weniger hervorheben.

enter image description here

Sie werden einige Interpolation auf Ihrem heightmap zu tun haben.

Ansonsten habe ich keine Ahnung .. Viel Glück!

+0

Danke, aber leider habe ich schon versucht, so etwas zu tun. Ich beginne mich zu fragen, ob das Problem in meiner Grafikkarte ist (1,5 Jahre alter integrierter Chip von Intel). – sigill

+0

Ich bezweifle es sehr. Der Shader-Code sollte auf allen Grafikkarten, die ihn unterstützen, genauso ausgeführt werden. – Hannesh

Verwandte Themen