Runs only once
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f
};
GLuint triangles[] = {0,1,2};
int lengthV = 3; //Number of vertices
int lenfthT = 1; //Number of triangles
glGenVertexArrays(1, &vaoID);
glBindVertexArray(vaoID);
glGenBuffers(vaoID, &verticesVBOID);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBOID);
glBufferData(GL_ARRAY_BUFFER, lengthV*sizeof(GLfloat)*3, vertices, GL_STATIC_DRAW);
glGenBuffers(vaoID, &trianglesVBOID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, trianglesVBOID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, lengthT*sizeof(GLuint)*3, triangles, GL_STATIC_DRAW);
Runs once per frame
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBOID);
glVertexAttribPointer(0, lengthV, GL_FLOAT, GL_FALSE, 0, nullptr);
glUseProgram(program);
//glDrawArrays(GL_TRIANGLES, 0, verticeCount*3);
glDrawElements(GL_TRIANGLES, lengthT,GL_UNSIGNED_INT, nullptr);
glDisableVertexAttribArray(0);
glfwSwapBuffers(window);
When I run this, this renders, which is right.
When I change the number of vertices to 4 to try and render a quad eventually.
int lengthV = 4;
This happens.
I don't understand why this is happening because I only changed the number of vertices.
Ive Tried to find an answer but I could not. I have looked at this persons problem and his code looks the same as mine after applying the answer.
No display from glDrawElements
You missinterpret the second parameter of glVertexAttribPointer.
The size parameter specifies the number of components of an attribute (which basically is the number of floats it gets). Since you still have a vec3 (3 floats) per vertex when drawing a quad, this number shouldn't be changed.
Related
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...
I am trying to draw shapes onto my application. I have added #include <glad/glad.h> into my code.
I set my vertex array, vertex buffer & index buffer as unsigned ints in my header file.
In my application.h file I added this:
unsigned int m_FCvertexArray; // Textured Phong VAO
unsigned int m_FCvertexBuffer;// Textured Phong VBO
unsigned int m_FCindexBuffer; // Index buffer for texture Phong cube
In my application.cpp in my constructor I added this:
Application::Application()
{
//------------- OPENGL VALUES -----------//
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
// Enabling backface culling to ensure triangle vertices are correct ordered (CCW)
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
////--------DRAW VERTICES---------//
float FCvertices[3 * 3] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
glGenVertexArrays(1, &m_FCvertexArray);
glBindVertexArray(m_FCvertexArray);
glCreateBuffers(1, &m_FCvertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_FCvertexBuffer);
//
//
glBufferData(GL_ARRAY_BUFFER, sizeof(FCvertices), FCvertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(sizeof(float) * 3));
////--------DRAW INDICES---------//
glCreateBuffers(1, &m_FCindexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_FCindexBuffer);
unsigned int indices[3] = {0, 1, 2};
glBufferData(GL_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
}
in my void Application::run() I added:
glUseProgram(m_FCprogram);
glBindVertexArray(m_FCvertexArray);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
now the problem is when I run the code, it gives me the error mentioned on the title:
Exception thrown at 0x000000005D78F420 (nvoglv64.dll) in Sandbox.exe: 0xC0000005: Access violation reading location 0x0000000000000000.
I've been trying ways to fix this but it seems not to work. and if i comment out glDrawElements, the code runs and works but no shapes are drawn (obvious).
When you create the index buffer, you need to use GL_ELEMENT_ARRAY_BUFFER instead of GL_ARRAY_BUFFER.
I was hoping to get some help on an OpenGL question concerning the creation and rendering of VAOs. The goal here is simply to take this:
glBegin(GL_TRIANGLES);
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glVertex3f(-0.5f, 0.5f, 0.0f);
glVertex3f(-0.5f, -0.5f, 0.0f);
glVertex3f(0.5f, -0.5f, 0.0f);
glVertex3f(-0.5f, 0.5f, 0.0f);
glVertex3f(0.5f, -0.5f, 0.0f);
glVertex3f(0.5f, 0.5f, 0.0f);
glEnd();
which renders a red square in the middle of the window, and turn it into a VAO with vertices, colors, and indices. Now, this is what I have so far as far as creating the VAO (sorry if this is a bit long for the code):
//initialize all data
verts_amt = 6;
Vertex* verts = (Vertex*)malloc(sizeof(Vertex) * verts_amt);
int* indices = (int*)malloc(sizeof(int) * verts_amt);
verts[0] = createVertex(-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
verts[1] = createVertex(-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
verts[2] = createVertex(0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
verts[3] = createVertex(-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
verts[4] = createVertex(0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
verts[5] = createVertex(0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
int i;
for(i = 0; i < 6; i ++)
indices[i] = i;
unsigned int vbo, ibo;
//create, bind, set data, and then unbind for the vbo and ibo
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, verts_amt * sizeof(Vertex), verts, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, verts_amt * sizeof(int), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//create vao, bind vao, bind and set data for vbo, bind ibo, then unbind vao
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), NULL);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, r));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBindVertexArray(0);
in case you are wondering, Vertex is just a struct made up of seven floats in the order x, y, z, r, g, b, a. After looking through similar questions on this topic, I'm still not seeing what I'm missing and/or not doing right, because when I render it with these simple lines:
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, verts_amt, GL_UNSIGNED_INT, NULL);
it renders just a competey white square. Keep in mind I'm not changing anything else about my rendering loop except of course getting rid of the Vertex3f, glBegin/glEnd, and Color4f calls. I should also mention that I'm not using a shader program, I'm not entirely sure if that changes anything drastically here. Any help on this would be much appreciated!
I should also mention that I'm not using a shader program.
You cannot use glVertexAttribPointer without a shader. These functions cannot interface with the OpenGL fixed function pipeline (FFP).
If you want to use the FFP and still use buffer objects, then you should use the appropriate functions. glVertexPointer (no "Attrib") and glColorPointer are the array equivalents to glVertex and glColor. These work with VAOs just fine.
So the only thing you need to change is your two glVertexAttribPointer calls to be glVertexPointer and glColorPointer (and of course adjusting the parameters accordingly).
Running a very simple draw a triangle example, I'm trying to find out which lines refer specifically to the VAO definition and which others can run apart.
Currently I'm using this code:
Buffer creation & filling:
TriangleVertices = new float[9]
{
0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
};
TriangleColors = new float[12]
{
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
};
glGenBuffers(1, &VertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(float), TriangleVertices, GL_STATIC_DRAW);
glGenBuffers(1, &ColorsBuffer);
glBindBuffer(GL_ARRAY_BUFFER, ColorsBuffer);
glBufferData(GL_ARRAY_BUFFER, 12*sizeof(float), TriangleColors, GL_STATIC_DRAW);
glGenVertexArrays(1, &VAOID);
VAO definition:
glBindVertexArray(VAOID);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, ColorsBuffer);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
Drawing Loop
glBindVertexArray(VAOID);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
The example runs fine if in the drawing loop I include the VAO definition each frame, but it doesn't work if I define the VAO only once before starting to draw so I guess the VAO definition lacks some code.
What am I missing?
EDIT: The code in the question was correct. The problem was coming from collision with other OpenGL calls I thought I wasn't running.
The code described below is just situational. As #derhass commented, there is no need to enable nor disable VertexAttribArray when making the draw call.
...
Old answer:
Unbindinding and disabling each element when not needed anymore fixed the problem, but I don't know if this solution can be widespread or it is specific to my environment only.
Buffer creation & filling:
TriangleVertices = new float[9]
{
0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
};
TriangleColors = new float[12]
{
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
};
glGenBuffers(1, &VertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(float), TriangleVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &ColorsBuffer);
glBindBuffer(GL_ARRAY_BUFFER, ColorsBuffer);
glBufferData(GL_ARRAY_BUFFER, 12*sizeof(float), TriangleColors, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenVertexArrays(1, &VAOID);
VAO definition:
glBindVertexArray(VAOID);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, ColorsBuffer);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
Drawing Loop
glBindVertexArray(VAOID);
glEnableVertexAttribArray(0);//not needed
glEnableVertexAttribArray(1);//not needed
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);//not needed
glDisableVertexAttribArray(1);//not needed
glBindVertexArray(0);
I began to learn OpenGL about a week ago and I now want to create a mesh class. The code I'm about to show gives me a black screen (that's the color I fill it with).
I basically stripped the code from my main function and placed it inside a class, it worked inside main.
mesh.cpp
#include "mesh.h"
mesh::mesh(std::vector<GLfloat> vertices, std::vector<GLuint> indices)
{
this->vertices = vertices;
this->indices = indices;
glGenVertexArrays(1, &vertexArrayObject);
glGenBuffers(1, &vertexBuffer);
glGenBuffers(1, &triangleBuffer);
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(GLfloat), this->vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangleBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->indices.size() * sizeof(GLuint), this->indices.data(), GL_STATIC_DRAW);
glBindVertexArray(0);
}
mesh::~mesh()
{
glDeleteBuffers(1, &triangleBuffer);
glDeleteBuffers(1, &vertexBuffer);
glDeleteVertexArrays(1, &vertexArrayObject);
}
void mesh::update(){
glBindVertexArray(vertexArrayObject);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
mesh.h
#ifndef MESH_H
#define MESH_H
#include <iostream>
#include <vector>
#include <GL/glew.h>
#include <glm/glm.hpp>
class mesh
{
public:
mesh(std::vector<GLfloat> vertices, std::vector<GLuint> triangles);
~mesh();
void update();
protected:
private:
GLuint vertexArrayObject, vertexBuffer, triangleBuffer;
std::vector<GLfloat> vertices;
std::vector<GLuint> indices;
};
#endif // MESH_H
According to this, this should be the correct way to do it (?).
BTW, all this code is a mashup from this and open.gl sites, here are the variables I pass into the constructor.
For the vertices:
std::vector<GLfloat> vertices = {
// Position Color Texcoords
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top-left
0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Top-right
0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Bottom-right
-0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f // Bottom-left
};
and the indices:
std::vector<GLuint> elements = {
0, 1, 2,
2, 3, 0
};
Also please note that I changed the code snippets according to Anton's suggestions, that didn't seem to work
You have two problems that immediately come to mind:
this->triangles.size() * sizeof(GLfloat)
This problem will not affect anything because GLfloat has the same size as GLuint, but if that was not a typo, it indicates to me you may be thinking about the index buffer wrong.
Make this triangles.size () * sizeof (GLuint) for consistency.
glDrawElements(GL_TRIANGLES, this->vertices.size(), GL_UNSIGNED_INT, 0);
You have two separate lists in your class, vertices and triangles, and this call only cares about the size of one of those.
triangles is an array of indices that makes a list of triangles (3 indices per-triangle).
When you draw your elements array, you pass the number of elements in that list, not the number of vertices in your mesh.
While not technically a problem, I think you use this-> a little bit too much when you write your code.
It is useful when you have variables at one scope that have the same name as members in your class (which one could argue builds a case for inadequately descriptive names), but completely unnecessary in functions like mesh::~mesh(). It makes your code harder to read (for me anyway) because the lines are much longer.
Following the theme of inadequately descriptive names, by calling your index array "triangles" you have inadvertently limited this mesh class to drawing triangles. That might be a good variable name for a specialized constructor that builds a triangle mesh, but not so much for a class member. If you use indices instead, that gets rid of the name collision and the need to qualify everything using this->.