Program Specific OpenGL Runtime Bug: Multiple Input Buffers For Skinned Animation - c++

The Problem:
It seems as if the second GLuint buffer is not being read in properly.
Update: So the problem must be when I try to input the data to the shader. I rewrote the code (the old code is still below) to use swizzling for the index parameter. That was the only way I could get it to work. I would like to use multiple glVertexAttribPointer's, but every time I try to gives me the same undefined results.
What I Am Trying To Do:
I'm testing out very simple skinned animation with a very simplified shader,
#version 330 core
in vec2 model;
in uint jointID;
const int MAX_JOINTS = 10;
uniform mat4 joints[MAX_JOINTS];
void main()
{
gl_Position = joints[jointID] * vec4(model, 0.0f, 1.0f);
}
I input some simple data,
const GLfloat vertices[] =
{
// upper arm
0.0f, 0.0f,
0.4f, 0.0f,
0.4f, 0.2f,
0.0f, 0.0f,
0.4f, 0.2f,
0.0f, 0.2f,
// lower arm
0.4f, 0.0f,
0.8f, 0.0f,
0.8f, 0.2f,
0.4f, 0.0f,
0.8f, 0.2f,
0.4f, 0.2f
};
const GLuint indices[] =
{
// upper arm
0,
1,
1,
0,
1,
0,
// lower arm
1,
1,
1,
1,
1,
1
};
(The first array containing the vertices and the second array containing the corresponding boneID's.) Oddly, the boneID's never seem too equal 1 because when I make the matrix at index 1 some really funky value, the vertices remain untransformed. This leads me to believe that it is a problem with the way I set up my glVertexAttribPointer's,
void SkinnedModel::draw()
{
shaderProgram.use();
glEnableVertexAttribArray(modelLoc);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(modelLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(jointIDLoc);
glBindBuffer(GL_ARRAY_BUFFER, indexBuffer);
glVertexAttribPointer(jointIDLoc, 1, GL_UNSIGNED_INT, GL_FALSE, 0, NULL);
glUniformMatrix4fv(jointsLoc, 10, GL_FALSE, (GLfloat*)&poseMatrices);
glDrawArrays(GL_TRIANGLES, 0, numVertices);
glDisableVertexAttribArray(modelLoc);
glDisableVertexAttribArray(jointIDLoc);
}
I've been banging my head against the desk for the past few hours looking at what seems to be correct code. Anyway, it's probably something dumb I missed. Any help is appreciated.
Here is all the relevant source code (just in case):
SkinnedModel.h
#pragma once
#include "stl/DataTypes.h"
#include "Shader.h"
#include <Dense>
using namespace Eigen;
struct Joint
{
Joint** children;
Joint* parent;
U32 index;
};
class SkinnedModel
{
public:
static void init();
static void destroy();
SkinnedModel();
~SkinnedModel();
void create(const GLfloat* vertices, const GLuint* jointIndices, GLint numVertices, Joint* rootJoint);
void draw();
void rotate(Joint* joint, F32 angle, F32 x, F32 y);
GLuint vertexBuffer;
GLuint indexBuffer;
GLint numVertices;
//GLint numJoints;
Joint* root;
Matrix<GLfloat,4,4> poseMatrices[10];
static ShaderProgram shaderProgram;
static GLuint modelLoc;
static GLuint jointIDLoc;
static GLuint modelViewMatrixLoc;
static GLuint jointsLoc;
};
SkinnedModel.cpp
#include "SkinnedModel.h"
ShaderProgram SkinnedModel::shaderProgram;
GLuint SkinnedModel::modelLoc = -1;
GLuint SkinnedModel::jointIDLoc = -1;
GLuint SkinnedModel::modelViewMatrixLoc = -1;
GLuint SkinnedModel::jointsLoc = -1;
void SkinnedModel::init()
{
ShaderProgramSettings shaderPS;
shaderPS.loadShader("Skinned.v.glsl", ShaderType::VERTEX);
shaderPS.loadShader("Skinned.f.glsl", ShaderType::FRAGMENT);
shaderProgram = shaderPS.create();
shaderProgram.use();
modelLoc = shaderProgram.getAttrib("model");
jointIDLoc = shaderProgram.getAttrib("jointID");
//modelViewMatrixLoc = shaderProgram.getUniform("modelViewMatrix");
jointsLoc = shaderProgram.getUniform("joints");
}
void SkinnedModel::destroy()
{
shaderProgram.destroy();
}
SkinnedModel::SkinnedModel()
{
}
SkinnedModel::~SkinnedModel()
{
glDeleteBuffers(1, &vertexBuffer);
glDeleteBuffers(1, &indexBuffer);
}
void SkinnedModel::create(const GLfloat* vertices, const GLuint* jointIndices, GLint numVertices, Joint* rootJoint)
{
this->numVertices = numVertices;
this->root = rootJoint;
for(U32 i=0;i<10;++i)
{
poseMatrices[i] = Matrix<GLfloat,4,4>::Identity();
}
poseMatrices[1] = Matrix<GLfloat,4,4>::Zero(); // <--- This should mess it up!
// Creating buffers
glDeleteBuffers(1, &vertexBuffer);
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, numVertices*2*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
glDeleteBuffers(1, &indexBuffer);
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(GLuint), jointIndices, GL_STATIC_DRAW);
}
void SkinnedModel::draw()
{
shaderProgram.use();
glEnableVertexAttribArray(modelLoc);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(modelLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(jointIDLoc);
glBindBuffer(GL_ARRAY_BUFFER, indexBuffer);
glVertexAttribPointer(jointIDLoc, 1, GL_UNSIGNED_INT, GL_FALSE, 0, NULL);
glUniformMatrix4fv(jointsLoc, 10, GL_FALSE, (GLfloat*)&poseMatrices);
glDrawArrays(GL_TRIANGLES, 0, numVertices);
glDisableVertexAttribArray(modelLoc);
glDisableVertexAttribArray(jointIDLoc);
}
void SkinnedModel::rotate(Joint* joint, F32 angle, F32 x, F32 y)
{
F32 rcos = cos(angle);
F32 rsin = sin(angle);
Matrix<GLfloat, 4, 4> rotMatrix = Matrix<GLfloat, 4, 4>::Identity();
rotMatrix(0,0) = rcos;
rotMatrix(0,1) = -rsin;
rotMatrix(1,0) = rsin;
rotMatrix(1,1) = rcos;
rotMatrix(0,3) = x-rcos*x+rsin*y;
rotMatrix(1,3) = y-rsin*x-rcos*y;
poseMatrices[joint->index] *= rotMatrix;
}
Game.cpp
void Game::init()
{
GUI::init();
SkinnedModel::init();
getScreen()->setBackgroundColor(1.0f, 1.0f, 1.0f);
const GLfloat vertices[] =
{
// upper arm
0.0f, 0.0f,
0.4f, 0.0f,
0.4f, 0.2f,
0.0f, 0.0f,
0.4f, 0.2f,
0.0f, 0.2f,
// lower arm
0.4f, 0.0f,
0.8f, 0.0f,
0.8f, 0.2f,
0.4f, 0.0f,
0.8f, 0.2f,
0.4f, 0.2f
};
const GLuint indices[] =
{
// upper arm
0,
1,
1,
0,
1,
0,
// lower arm
1,
1,
1,
1,
1,
1
};
upperArm.parent = 0;
upperArm.children = new Joint*[1];
upperArm.children[0] = &lowerArm;
upperArm.index = 0;
lowerArm.parent = &upperArm;
lowerArm.children = 0;
lowerArm.index = 1;
m.create(vertices, indices, 12, &upperArm);
//m.rotate(&lowerArm, PI/4, 0.4f, 0.1f);
//DEBUG("SIZE %i", sizeof(Eigen::Matrix<GLfloat,4,4>));
}
void Game::loop(double dt)
{
m.draw();
}
Update: Apparently if all values for the boneID are set to 1 it never uses 1 in the shader either #.#. So the second array isn't even being read, or it's not being read correctly.

You need to use glVertexAttribIPointer if you are using integer vertex attributes (i.e. something you have declared in uint or in int etc. in your vertex shader).
replace
glVertexAttribPointer(jointIDLoc, 1, GL_UNSIGNED_INT, GL_FALSE, 0, NULL);
with
glVertexAttribIPointer(jointIDLoc, 1, GL_UNSIGNED_INT, 0, NULL);
(note that glVertexAttribIPointer doesn't take the normalized parameter)

Related

Why is my OpenGL code producing a black screen?

This is my code written in C++ that is supposed to produce 2 triangles, however I am getting a blank screen. Is there something I am missing?
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <glm/vec3.hpp> // glm::vec3
#include <glm/vec4.hpp> // glm::vec4
#include <glm/mat4x4.hpp> // glm::mat4
#include <glm/gtc/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::perspective
using namespace std;
static string ParseShader(string filepath) {
ifstream stream(filepath);
string line;
stringstream stringStream;
while (getline(stream, line))
{
stringStream << line << '\n';
}
return stringStream.str();
}
static unsigned int CompileShader(unsigned int type, const string& source) {
unsigned int id = glCreateShader(type);
const char* src = source.c_str(); // this returns a pointer to data inside the string, the first character
glShaderSource(id, 1, &src, nullptr); // shader id, count of source codes, a pointer to the array that holds the strings
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE) {
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
cout << type << endl;
cout << message << endl;
glDeleteShader(id);
return 0;
}
return id;
}
// takes the shader codes as a string parameters
static unsigned int CreateShader(const string& vertexShader, const string& fragmentShader)
{
GLuint program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program); // validate if the program is valid and can be run in the current state of opengl
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
int main(void)
{
GLFWwindow* window;
float Angle = 0;
/* 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);
// call glewInit after creating the context...
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
}
GLfloat coordinates[12] = {
-0.5f, 0.5f,
0.0f, 0.5f,
0.5f, 0.5f,
-0.5f, -0.5f,
0.0f, -0.5f,
0.5f, -0.5f
};
GLuint indices[6] = { 0, 3, 1, 4, 2, 5 };
GLuint position_buffer;
glGenBuffers(1, &position_buffer);
glBindBuffer(GL_ARRAY_BUFFER, position_buffer);
glBufferData(GL_ARRAY_BUFFER, 6 * 2 * sizeof(float), coordinates, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0); //vertex positions
glEnableVertexAttribArray(0);
GLuint index_buffer;
glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), indices, GL_STATIC_DRAW);
string vertexSource = ParseShader("vertex.shader");
string fragmentSource = ParseShader("fragment.shader");
unsigned int program = CreateShader(vertexSource, fragmentSource);
glUseProgram(program);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
// Render here
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, nullptr);
//Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glDeleteProgram(program);
glfwTerminate();
return 0;
}
This is my vertex shader.
#version 330 core
layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;
out vec4 var_color;
void main()
{
var_color = color;
gl_Position = position;
};
And here is my fragment shader.
#version 330 core
out vec4 color;
in vec4 var_color;
void main()
{
//color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
color = var_color;
//discard;
};
I get a black screen as a result, I doubt this is an issue with my machine as other code snippets worked on it.
Colors are not specified in the provided code. The shader are most probably drawing black squares because of the value already in memory when you execute the program. To add colors, use this code:
GLfloat colors[24] = { // Random colors
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
};
GLuint color_buffer;
glGenBuffers(1, &color_buffer);
glBindBuffer(GL_ARRAY_BUFFER, color_buffer);
glBufferData(GL_ARRAY_BUFFER, 6 * 4 * sizeof(float), colors, GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); //vertex colors
glEnableVertexAttribArray(1);
The code shouldn't produce two triangles, as it is asked to render a triangle strip. The first three vertices define one triangle and each subsequent vertex adds another triangle for a total of 4 triangles.
The blank screen you're getting is the result of the vertex shader being sent 2D positions and interpreting them as 4D positions, as well as no color information being present.
To resolve these issues:
The vertex shader should receive a vec2 for the positions, since these are given in 2D:
layout(location = 0) in vec2 position;
Then convert these to 4D for gl_Position:
gl_Position = vec4(position, 0.0f, 1.0f);
The definition of the colors, setting up the corresponding buffer and uploading of the color data was missing. For example, add:
GLfloat colors[24] = {
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
};
GLuint color_buffer;
glGenBuffers(1, &color_buffer);
glBindBuffer(GL_ARRAY_BUFFER, color_buffer);
glBufferData(GL_ARRAY_BUFFER, 6 * 4 * sizeof(float), colors, GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
glEnableVertexAttribArray(1);
The result:

OpenGL fragment shader crashes with EXC_BAD_ACCESS on glDrawArrays

I'm using OpenGL 3.3 on Mac OSX 11.5.2. I have 6 fragment shaders, 3 that works and 3 that crashes with EXC_BAD_ACCESS. They all use the same vertex shader. There have been many questions about this problem, but I've made sure to:
Unbind my previous state.
Made sure attribute arrays enabled and used.
Am only using a single-thread, i.e. no concurrency.
The shaders that crash are all using one array of offsets and a kernel to do post-processing effects. If I replace texture_coordinate.st + offsets[i] with just texture_coordinate.st, it'll work just fine. As this makes the offsets array unused and optimized out, I have a suspicion that it could be due to a register allocation bug as mentioned in the comments in this question, but can't confirm.
I've also checked for other problems, such as loading them in different orders, using different compiler flags, but the crashes are consistent.
Here's a minimal, reproducible example (dependent on glad and glfw3, compiled with c++17) with one of the problematic shaders.
#include <glad/glad.h>
#include <GLFW/glfw3.h>
const char VERTEX_POST[] = R"(
#version 330 core
layout (location = 0) in vec2 position;
layout (location = 1) in vec2 in_texture_coordinate;
out vec2 texture_coordinate;
void main()
{
gl_Position = vec4(position.x, position.y, 0.0, 1.0);
texture_coordinate = in_texture_coordinate;
}
)";
const char FRAGMENT_POST[] = R"(
#version 330 core
in vec2 texture_coordinate;
out vec4 FragColor;
uniform sampler2D image;
const float offset = 1.0 / 300.0;
void main()
{
vec2 offsets[9] = vec2[](
vec2(-offset, offset), // top-left
vec2( 0.0f, offset), // top-center
vec2( offset, offset), // top-right
vec2(-offset, 0.0f), // center-left
vec2( 0.0f, 0.0f), // center-center
vec2( offset, 0.0f), // center-right
vec2(-offset, -offset), // bottom-left
vec2( 0.0f, -offset), // bottom-center
vec2( offset, -offset) // bottom-right
);
float kernel[9] = float[](
-1, -1, -1,
-1, 9, -1,
-1, -1, -1
);
vec3 sample_texture[9];
for(int i = 0; i < 9; i++)
sample_texture[i] = vec3(texture(image, texture_coordinate + offsets[i]));
vec3 color = vec3(0.0);
for (int i = 0; i < 9; i++)
color += sample_texture[i] * kernel[i];
FragColor = vec4(color, 1.0);
}
)";
float vertices[] = {
// Positions // Texture coords
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
GLuint create_shader(const char* source, GLenum type)
{
GLuint id = glCreateShader(type);
glShaderSource(id, 1, &source, nullptr);
glCompileShader(id);
int success;
glGetShaderiv(id, GL_COMPILE_STATUS, &success);
assert(success);
return id;
}
int main()
{
// ---- INIT GLFW & GLAD ----
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
GLFWwindow* window = glfwCreateWindow(800, 800, "Temp", nullptr, nullptr);
if (window == nullptr) return -1;
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) return -1;
// ---- CREATE QUAD ----
GLuint quad, vbo;
glGenVertexArrays(1, &quad);
glGenBuffers(1, &vbo);
glBindVertexArray(quad);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(float)));
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// ---- CREATE TEXTURE ----
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
char data[800 * 800 * 4] = {};
for (char& i : data) i = 127;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 800, 800, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
// ---- CREATE SHADER PROGRAM ----
GLuint vertex_shader = create_shader(VERTEX_POST, GL_VERTEX_SHADER);
GLuint fragment_shader = create_shader(FRAGMENT_POST, GL_FRAGMENT_SHADER);
GLuint program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
glValidateProgram(program);
int success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
assert(success);
// ---- MAIN LOOP ----
while (!glfwWindowShouldClose(window))
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(program, "image"), 0);
glBindVertexArray(quad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
return 0;
}
The example gives me a grey image when not including offsets and otherwise exhibits the crash. What could be causing this?

delete array in C++ causing program crash

I am following along with a youtube tutorial concerning opengl (a graphics programming library). I've created classes called vertex, ShapeData and ShapeGenerator. The overall idea is I'm creating code which will hold data for any type of shape I decide to come up with and want to display to the screen. The problem is my program seems to crash once the first "delete[]" is hit within ShapeData.h in the cleanup() function. Here is the relevant code:
Vertex.h
#pragma once
#include "GLM/glm.hpp"
class Vertex
{
public:
Vertex();
Vertex(glm::vec3 thePosition, glm::vec3 theColor);
glm::vec3 position;
glm::vec3 color;
};
Vertex.cpp
#include "Vertex.h"
Vertex::Vertex()
{}
Vertex::Vertex(glm::vec3 thePosition, glm::vec3 theColor) :
position(thePosition),
color(theColor)
{
}
ShapeData.h
#pragma once
#include "Vertex.h"
#include "GL/glew.h"
struct ShapeData
{
ShapeData() :
verticies(0), numberOfVerts(0),
indicies(0), numberOfIndicies(0)
{}
Vertex* verticies;
GLuint numberOfVerts;
GLushort* indicies;
GLuint numberOfIndicies;
GLsizeiptr VertexBufferSize() const
{
return numberOfVerts * sizeof(Vertex);
}
GLsizeiptr IndexBufferSize() const
{
return numberOfIndicies * sizeof(GLushort);
}
void CleanUp()
{
delete[] verticies;
delete[] indicies;
verticies = 0;
indicies = 0;
numberOfIndicies = 0;
numberOfVerts = 0;
}
};
ShapeGenerator.cpp
#include "ShapeGenerator.h"
ShapeData ShapeGenerator::MakeTriangle()
{
Vertex triangle[] = {
Vertex(glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f)),
Vertex(glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f)),
Vertex(glm::vec3(1.0f, -1.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f))
};
ShapeData shapeData;
shapeData.numberOfVerts = sizeof(triangle) / sizeof(*triangle);
shapeData.verticies = new Vertex[shapeData.numberOfVerts];
memcpy(shapeData.verticies, triangle, sizeof(triangle));
shapeData.verticies = triangle;
GLushort indicies[] = { 0,1,2 };
shapeData.numberOfIndicies = sizeof(indicies) / sizeof(*indicies);
shapeData.indicies = new GLushort[shapeData.numberOfIndicies];
memcpy(shapeData.indicies, indicies, sizeof(indicies));
return shapeData;
}
I'm trying to create a triangle and everything works fine without running the cleanup() function within main. Here is the portion where I'm calling Cleanup() in main:
main.cpp
ShapeData triangle = ShapeGenerator::MakeTriangle();
GLuint bufferID;
glGenBuffers(1, &bufferID);
glBindBuffer(GL_ARRAY_BUFFER, bufferID);
glBufferData(GL_ARRAY_BUFFER, triangle.VertexBufferSize(), triangle.verticies, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (char*)(sizeof(float) * 3));
GLuint indexBufferID;
glGenBuffers(1, &indexBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, triangle.IndexBufferSize(),triangle.indicies, GL_STATIC_DRAW);
triangle.CleanUp();
You are replacing the new[]'d pointer here. This causes a crash because triangle is not new[]'d.
shapeData.verticies = new Vertex[shapeData.numberOfVerts];
memcpy(shapeData.verticies, triangle, sizeof(triangle));
shapeData.verticies = triangle;

How to pass the model matrix off to the shader and make the triangle rotate

I am using OpenGL and GLM library, and I try to pass the model matrix off to the shader and make the triangle rotate. I have already got the basic code and getting the IDs of the variables in the vertex shader. While I have no idea how to actually setting them.
#include <GL/GLEW.h>
#include <GL/freeglut.h>
#include <stdio.h>
#include <glm/vec3.hpp> // glm::vec3
#include <glm/vec4.hpp> // glm::vec4
#include <glm/mat4x4.hpp> // glm::mat4
#include <glm/gtc/matrix_transform.hpp> // glm::translate/rotate/scale/etc
#include <glm/gtc/type_ptr.hpp> // glm::value_ptr
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
glm::mat4 M;
glm::mat4 V;
glm::mat4 P;
glm::mat4 trans;
glm::mat4 rot;
float rotAmount = 0.0f;
GLint umM;
GLint umV;
GLint umP;
void func(GLuint LocationMVP, float Translate, glm::vec2 const & Rotate)
{
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.f);
glm::mat4 ViewTranslate = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -Translate));
glm::mat4 ViewRotateX = glm::rotate(ViewTranslate, Rotate.y, glm::vec3(-1.0f, 0.0f, 0.0f));
glm::mat4 View = glm::rotate(ViewRotateX, Rotate.x, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 Model = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f));
glm::mat4 MVP = Projection * View * Model;
glUniformMatrix4fv(LocationMVP, 1, GL_FALSE, glm::value_ptr(MVP));
}
void render()
{
trans = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, -1));
rot = glm::rotate(glm::mat4(1.0f), rotAmount, glm::vec3(0, 1, 0));
M = trans*rot;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 9, GL_UNSIGNED_INT, NULL);
glutSwapBuffers();
glutPostRedisplay();
}
void specialKeys(int key, int x, int y) {
switch (key) {
case GLUT_KEY_UP: printf("The UP key was pressed\n"); break;
case GLUT_KEY_DOWN: printf("The DOWN key was pressed\n"); break;
}
}
void mousePressed(int button, int state, int x, int y)
{
if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN)) {
//printf("Mouse clicked at %d %d\n", x, y);
}
}
void mouseMoved(int x, int y) {
//printf("Mouse moved at %d %d\n", x, y);
}
void mouseDragged(int x, int y) {
//printf("Mouse dragged at %d %d\n", x, y);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); // Set up buffers
glutInitWindowPosition(200, 200); // Optional: position the upper-left of the window
glutInitWindowSize(800, 600); // Set the window size
glutCreateWindow("Lab 5"); // Create the window and give it a title
glewInit(); // Ask the driver for all the OpenGL functions
// Some callback functions
glutDisplayFunc(render); // Use the render function to draw
glutSpecialFunc(specialKeys); // Use the specialKeys function for Up/Down/Left/Right keys
glutMouseFunc(mousePressed); // Use for mouse clicks
glutMotionFunc(mouseDragged); // Use for mouse dragging
glutPassiveMotionFunc(mouseMoved); // Use for mouse moving
#pragma region SHADER_STUFF
// ========= SHADER STUFF ===============
const GLchar* vertexShaderCode = "#version 150\n\
in vec4 vPosition;\n\
in vec4 vColor;\n\
out vec4 color;\n\
void main () {\n\
color = vColor;\n\
\tgl_Position = vPosition;\n\
}\n";
const GLchar* fragmentShaderCode = "#version 150\n\n\
out vec4 fColor;\n\
in vec4 color;\n\
void main () {\
fColor = color;\n\
}";
// Vertex Shader
GLint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderID, 1, &vertexShaderCode, NULL);
glCompileShader(vertexShaderID);
GLint compiled = -10;
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &compiled);
printf("Vertex compile status %d!\n", compiled);
printf("Vertex shader ID is %d\n", vertexShaderID);
// Fragment Shader
GLint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderID, 1, &fragmentShaderCode, NULL);
glCompileShader(fragmentShaderID);
GLint compiled2 = -19;
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &compiled2);
printf("Fragment compile status %d!\n", compiled2);
printf("Fragment shader ID is %d\n", fragmentShaderID);
// Make the program
GLint shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShaderID);
glAttachShader(shaderProgram, fragmentShaderID);
glLinkProgram(shaderProgram);
GLint linkedStatus = 14;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &linkedStatus);
printf("Link status is %d\n", linkedStatus);
printf("Shader program ID is %d\n", shaderProgram);
glUseProgram(shaderProgram);
#pragma endregion SHADER_STUFF
// Positions
GLfloat vertices[] = { -0.5f, -0.5f, 0.0f, // 0
-0.25f, 0.0f, 0.0f, // 1
0.0f, 0.5f, 0.0f, // 2
0.0f, -0.5f, 0.0f, // 3
0.25f, 0.0f, 0.0f, // 4
0.5f, -0.5f, 0.0f, // 5
};
// Color information
GLfloat colors[] = { 1.0f, 0.73f, 0.0f, 1.0f, //0
1.0f, 1.0f, 0.0f, 1.0f, // 1
1.0f, 1.0f, 0.0f, 1.0f, // 2
1.0f, 0.73f, 0.0f, 1.0f, // 3
1.0f, 0.65f, 0.0f, 1.0f, // 4
1.0f, 0.65f, 0.0f, 1.0f, // 5
};
// Connect the dots
GLuint index_buffer[] = { 0, 3, 1, 2, 1, 4, 4, 3, 5 };
int numVertices = 6;
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao); // Use the Vertex Array Object we created above
GLuint vbo; // The Vertex Buffer Object ID
glGenBuffers(1, &vbo); // Ask the GPU driver for a buffer array. "vbo" now has the ID
glBindBuffer(GL_ARRAY_BUFFER, vbo); // Make this buffer the active one for subsequent operations (below)
// Specify how big the buffer is, but don't pass the data yet (see NULL). We *could* have, but I wanted to show glBufferSubData
glBufferData(GL_ARRAY_BUFFER, numVertices * 7 * sizeof(GLfloat), NULL, GL_STATIC_DRAW);
// NOW we copy the data in as a separate step. There is an "offset" of 0 - meaning the beginning of the buffer.
// We specify the size of the data we want to copy, followed by a pointer to the actual data
glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices * 3 * sizeof(GLfloat), vertices);
glBufferSubData(GL_ARRAY_BUFFER, numVertices * 3 * sizeof(GLfloat), numVertices * 4 * sizeof(GLfloat), colors);
// Figure out where vPosition is in our shader and get its ID
GLuint loc = glGetAttribLocation(shaderProgram, "vPosition");
GLuint loc2 = glGetAttribLocation(shaderProgram, "vColor");
glEnableVertexAttribArray(loc);
glEnableVertexAttribArray(loc2);
printf("vPosition ID is %d\n", loc);
printf("vColor ID is %d\n", loc2);
// When it's time for vPosition to find information, we need to tell it where the data is (or how the data should be parsed)
// Here, we're saying that "vPosition" (loc from above) should look for 3 GLfloats. The data isn't normalized or interlaced,
// and starts at index 0 (the beginning of the current buffer)
glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(loc2, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numVertices * 3 * sizeof(GLfloat)));
GLuint index_vbo;
// Ask the graphics card (driver) for another buffer – same as the old code
glGenBuffers(1, &index_vbo);
// We still want the VAO active to remember these settings
glBindVertexArray(vao);
// Here's where we tell the driver that it's an index buffer.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_vbo);
// This time, we'll just go ahead and pass the data off to the buffer because
// we're not packing multiple data sets into the buffer - only indices
umM = glGetUniformLocation(shaderProgram, "mM"); // Find the mM variable
umV = glGetUniformLocation(shaderProgram, "mV"); // Find the mV variable
umP = glGetUniformLocation(shaderProgram, "mP"); // Find the mP variable
if (umP != -1)
{
glUniformMatrix4fv(umP, 1, GL_FALSE, glm::value_ptr(P));
}
if (umV != -1)
{
glUniformMatrix4fv(umV, 1, GL_FALSE, glm::value_ptr(V));
}
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 9*sizeof(GLuint), index_buffer, GL_STATIC_DRAW);
P = glm::perspective(-60.0f, 1.3f, 0.1f, 1000.0f);
V = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0));
glm::mat4 T = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
glm::mat4 Rx = glm::rotate(T, rotation_x, glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 Ry = glm::rotate(Rx, rotation_y, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 M = glm::rotate(Ry, rotation_z, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 MVP = P*V*M;
glutMainLoop(); // Start listening for events
}
and also my shader file is like
#version 150
in vec4 vPosition;
uniform mat4 mM; // The matrix for the pose of the model
uniform mat4 mV; // The matrix for the pose of the camera
uniform mat4 mP; // The perspective matrix
void main()
{
gl_Position = mP*mV*mM*vPosition;
}
Could any one help me, or teach me how to setting them?

Cube is not rendering in OpenGL

I'm trying to write a basic OpenGL 3.3 program with shaders, buffers, etc. drawing a cube. The problem is that the cube is not drawn. Sorry for such an amout of code, but i feel like the error might be anywhere, because to me it all seems right: display function is looping, shaders are compiled, matrices are passed to shaders. I suspecting that something might be wrong with culling. Please take a look. Here is the code (I'm using freeglut, first init() is called, then display runs in a loop):
initialization code:
struct ProgramData
{
GLuint theProgram;
GLuint iModel;
GLuint iView;
GLuint iProjection;
};
ProgramData shaderProgram;
ProgramData LoadProgram(const std::string &strVertexShader,
const std::string &strFragmentShader)
{
std::vector<GLuint> shaderList;
shaderList.push_back(LoadShader(GL_VERTEX_SHADER, strVertexShader));
shaderList.push_back(LoadShader(GL_FRAGMENT_SHADER, strFragmentShader));
ProgramData data;
data.theProgram = CreateProgram(shaderList);
data.iModel = glGetUniformLocation(data.theProgram, "mModel");
data.iView = glGetUniformLocation(data.theProgram, "mView");
data.iProjection = glGetUniformLocation(data.theProgram, "mProjection");
return data;
}
float cube_vertices[] = {
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
GREEN_COLOR,
BLUE_COLOR,
RED_COLOR,
BROWN_COLOR,
GREEN_COLOR,
BLUE_COLOR,
RED_COLOR,
BROWN_COLOR,
};
GLubyte cube_elements[] = {
0,1,2, 2,3,0,
0,3,4, 4,5,0,
0,5,6, 6,1,0,
1,6,7, 7,2,1,
7,4,3, 3,2,7,
4,7,6, 6,5,4
};
void InitializeProgram()
{
//initialize vertex buffer
glGenBuffers(1, &vertex_buffer_obj);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_obj);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices),
cube_vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//initialize index buffer
glGenBuffers(1, &index_buffer_obj);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_obj);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements),
cube_elements, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
shaderProgram = LoadProgram("shader.vert", "shader.frag");
}
void init()
{
InitializeProgram();
int numberOfVertices = 8;
size_t color_data_offset = sizeof(float) * 3 * numberOfVertices;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_obj);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0,
(void*)color_data_offset);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_obj);
glBindVertexArray(0);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.0f, 1.0f);
}
vertex shader:
#version 330
layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec3 color;
uniform mat4 mProjection;
uniform mat4 mView;
uniform mat4 mModel;
smooth out vec3 theColor;
void main()
{
gl_Position = mProjection * mView * mModel * vec4(inPosition, 1);
theColor = color;
}
fragment shader:
#version 330
smooth in vec3 theColor;
out vec4 outputColor;
void main()
{
outputColor = vec4(theColor, 1);
}
draw code:
glm::vec3 cam_pos(3, 2, 3);
void display()
{
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgram.theProgram);
glm::mat4 model_matrix = glm::translate(glm::vec3(0, 0, 0));
glm::mat4 view_matrix = glm::lookAt(cam_pos,
glm::vec3(0, 0, 0), glm::vec3(0, 0, 1));
glm::mat4 proj_matrix = glm::perspective(45.0f, 1.0f, 1.0f, 100.0f);
glUniformMatrix4fv(shaderProgram.iProjection, 1,
GL_FALSE, glm::value_ptr(proj_matrix));
glUniformMatrix4fv(shaderProgram.iView, 1,
GL_FALSE, glm::value_ptr(view_matrix));
glUniformMatrix4fv(shaderProgram.iModel, 1,
GL_FALSE, glm::value_ptr(model_matrix));
glBindVertexArray(vao);
int size; glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER,
GL_BUFFER_SIZE, &size);
glDrawElements(GL_TRIANGLES, size / sizeof(GLubyte), GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
glUseProgram(0);
glutSwapBuffers();
glutPostRedisplay();
}
UPD: in init method when an offset for colors is calculated should be
sizeof(float) * 3 * numberOfVertices instead of
sizeof(GLubyte) * 3 * numberOfVertices, colors are stored as floats. Rendering problem not solved.
SOLVED: thank you for help. See my answer below.
On thing I did spot when glancing over your code is the following line from your vertex shader:
gl_Position = mProjection * mView * mModel * vec4(inPosition, 0);
That 0 should really be a 1.0.
In display() function
glDrawElements(GL_TRIANGLES, size / sizeof(GLubyte), GL_UNSIGNED_SHORT, 0);
should be changed to
glDrawElements(GL_TRIANGLES, size / sizeof(GLubyte), GL_UNSIGNED_BYTE, 0);
and in init()
glFrontFace(GL_CW);
to
glFrontFace(GL_CCW);
So the problem was that I passed to OpenGL incorrect data. Index array is of GLUbyte (1byte size each array element) but I for some reason decided it was GLushort (2bytes).
edit: doesn't matter a lot, but up vector (when generating camera matrix) should be not glm::vec3(0, 0, 1) but glm::vec3(0, 1, 0)