Cannot get Triangle to Display with OpenGL in GLFW [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have been following the Modern Opengl Tutorials on YouTube by Nico Cvitak to help me transition from SDL to OpenGl/GLFW; here is a link to the lesson I can't get to work: [https://www.youtube.com/watch?v=2K_R4C1UP-c][1]
Here is my code:
myVertexShader.vs
#version 150 core
in vec2 v_pos;
void main()
{
gl_Position = vec4(v_pos, 0.0, 1.0);
}
myFragmentShader.fs
#version 150 core
out vec4 fragData;
void main()
{
fragData = vec4(1.0, 1.0, 1.0, 1.0);
}
main.cpp
#define GLFW_INCLUDE_GLCOREARB
#include <iostream>
#include <GLFW/glfw3.h>
#include <OpenGL/OpenGL.h>
#include "ShaderUtils.h"
int main(int argc, const char * argv[])
{
GLFWwindow * window;
//Initialize the library
if (!glfwInit())
return -1;
//Specify Hints
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
//Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(640, 480, "Mojicon", NULL, NULL);
if (!window)
{
glfwTerminate();
return 1;
}
//Make the window's context current
glfwMakeContextCurrent(window);
std::cout << glGetString(GL_VERSION) << std::endl;
glClearColor(0.0, 0.0, 0.0, 1.0);
GLuint vertexShader = ShaderUtils::createShaderFromFile("myVertexShader.vs", GL_VERTEX_SHADER);
GLuint fragmentShader = ShaderUtils::createShaderFromFile("myFragmentShader.fs", GL_FRAGMENT_SHADER);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "fragData");
glLinkProgram(shaderProgram);
GLint linkStatus;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &linkStatus);
if (linkStatus != GL_TRUE)
{
cout << "Program Link Failed!" << endl;
GLint infoLogLength;
glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar * infoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(shaderProgram, infoLogLength + 1, NULL, infoLog);
cout << infoLog << endl;
delete infoLog;
return 0;
}
glUseProgram(shaderProgram);
//vertex buffer objects
GLuint myVBO;
glGenBuffers(1, &myVBO);
glBindBuffer(GL_ARRAY_BUFFER, myVBO);
GLfloat bufferData[] =
{
+0.0, +0.5,
-0.5, -0.5,
+0.5, -0.5,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, NULL);
GLuint myVAO;
glGenVertexArrays(1, &myVAO);
glBindVertexArray(myVAO);
GLint positionLoc = glGetAttribLocation(shaderProgram, "v_pos");
glEnableVertexAttribArray(positionLoc);
glBindBuffer(GL_ARRAY_BUFFER, myVBO);
glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
glBindBuffer(GL_ARRAY_BUFFER, NULL);
glBindVertexArray(NULL);
//Loop the window until closed
while (!glfwWindowShouldClose(window))
{
//Render here
GLint windowWidth, windowHeight;
glfwGetWindowSize(window, &windowWidth, &windowHeight);
glViewport(0, 0, windowWidth, windowHeight);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(myVAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(NULL);
//Poll for events
glfwPollEvents();
//Swap buffers
glfwSwapBuffers(window);
}
glDeleteBuffers(1, &myVBO);
glDeleteVertexArrays(1, &myVAO);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteProgram(shaderProgram);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
ShaderUtil.h
#define GLFW_INCLUDE_GLCOREARB
#include <iostream>
#include <fstream>
#include <streambuf>
#include <GLFW/glfw3.h>
using namespace std;
class ShaderUtils
{
public:
static GLuint createShaderFromFile(const GLchar * path, GLenum shaderType);
};
ShaderUtil.cpp
#include "ShaderUtils.h"
GLuint ShaderUtils::createShaderFromFile(const GLchar * path, GLenum shaderType)
{
GLuint shaderID = glCreateShader(shaderType);
ifstream fin;
fin.open(path);
if (!fin.is_open())
{
cout << "File Not Found '" << path << "'!" << endl;
return -1;
}
string source((istreambuf_iterator<GLchar>(fin)), istreambuf_iterator<GLchar>());
fin.close();
const GLchar * shaderSource = source.c_str();
glShaderSource(shaderID, 1, &shaderSource, NULL);
glCompileShader(shaderID);
GLint compileStatus;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compileStatus);
if (compileStatus != GL_TRUE)
{
cout << "Shader Failed To Compile: '" << path << "'!" << endl;
GLint infoLogLength;
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar * infoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(shaderID, infoLogLength + 1, NULL, infoLog);
cout << infoLog << endl;
delete infoLog;
return -1;
}
return 0;
}
I tried to make this code nearly identical with the tutorials code, and I cannot for the life of me find any differences. Help me find the problem (there are no bugs) and explain it to me.

Your createShaderFromFile() method always returns 0:
GLuint ShaderUtils::createShaderFromFile(const GLchar * path, GLenum shaderType)
{
...
return 0;
}
You use this return value as a shader id:
GLuint vertexShader = ShaderUtils::createShaderFromFile(
"myVertexShader.vs", GL_VERTEX_SHADER);
GLuint fragmentShader = ShaderUtils::createShaderFromFile(
"myFragmentShader.fs", GL_FRAGMENT_SHADER);
These values will come out as 0. To make this work, you will need to return the shader id from the method:
GLuint ShaderUtils::createShaderFromFile(const GLchar * path, GLenum shaderType)
{
...
return shaderID;
}
You should be able to track down this kind of problem by stepping through the code in a debugger.

Related

Creating a triangle with OpenGL

I am having trouble with my C++ code for an OpenGL program that is supposed to create a 2D triangle and keep receiving this error message:
Error! Fragment shader failed to compile.
ERROR: 0:1: '' : syntax error: #version directive must occur in a shader before anything else.
Error! Shader Program Linker Failure.
I have tried putting the code from lines 13-27 before the const char* APP_TITLE line (line 8) but that doesn't seem to make a difference.
What can I do to generate this 2D triangle?
#include <iostream>
#include <sstream>
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"
const char* APP_TITLE = "Texturing a Pyramid";
const int gwindowWidth = 800;
const int gwindowHeight = 600;
GLFWwindow* gWindow = NULL;
const GLchar* vertexShaderSrc =
"#version 330 core\n"
"layout (location = 0) in vec3 pos;"
"void main()"
"{"
" gl_Position = vec4(pos.x, pos.y, pos.z, 1.0);"
"}";
const GLchar* fragmentShaderSrc =
"version 330 core\n"
"out vec4 frag_color;"
"void main()"
"{"
" frag_color = vec4(0.35f, 0.96f, 0.3f, 1.0);"
"}";
void glfw_onKey(GLFWwindow* window, int key, int scancode, int action, int mode);
void showFPS(GLFWwindow* window);
bool initOpenGL();
int main()
{
if (!initOpenGL())
{
std::cerr << "GLFW intialization failed." << std::endl;
return false;
}
GLfloat vertices[] = {
0.0f, 0.5f, 0.0f, // Top Vertex
0.5f, -0.5f, 0.0f, // Right Vertex
-0.5f, -0.5f, 0.0f // Left Vertex
};
GLuint vbo, vao;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource (vs, 1, &vertexShaderSrc, NULL);
glCompileShader(vs);
GLint result;
GLchar infoLog[512];
glGetShaderiv(vs, GL_COMPILE_STATUS, &result);
if (!result)
{
glGetShaderInfoLog(vs, sizeof(infoLog), NULL, infoLog);
std::cout << "Error! Vertex shader failed to compile." << infoLog << std::endl;
}
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource (fs, 1, &fragmentShaderSrc, NULL);
glCompileShader(fs);
glGetShaderiv(fs, GL_COMPILE_STATUS, &result);
if (!result)
{
glGetShaderInfoLog(fs, sizeof(infoLog), NULL, infoLog);
std::cout << "Error! Fragment shader failed to compile." << infoLog << std::endl;
}
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vs);
glAttachShader(shaderProgram, fs);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(shaderProgram, sizeof(infoLog), NULL, infoLog);
std::cout << "Error! Shader Program Linker Failure" << std::endl;
}
glDeleteShader(vs);
glDeleteShader(fs);
// Main loop
while (!glfwWindowShouldClose(gWindow))
{
showFPS(gWindow);
glfwPollEvents();
glfwSwapBuffers(gWindow);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSetKeyCallback(gWindow, glfw_onKey);
}
glDeleteProgram(shaderProgram);
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glfwTerminate();
return 0;
}
bool initOpenGL()
{
if (!glfwInit())
{
std::cerr << "GLFW initialization failed." << std::endl;
return -1;
}
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);
GLFWwindow* gWindow = glfwCreateWindow(gwindowWidth, gwindowHeight, APP_TITLE, NULL, NULL);
if (gWindow == NULL)
{
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(gWindow);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cerr << "GLEW initialization failed." << std::endl;
return false;
}
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
return true;
}
void glfw_onKey(GLFWwindow* window, int key, int scancode, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
void showFPS(GLFWwindow* window)
{
static double previousSeconds = 0.0;
static int frameCount = 0;
double elapsedSeconds;
double currentSeconds = glfwGetTime(); // returns # of seconds since GLFW started, as a double
elapsedSeconds = currentSeconds - previousSeconds;
// limit text update 4 times per second
if (elapsedSeconds > 0.25)
{
previousSeconds = currentSeconds;
double fps = (double)frameCount / elapsedSeconds;
double msPerFrame = 1000.0 / fps;
std::ostringstream outs;
outs.precision(3);
outs << std::fixed
<< APP_TITLE << " "
<< "FPS: " << fps << " "
<< "FrameTime: " << msPerFrame << " (ms)";
glfwSetWindowTitle(window, outs.str().c_str());
frameCount = 0;
}
frameCount++;
}
fragmentShaderSrc is missing a # (U+0023 NUMBER SIGN) in front of version:
"version 330 core\n"
^ note lack of #
Should be:
"#version 330 core\n"
^ note the #

Display white triangle with SFML and OpenGL?

I should be seeing a white triangle on the output, but I am just seeing a black screen. I think that the issue is with the glsl shaders. What is wrong with my code?
#define GLEW_STATIC
#include <iostream>
#include <GL/glew.h>
#include <SFML/Window.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
using namespace std;
// Shader sources
const char* vertexSource = R"glsl(
#version 330 core
in vec2 position;
void main()
{
gl_Position = vec4(position, 0.0, 1.0);
}
)glsl";
const char* fragmentSource = R"glsl(
#version 330 core
out vec4 outColor;
void main()
{
outColor = vec4(1.0, 1.0, 1.0, 1.0);
}
)glsl";
int main()
{
sf::ContextSettings settings;
settings.depthBits = 24;
settings.stencilBits = 8;
settings.antialiasingLevel = 2;
settings.majorVersion = 3;
settings.minorVersion = 2;
settings.attributeFlags = sf::ContextSettings::Core;
sf::RenderWindow window(sf::VideoMode(800, 600), "OpenGL", sf::Style::Titlebar | sf::Style::Close, settings);
// Initialize GLEW
glewExperimental = GL_TRUE;
glewInit();
//generate a vao
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//generate 1 buffer
GLuint vbo;
glGenBuffers(1, &vbo);
float vertices[] = {
0.0f, 0.5f, // Vertex 1 (X, Y)
0.5f, -0.5f, // Vertex 2 (X, Y)
-0.5f, -0.5f // Vertex 3 (X, Y)
};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//compiling the vertex shader
GLuint vertexshader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexshader, 1, &vertexSource, NULL);
glCompileShader(vertexshader);
GLint shaderstatus;
glGetShaderiv(vertexshader, GL_COMPILE_STATUS, &shaderstatus);
char buffer[512];
glGetShaderInfoLog(vertexshader, 512, NULL, buffer);
while (shaderstatus = true){
cout << "vertex" << endl;
cout << buffer << endl;
break;
}
//compiling the fragment shader
GLuint fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentshader, 1, &fragmentSource, NULL);
glCompileShader(fragmentshader);
GLint fragmentstatus;
glGetShaderiv(fragmentshader, GL_COMPILE_STATUS, &fragmentstatus);
char bufferfrag[512];
glGetShaderInfoLog(fragmentshader, 512, NULL, bufferfrag);
while (fragmentstatus = true){
cout << "fragment" << endl;
cout << bufferfrag << endl;
break;
}
//connecting vertex and fragment shaders
GLuint shaderprogram = glCreateProgram();
glAttachShader(shaderprogram, vertexshader);
glAttachShader(shaderprogram, fragmentshader);
glBindFragDataLocation(shaderprogram, 0, "outColor");
glLinkProgram(shaderprogram);
glUseProgram(shaderprogram);
GLint posAttrib = glGetAttribLocation(shaderprogram, "Position");
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(posAttrib);
while (window.isOpen())
{
// Process events
sf::Event event;
while (window.pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
window.close();
}
// Clear screen
window.clear();
//window.clear();
glDrawArrays(GL_TRIANGLES, 0, 3);
// Update the window
window.display();
}
return 0;
}
At line:
GLint posAttrib = glGetAttribLocation(shaderprogram, "Position");
The p in "Position" should be lowercase, as GLSL is case sensitive.
Also, in:
while (shaderstatus = true){
cout << "vertex" << endl;
cout << buffer << endl;
break;
}
There should be two equal signs, as this is to test equality, not to set shaderstatus to true.

OpenGL exception when glDrawArrays

I am trying to just render a triangle in one file so I can understand how openGL works so I can use that as an example when creating an engine. The program worked correctly before I created the shaders and the VAO stuff. The exception said: "Access violation at memory location: 0x000000" when the glDrawArrays() function was called. My guess is that i messed up the VAO. It could be the shader too. Thanks in advance for your time!
here is my code
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <iostream>
#include <string>
#include <fstream>
const std::string FILENAME = "src\\shaders\\basic";
static void error_callback(int error, const char* description);
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
static void resize_callback(GLFWwindow* window, int width, int height);
static std::string LoadShader(const std::string& filename);
static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage);
static GLuint CreateShader(const std::string& text, GLenum shaderType);
int main()
{
//Initalize GLFW
if (!glfwInit())
{
//TODO: Failed to initialize GLFW
}
//Create window and store it to a handler
GLFWwindow* window = glfwCreateWindow(1024, 768, "GL Noob Project", NULL, NULL);
if (!window)
{
//TODO: Failed to create window
}
glfwMakeContextCurrent(window); //Set the OpenGL context to our window
glfwSwapInterval(1); //Set the buffer swap interval to 1
//Initialize GLEW
if (glewInit() != GLEW_OK) {
//TODO Failed to initialize glew
}
//Set callbacks
glfwSetErrorCallback(error_callback);
glfwSetKeyCallback(window, key_callback);
glfwSetFramebufferSizeCallback(window, resize_callback);
//Shaders
GLuint program;
GLuint v_shader;
GLuint f_shader;
program = glCreateProgram();
v_shader = CreateShader(LoadShader(FILENAME + ".vs"), GL_VERTEX_SHADER);
f_shader = CreateShader(LoadShader(FILENAME + ".fs"), GL_FRAGMENT_SHADER);
glBindAttribLocation(program, 0, "position");
glAttachShader(program, v_shader);
glAttachShader(program, f_shader);
glLinkProgram(program);
CheckShaderError(program, GL_LINK_STATUS, true, "Shader Error");
glValidateProgram(program);
CheckShaderError(program, GL_VALIDATE_STATUS, true, "Shader Error");
glUseProgram(program);
//CREATE VAO
static const GLfloat data[] = { 0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0 };
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, sizeof(data), GL_FLOAT, GL_FALSE, 0, 0);
while (!glfwWindowShouldClose(window)) //While there is no close flag
{
//DRAW
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(window); //Swap front and back buffer
glfwPollEvents(); //Get events
}
glDetachShader(program, v_shader);
glDeleteShader(v_shader);
glDetachShader(program, f_shader);
glDeleteShader(f_shader);
glDeleteProgram(program);
glfwDestroyWindow(window); //Destroy window
glfwTerminate(); //Terminate GLFW
return 0;
}
//CALLBACK FUNCTIONS
//Error callback
static void error_callback(int error, const char* description) {
std::cerr << "Error: " << description << std::endl;
}
//Key callback
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
static void resize_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
//SHADER FUNCTIONS
static std::string LoadShader(const std::string& filename) {
std::ifstream file;
file.open(filename.c_str());
std::string output;
std::string line;
if (file.is_open())
{
while (file.good())
{
getline(file, line);
output.append(line + "\n");
}
}
else {
std::cerr << "Unable to load shader from file: "<< filename << std::endl;
}
return output;
}
static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage)
{
GLint success = 0;
GLchar error[1024] = { 0 };
if (isProgram)
glGetProgramiv(shader, flag, &success);
else
glGetShaderiv(shader, flag, &success);
if (success == GL_FALSE)
{
if (isProgram)
glGetProgramInfoLog(shader, sizeof(error), NULL, error);
else
glGetShaderInfoLog(shader, sizeof(error), NULL, error);
std::cerr << errorMessage << ": " << error << std::endl;
}
}
static GLuint CreateShader(const std::string& text, GLenum shaderType)
{
GLuint shader = glCreateShader(shaderType);
if (shader == 0) std::cerr << "Error: shader creation failed" << std::endl;
const GLchar* shaderSourceString = text.c_str();
const GLint shaderSourceStringLength = text.length();
glShaderSource(shader, 1, &shaderSourceString, &shaderSourceStringLength);
glCompileShader(shader);
CheckShaderError(shader, GL_COMPILE_STATUS, false, "Error: shader compilation Failed");
return shader;
}
here are the shader files (My guess is that i have propably messed up something here)
Vertex Shader:
#version 330 core
layout(location = 0) in vec3 position;
void main()
{
gl_Position = vec4(position, 1.0);
}
Fragment Shader:
#version 330 core
out vec4 color;
void main() {
color = vec4(1.0, 0.0, 0.0, 1.0);
}

Open gl sprite class not working

So first of all, i am a total beginner in open gl, and i am learning opengl from learnopengl.com. So i understood whats going on in the code in the main method.The code works in main method. But when i tried to create a class for it, it doesn't render anything!! I have absolutely no idea whats going wrong!
Sprite.h
#pragma once
#include"Shader.h"
#include<GL\glew.h>
class Sprite {
GLuint vao;
GLuint vbo;
int vertexCount;
Shader shader;
public:
Sprite(const GLfloat vertices[9], int noOfVertices, Shader s = Shader()) : vertexCount(noOfVertices) , shader(s)
{
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, this->vertexCount, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void draw() {
glBindVertexArray(this->vao);
glDrawArrays(GL_TRIANGLES, 0, this->vertexCount);
glBindVertexArray(0);
}
};
Shader.h
#pragma once
#include<iostream>
#include<fstream>
#include<sstream>
#include<string>
#include<vector>
#include<GL\glew.h>
class Shader {
GLuint programID;
GLuint vertID;
GLuint fragID;
public:
Shader(std::string vertex = "Shaders/Dvert.vert", std::string fragment = "Shaders/Dfrag.frag")
{
this->programID = glCreateProgram();
this->vertID = glCreateShader(GL_VERTEX_SHADER);
this->fragID = glCreateShader(GL_FRAGMENT_SHADER);
this->CompileShaders(vertex, fragment);
this->LinkProgram();
}
GLuint getProgramId() {
return this->programID;
}
private:
void CompileShaders(std::string vertexShaderPath, std::string FragShaderPath) {
std::string vCode = GetContentsFrom(vertexShaderPath).c_str();
const char * vertexCode = vCode.c_str();
glShaderSource(this->vertID, 1, &vertexCode, NULL);
glCompileShader(this->vertID);
this->HandleShaderErrors(this->vertID);
std::string fCode = GetContentsFrom(FragShaderPath).c_str();
const char * fragCode = fCode.c_str();
glShaderSource(this->fragID, 1, &fragCode, NULL);
glCompileShader(this->fragID);
std::cout << fragCode << std::endl;
this->HandleShaderErrors(this->fragID);
}
void LinkProgram() {
glAttachShader(this->programID, this->vertID);
glAttachShader(this->programID, this->fragID);
glLinkProgram(this->programID);
this->HandleLinkErrors();
}
std::string GetContentsFrom(std::string path) {
std::ifstream file(path);
std::ostringstream stream;
if (!file) {
std::cout << "Specified file path is invalid" << std::endl;
return "";
}
stream << file.rdbuf();
std::cout << stream.str() << std::endl << std::endl;
return stream.str();
}
void HandleLinkErrors() {
int result;
glGetProgramiv(this->programID, GL_LINK_STATUS, &result);
if (result == GL_FALSE) {
int length;
glGetProgramiv(this->programID, GL_INFO_LOG_LENGTH, &length);
std::vector<char> error(length);
glGetProgramInfoLog(this->programID, length , &length, &error[0]);
std::cout << &error[0] << std::endl;
glDetachShader(this->programID, this->vertID);
glDetachShader(this->programID, this->fragID);
}
}
void HandleShaderErrors(GLuint shader) {
int status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
int length;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
std::vector<char> error(length);
glGetShaderInfoLog(shader, length, &length, &error[0]);
std::cout << &error[0] << std::endl;
glDeleteShader(shader);
}
}
};
Main.cpp
#include<GL\glew.h>
#include<GLFW\glfw3.h>
#include"Console.h"
#include"Headers\Shader.h"
#include"Headers\Sprite.h"
#include<iostream>
static const GLfloat vertices[] = {
0.5f, -0.5f ,0.0f ,
-0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
int main() {
if (!glfwInit()) {
Console.Log("GLFW could not be initialised!!");
Console.Wait();
}
GLFWwindow *window = glfwCreateWindow(600, 400, "Open GL", nullptr, nullptr);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) {
Console.Log("GLEW could not be initialised!!");
Console.Wait();
}
Sprite s(vertices, 3);
glClearColor(0, 0, 0, 1);
glfwWindowHint(GLFW_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_VERSION_MINOR, 3);
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwPollEvents();
s.draw();
glfwSwapBuffers(window);
}
}
Please help me out!!
Note:- The code in the main method renders the white triangle without the
shaders,so my graphics card works without shaders.
Also the Console class i have created is just to print to the console and has nothing to do with the opengl stuff. Console.Log isstd::cout<< and Console.Wait is std::cin.get();
There are at least two problems. The first is that your sizeof(vertices) in Sprite produces wrong result, because it gives the size of a pointer, not the size of the array. To fix it, replace it with sizeof(GLfloat) * 9.
The second problem is that you are specifying the OpenGL context version too late, after creating the window and context. To fix it, call these methods before glfwCreateWindow, not after:
glfwWindowHint(GLFW_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_VERSION_MINOR, 3);

Can't get ids assigned to an attribute in OpenGL

I am trying to have OpenGL automatically assign an ID to a glsl-attribute, but it is failing.
My main program:
#include <iostream>
#include <GL/glew.h>
#include <GL/glfw3.h>
#include "test.h"
#include "shader_utils.h"
static void error_callback(int error, const char* description) {
std::cout << description << std::endl;
}
static void key_callback(GLFWwindow* window, int a, int b) {
if (a == GLFW_KEY_ESCAPE && b == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
void test()
{
std::cout << "Starting up" << std::endl;
init();
run();
}
GLFWwindow *window;
GLuint shaders;
GLuint vertexBuffer;
int init() {
glfwSetErrorCallback(error_callback);
if(!glfwInit()) {
return -1;
}
window = glfwCreateWindow(640, 480, "GLFW test", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
glewExperimental = true;
glewInit();
shaders = LoadShaders("vertex.glsl", "fragment.glsl");
GLuint vao_id;
glGenVertexArrays(1, &vao_id);
glBindVertexArray(vao_id);
static const GLfloat vertex_data[] = {
// Bottom
-.5f, -.5f, -.5f, 1.f, 0.f, 0.f,
-.5f, -.5f, .5f, 1.f, 0.f, 0.f,
.5f, -.5f, .5f, 1.f, 0.f, 0.f,
};
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
}
void checkE() {
std::cout << "Checking for errors: ";
int err;
int a = 0;
while((err = glGetError()) != GL_NO_ERROR) {
std::cout << "Error: " << err << std::endl;
a = 1;
}
if(a == 0) {
std::cout << "no errors" << std::endl;
}
std::cout.flush();
}
int run() {
GLfloat angle = 0;
while(!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaders);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
GLuint attrLocation = glGetAttribLocation(shaders, "location");
GLuint attrColor = glGetAttribLocation(shaders, "color");
std::cout << "AttribLocation('location'): ";
std::cout << glGetAttribLocation(shaders, "location") << std::endl;
std::cout << "AttribLocation('color'): ";
std::cout << glGetAttribLocation(shaders, "color") << std::endl;
checkE();
std::cout << std::endl;
std::cout << "glEnableVertexAttribArray()" << std::endl;
glEnableVertexAttribArray(attrLocation);
glEnableVertexAttribArray(attrColor);
checkE();
std::cout << std::endl;
std::cout << "glVertexAttribPointer();" << std::endl;
glVertexAttribPointer(
glGetAttribLocation(shaders, "location"), // Attribute
3, // Size
GL_FLOAT, // Size
GL_FALSE, // Normalized
24, // Stride
(GLvoid*) 0 // Offset
);
checkE();
std::cout << std::endl;
std::cout << "glVertexAttribPointer();" << std::endl;
glVertexAttribPointer(
glGetAttribLocation(shaders, "color"),
3,
GL_FLOAT,
GL_FALSE,
24,
(GLvoid*) (3*sizeof(GLfloat))
);
checkE();
std::cout << std::endl;
glDrawArrays(GL_TRIANGLES, 0, 3);
checkE();
std::cout << std::endl;
glDisableVertexAttribArray(attrLocation);
glDisableVertexAttribArray(attrColor);
checkE();
std::cout << std::endl;
glfwSwapBuffers(window);
glfwPollEvents();
glfwSetWindowShouldClose(window, GL_TRUE);
}
glfwDestroyWindow(window);
glfwTerminate();
}
Output from program:
Starting up
Compiling shader : vertex.glsl
Compiling shader : fragment.glsl
Linking program
AttribLocation('location'): -1
AttribLocation('color'): -1
Checking for errors: no errors
glEnableVertexAttribArray()
Checking for errors: Error: 1281
glVertexAttribPointer();
Checking for errors: Error: 1281
glVertexAttribPointer();
Checking for errors: Error: 1281
Checking for errors: no errors
Checking for errors: Error: 1281
Shader loader:
#include "shader_utils.h"
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include "GL/glew.h"
#include "GL/glfw3.h"
GLuint LoadShaders(const char * vertex_file_path, const char * fragment_file_path){
// 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, std::ios::in);
if(VertexShaderStream.is_open())
{
std::string Line = "";
while(getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
} else {
std::cout << "could not open\n";
}
// 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(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);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> VertexShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
// Compile Fragment Shader
printf("Compiling shader : %s\n", fragment_file_path);
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);
std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
// Link the program
fprintf(stdout, "Linking program\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);
std::vector<char> ProgramErrorMessage( std::max(InfoLogLength, int(1)) );
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
std::cout.flush();
return ProgramID;
}
Vertex shader:
#version 130
in vec4 position;
in vec3 color;
out vec3 f_color;
void main() {
f_color = color;
gl_Position = position * gl_ModelViewProjectionMatrix;
}
Fragment shader:
#version 130
in vec3 color;
void main() {
gl_FragColor = vec4(color, 1);
}
For some reason I get just -1 as the location for both the attributes. Obviously the rest of the errors are caused by invalid location indices?
From OpenGL docs:
If the named attribute variable is not an active attribute in the specified program object or if name starts with the reserved prefix "gl_", a value of -1 is returned.
The names do not begin with gl_ and they are in use in the shaders, so I shouldn't get a value of -1. What am I missing?
You are failing to get an attribute location for color because it is not active. While it is true that color is used to calculate f_color in this example, the fragment shader does not use f_color so the linker determines that the vertex attribute named: color is inactive.
The solution is quite simple, really:
Fragment Shader:
#version 130
in vec3 f_color; // RENAMED from color, so that this matches the output from the VS.
void main() {
gl_FragColor = vec4(f_color, 1);
}
It is not an error to re-use the name color for different purposes in the Vertex Shader (input vertex attribute) and Fragment Shader (input varying) stages so the compiler/linker will not complain. It would be an error if you tried to do something like inout color though, so this is why you have to pass vertex attributes to geometry/tessellation/fragment shaders using a differently named varying. If the input/output names between stages do not match then chances are quite good that the original vertex attribute will be considered inactive.
Also, unless you are transposing your ModelViewProjection matrix, you have the matrix multiplication in your vertex shader backwards. Column-major matrix multiplication, as OpenGL uses, should read right-to-left. That is, you start with an object space position (right-most) and transform to clip space (left-most).
In other words, this is the proper way to transform your vertices...
gl_Position = gl_ModelViewProjectionMatrix * position;
~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~
clip space object space to clip space obj space