Frage

Hallo ich 3D-Modellierung app schreibe und ich möchte in OpenGL beschleunigen Rendering. Derzeit verwende ich glBegin / glEnd, die wirklich Art und Weise langsam und veraltet ist. Ich brauche sehr schnell flach schattierten Modellen zu zeichnen. Ich erzeugen Normalen auf CPU jeden einzelnen Frame. Dies ist sehr langsam. Ich habe versucht, glDrawElements mit indexierten Geometrie zu verwenden, aber es gibt Probleme in normalen Generation, weil Normalen an Vertex spezifiziert sind nicht auf Dreieck Ebene.
Eine weitere Idee war GLSL zu verwenden Normale auf GPU in der Geometrie-Shader zu erzeugen. Ich diesen Code geschrieben für normale Generation:

#version 120 
#extension GL_EXT_geometry_shader4 : enable

vec3 NormalFromTriangleVertices(vec3 triangleVertices[3])
{
    // now is same as RedBook (OpenGL Programming Guide)
    vec3 u = triangleVertices[0] - triangleVertices[1];
    vec3 v = triangleVertices[1] - triangleVertices[2];
    return cross(v, u);
}

void main()
{
    // no change of position
    // computes normal from input triangle and front color for that triangle

    vec3 triangleVertices[3];
    vec3 computedNormal;

    vec3 normal, lightDir;
    vec4 diffuse;
    float NdotL;

    vec4 finalColor;

    for(int i = 0; i < gl_VerticesIn; i += 3)
    {
        for (int j = 0; j < 3; j++)
        {
            triangleVertices[j] = gl_PositionIn[i + j].xyz;
        }
        computedNormal = NormalFromTriangleVertices(triangleVertices);
        normal = normalize(gl_NormalMatrix * computedNormal);

        // hardcoded light direction 
        vec4 light = gl_ModelViewMatrix * vec4(0.0, 0.0, 1.0, 0.0);
        lightDir = normalize(light.xyz);

        NdotL = max(dot(normal, lightDir), 0.0);

        // hardcoded
        diffuse = vec4(0.5, 0.5, 0.9, 1.0);

        finalColor = NdotL * diffuse; 
        finalColor.a = 1.0; // final color ignores everything, except lighting

        for (int j = 0; j < 3; j++)
        { 
            gl_FrontColor = finalColor;
            gl_Position = gl_PositionIn[i + j];
            EmitVertex();
        }
    }
    EndPrimitive();
}

Als ich Shadern meine Anwendung integriert, trat keine Verbesserung der Geschwindigkeit. Es war schlimmer als zuvor. Ich bin Neuling in GLSL und Shadern Gesamt damit ich weiß nicht, was ich falsch gemacht. Ich habe versucht, diesen Code auf MacBook mit Geforce 9400M.

mehr klar zu sein, ist dieser Code, den ich ersetzen will:

- (void)drawAsCommandsWithScale:(Vector3D)scale
{
    float frontDiffuse[4] = { 0.4, 0.4, 0.4, 1 };
    CGFloat components[4];
    [color getComponents:components];
    float backDiffuse[4];
    float selectedDiffuse[4] = { 1.0f, 0.0f, 0.0f, 1 };

    for (uint i = 0; i < 4; i++)
        backDiffuse[i] = components[i];

    glMaterialfv(GL_BACK, GL_DIFFUSE, backDiffuse);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, frontDiffuse);

    Vector3D triangleVertices[3];

    float *lastDiffuse = frontDiffuse; 

    BOOL flip = scale.x < 0.0f || scale.y < 0.0f || scale.z < 0.0f;

    glBegin(GL_TRIANGLES);

    for (uint i = 0; i < triangles->size(); i++)
    {
        if (selectionMode == MeshSelectionModeTriangles) 
        {
            if (selected->at(i))
            {
                if (lastDiffuse == frontDiffuse)
                {
                    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, selectedDiffuse);
                    lastDiffuse = selectedDiffuse;
                }
            }
            else if (lastDiffuse == selectedDiffuse)
            {
                glMaterialfv(GL_BACK, GL_DIFFUSE, backDiffuse);
                glMaterialfv(GL_FRONT, GL_DIFFUSE, frontDiffuse);
                lastDiffuse = frontDiffuse;
            }
        }    
        Triangle currentTriangle = [self triangleAtIndex:i];
        if (flip)
            currentTriangle = FlipTriangle(currentTriangle);

        [self getTriangleVertices:triangleVertices fromTriangle:currentTriangle];
        for (uint j = 0; j < 3; j++)
        {
            for (uint k = 0; k < 3; k++)
            {
                triangleVertices[j][k] *= scale[k];
            }
        }
        Vector3D n = NormalFromTriangleVertices(triangleVertices);
        n.Normalize();
        for (uint j = 0; j < 3; j++)
        {
            glNormal3f(n.x, n.y, n.z);
            glVertex3f(triangleVertices[j].x, triangleVertices[j].y, triangleVertices[j].z);            
        }
    }

    glEnd();    
}

Wie Sie sehen können, ist es sehr ineffizient, aber working.triangles ist Array von Indizes in vertices Array.

Ich habe versucht, diesen Code zu verwenden, um zu zeichnen, aber ich kann nicht nur ein Indexfeld nicht zwei (eine für Ecken und zweite für Normalen) haben.

glEnableClientState(GL_VERTEX_ARRAY);

uint *trianglePtr = (uint *)(&(*triangles)[0]); 
float *vertexPtr = (float *)(&(*vertices)[0]);

glVertexPointer(3, GL_FLOAT, 0, vertexPtr);
glDrawElements(GL_TRIANGLES, triangles->size() * 3, GL_UNSIGNED_INT, trianglePtr);
glDisableClientState(GL_VERTEX_ARRAY);

Nun, wie kann ich Zeiger auf Normalen angeben, wenn einige Ecken von verschiedenen Dreiecken geteilt werden, so unterschiedlich Normalen für sie?

War es hilfreich?

Lösung

Also habe ich es endlich geschafft, Rendering-Geschwindigkeit zu erhöhen. Ich neu berechnen Normalen auf CPU, nur dann, wenn Ecken oder Dreiecken Änderungen, die nur dann auftreten, wenn in einem Netz nicht in ganzer Szene arbeiten. Es ist nicht Lösung, dass ich aber in der realen Welt wollte es besser als bisherige Ansätze.
I-Cache ganz Geometrie in separate normal und Vertex-Array kann indizierte Zeichnung nicht verwendet werden, weil ich Schattierung (Gruppen in 3ds max zu glätten ähnliches Problem) will.
Ich benutze einfach glDrawArrays und Vertex-Shader für die Beleuchtung, die, weil ich in Dreieck-Modus unterschiedliche Farbe für ausgewählte Dreieck und ein anderer für nicht ausgewählte wollen, und es gibt keine Reihe von Materialien (ich habe gefunden keine eins).

Andere Tipps

Sie würden nicht in der Regel den Normalen jeden Rahmen berechnen, nur dann, wenn die Geometrie ändern. Und hat ein normales pro Dreieck nur den gleichen Normalsatz für jeden Scheitelpunkt im Dreieck. Das bedeutet man kann nicht eckenverknüpft zwischen benachbarten Dreiecken in Ihrer Masche aber das ist überhaupt in dieser Art der Sache nicht ungewöhnlich.

Ihre Frage macht mich daran erinnern Normals ohne Normals Blog-Post.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top