2012-04-11 4 views
8

Alle Tutorials, die ich gesehen habe, verwenden immer ein einzelnes Objekt, wie ein Dreieck oder einen Würfel. Aber mir ist nicht klar, wie ich einzelne Objekte unabhängig voneinander manipulieren kann. Ich habe einige Tutorials gesehen, die sich auf die feste Funktionspipeline beziehen und Pushmatrix und Popmatrix verwenden, aber mit der programmierbaren Pipeline sind diese Funktionen weg. Unten sind eine Init-Funktion und eine Zeichenfunktion, die ein einzelnes Dreieck auf dem Bildschirm zeichnen und es um die Z-Achse drehen. Kann jemand mir den Code zeigen, oder sogar Pseudocode, um ein zweites Dreieck hinzuzufügen und es unabhängig von dem anderen Dreieck zu drehen? Sprich um eine andere Achse oder in die entgegengesetzte Richtung?Objekte in OpenGL ES 2.0 unabhängig transformieren

Hier sind sie:

int Init(ESContext* esContext) 
{ 
    UserData* userData = (UserData *)esContext->userData; 
    const char *vShaderStr = 
     "attribute vec4 vPosition; \n" 
     "uniform mat4 MVPMatrix;" 
     "void main()    \n" 
     "{       \n" 
     " gl_Position = MVPMatrix * vPosition;\n" 
     "}       \n"; 

    const char *fShaderStr = 
     "precision mediump float; \n" 
     "void main()    \n" 
     "{       \n" 
     " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n" 
     "}       \n"; 

    GLuint vertexShader; 
    GLuint fragmentShader; 
    GLuint programObject; 
    GLint linked; 
    GLfloat ratio = 320.0f/240.0f; 

    vertexShader = LoadShader(GL_VERTEX_SHADER, vShaderStr); 
    fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fShaderStr); 

    programObject = glCreateProgram(); 

    if (programObject == 0) 
     return 0; 

    glAttachShader(programObject, vertexShader); 
    glAttachShader(programObject, fragmentShader); 

    glBindAttribLocation(programObject, 0, "vPosition"); 
    glLinkProgram(programObject); 
    glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &linked); 

    if (!linked) 
    { 
     GLint infoLen = 0; 
     glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen); 

     if (infoLen > 1) 
     { 
      char* infoLog = (char *)malloc(sizeof(char) * infoLen); 
      glGetProgramInfoLog(programObject, infoLen, NULL, infoLog); 

      free(infoLog); 
     } 

     glDeleteProgram(programObject); 
     return FALSE; 
    } 

    userData->programObject = programObject; 

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 

    glViewport(0, 0, esContext->width, esContext->height); 
    glClear(GL_COLOR_BUFFER_BIT); 


    glUseProgram(userData->programObject); 

    userData->angle = 0.0f; 
    userData->start = time(NULL); 
    userData->ProjMatrix = PVRTMat4::Perspective(ratio*2.0f, 2.0f, 3.0f, 7.0f, PVRTMat4::eClipspace::OGL, false, false); 
    userData->ViewMatrix = PVRTMat4::LookAtLH(PVRTVec3(0.0f, 0.0f, -3.0f), PVRTVec3(0.0f, 0.0f, 0.0f), PVRTVec3(0.0f, 1.0f, 0.0f)); 
    return TRUE; 
} 



void Draw(ESContext *esContext) 
{ 
    GLfloat vVertices[] = {0.0f, 0.5f, 0.0f, 
          -0.5f, -0.5f, 0.0f, 
          0.5f, -0.5f, 0.0f}; 

    GLint MVPHandle; 
    double timelapse; 

    PVRTMat4 MVPMatrix = PVRTMat4::Identity(); 
    UserData* userData = (UserData *)esContext->userData; 

    timelapse = difftime(time(NULL), userData->start) * 1000; 
    if(timelapse > 16.0f) //Maintain approx 60FPS 
    { 
     if (userData->angle > 360.0f) 
     { 
      userData->angle = 0.0f; 
     } 
     else 
     { 
      userData->angle += 0.1f; 
     } 
    } 

    userData->ModelMatrix = PVRTMat4::RotationZ(userData->angle); 

    MVPMatrix = userData->ViewMatrix * userData->ModelMatrix; 
    MVPMatrix = userData->ProjMatrix * MVPMatrix; 

    MVPHandle = glGetUniformLocation(userData->programObject, "MVPMatrix"); 
    glUniformMatrix4fv(MVPHandle, 1, FALSE, MVPMatrix.ptr()); 

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices); 
    glEnableVertexAttribArray(0); 

    glClear(GL_COLOR_BUFFER_BIT); 
    glDrawArrays(GL_TRIANGLES, 0, 3); 
    eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface); 
} 

Antwort

6

Nachdem das erste Dreieck zeichnen, eine neue MVP-Matrix mit dem neuen gewünschten Dreh/Position erzeugen, laden, und dann dem Dreieck ein zweites Mal ziehen. Sie können Uniformen während der Szene beliebig oft wechseln.

Dies ist vergleichbar mit dem, was Push und Pop tun, sie ändern nur die aktive Matrix vor dem Zeichnen eines bestimmten Objekts.

Beispiel Pseudo-Code:

MMatrix = identity; 
MVPMatrix = VPMatrix * MMatrix; 
glUniformMatrix4fv(MVPHandle, 1, FALSE, MVPMatrix.ptr()); 
glDrawArrays(GL_TRIANGLES, 0, 3); //draw triangle at 0,0,0 

MMatrix.translate(1,0,0); 
MVPMatrix = VPMatrix * MMatrix; 
glUniformMatrix4fv(MVPHandle, 1, FALSE, MVPMatrix.ptr()); 
glDrawArrays(GL_TRIANGLES, 0, 3); //draw triangle at 1,0,0 

MMatrix.translate(1,0,0); 
MVPMatrix = VPMatrix * MMatrix; 
glUniformMatrix4fv(MVPHandle, 1, FALSE, MVPMatrix.ptr()); 
glDrawArrays(GL_TRIANGLES, 0, 3); //draw triangle at 2,0,0 

..repeat for as many objects as you want.. 

Dies werden Sie mit drei Dreiecken verlassen, bei (0,0,0), (1,0,0) und (2,0,0).

+0

Können Sie ein bisschen expliziter sein? Wenn ich den Wert der uniformen MVPMatrix einfach so ändere, dass sie eine Übersetzung enthält, wie kann sie dann eine Kopie des Dreiecks an der neuen Position zeichnen und nicht einfach das bestehende Dreieck an diesen Ort verschieben? – Legion

+1

Sobald Sie ein Dreieck über glDrawArrays versenden, ist es fertig. Keine weiteren Änderungen an irgendwelchen Variablen haben einen Einfluss darauf. Sobald etwas gerendert wurde, kann es nicht mehr verschoben werden. Änderungen an Uniformen wirken sich nur auf Zeichnungsaufrufe nach der Änderung aus. Ich habe einen kleinen Beispielcode in meine Antwort eingefügt, um Ihnen das Verständnis zu erleichtern. – Tim

+0

@Legion aktualisiert mit neuem Kommentar und Erklärung – Tim