I have just started to learn OpenGL, and am following this tutorial. I am having difficulty compiling the GLSL files that the tutorial uses.
Originally when I tried compiling them the compiler said that mesa did not support GLSL version 330 so I changed #version 330 core to #version 130. Now when I run it it gives me the following error:
3.0 Mesa 10.0.20Compiling shader : SimpleVertexShader.vertexshader
0:3(1): error: syntax error, unexpected NEW_IDENTIFIER
Compiling shader : SimpleFragmentShader.fragmentshader
Linking program
error: linking with uncompiled shader
I have searched on google and cannot find anyone with this problem. Anyway, here are all of the files in question:
SimpleVertexShader.vertexshader:
#version 130
layout(location = 0) in vec3 vertexPosition_modelspace;
void main(){
gl_Position.xyz = vertexPosition_modelspace;
gl_Position.w = 1.0;
}
SimpleFragmentShader.fragmentshader:
#version 130
out vec3 color;
void main() {
color = vec3(1,0,0);
}
loadShader.cpp:
#include <stdio.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
#include <stdlib.h>
#include <string.h>
#include <GL/glew.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();
}
// 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( max(InfoLogLength, int(1)) );
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
main.cpp:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
//#define GLFW_DLL // maybe some glu problems - look up
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path);
int main()
{
GLFWwindow * window;
if (!glfwInit()) {
std::cout << "Failed to initiate GLFW\n";
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4); //4x antialiasing
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //version 3
//open a window and create context
window=glfwCreateWindow(1024,768,"Lerning", glfwGetPrimaryMonitor(), NULL);
if (!window) {
std::cout << "Failed to open window\n";
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
std::cout << glGetString(GL_VERSION);
// initialize GLEW
glewExperimental=GL_TRUE; //needed
GLenum err = glewInit();
std::cout << err;
if (err != GLEW_OK) {
std::cout << "Failed to initialize\n" << glewGetErrorString(err);
return -1;
}
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data),
g_vertex_buffer_data, GL_STATIC_DRAW);
GLuint programID = LoadShaders("SimpleVertexShader.vertexshader",
"SimpleFragmentShader.fragmentshader");
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
layout(location = 0) is not valid in GLSL 1.30. Layout qualifiers were introduced in GLSL 1.40. You will need to manually bind that vertex attribute location in your C++ code prior to linking your shaders.
// 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]);
// Create the program
fprintf(stdout, "Linking program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
// Setup Vertex Attributes [NEW]
glBindAttribLocation (ProgramID, 0, "vertexPosition_modelspace");
// Link the program
glLinkProgram(ProgramID);
Chances are this attribute is going to be automatically assigned 0 by the GLSL implementation anyway once you remove the layout (location = 0), but you should go ahead and bind the location to do things the right way.
Related
When I tried to run this I got a "Segmentation fault (core dumped) error and nothing ran:
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include </home/rohan/Documents/opengl/common/loadShader.hpp>
using namespace glm;
int main() {
glewExperimental = true;
if ( !glfwInit() )
{
fprintf(stderr, "Failed to initialize GLFW\n");
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want OpenGL 3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// An array of 3 vectors which represents 3 vertices
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
// This will identify our vertex buffer
GLuint vertexbuffer;
// Generate 1 buffer, put the resulting identifier in vertexbuffer
glGenBuffers(1, &vertexbuffer);
// The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
// Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
GLFWwindow* window;
window = glfwCreateWindow(1024, 768, "Tutorial 01", NULL, NULL);
if (window == NULL)
{
fprintf(stderr, "Failed to open GLFW window.If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental=true;
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "SimpleVertexShader.glsl", "SimpleFragmentShader.glsl" );
do{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 1st attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
// unknown, size, type, normalized?, stride, array buffer offset
0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
// Use our shader
glUseProgram(programID);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
glDisableVertexAttribArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0);
}
vertex shader
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
void main()
{
gl_Position.xyz = vertexPosition_modelspace;
gl_Position.w = 1.0;
}
fragment shader:
#version 330 core
out vec3 color;
void main()
{
color = vec3(1,0,0);
}
shader-loader:
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
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::stringstream sstr;
sstr << VertexShaderStream.rdbuf();
VertexShaderCode = sstr.str();
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();
return 0;
}
// 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::stringstream sstr;
sstr << FragmentShaderStream.rdbuf();
FragmentShaderCode = sstr.str();
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);
if ( InfoLogLength > 0 ){
std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
printf("%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);
if ( InfoLogLength > 0 ){
std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
}
// 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);
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, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
The code is supposed to make a red triangle appear.
To call an OpenGL instruction, you need a valid and current OpenGL context and the OpenGL loader (in your case glew) must be in initialized. Therefore you cannot do the vertex specification before glewInit. Move all OpenGL commands after that:
// [...]
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
// The earliest point for calling an OpenGL (gl*) instruction is here
// [...]
Note, glewExperimental = True is not further necessary (see Initializing GLEW).
I am trying to draw a triangle with GLFW and Glad. But the screen won't display anything (I can only clear the screen).
I am able to Open a Window, and clear the screen to a dark blue color (or any other color)
But I cannot draw a triangle on the Screen, and I do not know why.
I thought maybe my GPU didn't have a default shader.
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <string.h>
#include <vector>
void Log(const char* str) {
std::cout << str << std::endl;
}
void error_callback(int error, const char* description)
{
std::cout << "Error Code ["<< stderr << "] Error: \n" << description << std::endl;
}
class Shader {
public:
Shader(const std::string& vertexSrc, const std::string& fragSrc) {
// Create an empty vertex shader handle
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
const GLchar* source = vertexSrc.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);
std::vector<GLchar> infoLog(maxLength);
glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &infoLog[0]);
glDeleteShader(vertexShader);
return;
}
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
source = fragSrc.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);
std::vector<GLchar> infoLog(maxLength);
glGetShaderInfoLog(fragmentShader, maxLength, &maxLength, &infoLog[0]);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
return;
}
m_RendererID = glCreateProgram();
glAttachShader(m_RendererID, vertexShader);
glAttachShader(m_RendererID, fragmentShader);
glLinkProgram(m_RendererID);
// Note the different functions here: glGetProgram* instead of glGetShader*.
GLint isLinked = 0;
glGetProgramiv(m_RendererID, GL_LINK_STATUS, (int*)&isLinked);
if (isLinked == GL_FALSE)
{
GLint maxLength = 0;
glGetProgramiv(m_RendererID, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> infoLog(maxLength);
glGetProgramInfoLog(m_RendererID, maxLength, &maxLength, &infoLog[0]);
glDeleteProgram(m_RendererID);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return;
}
Log("Shader compiled Successfully at:");
std::cout << m_RendererID << std::endl;
glDetachShader(m_RendererID, vertexShader);
glDetachShader(m_RendererID, fragmentShader);
}
~Shader() {
glDeleteProgram(m_RendererID);
}
void Bind() const {
glUseProgram(m_RendererID);
}
void Unbind() const {
glUseProgram(0);
}
private:
uint32_t m_RendererID = 0;
};
int main() {
Log("Initializing...");
glfwSetErrorCallback(error_callback);
if (!glfwInit())
{
// Initialization failed
Log("Initialization Failed");
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
GLFWwindow* window = glfwCreateWindow(1080, 720, "GLFW_GLAD TEST", NULL, NULL);
if (!window)
{
glfwTerminate();
Log("Window or OpenGL Context Failed");
}
glfwMakeContextCurrent(window);
gladLoadGL();
glfwSwapInterval(1);
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
//APP CODE
unsigned int m_VertexArray;
unsigned int m_VertexBuffer;
unsigned int m_IndexBuffer;
float vertices[9] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
// Vertex Array
glGenVertexArrays(1, &m_VertexArray);
glBindVertexArray(m_VertexArray);
// Vertex Buffer
glGenBuffers(1, &m_VertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glDisableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
// Index Buffer
glGenBuffers(1, &m_IndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IndexBuffer);
unsigned int indices[3] = {
0, 1, 2,
};
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
std::string vertexSrc = R"(
#version 330
layout(location = 0) in vec3 a_Pos;
void main()
{
gl_Position = vec4(a_Pos, 1);
}
)";
std::string fragmentSrc = R"(
#version 330
layout(location = 0) out vec4 FragColor;
void main()
{
FragColor = vec4(0.8f, 0.5f, 0.2f, 1.0f);
}
)";
Shader* shader = new Shader(vertexSrc, fragmentSrc);
shader->Bind();
while (!glfwWindowShouldClose(window))
{
glViewport(0, 0, width, height);
glClearColor(0.1f, .1f, .14f, 1);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(m_VertexArray);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
This here definitively is wrong.
glDisableVertexAttribArray(0);
You meant glEnableVertexAttribArray here, so that the attibute pointer you are setting up is actually used. For disabled attribute arrays, all shader invocations will get a constant value.
Also your shaders use #version 330 and actually require GLSL 330 syntax, however:
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
you request only a GL 2.0 context and GL 2.0 only mandates support for GLSL 1.10. If this is going to work will be completely up to your driver, you might get some >= 3.3 compatibility profile, but you can't count on it.
You should create a 3.3 context explicitly, and also explicitly request a core profile.
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.
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()
I'm trying to learn SDL2, modern OpenGL, etc...
Below is the code I've adapted from tutorial for use with SDL2.
I have managed to get everything else to work, but for some reason the shader part crashes the program...
...I'm unable to get any console output to work (any tips on that?).
I'm using Eclipse.
Also if you find any other fixable spots on the code, please feel free to
point them out.
Program compiles without any errors or warnings.
#include <windows.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <SDL2/SDL.h>
#include <fstream>
#include <string>
#include <cmath>
#include <vector>
const int WINDOW_W = 1280;
const int WINDOW_H = 720;
const int WINDOW_X = 200;
const int WINDOW_Y = 200;
// FUNCTIONS
/* Shader loader:
* Handles loading GLSL vertex and fragment shaders
*/
GLuint ShaderLoad(const char * vertex_file_path, const char * fragment_file_path)
{
// Vertex shader ID
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
//Read the vertex shader files
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();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile vertex shader
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]);
// Fragment shader ID
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
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();
}
// 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(InfoLogLength);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
//GLuint programID = ShaderLoad("vshader.glsl", "fshader.glsl");
// Main
int main(int argc, char **argv)
{
//Variables
SDL_Window * SDLWindow = NULL;
SDL_GLContext GLContext;
SDL_Event event;
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
SDL_Init(SDL_INIT_EVERYTHING);
SDLWindow = SDL_CreateWindow("ELSA",
WINDOW_X, WINDOW_Y,
WINDOW_W, WINDOW_H,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
GLContext = SDL_GL_CreateContext(SDLWindow);
SDL_GL_MakeCurrent(SDLWindow, GLContext);
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetSwapInterval(1);
// OPENGL INIT
glewExperimental = GL_TRUE;
glewInit();
GLuint vertexbuffer;
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Generate 1 buffer, put the resulting identifier in vertexbuffer
glGenBuffers(1, &vertexbuffer);
// The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
// Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER,
sizeof(g_vertex_buffer_data),
g_vertex_buffer_data, GL_STATIC_DRAW);
while(true)
{
while (SDL_PollEvent(&event)) // Get all events per frame
{
if (event.type == SDL_QUIT)
{
return false;
}
if (event.type == SDL_WINDOWEVENT_RESIZED)
{
glViewport(0, 0,
SDL_GetWindowSurface(SDLWindow)->w,
SDL_GetWindowSurface(SDLWindow)->h);
}
}
//OpenGL code
glClearColor(0.15, 0.15, 0.30, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use shader
//glUseProgram(programID);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_TRIANGLES, 0, 3);
SDL_GL_SwapWindow(SDLWindow);
glDisableVertexAttribArray(0);
}
SDL_GL_DeleteContext(GLContext);
SDL_DestroyWindow(SDLWindow);
SDL_Quit();
return 0;
}