Domanda

Sto realizzando alcune forme abbastanza basilari in OpenGL-ES in base al codice di esempio di Apple. Hanno usato una serie di punti, con una serie di indici nel primo array e ogni set di tre indici crea un poligono. È tutto fantastico, posso creare le forme che voglio. Per ombreggiare correttamente le forme credo di dover calcolare le normali per ogni vertice su ciascun poligono. Inizialmente le forme erano cuboidali, quindi era molto facile, ma ora sto preparando (leggermente) forme più avanzate che voglio creare automaticamente quelle normali. Sembra abbastanza facile se ricevo vettori per due bordi di un poligono (tutti i polys sono triangoli qui) e uso il loro prodotto incrociato per ogni vertice su quel poligono. Dopo di che uso il codice come sotto per disegnare la forma.

glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, triangleVertices);

glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, 0, triangleColours);

glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 0, triangleNormals);

glDrawArrays(GL_TRIANGLES, 0, 48);

glDisableVertexAttribArray(GLKVertexAttribPosition);
glDisableVertexAttribArray(GLKVertexAttribColor);
glDisableVertexAttribArray(GLKVertexAttribNormal);

Quello che ho problemi a capire è il motivo per cui devo farlo manualmente. Sono sicuro che ci sono casi in cui vorresti qualcosa di diverso da un semplice perpendicolare in superficie, ma sono anche sicuro che questo è di gran lunga il caso d'uso più popolare, quindi non dovrebbe esserci un modo più semplice? Mi sono perso qualcosa di ovvio? glcalculateNormals () sarebbe fantastico.

// ed ecco un passaggio di risposta in un Glkvector3 [] che desideri essere riempito con i tuoi normali, un altro con i vertici (ciascuno tre sono raggruppati in poligoni) e quindi il conteggio dei vertici.

- (void) calculateSurfaceNormals: (GLKVector3 *) normals forVertices: (GLKVector3 *)incomingVertices count:(int) numOfVertices
{

    for(int i = 0; i < numOfVertices; i+=3)
    {
        GLKVector3 vector1 = GLKVector3Subtract(incomingVertices[i+1],incomingVertices[i]);
        GLKVector3 vector2 = GLKVector3Subtract(incomingVertices[i+2],incomingVertices[i]);        
        GLKVector3 normal = GLKVector3Normalize(GLKVector3CrossProduct(vector1, vector2));
        normals[i] = normal;
        normals[i+1] = normal;
        normals[i+2] = normal;
    }
}
È stato utile?

Soluzione

E ancora la risposta è: OpenGL non è né una libreria di gestione della scena né una libreria di geometria, ma solo un'API di disegno Questo disegna belle foto sullo schermo. Per l'illuminazione ha bisogno di normali e le dai normali. È tutto. Perché dovrebbe calcolare le normali se questo può essere fatto dall'utente e non ha nulla a che fare con il disegno effettivo?

Spesso non li calcola comunque in fase di esecuzione, ma caricali da un file. E ci sono molti modi per calcolare le normali. Vuoi normali per facciate o normali per verteci? Hai bisogno di bordi duri specifici o patch fluidi specifici? Se vuoi essere in media rivolgersi alle normali per ottenere le normali del vertice, come si desidera in media?

E con l'avvento degli shader e la rimozione degli attributi normali incorporati e dei calcoli di illuminazione nelle versioni più recenti, tutta questa domanda diventa comunque obsoleta in quanto puoi fare l'illuminazione in ogni modo che desideri e non hai più bisogno di normali tradizionali.

A proposito, sembra che al momento stai usando le normali per faccia, il che significa che ogni vertice di una faccia ha la stessa normalità. Questo crea un modello molto sfaccettato con bordi duri e inoltre non funziona molto bene insieme agli indici. Se vuoi un modello liscio (non lo so, forse vuoi davvero un aspetto sfaccettato), dovresti in media le normali del viso delle facce adiacenti per ogni vertice per calcolare le normali per verteci. Sarebbe in realtà il caso d'uso più abituale e non normali per faccia.

Quindi puoi fare qualcosa di simile a questo pseudo-code:

for each vertex normal:
    intialize to zero vector

for each face:
    compute face normal using cross product
    add face normal to each vertex normal of this face

for each vertex normal:
    normalize

Per generare normali lisce per-vertex. Anche nel codice reale questo dovrebbe comportare qualcosa tra 10 e 20 righe di codice, che non è davvero complesso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top