Unable to draw multiple objects using VAOs and EBOs (openGL) - c++

I was experimenting with using Vertex Array Objects and Element Buffer Objects. I managed to draw the letter "H" on my screen using a single VAO with an EBO bound since all my vertices and indices were in one array. I wanted to split each rectangle into a different object though and give them a different color, but only one of them is drawing on the screen.
Here's the code:
#include <glew.h>
#include <glfw3.h>
#include <iostream>
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"FragColor = vec4(0.2f, 0.6f, 0.7f, 1.0f);\n"
"}\0";
const char* fragmentShaderSource2 = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"FragColor = vec4(0.7f, 0.4f, 0.3f, 1.0f);\n"
"}\0";
const char* fragmentShaderSource3 = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"FragColor = vec4(0.1f, 0.2f, 0.6f, 1.0f);\n"
"}\0";
int main(void)
{
GLFWwindow* window;
glewInit();
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
std::cout << "Error!" << std::endl;
float vertices[] = {
0.2f, 0.7f, 0.0f,
0.3f, 0.7f, 0.0f,
0.3f, 0.2f, 0.0f,
0.2f, 0.2f, 0.0f
};
float vertices2[] = {
0.6f, 0.7f, 0.0f,
0.7f, 0.7f, 0.0f,
0.7f, 0.2f, 0.0f,
0.6f, 0.2f, 0.0f
};
float vertices3[] = {
0.3f, 0.4f, 0.0f,
0.3f, 0.5f, 0.0f,
0.6f, 0.5f, 0.0f,
0.6f, 0.4f, 0.0f
};
unsigned int indices[] = {
1, 0, 2,
2, 3, 0
};
unsigned int indices2[] = {
5, 4, 6,
6, 7, 4
};
unsigned int indices3[] = {
8, 9, 11,
11, 10, 9
};
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
unsigned int fragmentShader2 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader2, 1, &fragmentShaderSource2, NULL);
glCompileShader(fragmentShader2);
unsigned int fragmentShader3 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader3, 1, &fragmentShaderSource3, NULL);
glCompileShader(fragmentShader3);
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
unsigned int shaderProgram2;
shaderProgram2 = glCreateProgram();
unsigned int shaderProgram3;
shaderProgram3 = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glAttachShader(shaderProgram2, fragmentShader2);
glAttachShader(shaderProgram2, vertexShader);
glLinkProgram(shaderProgram2);
glAttachShader(shaderProgram3, fragmentShader3);
glAttachShader(shaderProgram3, vertexShader);
glLinkProgram(shaderProgram3);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteShader(fragmentShader2);
glDeleteShader(fragmentShader3);
unsigned int VBOs[3], VAOs[3], EBOs[3];
glGenVertexArrays(3, VAOs);
glGenBuffers(3, VBOs);
glGenBuffers(3, EBOs);
glBindVertexArray(VAOs[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOs[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(VAOs[1]);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOs[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(VAOs[2]);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices3), vertices3, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOs[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices3), indices3, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAOs[0]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glUseProgram(shaderProgram2);
glBindVertexArray(VAOs[1]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glUseProgram(shaderProgram3);
glBindVertexArray(VAOs[2]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glDeleteVertexArrays(3, VAOs);
glDeleteBuffers(3, VBOs);
glDeleteBuffers(3, EBOs);
glfwTerminate();
return 0;
}

You'll have here:
float vertices2[] = {
0.6f, 0.7f, 0.0f,
0.7f, 0.7f, 0.0f,
0.7f, 0.2f, 0.0f,
0.6f, 0.2f, 0.0f
};
together with:
unsigned int indices2[] = {
5, 4, 6,
6, 7, 4
};
That does not make sense. You only copy 4 vertices to your VBO[1], and you set the attrib pointer to offset 0 in that buffer, so the only valid indices are 0,1,2 and 3.
Your indices are set as if all your vertices were in a single big array as before, and actually, that would be a much better strategy: Keep one big vertex array, and one big element indices array, and one VAO, and just draw individual parts of that array by changing the indices argument in the glDrawElements() call, like this:
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // first 6 indices
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)(6*sizeof(GLuint))); // second 6 indices
// ...
Also not that using 3 different shaders here is very inefficient. It woold be best if you just added the color as another attribute, and use a single draw call (implying a single shader, single VAO) for everything.

Related

Trying to draw a square with two triangles in OpenGL but I'm only getting a black screen

As the title says, I'm trying to draw a square from two triangles for class. I've tried everything I can think of but I cannot figure out why it just displays a black screen. Here is my code so far. I have the project and libraries set up correctly. I've looked over it a dozen times and can't seem to find the issue.
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
static unsigned int CompileShader(unsigned int type, const std::string& source) {
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
return id;
}
static unsigned int CreateShader(const std::string& vrtxShader, const std::string& fragShader) {
unsigned int program = glCreateProgram();
//compile shaders
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vrtxShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragShader);
//attach shaders to program
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
//delete shaders
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
//sets up GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Module 3", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
//Initialize GLEW
if (glewInit() != GLEW_OK)
std::cout << "Error!" << std::endl;
float vertPositions[] = {
// index 0
-0.5f, -0.5f, 0.0f,
1.0f, 0.0f, 0.0f,
// index 1
-5.0f, 0.5f, 0.0f,
0.0f, 0.0f, 1.0f,
// index 2
0.5f, -0.5f, 0.0f,
0.0f, 1.0f, 0.0f,
// index 3
0.5f, 0.5f, 0.0f,
1.0f, 0.0f, 0.0f,
};
float indices[] = { 0, 1, 2, 1, 2, 3 };
//creates vertex buffer object
unsigned int vbo;
unsigned int ebo;
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertPositions), vertPositions, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//attribute location and layout to gpu.
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)(3 * sizeof(float)));
// Vertex Shader Program Source Code
std::string vertexShaderSource = "#version 440 core\n"
"layout (location = 0) in vec4 aPos;\n"
"layout (location = 1) in vec4 aColor;\n"
"out vec4 colorOut;\n"
"void main()\n"
"{\n"
" gl_Position = aPos;\n"
" colorOut = aColor;\n"
"}\n\0";
// Fragment Shader Program Source Code
std::string fragmentShaderSource = "#version 440 core\n"
"in vec4 colorOut;\n"
"out vec4 fragColor;\n"
"void main()\n"
"{\n"
"fragColor = colorOut;\n"
"}\n\0";
unsigned int shader = CreateShader(vertexShaderSource, fragmentShaderSource);
glUseProgram(shader);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
//draw the shapes
glDrawElements(GL_TRIANGLES, 6, GL_FLOAT, nullptr);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Why using a core profile OpenGL Context (GLFW_OPENGL_CORE_PROFILE) it is mandatory to create a Vertex Array Object. There is no default VAO when using a core profile.
e.g.:
unsigned int vao, vbo, ebo;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertPositions), vertPositions, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)(3 * sizeof(float)));
Further more the type of the indices must be integral. e.g:
unsigned int indices[] = { 0, 1, 2, 1, 2, 3 };
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);

Different fragment shader colors

I want to draw different figures with different colors using shaders.
I tried using uniform variables and using vertex attributes of the meshes to separate Vertex Buffer Objects but when I run the program only the second color is used and the first figure isn't shown at all. Im not sure if it's an issue with how I bind the shaders or with the way I use uniform variables. Thanks in advance.
Here is the code:
#include <GL/glew.h>
#include <GL/glut.h>
#include <stdio.h>
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char* fragmentShaderSource = "#version 330 core\n"
"in vec4 color;\n"
"out vec4 FragColor;\n"
"uniform vec3 figColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(figColor, 0.0f);\n"
"}\n\0";
// Set of vertices that draw the different figures:
float vertices1[] = {
-0.8f, 0.6f, 0.0f,
-0.8f, 0.4f, 0.0f,
-0.83f, 0.44f, 0.0f,
-0.87f, 0.51f, 0.0f,
-0.9f, 0.57f, 0.0f,
-0.93f, 0.63f, 0.0f,
-0.95f, 0.69f, 0.0f,
-0.97f, 0.75f, 0.0f,
-0.98f, 0.8f, 0.0f,
-0.91f, 0.8f, 0.0f,
-0.85f, 0.79f, 0.0f,
-0.8f, 0.77f, 0.0f,
};
float vertices2[] = {
-0.8f, -0.15f, 0.0f,
-1.0f, 0.0f, 0.0f,
-0.95f, 0.0f, 0.0f,
-0.86f, -0.01f, 0.0f,
-0.81f, -0.02f, 0.0f,
-0.75f, -0.03f, 0.0f,
};
GLuint vertexShader;
GLuint fragmentShader;
GLuint shaderProgram;
void display(void) {
// Background color.
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
GLint uniform = glGetUniformLocation(shaderProgram, "figColor");
glUniform3f(uniform, 1.0f, 0.0f, 0.0f);
glDrawArrays(GL_TRIANGLE_FAN, 0, 12);
glUniform3f(uniform, 0.0f, 0.749f, 1.0f);
glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
glUseProgram(0);
glFlush();
}
// Main.
int main(int argc, char** argv) {
glutInit(&argc, argv);
// Color mode.
glutInitDisplayMode(GLUT_RGBA);
// Window size.
glutInitWindowSize(500, 500);
// Title.
glutCreateWindow("Tarea 3: Figura con curvas");
GLenum err = glewInit();
if (err != GLEW_OK) {
printf("glewInit failed: %s", glewGetErrorString(err));
exit(1);
}
// Compile vertex shader.
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// Check for vertex shader compilation errors.
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n");
}
// Compile fragment shader.
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// Check for fragment shader compile errors.
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n");
}
// Link and delete shaders.
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//Separating the Vertex Buffer Objects.
GLuint VBOs[2];
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1), vertices1, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);
// Specify a VertexArrayObject for each mesh.
GLuint VAOs[2];
glGenVertexArrays(2, VAOs);
glBindVertexArray(VAOs[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(VAOs[1]);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Bind the VAO before the draw call.
glBindVertexArray(VAOs[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, 12);
glBindVertexArray(VAOs[1]);
glDrawArrays(GL_TRIANGLE_FAN, 0, 24);
// Displaying the figures.
glutDisplayFunc(display);
glutMainLoop();
}
You missed to generate the vertex buffer object names:
//Separating the Vertex Buffer Objects.
GLuint VBOs[2];
glGenBuffers(2, VBOs); <----
You have to bind the vertex array before drawing the mesh in the main loop:
GLuint VAOs[2];
void display(void) {
// Background color.
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
GLint uniform = glGetUniformLocation(shaderProgram, "figColor");
glUniform3f(uniform, 1.0f, 0.0f, 0.0f);
glBindVertexArray(VAOs[0]); // <---
glDrawArrays(GL_TRIANGLE_FAN, 0, 12);
glUniform3f(uniform, 0.0f, 0.749f, 1.0f);
glBindVertexArray(VAOs[1]); // <----
glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
glUseProgram(0);
glFlush();
}
int main(int argc, char** argv) {
// [...]
// Specify a VertexArrayObject for each mesh.
// GLuint VAOs[2]; <---- DELETE
glGenVertexArrays(2, VAOs);
// [...]
// DELETE
/*
// Bind the VAO before the draw call.
glBindVertexArray(VAOs[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, 12);
glBindVertexArray(VAOs[1]);
glDrawArrays(GL_TRIANGLE_FAN, 0, 24);
*/
// [...]

Don't get OpenGL output when using glVertexAttribFormat

I'm trying to use glVertexAttribFormat and glVertexAttribBinding to create two triangles, but it doesn't work. I followed the description of how to do this in the question here (Render one VAO containing two VBOs). I don't really knnow what to try. I am new to OpenGL and all descriptions of glVertexAttribFormat appear to assume you already know OpenGL.
This is my code:
#include <glad/glad.h>
#include <glfw/glfw3.h>
#include <iostream>
void adjustViewportToWindowSize(GLFWwindow* window, int width, int height);
void checkEsc(GLFWwindow* window);
int main(void)
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(800, 600, "Tab name", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glViewport(0, 0, 800, 600); //size of GL rendering window.
glfwSetFramebufferSizeCallback(window, adjustViewportToWindowSize);
const char* vertexShaderSource = "#version 430 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char* fragmentShaderSource = "#version 430 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\0";
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
//Attaching shaders to program
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
//Can delete shader objects after they are linked
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
float triangleVertices1[] = {
-0.50f, 0.0f, 0.0f,
-0.25f, 0.5f, 0.0f,
0.00f, 0.0f, 0.0f
};
float triangleVertices2[] = {
0.0f, 0.0f, 0.0f,
0.25f, 0.5f, 0.0f,
0.5f, 0.0f, 0.0f
};
unsigned int aVBO[2], VAO2;
glGenVertexArrays(1, &VAO2);
glBindVertexArray(VAO2);
glVertexAttribFormat(0, 3, GL_FLOAT, GL_FALSE, 0); //format setup without a buffer
glVertexAttribBinding(0, 0);
glBindVertexArray(0);
//Bind Buffers to data next
glGenBuffers(2, aVBO);
glBindBuffer(GL_ARRAY_BUFFER, aVBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices1), triangleVertices1, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, aVBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices2), triangleVertices2, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
while (!glfwWindowShouldClose(window))
{
checkEsc(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO2);
glBindVertexBuffer(0, aVBO[0], 0, 3*sizeof(float));
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexBuffer(0, aVBO[1], 0, 3*sizeof(float));
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
//Clear up
glDeleteVertexArrays(1, &VAO2);
glDeleteBuffers(1, aVBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
void adjustViewportToWindowSize(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void checkEsc(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
Can also be accessed on github: https://github.com/Ritzerk/OpenGLSelfStudy
In addition to setting up the buffer bindings, you also have to enable the vertex attribute in the shader. To do so, you have to call glEnableVertexAttribArray during VAO setup:
glBindVertexArray(VAO2);
glVertexAttribFormat(0, 3, GL_FLOAT, GL_FALSE, 0);
glVertexAttribBinding(0, 0);
//Enable input in shader
glEnableVertexAttribArray(0);
glBindVertexArray(0);

glMapBufferRange gives me an access violation

I just got a laptop with an Intel HD4000 "graphics card" and my code that works on my stationary computer with an HD6950 gives me an access violation. I changed from version 4.4 to 4.0 since the HD4000 only supports up to 4.0.
Looking at the OpenGL wiki for it says it can only guarantee alignment from version 4.2 and up, so I'm thinking that may be the issue but I'm not sure and I don't know how to deal with it
I took this code from open.gl and modified it to use GLFW to test with:
// Link statically with GLEW
#define GLEW_STATIC
// Headers
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <windows.h>
// Shader sources
const GLchar* vertexSource =
"#version 150 core\n"
"in vec2 position;"
"in vec3 color;"
"out vec3 Color;"
"void main() {"
" Color = color;"
" gl_Position = vec4(position, 0.0, 1.0);"
"}";
const GLchar* fragmentSource =
"#version 150 core\n"
"in vec3 Color;"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(Color, 1.0);"
"}";
int main()
{
if(!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = nullptr;
window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL);
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = GL_TRUE;
int glewRes = glewInit();
if(glewRes != GLEW_OK)
{
glfwTerminate();
OutputDebugStringA(reinterpret_cast<const char*>(glewGetErrorString(glewRes)));
OutputDebugStringA("\n");
return -2;
}
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers(1, &vbo);
GLfloat vertices[] = {
-0.5f, 0.5f, 1.0f, 0.0f, 0.0f, // Top-left
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // Top-right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Bottom-right
-0.5f, -0.5f, 1.0f, 1.0f, 1.0f // Bottom-left
};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), NULL, GL_DYNAMIC_DRAW);
GLfloat* mappedData = static_cast<GLfloat*>(glMapBufferRange(GL_ARRAY_BUFFER, 0, sizeof(vertices), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT));
GLenum error = glGetError();
error = glGetError();
error = glGetError();
if(mappedData == NULL)
{
glfwTerminate();
return -3;
}
for(int i = 0; i < ARRAYSIZE(vertices); i++)
{
mappedData[i] = vertices[i];
}
glUnmapBuffer(GL_ARRAY_BUFFER);
// Create an element array
GLuint ebo;
glGenBuffers(1, &ebo);
GLuint elements[] = {
0, 1, 2,
2, 3, 0
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
while(!glfwWindowShouldClose(window))
{
glfwPollEvents();
// Clear the screen to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Draw a rectangle from the 2 triangles using 6 indices
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// Swap buffers
glfwSwapBuffers(window);
}
glDeleteProgram(shaderProgram);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
glDeleteBuffers(1, &ebo);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
glfwTerminate();
}
For some reason whenever I use glMapBufferRange it gives me an access violation at mappedData[i] = vertices[i];.
If I simply use glBufferData or glMapBuffer it works fine
Windows just installed 38 updates and now it works

OpenGL ES2 coloured triangle

I am trying to make basic triangle in opengl es 2, but whatever I do, it just doesn't seem to be working.. All I get is a white triangle. However, I think there might be a problem
when linking the program (that's I have disabled return from linking checking "if", otherwise it won't run at all). Also, when I run with the console, I get in the output "error: 1281". My code:
int loadShader(int type, char * shaderCode)
{
int length = strlen(shaderCode);
int shader = glCreateShader(type);
glShaderSource(shader, 1, (const char **) &shaderCode, NULL);
glCompileShader(shader);
return shader;
}
// Initializes the application data
int Init(void)
{
// Vertex shaders
char * vertexShaderCode =
"attribute vec4 vPosition; \n"
"void main() { \n"
" gl_Position = vPosition; \n"
"} \n";
char * fragmentShaderCode =
"precision mediump float; \n"
"void main() { \n"
" gl_FragColor = vec4(0.5, 0.5, 0.5, 1.0);\n"
"} \n";
GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexShaderCode);
GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentShaderCode);
GLint linked;
program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glBindAttribLocation(program, 0, "vPosition");
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if(!linked)
{
GLint infoLen = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = (char *) malloc(sizeof(char) * infoLen);
glGetProgramInfoLog(program, infoLen, NULL, infoLog);
free(infoLog);
}
glDeleteProgram(program);
//return 0;
}
// Basic GL setup
glClearColor (0.0, 0.0, 0.0, 1.0);
return GL_TRUE;
}
// Main-loop workhorse function for displaying the object
void Display(void)
{
// Clear the screen
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 1.0);
GLfloat vertices[] = {
-0.5f, 0.0f, -1.0f,
0.0f, 1.0f, -1.0f,
0.5f, 0.0f, -1.0f,
};
GLfloat colors[] = {
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
};
glUseProgram(program);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
enable the vertex attrib array first and then pass the pointers...
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
Also you are sending colors in the "1" attrib array but there is no such attrib in the shader.