OpenGL Perspective matrices not working - c++

I'm new to both stack overflow and OpenGL.
I'm trying to create my first little 3d program with custom shaders, but i have a problem with the various matrices that are required. I don't know exactly what causes complete black screen, if it is that i load uniforms incorrectly or that I'm failing at calculating the matrices. Anyway, I post the code down here and if anyone can help it would be amazing.
Main Cpp file
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <GL\glew.h>
#include <GL\glut.h>
#include <glm\glm.hpp>
#include <glm\vec3.hpp>
#include <glm\mat4x4.hpp>
#include <glm\gtc\matrix_transform.hpp>
#include <glm\gtc\type_ptr.hpp>
GLuint programID, vbo;
using namespace glm;
void loadShaders(){
char vertex_file_path[] = "vertex.glsl";
char fragment_file_path[] = "fragment.glsl";
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path);
if (VertexShaderStream.is_open()){
std::string Line = "";
while (std::getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
}
else{
printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", vertex_file_path);
getchar();
throw new std::runtime_error("Shaders not found");
}
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if (FragmentShaderStream.is_open()){
std::string Line = "";
while (std::getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("Compiling shader : %s\n", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
if (Result == GL_FALSE){
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
char * VertexShaderErrorMessage = new char[InfoLogLength + 1];
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, VertexShaderErrorMessage);
std::cout << VertexShaderErrorMessage << std::endl;
printf("Could not compile vertex shader: %s\n", VertexShaderErrorMessage);
getchar();
throw new std::runtime_error("Could not compile vertex shader");
}
// Compile Fragment Shader
std::cout << "Compiling shader : " << fragment_file_path << std::endl;
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
if (Result == GL_FALSE){
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
char * FragmentShaderErrorMessage = new char[InfoLogLength + 1];
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, FragmentShaderErrorMessage);
printf("Could not compile fragment shader: %s\n", FragmentShaderErrorMessage);
getchar();
throw new std::runtime_error("Could not compile fragment shader");
}
// Link the program
printf("Linking program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE){
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
throw new std::runtime_error("Could not compile program");
}
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
programID = ProgramID;
}
void loadMatrices(){
GLuint modelLoc = glGetUniformLocation(programID, "model");
GLuint viewLoc = glGetUniformLocation(programID, "view");
GLuint projLoc = glGetUniformLocation(programID, "projection");
mat4 model = scale(mat4(1.0f), vec3(1.0f));
mat4 view = lookAt(vec3(0.0f, 0.0f, 2.0f), vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f));
mat4 projection = perspective(45.0f, 16.0f / 9.0f, 0.01f, 100.0f);
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, value_ptr(projection));
}
void renderLoop(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
(void *) 0
);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glutSwapBuffers();
}
int _tmain(int argc, _TCHAR* argv[])
{
int MY_ZERO = 0;
glutInit(&MY_ZERO, NULL);
glutInitWindowSize(1280, 720);
glutInitDisplayMode(GLUT_DOBULE);
glutCreateWindow("Test");
glewExperimental = true;
glewInit();
glutIdleFunc(renderLoop);
glutDisplayFunc(renderLoop);
glMatrixMode(GL_PROJECTION);
glEnable(GL_DEPTH_TEST);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Nice perspective corrections
glDepthFunc(GL_LEQUAL);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_BLEND);
gluPerspective(75.0f, 16.0f / 9, 0.1f, 100.0f);
std::cout << "Setting blendFunc..." << std::endl;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
loadShaders();
loadMatrices();
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
float vals[] = {
0.0f, 1.0f, -10.0f,
1.0f, 1.0f, -10.0f,
1.0f, 0.0f, -10.0f
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vals), vals, GL_STATIC_DRAW);
glutMainLoop();
system("pause");
return 0;
}
Vertex Shader
layout (location = 0) in vec3 pos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
gl_Position = projection * vec4(pos, 1.0f);
}
Fragment Shader
void main(){
gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
}

There are several general aspects of the code which need improvement; e.g.
⊗ it can throw but doesn't catch and cleanup:
// there's no try/catch block enclosing this
throw new std::runtime_error("Could not compile vertex shader");
⊗ it's ready to leak:
char * VertexShaderErrorMessage = new char[InfoLogLength + 1];
/* ... */
throw new std::runtime_error("Could not compile vertex shader");
⊗ it needlessly consumes CPU and GPU time
glutIdleFunc(renderLoop); // boosts the frame rate for performance
// meters only
and so on, e.g. unrolling the shader creation and error handling loop violates DRY.
From an OpenGL-specific pov, there are several things which are not ok.
⊗ This
mat4 view = lookAt(vec3(0.0f, 0.0f, 2.0f),
vec3(0.0f, 0.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f));
(rightfully) prepares to step back back 2 units with the cam; but that matrix is not used in the shader
void main(){
gl_Position = projection * vec4(pos, 1.0f);
}
⊗ The shaders are first created and attached to the program, but on success deleted and detached again from the program which is intended to be used
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
⊗ These calls
glMatrixMode(GL_PROJECTION);
/* ... */
gluPerspective(75.0f, 16.0f / 9, 0.1f, 100.0f);
/* ... */
glMatrixMode(GL_MODELVIEW);
are meant for the (deprecated) fixed pipeline; which is not used here, and
⊗ there is no glClear() call in the code
There may be more things to attend to, but this is what I see on the first look.
We can have a deeper look into the code it if those things are dealt with first.

Solved!
The problem was that I wasn't using the program that holds the uniforms, so it failed to load them. Thanks to #BDL I started watching for OpenGL errors and i found GL_INVALID_OPERATION after every glUniformMatrix4fv. Poor debugging on my part. Thanks to everyone that helped
TL;DR put glUseProgram(program) before any glUniformMatrix4fv()

Related

What is causing the lack of color from fragment shader output?

I have a "Hello Triangle" program I'm working on and can't for the life of me figure out why there is no color coming from the fragment shader. What is causing all fragments to output as white? I'm on Visual Studio 2019, program compiles just fine, and stepping through the debugger yields no results. I'm assuming the error is either in GLSL or my vertex attribute plumbing.
Vertex Shader:
#version 450 core
layout (location = 0) in vec4 vPosition;
layout (location = 1) in vec4 color;
out vec4 fColor;
void main() {
fColor = color;
gl_Position = vPosition;
}
Fragment Shader:
#version 450 core
in vec4 fColor;
out vec4 fragColor;
void main() {
//fColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
fragColor = fColor;
}
Main:
#include <Windows.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cstdlib>
#include <string>
#include <GL/gl3w.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
std::string readFile(const char* filePath) {
std::string content;
std::ifstream fileStream(filePath, std::ios::in);
if (!fileStream.is_open()) {
std::cerr << "Could not read file " << filePath << ". File does not exist." << std::endl;
return "";
}
std::string line = "";
while (!fileStream.eof()) {
std::getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
void loadShaders(std::string filedir, GLenum type, GLuint &prog) {
GLenum errorVal;
std::string vertexSource = readFile("./vert.vert");
std::string fragmentSource = readFile("./frag.frag");
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
const GLchar* source = (const GLchar*)vertexSource.c_str();
glShaderSource(vertexShader, 1, &source, 0);
glCompileShader(vertexShader);
GLint isCompiled = 0;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength);
// The maxLength includes the NULL character
std::vector<GLchar> infoLog(maxLength);
glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &infoLog[0]);
// We don't need the shader anymore.
glDeleteShader(vertexShader);
// Use the infoLog as you see fit.
// In this simple program, we'll just leave
return;
}
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
source = (const GLchar*)fragmentSource.c_str();
glShaderSource(fragmentShader, 1, &source, 0);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength);
// The maxLength includes the NULL character
std::vector<GLchar> infoLog(maxLength);
glGetShaderInfoLog(fragmentShader, maxLength, &maxLength, &infoLog[0]);
// We don't need the shader anymore.
glDeleteShader(fragmentShader);
// Either of them. Don't leak shaders.
glDeleteShader(vertexShader);
// Use the infoLog as you see fit.
// In this simple program, we'll just leave
return;
}
// Vertex and fragment shaders are successfully compiled.
// Now time to link them together into a program.
// Get a program object.
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
GLint isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, (int*)&isLinked);
if (isLinked == GL_FALSE)
{
GLint maxLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
// The maxLength includes the NULL character
std::vector<GLchar> infoLog(maxLength);
glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
// We don't need the program anymore.
glDeleteProgram(program);
// Don't leak shaders either.
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// Use the infoLog as you see fit.
// In this simple program, we'll just leave
return;
}
// Always detach shaders after a successful link.
glDetachShader(program, vertexShader);
glDetachShader(program, fragmentShader);
}
int main(int argc, char** argv) {
GLenum errorVal;
//glfw and gl3w initialization and window creation
glfwInit();
GLFWwindow* window = glfwCreateWindow(1920, 1080, "openGL bullshit", NULL, NULL);
glfwMakeContextCurrent(window);
gl3wInit();
//do shit here
GLuint VAOs[1];
GLuint bufferNames[1];
//vertices gets copied into the GPU, can be modified GPU-side using glMapData, glBufferSubData, or glNamedBufferStorage
GLfloat vertices[12][4] = {
{ -1.0f, 1.0f, 0.0f, 1.0f }, // Triangle 1
{ -1.0f, -1.0f, 0.0f, 1.0f },
{ 1.0f, -1.0f, 0.0f, 1.0f },
{ 1.0f, -1.0f, 0.0f, 1.0f }, //Traingle 2
{ 1.0f, 1.0f, 0.0f, 1.0f },
{ -1.0f, 1.0f, 0.0f, 1.0f },
{1.0f, 0.0f, 0.0f, 1.0f}, //colors
{1.0f, 0.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f, 1.0f}
};
glCreateVertexArrays(1, VAOs);
glCreateBuffers(1, bufferNames);
glNamedBufferStorage(bufferNames[0], sizeof(vertices), vertices, GL_DYNAMIC_STORAGE_BIT + GL_MAP_WRITE_BIT);
//glNamedBufferSubData(bufferNames[0], sizeof(GLfloat) * 12, sizeof(GLfloat)*24, colors);
//insert shader shit here
GLuint program = glCreateProgram();
loadShaders("./vert.vert", GL_VERTEX_SHADER, program); //ignore the inputs, they aren't used. This one command loads both vertex and fragment shaders
glUseProgram(program);
//binding and plumbing
glBindVertexArray(VAOs[0]);
glBindBuffer(GL_ARRAY_BUFFER, bufferNames[0]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (void*)0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)(sizeof(GLfloat) * 24));
//glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(GLfloat) * 2));
//main loop
GLfloat debugArr[6][2];
while (!glfwWindowShouldClose(window)) {
static const float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
vertices[0][0] += 0.0001f;
void *pointer = glMapNamedBuffer(bufferNames[0], GL_WRITE_ONLY);
memcpy(pointer, vertices, sizeof(vertices) / 12);
glUnmapNamedBuffer(bufferNames[0]);
glClearBufferfv(GL_COLOR, 0, black);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
//shutdown if main loop stops
glfwDestroyWindow(window);
glfwTerminate();
}
That is just undefined behavoir:
glNamedBufferStorage(bufferNames[0], sizeof(vertices) + sizeof(colors), vertices, GL_DYNAMIC_STORAGE_BIT + GL_MAP_WRITE_BIT);
You tell the GL to read sizeof(vertices) + sizeof(colors) bytes beginning from the vertex array, but the memory after that array is completely unspecified. This might crash your program, or put random data into your buffer.
glBufferSubData(bufferNames[0], sizeof(GLfloat) * 12, sizeof(GLfloat)*24, colors);
This will just generate a GL_INVALID_ENUM error as glBufferSubData's first parameter is the binding target (like GL_ARRAY_BUFFER). So you never transfer the color data into the buffer. You need to use the DSA variant glNamedBufferSubData here.
Turns out the issue was with the program, when shaders were loaded it used a program variable that was baked into the load routine from the tutorial I used for that part, and I completely forgot about the program variable that passed as reference into the loadShaders function. Once the code was corrected to use the prog reference instead, all of the color came in!

No output from tessellation shader?

I have been working on a terrain LOD algorithm, but the primary logic is on the CPU:
I tried to convert most of the logic to the tessellation control and evaluation phases of the opengl pipeline, but nothing is displayed:
I reduced the code to a basic "hello quad" program
#define GLEW_STATIC
#include <glew.h>
#include <glfw3.h>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <stdio.h>
#include <string>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
/* Shader Source */
// vertex shader
const GLchar * VS_src[] = {
"#version 430\n"
"layout(location = 0) in vec3 position;\n"
"out vec4 vposition;\n"
"void main()\n"
"{\n"
" vposition = vec4(position, 1.0);\n"
"}\n"
};
// tesselation control shader
const GLchar * TCS_src[] = {
"#version 430\n"
"layout(vertices = 4) out;\n"
"in vec4 vposition[];\n"
"out vec4 tposition[];\n"
"void main()\n"
"{\n"
" tposition[gl_InvocationID] = vposition[gl_InvocationID];\n"
" if (gl_InvocationID == 0)\n"
" {\n"
" float tessLevel = 1.0;\n"
" gl_TessLevelInner[0] = tessLevel;\n"
" gl_TessLevelInner[1] = tessLevel;\n"
" gl_TessLevelOuter[0] = tessLevel;\n"
" gl_TessLevelOuter[1] = tessLevel;\n"
" gl_TessLevelOuter[2] = tessLevel;\n"
" gl_TessLevelOuter[3] = tessLevel;\n"
" }\n"
"}\n"
};
// tesselation evaluation shader
const GLchar * TES_src[] = {
"#version 430\n"
"uniform mat4 mvp;\n"
"layout(quads) in;\n"
"in vec4 tposition[];\n"
"void main()\n"
"{\n"
" float x = gl_TessCoord[0] * (tposition[1].x - tposition[0].x) + tposition[0].x;\n"
" float z = gl_TessCoord[2] * (tposition[1].z - tposition[2].z) + tposition[2].z;\n"
" float y = 0.0;\n"
" gl_Position = mvp * vec4(x, y, z, 1.0);\n"
"}\n"
};
// fragment shader
const GLchar * FS_src[] = {
"#version 430\n"
"out vec3 color;\n"
"void main()\n"
"{\n"
"color = vec3(0.0);\n"
"}\n"
};
/* Link Shaders to Program */
GLuint LoadShaders(const GLchar ** VS, const GLchar ** TCS, const GLchar ** TES, const GLchar ** FS)
{
// Create the shaders
GLuint VS_ID = glCreateShader(GL_VERTEX_SHADER);
GLuint TCS_ID = glCreateShader(GL_TESS_CONTROL_SHADER);
GLuint TES_ID = glCreateShader(GL_TESS_EVALUATION_SHADER);
GLuint FS_ID = glCreateShader(GL_FRAGMENT_SHADER);
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("compiling vertex shader\n");
glShaderSource(VS_ID, 1, VS, NULL);
glCompileShader(VS_ID);
// Check Vertex Shader
glGetShaderiv(VS_ID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VS_ID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(VS_ID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}
// Compile Tess Control Shader
printf("compiling tesselation control shader\n");
glShaderSource(TCS_ID, 1, TCS, NULL);
glCompileShader(TCS_ID);
// Check Tess Control Shader
glGetShaderiv(TCS_ID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(TCS_ID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> TessControlShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(TCS_ID, InfoLogLength, NULL, &TessControlShaderErrorMessage[0]);
printf("%s\n", &TessControlShaderErrorMessage[0]);
}
// Compile Tess Evaluation Shader
printf("compiling tesselation evaluation shader\n");
glShaderSource(TES_ID, 1, TES, NULL);
glCompileShader(TES_ID);
// Check Tess Evaluation Shader
glGetShaderiv(TES_ID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(TES_ID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> TessEvaluationShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(TES_ID, InfoLogLength, NULL, &TessEvaluationShaderErrorMessage[0]);
printf("%s\n", &TessEvaluationShaderErrorMessage[0]);
}
// Compile Fragment Shader
printf("compiling fragment shader\n");
glShaderSource(FS_ID, 1, FS, NULL);
glCompileShader(FS_ID);
// Check Fragment Shader
glGetShaderiv(FS_ID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FS_ID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(FS_ID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
}
// Link the program
printf("linking program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VS_ID);
glAttachShader(ProgramID, TCS_ID);
glAttachShader(ProgramID, TES_ID);
glAttachShader(ProgramID, FS_ID);
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]);
printf("%s\n", &ProgramErrorMessage[0]);
}
glDetachShader(ProgramID, VS_ID);
glDetachShader(ProgramID, TCS_ID);
glDetachShader(ProgramID, TES_ID);
glDetachShader(ProgramID, FS_ID);
glDeleteShader(VS_ID);
glDeleteShader(TCS_ID);
glDeleteShader(TES_ID);
glDeleteShader(FS_ID);
return ProgramID;
}
/* MAIN */
int main()
{
GLFWwindow * window;
if (!glfwInit()) return 0;
glfwWindowHint(GLFW_SAMPLES, 0);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(1600, 900, "Test", NULL, NULL);
if (!window) return 0;
glfwMakeContextCurrent(window);
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
glewExperimental=true;
if (glewInit() != GLEW_OK) return 0;
// Init
glm::mat4 p = glm::perspective(glm::radians(45.0f), 1600.0f / 900.0f, 0.1f, 1000.0f);
// look at <0,0,0> from <20,20,20>
glm::mat4 v = glm::lookAt(glm::vec3(20.0f), glm::vec3(0.0f), glm::vec3(0,1,0));
glm::mat4 m = glm::mat4(1.0f);
glm::mat4 mvp = p * v * m;
// draw 1 quad
std::vector<unsigned int> indices;
std::vector<glm::vec3> vertices;
indices.push_back(0);
indices.push_back(1);
indices.push_back(2);
indices.push_back(3);
vertices.push_back(glm::vec3(-10.0f, 0.0f, -10.0f));
vertices.push_back(glm::vec3( 10.0f, 0.0f, -10.0f));
vertices.push_back(glm::vec3( 10.0f, 0.0f, 10.0f));
vertices.push_back(glm::vec3(-10.0f, 0.0f, 10.0f));
// VAO
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// program
GLuint ProgramID = LoadShaders(VS_src, TCS_src, TES_src, FS_src);
// mvp uniform
GLuint MatrixID = glGetUniformLocation(ProgramID, "mvp");
// Vertex Buffer
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
// Element Buffer
GLuint elementbuffer;
glGenBuffers(1, &elementbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
// loop
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 )
{
glViewport(0, 0, 1600, 900);
glClearColor(0.478f, 0.702f, 0.816f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glUseProgram(ProgramID);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glPatchParameteri(GL_PATCH_VERTICES, 4);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glDrawElements(GL_PATCHES, indices.size(), GL_UNSIGNED_INT, (void*)0);
glDisableVertexAttribArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
// cleanup
glDeleteVertexArrays(1, &VertexArrayID);
glDeleteProgram(ProgramID);
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &elementbuffer);
glfwTerminate();
return 0;
}
but still nothing is displayed (besides the blue clearcolor background). All shaders compile with no errors and the program is linked with no errors.
When the quads primitive mode is used, then only the first 2 components of gl_TessCoord have a meaning. The 3rd component is 0.0. gl_TessCoord[0] and gl_TessCoord[1] provide normalized 2D coordinates, similar the UV coordinates of textures.
This means that you have to use gl_TessCoord[1] instead of gl_TessCoord[2] in the tessellation evaluation shader:
float x = gl_TessCoord[0] * (tposition[1].x - tposition[0].x) + tposition[0].x;
float z = gl_TessCoord[1] * (tposition[1].z - tposition[2].z) + tposition[2].z;
See Tessellation, Quads
Specification:
GLSL - The OpenGL Shading Language 4.6, 7.1 Built-In Language Variables, page 129:
The variable gl_TessCoord is available only in the tessellation evaluation language. It specifies a threecomponent (u,v,w) vector identifying the position of the vertex being processed by the shader relative to the primitive being tessellated.
OpenGL 4.6 core profile specification, 11.2.2.2 Quad Tessellation, page 416:
If the tessellation primitive mode is quads, a rectangle is subdivided into a collection of triangles covering the area of the original rectangle. First, the original rectangle is subdivided into a regular mesh of rectangles, where the number of rectangles along the u = 0 and u = 1 (vertical) and v = 0 and v = 1 (horizontal) edges are derived from the first and second inner tessellation levels, respectively.

OpenGL triangle not rendering

I've written some OpenGL code in c++ to render a red triangle to the screen. The program uses opengl 3.3 and glsl version 330. I've narrowed down the code that doesn't work to a few .cpp class files or my glsl code. I get no compiler or linker errors (I do get some linker warnings but I dont think those are important). I've given the code in what I believe to be the most likely place for errors to occur.
Renderer.cpp:
#include "Renderer.h"
#include <GL/glew.h>
void Renderer::render(int vbo){
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
}
ShaderProgram.cpp
#pragma warning(disable:4101)
#include "ShaderProgram.h"
#include <fstream>
#include <sstream>
ShaderProgram::ShaderProgram(std::string vertexLocation, std::string fragmentLocation){
programID = glCreateProgram();
vertexID = glCreateShader(GL_VERTEX_SHADER);
fragmentID = glCreateShader(GL_FRAGMENT_SHADER);
createShader(vertexID, vertexLocation);
createShader(fragmentID, fragmentLocation);
glLinkProgram(programID);
GLint success;
glGetProgramiv(programID, GL_LINK_STATUS, &success);
if (success == 0) {
GLchar ErrorLog[1024];
glGetProgramInfoLog(programID, sizeof(ErrorLog), nullptr, ErrorLog);
fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
}
glValidateProgram(programID);
glUseProgram(programID);
}
void ShaderProgram::createShader(GLint shaderID, std::string srcLocation){
const std::string shaderText = loadShaderSource(srcLocation);
const GLchar* shaderSource = shaderText.data();
glShaderSource(shaderID, 1, &shaderSource, nullptr);
glCompileShader(shaderID);
GLint success;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
if (!success) {
GLchar InfoLog[1024];
glGetShaderInfoLog(shaderID, sizeof(InfoLog), nullptr, InfoLog);
fprintf(stderr, "Error compiling shader: '%s'\n", InfoLog);
}
glAttachShader(programID, shaderID);
}
std::string ShaderProgram::loadShaderSource(std::string location){
std::ifstream file (location);
std::string source;
std::stringstream stringStream;
if (!file.is_open()){
throw std::runtime_error("Could not open file " + location);
}
stringStream << file.rdbuf();
source = stringStream.str();
return source;
}
Entity.cpp
#include "Entity.h"
Entity::Entity(){
vertices[0] = glm::vec3(-1.0f, -1.0f, 0.0f);
vertices[1] = glm::vec3(1.0f, -1.0f, 0.0f);
vertices[2] = glm::vec3(0.0f, 1.0f, 0.0f);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
}
int Entity::getID(){
return vbo;
}
GLSL Code:
Vertex Shader:
#version 330
layout (location = 0) in vec3 position;
void main(){
gl_Position = vec4(0.5 * position.x, 0.5 * position.y, position.z, 1.0);
}
Fragment Shader:
#version 330
out vec4 colour;
void main(){
colour = vec4(1.0, 0.0, 0.0, 1.0);
}
you cant use glm::vec3 like this.Reference to it doesn't provide you anything.Start of its real array obtained :
glm::vec3 k;
float* t= &k[0];
But i doubt you can do something worth with it too.
use just float GLfloat array.

OpenGL fragment shader for GL_LINES only renders lines when shader compilation fails

I've looked for an answer to my problem for two days. Maybe I'm just terrible at searching but there doesn't seem to be an answer already out there.
I am trying to draw lines on the screen using OpenGL's glDrawArrays(GL_LINES, ..., ...). This is the current code for my fragment shader:
#version 330 core
in vec4 vertexColor;
out vec4 color;
void main( )
{
//color = vec3(0.5f, 1.0f, 1.0f);
color = vec4(0.5f, 1.0f, 1.0f, 0.5f);
//color = vertexColor;
}
Originally the color=vertexColor line was supposed to work, but nothing appeared on the screen. I thought maybe something was wrong with the data being sent from the vertex shader so I tried setting the output manually in the fragment shader. I accidentally made it a vec3 instead of a vec4 and I got an error in my console window telling me compilation of the shader had failed. But the lines appeared! They showed up in the right spot as white/gray lines of static. When I corrected the mistake and set the output to a vec4, like shown, the lines were invisible again and I had no compilation error.
What am I doing wrong that makes my lines invisible?
Edit:
Here is my first go at a "minimal, complete, and verifiable example". If you link a project with these files to GLEW, GLFW and GLM, this should run on your system. If I'm not supposed to upload a whole program, I apologize. This seems a bit big, but I don't know how else it could be "complete".
Instead of making two white static lines, this one is making only one solid black line when the fragment shader fails to compile. It still renders nothing when compilation is successful.
Main.cpp
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "ShaderMaker.h"
#include "TargetBox.h"
const GLint WIDTH = 800, HEIGHT = 600;
//Camera
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
GLfloat yaw = -90.0f;
GLfloat pitch = 0.0f;
// Delta time
GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;
int main() {
cameraFront.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraFront.y = sin(glm::radians(pitch));
cameraFront.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraFront = glm::normalize(cameraFront);
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Debugger", nullptr, nullptr);
int screenWidth, screenHeight;
glfwGetFramebufferSize(window, &screenWidth, &screenHeight);
if (window == nullptr) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return EXIT_FAILURE;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (GLEW_OK != glewInit()) {
std::cout << "Failed to initialize GLEW" << std::endl;
return EXIT_FAILURE;
}
glViewport(0, 0, screenWidth, screenHeight);
glEnable(GL_DEPTH_TEST);
TargetBox tb;
GLuint modelLoc = tb.getUniform("model");
GLuint viewLoc = tb.getUniform("view");
GLuint projectionLoc = tb.getUniform("projection");
glm::mat4 projection;
projection = glm::perspective(glm::radians(45.0f), (float)screenWidth / screenHeight, 0.1f, 100.0f);
while (!glfwWindowShouldClose(window)) {
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glfwPollEvents();
glClearColor(0.5f, 0.7f, 0.9f, 1.0f); // Unnecessary, but adds some color to an otherwise blank window
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 view;
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
tb.useShader();
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(tb.getVAO());
glm::vec3 posMod = tb.getPos();
glm::mat4 model;
model = glm::translate(model, glm::vec3(posMod.x, posMod.y, posMod.z));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_LINES, 0, 4);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
glfwTerminate();
return EXIT_SUCCESS;
}
ShaderMaker.h
#pragma once
#ifndef SHADERMAKER_H
#define SHADERMAKER_H
#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
#include<GL/glew.h>
class ShaderMaker {
public:
// The program ID
GLuint Program;
// Constructor reads and builds the shader
ShaderMaker(const GLchar* vertexPath, const GLchar* fragmentPath) {
// 1. Retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// ensures ifstream objects can throw exceptions:
vShaderFile.exceptions(std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::badbit);
try {
// Open files
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
// Read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
// close file handlers
vShaderFile.close();
fShaderFile.close();
// Convert stream into GLchar array
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (std::ifstream::failure e) {
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl;
}
const GLchar* vShaderCode = vertexCode.c_str();
const GLchar* fShaderCode = fragmentCode.c_str();
// 2. Compile shaders
GLuint fragment;
GLint success;
GLchar infoLog[512];
// Vertex shader
GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
// Print compile errors if any
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Similar for fragment shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
// Print compile errors if any
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Shader program
this->Program = glCreateProgram();
glAttachShader(this->Program, vertex);
glAttachShader(this->Program, fragment);
glLinkProgram(this->Program);
// Print linking errors if any
glGetShaderiv(this->Program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
// Delete the shaders as they're linked into our program now and no longer necessary
glDeleteShader(vertex);
glDeleteShader(fragment);
}
// Use the program
void Use() { glUseProgram(this->Program); }
// Get a uniform
GLint getUniform(const GLchar * name) {
return glGetUniformLocation(this->Program, name);
}
};
#endif
TargetBox.h
#pragma once
#ifndef TARGETBOX_H
#define TARGETBOX_H
#define GLEW_STATIC
#include <GL/glew.h>
#include<glm/glm.hpp>
#include <GLFW/glfw3.h>
#include "ShaderMaker.h"
class TargetBox
{
public:
TargetBox();
~TargetBox();
void useShader();
GLuint getVAO();
glm::vec3 getPos();
void setPos(glm::vec3 p);
GLuint getUniform(GLchar * u);
private:
glm::vec3 pos;
GLuint VAO, VBO;
const GLchar *vertexShaderPath = ".\\VShaderLine.txt";
const GLchar *fragmentShaderPath = ".\\FShaderLine.txt";
ShaderMaker shader = ShaderMaker(vertexShaderPath, fragmentShaderPath);
};
#endif
TargetBox.cpp
#include "TargetBox.h"
TargetBox::TargetBox()
{
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
GLfloat vertices[] = {
-2, 0, -5, 1.0f, 1.0f, 1.0f,
2, 0, 5, 1.0f, 1.0f, 1.0f,
2, 0, 5, 1.0f, 0.0f, 0.0f,
2, 10, 5, 0.0f, 1.0f, 0.0f
};
size_t data_len = sizeof(vertices);
glBufferData(GL_ARRAY_BUFFER, data_len, vertices, GL_STATIC_DRAW);
// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)0);
glEnableVertexAttribArray(0);
//Color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
TargetBox::~TargetBox()
{
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
}
void TargetBox::useShader() { shader.Use(); }
GLuint TargetBox::getVAO() { return VAO; }
glm::vec3 TargetBox::getPos() { return pos; }
void TargetBox::setPos(glm::vec3 p) { pos = p; }
GLuint TargetBox::getUniform(GLchar * u) { return shader.getUniform(u); }
VShaderLine.txt
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
out vec4 vertexColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main( )
{
// The order of multiplication is important?
gl_Position = projection * view * model * vec4( position, 1.0 );
vertexColor = vec4(color.xyz, 1.0f);
}
FShaderLine.txt
#version 330 core
in vec4 vertexColor;
out vec4 color;
void main( )
{
color = vec3(0.5f, 1.0f, 1.0f);
//color = vec4(0.5f, 1.0f, 1.0f, 0.5f);
//color = vertexColor;
}

OpenGL - Can't get Vertex Array Objects and Vertex Buffer Objects to draw

I'm using OpenGL with SDL2 on MacOSX 10.10. I've been trying to use VAOs and VBOs in modern OpenGL, but I am not able to get them to draw. My shaders are super simple, but according to tutorials I've been trying to follow they're supposed to work. I'm not getting any errors, but it's still not working. All I receive is a window that's completely black. If anyone could help me understand where my problem is and how I can fix it I would greatly appreciate it. I hope I'm not repeating a previous question, but I have searched and searched and found nothing to solve this problem. Here's my code:
vertexShader.glsl:
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
void main(){
gl_Position.xyz = vertexPosition_modelspace;
gl_Position.w = 1.0;
}
fragmentShader.glsl
#version 330 core
out vec4 color;
void main(){
color = vec4(1.0, 1.0, 0.0, 1.0);
}
Here is my code for loading the shaders, which has worked and provided no errors:
//Note: PXConsole is a util class for printing to the console.
GLuint loadShaders(std::string vertexPath, std::string fragmentPath){
const char* vertexShaderPath = vertexPath.c_str();
const char* fragmentShaderPath = fragmentPath.c_str();
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertexShaderPath, std::ios::in);
if(VertexShaderStream.is_open()){
std::string Line = "";
while(getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
}else{
std::string error ="Could not open vertex shader at \"" + vertexPath +"\". Is the the path written correctly? ";
PXConsole::err(error);
return 0;
}
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragmentShaderPath, std::ios::in);
if(FragmentShaderStream.is_open()){
std::string Line = "";
while(getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
}else{
std::string error ="Could not open fragment shader at \"" + fragmentPath +"\". Is the the path written correctly? ";
PXConsole::err(error);
return 0;
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
PXConsole::info("Compiling Vertex Shader at: " + vertexPath);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
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]);
PXConsole::err(&VertexShaderErrorMessage[0]);
}
// Compile Fragment Shader
PXConsole::info("Compiling Fragment Shader at: " + fragmentPath);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , 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]);
PXConsole::err(&FragmentShaderErrorMessage[0]);
}
// Link the program
PXConsole::info("Linking Shader Program!");
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]);
PXConsole::err(&ProgramErrorMessage[0]);
}
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
Here is my OpenGL context creation with SDL2:
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
appWindow = SDL_CreateWindow("Window Title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL);
if (!application->appWindow) {
PXConsole::err("Couldn't Initialize Window!!");
endApp();
}
appGLContext = SDL_GL_CreateContext(appWindow);
And lastly here is my render function which is in a loop:
void render(){
GLuint vaoID;
GLuint posVBO;
GLfloat positions[] = {-0.5f, -0.5f, 1.0f,
0.5f, -0.5f, 1.0f,
0.5f, 0.5f, 1.0f,
-0.5f, 0.5f, 1.0f};
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//shaderProgramID = the function mentioned above in an initializating function and has no errors finding the shader files
glUseProgram(shaderProgramID);
glColor4f(1.0, 1.0, 0.0, 1.0);
glGenVertexArrays(1, &vaoID);
glBindVertexArray(vaoID);
glGenBuffers(1, &posVBO);
glBindBuffer(GL_ARRAY_BUFFER, posVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, posVBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glColor4f(1.0, 0.0, 0.0, 1.0);
glDrawArrays(GL_QUADS, 0, 4);
glDisableVertexAttribArray(0);
SDL_GL_SwapWindow(appWindow);
}
I hope that's enough code to be able to determine the issue. Thanks for any help!
A VAO basically stores the attribute bindings set by glVertexAttribPointer. In order to store them, they have to be set while the VAO is bound. In your case, you first unbind it and then set the attribute binding.
Additionally, one should never generate buffers or vaos in each frame. This are things that have to be done during initialization.
Since you said in the question that you are not getting any errors: There are at least three of them in each frame. How do you check for errors?
glColor4f has been removed from the OpenGL 3.3 Core Profile. Calling this should result in an error. (2x)
GL_QUADS is not a valid drawing mode in Core Profile and should also generate an error.
A corrected version could look like this
Init
glGenVertexArrays(1, &vaoID);
glBindVertexArray(vaoID);
glGenBuffers(1, &posVBO);
glBindBuffer(GL_ARRAY_BUFFER, posVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
Render
glBindVertexArray(vaoID);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
Update
When you want to use new coordinates in each frame, you still generate the buffers and setup the VAO in the initialization. What you do in each frame is to upload new data to the buffer like this (assuming the amount of vertices stays the same):
glBindBuffer(GL_ARRAY_BUFFER, posVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(positions), positions);
This will override the data of the buffer without allocating new GPU memory. Note that you have to call glBufferData once in the initialization with the correct size, but with a nullptr as data pointer to allocate the memory for the buffer.