nvoglv32.dll Access violation reading location 0x00000000 - c++

I've been having a problem lately with openGL. In my program that has worked fine before, I try to draw a group of polygons to the screen but the program throws an error and for the life of me I can't find the cause of it. I've literally changed nothing from my code, it just started throwing errors one day after coming back to it after a month. The error is:
Unhandled exception at 0x69F2883E (nvoglv32.dll) in openGLtest.exe:
0xC0000005: Access violation reading location 0x00000000.
I have reproduced the error with the code below. Some more strange behavior I've noticed is that if I change the call to glDrawArrays to something like:
glDrawArrays(GL_TRIANGLES, 3, numV);
or
glDrawArrays(GL_TRIANGLES, 0, 258);
then the program doesn't throw the error though obviously it doesn't render properly, rendering only half of the rectangle, or rendering the rectangle plus some garbage input.
It's very strange, if it renders more than 255 points it works fine but any less and it throws the error.
#include <SDL.h>
#include <GL/glew.h>
#include <math.h>
#include <vector>
struct Vector2f{
public:
float x, y;
Vector2f() {}
Vector2f(float _x, float _y) { x = _x; y = _y; }
};
struct Vector3f {
public:
float x, y, z;
Vector3f() { x = 0.0, y = 0.0, z = 0.0; }
Vector3f(float _x, float _y, float _z) { x = _x; y = _y; z = _z; }
};
struct Vertex {
Vector3f m_pos;
Vector2f m_tex;
Vector3f m_normal;
Vertex() {}
Vertex(Vector3f pos, Vector2f tex) {
m_pos = pos;
m_tex = tex;
m_normal = Vector3f(0.0f, 0.0f, 0.0f);
}
Vertex(Vector3f pos, Vector2f tex, Vector3f norm) {
m_pos = pos;
m_tex = tex;
m_normal = norm;
}
};
SDL_Window* Window_Display = NULL;
SDL_GLContext glcontext;
GLuint VBO;
int width = 800;
int height = 600;
float ratio = (float)width / (float)height;
int numV;
std::vector<Vertex> _VBO;
bool initWindow() {
//draw a square
_VBO.push_back(Vertex(Vector3f(-0.8f, -0.8f, 0.0f), Vector2f(0.0f, 0.0f), Vector3f(0.0f, 0.0f, 0.0f)));
_VBO.push_back(Vertex(Vector3f(0.8f, -0.8f, 0.0f), Vector2f(0.0f, 0.0f), Vector3f(0.0f, 0.0f, 0.0f)));
_VBO.push_back(Vertex(Vector3f(0.8f, 0.8f, 0.0f), Vector2f(0.0f, 0.0f), Vector3f(0.0f, 0.0f, 0.0f)));
_VBO.push_back(Vertex(Vector3f(-0.8f, -0.8f, 0.0f), Vector2f(0.0f, 0.0f), Vector3f(0.0f, 0.0f, 0.0f)));
_VBO.push_back(Vertex(Vector3f(-0.8f, 0.8f, 0.0f), Vector2f(0.0f, 0.0f), Vector3f(0.0f, 0.0f, 0.0f)));
_VBO.push_back(Vertex(Vector3f(0.8f, 0.8f, 0.0f), Vector2f(0.0f, 0.0f), Vector3f(0.0f, 0.0f, 0.0f)));
numV = 6;
if (SDL_Init(SDL_INIT_VIDEO) < 0) return false;
if ((Window_Display = SDL_CreateWindow("OpenGL Drawing Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL)) == NULL) return false;
glcontext = SDL_GL_CreateContext(Window_Display);
glewInit();
return true;
}
bool drawScene() {
glEnableClientState(GL_VERTEX_ARRAY);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspective
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, numV * sizeof(Vertex), &_VBO[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)20);
glDrawArrays(GL_TRIANGLES, 0, numV); //Unhandled exception at 0x69F2883E (nvoglv32.dll) in openGLtest.exe: 0xC0000005: Access violation reading location 0x00000000.
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
SDL_GL_SwapWindow(Window_Display); //Send the 3D scene to the screen
glDisableClientState(GL_VERTEX_ARRAY);
return true;
}
int main(int argc, char* args[]) {
if (initWindow()) {
while (drawScene()) {}
}
return 0;
}

Related

What is causing this cube to not render?

When running the program, the camera seems to work fine and I can manipulate the clear colour but the cube itself will not render.
Here's my code:
(The camera and renderer objects are both declared in their respective header files along with their methods)
Main.cpp
#include <GL/glew.h>
#include "Shapes.h"
#include "Renderer.h"
#include "Camera.h"
int main()
{
Renderer* renderer = new Renderer(800, 800, (const char*)"OpenGL Sample Test", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
GLFWwindow* window = renderer->getWindow();
Block* cube = new Block(renderer);
cube->setColourTint(glm::vec4(0.3f, 0.0f, 0.4f, 1.0f));
while (!glfwWindowShouldClose(window))
{
renderer->updateRender();
cube->rotate((float)glfwGetTime() * glm::radians(50.0f), glm::vec3(0.5f, 0.5f, 0.0f));
}
delete renderer;
return 0;
}
Renderer.cpp
#include "Renderer.h"
#include "Shapes.h"
Renderer::Renderer(int Window_X, int Window_Y, const char* Window_Title, glm::vec4 ClearColour)
{
Renderer::renderList = new std::vector<Shape*>;
Renderer::clearColour = ClearColour;
Renderer::WINDOW_X = Window_X;
Renderer::WINDOW_Y = Window_Y;
Renderer::WINDOW_TITLE = Window_Title;
createWindow();
std::cout << "Running OpenGL extension checks... ";
GLenum glewTest = glewInit();
if (GLEW_OK != glewTest)
{
std::cout << "FAILED";
std::cout << (const char*)glewGetErrorString(glewTest) << std::endl;
glfwDestroyWindow(window);
}
else
{
std::cout << "OK" << std::endl;
glfwMakeContextCurrent(window);
}
//OPENGL//
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, Window_X, Window_Y);
Renderer::shader = new Shader("Vertex.glsl", "Fragment.glsl"); //Create the shaders
Renderer::camera = new Camera(Window_X, Window_Y, glm::vec3(0.0f, 0.0f, 2.0f));
Renderer::modelMatrixShaderLocation = glGetUniformLocation(shader->ID, "model"); //Grab the name of the uniform of the model matrix
Renderer::fragmentColourTintLocation = glGetUniformLocation(shader->ID, "colourTint");
glCheckError();
}
void Renderer::createWindow()
{
//Define OpenGL Version | Create Window
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
std::cout << "Creating GLFW Window... ";
Renderer::window = glfwCreateWindow(WINDOW_X, WINDOW_Y, WINDOW_TITLE, NULL, NULL);
if (window == NULL)
{
std::cout << "ERROR: GLFW WINDOW FAILED TO INSTANTIATE" << std::endl;
glfwTerminate();
}
else
{
std::cout << "OK" << std::endl;
glfwMakeContextCurrent(window);
//Key Callbacks
glfwSetKeyCallback(window, key_callback);
glfwSetWindowCloseCallback(window, close_callback);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
}
}
bool Renderer::updateRender()
{
glClearColor(clearColour.r, clearColour.g, clearColour.b, clearColour.a); //Add background color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clear the color and depth back buffers
shader->use(); //Bind to the shader program
for (int i = 0; i < renderList->size(); i++)
{
Shape* current = renderList->at(i);
current->clearMatrix();
}
//Refresh the projection matrix
//projection = glm::mat4(1.0f);
//projection = glm::perspective(glm::radians(45.0f), (float)WINDOW_X / (float)WINDOW_Y, 0.1f, 100.0f);
//shader->setMat4("projection", projection);
glCheckError();
for (int i = 0; i < renderList->size(); i++) //Update matrix of each renderable object
{
Shape* current = renderList->at(i);
glUniformMatrix4fv(modelMatrixShaderLocation, 1, GL_FALSE, glm::value_ptr(current->getPosition()));
glUniform4f(fragmentColourTintLocation, current->getColourTint().r, current->getColourTint().g, current->getColourTint().b, current->getColourTint().a);
glBindVertexArray(current->getVAO());
std::cout << "Drawing: " << current << " : " << current->getVAO() << std::endl;
glDrawElements(GL_TRIANGLES, current->getIndicesStride(), GL_UNSIGNED_INT, 0);
glCheckError();
}
camera->Inputs(window); //Process camera input
//Camera Matrix updating
camera->Matrix(45.0f, 0.1f, 100.0f, shader, "camMatrix");
glfwSwapBuffers(window);
glfwPollEvents();
if (glCheckError() != NULL)
{
return true;
}
else
{
return false;
}
}
Renderer::~Renderer()
{
for (int i = 0; i < renderList->size(); i++)
{
Shape* current = renderList->at(i);
glDeleteVertexArrays(1, current->getVAOAddress());
glDeleteBuffers(1, current->getVBOAddress());
glDeleteBuffers(1, current->getEBOAddress());
delete current;
}
glfwDestroyWindow(window);
glfwTerminate();
glDeleteProgram(shader->ID);
delete renderList;
delete shader;
delete camera;
}
GLFWwindow* Renderer::getWindow()
{
return window;
}
void Renderer::push_Renderer(Shape* Renderable_Object)
{
renderList->push_back(Renderable_Object);
}
void Renderer::updateClearColour(glm::vec4 ClearColour)
{
clearColour = ClearColour;
}
Camera.cpp
#include "Camera.h"
Camera::Camera(int width, int height, glm::vec3 position)
{
Camera::width = width;
Camera::height = height;
Position = position;
}
void Camera::Matrix(float FOVdeg, float nearPlane, float farPlane, Shader* shader, const char* uniform)
{
//Matrix Magic
glm::mat4 view = glm::mat4(1.0f);
glm::mat4 projection = glm::mat4(1.0f);
view = glm::lookAt(Position, Position + Orientation, Up);
projection = glm::perspective(glm::radians(FOVdeg), (float)(width / height), nearPlane, farPlane);
//std::cout << "XYZ: " << Position.x << " : " << Position.y << " : " << Position.z << std::endl;
glUniformMatrix4fv(glGetUniformLocation(shader->ID, uniform), 1, GL_FALSE, glm::value_ptr(projection * view));
}
void Camera::Inputs(GLFWwindow* window)
{
//Basic Camera Controls
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
{
Position += speed * Orientation;
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
{
Position += speed * -glm::normalize(glm::cross(Orientation, Up));
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
{
Position += speed * -Orientation;
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
{
Position += speed * glm::normalize(glm::cross(Orientation, Up));
}
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
{
Position += speed * Up;
}
if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS)
{
Position += speed * -Up;
}
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS)
{
speed = 0.4f;
}
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_RELEASE)
{
speed = 0.1f;
}
//Mouse Control
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) //Hide cursor when left mouse button is pressed
{
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
double MouseX;
double MouseY;
glfwGetCursorPos(window, &MouseX, &MouseY);
float rotX = sensitivity * (float)(MouseY - (height / 2)) / height;
float rotY = sensitivity * (float)(MouseX - (height / 2)) / height;
glm::vec3 newOrientation = glm::rotate(Orientation, glm::radians(-rotX), glm::normalize(glm::cross(Orientation, Up)));
if (!((glm::angle(newOrientation, Up) <= glm::radians(5.0f)) or (glm::angle(newOrientation, -Up) <= glm::radians(5.0f))))
{
Orientation = newOrientation;
}
Orientation = glm::rotate(Orientation, glm::radians(-rotY), Up);
glfwSetCursorPos(window, (width / 2), (height / 2));
}
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_RELEASE) //Show cursor when left mouse button is released
{
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
}
Shapes.h
#pragma once
#ifndef SHAPES_H
#define SHAPES_H
#include "Renderer.h"
#include <GL/glew.h>
#include <glm.hpp>
#include <gtc/type_ptr.hpp>
#include <gtx/rotate_vector.hpp>
#include <gtx/vector_angle.hpp>
inline void GeneralVao(GLuint &VAO, GLuint &VBO, GLuint &EBO, GLint* indices, GLfloat* vertices, GLsizeiptr sizeofidef, GLsizeiptr sizeofvdef)
{
//bind the Vertex Array Object first, then bind and set vertex buffer, and then configure vertex attributes(s).
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
//EBO
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeofidef, indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeofvdef, vertices, GL_STATIC_DRAW);
//Position Attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0);
glEnableVertexAttribArray(0);
//Colour Attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
//unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
class Shape
{
protected:
GLfloat* vertices = NULL;
GLint* indices = NULL;
virtual void constructVao() = 0;
GLuint VAO = NULL, VBO = NULL, EBO = NULL;
glm::mat4 ModelMatrix = glm::mat4(1.0f);
glm::vec4 colourTint = glm::vec4(1.0f);
public:
GLuint getVAO()
{
return VAO;
}
glm::vec4 getColourTint()
{
return colourTint;
}
void setColourTint(glm::vec4 Colour)
{
colourTint = Colour;
}
//Addresses
GLuint* getVAOAddress()
{
return &VAO;
}
GLuint* getVBOAddress()
{
return &VBO;
}
GLuint* getEBOAddress()
{
return &EBO;
}
//
void setPosition(glm::mat4 Matrix)
{
ModelMatrix = Matrix;
}
void rotate(glm::f32 angle, glm::vec3 axis) //Rotates by an angle (floating point) and an axis (vector3)
{
ModelMatrix = glm::rotate(ModelMatrix, angle, axis);
}
void scale(glm::vec3 ScaleFactor3)
{
ModelMatrix = glm::scale(ModelMatrix, ScaleFactor3);
}
void move(glm::vec3 Vector)
{
ModelMatrix = glm::translate(ModelMatrix, Vector);
}
void clearMatrix()
{
ModelMatrix = glm::mat4(1.0f);
}
virtual GLsizei getIndicesStride() = 0;
glm::mat4 getPosition()
{
return ModelMatrix;
}
virtual ~Shape()
{
}
};
class Pyramid : public Shape
{
private:
GLfloat vdef[30] = {
//Position Colour
-0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, //Front Bottom Left | 0
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, //Front Bottom Right | 1
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, //Back Bottom Left | 2
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, //Back Bottom Right | 3
0.0f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f //Top | 4
};
GLint idef[18] = {
//Bottom
0, 2, 3,
3, 1, 0,
//Front
1, 4, 0 ,
//Left
0, 4, 2,
//Right
1, 4, 3,
//Back
3, 4, 2
};
public:
Pyramid(Renderer* renderer)
{
indices = idef;
vertices = vdef;
constructVao();
renderer->push_Renderer(this);
}
void constructVao()
{
GeneralVao(VAO, VBO, EBO, idef, vdef, sizeof(idef), sizeof(vdef));
}
GLsizei getIndicesStride()
{
return sizeof(idef) / sizeof(GLint);
}
virtual ~Pyramid()
{
}
};
class Block : public Shape
{
private:
GLfloat vdef[48] = {
//Position Colour
-0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, //Front Bottom Left | 0
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, //Front Bottom Right | 1
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, //Back Bottom Left | 2
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, //Back Bottom Right | 3
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, //Front Top Left | 4
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, //Front Top Right | 5
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, //Back Top Left | 6
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, //Back Top Right | 7
};
GLint idef[36] = {
//Bottom
0, 1, 3,
3, 2, 0,
//Front
1, 0, 4,
4, 5, 1,
//Left
0, 2, 6,
6, 4, 0,
//Right
1, 3, 7,
7, 5, 1,
//Top
4, 5, 7,
7, 6, 4,
//Back
2, 3, 5,
5, 5, 2
};
public:
Block(Renderer* renderer)
{
indices = idef;
vertices = vdef;
setColourTint(glm::vec4(0.3, 0.0, 1.0, 1.0));
constructVao();
renderer->push_Renderer(this);
}
void constructVao()
{
GeneralVao(VAO, VBO, EBO, idef, vdef, (GLsizeiptr)sizeof(idef), (GLsizeiptr)sizeof(vdef));
}
GLsizei getIndicesStride()
{
return sizeof(idef) / sizeof(GLint);
}
virtual ~Block()
{
}
};
#endif
Vertex.glsl
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
uniform mat4 model;
uniform mat4 camMatrix;
out vec3 ourColor;
void main()
{
gl_Position = camMatrix * model * vec4(aPos, 1.0);
ourColor = aColor;
}
Fragment.glsl
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
uniform vec4 colourTint;
void main()
{
FragColor.a = colourTint.a;
FragColor.rgb = ((FragColor.rgb - colourTint.rgb) / FragColor.rgb) * 100;
}
I found the issue.
Turns out it worked, just the cube was unexpectedly black along with the clearcolor.

only one value inserted in vector in opengl code

unable to insert more than one element in vector; worked fine when I tested with an integer vector. tried the following:
push_back function
insert function
assign function
The issue is in the createObjects() function this error due to the way i have written the opengl code...?
Thank you very much
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <array>
#include <sstream>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <glfw3.h>
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
using namespace glm;
// Include AntTweakBar
#include <AntTweakBar.h>
#include <common/shader.hpp>
#include <common/controls.hpp>
#include <common/objloader.hpp>
#include <common/vboindexer.hpp>
typedef struct Vertex {
float XYZW[4];
float RGBA[4];
void SetCoords(float *coords) {
XYZW[0] = coords[0];
XYZW[1] = coords[1];
XYZW[2] = coords[2];
XYZW[3] = coords[3];
}
void SetColor(float *color) {
RGBA[0] = color[0];
RGBA[1] = color[1];
RGBA[2] = color[2];
RGBA[3] = color[3];
}
};
// ATTN: USE POINT STRUCTS FOR EASIER COMPUTATIONS
typedef struct point {
float x, y, z;
point(const float x = 0, const float y = 0, const float z = 0) : x(x), y(y), z(z) {};
point(float *coords) : x(coords[0]), y(coords[1]), z(coords[2]) {};
point operator -(const point& a)const {
return point(x - a.x, y - a.y, z - a.z);
}
point operator +(const point& a)const {
return point(x + a.x, y + a.y, z + a.z);
}
point operator *(const float& a)const {
return point(x*a, y*a, z*a);
}
point operator /(const float& a)const {
return point(x / a, y / a, z / a);
}
float* toArray() {
float array[] = { x, y, z, 1.0f };
return array;
}
};
// function prototypes
int initWindow(void);
void initOpenGL(void);
void createVAOs(Vertex[], unsigned short[], size_t, size_t, int);
void createObjects(void);
void pickVertex(void);
void moveVertex(void);
void drawScene(void);
void cleanup(void);
static void mouseCallback(GLFWwindow*, int, int, int);
static void keyCallback(GLFWwindow*, int, int, int, int);
// GLOBAL VARIABLES
GLFWwindow* window;
const GLuint window_width = 1024, window_height = 768;
glm::mat4 gProjectionMatrix;
glm::mat4 gViewMatrix;
GLuint gPickedIndex;
std::string gMessage;
GLuint programID;
GLuint pickingProgramID;
GLuint kthLevel = 0;
// ATTN: INCREASE THIS NUMBER AS YOU CREATE NEW OBJECTS
const GLuint NumObjects = 3; // number of different "objects" to be drawn
GLuint VertexArrayId[NumObjects] = { 0, 1, 2 };
GLuint VertexBufferId[NumObjects] = { 0, 1, 2 };
GLuint IndexBufferId[NumObjects] = { 0, 1, 2 };
size_t NumVert[NumObjects] = { 0, 1, 2 };
GLuint MatrixID;
GLuint ViewMatrixID;
GLuint ModelMatrixID;
GLuint PickingMatrixID;
GLuint pickingColorArrayID;
GLuint pickingColorID;
GLuint LightID;
// Define objects
Vertex Vertices[] =
{
{ { 1.0f, 1.0f, 0.0f, 1.0f },{ 0.0f, 0.0f, 0.0f, 1.0f } }, // 0
{ { 0.0f, 1.4f, 0.0f, 1.0f },{ 0.0f, 0.0f, 1.0f, 1.0f } }, // 1
{ { -1.0f, 1.0f, 0.0f, 1.0f },{ 0.0f, 1.0f, 0.0f, 1.0f } }, // 2
{ { -1.4f, 0.0f, 0.0f, 1.0f },{ 0.0f, 1.0f, 1.0f, 1.0f } }, // 3
{ { -1.0f, -1.0f, 0.0f, 1.0f },{ 1.0f, 0.0f, 0.0f, 1.0f } }, // 4
{ { 0.0f, -1.4f, 0.0f, 1.0f },{ 1.0f, 0.0f, 1.0f, 1.0f } },// 5
{ { 1.0f, -1.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, 0.0f, 1.0f } }, // 6
{ { 1.4f, 0.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1.0f } },// 7
};
Vertex OriginalVertices[] =
{
{ { 1.0f, 1.0f, 0.0f, 1.0f },{ 0.0f, 0.0f, 0.0f, 1.0f } }, // 0
{ { 0.0f, 1.4f, 0.0f, 1.0f },{ 0.0f, 0.0f, 1.0f, 1.0f } }, // 1
{ { -1.0f, 1.0f, 0.0f, 1.0f },{ 0.0f, 1.0f, 0.0f, 1.0f } }, // 2
{ { -1.4f, 0.0f, 0.0f, 1.0f },{ 0.0f, 1.0f, 1.0f, 1.0f } }, // 3
{ { -1.0f, -1.0f, 0.0f, 1.0f },{ 1.0f, 0.0f, 0.0f, 1.0f } }, // 4
{ { 0.0f, -1.4f, 0.0f, 1.0f },{ 1.0f, 0.0f, 1.0f, 1.0f } },// 5
{ { 1.0f, -1.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, 0.0f, 1.0f } }, // 6
{ { 1.4f, 0.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1.0f } },// 7
};
Vertex LineVertices[] =
{
{ { 1.0f, 1.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1.0f } }, // 0
{ { 0.0f, 1.4f, 0.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1.0f } }, // 1
{ { -1.0f, 1.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1.0f } }, // 2
{ { -1.4f, 0.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1.0f } }, // 3
{ { -1.0f, -1.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1.0f } }, // 4
{ { 0.0f, -1.4f, 0.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1.0f } },// 5
{ { 1.0f, -1.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1.0f } }, // 6
{ { 1.4f, 0.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1.0f } },// 7
};
Vertex *kVertices;
Vertex *kPlusOneVertices;
unsigned short *kIndices;
unsigned short *kPlusOneIndices;
//Vertex VTwo[32];
//Vertex VThree[64];
//unsigned short IOne[];
//unsigned short ITwo[];
//unsigned short IThree[];
std::vector<Vertex>TaskTwoVerticesN;
std::vector<unsigned short>TaskTwoIndicesN;
std::vector<Vertex>TaskTwoVerticesNPlusOne;
std::vector<unsigned short>TaskTwoIndicesNPlusOne;
unsigned short Indices[] = {
0, 1, 2, 3, 4, 5, 6, 7
};
unsigned short LineIndices[] = {
0, 1, 2, 3, 4, 5, 6, 7
};
const size_t IndexCount = sizeof(Indices) / sizeof(unsigned short);
// ATTN: DON'T FORGET TO INCREASE THE ARRAY SIZE IN THE PICKING VERTEX SHADER WHEN YOU ADD MORE PICKING COLORS
float pickingColor[IndexCount] = { 0 / 255.0f, 1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f, 5 / 255.0f, 6 / 255.0f, 7 / 255.0f };
// ATTN: ADD YOU PER-OBJECT GLOBAL ARRAY DEFINITIONS HERE
**void createObjects(void)
{
// ATTN: DERIVE YOUR NEW OBJECTS HERE:
// each has one vertices {posCurrent;color} and one indices array (no picking needed here)
if (kthLevel > 4 || kthLevel == 0) {
kthLevel = 0;
TaskTwoVerticesN.clear();
for (int i = 0;i < 8;i++) {
TaskTwoVerticesN.push_back(Vertex());
printf("pushed");
TaskTwoVerticesN[i].XYZW[0] = Vertices[i].XYZW[0];
TaskTwoVerticesN[i].XYZW[1] = Vertices[i].XYZW[1];
TaskTwoVerticesN[i].XYZW[2] = Vertices[i].XYZW[2];
TaskTwoVerticesN[i].XYZW[3] = Vertices[i].XYZW[3];
TaskTwoVerticesN[i].RGBA[0] = Vertices[i].RGBA[0];
TaskTwoVerticesN[i].RGBA[1] = Vertices[i].RGBA[1];
TaskTwoVerticesN[i].RGBA[2] = Vertices[i].RGBA[2];
TaskTwoVerticesN[i].RGBA[3] = Vertices[i].RGBA[3];
}
TaskTwoVerticesN.insert(TaskTwoVerticesN.begin(), Vertices, Vertices + 8);
TaskTwoIndicesN.clear();
TaskTwoIndicesN.insert(TaskTwoIndicesN.begin(), Indices, Indices + (sizeof(Indices) / sizeof(Indices[0])));
printf("\n size of vertices %d\n ", sizeof(TaskTwoVerticesN) / sizeof(TaskTwoVerticesN[0]));
//TaskTwoVerticesNPlusOne = TaskTwoVerticesN;
//TaskTwoIndicesNPlusOne = TaskTwoIndicesN;
kVertices = &TaskTwoVerticesN[0];
kIndices = &TaskTwoIndicesN[0];
//kPlusOneVertices = &TaskTwoVerticesNPlusOne[0];
//kPlusOneIndices = &TaskTwoIndicesNPlusOne[0];
}
else {
GLint numberOfPoints = sizeof(TaskTwoVerticesN) / sizeof(TaskTwoVerticesN[0]);
GLint newPointsLength = (8 * 2 ^ kthLevel);
GLint oldPointsLength = newPointsLength / 2;
printf("\n%d\n", newPointsLength);
Vertex newVertexOne, newVertexTwo;
newVertexOne.RGBA[0] = 0.0f;
newVertexOne.RGBA[1] = 1.0f;
newVertexOne.RGBA[2] = 0.0f;
newVertexOne.RGBA[3] = 1.0f;
newVertexOne.XYZW[2] = 0.0f;
newVertexOne.XYZW[3] = 1.0f;
newVertexTwo = newVertexOne;
for (GLint i = 0; i < oldPointsLength; i++)
{
GLint posMinusTwo = abs(oldPointsLength + i - 2) % oldPointsLength;
GLint posMinusOne = abs(oldPointsLength + i - 1) % oldPointsLength;
GLint posCurrent = abs(i) % oldPointsLength;
GLint posPlusOne = abs(oldPointsLength + i + 1) % oldPointsLength;
GLint newPosOne = abs(2 * i) % newPointsLength;
GLint newPosTwo = abs((2 * i) + 1) % newPointsLength;
float xMinusTwo = TaskTwoVerticesN[posMinusTwo].XYZW[0];
float xMinusOne = TaskTwoVerticesN[posMinusOne].XYZW[0];
float xCurrent = TaskTwoVerticesN[posCurrent].XYZW[0];
float xPlusOne = TaskTwoVerticesN[posPlusOne].XYZW[0];
float yMinusTwo = TaskTwoVerticesN[posMinusTwo].XYZW[1];
float yMinusOne = TaskTwoVerticesN[posMinusOne].XYZW[1];
float yCurrent = TaskTwoVerticesN[posCurrent].XYZW[1];
float yPlusOne = TaskTwoVerticesN[posPlusOne].XYZW[1];
newVertexOne.XYZW[0] = (xMinusTwo + (10 * xMinusOne) + (5 * xCurrent)) / 16;
newVertexOne.XYZW[1] = (yMinusTwo + (10 * yMinusOne) + (5 * yCurrent)) / 16;
TaskTwoVerticesNPlusOne.insert(TaskTwoVerticesNPlusOne.begin() + newPosOne, newVertexOne);
TaskTwoIndicesNPlusOne.insert(TaskTwoIndicesNPlusOne.begin() + newPosOne, newPosOne);
printf("\nIn createObjects");
newVertexTwo.XYZW[0] = (xMinusOne + (10 * xCurrent) + (5 * xPlusOne)) / 16;
newVertexTwo.XYZW[1] = (yMinusOne + (10 * yCurrent) + (5 * yPlusOne)) / 16;
TaskTwoVerticesNPlusOne.insert(TaskTwoVerticesNPlusOne.begin() + newPosTwo, newVertexTwo);
TaskTwoIndicesNPlusOne.insert(TaskTwoIndicesNPlusOne.begin() + newPosTwo, newPosTwo);
}
TaskTwoVerticesN.clear();
TaskTwoVerticesN = TaskTwoVerticesNPlusOne;
TaskTwoIndicesN = TaskTwoIndicesNPlusOne;// is this possible?
//TaskTwoVerticesN.assign(TaskTwoIndicesNPlusOne.begin(), TaskTwoIndicesNPlusOne.end());
kVertices = &TaskTwoVerticesN[0];
kIndices = &TaskTwoIndicesN[0];
kPlusOneVertices = &TaskTwoVerticesNPlusOne[0];
kPlusOneIndices = &TaskTwoIndicesNPlusOne[0];
}
printf("\n%d", kthLevel);
kthLevel++;
}**
void drawScene(void)
{
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
// Re-clear the screen for real rendering
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
{
glm::mat4 ModelMatrix = glm::mat4(1.0); // TranslationMatrix * RotationMatrix;
glm::mat4 MVP = gProjectionMatrix * gViewMatrix * ModelMatrix;
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &gViewMatrix[0][0]);
glm::vec3 lightPos = glm::vec3(4, 4, 4);
glUniform3f(LightID, lightPos.x, lightPos.y, lightPos.z);
glEnable(GL_PROGRAM_POINT_SIZE);
glBindVertexArray(VertexArrayId[0]); // draw Vertices
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[0]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertices), Vertices); // update buffer data
//glDrawElements(GL_LINE_LOOP, NumVert[0], GL_UNSIGNED_SHORT, (void*)0);
glDrawElements(GL_POINTS, NumVert[0], GL_UNSIGNED_SHORT, (void*)0);
// ATTN: OTHER BINDING AND DRAWING COMMANDS GO HERE, one set per object:
//glBindVertexArray(VertexArrayId[<x>]); etc etc
glBindVertexArray(0);
glBindVertexArray(VertexArrayId[1]); // draw Vertices
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[1]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(LineVertices), LineVertices); // update buffer data
glDrawElements(GL_LINE_STRIP, NumVert[1], GL_UNSIGNED_SHORT, (void*)0);
glBindVertexArray(1);
glBindVertexArray(VertexArrayId[2]); // draw Vertices
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[2]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(kPlusOneIndices), kPlusOneVertices); // update buffer data
glDrawElements(GL_LINE_STRIP, NumVert[2], GL_UNSIGNED_SHORT, (void*)0);
glBindVertexArray(2);
}
glUseProgram(0);
// Draw GUI
TwDraw();
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
}
void pickVertex(void)
{
// Clear the screen in white
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(pickingProgramID);
{
glm::mat4 ModelMatrix = glm::mat4(1.0); // TranslationMatrix * RotationMatrix;
glm::mat4 MVP = gProjectionMatrix * gViewMatrix * ModelMatrix;
// Send our transformation to the currently bound shader, in the "MVP" uniform
glUniformMatrix4fv(PickingMatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniform1fv(pickingColorArrayID, NumVert[0], pickingColor); // here we pass in the picking marker array
// Draw the ponts
glEnable(GL_PROGRAM_POINT_SIZE);
glBindVertexArray(VertexArrayId[0]);
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[0]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertices), Vertices); // update buffer data
glDrawElements(GL_POINTS, NumVert[0], GL_UNSIGNED_SHORT, (void*)0);
glBindVertexArray(0);
}
glUseProgram(0);
// Wait until all the pending drawing commands are really done.
// Ultra-mega-over slow !
// There are usually a long time between glDrawElements() and
// all the fragments completely rasterized.
glFlush();
glFinish();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Read the pixel at the center of the screen.
// You can also use glfwGetMousePos().
// Ultra-mega-over slow too, even for 1 pixel,
// because the framebuffer is on the GPU.
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
unsigned char data[4];
glReadPixels(xpos, window_height - ypos, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data); // OpenGL renders with (0,0) on bottom, mouse reports with (0,0) on top
// Convert the color back to an integer ID
gPickedIndex = int(data[0]);
// Uncomment these lines to see the picking shader in effect
//glfwSwapBuffers(window);
//continue; // skips the normal rendering
}
// fill this function in!
void moveVertex(void)
{
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
unsigned char data[4];
glReadPixels(xpos, 768 - ypos, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data); // OpenGL renders with (0,0) on bottom, mouse reports with (0,0) on top
glm::mat4 ModelMatrix = glm::mat4(1.0);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glm::vec4 vp = glm::vec4(viewport[0], viewport[1], viewport[2], viewport[3]);
// retrieve your cursor position
// get your world coordinates
// move points
if (gPickedIndex == 255) { // Full white, must be the background !
gMessage = "background";
}
else {
std::ostringstream oss;
oss << "point " << gPickedIndex;
gMessage = oss.str();
}
if ((glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT)) == GLFW_PRESS) {
printf("\n pressed");
Vertices[gPickedIndex].RGBA[0] = 0.5f;
Vertices[gPickedIndex].RGBA[1] = 0.5f;
Vertices[gPickedIndex].RGBA[2] = 0.5f;
Vertices[gPickedIndex].RGBA[3] = 1.0f;
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glm::vec3 vertex = glm::unProject(glm::vec3(xpos, 768 - ypos, 0.0), ModelMatrix, gProjectionMatrix, vp);
Vertices[gPickedIndex].XYZW[0] = -vertex[0];
Vertices[gPickedIndex].XYZW[1] = vertex[1];
LineVertices[gPickedIndex].XYZW[0] = -vertex[0];
LineVertices[gPickedIndex].XYZW[1] = vertex[1];
}
else {
printf("released");
Vertices[gPickedIndex].RGBA[0] = OriginalVertices[gPickedIndex].RGBA[0];
Vertices[gPickedIndex].RGBA[1] = OriginalVertices[gPickedIndex].RGBA[1];
Vertices[gPickedIndex].RGBA[2] = OriginalVertices[gPickedIndex].RGBA[2];
Vertices[gPickedIndex].RGBA[3] = OriginalVertices[gPickedIndex].RGBA[3];
}
}
int initWindow(void)
{
// Initialise GLFW
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
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);
// Open a window and create its OpenGL context
window = glfwCreateWindow(window_width, window_height, "Lastname,FirstName(ufid)", NULL, NULL);
if (window == NULL) {
fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
// Initialize the GUI
TwInit(TW_OPENGL_CORE, NULL);
TwWindowSize(window_width, window_height);
TwBar * GUI = TwNewBar("Picking");
TwSetParam(GUI, NULL, "refresh", TW_PARAM_CSTRING, 1, "0.1");
TwAddVarRW(GUI, "Last picked object", TW_TYPE_STDSTRING, &gMessage, NULL);
// Set up inputs
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_FALSE);
glfwSetCursorPos(window, window_width / 2, window_height / 2);
glfwSetMouseButtonCallback(window, mouseCallback);
glfwSetKeyCallback(window, keyCallback);
return 0;
}
void initOpenGL(void)
{
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS);
// Cull triangles which normal is not towards the camera
glEnable(GL_CULL_FACE);
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
//glm::mat4 ProjectionMatrix = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
// Or, for an ortho camera :
gProjectionMatrix = glm::ortho(-4.0f, 4.0f, -3.0f, 3.0f, 0.0f, 100.0f); // In world coordinates
// Camera matrix
gViewMatrix = glm::lookAt(
glm::vec3(0, 0, -5), // Camera is at (4,3,3), in World Space
glm::vec3(0, 0, 0), // and looks at the origin
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
// Create and compile our GLSL program from the shaders
programID = LoadShaders("StandardShading.vertexshader", "StandardShading.fragmentshader");
pickingProgramID = LoadShaders("Picking.vertexshader", "Picking.fragmentshader");
// Get a handle for our "MVP" uniform
MatrixID = glGetUniformLocation(programID, "MVP");
ViewMatrixID = glGetUniformLocation(programID, "V");
ModelMatrixID = glGetUniformLocation(programID, "M");
PickingMatrixID = glGetUniformLocation(pickingProgramID, "MVP");
// Get a handle for our "pickingColorID" uniform
pickingColorArrayID = glGetUniformLocation(pickingProgramID, "PickingColorArray");
pickingColorID = glGetUniformLocation(pickingProgramID, "PickingColor");
// Get a handle for our "LightPosition" uniform
LightID = glGetUniformLocation(programID, "LightPosition_worldspace");
createVAOs(Vertices, Indices, sizeof(Vertices), sizeof(Indices), 0);
createVAOs(LineVertices, LineIndices, sizeof(LineVertices), sizeof(LineIndices), 1);
createVAOs(kPlusOneVertices, kPlusOneIndices, sizeof(kPlusOneVertices), sizeof(kPlusOneIndices), 2);
printf("\nVAO");
createObjects();
// ATTN: create VAOs for each of the newly created objects here:
// createVAOs(<fill this appropriately>);
}
void createVAOs(Vertex Vertices[], unsigned short Indices[], size_t BufferSize, size_t IdxBufferSize, int ObjectId) {
NumVert[ObjectId] = IdxBufferSize / (sizeof GLubyte);
GLenum ErrorCheckValue = glGetError();
size_t VertexSize = sizeof(Vertices[0]);
size_t RgbOffset = sizeof(Vertices[0].XYZW);
// Create Vertex Array Object
glGenVertexArrays(1, &VertexArrayId[ObjectId]);
glBindVertexArray(VertexArrayId[ObjectId]);
// Create Buffer for vertex data
glGenBuffers(1, &VertexBufferId[ObjectId]);
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId[ObjectId]);
glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW);
// Create Buffer for indices
glGenBuffers(1, &IndexBufferId[ObjectId]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId[ObjectId]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, IdxBufferSize, Indices, GL_STATIC_DRAW);
// Assign vertex attributes
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, VertexSize, 0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid*)RgbOffset);
glEnableVertexAttribArray(0); // position
glEnableVertexAttribArray(1); // color
// Disable our Vertex Buffer Object
glBindVertexArray(0);
ErrorCheckValue = glGetError();
if (ErrorCheckValue != GL_NO_ERROR)
{
fprintf(
stderr,
"ERROR: Could not create a VBO: %s \n",
gluErrorString(ErrorCheckValue)
);
}
}
void cleanup(void)
{
// Cleanup VBO and shader
for (int i = 0; i < NumObjects; i++) {
glDeleteBuffers(1, &VertexBufferId[i]);
glDeleteBuffers(1, &IndexBufferId[i]);
glDeleteVertexArrays(1, &VertexArrayId[i]);
}
glDeleteProgram(programID);
glDeleteProgram(pickingProgramID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
}
static void mouseCallback(GLFWwindow* window, int button, int action, int mods)
{
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
pickVertex();
}
}
static void keyCallback(GLFWwindow* window, int button, int scancode, int action, int mods) {
if (button == GLFW_KEY_1 && action == GLFW_PRESS) {
createObjects();
//printf("\n1 pressed");
}
}
int main(void)
{
// initialize window
int errorCode = initWindow();
if (errorCode != 0)
return errorCode;
// initialize OpenGL pipeline
initOpenGL();
// For speed computation
double lastTime = glfwGetTime();
int nbFrames = 0;
do {
// Measure speed
double currentTime = glfwGetTime();
nbFrames++;
if (currentTime - lastTime >= 1.0) { // If last prinf() was more than 1sec ago
// printf and reset
printf("%f ms/frame\n", 1000.0 / double(nbFrames));
nbFrames = 0;
lastTime += 1.0;
}
glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, 1);
// DRAGGING: move current (picked) vertex with cursor
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT))
moveVertex();
// DRAWING SCENE
glfwSetKeyCallback(window, keyCallback);
//createObjects(); // re-evaluate curves in case vertices have been moved
drawScene();
} // Check if the ESC key was pressed or the window was closed
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);
cleanup();
return 0;
}
have you tried using arrays like this
bool MAP::InsertVertex(long obj, GLdouble x, GLdouble y, GLdouble z,GLfloat r
,GLfloat g, GLfloat b, GLfloat a,GLfloat nx, GLfloat ny
,GLfloat nz, GLfloat fogdepth)
{
MAP_VERTEX new_vertex;
long rgb = GenerateVertexColor(obj);
if(obj>header.max_objects||obj<0)
return (false);
new_vertex.xyz[0] =x;
new_vertex.xyz[1] =y;
new_vertex.xyz[2] =z;
new_vertex.rgba[0] =r;
new_vertex.rgba[1] =g;
new_vertex.rgba[2] =b;
new_vertex.rgba[3] =a;
new_vertex.normal[0] =nx;
new_vertex.normal[1] =ny;
new_vertex.normal[2] =nz;
new_vertex.fogdepth =fogdepth;
new_vertex.select_rgb[0] = GetRValue(rgb);
new_vertex.select_rgb[1] = GetGValue(rgb);
new_vertex.select_rgb[2] = GetBValue(rgb);
if(object[obj].max_vertices==0) object[obj].vertex = new MAP_VERTEX
[object[obj].max_vertices+1];
else{
//Backing up the vertices that are already there
MAP_VERTEX *temp = new MAP_VERTEX[object[obj].max_vertices+1];
for(long i=0;i<object[obj].max_vertices;i++)
temp[i] = object[obj].vertex[i];
//Deleting the old vertices that were allocated earlier
delete [] object[obj].vertex;
//Now allocating new memory for vertex with an extra buffer
object[obj].vertex = new MAP_VERTEX[object[obj].max_vertices+2];
for(long i=0;i<object[obj].max_vertices;i++)
object[obj].vertex[i] =temp[i];
delete [] temp;
temp = NULL;
}
//Insert a new Vertex
object[obj].vertex[object[obj].max_vertices] = new_vertex;
object[obj].max_vertices++;
return (true);
}

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?

GLFW hangs on close when adding an extra rendering call

So I've been attempting to learn how to program openGL for the past little while and although it has been mind-bending a lot of the time I think I'm beginning to gain a solid understanding of how it works.
I've been using GLFW for window handling and basic input, and GLEW for accessing the extension methods.
I've also been following the tutorial over at www.learnopengl.com and that has been fairly useful. Lately, though, I've been spending some time trying to create some basic abstractions for drawing to screen. When I abstracted away some of the code that the tutorial provided everything went fine (I'm still at the co-ordinate system section of "Getting Started").
After doing that I decided it would be nice to emulate a simple UI overlay where I just have a function that draws a rectangle to the screen in 2-D as opposed to 3-D and just floats above everything else on the screen. Eventually I got something working with different shaders for the UI and the 3-D objects. It successfully draws a colored rectangle to the screen on top of everything else, BUT unfortunately I have this bizarre problem that whenever I try to close the window by setting the glfwSetWindowShouldClose call to true the window can hang indefinitely.
Whenever I remove the call to draw the simple 2-D rectangle this hang goes away and the window closes immediately as expected. Does anyone have any ideas why this might be the case?
Main.cpp
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// GL includes
#include "shader.h"
// GLM Mathemtics
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// Other Libs
#include <SOIL.h>
#include "glfw_x360_button_mappings.h"
#include "cube.h"
#include "texture.h"
// Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void handleControllerInput(GLFWwindow* window);
// GLOBALS!!!
const unsigned int MONITOR_WIDTH = 1920;
const unsigned int MONITOR_HEIGHT = 1080;
const unsigned int SCREEN_WIDTH = 800;
const unsigned int SCREEN_HEIGHT = 600;
float camera_z = -3.0f;
float camera_x = 0.0f;
// The MAIN function, from here we start our application and run our Game loop
int main()
{
// Init GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed
// TODO: Make window position adapt to any sized window.
glfwSetWindowPos(window, (MONITOR_WIDTH / 2) - (SCREEN_WIDTH / 2), (MONITOR_HEIGHT / 2) - (SCREEN_HEIGHT / 2));
glfwMakeContextCurrent(window);
// Set the required callback functions
glfwSetKeyCallback(window, key_callback);
// Initialize GLEW to setup the OpenGL Function pointers
glewExperimental = GL_TRUE;
glewInit();
// Define the viewport dimensions
glViewport(0, 0, 800, 600);
// Setup OpenGL options
glEnable(GL_DEPTH_TEST);
// Setup and compile our shaders
GLuint vert_id = buildShader("shader.vert", GL_VERTEX_SHADER);
GLuint frag_id = buildShader("shader.frag", GL_FRAGMENT_SHADER);
GLuint shader_program_id = buildProgram(vert_id, frag_id);
glDeleteShader(vert_id);
glDeleteShader(frag_id);
vert_id = buildShader("shader_ui.vert", GL_VERTEX_SHADER);
frag_id = buildShader("shader_ui.frag", GL_FRAGMENT_SHADER);
GLuint ui_shader_program_id = buildProgram(vert_id, frag_id);
glDeleteShader(vert_id);
glDeleteShader(frag_id);
// World space positions of our cubes
glm::vec3 cubePositions[] = {
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3(2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3(1.3f, -2.0f, -2.5f),
glm::vec3(1.5f, 2.0f, -2.5f),
glm::vec3(1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
};
// Load and create a texture
GLuint texture1 = create_texture("container.jpg");
GLuint texture2 = create_texture("awesomeface.png");
glm::mat4 view_matrix;
glm::mat4 view_matrix_origin;
glm::mat4 projection_matrix;
view_matrix_origin = glm::translate(view_matrix, glm::vec3(0.0f, 0.0f, 0.0f));
projection_matrix = glm::perspective(45.0f, (float) 512 / (float) 512, 0.1f, 1000.0f);
GLint view_matrix_location = glGetUniformLocation(shader_program_id, "view");
GLint projection_matrix_location = glGetUniformLocation(shader_program_id, "projection");
glUseProgram(shader_program_id);
glUniformMatrix4fv(projection_matrix_location, 1, GL_FALSE, glm::value_ptr(projection_matrix));
Cube test_cube;
init_cube(&test_cube, cube_vertices, sizeof(cube_vertices));
// Game loop
while(!glfwWindowShouldClose(window))
{
// Check and call events
glfwPollEvents();
handleControllerInput(window);
// Clear the colorbuffer
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_program_id);
// Bind Textures using texture units
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glUniform1i(glGetUniformLocation(shader_program_id, "ourTexture1"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUniform1i(glGetUniformLocation(shader_program_id, "ourTexture2"), 1);
glUniform1f(glGetUniformLocation(shader_program_id, "time"), glfwGetTime());
view_matrix = glm::translate(view_matrix_origin, glm::vec3(camera_x, 0.0f, camera_z));
glUniformMatrix4fv(view_matrix_location, 1, GL_FALSE, glm::value_ptr(view_matrix));
/* THIS IS THE OFFENDING DRAW CALL
* IF REMOVED THE WINDOW STOPS HANGING ON CLOSE */
draw_rect(ui_shader_program_id, glm::vec2(0.0f, 0.0f));
for (GLuint i = 0; i < 10; i++)
{
GLfloat angle = glfwGetTime() * 25.0f;
draw_cube(&test_cube, shader_program_id, cubePositions[i], angle);
}
// Swap the buffers
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
std::cout << key << std::endl;
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
void handleControllerInput(GLFWwindow* window)
{
if (glfwJoystickPresent(GLFW_JOYSTICK_1))
{
int size;
const unsigned char* results = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &size);
if (get_current_button_pressed(results, size) == X360_DPAD_DOWN)
{
camera_z += 0.001f;
}
else if (get_current_button_pressed(results, size) == X360_DPAD_UP)
{
camera_z -= 0.001f;
}
if (get_current_button_pressed(results, size) == X360_DPAD_LEFT)
{
camera_x -= 0.001f;
}
else if (get_current_button_pressed(results, size) == X360_DPAD_RIGHT)
{
camera_x += 0.001f;
}
if (get_current_button_pressed(results, size) == X360_B_BUTTON)
{
camera_z = -3.0f;
camera_x = 0.0f;
}
if (get_current_button_pressed(results, size) == X360_BACK_BUTTON)
{
glfwSetWindowShouldClose(window, true);
}
}
}
rect.h
#ifndef RECT_H
#define RECT_H
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
const GLfloat rect_vertices[] = {
0.75f, 0.5f, 1.0f, 0.7f, 0.0f,
0.75f, -0.5f, 1.0f, 0.7f, 0.0f,
-0.75f, 0.5f, 1.0f, 0.7f, 0.0f,
-0.75f, 0.5f, 1.0f, 0.7f, 0.0f,
-0.75f, -0.5f, 1.0f, 0.7f, 0.0f,
0.75f, -0.5f, 1.0f, 0.7f, 0.0f,
};
void draw_rect(GLuint shader_program_id, glm::vec2 position);
#endif
rect.cpp
#include "rect.h"
void draw_rect(GLuint shader_program_id, glm::vec2 position)
{
glUseProgram(shader_program_id);
GLuint vao, vbo;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(rect_vertices), rect_vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*) 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
//glm::mat4 model;
//glm::mat4 view;
//glm::mat4 projection;
//model = glm::translate(model, glm::vec3(position, 0.0f));
//glUniformMatrix4fv(glGetUniformLocation(shader_program_id, "model"), 1, GL_FALSE, glm::value_ptr(model));
//view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
//glUniformMatrix4fv(glGetUniformLocation(shader_program_id, "view"), 1, GL_FALSE, glm::value_ptr(view));
//projection = glm::ortho(0, 800, 0, 600, 1, 1000);
//glUniformMatrix4fv(glGetUniformLocation(shader_program_id, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
shader_ui.vert
#version 330 core
layout (location = 0) in vec2 position;
layout (location = 1) in vec3 color;
out vec3 fragColor;
void main()
{
gl_Position = vec4(position, 0.0f, 1.0f);
fragColor = color;
}
shader_ui.frag
#version 330 core
in vec3 fragColor;
out vec4 color;
void main()
{
color = vec4(fragColor, 1.0f);
}
If I'm failing to provide any pertinent code, please let me know. I think this covers everything necessary to potentially dissect what the problem is, but if not I'll be happy to add anything.
Your draw_rect() function is allocating a new vertex buffer every frame and never freeing it. It would seem that after running the main loop for a short amount of time, enough of these VBOs have built up that freeing them when the program terminates takes a noticeable amount of time. This should be what is causing hangs.
To fix this, simply create a single VBO on initialization and bind it before calling glDrawArrays(). You can free it when the program terminates with glDeleteBuffers().

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

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)