0

I have a scene that consists of a lot of objects, and when I'm rendering them I iterate through all items that are in the scene and call glDrawElements on them. This works fine. However, now I'm implementing shadow mapping to the scene, and I am using the same way to draw to the shadow buffer. However, only the first element in the scene is drawn to the texture in a correct way, I'm checking this by attaching the depth texture to a scene element which you will see below.

The code is as follows:

glBindFramebuffer(GL_FRAMEBUFFER, vFrameBuffers[ShadowFB]);
glViewport(0,0,1024,1024);

glClearDepth(1.0f);
glClear(GL_DEPTH_BUFFER_BIT);

glUseProgram(shadowShader);
depth_loc = glGetUniformLocation(shadowShader, "depthProj");
model_view_loc = glGetUniformLocation(shadowShader, "modelmat");

glUniformMatrix4fv(depth_loc, 1, GL_FALSE, depthproj);

depthproj = mat4(1.0);
depthproj = Ortho(-250.0f, 250.0f, -200.0f, 200.0f, -200.0f, 200.0f);
depthproj = depthproj * RotateX(15);
depthproj = depthproj * RotateY(220);

for (int i = 0; i < _objectArray.size(); i++)
{
    modelmat = mat4(1.0);
    modelmat = modelmat*Translate(_objectArray[i]->getLocation()->getX(),
        _objectArray[i]->getLocation()->getY(),
        _objectArray[i]->getLocation()->getZ());

    glUniformMatrix4fv(model_view_loc, 1, GL_FALSE, modelmat);

    if (_objectArray[i]->getType() == TypeMountain)
    {
        glBindVertexArray(vArrays[ShadowMountainA]);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vElements[ShadowMountainE]);
        glDrawElements(GL_TRIANGLES, 40*40*6, GL_UNSIGNED_SHORT, NULL);
        glBindVertexArray(0);
    }
    else if (_objectArray[i]->getType() == TypePasture)
    {   
        glBindVertexArray(vArrays[ShadowPastureA]);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vElements[ShadowPastureE]);
        glDrawElements(GL_TRIANGLES, 40*40*6, GL_UNSIGNED_SHORT, NULL);
        glBindVertexArray(0);
    }
    else if (_objectArray[i]->getType() == TypeWater)
    {   
        glBindVertexArray(vArrays[ShadowWaterA]);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vElements[ShadowWaterE]);
        glDrawElements(GL_TRIANGLES, 40*40*6, GL_UNSIGNED_SHORT, NULL);
        glBindVertexArray(0);
    }
    else if (_objectArray[i]->getType() == TypeTree)
    {   
        glBindVertexArray(vArrays[ShadowTreeA]);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vElements[ShadowTreeE]);
        glDrawElements(GL_TRIANGLES, 180, GL_UNSIGNED_SHORT, NULL);
        glBindVertexArray(0);
    }
}

glUseProgram(0);

When I run it only on the mountain object, this is the resulting image I get, as you can see it is correct. Mountain in framebuffer It works on other scene elements individually as well. My question is how do I draw without problems into the same buffer using multiple draws?

edit: Just because it was requested here are the shadow shader components:

Vertex shader:

#version 330 core

uniform mat4 depthProj;
uniform mat4 modelmat;

layout(location = 0) attribute vec4 vPosition;

void main()
{
    gl_Position = depthProj * modelmat * vPosition;
}

Fragment shader:

#version 330 core

layout(location = 0) out float fragmentDepth;

void main()
{
}
  • *"I'm checking this by attaching the depth texture to a scene element which you will see below"* This does not look like any depth texture I have ever seen. Why is it in color? Maybe you should include the shader you used to generate that image to show what's really going on. – Andon M. Coleman Apr 27 '14 at 02:43
  • It is not in color, the depth texture is used on the little islands that surround the mountain. They are white, except for the depth values of the mountain which are grey that can be seen in the center of the texture. And there's nothing of value in the shadow shader. – user1800978 Apr 27 '14 at 02:50
  • You're not drawing into the depth texture at the same time as you're trying to sample it, are you? That could explain why every type of object other than your mountain behaves that way. – Andon M. Coleman Apr 27 '14 at 02:52
  • The depth texture is only used during the actual rendering process which is after the loop I have put above. Which is very much like the loop above but with the actual shader and its variables. If OpenGL is accessing it between glDrawElements I have no idea. – user1800978 Apr 27 '14 at 02:56

1 Answers1

0

I don't know why, but when the lines,

glUniformMatrix4fv(depth_loc, 1, GL_FALSE, depthproj);

and

glUniformMatrix4fv(model_view_loc, 1, GL_FALSE, modelmat);

are turned into;

glUniformMatrix4fv(depth_loc, 1, GL_TRUE, depthproj);

and

glUniformMatrix4fv(model_view_loc, 1, GL_TRUE, modelmat);

the scene is drawn as it should.

  • 2
    I was just going to make a related comment under the question. In the original code, you set the uniform for `depthproj` before you build the matrix. Anyway, if you need `GL_TRUE` for that argument, it means that you're building your matrices in row-major orders, while OpenGL wants column-major matrices. – Reto Koradi Apr 27 '14 at 03:43