OpenGL ES 2.0 (in particolare per l'iPhone) rendering è un po 'fuori. Ipotesi migliore è che è un problema matrice di proiezione

StackOverflow https://stackoverflow.com/questions/3886329

Domanda

Così ho comprato la programmazione Iphone 3D di O'Reilly e ho trovato quello che credo di essere un bug in là codice. Tuttavia non riesco a capire quale sia il problema, e se non lo faccio io non posso andare avanti con il mio codice.

I incollerà quello che io ritengo essere il codice appropriato in questo post, ma per fortuna tutto il codice è disponibile online all'indirizzo: http://examples.oreilly.com/9780596804831/HelloCone/

Il problema che sto avendo è con il loro 2,0 renderer OpenGL ES, che non compare nella loro ES 1.1 renderer.

Quindi cosa Ho notato è che il cono non rende esattamente nella posizione corretta. Per verificare questa ho cambiato il ModelViewMatrix di rendere esattamente sul piano FrustumNear. Così il cono dovrebbero apparire tagliare completamente in due. Quando faccio questo con l'ES 1.1 rende questo è il caso, quando lo faccio lo stesso in OpenGL ES 2.0 tuttavia non è. Il cono è per la maggior parte lì, ma leggermente rasato. Che significa che non sta atterrando esattamente vicino al viso del fustrum.

Ecco il codice di inizializzazione in cui viene creata la matrice di proiezione e impostare:

void RenderingEngine2::Initialize(int width, int height)
{
const float coneRadius = 0.5f;
const float coneHeight = 1.0f;
const int coneSlices = 40;

{
    // Allocate space for the cone vertices.
    m_cone.resize((coneSlices + 1) * 2);

    // Initialize the vertices of the triangle strip.
    vector<Vertex>::iterator vertex = m_cone.begin();
    const float dtheta = TwoPi / coneSlices;
    for (float theta = 0; vertex != m_cone.end(); theta += dtheta) {

        // Grayscale gradient
        float brightness = abs(sin(theta));
        vec4 color(brightness, brightness, brightness, 1);

        // Apex vertex
        vertex->Position = vec3(0, 1, 0);
        vertex->Color = color;
        vertex++;

        // Rim vertex
        vertex->Position.x = coneRadius * cos(theta);
        vertex->Position.y = 1 - coneHeight;
        vertex->Position.z = coneRadius * sin(theta);
        vertex->Color = color;
        vertex++;
    }
}

{
    // Allocate space for the disk vertices.
    m_disk.resize(coneSlices + 2);

    // Initialize the center vertex of the triangle fan.
    vector<Vertex>::iterator vertex = m_disk.begin();
    vertex->Color = vec4(0.75, 0.75, 0.75, 1);
    vertex->Position.x = 0;
    vertex->Position.y = 1 - coneHeight;
    vertex->Position.z = 0;
    vertex++;

    // Initialize the rim vertices of the triangle fan.
    const float dtheta = TwoPi / coneSlices;
    for (float theta = 0; vertex != m_disk.end(); theta += dtheta) {
        vertex->Color = vec4(0.75, 0.75, 0.75, 1);
        vertex->Position.x = coneRadius * cos(theta);
        vertex->Position.y = 1 - coneHeight;
        vertex->Position.z = coneRadius * sin(theta);
        vertex++;
    }
}

// Create the depth buffer.
glGenRenderbuffers(1, &m_depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, m_depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER,
                      GL_DEPTH_COMPONENT16,
                      width,
                      height);

// Create the framebuffer object; attach the depth and color buffers.
glGenFramebuffers(1, &m_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
                          GL_COLOR_ATTACHMENT0,
                          GL_RENDERBUFFER,
                          m_colorRenderbuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
                          GL_DEPTH_ATTACHMENT,
                          GL_RENDERBUFFER,
                          m_depthRenderbuffer);

// Bind the color buffer for rendering.
glBindRenderbuffer(GL_RENDERBUFFER, m_colorRenderbuffer);

// Set up some GL state.
glViewport(0, 0, width, height);
glEnable(GL_DEPTH_TEST);

// Build the GLSL program.
m_simpleProgram = BuildProgram(SimpleVertexShader, SimpleFragmentShader);
glUseProgram(m_simpleProgram);

// Set the projection matrix.
GLint projectionUniform = glGetUniformLocation(m_simpleProgram, "Projection");
mat4 projectionMatrix = mat4::Frustum(-1.6f, 1.6, -2.4, 2.4, 5, 10);
glUniformMatrix4fv(projectionUniform, 1, 0, projectionMatrix.Pointer());
}

E qui è il codice di rendering. Come potete vedere ho cambiato il ModelVieMatrix per posizionare il cono in basso a sinistra del volto Frustum vicino.

void RenderingEngine2::Render() const
{
GLuint positionSlot = glGetAttribLocation(m_simpleProgram, "Position");
GLuint colorSlot = glGetAttribLocation(m_simpleProgram, "SourceColor");

glClearColor(0.5f, 0.5f, 0.5f, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnableVertexAttribArray(positionSlot);
glEnableVertexAttribArray(colorSlot);

Mat4 rotazione (m_animation.Current.ToMatrix ());     traduzione Mat4 = Mat4 :: Tradurre (-1.6, -2.4, -5);

// Set the model-view matrix.
GLint modelviewUniform = glGetUniformLocation(m_simpleProgram, "Modelview");
mat4 modelviewMatrix = rotation * translation;
glUniformMatrix4fv(modelviewUniform, 1, 0, modelviewMatrix.Pointer());

// Draw the cone.
{
  GLsizei stride = sizeof(Vertex);
  const GLvoid* pCoords = &m_cone[0].Position.x;
  const GLvoid* pColors = &m_cone[0].Color.x;
  glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, stride, pCoords);
  glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, stride, pColors);
  glDrawArrays(GL_TRIANGLE_STRIP, 0, m_cone.size());
}

// Draw the disk that caps off the base of the cone.
{
  GLsizei stride = sizeof(Vertex);
  const GLvoid* pCoords = &m_disk[0].Position.x;
  const GLvoid* pColors = &m_disk[0].Color.x;
  glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, stride, pCoords);
  glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, stride, pColors);
  glDrawArrays(GL_TRIANGLE_FAN, 0, m_disk.size());
}

glDisableVertexAttribArray(positionSlot);
glDisableVertexAttribArray(colorSlot);
}
È stato utile?

Soluzione

Sembra che ho trovato la risposta alla mia domanda.

La matrice di proiezione nel codice O'Reilly viene calcolato in modo errato.

Nel loro codice hanno:

T a = 2 * near / (right - left);
T b = 2 * near / (top - bottom);
T c = (right + left) / (right - left);
T d = (top + bottom) / (top - bottom);
T e = - (far + near) / (far - near);
T f = -2 * far * near / (far - near);
Matrix4 m;
m.x.x = a; m.x.y = 0; m.x.z = 0; m.x.w = 0;
m.y.x = 0; m.y.y = b; m.y.z = 0; m.y.w = 0;
m.z.x = c; m.z.y = d; m.z.z = e; m.z.w = -1;
m.w.x = 0; m.w.y = 0; m.w.z = f; m.w.w = 1;
return m;

Tuttavia questo non è la matrice di proiezione. m.w.w dovrebbe essere 0 non 1.

Matrix4 m;
m.x.x = a; m.x.y = 0; m.x.z = 0; m.x.w = 0;
m.y.x = 0; m.y.y = b; m.y.z = 0; m.y.w = 0;
m.z.x = c; m.z.y = d; m.z.z = e; m.z.w = -1;
m.w.x = 0; m.w.y = 0; m.w.z = f; m.w.w = 0;
return m;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top