Related
I have a script that I am unable to make fully 3D. So far on ortho the background shows up only. In perspective, almost nothing shows up but when I move the camera it does change color.
projection = glm::perspective(glm::radians(44.0f), static_cast<GLfloat>(Width) / static_cast<GLfloat>(Height), 0.1f, 100.0f);
projection = glm::ortho(0.0f, static_cast<GLfloat>(Width), static_cast<GLfloat>(Height), 0.0f, -1.0f, 1.0f);
See below for images:
Image 1:
3D version - Ortho
Image 2:
3D version - Ortho
Image 3:
2D version - Stable and works perfectly
Here is my code that creates and renders sprites:
#ifndef SPRITE_H
#define SPRITE_H
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "ShaderClass.h"
#include "TextureClass.h"
class Sprite
{
public:
Shader shader;
// Set up Vertex Array Object && Vertex Buffer Object
GLuint VAO,
VBO;
// Constructor
Sprite(Shader &shader){ this->shader = shader; setBuffers(); }
// Deconstructor
~Sprite(){ glDeleteVertexArrays(1, &VAO); }
// Initializes and configures the buffers and vertex attributes
void setBuffers()
{
// Define vertices for the sprite
GLfloat vertices[] = {
// x y z u v
0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
//
// OpenGL buffers
// Initialization code using Vertex Array Object (VAO) (done once (unless the object frequently changes))
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// Copy our vertices array in a buffer for OpenGL to use
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Bind Vertex Array Object
glBindVertexArray(VAO);
//Attributes
glEnableVertexAttribArray(0); // location = 0
glVertexAttribPointer(
0, // location = 0
3, // 3 components (x, y, z)
GL_FLOAT, GL_FALSE,
5 * sizeof(GLfloat), // stride: 5 * float (x, y, z, u, v)
(GLvoid*)0); // offset: 0
glEnableVertexAttribArray(1); // location = 1
glVertexAttribPointer(
1, // location = 1
2, // 2 components (u, v)
GL_FLOAT, GL_FALSE,
5 * sizeof(GLfloat), // stride: 5 * float (x, y, z, u, v)
(GLvoid*)(3 * sizeof(GLfloat))); // offset: 3 * float (x, y, z)
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//Unbind the VAO
glBindVertexArray(0);
}
// Renders the sprite
void DrawSprite(Texture &texture, glm::vec2 position, glm::vec2 size = glm::vec2(10, 10), GLfloat rotate = 0.0f, glm::vec3 colour = glm::vec3(1.0f))
{
// Apply the shader
this->shader.Use();
// Transform the object
glm::mat4 transformObject;
transformObject = glm::translate(transformObject, glm::vec3(position, 0.0f));
transformObject = glm::translate(transformObject, glm::vec3(0.5f * size.x, 0.5f * size.y, 0.0f));
transformObject = glm::rotate(transformObject, rotate, glm::vec3(0.0f, 0.0f, 1.0f));
transformObject = glm::translate(transformObject, glm::vec3(-0.5f * size.x, -0.5f * size.y, 0.0f));
transformObject = glm::scale(transformObject, glm::vec3(size, 1.0f));
this->shader.SetVector3f("spriteColour", colour);
this->shader.SetMatrix4("transformObject", transformObject);
glActiveTexture(GL_TEXTURE0);
// Bind the appropriate texture to *this* model
texture.Bind();
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 36 * 5);
glBindVertexArray(0);
}
};
#endif
These are the shaders that I am using:
Vertex shader:
#version 440 core
layout (location = 0) in vec3 Position;
layout (location = 1) in vec2 texCoord;
out vec2 TexCoords;
uniform mat4 transformObject;
uniform mat4 view;
uniform mat4 projection;
void main()
{
TexCoords = vec2(texCoord.x, texCoord.y);
gl_Position = projection * view * transformObject * vec4(Position.x, Position.y, Position.z, 1.0);
}
Fragment shader:
#version 440 core
in vec2 TexCoords;
out vec4 colour;
uniform sampler2D tex;
uniform vec3 spriteColour;
void main()
{
colour = vec4(spriteColour, 1.0) * texture(tex, TexCoords);
}
I have a code that initially had one shader (ourShader), one VAO and one VBO. It would render a scene with a textured cube and its reflection on the ground using Stencil testing. Now, I wanted to add a framebuffer for post-processing so I needed a second shader. I added a second shader (screenShader) and a second VBO. I don't use them in my drawing yet, but the simple fact that I'm adding them makes my code render a black, red triangle instead of the usual scene.
My code looks like this :
Shader ourShader(string("core.vs"), string("core.frag")); // shader class creating a shader program from vertex shader and fragment shader source files.
Shader screenShader(string("core2.vs"), string("core2.frag"));
// Setting up attributes, VAO, VBO
GLuint VAO;
array<GLuint, 2> VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(2, &VBO[0]);
glBindVertexArray(VAO);
// Data for first shader and first VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(verticesCube), verticesCube, GL_STATIC_DRAW);
GLint posAttribLoc = glGetAttribLocation(ourShader.Program, "position");
glVertexAttribPointer(posAttribLoc, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); // specify (to the active VAO) how to retrieve the values for the attribute "position" from the data stored ("vertices" here) on the active VBO (GPU)
glEnableVertexAttribArray(posAttribLoc); // enable attribute for rendering
GLint colAttribLoc = glGetAttribLocation(ourShader.Program, "color");
glVertexAttribPointer(colAttribLoc, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(colAttribLoc);
GLint texAttribLoc = glGetAttribLocation(ourShader.Program, "texCoord");
glVertexAttribPointer(texAttribLoc, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(texAttribLoc);
// ##### PART GIVING A WEIRD RESULT #####
// Data for second shader and second VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(verticesRectangle), verticesRectangle, GL_STATIC_DRAW);
GLint posAttribLoc2 = glGetAttribLocation(screenShader.Program, "position");
glVertexAttribPointer(posAttribLoc2, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0); // specify (to the active VAO) how to retrieve the values for the attribute "position" from the data stored ("vertices" here) on the active VBO (GPU)
glEnableVertexAttribArray(posAttribLoc2); // enable attribute for rendering
GLint texAttribLoc2 = glGetAttribLocation(screenShader.Program, "texCoord");
glVertexAttribPointer(texAttribLoc2, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat)));
glEnableVertexAttribArray(texAttribLoc2);
// ##### END #####
// Setting up texture that will be used for the first shader
GLuint texture;
int width, height;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture); // makes "texture" the current texture and attaches it to texture unit 0
// Set the wrapping
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set the filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
unsigned char* image = SOIL_load_image("res/images/image1.jpg", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
// Unbind VBO, texture before main loop
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glfwSwapInterval(1);
glfwSetKeyCallback(window, Input::keyCallback); // Input is a singleton class handling inputs. It works well.
glfwSetCursorPosCallback(window, Input::mouseCallback);
glfwSetScrollCallback(window, Input::scrollCallback);
while (glfwWindowShouldClose(window) == GLFW_FALSE) {
// MAIN LOOP
// ...
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(2, &VBO[0]);
The mainloop is not important I think. What I want to say is that if I remove the few lines dealing with the the second VBO, then the scene renders well. Otherwise, I get a weird-colored triangle.
And my two shaders use those source files for their respective vertex shader and fragment shader. By the way, I get no compilation errors from my shaders.
core.vs :
#version 330 core
in vec3 position;
in vec2 texCoord;
in vec3 color;
out vec2 TexCoord;
out vec3 Color;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection*view*model*vec4(position, 1.0);
TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
Color = color;
}
core.frag :
#version 330 core
in vec2 TexCoord;
in vec3 Color;
out vec4 outColor;
uniform sampler2D ourTexture0;
void main()
{
outColor = vec4(Color, 1)*texture(ourTexture0, TexCoord);
}
core2.vs :
#version 330 core
in vec2 position;
in vec2 texCoord;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(position, 0.0, 1.0);
TexCoord = texCoord;
}
core2.frag :
#version 330 core
in vec2 TexCoord;
out vec4 outColor;
uniform sampler2D texFramebuffer;
void main()
{
outColor = texture(texFramebuffer, TexCoord);
}
The vertices look like this (but only the way to read them is important) :
GLfloat verticesRectangle[] = {
// position // texture coordinates
-0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 1.0f,
0.5f, 0.5f, 1.0f, 1.0f
};
GLfloat verticesCube[] = {
// position // color // texture coordinates
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // reflection surface // not a part of the cube itself
-1.0f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
1.0f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-1.0f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
1.0f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f
};
I've already looked at Binding a second vertex buffer seems to spoil my first vertex buffer, OpenGL OES ios 5.1 but the person had this problem because he didn't use his VAO correctly.
Most probably two of your attribute locations have the same value. Since you use just one VAO, you override some of the bindings. The correct way of using multiple independent geometries is to use on VAO per geometry.
The correct code has to look somehow like this:
glBindVertexArray(vao1);
glBindBuffer(VBO[0])
glVertexAttribPointer...
glEnableVertexAttribArray...
//Setup all attributes for first VBO
glBindVertexArray(vao2);
glBindBuffer(VBO[1])
glVertexAttribPointer...
glEnableVertexAttribArray...
//Setup all attributes for second VBO
When rendering do the following:
glBindVertexArray(vao1);
glDraw*... //Draw VAO1
glBindVertexArray(vao2);
glDraw*.... //Draw VAO2
I am trying to program some game with OpenGL and read a whole bunch of tutorials. Unfortunately I got a small problem who just interrupts my progress.
I created a "Mesh" class where I handover an array of GLfloats. These floats are included by an VAO and VBO.
As long as I create the array inside the constructor (with the whole initialization-functions) it works fine. But if I want to handover the array as an argument OpenGL just won't draw. Did I forget something?
Here is my main code:
Mesh.cpp
Mesh::Mesh(GLfloat* vertices)
{
glGenVertexArrays(1, &m_vertexArray);
glBindVertexArray(m_vertexArray);
glGenBuffers(1, &m_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindVertexArray(0);
}
Mesh::~Mesh()
{
glDeleteVertexArrays(1, &m_vertexArray);
}
void Mesh::draw()
{
glBindVertexArray(m_vertexArray);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
main.cpp
[...]
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
-0.5f, 0.0f, 0.0f
};
Mesh mesh(vertices);
while (!mainWindow->isClosed())
{
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
shaders->bind();
// here main functions:
mesh.draw();
mainWindow->update();
}
I handover an array of GLfloats
No, you do not "handover" an array of anything. You passed a pointer. Pointers and arrays are different things in C++. Most importantly, arrays can "decay" into pointers (that's what allows you to pass them to functions that take pointers), but when they do, all sizing information is lost.
sizeof(vertices) is the size of a GLfloat*. In all likelihood, that's either 4 or 8. It is most assuredly not the size of the array you had in the caller of the function.
The preferred method for handling this would be to pass the pointer and a size to that function. However, sizeof(vertices) will be the number of bytes in the array, not the number of array elements.
One way to handle this would be to get a std::vector rather than an array, through C++11:
std::vector<GLfloat> vertices = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
-0.5f, 0.0f, 0.0f
};
Mesh mesh(vertices.data(), vertices.size());
Alternately, you can calculate the size with some clever macros:
#define ARRAY_COUNT(arr) ( sizeof(arr) / sizeof(arr[0]))
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
-0.5f, 0.0f, 0.0f
};
Mesh mesh(vertices, ARRAY_COUNT(vertices));
Or, if you want to use cleverer C++11 features:
template<typename T, size_t N>
constexpr size_t array_count(T (&arr)[N]) {return N;}
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
-0.5f, 0.0f, 0.0f
};
Mesh mesh(vertices, array_count(vertices));
Or you can just skip the middle-man and employ the C++ Core Guidelines support library class span:
Mesh::Mesh(gsl::span<GLfloat> vertices)
{
glGenVertexArrays(1, &m_vertexArray);
glBindVertexArray(m_vertexArray);
glGenBuffers(1, &m_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size_bytes(), vertices.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindVertexArray(0);
}
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
-0.5f, 0.0f, 0.0f
};
Mesh mesh(vertices);
I'm new to OpenGL and theres a small project I'm working on. A part of this project is create a grid which allows for some sections of the grid to have different colors.
E.g. The entire grid is green but a block on the grid is lit red and maybe another one yellow.
What I have done to draw this grid is with GL_TRIANGLE_STRIP while using indicies. After that stage, I have also included colors in the same vertex data array. But the output isn't how i want it to be.
Firstly there was an interpolation which i tried to remove by adding the 'flat' flag for the color. But there seem to be a overlapping problem. Which resulted this picture.
Is there anyway to create a grid. Where a block of the grid can be of a different color than the grid.
Update
Here is my code for GL_TRIANGLES
short* Grid::Indicies()
{
const int X_GRID_SIZE = X_GRID_SIZE_;
const int Y_GRID_SIZE = Y_GRID_SIZE_;
const int INDICIES_SIZE = (((X_GRID_SIZE * 4) + ((X_GRID_SIZE_ - 3) * 2)) * Y_GRID_SIZE);
short* indicies = new short[INDICIES_SIZE];
int index = 0;
for (size_t y = 0; y < Y_GRID_SIZE_; y++)
{
// Current, Down, Right, Down
indicies[index++] = (short)(y * X_GRID_SIZE_);
indicies[index++] = (short)((y + 1) * X_GRID_SIZE_);
indicies[index++] = (short)((y * X_GRID_SIZE_) + 1);
indicies[index++] = (short)((y + 1) * X_GRID_SIZE_);
for (size_t x = 1; x < X_GRID_SIZE_ - 1; x++)
{
// Current, Down, Current, Down, Right, Down
for (size_t i = 0; i < 2; i++)
{
indicies[index++] = (short)((y * X_GRID_SIZE_) + x);
indicies[index++] = (short)(((y + 1) * X_GRID_SIZE_) + x);
}
indicies[index++] = (short)((y * X_GRID_SIZE_) + x + 1);
indicies[index++] = (short)(((y + 1) * X_GRID_SIZE_) + x);
}
// Current, Down
indicies[index++] = (short)(((y + 1) * X_GRID_SIZE_) - 1);
indicies[index++] = (short)(((y + 2) * X_GRID_SIZE_) - 1);
}
indicies_size_ = index;
return (indicies);
}
GLfloat vertices[] = {
// Position // Color
-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-1.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-1.0f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
1.0f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
};
GLuint v_buffer_object, v_array_object, e_buffer_object;
glGenVertexArrays(1, &v_array_object);
glGenBuffers(1, &v_buffer_object);
glGenBuffers(1, &e_buffer_object);
glBindVertexArray(v_array_object);
glBindBuffer(GL_ARRAY_BUFFER, v_buffer_object);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, e_buffer_object);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(grid.Indicies()) * grid.IndiciesSize(), grid.Indicies(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
Don't use GL_TRIANGLE_STRIP. Use GL_TRIANGLES and draw each block with 2 triangles and 4 vertices. Each vertex belongs to only 1 block. Thanks to that you don't have to use 'flat' flag, just change color for 4 vertices at once. You can try to draw each block separate, with space between each other. Then you can connect them by translating vertices and create the grid.
With GL_TRIANGLE_STRIP, flat shading will use the color from vertex i+2 to color traingle i (this is called the provoking vertex). This doesn't get you what you want. An easy option is to switch to GL_TRIANGLES, and make sure to specify your element indexes so that the same vertex is chosen third for both triangles in each quad (because the third vertex is the provoking vertex for triangles, by default). For example, suppose these are the vertexes:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
Let's look at one of the quads:
0---1
| |
4---5
Let's choose vertex 0 to hold the color for the entire quad. What we then do is make sure that both triangles include vertex 0, and that vertex 0 is last in both triangles.
0---1
| \ |
4---5
So our index array will be:
5 1 0 4 5 0 ...
This uses positive (anticlockwise) winding order.
I'm creating a glBufferData using an array explicitly defined of vertex coordinates and everything works fine. When using a non explicitly defined array the result is totally different althought I'm using the same coordinates values. The drawcall renders things in a different vertexs order.
The vertexs are a grid of triangles.
Code 1 that works fine:
this->graphics->createBuffers(1, vboIndexsID);
this->graphics->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, *vboIndexsID);
this->graphics->bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*numIndexs, ind, GL_STATIC_DRAW);
this->graphics->createBuffers(1, vboVertexsID);
this->graphics->bindBuffer(GL_ARRAY_BUFFER, *vboVertexsID);
this->graphics->bufferData(GL_ARRAY_BUFFER, 300, quad_verts2, GL_STATIC_DRAW);
where quad_verts2 is:
GLfloat quad_verts2[75] =
{
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 100.0f,
0.0f, 0.0f, 200.0f,
0.0f, 0.0f, 300.0f,
0.0f, 0.0f, 400.0f,
100.0f, 0.0f, 0.0f,
100.0f, 0.0f, 100.0f,
100.0f, 0.0f, 200.0f,
100.0f, 0.0f, 300.0f,
100.0f, 0.0f, 400.0f,
200.0f, 0.0f, 0.0f,
200.0f, 0.0f, 100.0f,
200.0f, 0.0f, 200.0f,
200.0f, 0.0f, 300.0f,
200.0f, 0.0f, 400.0f,
300.0f, 0.0f, 0.0f,
300.0f, 0.0f, 100.0f,
300.0f, 0.0f, 200.0f,
300.0f, 0.0f, 300.0f,
300.0f, 0.0f, 400.0f,
400.0f, 0.0f, 0.0f,
400.0f, 0.0f, 100.0f,
400.0f, 0.0f, 200.0f,
400.0f, 0.0f, 300.0f,
400.0f, 0.0f, 400.0f
};
Code 2 that doesn't work:
this->graphics->createBuffers(1, vboIndexsID);
this->graphics->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, *vboIndexsID);
this->graphics->bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*numIndexs, ind, GL_STATIC_DRAW);
this->graphics->createBuffers(1, vboVertexsID);
this->graphics->bindBuffer(GL_ARRAY_BUFFER, *vboVertexsID);
this->graphics->bufferData(GL_ARRAY_BUFFER, 300, list, GL_STATIC_DRAW);
exactly the same as before, but the list data instead of quad_vert2.
where list is:
GLfloat list[75];
int j = 0;
for(int i=0;i<numVertexs;++i) {
list[j] = v->coord.x;j++;
list[j] = v->coord.y;j++;
list[j] = v->coord.z;j++;
++v;
}
the data in v, is exactly the same values than in quad_vert2.
glGetError, after glBufferData is always 0.
If I get the data in the buffer using glGetBufferSubData the values are the same.
Ideas?
thanks in advance.
I would be suspect of the value of numVertexs, since your buffer data upload call does not actually use it. You should be uploading sizeof (GLfloat) * 3 * numVertexs bytes of data and not using the magic number 300. If you replace 300 with that expression in both situations chances are good that it will expose your real problem.
Thank you all,
the problem here was:
I was rendering two objects, with different number of vertexs. When rendering, I forgot to assign the indexs buffer correctly, and openGL was trying to draw the second object with the indexs of the first one.