Related
I'm trying to create a Mesh class that can generate a model for me and then calling that model in the createTriangle function. However, whenever I try creating the meshObj1 and meshObj2 and then pushing it to the meshVector, it does not want to render? Why is this happening?
Mesh.h
#ifndef MESH_H
#define MESH_H
#include "GL/glew.h"
class Mesh {
public:
Mesh();
~Mesh();
void createMesh(GLfloat *vertices, unsigned int *indices, unsigned int numOfVertices, unsigned int numOfIndices);
void renderMesh();
void clearMesh();
private:
GLuint VAO, VBO, IBO;
GLsizei indexCount;
};
#endif
Mesh.cpp
#include "Mesh.h"
Mesh::Mesh() {
VAO = 0;
VBO = 0;
IBO = 0;
indexCount = 0;
}
Mesh::~Mesh() {
clearMesh();
}
void Mesh::createMesh(GLfloat* vertices, unsigned int* indices, unsigned int numOfVertices, unsigned int numOfIndices) {
indexCount = numOfIndices;
//Binding
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
//Information
//VBO Information
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0] * numOfVertices), vertices, GL_STATIC_DRAW);
//IBO Information
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * numOfIndices, indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
//Unbinding
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Mesh::renderMesh() {
//Binding
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
//Rendering
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
//Unbinding
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Mesh::clearMesh() {
if (VAO != 0) {
glDeleteVertexArrays(1, &VAO);
VAO = 0;
}
if (VBO != 0) {
glDeleteBuffers(1, &VBO);
VBO = 0;
}
if (IBO != 0) {
glDeleteBuffers(1, &IBO);
IBO = 0;
}
indexCount = 0;
}
Main.cpp
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include <iostream>
#include <vector>
#include <memory>
#include "Mesh.h"
//Window dimensions
const GLint SCREEN_WIDTH = 1280, SCREEN_HEIGHT = 900;
GLuint shader, uniformModel, uniformProjection;
bool isMovingLeft = true;
float triOffset = 0.f;
float triMaxOffset = 0.7;
float triIncrement = 0.005;
std::vector<Mesh*> meshVector;
//Vertex shader
static const char* vShader = " \n\
#version 460 \n\
\n\
layout(location = 0) in vec3 pos; \n\
\n\
out vec4 vColor; \n\
\n\
uniform mat4 model; \n\
uniform mat4 projection; \n\
\n\
void main() { \n\
gl_Position = projection * model * vec4(pos, 1.0); \n\
vColor = vec4(clamp(pos, 0.f, 1.f), 1.f); \n\
}; \n\
";
//Fragment shader
static const char* fShader = " \n\
#version 460 \n\
\n\
in vec4 vColor; \n\
\n\
out vec4 color; \n\
\n\
void main() { \n\
color = vColor; \n\
}; \n\
";
void createTriangle() {
unsigned int indices[] = {
0, 3, 1,
1, 3, 2,
2, 3, 0,
0, 1, 2
};
//Points of the triangle
GLfloat vertices[] = {
-1.f, -1.f, 0.f,
0.f, -1.f, 1.f,
1.f, -1.f, 0.f,
0.f, 1.f, 0.f
};
Mesh* meshObj1 = new Mesh();
meshObj1->createMesh(vertices, indices, 12, 12);
meshVector.push_back(meshObj1);
Mesh* meshObj2 = new Mesh();
meshObj2->createMesh(vertices, indices, 12, 12);
meshVector.push_back(meshObj2);
}
void addShader(GLuint theProgram, const char* shaderCode, GLenum shaderType) {
GLuint theShader = glCreateShader(shaderType);
const GLchar* theCode[1];
theCode[0] = shaderCode;
GLint codeLength[1];
codeLength[0] = strlen(shaderCode);
glShaderSource(theShader, 1, theCode, codeLength);
glCompileShader(theShader);
//Getting error information for linking
GLint result = 0;
GLchar eLog[1024] = { 0 };
glGetShaderiv(theShader, GL_COMPILE_STATUS, &result);
if (result != GL_TRUE) {
glGetShaderInfoLog(theShader, sizeof(eLog), NULL, eLog);
std::cout << "Error compiling the " << shaderType << ' ' << eLog << '\n';
}
glAttachShader(theProgram, theShader);
}
void compileShaders() {
shader = glCreateProgram();
if (shader != GL_TRUE) {
std::cout << "Shader program error!\n";
}
//Adding shaders
addShader(shader, vShader, GL_VERTEX_SHADER);
addShader(shader, fShader, GL_FRAGMENT_SHADER);
//Getting error information for linking
GLint result = 0;
GLchar eLog[1024] = { 0 };
//Linking shader
glLinkProgram(shader);
//Shader linking status
glGetProgramiv(shader, GL_LINK_STATUS, &result);
if (result != GL_TRUE) {
glGetProgramInfoLog(shader, sizeof(eLog), NULL, eLog);
std::cout << "Error linking program! " << eLog << '\n';
}
//Gets shader ID and then binds it with the variable inside shader
uniformModel = glGetUniformLocation(shader, "model");
uniformProjection = glGetUniformLocation(shader, "projection");
}
int main() {
//Initialize GLFW
if (glfwInit() != GLFW_TRUE) {
std::cout << "GLFW init failed\n";
glfwTerminate();
}
//Setup GLFW window properties
//OpenGL version
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); //Large version
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4); //Small version
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //Detects any old OpenGL code, this will throw an error
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //Allows forward compatibility (between differnt OS)
//Creating window
GLFWwindow* window;
window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "OpenGL Test Window", NULL, NULL);
glfwSetWindowPos(window, 250, 100);
if (window == NULL) {
std::cout << "GLFW window creation failed!\n";
glfwTerminate();
}
//Get buffer size information
int bufferWidth, bufferHeight;
glfwGetFramebufferSize(window, &bufferWidth, &bufferHeight);
//Set context for GLEW to use (can change between which window)
glfwMakeContextCurrent(window);
//Allow modern extension features
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cout << "Glew init failed!\n";
glfwDestroyWindow(window);
glfwTerminate();
}
glEnable(GL_DEPTH_TEST);
//Setup viewport size
glViewport(0, 0, bufferWidth, bufferHeight);
createTriangle();
compileShaders();
glm::mat4 projection = glm::perspective(45.f, (GLfloat)bufferWidth / (GLfloat)bufferHeight, 0.1f, 100.f);
//Main game loop
while (!glfwWindowShouldClose(window)) {
//Get + Handle user input events
glfwPollEvents();
//Left-Right
if (isMovingLeft) {
triOffset += triIncrement;
}
else {
triOffset -= triIncrement;
}
if (abs(triOffset) >= triMaxOffset) {
isMovingLeft = !isMovingLeft;
}
//Clear window
glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader);
//Matrix 4x4
glm::mat4 model(1.f);
model = glm::translate(model, glm::vec3(triOffset, 0.f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(uniformProjection, 1, GL_FALSE, glm::value_ptr(projection));
meshVector[0]->renderMesh();
model = glm::mat4(1.f);
model = glm::translate(model, glm::vec3(-triOffset, 1.f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4, 1.f));
meshVector[1]->renderMesh();
glUseProgram(0);
glfwSwapBuffers(window);
}
}
I expect two pyramids to form with color.
The GL_ELEMENT_ARRAY_BUFFER target binding is stored in the Vertex Array Object. See Index buffers.
This means, that the instruction
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
breaks the former binding of IBO to the vertex array object VAO. Remove this instruction from your code, to solve the issue.
Note, GL_ARRAY_BUFFER and the GL_ELEMENT_ARRAY_BUFFER behave differently. The current GL_ARRAY_BUFFER binding is a global state, but the GL_ELEMENT_ARRAY_BUFFER binding is stated in the current Vertex Array Object.
Also the GL_ARRAY_BUFFER is stated in the state vector of the VAO, but this happens when glVertexAttribPointer is called. When glVertexAttribPointer is called, then the buffer which is currently bound to the target GL_ARRAY_BUFFER is associated to the vertex attribute with the specified index.
That causes the difference in the behavior of GL_ELEMENT_ARRAY_BUFFER and GL_ARRAY_BUFFER. A VAO can only refer to 1 index (element) buffer, but it can refer to multiple array buffers. Each attribute (index) can be associated to a different buffer.
Before you render the 2nd mesh, you've the set the corresponding model matrix to the default uniform block of the installed program:
glUseProgram(shader);
glUniformMatrix4fv(uniformProjection, 1, GL_FALSE, glm::value_ptr(projection));
glm::mat4 model(1.f);
model = glm::translate(model, glm::vec3(triOffset, 0.f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
meshVector[0]->renderMesh();
model = glm::mat4(1.f);
model = glm::translate(model, glm::vec3(-triOffset, 1.f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4, 1.f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model)); // <---
meshVector[1]->renderMesh();
I am trying to make my first cube using open gl. Unfortunately I stucked in easy rotation. This is how it should look:
Instead I am getting those weird, do not even know how to called it : https://youtu.be/0A5Hi-8bygE
Vertex shader
#version 330 core
layout (location = 0) in vec2 a_position;
layout (location = 1) in vec2 a_uv;
layout (location = 2) in vec4 a_color;
out vec2 v_fragmentPosition;
out vec2 v_fragmentUV;
out vec4 v_fragmentColor;
uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;
void main()
{
gl_Position = u_projection * u_view * u_model * vec4(a_position, 0.0, 1.0);
v_fragmentPosition = a_position;
v_fragmentUV = vec2(a_uv.x, 1 - a_uv.y);
v_fragmentColor = a_color;
}
Fragment
#version 330 core
out vec4 outColor;
in vec2 v_fragmentPosition;
in vec2 v_fragmentUV;
in vec4 v_fragmentColor;
void main()
{
outColor = v_fragmentColor;
}
Main
#include <glad.h>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>
#include <iostream>
#include "Mesh.h"
#include "Shader.h"
int main(int argc,char*args[])
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_Window* window = SDL_CreateWindow("fdas", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL);
SDL_GLContext context = SDL_GL_CreateContext(window);
gladLoadGLLoader(SDL_GL_GetProcAddress);
glEnable(GL_DEPTH_TEST);
Shader shader;
std::string vertex = shader.LoadFromFile("vertex.shader");
std::string fragment = shader.LoadFromFile("fragment.shader");
shader.CreateShaderProgram(vertex.c_str(), fragment.c_str());
shader.useProgram();
Mesh mesh;
mesh.CreateVertexArray();
bool quit = false;
SDL_Event event;
while (!quit)
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
exit(0);
}
}
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 model;
model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 view;
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
glm::mat4 projection;
projection = glm::perspective(glm::radians(45.0f), 1280 / 720.0f, 0.1f, 100.0f);
GLint u_model = shader.GetUniformLocation("u_model");
GLint u_view = shader.GetUniformLocation("u_view");
GLint u_projection = shader.GetUniformLocation("u_projection");
glUniformMatrix4fv(u_model, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(u_view, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(u_projection, 1, GL_FALSE, glm::value_ptr(projection));
Rect destRect = { -0.5f, -0.5f, 1.0f, 1.0f };
Rect uvRect = { 0.0f, 0.0f, 1.0f, 1.0f };
ColorRGBA color = { 255, 255, 128, 255 };
mesh.CreateQuad(destRect, uvRect, color);
mesh.Draw(0);
SDL_GL_SwapWindow(window);
}
return 0;
}
Mesh
void Mesh::CreateVertexArray()
{
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, uv));
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, color));
glBindVertexArray(0);
}
void Mesh::CreateQuad(Rect destRect, Rect uvRect, ColorRGBA color)
{
vertex[0].color = color; // topleft
vertex[0].setPosition(destRect.x, destRect.y + destRect.h);
vertex[0].setUV(uvRect.x, uvRect.y + uvRect.h);
vertex[1].color = color;
vertex[1].setPosition(destRect.x, destRect.y); // bottom left
vertex[1].setUV(uvRect.x, uvRect.y);
vertex[2].color = color;
vertex[2].setPosition(destRect.x + destRect.w, destRect.y); // bottom right
vertex[2].setUV(uvRect.x + uvRect.w, uvRect.y);
vertex[3].color = color;
vertex[3].setPosition(destRect.x + destRect.w, destRect.y + destRect.h); // top right
vertex[3].setUV(uvRect.x + uvRect.w, uvRect.y + uvRect.h);
GLuint indices[6] = {
0, 1, 2,
2, 3, 0
};
glBindVertexArray(vao);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(vertex), NULL, GL_STATIC_DRAW); // orphan the buffer
glBufferSubData(GL_ARRAY_BUFFER, 0, 6 * sizeof(vertex), vertex);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), NULL, GL_STATIC_DRAW); // orphan the buffer
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, 6 * sizeof(GLuint), indices);
glBindVertexArray(0);
}
void Mesh::Draw(GLuint texture)
{
glBindVertexArray(vao);
// glEnable(GL_CULL_FACE);
// glCullFace(GL_FRONT);
//glFrontFace(GL_CW);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
glBindVertexArray(0);
}
Vertex
struct Rect {
float x, y;
float w, h;
};
struct Position {
float x, y;
};
struct UV {
float u, v;
};
struct ColorRGBA {
GLubyte r, g, b, a;
};
class Vertex
{
public:
Vertex();
~Vertex();
void setPosition(float x, float y);
void setcolor(ColorRGBA color);
void setUV(float u, float v);
UV uv;
ColorRGBA color;
Position position;
};
I will not show shader class, because there is all good with it.
I know it, because I did an experiment.
I created a new uniform in fragment class called u_expColor and set outColor = u_expColor and a quad's color changed.
Also I created uniform vec4 u_expPos in vertex shader and said gl_Position = e_expPos and it created quad with no problems.
Only if I want to create/multiply position by mvp in vertex shader there is a problem like on the you tube video.
How to fix it?
I have fixed it thanks http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/#putting-it-all-together. I saw he had
glm::mat4 model = glm::mat4(1.0f)
and it was all I had to do.
I've encountered following problem:
I got this vertex shader:
#version 410 core
in vec3 vertex_position;
out vec3 color;
void main()
{
color = vec3(0.0, 0.0, 0.0);
gl_Position = vec4(vertex_position, 1.0);
}
And following fragment shader:
#version 410 core
in vec3 color;
out vec4 frag_color;
void main()
{
frag_color = vec4(color, 1.0);
}
I want to pass the color vector from the vertex shader to the fragent shader, however, nothing is showing up on the screen. When I set the frag_color within the fragment shader like: frag_color = vec4(0.0, 0.0, 0.0, 1.0); it works. Thus, something with passing the value between the 2 stages must be wrong.
This is my shader code:
void Shader::CreateShaders(std::string filePathVert, std::string filePathFrag)
{
// setup shaders
std::string vertex_shader_source = LoadSourceFile(filePathVert);
std::string fragment_shader_source = LoadSourceFile(filePathFrag);
const GLchar* vs_source = vertex_shader_source.c_str();
const GLchar* fs_source = fragment_shader_source.c_str();
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vs_source, NULL);
glCompileShader(vs);
CheckShaderError(vs, GL_COMPILE_STATUS, false, "Error: Shader compilation failed: ");
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fs_source, NULL);
glCompileShader(fs);
CheckShaderError(fs, GL_COMPILE_STATUS, false, "Error: Shader compilation failed: ");
this->shader_program = glCreateProgram();
glAttachShader(this->shader_program, fs);
glAttachShader(this->shader_program, vs);
glLinkProgram(this->shader_program);
CheckValidationError(this->shader_program);
glDeleteShader(vs);
glDeleteShader(fs);
}
void Shader::Bind()
{
glUseProgram(this->shader_program);
}
void Shader::Destroy()
{
glDeleteProgram(this->shader_program);
}
static std::string LoadSourceFile(std::string filePath)
{
std::ifstream ifs(filePath);
std::string content( (std::istreambuf_iterator<char>(ifs) ),
(std::istreambuf_iterator<char>() ) );
if(content.empty())
{
std::cerr << "source file was empty or not correctly loaded\n";
}
return content;
}
And my drawing code:
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo_positions);
glVertexAttribPointer(glGetAttribLocation(shader.GetProgramID(), "vertex_position"), 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, vbo_colors);
glVertexAttribPointer(glGetAttribLocation(shader.GetProgramID(), "vertex_color"), 3, GL_FLOAT, GL_FALSE, 0, NULL);
while(!glfwWindowShouldClose(display.GetWindowID())) {
display.UpdateFPSCounter();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.Bind();
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
update();
glfwSwapBuffers(display.GetWindowID());
display.CheckWindowShouldClose();
}
Does anyone see what I'm doing wrong?
Thanks in advance!
vertex_color doesn't match the variable in your vertex shader.
The problem is here:
glEnableVertexAttribArray(0);
glVertexAttribPointer(glGetAttribLocation(shader.GetProgramID(), "vertex_position"),
3, GL_FLOAT, GL_FALSE, 0, NULL);
Both of these calls take the attribute location as the first argument. While the location for the position may happen to be 0, this is not guaranteed, and you should pass the same argument to both these calls:
GLuint posLoc = glGetAttribLocation(shader.GetProgramID(), "vertex_position");
glEnableVertexAttribArray(posLoc);
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, NULL);
I'm learning OpenGL and I set up a Mesh class to render my shapes. Drawing only works without
glBindVertexArray(0);
at the end so I'm guessing I messed up something but I can't figure it out.
Here is the code: main.cpp
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <iostream>
#include "mesh.h"
#define WIDTH 1280
#define HEIGHT 720
// Vertex shader
const char* vs = "\n\
#version 330 \n\
layout (location = 0) in vec2 position; \n\
layout (location = 1) in vec3 color; \n\
out vec3 Color; \n\
\n\
void main() { \n\
Color = color; \n\
gl_Position = vec4(position, 0.0, 1.0); \n\
} \n\
\n\
";
// Fragment shader
const char* fs = "\n\
#version 330 \n\
in vec3 Color; \n\
out vec4 fragColor; \n\
\n\
void main() { \n\
fragColor = vec4(Color, 1.0); \n\
} \n\
";
bool checkShader(GLuint shader) {
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
char buffer[512];
glGetShaderInfoLog(shader, 512, NULL, buffer);
std::cout << "Error compiling shader:" << buffer << std::endl;
return false;
}
return true;
}
bool compileShaders() {
// compile the vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vs, NULL);
glCompileShader(vertexShader);
if (!checkShader(vertexShader))
return false;
// compile the fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fs, NULL);
glCompileShader(fragmentShader);
if (!checkShader(fragmentShader))
return false;
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
return true;
}
int main() {
bool success = true;
bool running = true;
SDL_Window* window;
SDL_GLContext context;
// Initialize SDL/Glew
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "Video initialization failed:" << SDL_GetError() << std::endl;
success = false;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
window = SDL_CreateWindow("Game Title", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN |
SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS);
context = SDL_GL_CreateContext(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cerr << "Problem initializing GLEW." << std::endl;
success = false;
}
SDL_Event e;
// Mesh setup
float vertices[] = { 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f,-0.5f, 0.0f, 1.0f, 0.0f,
-0.5f,-0.5f, 0.0f, 0.0f, 1.0f };
float vertices2[] = { -1.0f,-1.0f, 1.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-0.0f, 0.0f, 0.0f, 0.0f, 1.0f };
GLuint elements[] = { 0, 1, 2 };
Mesh triangle(vertices, elements, sizeof(vertices), sizeof(elements));
Mesh triangle2(vertices2, elements, sizeof(vertices2), sizeof(elements));
if (!compileShaders())
success = false;
if (!success) {
std::cerr << "A problem ocurred during initialization, will exit." << std::endl;
exit(1);
}
while (running) {
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT)
running = false;
if (e.type == SDL_KEYDOWN)
if (e.key.keysym.sym == SDLK_ESCAPE)
running = false;
}
glClearColor(0.0f, 1.0f, 0.5f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
triangle.draw();
triangle2.draw();
SDL_GL_SwapWindow(window);
SDL_Delay(1);
}
SDL_GL_DeleteContext(context);
SDL_Quit();
return 0;
}
mesh.h
#ifndef MESH_H
#define MESH_H
#include <GL/glew.h>
class Mesh {
private:
GLuint IBO;
GLuint VBO;
GLuint VAO;
float* vertices;
GLuint* indices;
int sizeVertices;
int sizeIndices;
public:
Mesh(float* vertices, GLuint* indices, int sizeVertices, int sizeIndices);
void draw();
};
#endif //MESH_H
mesh.cpp
#include "mesh.h"
#define POSITION 0
#define COLOR 1
Mesh::Mesh(float* vertices, GLuint* indices, int sizeVertices, int sizeIndices) {
this->vertices = vertices;
this->indices = indices;
this->sizeVertices = sizeVertices;
this->sizeIndices = sizeIndices;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &IBO);
}
void Mesh::draw() {
glEnableVertexAttribArray(POSITION);
glVertexAttribPointer(POSITION, 2, GL_FLOAT, GL_FALSE,5*sizeof(float), 0);
glEnableVertexAttribArray(COLOR);
glVertexAttribPointer(COLOR, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)(2*sizeof(float)));
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeVertices, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeIndices, indices, GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
//glBindVertexArray(0); If I uncomment this, the mesh is not displayed
}
The calls to glVertexAttribPointer pointer refer to the VAO and VBO bound at the time of calling. In your code you're calling glVertexAttribPointer before the VAO and the VBO are bound. So the first iteration round those calls will fail. Without unbinding the VAO/VBO the next iteration the VAO/VBO state will happen (by circumstance) to the more or less right; actually you've swapped the VAO/VBO between the two triangle instances.
Update – fixed code
Mesh::Mesh(float* vertices, GLuint* indices, int sizeVertices, int sizeIndices) {
this->vertices = vertices;
this->indices = indices;
this->sizeVertices = sizeVertices;
this->sizeIndices = sizeIndices;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &IBO);
/* VAOs contain ARRAY_BUFFERS */
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeVertices, vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(POSITION);
glVertexAttribPointer(POSITION, 2, GL_FLOAT, GL_FALSE,5*sizeof(float), 0);
glEnableVertexAttribArray(COLOR);
glVertexAttribPointer(COLOR, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)(2*sizeof(float)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(VAO);
/* ELEMENT_ARRAY_BUFFERS are not contained in VAOs */
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeIndices, indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void Mesh::draw() {
/* VAOs keep the glVertexAttribPointer bindings,
* so it's sufficient to just bind the VAO;
* no need for binding the VBOs (as long as you don't
want to change the pointers). */
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
/* Need to bind the ELEMENT_ARRAY_BUFFER though */
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
I am using uniform blocks and have encountered a problem when creating uniform buffers for them. The problem is that when generating a buffer in a certain place (as show in the 1st code sample, about 2/3 way down), a segfault occurs during glClear();
Interestingly the order of the glGenBuffers matters, as the segfault will not occur if I swap 2 calls to the function.
program.cpp:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <helpful.hpp> //Contains text read and shader loading functions
using namespace std;
int main(int args, char* argv[])
{
//## Create context ##//
unsigned int a;
glfwInit();
glfwWindowHint(GLFW_DEPTH_BITS,16);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
GLFWwindow* window = glfwCreateWindow(1368, 768, "", NULL, NULL);
glfwMakeContextCurrent(window);
glewExperimental=GL_TRUE;
glewInit();
cout << "GL context created" << endl;
a = glGetError();
if (a!=0)cout << "Context error" << a << endl;
glViewport(0, 0, 1368, 768);
//## Setup shader ##//
const char* vsText = textFileRead("shaders/testShader/shader.vert"); //Reads a text file
const char* fsText = textFileRead("shaders/testShader/shader.frag");
string vsource = "#version 140 \n";
string fsource = "#version 140 \n";
vsource += vsText;
fsource += fsText;
array<GLuint, 3> out = loadShaders("testShader",vsource,fsource);
GLuint shader_id = out[0];
GLuint shader_vp = out[1];
GLuint shader_fp = out[2];
glBindAttribLocation(shader_id, 0, "in_Vertex");
glBindFragDataLocation(shader_id, 0, "out_Scene");
glAttachShader(shader_id, shader_fp);
glAttachShader(shader_id, shader_vp);
glLinkProgram(shader_id);
glUseProgram(shader_id);
cout << "s : " << shader_id << endl;
GLuint globalIndex = glGetUniformBlockIndex(shader_id, "GlobalSettings");
glUniformBlockBinding(shader_id, globalIndex, 1);
GLuint modelIndex = glGetUniformBlockIndex(shader_id, "ModelSettings");
glUniformBlockBinding(shader_id, modelIndex, 2);
//## Fill Uniform block buffers ##//
float f[16] = {
1.f, .2f, 1.f, .2f,
1.f, .2f, 1.f, .2f,
1.f, .2f, 1.f, .2f,
1.f, .2f, 1.f, .6f,
};
GLuint subo; //"GlobalSettings" block
glGenBuffers(1, &subo);
glBindBuffer(GL_UNIFORM_BUFFER, subo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * 16, f, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, subo, 1);
//This is what causes the error
//Comment out these 2 lines and it works
//Or swap this block with the one below
GLuint b;
glGenBuffers(1, &b);
GLuint mubo; //"ModelSettings" block
glGenBuffers(1, &mubo);
glBindBuffer(GL_UNIFORM_BUFFER, mubo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * 16, f, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, mubo, 2);
//## Create a simple quad to draw on screen ##//
GLuint vao;
GLuint vbo;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
std::vector<glm::vec3> v;
v.push_back(glm::vec3(-1.,-1.,0));
v.push_back(glm::vec3(1.,-1.,0));
v.push_back(glm::vec3(1.,1.,0));
v.push_back(glm::vec3(-1.,-1.,0));
v.push_back(glm::vec3(1.,1.,0));
v.push_back(glm::vec3(-1.,1.,0));
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
int numVertices = v.size();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(GLfloat) * 3, v.data(), GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
glfwPollEvents();
glClearColor(0.2,0.2,0.2,1);
while (true)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glUseProgram(shader_id);
glDrawArrays(GL_TRIANGLES, 0, numVertices);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
}
Here are the shaders:
Vertex:
layout( std140 ) uniform GlobalSettings {
mat4 projectionMatrix;
};
layout( std140 ) uniform ModelSettings {
mat4 MVMatrix;
};
in vec3 in_Vertex;
in vec3 in_Normal;
out vec4 eyePosition;
out vec4 screenPosition;
out vec3 pass_Normal;
void main(void)
{
vec4 vertex=vec4(in_Vertex, 1.0);
eyePosition = MVMatrix * vertex;
screenPosition = gl_Position = vertex;
pass_Normal = in_Normal;
}
Fragment
layout( std140 ) uniform GlobalSettings {
mat4 projectionMatrix;
};
layout( std140 ) uniform ModelSettings {
mat4 MVMatrix;
};
in vec4 screenPosition;
in vec4 eyePosition;
in vec3 pass_Normal;
out vec4 out_Scene;
void main(void)
{
float d = dot(normalize(pass_Normal), vec3(0,0,-1));
float a = 1;
//if(d>0)a=1;
out_Scene = vec4(MVMatrix[3][1],MVMatrix[3][2],MVMatrix[3][3],a);
}
The shader loading function can be found here http://pastebin.com/XqewS28W in needed.
The problem is that the parameters in glBindBufferBase are the wrong way around, thus the index argument was being given a buffer name and vice versa. It only worked by coincidence as the buffer names happened to be the same as the indices, and generating in the extra buffer resulted in the indices no longer matching the buffers.