Depth Buffer Not Working With Multiple Shader Programs - c++

I am writing a 3D graphics renderer in C++ using OpenGL-ES for a handheld system and I am utilizing a decal (texture) shader, as well as a color-fill shader. I have two render passes where I use the respective program and use Array/Element buffers to draw data using glDrawElements.
Although I enable GL_DEPTH_TEST in my application, my decal polygons always render in front of my color-filled polygons.
I have tried reworking how my projection/modelView matrices are built and passed to the shaders, I have tried different glDepthFunc parameters but I am not able to get them to render properly.
This is my draw code - I start each frame with
glClearColor(0.25f, 0.25f, 0.25f, 1.f);
glClearDepthf(1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Then I calculate world-space polygon coordinates and arrange it into GLfloat vectors. I draw the decal data first:
GLuint programId = decalProgramId;
glUseProgram(programId);
// All of my uniform params are setup here - omitting to save space
// Set proj/mv matrices
glUniformMatrix4fv(glGetUniformLocation(programId, "uProjection"), 1, GL_TRUE, static_cast<f32*>(gameEngine.proj));
glUniformMatrix4fv(glGetUniformLocation(programId, "uModelView"), 1, GL_TRUE, static_cast<f32*>(gameEngine.modelView));
// Then I prepare the buffer data
glBindBuffer(GL_ARRAY_BUFFER, decalBufferId);
glBufferData(GL_ARRAY_BUFFER, coordSize + texCoordSize, 0, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, coordSize, &coords[0]);
glBufferSubData(GL_ARRAY_BUFFER, coordSize, texCoordSize, &texCoords[0]);
// And element array buffer data
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, decalElementBufferId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, &indices[0], GL_STATIC_DRAW);
// Enable our vertex attributes
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(coordSize));
// Bind my test texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// Draw the elements
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, 0);
The process is then repeated with my color polygons. Followed by SwapBuffer and WaitVSync commands.
Here is my code for creating one of the triangles and the front face of the cube:
// Add polygon directly to the scene object
scene.AddPolygon(polygonBuilder
.AddVertex(Vector3(0.5f, 0.5f, 0.f), Vector4(0.f, 0.f, 1.f, 1.f))
.AddVertex(Vector3(0.25f, 0.f, 0.f), Vector4(0.f, 1.f, 0.f, 1.f))
.AddVertex(Vector3(0.75f, 0.f, 0.f), Vector4(1.f, 0.f, 0.f, 1.f))
.AddIndex(0).AddIndex(1).AddIndex(2)
.Build()
);
// Create a polygon within the crate object
crateObject.AddPolygon(polygonBuilder
.AddVertex(Vector3(-0.25f, 0.25f, 0.f), Vector2(0.f, 0.f))
.AddVertex(Vector3(-0.25f, -0.25f, 0.f), Vector2(0.f, 1.f))
.AddVertex(Vector3(0.25f, -0.25f, 0.f), Vector2(1.f, 1.f))
.AddVertex(Vector3(0.25f, 0.25f, 0.f), Vector2(1.f, 0.f))
.SetTexture("crate")
.AddIndex(0).AddIndex(1).AddIndex(3)
.AddIndex(3).AddIndex(1).AddIndex(2)
.Build()
);
// Add the crate object as a child within the scene
scene.AddChild(crate);
This screenshot is the current output when I create two colored triangles and one textured cube:
The blue arrow indicates a triangle that should have rendered in the front. Any ideas?

I feel really silly now. My color shader was not properly applying the model-view matrix. It was always rendering at a fixed depth.
I modified my color shader code to apply the matrix the same way as the decal and now it works perfectly.

Related

How to enable an OpenGL Texture for different multiple buffer objects?

I have a problem about activating a single texture to multiple buffer objects. I am trying to draw two different graphical objects that using the same texture. However could not make it bind.
After searchs so far, I could find an answer that fits to my question in this (Re-using one texture for multiple OpenGL Quads) link. I tried this method in my code by using the glBindTexture() function before the main opengl render loop, and also inside of the render loop but it did not bind. Also it is said that, bind the texture before the draw call, in here (OpenGl all models are with the same texture). But this way also did not work for me.
How can I use the exact same texture which is named texture1 for second buffer object?
I use two buffer objects and two vertex array objects for different graphical objects. What I really want to accomplish to describe only one texture after the first buffer array and then use the exact same texture for the second object. But when I try to bind the texture after vertex array object it does not work.
By the way I do not load any images for the texture. The main purpose that I use texture in order to utilize the texture coordinates. I do necessary works in the fragment shader.
#shader vertex
#version 330 core
layout (location=0) in vec3 position;
layout (location=1) in vec2 TextureCoords;
out vec2 TexCoord;
void main()
{
TexCoord = vec2(TextureCoords.x, TextureCoords.y);
gl_Position = vec4(position, 1.0);
};
#shader fragment
#version 330 core
out vec4 fragColor;
in vec2 TexCoord;
void main()
{
vec2 xy = TexCoord.xy;
vec4 color = vec4(vec3(xy.x), 1.0);
fragColor = color;
};
float vertexArray1[] = {
// Vertex Position | Texture Coords
// x y z x y
0.9f, 0.9f, 0.0f, 1.0f, 1.0f,
0.9f, 0.2f, 0.0f, 1.0f, 0.0f,
0.2f, 0.2f, 0.0f, 0.0f, 0.0f,
0.2f, 0.9f, 0.0f, 0.0f, 1.0f,
0.9f, 0.9f, 0.0f, 1.0f, 1.0f,
0.2f, 0.2f, 0.0f, 0.0f, 0.0f,
};
float vertexArray2[] = {
-0.2f, 0.9f, 0.0f, 1.0f, 1.0f,
-0.2f, 0.2f, 0.0f, 1.0f, 0.0f,
-0.9f, 0.2f, 0.0f, 0.0f, 0.0f,
-0.9f, 0.9f, 0.0f, 0.0f, 1.0f,
-0.2f, 0.9f, 0.0f, 1.0f, 1.0f,
-0.9f, 0.2f, 0.0f, 0.0f, 0.0f,
};
unsigned int buffer;
unsigned int VAO;
glGenBuffers(1, &buffer);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexArray1), vertexArray1, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
glEnableVertexAttribArray(0);
unsigned int texture1;
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
unsigned int buffer2;
unsigned int VAO2;
glGenBuffers(1, &buffer2);
glGenVertexArrays(1, &VAO2);
glBindVertexArray(VAO2);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexArray2), vertexArray2, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
glEnableVertexAttribArray(0);
// I want to use the previously described texture1 in here, but it does not bind.
glBindTexture(GL_TEXTURE_2D, texture1);
while(!glfwWindowShouldClose(window)){
processInput(window);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader);
glBindVertexArray(VAO);
glDrawArrays(GL_LINES, 0, 6*3*1);
glBindVertexArray(VAO2);
glDrawArrays(GL_LINES, 0, 6*3*1);
glfwSwapBuffers(window);
glfwPollEvents();
}
Note: When I create another different texture for the buffer2 object it works like a charm. I mean texture1 for buffer1, texture2 for buffer2... But I want to keep the number of the texture as possible as minimum. Maybe in future developments, I will have to create more than 50 buffer object, thus I do not want to create different textures for every single buffer object.
EDIT: I have changed my misunderstanding of "binding a texture to a vertex array" to "enabling attributes of a texture for other objects". I've also included my shader scripts for debugging purposes.
Textures are not bound to buffer objects. When you draw something, it uses the currently bound texture, not one from a buffer.
Textures are not bound to VAOs either so there's no need to worry about that.
To use a texture, you do need to have a sampler in your shader, bind the texture unit (not the texture) to the sampler with glUniform1i, and call the texture function in the shader and do something with the return value.
Since you say your shader isn't doing anything with your texture anyway, I wonder how you can tell whether it's bound or not.
In fact, there's no reason to have a texture if you don't have a shader that does something with it! There is no magical texture-shader interaction. A texture is something you have to specifically query (by calling texture) or else it doesn't do anything by itself.
You don't need to have a texture to have texture coordinates.
Since you haven't shown your shaders, it's impossible to debug them for you.
After I review my code again and search once more, I came across a solution for my question.
And I guess where I was wrong was trying to bind a texture which was already bound to the global context, as #ColonelThirtyTwo pointed out in the comment.
As I understood, instead of trying to bind the same texture I should have called the glVertexAttribPointer() and enable with glEnableVertexAttribArray() for bounded texture.
Since in the answer of this question (glVertexAttribPointer clarification), it is said that:
"A Vertex Array Object or VAO is used to store the state of all the glVertexAttribPointer calls and the VBOs that were targeted when each
of the glVertexAttribPointer calls were made."
So I came up to this solution and it worked:
unsigned int buffer;
unsigned int VAO;
glGenBuffers(1, &buffer);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexArray1), vertexArray1, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
glEnableVertexAttribArray(0);
unsigned int texture1;
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
unsigned int buffer2;
unsigned int VAO2;
glGenBuffers(1, &buffer2);
glGenVertexArrays(1, &VAO2);
glBindVertexArray(VAO2);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexArray2), vertexArray2, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
glEnableVertexAttribArray(0);
// Inseted of the bind call,
// I called the glVertexAttribPointer() and glEnableVertexAttribArray() here.
// And if I am not wrong these calls use the currently bounded texture which is texture1.
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
while(!glfwWindowShouldClose(window)){
processInput(window);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader);
glBindVertexArray(VAO);
glDrawArrays(GL_LINES, 0, 6*3*1);
glBindVertexArray(VAO2);
glDrawArrays(GL_LINES, 0, 6*3*1);
glfwSwapBuffers(window);
glfwPollEvents();
}

LWJGL - Interleaved VAO/VBO not texturing

I have been attempting to transition my game's prototype renderer from it's immediate mode testing implementation to an actual VAO/VBO implementation. The VBO is rendering on screen, but is refusing to texture. Below is the simplest test class that shows the problem:
public static void main(String[] args) throws Exception {
// VertX,VertY TexX, TexY
float[] data = new float[] {0.0f, 0.0f, 0.25f, 0.75f,
0.0f, 64.0f, 0.25f, 1.0f,
64.0f, 64.0f, 0.5f, 1.0f,
0.0f, 0.0f, 0.25f, 0.75f,
64.0f, 64.0f, 0.5f, 1.0f,
64.0f, 0.0f, 0.5f, 0.75f};
glfwSetErrorCallback(GLFWErrorCallback.createPrint(System.err));
if (!glfwInit())
throw new IllegalStateException("Unable to initialize GLFW");
long window = GLFW.glfwCreateWindow(1600, 900, "TEST", 0, 0);
GLFW.glfwMakeContextCurrent(window);
GL.createCapabilities();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1600, 900, 0, 0.000001, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
int vboId = glGenBuffers();
int vaoId = glGenVertexArrays();
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindVertexArray(vaoId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, data, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 4*Float.BYTES, 0);
glTexCoordPointer(2, GL_FLOAT, 4*Float.BYTES, 4*Float.BYTES);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glTranslatef(50, 50, 0);
Texture t = new Texture(TEST.class.getClassLoader().getResourceAsStream("test/WallFloor.png"));
while (!GLFW.glfwWindowShouldClose(window)) {
GLFW.glfwPollEvents();
GLFW.glfwSwapBuffers(window);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindVertexArray(vaoId);
glEnableVertexAttribArray(0);
t.bind();
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
/* Equivelent immediate mode code - that works
t.bind();
glBegin(GL_TRIANGLES);
glTexCoord2f(0.25f, 0.75f);
glVertex2f(0, 0);
glTexCoord2f(0.25f, 1f);
glVertex2f(0, 64);
glTexCoord2f(0.5f, 0.75f);
glVertex2f(64, 0);
glTexCoord2f(0.5f, 1f);
glVertex2f(64, 64);
glTexCoord2f(0.25f, 1f);
glVertex2f(0, 64);
glTexCoord2f(0.5f, 0.75f);
glVertex2f(64, 0);
glEnd();
*/
}
}
The texture bind call is the following (where wrap = GL_REPEAT and filter = GL_NEAREST):
public void bind()
{
glActiveTexture(GL_TEXTURE0);
glClientActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(target, id);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);
}
Having spent the weekend googling it an not finding an answer, am I doing something horribly wrong? I have also tested using immediate mode, which does still render with a texture.
In addition, you are mixing core profile code (glVertexAttribPointer) with non-core profile (glTexCoordPointer)
But the real problem comes from the wrong stride and offset used. Stride defines how large the data of one vertex is, while the offset specifies how far from the beginning of each vertex the actual data starts. In your case, every vertex consists of 4 floats thus the stride has to be 4 * Float.BYTES. The positions are the first two floats in each vertex (offset 0) while the texture coordinates are the 3rd and 4th floats which means offset = 2 * Float.BYTES. The correct code could look somehow like this (note the usage of glVertexPointer instead of glVertexAttribPointer):
glVertexPointer(2, GL_FLOAT, false, 4*Float.BYTES, 0);
glTexCoordPointer(2, GL_FLOAT, 4*Float.BYTES, 2*Float.BYTES);
Edit
The usage of your VAOs is also wrong. In the initialization you store the glVertexPointer/glTexCoordPointer to the VAO vaoId. But in the rendering code you bind VAO 0 instead. Most probably the attribute settings are not present when drawing. In addition, I'm not absolutely sure whether VAOs work together with fixed function calls. In this case you can remove all of the VAO calls.

Skybox in openGL using triangles

I'm trying to implement a skybox in openGL but for some reason its not being drawn properly unless I turn off back face culling and even then it shows 3 triangles that are screwed up. Maby I'm not drawing the triangles right but I'm not sure.
bool Skybox::onInitialize()
{
myRadius = 100;
setPosition(Vector3(0.0f, 0.0f, 0.0f));
//Initialize color matrix
myColors.push_back(Color(1.0f, 0.0f, 0.0f, 1.0f));
myColors.push_back(Color(1.0f, 1.0f, 0.0f, 1.0f));
myColors.push_back(Color(1.0f, 0.5f, 0.0f, 1.0f));
myColors.push_back(Color(0.5f, 0.5f, 0.5f, 1.0f));
//Position the key points of the cube
myVertices.push_back(Vertex(-myRadius, -myRadius, myRadius));//0
myVertices.push_back(Vertex(-myRadius, -myRadius, -myRadius));//1
myVertices.push_back(Vertex(myRadius, -myRadius, -myRadius));//2
myVertices.push_back(Vertex(myRadius, -myRadius, myRadius));//3
myVertices.push_back(Vertex(-myRadius, myRadius, myRadius));//4
myVertices.push_back(Vertex(-myRadius, myRadius, -myRadius));//5
myVertices.push_back(Vertex( myRadius, myRadius, -myRadius));//6
myVertices.push_back(Vertex( myRadius, myRadius, myRadius));//7
//Push back the indices that make up the triangles for each face.
//Bottom
myIndices.push_back(0);
myIndices.push_back(1);
myIndices.push_back(2);
myIndices.push_back(2);
myIndices.push_back(1);
myIndices.push_back(0);
//Top
myIndices.push_back(7);
myIndices.push_back(6);
myIndices.push_back(4);
myIndices.push_back(6);
myIndices.push_back(5);
myIndices.push_back(4);
//Left
myIndices.push_back(0);
myIndices.push_back(4);
myIndices.push_back(1);
myIndices.push_back(4);
myIndices.push_back(5);
myIndices.push_back(1);
//Right
myIndices.push_back(2);
myIndices.push_back(6);
myIndices.push_back(3);
myIndices.push_back(6);
myIndices.push_back(7);
myIndices.push_back(3);
//Back
myIndices.push_back(6);
myIndices.push_back(1);
myIndices.push_back(5);
myIndices.push_back(6);
myIndices.push_back(2);
myIndices.push_back(1);
//Front
myIndices.push_back(0);
myIndices.push_back(7);
myIndices.push_back(4);
myIndices.push_back(0);
myIndices.push_back(3);
myIndices.push_back(7);
//Generate Texture Coordinates
//Bottom
myTexCoords.push_back(TexCoord(0.25, 0));
myTexCoords.push_back(TexCoord(0.25, 0.375));
myTexCoords.push_back(TexCoord(0.5, 0.375));
myTexCoords.push_back(TexCoord(0.5, 0));
//Top
myTexCoords.push_back(TexCoord(0.25, 1));
myTexCoords.push_back(TexCoord(0.25, 0.625));
myTexCoords.push_back(TexCoord(0.5, 0.625));
myTexCoords.push_back(TexCoord(0.5, 1));
//Left
myTexCoords.push_back(TexCoord(0, 0.625));
myTexCoords.push_back(TexCoord(0.25, 0.625));
myTexCoords.push_back(TexCoord(0.25, 0.375));
myTexCoords.push_back(TexCoord(0, 0.375));
//Right
myTexCoords.push_back(TexCoord(0.5, 0.625));
myTexCoords.push_back(TexCoord(0.75, 0.625));
myTexCoords.push_back(TexCoord(0.75, 0.375));
myTexCoords.push_back(TexCoord(0.5, 0.375));
//Back
myTexCoords.push_back(TexCoord(0.75, 0.625));
myTexCoords.push_back(TexCoord(1.0, 0.625));
myTexCoords.push_back(TexCoord(1.0, 0.375));
myTexCoords.push_back(TexCoord(0.75, 0.375));
const string vertexShader = (GLSLProgram::glsl130Supported()) ? VERTEX_SHADER_130 : VERTEX_SHADER_120;
const string fragmentShader = (GLSLProgram::glsl130Supported()) ? FRAGMENT_SHADER_130 : FRAGMENT_SHADER_120;
if (!myTexture.load(SKY_TEXTURE))
{
std::cerr << "Could not load the particle texture" << std::endl;
return false;
}
glGenTextures(1, &myTexID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, myTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myTexture.getWidth(),
myTexture.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
myTexture.getImageData());
m_shaderProgram = std::auto_ptr<GLSLProgram>(new GLSLProgram(vertexShader, fragmentShader));
if (!m_shaderProgram->initialize())
{
std::cerr << "Could not load the skybox shaders" << std::endl;
return false;
}
m_shaderProgram->bindAttrib(0, "a_Vertex");
m_shaderProgram->bindAttrib(1, "a_Color");
m_shaderProgram->bindAttrib(2, "a_TexCoord0");
m_shaderProgram->linkProgram();
m_shaderProgram->sendUniform("texture0", 0);
glGenBuffers(1, &myVertexBuffer); //Generate a buffer for the vertices
glBindBuffer(GL_ARRAY_BUFFER, myVertexBuffer); //Bind the vertex buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * myVertices.size(), &myVertices[0], GL_STATIC_DRAW); //Send the data to OpenGL
glGenBuffers(1, &myColorBuffer);
glBindBuffer(GL_ARRAY_BUFFER, myColorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Color) * myColors.size(), &myColors[0], GL_STATIC_DRAW); //Send the data to OpenGL
glGenBuffers(1, &myTexCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, myTexCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(TexCoord) * myTexCoords.size(), &myTexCoords[0], GL_STATIC_DRAW); //Send the data to OpenGL
glGenBuffers(1, &myIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, myIndexBuffer); //Bind the vertex buffer
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * myIndices.size(), &myIndices[0], GL_STATIC_DRAW); //Send the data to OpenGL
return true;
}
void Skybox::onRender() const
{
//glDisable(GL_DEPTH_TEST);
//glPushMatrix();
glTranslatef(0.0f, 0.0f, 0.0f);
static float modelviewMatrix[16];
static float projectionMatrix[16];
m_shaderProgram->bindShader();
//Get the current matrices from OpenGL
glGetFloatv(GL_MODELVIEW_MATRIX, modelviewMatrix);
glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix);
//Enable the point sprite and the automatic texture coordinates
glBindTexture(GL_TEXTURE_2D, myTexID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
//Send the modelview and projection matrices to the shaders
m_shaderProgram->sendUniform4x4("modelview_matrix", modelviewMatrix);
m_shaderProgram->sendUniform4x4("projection_matrix", projectionMatrix);
m_shaderProgram->sendUniform("texture0", 0);
//Bind the vertex array and set the vertex pointer to point at it
glBindBuffer(GL_ARRAY_BUFFER, myVertexBuffer);
glVertexAttribPointer((GLint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, myColorBuffer);
glVertexAttribPointer((GLint)1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, myTexCoordBuffer);
glVertexAttribPointer((GLint)2, 2, GL_FLOAT, GL_FALSE, 0, 0);
//Bind the index array
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, myIndexBuffer);
//glDrawElements(GL_TRIANGLES, myIndices.size(), GL_UNSIGNED_INT, 0);
glPointSize(5.0f);
glDrawArrays(GL_TRIANGLES, 0, myIndices.size());
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
// glPopMatrix();
}
Your drawing code is very confused. There are a lot of things wrong with it, but they all stem from one fundamental misunderstanding.
You have 4 colors, 8 positions, and 24 texture coordinates. OpenGL doesn't know what to do with that.
OpenGL can only work with unique groups of vertex attributes. So if you have positions and texture coordinates, the lengths of these arrays must be equal. For each texture coordinate, there is a specific position that pairs with it, and vice-versa. And for each position, there is a specific color that pairs with it, and vice-versa.
Yes, a cube only has 8 different positions. But you're not drawing 8 vertices (a vertex is a collection of attribute data, which may include a position, if you so desire). You are drawing 12 triangles. Each triangle has 3 vertices.
Triangles can only share vertices if they share all of the vertex attributes of that vertex. So one face of a cube can be represented by the four corner vertices, since the two triangles (along the main diagonal) share the same position/color/texCoord for the two shared vertices.
But the triangles of different faces can only share vertex data if they use the same position/color/texCoord triplet. In most cases, yours don't.
Therefore, you must replicate your positions and colors alot. Each face of the cube will have separate positions and colors (even though they may use the same values from others).
Also, consider avoiding the texture coordinate altogether. You're obviously using a shader, so just put your environment in a cubemap. You can pass "normals" at the 8 corners that point outwards from the cubemap. Interpolate them as standard and then access the cubemap texture with them.

drawing interleaved VBO with glDrawArrays

I'm currently using glDrawElements to render using multiple VBOs (vertex, color, texture, and index). I've found that very few vertices are shared, so I'd like to switch to glDrawArrays, and a single interleaved VBO.
I've been unable to find a clear example of 1) creating an interleaved VBO and adding a quad or tri to it (vert, color, texture), and 2) doing whatever is needed to draw it using glDrawArrays. What is the code for these two steps?
Off the top of my head:
//init
glBindBuffer(GL_ARRAY_BUFFER, new_array);
GLfloat data[] = {
0.f, 0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 100.f, 0.f, 1.f,
0.f, 100.f, 100.f, 1.f, 1.f,
0.f, 100.f, 100.f, 1.f, 1.f,
0.f, 100.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 0.f, 0.f,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
// draw
glBindBuffer(GL_ARRAY_BUFFER, new_array);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 5*sizeof(GLfloat), NULL);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 5*sizeof(GLfloat), ((char*)NULL)+3*sizeof(GLfloat) );
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
There is nothing particularly magic in this code. Just watch how:
The data from the data array gets loaded: as is, all contiguous
the stride for the various attributes is set to 5*sizeof(GLfloat), as this is what is in data: 3 floats for position and 2 for texcoord. Side note, you usually want this to be a power of 2, unlike here.
the offset is computed from the start of the array. so since we store vertex first, the offset for vertex is 0. texcoord is stored after 3 floats of position data, so its offset is 3*sizeof(GLfloat).
I did not include color in there for a reason: they typically are stored as UNORMs, which makes for a messier initialization code. You need to store both GLfloat and GLubyte in the same memory chunk. At that point, structs can help if you want to do it in code, but it largely depends on where your data is ultimately coming from.

Vertex Buffer Object not drawing in SDL window

I'm just using the opengl SDL template with Xcode, and everything runs fine. I removed the Atlantis code, and changed the main extension to .mm, then added some testing code to drawGL. Drawing a simple triangle (using immediate mode) at this point inside drawGL gives me a white triangle, but when I add the code to draw using a vertex buffer object, i just get a black window.
Here is my VBO drawing code:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity();
GLuint buffer;
float vertices[] = {
0.0f, 1.0f, 0.0f,
-1.0f,-1.0f, 0.0f,
1.0f,-1.0f, 0.0f
};
// VBO doesn't work :(
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 9, vertices, GL_STATIC_DRAW);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);
Your glVertexPointer() call looks suspect for VBO usage. I think you need a BUFFER_OFFSET construct instead of the vertices pointer.