4
\$\begingroup\$

I have been trying to get a simple triangle to render on the screen. I am using Projection, View and Transformation matrices but am unable to get anything to the screen.

Main loop

...
shader->start();

Matrix4f transformation = Math::createTransformationMatrix(Vec3<float>(0,0,-25),0,0,0, 1);
shader->loadTransformationMatrix(transformation);

Matrix4f camera = Math::createViewMatrix(Vec3<float>(0, 0, 0), 1, 0, 0);
shader->loadViewMatrix(camera);

Matrix4f projection = Math::getProjectionMatrix(1080,720);
shader->loadProjectionMatrix(projection);

glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
    0, 
    3,
    GL_FLOAT,
    GL_FALSE,
    0,
    (void*)0
);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);

shader->stop();
...

Math.h

static Matrix4f createTransformationMatrix(Vec3<float> translation, float rx, float ry, float rz, float scale) {
    Matrix4f matrix;
    Matrix4f::translate(translation, matrix,matrix);
    Matrix4f::rotate(toRadians(rx), Vec3<float>(1, 0, 0), matrix, matrix);
    Matrix4f::rotate(toRadians(ry), Vec3<float>(0, 1, 0), matrix, matrix);
    Matrix4f::rotate(toRadians(rz), Vec3<float>(0, 0, 1), matrix, matrix);
    Matrix4f::scale(Vec3<float>(scale, scale, scale), matrix, matrix);
    return matrix;
}
static Matrix4f createViewMatrix(Vec3<float> pos, float pitch, float yaw, float roll) {
    Matrix4f matrix;
    Matrix4f::rotate(toRadians(pitch), Vec3<float>(1, 0, 0), matrix, matrix);
    Matrix4f::rotate(toRadians(yaw), Vec3<float>(0, 1, 0), matrix, matrix);
    Matrix4f::rotate(toRadians(roll), Vec3<float>(0, 0, 1), matrix, matrix);

    Vec3<float> negativeCam(-pos.x, -pos.y, -pos.z);
    Matrix4f::translate(negativeCam, matrix, matrix);

    return matrix;
}
static Matrix4f getProjectionMatrix(int width, int height) {
    float aspectRatio = (float)width / (float)height;
    float y_scale = (float)((1 / tan(toRadians(FOV / 2)))*aspectRatio);
    float x_scale = y_scale / aspectRatio;
    float frustum_length = FAR_PLANE - NEAR_PLANE;

    Matrix4f projectionMatrix;
    projectionMatrix[0] = x_scale;
    projectionMatrix[5] = y_scale;
    projectionMatrix[10] = -((FAR_PLANE + NEAR_PLANE) / frustum_length);
    projectionMatrix[11] = -1;
    projectionMatrix[14] = -((2 * NEAR_PLANE * FAR_PLANE) / frustum_length);
    projectionMatrix[15] = 0;
    return projectionMatrix;
}

Vertex Shader

    #version 330 core

    layout(location = 0) in vec3 position;

    uniform mat4 transformationMatrix;
    uniform mat4 projectionMatrix;
    uniform mat4 viewMatrix;

    void main() {
        //Works but renders without any camera or projection applied
        //gl_Position.xyz = position;
        //gl_Position.w = 1.0;

        vec4 worldPosition = transformationMatrix * vec4(position, 1.0);
        vec4 positionRelitiveToCam = viewMatrix * worldPosition;
        gl_Position = projectionMatrix * positionRelitiveToCam;
    }
\$\endgroup\$
0

2 Answers 2

1
\$\begingroup\$

Some sanity checks could help you debug this:

  1. Disable culling with glDisable( GL_CULL_FACE );
  2. Disable depth test with glDisable( GL_DEPTH_TEST );
  3. Use super simple fragment shader that just sets frag colour to (1.0, 0.0, 0.0, 1.0) e.g.

If after that, you still only see a black screen, double check your view matrix.

Something that not everybody may know: the view matrix is nothing else than the inverse of your camera transform.

So instead of building up your viewmat as in your code, it is easier to just transform (position/orient) your camera in the world. Then take its matrix, and invert it.

That inverted matrix, is your view matrix.

\$\endgroup\$
0
\$\begingroup\$

There are many things that can be wrong, check the follows:

    • Use quaternions, because then you can normalize them and be sure that all is correct.
    • gl_position should look like this: ViewProjection * cameraRotation * cameraTranslation * Object transformation * vec4(Position,1.0);

    Where object transformation is: Object Translation * Object Rotation * Object Scale

    • Stop using glUseProgram(0) Opengl is sequential, it wont do anything good for you.
    • Make a buffer at the init to initializate the vertex buffer and save it for later use it. It should look something like this:

      glGenVertexArrays(1, &m_VAO); glBindVertexArray(m_VAO); glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[POS_VB]); glBufferData(GL_ARRAY_BUFFER, sizeof(Positions[0]) * Positions.size(), &Positions[0], GL_STATIC_DRAW); glEnableVertexAttribArray(POSITION_LOCATION); glVertexAttribPointer(POSITION_LOCATION, 3, GL_FLOAT, GL_FALSE, 0, 0);

    \$\endgroup\$
    5
    • 2
      \$\begingroup\$ I have to disagree about calling glUseProgram(0). If you don't call that, then the state remains set and future drawing will use the same program. If that isn't what you intended, you now have a bug in your program and don't realize it. \$\endgroup\$ Oct 23, 2016 at 14:50
    • \$\begingroup\$ He is using the whole time the same shader, it is no point on deleting it every frame. Also if you want to use another shader it is no point on calling glUseProgram(0), the new one will remplace the last one. \$\endgroup\$
      – Haruko
      Oct 23, 2016 at 15:01
    • 1
      \$\begingroup\$ A few points: 1) glUseProgram(0) does not delete the program. It just sets the current gl state to not use any program. 2) We don't know what other drawing happens in this code. This is just a snippet. 3) You're assuming that the developer will always remember to set a new program. My point is that if they don't they won't have any indication that the wrong program is being used. If you set it back to 0 when you're done, then there's a very obvious thing that's different when you go to draw the next piece of geometry. Most gl bugs I encounter are due to state not being set correctly. \$\endgroup\$ Oct 23, 2016 at 15:46
    • \$\begingroup\$ I see your point. You are right, but in this case we know that this user just want to draw a triangle, there is not more geometry to draw. Anyways, we just have different ways to see it, when i want to draw without using a shader i just use glUseProgram(0) or i use a shader that do nothing, when i want to use a shader i just use it, it will just replace the last one. It is just different ways to do it, seting whole time the shader to 0 can generate problems also, for example you might think that you are using a shader but you aren´t (it happened to me). \$\endgroup\$
      – Haruko
      Oct 23, 2016 at 16:20
    • \$\begingroup\$ The multiplication should use the inverse of camera, and there is no need to have cam-rot and cam-trans separate. Thus: glpos = projmat * inverse-cam-trf * model-trf * vertexpos. Personally, I compute the proj * view * model in c++ before sending it to the shader, as it is the same for all vertices in the model. \$\endgroup\$
      – Bram
      Mar 19, 2018 at 17:03

    You must log in to answer this question.

    Not the answer you're looking for? Browse other questions tagged .