Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

So I have the following...

float s = 0.5f;

void renderFrameLine() {
  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  GLfloat vVertices[] = { s, s, 0.0f, s, -s, 0.0f, -s, s,
    0.0f};
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
  glEnableVertexAttribArray(0);
  glDrawArrays(GL_TRIANGLES, 0, 3);
}

This works great so now I want to add depth so I get ready by changing my vertex shader as following...

GLbyte vShaderStr[] =
"attribute vec4 vPosition;   \n"
"uniform mat4 Projection;   \n"
"void main()                 \n"
"{                           \n"
"     gl_Position = Projection * vPosition; \n"
"}                           \n";

And based on this code in GLM...

template <typename valType>
    GLM_FUNC_QUALIFIER detail::tmat4x4<valType> perspectiveFov
    (
            valType const & fov,
            valType const & width,
            valType const & height,
            valType const & zNear,
            valType const & zFar
    )
    {
#ifdef GLM_FORCE_RADIANS
            valType rad = fov;
#else
            valType rad = glm::radians(fov);
#endif
            valType h = glm::cos(valType(0.5) * rad) / glm::sin(valType(0.5) * rad);
            valType w = h * height / width; ///todo max(width , Height) / min(width , Height)?

            detail::tmat4x4<valType> Result(valType(0));
            Result[0][0] = w;
            Result[1][1] = h;
            Result[2][2] = - (zFar + zNear) / (zFar - zNear);
            Result[2][3] = - valType(1);
            Result[3][2] = - (valType(2) * zFar * zNear) / (zFar - zNear);
            return Result;
    }

I create the following function to create a perspective matrix...

void glFrustumf(float near, float far){
        float aspectRatio = .5;
        float DEG2RAD = 3.14159f / 180.0f;
        float fov = 90*DEG2RAD;
        float h = cosf(0.5f*fov)/sinf(0.5f*fov);
        float w = h * aspectRatio;
        float a =  - (near+far)/(near - far);
        float b = - ((2*far*near)/(far-near));

        float proj[16] = {
                        w, 0, 0, 0,
                        0, h, 0, 0,
                        0, 0, a, 1,
                        0, 0, b, 0
                    };
        GLint projectionUniform = glGetUniformLocation(programObject, "Projection");
        glUniformMatrix4fv(projectionUniform, 1, 0, &proj[0]);
}

This doesn't seem to work and instead returns a blank screen. Can anyone tell me what I am doing wrong?

Update

I also tried

void glFrustumf(float near, float far, float left, float right, float bottom, float top){
        float deltaX = right - left;
        float deltaY = top - bottom;
        float deltaZ = far - near;

        float a = 2.0f * near / deltaX;
        float b = 2.0f * near / deltaY;
        float c = (right + left) / deltaX;
        float d = (top + bottom) / deltaY;
        float e = -(near + far) / deltaZ;
        float f = -2.0f * near * far / deltaZ;

        float proj[16] = {
                        a, 0, 0, 0,
                        0, b, 0, 0,
                        c, d, e, -1.0f,
                        0, 0, f, 0
                    };
        GLint projectionUniform = glGetUniformLocation(programObject, "Projection");
        glUniformMatrix4fv(projectionUniform, 1, GL_FALSE, &proj[0]);
}

but no dice...

Per previous comment

Based on this line...

2 ⁢ nearVal right - left 0 A 0 0 2 ⁢ nearVal top - bottom B 0 0 0 C D 0 0 -1 0

A = right + left right - left

B = top + bottom top - bottom

C = - farVal + nearVal farVal - nearVal

D = - 2 ⁢ farVal ⁢ nearVal farVal - nearVal

I changed to this...

float proj[16] = {
                        a, 0, c, 0,
                        0, b, d, 0,
                        0, 0, e, f,
                        0, 0, -1, 0
};

But still just black...

Also tried...

void glFrustumf(float near, float far){
    float aspectRatio = .5;
    float DEG2RAD = 3.14159f / 180.0f;
    float fov = 90*DEG2RAD;
    float w = fov/aspectRatio;
    float a =  - (near+far)/(near - far);
    float b = - ((2*far*near)/(near - far));

    float proj[16] = {
                    w, 0, 0, 0,
                    0, fov, 0, 0,
                    0, 0, a, b,
                    0, 0, -1, 0
                };
    GLint projectionUniform = glGetUniformLocation(programObject, "Projection");
    glUniformMatrix4fv(projectionUniform, 1, 0, &proj[0]);
}

Also tried ...

void glFrustumf(float near, float far){
    float aspectRatio = .5;
    float DEG2RAD = 3.14159f / 180.0f;
    float fov = 90*DEG2RAD;
    float cot = (1 / (tanf(fov)/2));
    float cota = cot /aspectRatio;
    float a =  - (far+near)/(near - far);
    float b = - ((2*far*near)/(near-far));

    float proj[16] = {
                    cota, 0, 0, 0,
                    0, cot, 0, 0,
                    0, 0, a, b,
                    0, 0, -1, 0
                };
    GLint projectionUniform = glGetUniformLocation(programObject, "Projection");
    glUniformMatrix4fv(projectionUniform, 1, 0, &proj[0]);
}
share|improve this question

closed as too localized by bobobobo, msell, Sean Middleditch, Maik Semder, Anko Jun 3 '13 at 13:49

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.If this question can be reworded to fit the rules in the help center, please edit the question.

    
Looking at opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml , the denominator of result[3][2] should be (zNear - zFar). Also, your frustum does not look like opengl.org/sdk/docs/man2/xhtml/glFrustum.xml –  sarahm Jun 1 '13 at 15:44
    
Thanks for trying to help check my update... –  Jackie Jun 1 '13 at 15:55
2  
This post has far too much code in it. You basically are lacking debugging skills. –  bobobobo Jun 1 '13 at 16:11
    
I am not using GLM I am trying to reimplement in C –  Jackie Jun 1 '13 at 16:31
add comment

2 Answers

I have had this exact problem. http://stackoverflow.com/questions/14713343/projection-theory-implimented-in-glsl

First thing I suggjest is getting a book called "3D Math Primer for Graphics and Game Development", which goes into detail on the clip matrix derives the whole formula for both OpenGL and DirectX projections. (There is a slight difference, oddly enough.)

Your matrix, in the first attempt, is actually correct. The error, or reason your screen is blank, is because your passing it to the Vertex Shader with glUniformMatrix4fv(projectUniform, 1, GL_FALSE, &proj[0]); That GL_FALSE, should be GL_TRUE. Giving glUniformMatrix4fv(projectUniform, 1, GL_TRUE, &proj[0]);

The projection matrices are as fallows (Row Major Format):

OpenGL:

| zoomX   0        0      0 |
|   0   zoomY      0      0 |
|   0     0   (f+n)/(f-n) 1 |
|   0     0   (2nf)/(n-f) 0 |

DirectX:

| zoomX   0        0      0 |
|   0   zoomY      0      0 |
|   0     0   (f+n)/(f-n) 1 |
|   0     0   (nf)/(n-f)  0 |

I'm also posting my implimentation. My implimentation automatically adjust's the row major format to column major format. So to pass a matrix in this format, you specify GL_FALSE. As opposed to your implimentation where you should specify GL_TRUE. Make shure you understand how to identify when to use GL_FALSE or GL_TRUE.

template <class type> struct mat4_t
{
    type m00, m10, m20, m30;
    type m01, m11, m21, m31;
    type m02, m12, m22, m32;
    type m03, m13, m23, m33;

    mat4_t();
    mat4_t(type, type, type, type,
           type, type, type, type,
           type, type, type, type,
           type, type, type, type);
};

template <class type> mat4_t<type>::mat4_t()
{
    m00 = 0; m01 = 0; m02 = 0; m03 = 0;
    m10 = 0; m11 = 0; m12 = 0; m13 = 0;
    m20 = 0; m21 = 0; m22 = 0; m23 = 0;
    m30 = 0; m31 = 0; m32 = 0; m33 = 0;
}

template <class type> mat4_t<type>::mat4_t(type n00, type n01, type n02, type n03,
                                           type n10, type n11, type n12, type n13,
                                           type n20, type n21, type n22, type n23,
                                           type n30, type n31, type n32, type n33)
{
    m00 = n00; m01 = n01; m02 = n02; m03 = n03;
    m10 = n10; m11 = n11; m12 = n12; m13 = n13;
    m20 = n20; m21 = n21; m22 = n22; m23 = n23;
    m30 = n30; m31 = n31; m32 = n32; m33 = n33;
}

typedef mat4_t<float> mat4;

mat4 ProjectionMatrix(float aspect, float fovy, float near, float far)
{
    float h = near * tan(radians(fovy));

    float fmn = far - near;
    return mat4(h * aspect, 0.0, 0.0,                0.0,
                0.0,        h,   0.0,                0.0,
                0.0,        0.0, (far + near) / fmn, 1.0,
                0.0,        0.0, (2*near*far) / fmn, 0.0);
}
share|improve this answer
    
Thanks a lot for showing your implementation! I will try to play around with it but from the documentation (Remember I am using GLES2.0) "Specifies whether to transpose the matrix as the values are loaded into the uniform variable. Must be GL_FALSE." So does this mean I just need to reverse the order of the variables? –  Jackie Jun 2 '13 at 14:25
    
I tried maunally transposing to float proj[16] = { w, 0, 0, 0, 0, h, 0, 0, 0, 0, a, b, 0, 0, 1, 0 }; But still no dice –  Jackie Jun 2 '13 at 14:47
    
adding GL_TRUE does cause an exception btw. –  Jackie Jun 2 '13 at 14:58
    
Odd that GLES2.0 has that requirement, Though I guess we cant change that. Looking at your implimentation again, I see you have a = -(near+far)/(near-far) and then b = -(2*near*far)/(far-near). for one thing, there is'nt supposed to be a - in either equasion. You also have the denominators wrong. it should be a = (near+far)/(far-near) and b = (2*near*far)/(near-far) try changing that and see what happens. –  Wolfgang Skyler Jun 2 '13 at 15:14
    
Or it could be a = (near+far)/(far-near) and b = -(2*near*far)/(far-near) I guess. so never mind, that should'nt change anything. –  Wolfgang Skyler Jun 2 '13 at 15:15
show 2 more comments
up vote 0 down vote accepted

Per previous this works...

void glFrustumf(float near, float far){
  float aspectRatio = .5;
  float DEG2RAD = 3.14159f / 180.0f;
  float fov = 90*DEG2RAD;
  float h = cosf(0.5f*fov)/sinf(0.5f*fov);
  float w = h * aspectRatio;
  float a =  - (near+far)/(near - far);
  float b = - ((2*far*near)/(far-near));

  float proj[16] = {
    w, 0, 0, 0,
    0, h, 0, 0,
    0, 0, a, 1,
    0, 0, b, 0
  };
  GLint projectionUniform = glGetUniformLocation(programObject, "Projection");
  glUniformMatrix4fv(projectionUniform, 1, 0, &proj[0]);
}
...
glFrustumf(0.1f, nf);

This now seems to work, I think Wolfgang's advice about the book is pretty solid. It helped a lot.

more info...

https://github.com/jrgleason/CrossGLESMobile

share|improve this answer
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.