I'm trying to write shaders using GLSL but whenever I try to compile this code an exception gets thrown in visual studio and I have no idea how to handle it or what exactly is causing the problem here so I'd appreciate some help. The exception says:
First-chance exception at 0x00220645 in Open GL.exe: 0xC0000005: Access violation reading location 0x00D54000.
I don't really know how to go about that. When I check my output I see that everything happens as it's supposed to with the exception of two lines:
'Open GL.exe' (Win32): Loaded 'C:\Windows\SysWOW64\ig7icd32.dll'. Cannot find or open the PDB file.
'Open GL.exe' (Win32): Loaded 'C:\Windows\SysWOW64\igdusc32.dll'. Cannot find or open the PDB file.
Here's my code:
Main.cpp
#include <iostream>
#include "Display.h"
#include "Shader.h"
int main(int argc, char *argv[])
{
Display display(800, 600, "test");
Shader shader("basicshader");
while (!display.isClosed())
{
display.Clear(1.0f, 0.0f, 0.0f, 1.0f);
shader.Bind();
display.Update();
}
return 0;
}
Display.cpp
#pragma once
#include "Display.h"
Display::Display(int width, int height, const char *title)
{
if (SDL_Init(SDL_INIT_EVERYTHING) == 0)
{
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
m_window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
m_context = SDL_GL_CreateContext(m_window);
GLenum status = glewInit();
if (status != GLEW_OK){
std::cerr << "this is where the problem is" << std::endl;
}
m_isClosed = false;
}
}
Display::~Display()
{
std::cerr << "destructor ran" << std::endl;
SDL_GL_DeleteContext(m_context);
SDL_DestroyWindow(m_window);
SDL_Quit();
}
void Display::Update()
{
SDL_Event event;
SDL_GL_SwapWindow(m_window);
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
m_isClosed = true;
}
}
}
void Display::Clear(float r, float g, float b, float a)
{
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT);
}
bool Display::isClosed(){
return m_isClosed;
}
Display.h
#pragma once
#include <SDL.h>
#include <glew.h>
#include <iostream>
class Display
{
public:
void Update();
void Clear(float r, float g, float b, float a);
bool isClosed();
Display(int width, int height, const char *title);
virtual ~Display();
private:
bool m_isClosed;
SDL_Window* m_window;
SDL_GLContext m_context;
};
Shader.cpp
#pragma once
#include "Shader.h"
std::string Shader::LoadShader(const std::string& filename)
{
std::ifstream file;
std::string output;
std::string line;
file.open(filename.c_str());
if (file.is_open())
{
while (file)
{
std::getline(file, line);
output.append(line + "\n");
}
file.close();
return output;
}
}
GLuint Shader::CreateShader(const std::string& text, GLenum shadertype)
{
GLuint shader = glCreateShader(shadertype);
const GLchar* shadersourcestrings[1];
GLint shadersourcelengths[1];
shadersourcestrings[0] = text.c_str();
shadersourcelengths[0] = text.length();
glShaderSource(shader, 1, shadersourcestrings, shadersourcelengths);
glCompileShader(shader);
return shader;
}
void Shader::Bind()
{
glUseProgram(m_program);
}
Shader::Shader(const std::string& filename)
{
m_program = glCreateProgram();
m_shaders[0] = CreateShader(LoadShader(filename + ".shade_v"), GL_VERTEX_SHADER);
m_shaders[1] = CreateShader(LoadShader(filename + ".shade_f"), GL_FRAGMENT_SHADER);
for (unsigned int i = 0; NUMOFSHADERS; i++)
{
glAttachShader(m_program, m_shaders[i]); <~(breaks here)
};
glBindAttribLocation(m_program, 0, "position");
glLinkProgram(m_program);
}
Shader::~Shader()
{
for (unsigned int i = 0; NUMOFSHADERS; i++)
{
glDetachShader(m_program, m_shaders[i]);
glDeleteShader(m_shaders[i]);
}
glDeleteProgram(m_program);
}
Shader.h
#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <glew.h>
class Shader
{
public:
const static unsigned int NUMOFSHADERS = 2;
GLuint m_program;
GLuint m_shaders[NUMOFSHADERS];
void Bind();
static std::string LoadShader(const std::string& filename);
static GLuint CreateShader(const std::string& text, GLenum shadertype);
Shader(const std::string& filename);
virtual ~Shader();
};
basicshader.shade_v
#version 120
void main()
{
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
basicshader.shade_f
#version 120
attribute vec3 position;
void main()
{
gl_position = vec4(postion, 1.0);
}
One problem is if LoadShader can't open the file it will return garbage, since it falls off the end without returning anything (which results in Undefined Behavior). This could result in the problem you're seeing.
If you compile with the warnings maxed out (/W4) you'll get a warning about that ("not all control paths return a value", or something like that).
Related
So I've been learning OpenGL for sometimes now and today I come up with an idea to put multiple
shaders in one std::map, like this
std::map<std::string, Shader> Shaders;
the key holds the name of the shader and the value is the Shader class I created.
Then I worte both add and get shader function
void AddShader(std::string filepath, std::string name)
{
Shader shader(filepath);
Shaders[name] = shader;
if (glIsProgram(Shaders[name].m_RendererID) != GL_TRUE)
{
std::cout << "invalid program" << std::endl;
__debugbreak();
}
}
Shader GetShader(std::string name)
{
//added for debug purposes.
if (glIsProgram(Shaders[name].m_RendererID) != GL_TRUE)
{
std::cout << "invalid program" << std::endl;
__debugbreak();
}
return Shaders[name];
}
Now here comes the problem. Whenever I tried to call GetShader function I would recieve
invalid program error and bind shader wouldn't work either as it would return GL_INVALID_VALUE
here is shader class I abstracted:
Shader.h
#pragma once
#include <string>
#include "glm/glm.hpp"
#include <glad/glad.h>
struct ShaderProgramSources
{
std::string VertexSource;
std::string FragmentSource;
};
class Shader
{
private:
std::string m_FilePath;
int GetUniformLocation(const std::string& name);
public:
unsigned int m_RendererID;
Shader(const std::string& filepath);
Shader(void) {}
~Shader();
void Bind() const;
void Unbind() const;
ShaderProgramSources ParseShader(const std::string& filepath);
unsigned int CompileShader(unsigned int type, const std::string& source);
unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader);
Shader.cpp
#include "Shader.h"
#include <iostream>
#include <string>
#include <fstream>
#include <string>
#include <sstream>
Shader::Shader(const std::string& filepath)
: m_FilePath(filepath), m_RendererID(0)
{
ShaderProgramSources source = ParseShader(filepath);
m_RendererID = CreateShader(source.VertexSource, source.FragmentSource);
}
Shader::~Shader()
{
glDeleteProgram(m_RendererID);
}
void Shader::Bind() const
{
glUseProgram(m_RendererID);
}
void Shader::Unbind() const
{
glUseProgram(0);
}
unsigned int Shader::CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
{
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program);
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
unsigned int Shader::CompileShader(unsigned int type, const std::string& source)
{
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
std::cout << "Failed to compile " << std::endl;
if (type == GL_VERTEX_SHADER)
std::cout << "vertex " << std::endl;
else
std::cout << "fragment " << std::endl;
std::cout << message << std::endl;
glDeleteShader(id);
return 0;
}
return id;
}
ShaderProgramSources Shader::ParseShader(const std::string& filepath)
{
std::ifstream stream(filepath);
enum class ShaderType
{
NONE = -1, VERTEX = 0, FRAGMENT = 1
};
std::string line;
std::stringstream ss[2];
ShaderType type = ShaderType::NONE;
while (getline(stream, line))
{
if (line.find("#shader") != std::string::npos)
{
if (line.find("vertex") != std::string::npos)
{
type = ShaderType::VERTEX;
}
if (line.find("fragment") != std::string::npos)
{
type = ShaderType::FRAGMENT;
}
}
else
{
ss[(int)type] << line << '\n';
}
}
ShaderProgramSources sources;
sources.VertexSource = ss[0].str();
sources.FragmentSource = ss[1].str();
return sources;
}
both vertex and fragment shader are put in one single file identified by "#shader vertex"
and "#shader fragment" at the beginning of each shader. Like this:
#shader vertex
#version 330 core
...
#shader fragment
#version 330 core
...
Main file
int main(int argc, char* argv[])
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
GLFWwindow* window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "TITLE", nullptr, nullptr);
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDebugMessageCallback([](GLenum source, GLenum type, GLuint id, GLenum serverity,
GLsizei length, const GLchar* message, const void* userParam)
{
std::cout << source << message << std::endl;
__debugbreak();
}, NULL);
AddShader("Shader/test1.shader", "shader1");
AddShader("Shader/test2.shader", "shader2");
Shader shader = GetShader("shader1");
Shader shader2 = GetShader("shader2");
shader.Bind();
float deltaTime = 0.0f;
float lastFrame = 0.0f;
while (!glfwWindowShouldClose(window))
{
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glfwPollEvents();
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
Can somebody please tell me where the problems are? Thanks
Look at your AddShader code:
Shader shader(filepath);
So you have a Shader object local to this function.
Shaders[name] = shader;
Now this copies the Shader object into the container, using the implicit copy constructor. You have now two Shader objects, both referencing the same GL object ID, one in the map, and one in your local variable.
When the function is left, the local variable gets out of scope, and the destructor is called, which destroys the GL object. What's left is the copy in the map, which still references the now-destroyed GL object ID.
Naively wrapping GL objects in C++ objects isn't going to work. You will need a more elaborate scheme for proper OpenGL object management.
if (glIsProgram(Shaders[name].m_RendererID) != GL_TRUE)
Shaders is a std::map. Its operator[] default-constructs the object if the key does not exist in the map.
Your Shader class's default constructor fails to initialize m_RendererID. As such, this results in undefined behavior, whenever the name that gets passed in does not exist.
You can use your debugger to set a breakpoint here, when that happens, then work your way up the call stack and determine the reason for the logical error. You will discover that m_RendererID gets set to the return value of glCreateProgram, and based on its description, a comparison against GL_TRUE appears to be meaningless.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I try to launch next code, but it gives error with code 1285 on line glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr) (Application.cpp).
If I replace preceding line of code with glDrawArrays(GL_TRIANGLES, 0, 3) it draws a triangle, so shader, vertex buffer, vertex array binding works fine. The problem should be in IndexBuffer, but I can't find it.
Renderer.h
#pragma once
#include <GL/glew.h>
#define ASSERT(x) if (!(x)) __debugbreak();
#define GLCall(x) GLClearError();\
x;\
ASSERT(GLLogCall(#x, __FILE__, __LINE__))
void GLClearError();
bool GLLogCall(const char* function, const char* file, int line);
Renderer.cpp
#include "Renderer.h"
#include <iostream>
void GLClearError()
{
while (glGetError() != GL_NO_ERROR);
}
bool GLLogCall(const char* function, const char* file, int line)
{
while (GLenum error = glGetError())
{
std::cout << "[OpenGL Error] (" << error << "): " << function <<
" " << file << ": " << line << std::endl;
return false;
}
return true;
}
VertexBuffer.h
#pragma once
class VertexBuffer
{
private:
unsigned int m_RendererID;
public:
VertexBuffer(const void* data, unsigned int size);
~VertexBuffer();
void Bind() const;
void Unbind() const;
};
VertexBuffer.cpp
#include "VertexBuffer.h"
#include "Renderer.h"
VertexBuffer::VertexBuffer(const void* data, unsigned int size)
{
GLCall(glGenBuffers(1, &m_RendererID));
GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_RendererID));
GLCall(glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW));
}
VertexBuffer::~VertexBuffer()
{
GLCall(glDeleteBuffers(1, &m_RendererID));
}
void VertexBuffer::Bind() const
{
GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_RendererID));
}
void VertexBuffer::Unbind() const
{
GLCall(glBindBuffer(GL_ARRAY_BUFFER, 0));
}
IndexBuffer.h
#pragma once
class IndexBuffer
{
private:
unsigned int m_RendererID;
unsigned int m_Count;
public:
IndexBuffer(const unsigned int* data, unsigned int count);
~IndexBuffer();
void Bind() const;
void Unbind() const;
inline unsigned int GetCount() const { return m_Count; }
};
IndexBuffer.cpp
#include "IndexBuffer.h"
#include "Renderer.h"
IndexBuffer::IndexBuffer(const unsigned int* data, unsigned int count)
: m_Count(count)
{
ASSERT(sizeof(unsigned int) == sizeof(GLuint));
GLCall(glGenBuffers(1, &m_RendererID));
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID));
GLCall(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(unsigned int), data, GL_STATIC_DRAW);
}
IndexBuffer::~IndexBuffer()
{
GLCall(glDeleteBuffers(1, &m_RendererID));
}
void IndexBuffer::Bind() const
{
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID));
}
void IndexBuffer::Unbind() const
{
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
Application.cpp
#pragma once
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include "Renderer.h"
#include "VertexBuffer.h"
#include "IndexBuffer.h"
struct ShaderProgramSource
{
std::string VertexSource;
std::string FragmentSource;
};
static ShaderProgramSource ParseShader(const std::string& filepath)
{
std::fstream stream(filepath);
enum class ShaderType
{
NONE = -1, VERTEX = 0, FRAGMENT = 1
};
std::string line;
std::stringstream ss[2];
ShaderType type = ShaderType::NONE;
while (getline(stream, line))
{
if (line.find("#shader") != std::string::npos)
{
if (line.find("vertex") != std::string::npos)
{
type = ShaderType::VERTEX;
}
else if (line.find("fragment") != std::string::npos)
{
type = ShaderType::FRAGMENT;
}
}
else
{
ss[(int)type] << line << '\n';
}
}
return { ss[0].str(), ss[1].str() };
}
static unsigned int CompileShader(unsigned int type, const std::string& source)
{
GLCall(unsigned int id = glCreateShader(type));
const char* src = source.c_str();
GLCall(glShaderSource(id, 1, &src, nullptr));
GLCall(glCompileShader(id));
int result;
GLCall(glGetShaderiv(id, GL_COMPILE_STATUS, &result));
if (result == GL_FALSE)
{
int length;
GLCall(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length));
char* message = (char*)alloca(length * sizeof(char));
GLCall(glGetShaderInfoLog(id, length, &length, message));
std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader!" << std::endl;
std::cout << message << std::endl;
GLCall(glDeleteShader(id));
return 0;
}
return id;
}
static unsigned int CreateProgram(const std::string& vertexShader, const std::string& fragmentShader)
{
GLCall(unsigned int program = glCreateProgram());
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
GLCall(glAttachShader(program, vs));
GLCall(glAttachShader(program, fs));
GLCall(glLinkProgram(program));
GLCall(glValidateProgram(program));
GLCall(glDeleteShader(vs));
GLCall(glDeleteShader(fs));
return program;
}
int main()
{
GLFWwindow* window;
if (!glfwInit())
{
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(640, 400, "Hello world", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
if (glewInit() != GLEW_OK)
{
std::cout << "Error while GLEW init!" << std::endl;
}
std::cout << glGetString(GL_VERSION) << std::endl;
{
float positions[] = {
-0.5f, -0.5f, // 0
0.5f, -0.5f, // 1
0.5f, 0.5f, // 2
-0.5f, 0.5f // 3
};
unsigned int indices[] = {
0, 1, 2,
2, 3, 0
};
unsigned int vao;
GLCall(glGenVertexArrays(1, &vao));
GLCall(glBindVertexArray(vao));
VertexBuffer vb(positions, 4 * 2 * sizeof(float));
GLCall(glEnableVertexAttribArray(0));
GLCall(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0));
IndexBuffer ib(indices, 6);
ShaderProgramSource source = ParseShader("res/shaders/Basic.shader");
unsigned int program = CreateProgram(source.VertexSource, source.FragmentSource);
GLCall(glUseProgram(program));
GLCall(int location = glGetUniformLocation(program, "u_Color"));
ASSERT(location != -1);
GLCall(glUniform4f(location, 0.8f, 0.3f, 0.8f, 1.0f));
GLCall(glBindVertexArray(0));
GLCall(glUseProgram(0));
vb.Unbind();
ib.Unbind();
float r = 0;
float increment = 0.05f;
while (!glfwWindowShouldClose(window))
{
GLCall(glClear(GL_COLOR_BUFFER_BIT));
glClearColor(1, 0, 0, 1);
GLCall(glUseProgram(program));
GLCall(glUniform4f(location, r, 0.3f, 0.8f, 1.0f));
GLCall(glBindVertexArray(vao));
ib.Bind();
// glDrawArrays(GL_TRIANGLES, 0, 3);
GLCall(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr));
if (r > 1.0f)
{
increment = -0.05f;
}
else if (r < 0.0f)
{
increment = 0.05f;
}
r += increment;
glfwSwapBuffers(window);
glfwPollEvents();
}
GLCall(glDeleteProgram(program));
}
glfwTerminate();
return 0;
}
Basic.shader
#shader vertex
#version 330 core
layout(location = 0) in vec4 position;
void main()
{
gl_Position = position;
}
#shader fragment
#version 330 core
layout(location = 0) out vec4 color;
uniform vec4 u_Color;
void main()
{
color = u_Color;
}
This does not look right. Missing a glBufferData?
GLCall(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(unsigned int), data, GL_STATIC_DRAW);
I'm having a problem with glCreateShaders. It always returns 0. I'm using Glew with SDL and whenever I run the program, it says:
0(1) : error C0000: syntax error, unexpected '}' at token "}"
Shader Shaders/colorShading.vert failed to compile!
main.cpp:
#include <iostream>
#include "MainGame.h"
int main(int argc, char** argv)
{
MainGame maingame;
maingame.run();
return 0;
}
MainGame.h:
//Core -> initializing glew, sdl etc...
//Just ignore the sprite class
#pragma once
#include <SDL/SDL.h>
#include <GL/glew.h>
#include <iostream>
#include <string>
#include "Errors.h"
#include "GLSLProgram.h"
enum class GameState {PLAY, EXIT};
#include "Sprite.h"
class MainGame
{
public:
MainGame(void);
~MainGame(void);
void run();
private:
void initSystems();
void initShaders();
void gameLoop();
void processInput();
void drawGame();
SDL_Window* _window;
int _screenWidth;
int _screenHeight;
GameState _gameState;
Sprite _sprite;
GLSLProgram _colorProgram;
};
MainGame.cpp:
#include "MainGame.h"
MainGame::MainGame(void)
{
_window = nullptr;
_screenWidth = 1024;
_screenHeight = 700;
_gameState = GameState::PLAY;
}
MainGame::~MainGame(void)
{
}
void MainGame::run()
{
initSystems();
_sprite.init(-1.0f, -1.0f, 1.0f, 1.0f);
gameLoop();
}
void MainGame::initSystems()
{
//Initialize SDL
SDL_Init(SDL_INIT_EVERYTHING);
_window = SDL_CreateWindow("Game Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, _screenWidth, _screenHeight, SDL_WINDOW_OPENGL);
if (_window == nullptr)
{
fatalError("SDL Window could not be created!");
}
SDL_GLContext glContext = SDL_GL_CreateContext(_window);
if (glContext == nullptr)
fatalError("SDL_GL context could not be created!");
GLenum error = glewInit();
if (error != GLEW_OK)
fatalError("Could not initialize glew!");
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
initShaders();
}
void MainGame::initShaders()
{
_colorProgram.compileShaders("Shaders/colorShading.vert", "Shaders/colorShading.frag");
_colorProgram.addAttribute("vertexPosition");
_colorProgram.linkShaders();
}
void MainGame::gameLoop()
{
while (_gameState != GameState::EXIT)
{
processInput();
drawGame();
}
}
void MainGame::processInput()
{
SDL_Event evnt;
while (SDL_PollEvent(&evnt))
{
switch (evnt.type)
{
case SDL_QUIT:
_gameState = GameState::EXIT;
break;
case SDL_MOUSEMOTION:
std::cout << "New Coords: " << evnt.motion.x << " " << evnt.motion.y << std::endl;
break;
}
}
}
void MainGame::drawGame()
{
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_colorProgram.use();
_sprite.draw();
_colorProgram.unUse();
SDL_GL_SwapWindow(_window);
}
GLSLProgram.h:
//Used for
#pragma once
#include <string>
#include <GL/glew.h>
//#include <SDL/SDL.h>
#include "Errors.h"
class GLSLProgram
{
public:
GLSLProgram();
~GLSLProgram();
void compileShaders(const std::string& vertextShaderFilePath, const std::string& fragmentShaderFilePath);
void linkShaders();
void addAttribute(const std::string&);
void use();
void unUse();
private:
int _numAttributes;
void _compileShader(const std::string&, GLuint);
GLuint _programID;
GLuint _vertexShaderID;
GLuint _fragmentShaderID;
};
GLSLProgram.cpp:
//Used for compiling shaders
#include "GLSLProgram.h"
#include <fstream>
#include <vector>
GLSLProgram::GLSLProgram() : _numAttributes(0), _programID(0), _vertexShaderID(0), _fragmentShaderID(0)
{
}
GLSLProgram::~GLSLProgram()
{
}
void GLSLProgram::compileShaders(const std::string& vertexShaderFilePath, const std::string& fragmentShaderFilePath)
{
_vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
if (_vertexShaderID == 0)
{
fatalError("Vertex shader failed to be created!");
SDL_Quit();
}
_fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
if (_fragmentShaderID == 0)
{
fatalError("Fragment shader failed to be created!");
SDL_Quit();
}
_compileShader(vertexShaderFilePath, _vertexShaderID);
_compileShader(fragmentShaderFilePath, _fragmentShaderID);
}
void GLSLProgram::addAttribute(const std::string& attributeName)
{
glBindAttribLocation(_programID, _numAttributes++, attributeName.c_str());
}
void GLSLProgram::use()
{
glUseProgram(_programID);
for (int x = 0; x < _numAttributes; x++)
{
glEnableVertexAttribArray(x);
}
}
void GLSLProgram::unUse()
{
glUseProgram(0);
for (int x = 0; x < _numAttributes; x++)
{
glDisableVertexAttribArray(x);
}
}
void GLSLProgram::linkShaders()
{
//Vertex and fragment shaders are successfully compiled.
//Now time to link them together into a program.
//Get a program object.
_programID = glCreateProgram();
//Attach our shaders to our program
glAttachShader(_programID, _vertexShaderID);
glAttachShader(_programID, _fragmentShaderID);
//Link our program
glLinkProgram(_programID);
//Note the different functions here: glGetProgram* instead of glGetShader*.
GLint isLinked = 0;
glGetProgramiv(_programID, GL_LINK_STATUS, (int *)&isLinked);
if (isLinked == GL_FALSE)
{
GLint maxLength = 0;
glGetProgramiv(_programID, GL_INFO_LOG_LENGTH, &maxLength);
//The maxLength includes the NULL character
std::vector<char> infoLog(maxLength);
glGetProgramInfoLog(_programID, maxLength, &maxLength, &infoLog[0]);
//We don't need the program anymore.
glDeleteProgram(_programID);
//Don't leak shaders either.
glDeleteShader(_vertexShaderID);
glDeleteShader(_fragmentShaderID);
printf("%s\n", &(infoLog[0]));
fatalError("Shaders failed to link!");
}
//Always detach shaders after a successful link.
glDetachShader(_programID, _vertexShaderID);
glDetachShader(_programID, _fragmentShaderID);
glDeleteProgram(_programID);
glDeleteShader(_vertexShaderID);
glDeleteShader(_fragmentShaderID);
}
void GLSLProgram::_compileShader(const std::string &filePath, GLuint id)
{
std::ifstream vertexFile(filePath);
if (vertexFile.fail())
{
perror(filePath.c_str());
fatalError("Failed to open " + filePath);
}
std::string fileContents;
std::string line;
while (std::getline(vertexFile, line));
{
fileContents += line + "\n";
}
vertexFile.close();
const char *contentsPtr = fileContents.c_str();
glShaderSource(id, 1, &contentsPtr, nullptr);
glCompileShader(id);
GLint isCompiled = 0;
glGetShaderiv(id, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &maxLength);
//The maxLength includes the NULL character
std::vector<char> errorLog(maxLength);
glGetShaderInfoLog(id, maxLength, &maxLength, &errorLog[0]);
//Provide the infolog in whatever manor you deem best.
//Exit with failure.
glDeleteShader(id); //Don't leak the shader.
printf("%s\n", &(errorLog[0]));
fatalError("Shader" + filePath + "failed to compile!");
}
}
vertex shader:
#version 130
//The vertex shader operates on each vertex
//input data from the VBO. Each vertex is 2 floats
in vec2 vertexPosition;
void main()
{
//Set the x,y position on the screen
gl_Position.xy = vertexPosition;
//the z position is zero since we are in 2D
gl_Position.z = 0.0;
//Indicate that the coordinates are normalized
gl_Position.w = 1.0;
}
and fragment shader:
#version 130
//The fragment shader operates on each pixel in a given polygon
//This is the 3 component float vector that gets outputted to the screen
//for each pixel.
out vec3 color;
void main() {
//Just hardcode the color to red
color = vec3(1.0, 0.0, 1.0);
}
I don't have any idea why it is happening. :(
PS: I'm beginner with glew so please don't answer with some advance stuff:D
Edit 1:
02/11/2014 (11/02/2014 for Americans)
I downloaded the source code from the tutorial I was using and it is working. So there's something with my code. I will edit the post when I find the problem.
Remove semicolon in file GLSLProgram.cpp at line:
while (std::getline(vertexFile, line));
You go through the file and then just add to the empty string fileContents the last line of your shader code, that is '}'.
for the last two days I've been watching following (really great and informative) tutorial series: http://www.youtube.com/playlist?list=PLEETnX-uPtBXT9T-hD0Bj31DSnwio-ywh
Last night I finished the part about meshes and now a red triangle is supposed to appear on my window, but it just doesn't. I don't know if it is a problem with my mesh or with my shader class (for both of them I don't get any errors). I use GLEW 1.10.0 for loading OpenGL, GLM 0.9.5.4 for OpenGL math stuff and SDL 2.0.3 for window stuff. Everything running on Windows 8.1 in Visual Studio 2013 Ultimate with the latest Nvidia graphics drivers.
Edit: I forgot to mention that the screen doesn't stay black, so the display.Clear method works. I hope thats any help.
Here are my shader and mesh files:
Shader.h:
#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <glew\glew.h>
using namespace std;
class Shader
{
public:
Shader(const string& fileName);
virtual ~Shader();
void Bind();
private:
string LoadShader(const string& fileName);
void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const string& errorMessage);
GLuint CreateShader(const string& text, GLenum shaderType);
static const unsigned int NUM_SHADERS = 2;
GLuint m_program;
GLuint m_shaders[NUM_SHADERS];
};
Shader.cpp
#include "Shader.h"
Shader::Shader(const string& fileName)
{
m_program = glCreateProgram();
m_shaders[0] = CreateShader(LoadShader(fileName + ".vert"), GL_VERTEX_SHADER);
m_shaders[1] = CreateShader(LoadShader(fileName + ".frag"), GL_FRAGMENT_SHADER);
for (unsigned int i = 0; i < NUM_SHADERS; i++)
glAttachShader(m_program, m_shaders[i]);
glLinkProgram(m_program);
CheckShaderError(m_program, GL_LINK_STATUS, true, "Error: Program linking failed");
glValidateProgram(m_program);
CheckShaderError(m_program, GL_VALIDATE_STATUS, true, "Error: Program is invalid");
}
Shader::~Shader()
{
for (unsigned int i = 0; i < NUM_SHADERS; i++)
{
glDetachShader(m_program, m_shaders[i]);
glDeleteShader(m_shaders[i]);
}
glDeleteProgram(m_program);
}
string Shader::LoadShader(const string& fileName)
{
ifstream file;
file.open(fileName.c_str());
string line;
string output;
if (file.is_open())
{
while (file.good())
{
getline(file, line);
output += (line + "\n");
}
}
else
{
cerr << "Unable to load shader: " << fileName << endl;
}
return output;
}
GLuint Shader::CreateShader(const string& text, GLenum shaderType)
{
GLuint shader = glCreateShader(shaderType);
if (shader == 0)
cerr << "Error: Shader creation failed!";
const GLchar* shaderSourceStrings[1] = { text.c_str() };
GLint shaderSourceStringLengths[1] = { text.length() };
glShaderSource(shader, 1, shaderSourceStrings, shaderSourceStringLengths);
glCompileShader(shader);
CheckShaderError(shader, GL_COMPILE_STATUS, false, "Error: Shader compilation failed");
return shader;
}
void Shader::Bind()
{
glUseProgram(m_program);
}
void Shader::CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const 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);
cerr << errorMessage << ": '" << error << "'" << endl;
}
}
BasicShader.vert:
#version 420 core
attribute vec3 position;
void main()
{
gl_Position = vec4(position, 1.0);
}
BasicShader.frag:
#version 420 core
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
Mesh.h:
#pragma once
#include <glew\glew.h>
#include "Vertex.h"
class Mesh
{
public:
Mesh(Vertex* vertecies, unsigned int numVertecies);
virtual ~Mesh();
void Draw();
private:
enum
{
POSITION_VB,
NUM_BUFFERS
};
GLuint m_vertexArrayObject;
GLuint m_vertexArrayBuffers[NUM_BUFFERS];
unsigned int m_drawCount;
};
Mesh.cpp:
#include "Mesh.h"
Mesh::Mesh(Vertex* vertecies, unsigned int numVertecies)
{
m_drawCount = numVertecies;
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(m_vertexArrayObject);
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertecies[0]) * numVertecies, vertecies, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
}
Mesh::~Mesh()
{
glDeleteBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glDeleteVertexArrays(1, &m_vertexArrayObject);
}
void Mesh::Draw()
{
glBindVertexArray(m_vertexArrayObject);
glDrawArrays(GL_TRIANGLES, 0, m_drawCount);
glBindVertexArray(0);
}
Vertex.h:
#pragma once
#include <glm\glm.hpp>
using namespace glm;
class Vertex
{
public:
Vertex(const vec3& pos);
virtual ~Vertex();
private:
vec3 m_pos;
};
Vertex.cpp:
#include "Vertex.h"
Vertex::Vertex(const vec3& pos)
{
m_pos = pos;
}
Vertex::~Vertex()
{
}
main.cpp:
#include "Display.h"
#include "Shader.h"
#include "Mesh.h"
using namespace std;
int main(int argc, char** argv)
{
Display display(800, 600, "Hello World");
Vertex vertecies[] =
{
Vertex(vec3(-0.5, -0.5, 0)),
Vertex(vec3(0, 0.5, 0)),
Vertex(vec3(0.5, -0.5, 0))
};
Mesh mesh(vertecies, sizeof(vertecies) / sizeof(vertecies[0]));
Shader shader(".\\res\\BasicShader");
while (!display.IsClosed())
{
display.Clear(0.0f, 0.15f, 0.3f, 1.0f);
shader.Bind();
mesh.Draw();
display.Update();
}
return 0;
}
I'd be very grateful for any help...
Try changing your vertex program to:
#version 420 core
layout(location = 0) in vec3 position;
void main()
{
gl_Position = vec4(position, 1.0);
}
and your fragment program to:
#version 420 core
out vec4 frag;
void main()
{
frag = vec4(1.0, 0.0, 0.0, 1.0);
}
This program builds with no problem, and the executable starts up, but no triangle shows up. I am following a GLSL tutorial where a Shader class is made to handle GLSL files.
Shader.h
#ifndef SHADER_H_
#define SHADER_H_
#include <GL/glew.h>
#include <GL/glfw.h>
#include <string>
class Shader {
public:
Shader();
Shader(const char *vsFile, const char *fsFile);
~Shader();
void init(const char *vsFile, const char *fsFile);
void bind();
void unbind();
unsigned int id();
private:
unsigned int shader_id;
unsigned int shader_vp;
unsigned int shader_fp;
};
#endif // SHADER_H_
Shader.cpp
#include "Shader.h"
#include <cstring>
#include <iostream>
#include <ftream>
#include <cstdlib>
using namespace std;
static char* textFileRead(const char *fileName) {
char* text;
if (fileName != NULL) {
FILE *file = fopen(fileName, "rt");
if (file != NULL) {
fseek(file, 0, SEEK_END);
int count = ftell(file);
rewind(file);
if (count > 0) {
text = (char*)malloc(sizeof(char) * (count + 1));
count = fread(text, sizeof(char), count, file);
text[count] = '\0';
}
fclose(file);
}
}
return text;
}
Shader::Shader() {}
Shader::Shader(const char *vsFile, const char *fsFile)
{
init(vsFile, fsFile);
}
void Shader::init(const char *vsFile, const char *fsFile)
{
shader_vp = glCreateShader(GL_VERTEX_SHADER);
shader_fp = glCreateShader(GL_FRAGMENT_SHADER);
const char *vsText = textFileRead(vsFile);
const char *fsText = textFileRead(fsFile);
if (vsText == NULL || fsText == NULL)
{
cerr << "Either vertex shader or fragment shader file is not found" << endl;
return;
}
glShaderSource(shader_vp, 1, &vsText, 0);
glShaderSource(shader_fp, 1, &fsText, 0);
glCompileShader(shader_vp);
glCompileShader(shader_fp);
shader_id = glCreateProgram();
glAttachShader(shader_id, shader_fp);
glAttachShader(shader_id, shader_vp);
glLinkProgram(shader_id);
}
Shader::~Shader()
{
glDetachShader(shader_id, shader_fp);
glDetachShader(shader_id, shader_vp);
glDeleteShader(shader_fp);
glDeleteShader(shader_vp);
glDeleteShader(shader_id);
}
unsigned int Shader::id()
{
return shader_id;
}
void Shader::bind()
{
glUseProgram(shader_id);
}
void Shader::unbind()
{
glUseProgram(0);
}
Main.cpp
#include "Shader.h"
#include <cstdlib>
#include <iostream>
using namespace std;
Shader shader;
void init()
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
shader.init("shader.vert", "shader.frag");
}
void resize(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
int main()
{
int running = GL_TRUE;
// init GLFW
if (!glfwInit())
exit(EXIT_FAILURE);
if (!glfwOpenWindow(300, 300, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetWindowTitle("ohhai.");
glfwSetWindowSizeCallback(resize);
/* CHECK GLEW */
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
cout << "Error: " << glewGetErrorString(err) << endl;
}
cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << endl;
if (!GLEW_ARB_vertex_buffer_object)
{
cerr << "VBO not supported\n";
exit(1);
}
init();
while (running)
{
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glShadeModel(GL_SMOOTH);
shader.bind();
glBegin(GL_TRIANGLES);
//glColor3f(0.2f, 0.5f, 0.54f);
glVertex2f(0.0f, 0.5f);
//glColor3f(0.75f, 0.8f, 0.1f);
glVertex2f(-.5f, -.5f);
//glColor3f(0.0f, 0.9f, 0.2f);
glVertex2f(0.5f, -0.5f);
glEnd();
shader.unbind();
glfwSwapBuffers();
running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam(GLFW_OPENED);
}
glfwTerminate();
exit(EXIT_SUCCESS);
}
shader.vert
void main()
{
// set the posistion of the current matrix
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
shader.frag
void main(void)
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
Again, when this compiles under g++, it goes through fine, but no triangle was shown.
I haven't found the part where you setup the camera (modelview matrix) with gluLookAt or glTranslate/glRotate/glScale. So you use the default, corresponding to a camera at the origin and looking into -z, thus your triangle (which lies in the z=0 plane) is behind the near plane.