I am writing a program in Windows with C++, OpenGL and Freeglut, to learn how to use it..
The code I have written is working as follows:
#define GLEW_STATIC
#include <iostream>
#include <GL/glew.h>;
#include <freeglut.h>
#include <Windows.h>
#include <stdio.h>
#include <string>
#include <vector>
#include "fstream"
#include <algorithm>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>;
#include <chrono>
GLint partColorUniformLocation;
GLint bufferColorUniformLocation;
GLint vpMatrixUniformLocation;
GLint shows;
float radi = 5.0f;
float angx = 0.30;
float angy = 4.60;
float camX = -cos(angx) * sin(angy) * radi;
float camY = -cos(angx) * cos(angy) * radi;
float camZ = sin(angx) * radi;
float zoom = 5.0f;
float ww0;
float ww1;
float wh0;
float wh1;
float menubar;
float menur = 400;
using namespace std;
using glm::vec3;
using glm::vec4;
using glm::mat3;
using glm::mat4;
mat4 PV;
vector <mat3> Model;
mat3 World = mat3(1.0f);
vec3 UP(0.0f, 0.0f, 1.0f);
HWND hWnd;
HINSTANCE hInst;
float ww;
float wh;
int ln0 = 1280;
int shaderProgram;
unsigned int VBO;
GLuint boxID;
unsigned int VCOx;
unsigned int VCOy;
unsigned int VCOz;
GLuint coordxID;
GLuint coordyID;
GLuint coordzID;
unsigned int VTO;
GLuint ptexID;
GLuint texID;
unsigned int VTO2;
GLuint rptexID;
GLuint rtexID;
vector <char> b;
vector <unsigned char> bu;
GLuint texture0;
GLint mW;
void GetDesktopResolution(int& ww, int& wh);
void getDesktop();
void box();
void coord();
void reshape(int ww, int wh);
void display(void);
void texturemenu();
void bmpsread();
void maketexture0(int tw, int th);
void mouseButton(int button, int state, int x, int y);
void mouseMove(int x, int y);
void installShader();
const char* vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"layout (location = 1) in vec3 inNormal;\n"
"layout (location = 2) in vec3 inColor;\n"
"layout (location = 3) in vec2 tex;\n"
"uniform mat4 VP;\n"
"out vec3 outColor;\n"
"out vec3 Normal;\n"
"out vec2 outTex;\n"
"void main()\n"
"{\n"
" vec4 v = vec4(position, 1.0);\n"
" gl_Position = VP * v;\n"
" outColor = inColor;\n"
" Normal = inNormal;\n"
" outTex = tex;\n"
"}\0";
const char* fragmentShaderSource =
"#version 330 core\n"
"out vec4 color;\n"
"in vec3 outColor;\n"
"in vec3 Normal;\n"
"in vec2 outTex;\n"
"uniform int shows;\n"
"uniform sampler2D texture0;\n"
"uniform vec3 partColor;"
"uniform vec3 bufferColor;"
"void main()\n"
"{\n"
" if (shows == 0) \n"
" {\n"
" color = vec4(bufferColor/255.0, 1.0);\n"
" }\n"
" else if (shows == 1)\n"
" {\n"
" color = vec4(1.0, 1.0, 1.0, 1.0);\n"
" }\n"
" else if (shows == 2)\n"
" {\n"
" color = vec4(partColor, 1.0);\n"
" }\n"
" else if (shows == 3)\n"
" {\n"
" color = texture(texture0, outTex);\n"
" }\n"
"}\n\0";
void GetDesktopResolution(float& ww, float& wh) {
RECT desktop;
const HWND hDesktop = GetDesktopWindow();
GetWindowRect(hDesktop, &desktop);
ww = desktop.right;
wh = desktop.bottom;
}
void getDesktop() {
wh = glutGet(GLUT_WINDOW_HEIGHT);
ww = glutGet(GLUT_WINDOW_WIDTH);
menubar = 35;
ww0 = -(ww - menur) / 10.0f;
ww1 = (ww - menur) / 10.0f;
wh0 = -(wh - menubar) / 10.0f + 30;
wh1 = (wh - menubar) / 10.0f + 30;
zoom = 0.2f;
}
void box() {
vector <float> box;
box.resize(72);
box = {
-10.0f, -10.0f, 20.0f,
10.0f, -10.0f, 20.0f,
10.0f, -10.0f, 20.0f,
10.0f, 10.0f, 20.0f,
10.0f, 10.0f, 20.0f,
-10.0f, 10.0f, 20.0f,
-10.0f, 10.0f, 20.0f,
-10.0f, -10.0f, 20.0f,
-10.0f, -10.0f, 0.0f,
10.0f, -10.0f, 0.0f,
10.0f, -10.0f, 0.0f,
10.0f, 10.0f, 0.0f,
10.0f, 10.0f, 0.0f,
-10.0f, 10.0f, 0.0f,
-10.0f, 10.0f, 0.0f,
-10.0f, -10.0f, 0.0f,
-10.0f, -10.0f, 20.0f,
-10.0f, -10.0f, 0.0f,
10.0f, -10.0f, 20.0f,
10.0f, -10.0f, 0.0f,
10.0f, 10.0f, 20.0f,
10.0f, 10.0f, 0.0f,
-10.0f, 10.0f, 20.0f,
-10.0f, 10.0f, 0.0f
};
glGenBuffers(1, &boxID);
glBindBuffer(GL_ARRAY_BUFFER, boxID);
glBufferData(GL_ARRAY_BUFFER, box.size() * sizeof(float), box.data(), GL_STATIC_DRAW);
box.clear();
glGenVertexArrays(1, &VBO);
glBindVertexArray(VBO);
glBindBuffer(GL_ARRAY_BUFFER, boxID);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindVertexArray(0);
}
void coord() {
vector <float> coordx(6);
coordx = {
0.0f, 0.0f, 0.0f,
10.0f, 0.0f, 0.0f
};
vector <float> coordy(6);
coordy = {
0.0f, 0.0f, 0.0f,
0.0f, 10.0f, 0.0f
};
vector <float> coordz(6);
coordz = {
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 10.0f
};
glGenBuffers(1, &coordxID);
glBindBuffer(GL_ARRAY_BUFFER, coordxID);
glBufferData(GL_ARRAY_BUFFER, coordx.size() * sizeof(float), coordx.data(), GL_STATIC_DRAW);
coordx.clear();
glGenBuffers(1, &coordyID);
glBindBuffer(GL_ARRAY_BUFFER, coordyID);
glBufferData(GL_ARRAY_BUFFER, coordy.size() * sizeof(float), coordy.data(), GL_STATIC_DRAW);
coordy.clear();
glGenBuffers(1, &coordzID);
glBindBuffer(GL_ARRAY_BUFFER, coordzID);
glBufferData(GL_ARRAY_BUFFER, coordz.size() * sizeof(float), coordz.data(), GL_STATIC_DRAW);
coordz.clear();
glGenVertexArrays(1, &VCOx);
glBindVertexArray(VCOx);
glBindBuffer(GL_ARRAY_BUFFER, coordxID);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glGenVertexArrays(1, &VCOy);
glBindVertexArray(VCOy);
glBindBuffer(GL_ARRAY_BUFFER, coordyID);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glGenVertexArrays(1, &VCOz);
glBindVertexArray(VCOz);
glBindBuffer(GL_ARRAY_BUFFER, coordzID);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindVertexArray(0);
}
void reshape(int ww, int wh) {
getDesktop();
glClearColor(0.7f, 0.7f, 0.7f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgram);
partColorUniformLocation = glGetUniformLocation(shaderProgram, "partColor");
bufferColorUniformLocation = glGetUniformLocation(shaderProgram, "bufferColor");
vpMatrixUniformLocation = glGetUniformLocation(shaderProgram, "VP");
shows = glGetUniformLocation(shaderProgram, "shows");
}
void display(void) {
glClearColor(0.7f, 0.7f, 0.7f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, ww - menur, wh - menubar);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glFrontFace(GL_CW);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
mat4 Projection = glm::ortho(ww0, ww1, wh0, wh1, -1000.0f, 1000.0f); //left, right, bottom, top, zNear, zFar
mat4 View = glm::lookAt(glm::vec3(camX, camY, camZ), glm::vec3(0.0f, 0.0f, 0.0f), UP);
mat4 VP = Projection * View;
vec3 partColor;
glUniformMatrix4fv(vpMatrixUniformLocation, 1, GL_FALSE, &VP[0][0]);
glUniform1i(shows, 2);
glLineWidth(2);
glBindVertexArray(VCOx); // Coordx
partColor = vec3(1.0f, 0.0f, 0.0f);
glUniform3fv(partColorUniformLocation, 1, &partColor[0]);
glDrawArrays(GL_LINES, 0, 2);
glBindVertexArray(VCOy); // Coordy
partColor = vec3(0.0f, 1.0f, 0.0f);
glUniform3fv(partColorUniformLocation, 1, &partColor[0]);
glDrawArrays(GL_LINES, 0, 2);
glBindVertexArray(VCOz); // Coordz
partColor = vec3(0.0f, 0.0f, 1.0f);
glUniform3fv(partColorUniformLocation, 1, &partColor[0]);
glDrawArrays(GL_LINES, 0, 2);
glBindVertexArray(VBO); // Box
partColor = vec3(1.0f, 1.0f, 1.0f);
glUniform3fv(partColorUniformLocation, 1, &partColor[0]);
glDrawArrays(GL_LINES, 0, 24);
glUniform1i(shows, 1);
glDisable(GL_DEPTH_TEST);
glViewport(0, wh - 35, ww, wh);
VP = glm::ortho(0.0f, ww, 0.0f, 35.0f) * glm::mat4(1.0f); //left, right, bottom, top
glUniformMatrix4fv(vpMatrixUniformLocation, 1, GL_FALSE, &VP[0][0]);
glBindVertexArray(VTO2);
glDrawArrays(GL_TRIANGLES, 0, 6);
glEnable(GL_TEXTURE0);
glUniform1i(shows, 3);
glViewport(0, wh - menubar, ln0, 35);
VP = glm::ortho(0.0f, float(ln0), 0.0f, 35.0f) * glm::mat4(1.0f); //left, right, bottom, top
glUniformMatrix4fv(vpMatrixUniformLocation, 1, GL_FALSE, &VP[0][0]);
glBindVertexArray(VTO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisable(GL_TEXTURE0);
glutSwapBuffers();
}
void texturemenu() {
vector <float> ptex(18);
float top = 35;
float bottom = 0;
float left = 0;
float right = 1280;
ptex = {
right, top, 0.0f,
left, top, 0.0f,
left, bottom, 0.0f,
left, bottom, 0.0f,
right, bottom, 0.0f,
right, top, 0.0f
};
vector <float> tex(12);
tex = {
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
glGenBuffers(1, &ptexID);
glBindBuffer(GL_ARRAY_BUFFER, ptexID);
glBufferData(GL_ARRAY_BUFFER, ptex.size() * sizeof(float), ptex.data(), GL_STATIC_DRAW);
ptex.clear();
glGenTextures(1, &texID);
glBindBuffer(GL_ARRAY_BUFFER, texID);
glBufferData(GL_ARRAY_BUFFER, tex.size() * sizeof(float), tex.data(), GL_STATIC_DRAW);
tex.clear();
glGenVertexArrays(1, &VTO);
glBindVertexArray(VTO);
glBindBuffer(GL_ARRAY_BUFFER, ptexID);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, texID);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindVertexArray(0);
}
void bmpsread() {
bu.clear();
bu.resize(3 * 35 * ln0, 255);
int bmpn = 0;
string sbmp;
sbmp = "C:/C++/icons/dll/new.bmp";
if (sbmp.size() > 0) {
ifstream fo;
unsigned int fn = 0;
fo.open(sbmp, std::ios::binary | std::ios::in);
if (fo.is_open()) {
std::ifstream in_file(sbmp, std::ios::binary | std::ios::ate);
fo.seekg(0, std::ios::beg);
int file_size = in_file.tellg();
fn = file_size;
b.resize(fn);
fo.seekg(0, std::ios::beg);
fo.read(b.data(), fn);
}
fo.close();
fo.clear();
int dataPos = *(int*)&(b[0x0A]);
int www = *(int*)&(b[0x12]);
int ka = 0;
int kx = ceil((((float)www * 3) + 1) / 4) * 4 - www * 3;
if (kx == 4) { kx = 0; }
for (int i = 0; i < 35; i++) {
for (int j = 0; j < www; j++) {
bu[i * ln0 * 3 + (bmpn + j) * 3] = (unsigned char)b[i * www * 3 + j * 3 + ka + dataPos];
bu[i * ln0 * 3 + (bmpn + j) * 3 + 1] = (unsigned char)b[i * www * 3 + j * 3 + ka + 1 + dataPos];
bu[i * ln0 * 3 + (bmpn + j) * 3 + 2] = (unsigned char)b[i * www * 3 + j * 3 + ka + 2 + dataPos];
}
ka += kx;
}
b.clear();
}
bmpn += 37;
}
void maketexture0(int tw, int th) {
glGenTextures(1, &texture0);
auto textureUniformLocation = glGetUniformLocation(shaderProgram, "texture0");
glUniform1i(texture0, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture0);
glEnable(GL_TEXTURE0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_BGR, GL_UNSIGNED_BYTE, bu.data());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
bu.clear();
}
void installShader() {
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDetachShader(shaderProgram, vertexShader);
glDetachShader(shaderProgram, fragmentShader);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitWindowSize(800, 600);
mW = glutCreateWindow(" Texture Test");
glewInit();
HWND win_handle = FindWindow(0, L" Texture Test");
WNDCLASS wc = { 0 };
if (!win_handle) {
return -1;
}
SetWindowLong(win_handle, GWL_STYLE, (GetWindowLong(win_handle, GWL_STYLE) | WS_MAXIMIZE));
ShowWindowAsync(win_handle, SW_SHOWDEFAULT);
ShowWindowAsync(win_handle, SW_SHOWMAXIMIZED);
box();
coord();
installShader();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
Without Texture:
But after I add texture to create a menu bar (in this sample a "new.bmp" picture) with adding following code after "coord();" in "int main(int argc, char** argv)":
bmpsread();
texturemenu();
maketexture0(ln0, 35);
Then my box disappears and my coordinates are wrong.
With Texture:
What am I doing wrong?
Related
After scaling model2 matrix. model2 matrix is matrix of grid
Before
I want to increase size of grid not cube. Why is it happened? Why scale set y of cube to 0? Where is the mistake? All my code below.
Look at draw_canvas.cpp paintGL function, there is scaling matrix with name 'model2'. This line model2.scale(10.0f,0.0f,10.0f). Why this scaling changes my cube?
QMatrix4x4 model2(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
unsigned int modelID2 = gridShaderProgram->uniformLocation("model");
model2.translate(QVector3D(0.0f, 0.0f, 0.0f));
model2.scale(10.0f, 0.0f, 10.0f);
draw_canwas3D.h
#pragma once
#include <QOpenGLWidget>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
#include <list>
class Canvas3D : public QOpenGLWidget
{
public:
Canvas3D(QWidget *parent = nullptr) : QOpenGLWidget(parent) { };
~Canvas3D();
private:
QOpenGLVertexArrayObject m_vao;
QOpenGLBuffer m_vbo;
QOpenGLShaderProgram* m_program;
QOpenGLShaderProgram* gridShaderProgram;
QOpenGLShaderProgram* shLightprogram;
QVector3D cameraPos {0.0f, 0.0f, 3.0f};
QVector3D cameraFront{0.0f, 0.0f, -1.0f};
QVector3D cameraUp{0.0f, 1.0f, 0.0f};
float yaw = -90.0f;
float pitch = 0.0f;
float lastX = 400, lastY = 300;
float Zoom = 45.0;
unsigned int gridVAO;
unsigned int gridEBO;
GLuint lenght = 0;
//std::list<Object*>
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
void keyPressEvent(QKeyEvent *ev) override;
bool eventFilter(QObject *obj, QEvent *event);
};
draw_canvas3D.cpp
#include "draw_canvas3D.h"
#include "src/common/geometry/shapes3D/cube.h"
#include <iostream>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QOpenGLExtraFunctions>
#include <QMatrix4x4>
#include <QVector3D>
#include <QtMath>
#include <QKeyEvent>
void Canvas3D::initializeGL()
{
connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
auto functions = this->context()->functions();
functions->glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
this->setGeometry(100, 100, 800, 600);
functions->glViewport(this->geometry().x(),
this->geometry().y(),
this->geometry().width(),
this->geometry().height());
m_program = new QOpenGLShaderProgram(this);
QOpenGLShader vxShader(QOpenGLShader::Vertex);
vxShader.compileSourceFile("/main/stage/home/andreyp/fork_invar/invar/shaders/shader.vs");
QOpenGLShader frShader(QOpenGLShader::Fragment);
frShader.compileSourceFile("/main/stage/home/andreyp/fork_invar/invar/shaders/shader.fs");
m_program->addShader(&vxShader);
m_program->addShader(&frShader);
m_program->link();
functions->glEnable(GL_DEPTH_TEST);
this->installEventFilter(this);
functions->glEnable(GL_POLYGON_SMOOTH);
functions->glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
functions->glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
/*GRID*/ //Create Class
auto additionalFunctions = this->context()->extraFunctions();
unsigned int gridVBO;
std::vector<QVector3D> vertices;
std::vector<unsigned int> indices;
int slices = 10;
for(int j=0; j<=slices; ++j) {
for(int i=0; i<=slices; ++i) {
float x = (float)i/(float)slices;
float y = 0;
float z = (float)j/(float)slices;
vertices.push_back(QVector3D(x, y, z));
}
}
for(int j=0; j<slices; ++j) {
for(int i=0; i<slices; ++i) {
int row1 = j * (slices+1);
int row2 = (j+1) * (slices+1);
indices.push_back(row1+i); indices.push_back(row1+i+1); indices.push_back(row1+i+1); indices.push_back(row2+i+1);
indices.push_back(row2+i+1); indices.push_back(row2+i); indices.push_back(row2+i); indices.push_back(row1+i);
}
}
lenght = (GLuint)indices.size()*4;
/*std::vector<QVector3D> vecLines;
std::vector<unsigned int> vecLinesIdx;*/
/*for(unsigned int nHorizontalLines = 0; nHorizontalLines < 10; ++nHorizontalLines)
{
vecLines.push_back(QVector3D(0.0f, 0.0, -(float)nHorizontalLines));
vecLines.push_back(QVector3D(9.0f, 0.0, -(float)nHorizontalLines));
}
for(unsigned int nVerticalLines = 0; nVerticalLines < 10; ++nVerticalLines)
{
vecLines.push_back(QVector3D((float)nVerticalLines, 0.0f, 0.0f));
vecLines.push_back(QVector3D((float)nVerticalLines, 0.0f, -9.0f));
}
for(unsigned int j = 0; j < 39; j+=2)
{
vecLinesIdx.push_back(j);
vecLinesIdx.push_back(j+1);
}*/
functions->glGenBuffers(1, &gridEBO);
functions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gridEBO);
functions->glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
functions->glGenBuffers(1, &gridVBO);
additionalFunctions->glGenVertexArrays(1, &gridVAO);
additionalFunctions->glBindVertexArray(gridVAO);
functions->glBindBuffer(GL_ARRAY_BUFFER, gridVBO);
functions->glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(QVector3D), vertices.data(), GL_STATIC_DRAW);
functions->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), nullptr);
functions->glEnableVertexAttribArray(0);
gridShaderProgram = new QOpenGLShaderProgram(this);
QOpenGLShader vxShader2(QOpenGLShader::Vertex);
vxShader2.compileSourceFile("/main/stage/home/andreyp/fork_invar/invar/shaders/shaderGrid.vs");
QOpenGLShader frShader2(QOpenGLShader::Fragment);
frShader2.compileSourceFile("/main/stage/home/andreyp/fork_invar/invar/shaders/shaderGrid.fs");
gridShaderProgram->addShader(&vxShader2);
gridShaderProgram->addShader(&frShader2);
gridShaderProgram->link();
/*GRID END*/
}
void Canvas3D::resizeGL(int w, int h)
{
auto functions = this->context()->functions();
functions->glViewport(0,
0,
this->geometry().width(),
this->geometry().height());
}
void Canvas3D::paintGL()
{
auto functions = this->context()->functions();
//auto additionalFunctions = this->context()->extraFunctions();
functions->glClearColor(0.0f / 255.0f, 25.0f / 255.0f, 53.0f / 255.0f, 1.0f);
functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 projection;
projection.perspective(Zoom, 800.0f / 600.0f, 0.1f, 100.0f);
QMatrix4x4 view;
view.lookAt(cameraPos,
cameraPos + cameraFront,
cameraUp);
unsigned int viewID = m_program->uniformLocation("view");
functions->glUniformMatrix4fv(viewID, 1, GL_FALSE, view.constData());
unsigned int projectionID = m_program->uniformLocation("projection");
functions->glUniformMatrix4fv(projectionID, 1, GL_FALSE, projection.constData());
QVector3D cubePositions[] = {
QVector3D(0.0f, 0.0, 0.0),
QVector3D( 0.5f, 0.0f, 0.5f),
QVector3D( 2.0f, 0.0f, 3.0f),
QVector3D(-1.5f, -2.2f, -2.5f),
QVector3D(-3.8f, -2.0f, -12.3f),
QVector3D( 2.4f, -0.4f, -3.5f),
QVector3D(-1.7f, 3.0f, -7.5f),
QVector3D( 1.3f, -2.0f, -2.5f),
QVector3D( 1.5f, 2.0f, -2.5f),
QVector3D( 1.5f, 0.2f, -1.5f),
QVector3D(-1.3f, 1.0f, -1.5f)
};
for(unsigned int i = 0; i < 2; i++)
{
QMatrix4x4 model(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
unsigned int modelID = m_program->uniformLocation("model");
model.translate(cubePositions[i]);
functions->glUniformMatrix4fv(modelID, 1, GL_FALSE, model.constData());
auto cube3d = new invar::geometry3D::Cube(cubePositions[i], 1*qSqrt(3), m_program);
cube3d->Draw();
}
auto additionalFunctions = this->context()->extraFunctions();
additionalFunctions->glBindVertexArray(0);
/*GRID*/
unsigned int viewID2 = gridShaderProgram->uniformLocation("view");
functions->glUniformMatrix4fv(viewID2, 1, GL_FALSE, view.constData());
unsigned int projectionID2 = gridShaderProgram->uniformLocation("projection");
functions->glUniformMatrix4fv(projectionID2, 1, GL_FALSE, projection.constData());
QMatrix4x4 model2(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
unsigned int modelID2 = gridShaderProgram->uniformLocation("model");
//model2.scale(10.0f, 0.0f, 10.0f); ------ THIS SCALING
model2.translate(QVector3D(0.0f, 0.0f, 0.0f));
functions->glUniformMatrix4fv(modelID2, 1, GL_FALSE, model2.constData());
gridShaderProgram->bind();
additionalFunctions->glBindVertexArray(gridVAO);
functions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gridEBO);
functions->glDrawElements(GL_LINES, lenght, GL_UNSIGNED_INT, 0);
/*GRID END*/
}
void Canvas3D::keyPressEvent(QKeyEvent *ev)
{
const float cameraSpeed = 0.25f;
if(ev->key() == Qt::Key_W)
cameraPos += cameraSpeed * cameraFront;
else if(ev->key() == Qt::Key_S)
cameraPos -= cameraSpeed * cameraFront;
else if(ev->key() == Qt::Key_A)
cameraPos -= QVector3D(QVector3D::crossProduct(cameraFront, cameraUp)) * cameraSpeed;
else if(ev->key() == Qt::Key_D)
cameraPos += QVector3D(QVector3D::crossProduct(cameraFront, cameraUp)) * cameraSpeed;
else if(ev->key() == Qt::Key_Q)
{
/*Rotate camera*/
}
else if(ev->key() == Qt::Key_E)
{
/*Rotate camera*/
}
}
bool Canvas3D::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
lastX = mouseEvent->pos().x();
lastY = mouseEvent->pos().y();
}
if (event->type() == QEvent::MouseMove)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
float xoffset = mouseEvent->pos().x() - lastX;
float yoffset = lastY - mouseEvent->pos().y();
lastX = mouseEvent->pos().x();
lastY = mouseEvent->pos().y();
float sensitivity = 0.1f;
xoffset *= sensitivity;
yoffset *= sensitivity;
yaw += xoffset;
pitch += yoffset;
if(pitch > 89.0f)
pitch = 89.0f;
if(pitch < -89.0f)
pitch = -89.0f;
QVector3D direction;
direction.setX(qCos(qDegreesToRadians(yaw)) * qCos(qDegreesToRadians(pitch)));
direction.setY(qSin(qDegreesToRadians(pitch)));
direction.setZ(qSin(qDegreesToRadians(yaw)) * qCos(qDegreesToRadians(pitch)));
cameraFront = direction.normalized();
}
else if (event->type() == QEvent::Wheel)
{
QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
QPoint numDegrees = wheelEvent->angleDelta();
if (numDegrees.y() < 0 && Zoom < 45.0f)
Zoom += 1.0f;
if (numDegrees.y() > 0 && Zoom > 1.0f)
Zoom -= 1.0f;
}
return false;
}
Canvas3D::~Canvas3D()
{
//delete f;
}
cube.cpp
#include "src/common/geometry/shapes3D/cube.h"
#include <QOpenGLExtraFunctions>
#include <QOpenGLWidget>
#include <QOpenGLContext>
#include <QtMath>
#include <iostream>
namespace invar::geometry3D
{
void Cube::Draw()
{
auto context = QOpenGLContext::currentContext();
auto functions = context->functions();
auto additionalFunctions = context->extraFunctions();
m_program->bind();
additionalFunctions->glBindVertexArray(VAO);
functions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
int size;
functions->glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
functions->glDrawElements(GL_TRIANGLES, size/sizeof(float), GL_UNSIGNED_INT, 0);
}
void Cube::setupShape()
{
auto context = QOpenGLContext::currentContext();
auto functions = context->functions();
auto additionalFunctions = context->extraFunctions();
float vertices[] = {
-0.5f,0.5f,-0.5f, 0.0f, 0.0f, 0.0f,//Point A 0
-0.5f,0.5f,0.5f, 0.0f, 0.0f, 1.0f,//Point B 1
0.5f,0.5f,-0.5f, 0.0f, 1.0f, 0.0f,//Point C 2
0.5f,0.5f,0.5f, 0.0f, 1.0f, 1.0f,//Point D 3
-0.5f,-0.5f,-0.5f, 1.0f, 0.0f, 0.0f,//Point E 4
-0.5f,-0.5f,0.5f, 1.0f, 0.0f, 1.0f,//Point F 5
0.5f,-0.5f,-0.5f, 1.0f, 1.0f, 0.0f,//Point G 6
0.5f,-0.5f,0.5f, 1.0f, 1.0f, 1.0f//Point H 7
};
unsigned int indices[] = {
0,1,2,
1,2,3,
4,5,6,
5,6,7,
0,1,5,
0,4,5,
2,3,7,
2,6,7,
0,2,6,
0,4,6,
1,5,7,
1,3,7
};
functions->glGenBuffers(1, &EBO);
functions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
functions->glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
unsigned int VBO;
functions->glGenBuffers(1, &VBO);
additionalFunctions->glGenVertexArrays(1, &VAO);
additionalFunctions->glBindVertexArray(VAO);
functions->glBindBuffer(GL_ARRAY_BUFFER, VBO);
functions->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
functions->glEnableVertexAttribArray(0);/*Check if need to normilize*/
functions->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float),(void*)0);
functions->glEnableVertexAttribArray(1);
functions->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float),
(void*)(3*sizeof(float)));
additionalFunctions->glBindVertexArray(0);
}
Cube::Cube(QVector3D pos, float diagonal, QOpenGLShaderProgram* m_program):
pos(pos), diagonal(diagonal), m_program(m_program)
{
this->setupShape();
}
}
cube.h
#pragma once
#include "shape3D.h"
#include <QOpenGLContext>
#include <QVector3D>
#include <QOpenGLShaderProgram>
namespace invar::geometry3D
{
class Cube
{
public:
Cube(QVector3D pos, float diagonal, QOpenGLShaderProgram* program);
void Draw();
private:
unsigned int VAO;
unsigned int EBO;
QVector3D pos;
float diagonal;
QOpenGLShaderProgram* m_program;
void setupShape();
};
}
Shaders is simple
shaderGrid.fs
#version 130
out vec4 FragColor;
void main()
{
FragColor = vec4(0, 1.0, 1.0, 1.0);
}
shaderGrid.vs
#version 130
in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
shader.fs //--- CUBE FRAGMENT SHADER
#version 130
out vec4 FragColor;
in vec3 ourColor;
void main()
{
FragColor = vec4(ourColor, 1.0);
}
shader.vs //--- CUBE VERTEX SHADER
#version 130
in vec3 aPos;
in vec3 aColor;
out vec3 ourColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
ourColor = aColor;
}
glUniform* changes a uniform of the currently installed shader program. Therefore, you must install (bind) the program before setting the uniforms:
gridShaderProgram->bind(); // <--- INSERT
unsigned int viewID2 = gridShaderProgram->uniformLocation("view");
functions->glUniformMatrix4fv(viewID2, 1, GL_FALSE, view.constData());
unsigned int projectionID2 = gridShaderProgram->uniformLocation("projection");
functions->glUniformMatrix4fv(projectionID2, 1, GL_FALSE, projection.constData());
QMatrix4x4 model2(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
unsigned int modelID2 = gridShaderProgram->uniformLocation("model");
//model2.scale(10.0f, 0.0f, 10.0f); ------ THIS SCALING
model2.translate(QVector3D(0.0f, 0.0f, 0.0f));
functions->glUniformMatrix4fv(modelID2, 1, GL_FALSE, model2.constData());
// gridShaderProgram->bind(); <--- DELETE
I can't get instanced geometry to work with a compute shader (I got both things work in isolation but don't know how to combine them). Below is an example that renders instances of a colored quad with different offsets. I'd like to be able to update those offsets via a compute shader.
#define COMPUTE_UPDATE
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "Shader.h"
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glEnable(GL_DEPTH_TEST);
Shader shader("res/shaders/instanced.vs", "res/shaders/instanced.fs");
Shader compute("res/shaders/instanced.glsl");
float translations[200];
int index = 0;
float offset = 0.1f;
for (int y = -10; y < 10; y += 2)
{
for (int x = -10; x < 10; x += 2)
{
float translation[2];
translation[0] = (float)x / 10.0f + offset;
translation[1] = (float)y / 10.0f + offset;
translations[index++] = translation[0];
translations[index++] = translation[1];
}
}
unsigned int instanceVBO;
glGenBuffers(1, &instanceVBO);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, 2 * sizeof(float) * 100, &translations[0], GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
float quadVertices[] = {
// positions // colors
-0.05f, 0.05f, 1.0f, 0.0f, 0.0f,
0.05f, -0.05f, 0.0f, 1.0f, 0.0f,
-0.05f, -0.05f, 0.0f, 0.0f, 1.0f,
-0.05f, 0.05f, 1.0f, 0.0f, 0.0f,
0.05f, -0.05f, 0.0f, 1.0f, 0.0f,
0.05f, 0.05f, 0.0f, 1.0f, 1.0f
};
unsigned int quadVAO, quadVBO;
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(2 * sizeof(float)));
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glVertexAttribDivisor(2, 1);
while (!glfwWindowShouldClose(window))
{
#ifdef COMPUTE_UPDATE
// update instanced buffer
compute.Use();
glBindVertexArray(quadVAO);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, instanceVBO);
glDispatchCompute(1, 1, 1);
glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
#endif
// render
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw 100 instanced quads
shader.Use();
glBindVertexArray(quadVAO);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 100); // 100 triangles of 6 vertices each
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &quadVAO);
glDeleteBuffers(1, &quadVBO);
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
Compute shader:
#version 460 core
struct Particle {
vec2 pos;
};
layout(std430, binding = 1) buffer particleBuffer
{
Particle particles[];
};
layout(local_size_x = 100, local_size_y = 1, local_size_z = 1) in;
void main() {
uint i = gl_GlobalInvocationID.x;
particles[i].pos += vec2(0.01, 0.0);
}
Vertex shader:
#version 460 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aOffset;
out vec3 fColor;
void main()
{
fColor = aColor;
gl_Position = vec4(aPos + aOffset, 0.0, 1.0);
}
The piece of code you find below draws a cube with a camera inside of it.
I don't understand why when I press escape key or the right, left, up and down arrow keys the program doesn't catch the event.
Inside key_callback I've added std::cout << key << std::endl; expecting to see on the console the identifier of the pressed keys, but everytime I press any keys nothing is printed in the console.
#include <cstdlib>
#include <iostream>
#include <vector>
#include <array>
#include <chrono>
using timer = std::chrono::high_resolution_clock;
#ifdef _WIN32
#include <GL/glew.h>
#else
#define GLFW_INCLUDE_GLCOREARB
#define GL_GLEXT_PROTOTYPES
#endif
#define PI 3.1415926535897932384626433832795f
#include <GLFW/glfw3.h>
#include "lodepng.hpp"
#define GLM_FORCE_RADIANS
#include "glm/glm.hpp"
#include "glm/gtx/norm.hpp"
#include "glm/gtx/rotate_vector.hpp"
#include "glm/gtc/matrix_transform.hpp"
#if defined(_MSC_VER)
#pragma comment(lib,"user32")
#pragma comment(lib,"gdi32")
#pragma comment(lib,"opengl32")
#pragma comment(lib,"glew32")
#pragma comment(lib,"glfw3")
#endif
glm::vec3 camera_position(0.0f, 0.0f, 6.0f);
glm::vec3 camera_direction(0.0f, 0.0f, -1.0f);
glm::vec3 camera_up(0.0f, 1.0f, 0.0f);
using timer = std::chrono::high_resolution_clock;
timer::time_point start_time, last_time;
float t = 0.0;
float dt = 0.0;
bool translate_forward = false;
bool translate_backward = false;
bool translate_right = false;
bool translate_left = false;
bool rotate_up = false;
bool rotate_down = false;
bool rotate_right = false;
bool rotate_left = false;
bool rotate_z_left = false;
bool rotate_z_right = false;
bool sky_on = true;
bool sun_visible = true;
bool earth_visible = true;
bool moon_visible = true;
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
GLuint tex_flag;
static void error_callback(int error, const char* description)
{
std::cerr << description << std::endl;
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
std::cout << key << std::endl;
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if (key == GLFW_KEY_UP)
{
if (action)
rotate_up = true;
else
rotate_up = false;
}
if (key == GLFW_KEY_DOWN)
{
if (action)
rotate_down = true;
else
rotate_down = false;
}
if (key == GLFW_KEY_RIGHT)
{
if (action)
rotate_right = true;
else
rotate_right = false;
}
if (key == GLFW_KEY_LEFT)
{
if (action)
rotate_left = true;
else
rotate_left = false;
}
}
// Shader sources
const GLchar* vertexSource =
#if defined(__APPLE_CC__)
"#version 150 core\n"
#else
"#version 130\n"
#endif
"in vec3 position;"
"in vec3 color;"
"in vec2 coord;"
"out vec3 Color;"
"out vec2 Coord;"
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 projection;"
"void main() {"
" Color = color;"
" Coord = coord;"
" gl_Position = projection * view * model * vec4(position, 1.0);"
"}";
const GLchar* fragmentSource =
#if defined(__APPLE_CC__)
"#version 150 core\n"
#else
"#version 130\n"
#endif
"in vec3 Color;"
"in vec2 Coord;"
"out vec4 outColor;"
"uniform sampler2D textureSampler;"
"void main() {"
" outColor = vec4(Color, 1.0)*texture(textureSampler, Coord);"
"}";
const GLfloat vertices[] = {
// Position Color Texcoords
-0.5f, 0.5f, -0.5f, 0.15f, 0.33f, 0.55f, .25f, 0.0f, // 0
0.5f, 0.5f, -0.5f, 0.15f, 0.33f, 0.55f, 0.5f, 0.0f, // 1
-0.5f, 0.5f, -0.5f, 0.15f, 0.33f, 0.55f, 0.0f, 1.f / 3.f, // 2
-0.5f, 0.5f, 0.5f, 0.15f, 0.33f, 0.55f, .25f, 1.f / 3.f, // 3
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.5f, 1.f / 3.f, // 4
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, .75f, 1.f / 3.f, // 5
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.f / 3.f, // 6
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 2.f / 3.f, // 7
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, .25f, 2.f / 3.f, // 8
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.5f, 2.f / 3.f, // 9
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, .75f, 2.f / 3.f, // 10
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 2.f / 3.f, // 11
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, .25f, 1.0f, // 12
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.5f, 1.0f, // 13
};
const GLuint elements[] = {
0, 3, 4, 0, 4, 1,
2, 7, 8, 2, 8, 3,
3, 8, 9, 3, 9, 4,
4, 9,10, 4,10, 5,
5,10,11, 5,11, 6,
8,12,13, 8,13, 9
};
GLuint vao;
GLuint vbo;
GLuint ibo;
GLuint shaderProgram;
GLuint textures[1];
float t = 0;
void check(int line)
{
GLenum error = glGetError();
while (error != GL_NO_ERROR)
{
switch (error)
{
case GL_INVALID_ENUM: std::cout << "GL_INVALID_ENUM : " << line << std::endl; break;
case GL_INVALID_VALUE: std::cout << "GL_INVALID_VALUE : " << line << std::endl; break;
case GL_INVALID_OPERATION: std::cout << "GL_INVALID_OPERATION : " << line << std::endl; break;
case GL_OUT_OF_MEMORY: std::cout << "GL_OUT_OF_MEMORY : " << line << std::endl; break;
default: std::cout << "Unrecognized error : " << line << std::endl; break;
}
error = glGetError();
}
}
void initialize_shader()
{
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
void destroy_shader()
{
glDeleteProgram(shaderProgram);
}
void initialize_vao()
{
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
// shaderProgram must be already initialized
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), 0);
GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
GLint cooAttrib = glGetAttribLocation(shaderProgram, "coord");
glEnableVertexAttribArray(cooAttrib);
glVertexAttribPointer(cooAttrib, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat)));
}
void destroy_vao()
{
glDeleteBuffers(1, &ibo);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
}
void initialize_texture()
{
glGenTextures(1, &textures[0]);
std::vector<unsigned char> image;
unsigned width, height;
unsigned error = lodepng::decode(image, width, height, "cube3.png");
if (error) std::cout << "decode error " << error << ": " << lodepng_error_text(error) << std::endl;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image.data());
// shaderProgram must be already initialized
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
void destroy_texture()
{
glDeleteTextures(1, &textures[0]);
}
void update_camera()
{
glm::vec3 right = glm::cross(camera_direction, camera_up);
glm::vec3 left = glm::cross(right, camera_up);
if (translate_forward)
{
camera_position += camera_direction*dt;
}
if (translate_backward)
{
camera_position -= camera_direction*dt;
}
if (translate_right)
{
camera_position += right * dt;
}
if (translate_left)
{
camera_position -= right * dt;
}
if (rotate_up)
{
camera_direction = glm::rotate(camera_direction, dt, right);
camera_up = glm::rotate(camera_up, dt, right);
}
if (rotate_down)
{
camera_direction = glm::rotate(camera_direction, -dt, right);
camera_up = glm::rotate(camera_up, -dt, right);
}
if (rotate_right)
{
camera_direction = glm::rotate(camera_direction, -dt, camera_up);
}
if (rotate_left)
{
camera_direction = glm::rotate(camera_direction, dt, camera_up);
}
if (rotate_z_left)
{
camera_direction = glm::rotate(camera_direction, dt, left);
camera_up = glm::rotate(camera_up, dt, left);
}
if (rotate_z_right)
{
camera_direction = glm::rotate(camera_direction, -dt, left);
camera_up = glm::rotate(camera_up, -dt, left);
}
}
void draw(GLFWwindow* window)
{
t = (timer::now() - start_time).count() * (float(timer::period::num) / float(timer::period::den));
dt = (timer::now() - last_time).count() * (float(timer::period::num) / float(timer::period::den));
update_camera();
last_time = timer::now();
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 projection = glm::perspective(PI / 4, 1.f / 1.f, 1.0f, 10.0f);
glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, -1.3f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 model = glm::rotate(glm::mat4(1.f), PI, glm::vec3(0.0f, 1.0f, 0.0f));
glUseProgram(shaderProgram);
glUniform1i(glGetUniformLocation(shaderProgram, "textureSampler"), tex_flag);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, &projection[0][0]);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, &view[0][0]);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, &model[0][0]);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 6 * 2 * 3, GL_UNSIGNED_INT, 0); // facce * triangoli per faccia * vertici per triangolo
}
int main(int argc, char const *argv[])
{
GLFWwindow *window;
glfwSetErrorCallback(error_callback);
tex_flag = 0;
if (!glfwInit())
return EXIT_FAILURE;
#if defined(__APPLE_CC__)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#else
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
#endif
window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Project", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
#if defined(_MSC_VER)
glewExperimental = true;
if (glewInit() != GL_NO_ERROR)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
#endif
glfwSetKeyCallback(window, key_callback);
initialize_shader(); check(__LINE__);
initialize_vao(); check(__LINE__);
initialize_texture(); check(__LINE__);
//start = timer::now();
glEnable(GL_DEPTH_TEST); check(__LINE__);
while (!glfwWindowShouldClose(window))
{
draw(window); check(__LINE__);
glfwSwapBuffers(window);
glfwPollEvents();
}
destroy_vao(); check(__LINE__);
destroy_shader(); check(__LINE__);
destroy_texture(); check(__LINE__);
glfwDestroyWindow(window);
glfwTerminate();
return EXIT_SUCCESS;
}
First order of business when hunting down problems like yours it to minimize the surface area and reduce the program as far as possible yet retaining the problematic behaviour. Your code snippet does not constitute a Minimal Complete Verifyable Example (MCVE). I stripped it down to a MCVE:
#include <cstdlib>
#include <iostream>
#include <GLFW/glfw3.h>
static void error_callback(int error, const char* description)
{
std::cerr << description << std::endl;
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
std::cout << key << std::endl;
}
int main(int argc, char const *argv[])
{
GLFWwindow *window;
glfwSetErrorCallback( error_callback );
if (!glfwInit())
return EXIT_FAILURE;
window = glfwCreateWindow(100, 100, "Project", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwSetKeyCallback(window, key_callback);
while (!glfwWindowShouldClose(window))
{
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return EXIT_SUCCESS;
}
Given this minimal example I am unable to reproduce your particular problem; i.e. I am getting key events out of this.
That can mean two things: Either the problem resides somewhere else in your code, or it is something about your particular system and development environment. This is why MCVEs are so important (especially the minimal part); it's the only way to pinpoint the actual culprit.
So here's my suggestion: Try the minimal code I put up and see if it still does not report key events. If so, then it's a problem with your system and not with the code. Otherwise you can re-add layers of functionality piece by piece until it breaks.
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?
I am trying to draw a simple cube for a homework assignment for a class but for some reason it isn't showing up.
I am using uniform blocks and modern OpenGL. I am sure I am not doing something correctly.
My complete code is below. The below example depends on GLEW + GLFW + GLM.
What I found interesting is that for my light and material uniform blocks I get the index but the uniform block for my MVP matrix I don't get the index.
Any ideas?
Here is the C++ code:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#ifndef OPENGL_INCLUDES_
#define OPENGL_INCLUDES_
#include "GL\glew.h"
#ifndef GLFW_INCLUDES_
#define GLFW_INCLUDES_
#if defined(_WIN32)
#include <Windows.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WGL
#elif defined(__linux__)
#include <X11/X.h>
#include <X11/extensions/Xrandr.h>
#define GLFW_EXPOSE_NATIVE_X11
#define GLFW_EXPOSE_NATIVE_GLX
#endif
#include "GLFW\glfw3.h"
#include "GLFW\glfw3native.h"
#endif
#endif
#ifndef GLM_INCLUDES_
#define GLM_INCLUDES_
#include <glm/glm.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
#endif
GLFWwindow* MainWindow;
#ifdef _WIN32
HWND MainWindowWin32Handle;
#endif
GLint WindowWidth = 1024;
GLint WindowHeight = 768;
GLulong SizeDivizor = 1;
GLboolean RiftAvailable = false;
GLboolean UseApplicationWindowFrame = false;
GLuint MainOpenGLShaderProgramID;
GLuint MatricesUniformBlockID;
GLuint MatricesUniformBufferID;
GLuint LightsUniformBlockID;
GLuint LightsUniformBufferID;
GLuint MaterialsUniformBlockID;
GLuint MaterialsUniformBufferID;
glm::mat4 ViewMatrix;
glm::mat4 ViewModelMatrix;
glm::mat4 ProjectionMatrix;
glm::mat4 MVPMatrix;
glm::mat3 NormalMatrix;
class StandardCube;
std::vector<StandardCube> Cubes;
class StandardCube {
private:
GLfloat* Vertices;
GLfloat* Normals;
GLuint* Indices;
GLuint VAO;
glm::mat4 ModelMatrix;
public:
void LoadIntoOpenGL() {
Vertices = new GLfloat[72]
{
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,
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,
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
};
Normals = new GLfloat[72] {
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f
};
Indices = new GLuint[36] {0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4,
8, 9, 10, 10, 11, 8,
12, 13, 14, 14, 15, 12,
16, 17, 18, 18, 19, 16,
20, 21, 22, 22, 23, 20
};
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
GLuint MeshBufferID;
glGenBuffers(1, &MeshBufferID);
glBindBuffer(GL_ARRAY_BUFFER, MeshBufferID);
GLuint TotalBufferData = (sizeof(GLfloat) * 72) + (sizeof(GLfloat) * 72);
glBufferData(GL_ARRAY_BUFFER, TotalBufferData, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, NULL, sizeof(GLfloat) * 72, Vertices);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 72, sizeof(GLfloat) * 72, Normals);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(sizeof(GLfloat) * 72));
glEnableVertexAttribArray(1);
GLuint IndexBufferID;
glGenBuffers(1, &IndexBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * 36, Indices, GL_STATIC_DRAW);
glBindVertexArray(NULL);
ModelMatrix = glm::mat4(1.0f);
}
void DrawMe() {
MVPMatrix = ProjectionMatrix * ViewMatrix * ModelMatrix;
ViewModelMatrix = ViewMatrix * ModelMatrix;
NormalMatrix = glm::transpose(glm::inverse(glm::mat3(MVPMatrix)));
glBindBuffer(GL_UNIFORM_BUFFER, MatricesUniformBufferID);
glBufferSubData(GL_UNIFORM_BUFFER, NULL, sizeof(glm::mat4), glm::value_ptr(MVPMatrix));
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(ViewModelMatrix));
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) + sizeof(glm::mat4), sizeof(glm::mat3), glm::value_ptr(NormalMatrix));
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
glBindVertexArray(VAO);
glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_INT, NULL, 1);
glBindVertexArray(NULL);
}
};
static void GLFWKeyCallback(GLFWwindow* p_Window, GLint p_Key, GLint p_Scancode, GLint p_Action, GLint p_Mods) {
if (p_Key == GLFW_KEY_ESCAPE && p_Action == GLFW_PRESS) {
glfwSetWindowShouldClose(p_Window, GL_TRUE);
}
if (p_Key == GLFW_KEY_O && p_Action == GLFW_PRESS) {
glClearColor(0.2f, 0.1f, 0.3f, 1.0f);
}
if (p_Key == GLFW_KEY_I && p_Action == GLFW_PRESS) {
glClearColor(1.0f, 0.5f, 0.5f, 1.0f);
}
}
static void GLFWWindowResizeCallBack(GLFWwindow* p_Window, GLint width, GLint height) {
//CurrentGLFWApplication->WindowResizeCallBack(p_Window, width, height);
}
static void GLFWMouseMovementCallBack(GLFWwindow* p_Window, GLdouble MouseX, GLdouble MouseY) {
//CurrentGLFWApplication->MouseMovementCallBack(p_Window, MouseX, MouseY);
}
static void GLFWFramebufferSizeCallback(GLFWwindow* window, GLint width, GLint height)
{
glViewport(0, 0, width, height);
}
int initializeGLFWGLEW() {
MainWindow = NULL;
if (!glfwInit())
{
fprintf(stderr, "GLFW failed to initialize.");
glfwTerminate();
return EXIT_FAILURE;
}
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
if (UseApplicationWindowFrame) {
MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Basic Oculus Rift Example", NULL, NULL);
}
else {
if (!RiftAvailable) {
MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Basic Oculus Rift Example", NULL, NULL);
}
else {
GLint MonitorCount;
GLFWmonitor** GLFW_Monitors = glfwGetMonitors(&MonitorCount);
GLFWmonitor* MonitorToUse;
switch (MonitorCount)
{
case 0:
printf("No monitors found, exiting.\n");
return EXIT_FAILURE;
break;
case 1:
printf("Two monitors expected, found only one, using primary...\n");
MonitorToUse = glfwGetPrimaryMonitor();
break;
case 2:
printf("Two monitors found, using second monitor\n");
MonitorToUse = GLFW_Monitors[1];
break;
default:
printf("More than two monitors found, using second monitor\n");
MonitorToUse = GLFW_Monitors[1];
}
MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Basic Oculus Rift Example", MonitorToUse, NULL);
}
}
if (!MainWindow)
{
fprintf(stderr, "Could not determine OpenGL version; exiting.");
glfwTerminate();
return EXIT_FAILURE;
}
glfwMakeContextCurrent(MainWindow);
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
return EXIT_FAILURE;
}
glfwSetInputMode(MainWindow, GLFW_STICKY_KEYS, GL_TRUE);
glfwSetKeyCallback(MainWindow, GLFWKeyCallback);
glfwSetWindowSizeCallback(MainWindow, GLFWWindowResizeCallBack);
glfwSetCursorPosCallback(MainWindow, GLFWMouseMovementCallBack);
glfwSetFramebufferSizeCallback(MainWindow, GLFWFramebufferSizeCallback);
glfwSwapBuffers(MainWindow);
glfwPollEvents();
return EXIT_SUCCESS;
}
int prepareOpenGL() {
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_MULTISAMPLE);
return EXIT_SUCCESS;
}
int loadShaders() {
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Compile Vertex Shader
printf("Compiling Vertext Shader.\n\n");
char const * VertexSource = "#version 330 \n\n\
layout(std140) uniform MatrixInformation {\n\
mat4 m_pvm;\n\
mat4 m_viewModel;\n\
mat3 m_normal;\n\
};\n\
layout(std140) uniform Lights {\n\
vec3 l_dir; \n\
};\n\
in vec4 position;\n\
in vec3 normal;\n\
\n\
\n\
out Data{\n\
vec3 normal;\n\
vec4 eye;\n\
} DataOut;\n\
\n\
void main() {\n\
\n\
DataOut.normal = normalize(m_normal * normal);\n\
DataOut.eye = -(m_viewModel * position);\n\
\n\
gl_Position = m_pvm * position;\n\
}\n\
\n";
glShaderSource(VertexShaderID, 1, &VertexSource, NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
GLint Result = GL_FALSE;
int InfoLogLength;
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0){
std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
std::string ErrorMessage = std::string(&VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}
printf("Compiling Fragment Shader.\n\n");
char const * FragmentSource = "#version 330\n\
layout(std140) uniform Materials {\n\
vec4 diffuse;\n\
vec4 ambient;\n\
vec4 specular;\n\
vec4 emissive;\n\
float shininess;\n\
int texCount;\n\
};\
\n\
layout(std140) uniform Lights {\n\
vec3 l_dir; \n\
};\
\n\
in Data{\n\
vec3 normal;\n\
vec4 eye;\n\
} DataIn;\n\
\n\
out vec4 colorOut;\
\n\
void main() {\n\
\n\
vec4 spec = vec4(0.0);\n\
\n\
vec3 n = normalize(DataIn.normal);\n\
vec3 e = normalize(vec3(DataIn.eye));\n\
\n\
float intensity = max(dot(n, l_dir), 0.0);\n\
\n\
if (intensity > 0.0) {\n\
vec3 h = normalize(l_dir + e);\n\
\n\
float intSpec = max(dot(h, n), 0.0);\n\
spec = specular * pow(intSpec, shininess);\n\
}\n\
\n\
colorOut = max(intensity * diffuse + spec, ambient);\n\
}";
glShaderSource(FragmentShaderID, 1, &FragmentSource, NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0){
std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
std::string ErrorMessage = std::string(&FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
}
// Link the program
printf("Linking shader program.\n\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0){
std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
std::string ErrorMessage = std::string(&ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
MainOpenGLShaderProgramID = ProgramID;
return EXIT_SUCCESS;
}
int prepareShaderUniforms() {
glUseProgram(MainOpenGLShaderProgramID);
LightsUniformBlockID = glGetUniformBlockIndex(MainOpenGLShaderProgramID, "Lights");
glUniformBlockBinding(MainOpenGLShaderProgramID, LightsUniformBlockID, 2);
glGenBuffers(1, &LightsUniformBufferID);
glBindBuffer(GL_UNIFORM_BUFFER, LightsUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 2, LightsUniformBufferID);
GLfloat LightDirection[3] = { 1.0f, 1.0f, 0.0f };
glBufferData(GL_UNIFORM_BUFFER, sizeof(LightDirection), &LightDirection, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
MatricesUniformBlockID = glGetUniformBlockIndex(MainOpenGLShaderProgramID, "MatrixInformation");
glUniformBlockBinding(MainOpenGLShaderProgramID, MatricesUniformBlockID, 1);
glGenBuffers(1, &MatricesUniformBufferID);
glBindBuffer(GL_UNIFORM_BUFFER, MatricesUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, MatricesUniformBufferID);
GLsizeiptr TotalBufferSize = sizeof(glm::mat4) + sizeof(glm::mat4);
TotalBufferSize += sizeof(glm::mat3);
glBufferData(GL_ARRAY_BUFFER, TotalBufferSize, NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
MaterialsUniformBlockID = glGetUniformBlockIndex(MainOpenGLShaderProgramID, "Materials");
glUniformBlockBinding(MainOpenGLShaderProgramID, MaterialsUniformBlockID, 3);
glGenBuffers(1, &MaterialsUniformBufferID);
glBindBuffer(GL_UNIFORM_BUFFER, MaterialsUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 3, MaterialsUniformBufferID);
GLfloat Material[18];
//Diffuse
Material[0] = 0.5f;
Material[1] = 0.0f;
Material[2] = 0.0f;
Material[3] = 1.0f;
//Ambient
Material[4] = 0.2f;
Material[5] = 0.2f;
Material[6] = 0.2f;
Material[7] = 1.0f;
//Specular
Material[8] = 0.0f;
Material[9] = 0.0f;
Material[10] = 0.0f;
Material[11] = 1.0f;
//Emissive
Material[12] = 0.0f;
Material[13] = 0.0f;
Material[14] = 0.0f;
Material[15] = 1.0f;
//Shininess
Material[16] = 2.0f;
//Texture Count
Material[17] = 0.0f;
glBufferData(GL_UNIFORM_BUFFER, sizeof(Material), &Material, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
return EXIT_SUCCESS;
}
int loadCubes() {
StandardCube NewCube;
NewCube.LoadIntoOpenGL();
Cubes.push_back(NewCube);
return EXIT_SUCCESS;
}
int prepareMatricies() {
GLfloat AspectRatio = (GLfloat)(WindowWidth) / (GLfloat)(WindowHeight);
ProjectionMatrix = glm::perspective(45.0f, AspectRatio, 1.0f, 1000.0f);
ViewMatrix = glm::lookAt(
glm::vec3(4.0f, 3.0f, 3.0f), // camera is at (4,3,3), in world space - Where the camera is inside world.
glm::vec3(0.0f, 0.0f, 0.0f), // and looks at the origin - What point the camera is looking at inside world.
glm::vec3(0.0f, 1.0f, 0.0f)// head is up(set to 0,1,0) - the direction of up for camera.
);
glViewport(0, 0, WindowWidth, WindowHeight);
return EXIT_SUCCESS;
}
int main(int argc, char** argv) {
if (initializeGLFWGLEW() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (prepareOpenGL() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (loadShaders() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (prepareShaderUniforms() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (loadCubes() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (prepareMatricies() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
while (!glfwWindowShouldClose(MainWindow))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (auto & C : Cubes) {
C.DrawMe();
}
glfwSwapBuffers(MainWindow);
glfwPollEvents();
}
exit(EXIT_SUCCESS);
}
Here is my vertex shader:
#version 330
layout(std140) uniform MatrixInformation {
mat4 m_pvm;
mat4 m_viewModel;
mat3 m_normal;
};
layout(std140) uniform Lights {
vec3 l_dir;
};
in vec4 position;
in vec3 normal;
out Data{
vec3 normal;
vec4 eye;
} DataOut;
void main() {
DataOut.normal = normalize(m_normal * normal);
DataOut.eye = -(m_viewModel * position);
gl_Position = m_pvm * position;
}
And here is my fragment shader:
#version 330
layout(std140) uniform Materials {
vec4 diffuse;
vec4 ambient;
vec4 specular;
vec4 emissive;
float shininess;
int texCount;
};
layout(std140) uniform Lights {
vec3 l_dir;
};
in Data{
vec3 normal;
vec4 eye;
} DataIn;
out vec4 colorOut;
void main() {
vec4 spec = vec4(0.0);
vec3 n = normalize(DataIn.normal);
vec3 e = normalize(vec3(DataIn.eye));
float intensity = max(dot(n, l_dir), 0.0);
if (intensity > 0.0) {
vec3 h = normalize(l_dir + e);
float intSpec = max(dot(h, n), 0.0);
spec = specular * pow(intSpec, shininess);
}
colorOut = max(intensity * diffuse + spec, ambient);
}
So the issue is this part:
//Binding uniform buffer
glBindBuffer(GL_UNIFORM_BUFFER, MatricesUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, MatricesUniformBufferID);
GLsizeiptr TotalBufferSize = sizeof(glm::mat4) + sizeof(glm::mat4);
TotalBufferSize += sizeof(glm::mat3);
//uploading to the unbound array buffer
glBufferData(GL_ARRAY_BUFFER, TotalBufferSize, NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
So you need to change
glBufferData(GL_ARRAY_BUFFER, TotalBufferSize, NULL, GL_DYNAMIC_DRAW);
to
glBufferData(GL_UNIFORM_BUFFER, TotalBufferSize, NULL, GL_DYNAMIC_DRAW);
Additionally uploading NULL doesn't work on my OpenGL driver (although it should), so I had to
std::array<unsigned char,sizeof(glm::mat4)*2+sizeof(glm::mat3)> buff;
glBufferData(GL_UNIFORM_BUFFER, TotalBufferSize, buff.data(), GL_DYNAMIC_DRAW);
As for how you would find that out: the old-school method is to litter your code with glGetError calls that only go off in debug mode. The more modern method is to create a debug context and print break on the callback to find out whereabouts the error is (then you can make glGetError calls in that area to get the exact function call if you don't know it by then, since modern OpenGL drivers are threaded and the callback may be triggered one or two function calls later).