Skybox in openGL using triangles - opengl

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.

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();
}

Draw 2D HUD elements over 3D rendered scene

I searched for this and only found a post from 2014 asking about a somewhat similar situation. However, as I couldn't understand what was done there, I'm asking again, specifically for my implementation, hoping this sheds some light on the topic in general as well. I am fairly new to c++ and openGL, so please be so kkind as to excuse stupid mistakes.
I'm trying to implement a simple 2D HUD for my 3D game. Now, my game is fully rendered, due to having a bloom effect in my game, I even rendered my game on a screen quad.
What I now want to do ist placing a HUD over this rendered scene, I, however, can't seem to do that.
My screen quad for the game is drawn like so:
unsigned int quadVAO = 0;
unsigned int quadVBO;
void renderQuad()
{
if (quadVAO == 0)
{
float quadVertices[] = {
// vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
// texCoords
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
// setup plane VAO
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
}
glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
What I tried to do, ist change my renderQuad method to a renderHUDquad one by basically just changing the dimensions of the quad to make it appear in the bottom left corner of the screen.
The code looks as follows:
unsigned int HUDquadVAO = 0;
unsigned int HUDquadVBO;
void renderHUDQuad()
{
if (HUDquadVAO == 0)
{
float HUDquadVertices[] = {
// vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
// texCoords
0.0f, 0.02f,
0.0f, 0.0f,
0.2f, 0.0f,
0.0f, 0.02f,
0.2f, 0.0f,
0.2f, 0.02f
};
// setup plane VAO
glGenVertexArrays(1, &HUDquadVAO);
glGenBuffers(1, &HUDquadVBO);
glBindVertexArray(HUDquadVAO);
glBindBuffer(GL_ARRAY_BUFFER, HUDquadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(HUDquadVertices), &HUDquadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
}
glBindVertexArray(HUDquadVAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
As this only needs to be a small green quad, i.e. a health bar for the player, I was thinking about just assigning it a green texture or sth..
However, when drawing my two quads like this:
// Third pass = Combined bloom pictures
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
bloomShader->use();
// Set uniform for multiple layout uniforms
bloomShader->setUniform("scene", 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, colorAndLightBuffers[0]);
// Set uniform for multiple layout uniforms
bloomShader->setUniform("bloomBlur", 1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, pingpongBuffer[horizontal == 0 ? 1 : 0]);
bloomShader->setUniform("bloom", bloom);
bloomShader->setUniform("exposure", exposure);
renderQuad();
renderHUDQuad();
// Swap buffers
glfwSwapBuffers(window);
I only get the HUD element without any of the stuff I drew before as if the rest of the screen was rendered black. I thought I could just add this to the old buffer, as there a way to do this?
You did screw up your GL state very badly:
void renderHUDQuad() {
if (HUDquadVAO == 0)
{
[...]
glGenVertexArrays(1, &quadVAO);
You actually use quadVAO in the rest of this function, so you overwrite your fullscreen quad by the smaller one, which means the rest of your scene will be scaled down to this quad from the next frame on...

Depth Buffer Not Working With Multiple Shader Programs

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.

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.

How to draw polygon with 3D points in modern openGL?

I know in 2.0- openGL we can draw a line simply like this.
glBegin(GL_LINES);
glVertex3f(20.0f,150.0f,0.0f);
glVertex3f(220.0f,150.0f,0.0f);
glVertex3f(200.0f,160.0f,0.0f);
glVertex3f(200.0f,160.0f,0.0f);
glEnd();
but how to do similar thing in modern openGL(3.0+)
I have read Drawing round points using modern OpenGL but the answer is not about certain point,since I want to draw polygon with points have certain coordinates,it's not quite helpful.
I use this code,but it shows nothing except a blue background.what do I missed?
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
static const GLfloat g_vertex_buffer_data[] = {
20.0f, 150.0f, 0.0f, 1.0f,
220.0f, 150.0f, 0.0f, 1.0f,
200.0f, 160.0f, 0.0f, 1.0f
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
do{
// Clear the screen
glClear( GL_COLOR_BUFFER_BIT );
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
4, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_LINES, 0, 2); // 3 indices starting at 0 -> 1 triangle
glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
1) You have to define an array of vertices, that contain the points of your polygon lines. Like in your example:
GLfloat vertices[] =
{
20.0f, 150.0f, 0.0f, 1.0f,
220.0f, 150.0f, 0.0f, 1.0f,
200.0f, 160.0f, 0.0f, 1.0f
};
2) You have to define and bind a Vertex Buffer Object (VBO) to be able to pass your vertices to the vertex shader. Like this:
// This is the identifier for your vertex buffer
GLuint vbo;
// This creates our identifier and puts it in vbo
glGenBuffers(1, &vbo);
// This binds our vbo
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// This hands the vertices into the vbo and to the rendering pipeline
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
3) Now we are ready to draw. Doing this:
// "Enable a port" to the shader pipeline
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// pass information about how vertex array is composed
glVertexAttribPointer(0, // same as in glEnableVertexAttribArray(0)
4, // # of coordinates that build a vertex
GL_FLOAT, // data type
GL_FALSE, // normalized?
0, // stride
(void*)0);// vbo offset
glDrawArrays(GL_LINES, 0, 2);
glDisableVertexAttribArray(0);
Step 1) and 2) can be done before rendering as initialization. Step 3) is done in your rendering loop. Also you'll need a vertex shader and a fragment shader to visualize the line with color.
If you don't know anything about these things and like to start with OpenGL 3, I'd suggest to start over with a tutorial like this:
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-1-opening-a-window/