Ok, I think I'm going crazy.
I've been developing a 3D game in OpenGL for a while now - all working well.
Then I decided to redesign it from scratch since it was turning to custard. So I set up a basic framework for rendering with OpenGL, and I can't for the life of me get the thing to render a triangle.
I have gone over every line of code about 60 times, gone through every checklist I can find on the internet, checked it against my old project which worked, and still can't see anything wrong with it.
So here is where it all starts (the main method):
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* cmdLine, int cmdShow)
{
try
{
GLContext gl(WINDOW_TITLE, 800, 600);
TestRenderable test;
while(true)
{
glClearColor(0.0f, 0.15f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
test.draw();
gl.swapBuffers();
}
}
catch(const std::string& err)
{
std::string msg = "Error: ";
msg += err;
MessageBox(NULL, msg.c_str(), WINDOW_TITLE, MB_OK | MB_ICONERROR);
}
catch(...)
{
MessageBox(NULL, "Unknown Error", WINDOW_TITLE, MB_OK | MB_ICONERROR);
}
}
And all class methods are below:
GLContext::GLContext(const std::string& title, int width, int height)
{
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
m_pWindow = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
m_glContext = SDL_GL_CreateContext(m_pWindow);
if(glewInit() != GLEW_OK)
throw(std::string("Failed to initialize GLEW"));
}
GLContext::~GLContext()
{
SDL_GL_DeleteContext(m_glContext);
SDL_DestroyWindow(m_pWindow);
}
void GLContext::swapBuffers()
{
SDL_GL_SwapWindow(m_pWindow);
}
TestRenderable::TestRenderable() : m_pShader(nullptr), m_pMesh(nullptr)
{
std::vector<std::string> attributes;
attributes.push_back("position");
attributes.push_back("color");
m_pShader = new Shader("shaders\\shader", attributes);
m_pShader->addUniform("transform");
glm::vec3 positions[] =
{
{ 10.0f, 10.0f, 0.0f },
{ 200.0f, 10.0f, 0.0f },
{ 10.0f, 100.0f, 0.0f }
};
glm::vec4 colors[] =
{
{ 0.0f, 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, 1.0f, 1.0f }
};
m_pMesh = new Mesh_PC(positions, colors, 3);
m_projection = glm::ortho<float>(0.0f, 800.0f, 600.0f, 0.0f, 0.0f, 1.0f);
}
TestRenderable::~TestRenderable()
{
if(m_pShader != nullptr)
delete m_pShader;
if(m_pMesh != nullptr)
delete m_pMesh;
}
void TestRenderable::draw()
{
m_pShader->bind();
m_pShader->setUniformMatrix("transform", m_projection);
m_pMesh->draw();
}
Mesh_PC::Mesh_PC(glm::vec3 positions[], glm::vec4 colors[], unsigned numVertices) : m_vertexCount(numVertices)
{
glGenVertexArrays(1, m_vertexArray);
glBindVertexArray(m_vertexArray[0]);
glGenBuffers(NUM_BUFFERS, m_buffers);
glBindBuffer(GL_ARRAY_BUFFER, m_buffers[POSITIONS_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(positions[0]), positions, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, m_buffers[COLORS_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(colors[0]), colors, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
}
Mesh_PC::~Mesh_PC()
{
glDeleteBuffers(NUM_BUFFERS, m_buffers);
glDeleteVertexArrays(1, m_vertexArray);
}
void Mesh_PC::draw()
{
glBindVertexArray(m_vertexArray[0]);
glDrawArrays(GL_TRIANGLES, 0, m_vertexCount);
glBindVertexArray(0);
}
Shader::Shader(const std::string& filename, const std::vector<std::string>& attributes)
{
m_program = glCreateProgram();
m_shaders[0] = createShader(loadShader(filename + ".vs"), GL_VERTEX_SHADER);
m_shaders[1] = createShader(loadShader(filename + ".fs"), GL_FRAGMENT_SHADER);
for(unsigned int i = 0; i < NUM_SHADERS; ++i)
glAttachShader(m_program, m_shaders[i]);
for(unsigned int i = 0; i < attributes.size(); ++i)
glBindAttribLocation(m_program, i, attributes[i].c_str());
glLinkProgram(m_program);
checkShaderError(m_program, GL_LINK_STATUS, true, "Program linking failed");
glValidateProgram(m_program);
checkShaderError(m_program, GL_VALIDATE_STATUS, true, "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);
}
void Shader::addUniform(const std::string& name)
{
m_uniforms.insert(std::make_pair(name, glGetUniformLocation(m_program, name.c_str())));
}
void Shader::bind()
{
glUseProgram(m_program);
}
void Shader::setUniformMatrix(const std::string& name, const glm::mat4& value)
{
bind();
auto it = m_uniforms.find(name);
if(it != m_uniforms.end())
{
glUniformMatrix4fv(it->second, 1, GL_FALSE, &value[0][0]);
}
}
void Shader::setUniformVec4(const std::string& name, const glm::vec4& value)
{
bind();
auto it = m_uniforms.find(name);
if(it != m_uniforms.end())
{
glUniform4fv(it->second, 1, &value[0]);
}
}
std::string Shader::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");
}
file.close();
}
else
{
std::string err("Unable to load shader: ");
err.append(filename);
throw(err);
}
return output;
}
void Shader::checkShaderError(GLuint shader, GLuint flag, bool isProgram, const char* 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::string err(errorMessage);
err.append(": '");
err.append(error);
err.append("'");
throw(err);
}
}
GLuint Shader::createShader(const std::string& text, GLenum shaderType)
{
GLuint shader = glCreateShader(shaderType);
if(shader == 0)
throw("Shader creation failed");
const GLchar *shaderSourceStrings[1];
GLint shaderSourceStringLengths[1];
shaderSourceStrings[0] = text.c_str();
shaderSourceStringLengths[0] = static_cast<GLint>(text.length());
glShaderSource(shader, 1, shaderSourceStrings, shaderSourceStringLengths);
glCompileShader(shader);
checkShaderError(shader, GL_COMPILE_STATUS, false, "Shader compilation failed");
return shader;
}
And by the way I am initalizing SDL - I have an object of the below type in the GLContext class:
class SDL
{
public:
SDL() { SDL_Init(SDL_INIT_VIDEO); }
~SDL() { SDL_Quit(); }
};
And my shaders:
Vertex Shader:
#version 120
attribute vec3 position;
attribute vec4 color;
varying vec4 color0;
uniform mat4 transform;
void main(void)
{
gl_Position = transform * vec4(position, 1.0);
color0 = color;
}
Fragment Shader:
#version 120
varying vec4 color0;
void main(void)
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
I know there is unused stuff in the shaders etc but this is just for testing purposes.
Can anyone help me here?
You need to call glBindBuffer before calling glVertexAttribPointer. At the moment, both attributes will be using the last buffer bound (the one with the color values).
Related
I'm making an OpenGL program. However, whenever I run it, the "vertexIn" attribute of the shader returns negative when getting its location. I've searched several stack overflow posts as well as docs and other websites. Still, I could not find any reason as to why vertexIn returns negative when OpenGL tries to get its location, given that in other working examples, it is used in the same way I use it.
Edited the post to have more code in main so it's able to be reproduced.
Main.cpp
#include <SDL.h>
#include <math.h>
#include "Header Files/Shader.h"
Shader shader;
bool isAppRunning{ true };
SDL_Window* window{ nullptr };
SDL_GLContext context{ nullptr };
GLuint VAO{ 0 };
GLuint EBO{ 0 };
GLuint vertexVBO{ 0 };
GLuint colorVBO{ 0 };
int main(int argc, char* argv[])
{
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) == -1)
{
std::cout << "SDL did not initialize properly." << std::endl;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
window = SDL_CreateWindow("OpenGL Project", 320, 180, 1280, 720, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (!window)
{
std::cout << "OpenGL Window was not created properly." << std::endl;
}
context = SDL_GL_CreateContext(window);
if (!context)
{
std::cout << "OpenGL context could not be created properly! The context is either invalid or not supported by your graphics card! Please try on Another PC!" << std::endl;
}
if (!gladLoaderLoadGL())
{
std::cout << "Error loading OpenGl extensions." << std::endl;
}
Shader::Initialize();
shader.Create("../OpenGl/Shader Files/Shader.vert", "../OpenGl/Shader Files/Shader.frag");
shader.Use();
GLfloat vertices[] = { -0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f };
GLfloat colours[] = { 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f };
GLuint indices[] = { 0, 1, 3,
3, 1, 2 };
auto vertexAttributeID = shader.GetAttributeID("vertexIn");
auto colourAttributeID = shader.GetAttributeID("colorIn");
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &vertexVBO);
glGenBuffers(1, &colorVBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(vertexAttributeID, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(vertexAttributeID);
glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(colours), colours, GL_STATIC_DRAW);
glVertexAttribPointer(colourAttributeID, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(colourAttributeID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindVertexArray(0);
while (isAppRunning)
{
SDL_Event events;
while (SDL_PollEvent(&events))
{
switch (events.type)
{
//close the window
case SDL_QUIT:
{
isAppRunning = false;
break;
}
}
}
glClearColor(191 / 255.0f, 87 / 255.0f, 205 / 255.0f, 255 / 255.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
SDL_GL_SwapWindow(window);
}
glDeleteBuffers(1, &EBO);
glDeleteBuffers(1, &colorVBO);
glDeleteBuffers(1, &vertexVBO);
glDeleteVertexArrays(1, &VAO);
glDisableVertexAttribArray(colourAttributeID);
glDisableVertexAttribArray(vertexAttributeID);
shader.Destroy();
Shader::Shutdown();
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit;
return 0;
}
Shader.cpp
#include "Header Files/Shader.h"
GLint Shader::vertexShaderID = 0;
GLint Shader::fragmentShaderID = 0;
bool Shader::Initialize()
{
vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
if (vertexShaderID == 0)
{
std::cout << "Error! Vertex Shader could not be created! This could be because of your Graphics Card not supporting modern OpenGL!" << std::endl;
return false;
}
fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
if (fragmentShaderID == 0)
{
std::cout << "Error! Fragment Shader could not be created! This could be because of your Graphics Card not supporting modern OpenGL!" << std::endl;
return false;
}
return true;
}
void Shader::Shutdown()
{
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
}
GLuint Shader::GetUniformID(const std::string& uniform) const
{
auto ID = glGetUniformLocation(programID, uniform.c_str());
assert(ID != -1);
return ID;
}
GLuint Shader::GetAttributeID(const std::string& attribute) const
{
auto ID = glGetAttribLocation(programID, attribute.c_str());
assert(ID != -1);
return ID;
}
bool Shader::Create(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename)
{
programID = glCreateProgram();
if (programID == 0)
{
std::cout << "Error! Shader Program could not be created! This could be because of your Graphics Card not supporting modern OpenGL!" << std::endl;
return false;
}
if (!CompileShaders(vertexShaderFilename))
{
return false;
}
if (!CompileShaders(fragmentShaderFilename))
{
return false;
}
if (!LinkProgram())
{
return false;
}
return true;
}
bool Shader::SendData(const std::string& uniform, GLint data)
{
glUniform1i(GetUniformID(uniform), data);
return true;
}
bool Shader::SendData(const std::string& uniform, GLuint data)
{
glUniform1ui(GetUniformID(uniform), data);
return true;
}
bool Shader::SendData(const std::string& uniform, GLfloat data)
{
glUniform1f(GetUniformID(uniform), data);
return true;
}
bool Shader::SendData(const std::string& uniform, GLfloat x, GLfloat y)
{
glUniform2f(GetUniformID(uniform), x, y);
return true;
}
bool Shader::SendData(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z)
{
glUniform3f(GetUniformID(uniform), x, y, z);
return true;
}
bool Shader::SendData(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
glUniform4f(GetUniformID(uniform), x, y, z, w);
return true;
}
void Shader::Use() const
{
glUseProgram(programID);
}
void Shader::Destroy() const
{
glDeleteProgram(programID);
}
bool Shader::LinkProgram()
{
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
glDetachShader(programID, vertexShaderID);
glDetachShader(programID, fragmentShaderID);
GLint linkResult = 0;
glGetProgramiv(programID, GL_LINK_STATUS, &linkResult);
if (linkResult == GL_FALSE)
{
GLchar error[1000];
GLsizei bufferSize = 1000;
glGetProgramInfoLog(programID, bufferSize, &bufferSize, error);
std::cout << "Error! Program did not link successfully! Error information down below: " << std::endl;
std::cout << error << std::endl;
return false;
}
std::cout << "Program Linked Successfully!" << std::endl;
return true;
}
bool Shader::CompileShaders(const std::string& filename)
{
std::ifstream file(filename);
//file.open(filename);
if (!file)
{
std::cout << "Error opening \"" + (filename)+"\"! File non - existent or unreachable! Make sure to check the spelling or the path!" << std::endl;
return false;
}
std::string line;
std::string sourceCode;
while (!file.eof())
{
std::getline(file, line);
sourceCode += line + "\n";
}
//file.close();
auto shaderID = (filename.find(".vert")) ? vertexShaderID : fragmentShaderID;
const GLchar* finalCode = reinterpret_cast<const GLchar*>(sourceCode.c_str());
//bind shader code with object
glShaderSource(shaderID, 1, &finalCode, nullptr);
//compile shader code
glCompileShader(shaderID);
GLint compileResult;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compileResult);
if (compileResult == GL_FALSE)
{
GLchar error[1000];
GLsizei bufferSize = 1000;
glGetShaderInfoLog(shaderID, bufferSize, &bufferSize, error);
std::cout << "Error! Shader did not compile successfully! Error information down below: " << std::endl;
std::cout << error << std::endl;
return false;
}
std::cout << "Shader compiled successfully!" << std::endl;
return true;
}
Shader.h
#pragma once
#include <iostream>
#include <assert.h>
#include <fstream>
#include <string>
#include "gl.h"
class Shader
{
public:
static bool Initialize();
static void Shutdown();
GLuint GetUniformID(const std::string& uniform) const;
GLuint GetAttributeID(const std::string& attribute) const;
bool Create(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename);
bool SendData(const std::string& uniform, GLint data);
bool SendData(const std::string& uniform, GLuint data);
bool SendData(const std::string& uniform, GLfloat data);
bool SendData(const std::string& uniform, GLfloat x, GLfloat y);
bool SendData(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z);
bool SendData(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void Use() const;
void Destroy() const;
private:
static GLint vertexShaderID;
static GLint fragmentShaderID;
GLuint programID{ 0 };
bool LinkProgram();
bool CompileShaders(const std::string& filename);
};
Shader.vert
#version 460
in vec3 vertexIn;
in vec3 colorIn;
out vec3 colorOut;
void main(void)
{
colorOut = colorIn;
gl_Position = vec4(vertexIn, 1.0);
}
Shader.frag
#version 460
in vec3 colorOut;
out vec4 pixelColor;
void main(void)
{
pixelColor = vec4(colorOut, 1.0);
}
I've already looked all over the internet for the past couple days and I cannot find a fix to this problem. I believe I've got the basic debugging stuff setup yet I get no errors telling me what I've done wrong. This is my first attempt at a renderer, and I'm also trying to use a OOP/DOD (Data oriented design) structure. I think the error is just something small that I am blind to, or I'm completely doing this wrong... please help if you can.
Also I'm using shaders, EBOs, VBOs, linking to a VAO (I think)
Additional information: I'm using SDL + GLAD(opengl 4.6, core)
If you need me to reply with anything else that could help you help me, let me know.
Here is my console output:
screenshot
All I see on the window: screenshot
Here are my files (that might have the error):
vertex shader
#version 460 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 ourColor;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
}
fragment shader
#version 460 core
out vec4 FragColor;
in vec3 ourColor;
void main()
{
FragColor = vec4(ourColor, 1.0f);
}
main.cpp (the window)
#include <loader.h>
using namespace testProgram;
int close(SDL_Window* window, SDL_GLContext glContext) {
IMG_Quit();
SDL_DestroyWindow(window);
SDL_GL_DeleteContext(glContext);
SDL_Quit();
return 0;
}
// Simple debugger callback, will most likely modify in the future.
static void APIENTRY openglCallbackFunction(
GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam
){
(void)source; (void)type; (void)id;
(void)severity; (void)length; (void)userParam;
fprintf(stderr, "%s\n", message);
if (severity==GL_DEBUG_SEVERITY_HIGH) {
fprintf(stderr, "Aborting...\n");
abort();
}
}
std::vector<GLfloat> vertices {
// positions // colors
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // bottom left
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // top
};
std::vector<GLuint> indices {
0, 1, 2
};
std::vector<int> vertexAttribSizes {
3
};
int main(int argc, char* argv[]) {
// Variables
bool quit = false;
// Initializations
SDL_Init(SDL_INIT_EVERYTHING);
IMG_Init(IMG_INIT_PNG);
setGLAttributes();
// Creating the window
SDL_Window* window = SDL_CreateWindow("test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, winW, winH, flags);
SDL_GLContext glContext = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, glContext);
SDL_Surface* icon = IMG_Load("images/icon.png");
setIcon(window, icon);
// Setting up OpenGL
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) {
printf("Failed to initialize GLAD\n");
return -1;
}
glViewport(0, 0, winW, winH);
// Enable the debug callback
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(openglCallbackFunction, nullptr);
glDebugMessageControl
(
GL_DONT_CARE,
GL_DONT_CARE,
GL_DONT_CARE,
0, NULL, true
);
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
Renderer::Queue queue;
Renderer::Shader shader;
Renderer::Object object;
shader.Update("CUT OUT THE DIRECTORY FOR THIS POST (because it doesn't matter)", "CUT OUT THE DIRECTORY FOR THIS POST (because it doesn't matter)");
object.Update(vertices, indices, shader.id, "triangle", vertexAttribSizes);
object.Attach(queue);
while(!quit) {
SDL_Event event;
mouseX = event.motion.x;
mouseY = event.motion.y;
while (SDL_PollEvent(&event) != 0) {
inputCollection(event, quit);
}
SDL_SetWindowHitTest(window, hitCallback, 0);
glClearColor(0.085f, 0.085f, 0.085f, 0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
queue.Render();
SDL_GL_SwapWindow(window);
}
// Closes all processes
object.Detach(queue);
close(window, glContext);
return 0;
}
renderer.h (it is included in loader.h, which is included in main.cpp. loader.h I believe doesn't contain the issue, so I dont want to pollute this post with even more code haha)
// Includes
#include <glad/glad.h>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <ctype.h>
#include <fstream>
#include <cstring>
#include <sstream>
// Renderer
namespace Renderer {
class Shader {
private:
// Read the shader's source code.
std::string readFile(const char* _path);
// Check the shader.
bool checkShader(GLuint &_shader);
// Check the program.
bool checkProgram(GLuint &_program);
public:
const char* vertexPath;
const char* fragmentPath;
GLuint id;
void Update(const char* _vertexPath, const char* _fragmentPath); // Update the shader's parameters.
void Use() { glUseProgram(id); } // Use the shader.
};
class Queue {
public:
GLuint VAO;
void listObjects(); // List all objects in the queue (BY NAME, INDEX IS THE ID FOR ALL VALUES/PARAMETERS)
GLuint getObject(std::string objName); // Grab an object from the queue (BY NAME, INDEX IS THE ID FOR ALL VALUES/PARAMETERS) [Returns the id of the object]
bool findObject(std::string objName); // Returns true or false if the object is found.
void Render(); // Render all objects in the queue. (Sets VAOs)
std::vector<std::vector<GLfloat>> vertices;
std::vector<std::vector<int>> indices;
std::vector<std::vector<int>> vertexAttribs;
std::vector<int> shaderProgramIDs;
std::vector<std::string> names;
};
class Object {
public:
GLuint VBO, EBO;
std::vector<GLfloat> vertices;
std::vector<int> indices;
std::vector<int> vertexAttribSizes; // This is the sizes of the vertex attributes, not the values.
GLuint shaderProgramID;
std::string name;
// Set the object's parameters.
void Update(
std::vector<GLfloat> _vertices,
std::vector<GLuint> _indices,
int _shaderProgramID,
std::string _name,
std::vector<int> _vertexAttribSizes
);
void Attach(Queue &queue);
void Detach(Queue &queue);
};
};
renderer.cpp
#include <renderer.h>
using namespace Renderer;
// List all objects in the queue.
void Queue::listObjects() {
for (auto name : names) {
std::cout << name << std::endl;
}
}
// Returns true or false if the object is found.
bool Queue::findObject(std::string objName) {
auto index = std::find(names.begin(), names.end(), objName);
if (index != names.end()) {
return true;
} else {
return false;
}
}
// Returns the object id.
GLuint Queue::getObject(std::string objName) {
auto index = std::find(names.begin(), names.end(), objName);
if (findObject(objName)) {
return index - names.begin();
} else {
return -1;
}
}
// Renders all objects linked to the current queue.
void Queue::Render() {
for (int i = 0; i < names.size(); i++) {
glUseProgram(shaderProgramIDs[i]);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, indices[i].size(), GL_UNSIGNED_INT, 0);
}
}
std::string Shader::readFile(const char* _path) {
std::string content;
std::ifstream fileStream(_path, std::ios::in);
if (!fileStream.is_open()) {
std::cerr << "Could not read file " << _path << ". File does not exist." << std::endl;
return "";
}
std::string line = "";
while (!fileStream.eof()) {
std::getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
bool Shader::checkShader(GLuint &_shader) {
GLint success;
glGetShaderiv(_shader, GL_COMPILE_STATUS, &success);
if(!success) {
GLint maxLength = 0;
glGetShaderiv(_shader, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> errorLog(maxLength);
glGetShaderInfoLog(_shader, maxLength, &maxLength, &errorLog[0]);
std::cout << "Shader compilation failed: " << std::endl;
std::cout << &errorLog[0] << std::endl;
return false;
}
return true;
}
bool Shader::checkProgram(GLuint &_program) {
GLint success;
glGetProgramiv(_program, GL_LINK_STATUS, &success);
if(!success) {
GLint maxLength = 0;
glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> errorLog(maxLength);
glGetProgramInfoLog(_program, maxLength, &maxLength, &errorLog[0]);
std::cout << "Program linking failed: " << std::endl;
std::cout << &errorLog[0] << std::endl;
return false;
}
return true;
}
void Shader::Update(
const char* _vertexPath,
const char* _fragmentPath
){
GLuint vertex, fragment;
vertex = glCreateShader(GL_VERTEX_SHADER);
fragment = glCreateShader(GL_FRAGMENT_SHADER);
vertexPath = _vertexPath;
fragmentPath = _fragmentPath;
std::string vertexString = readFile(_vertexPath);
std::string fragmentString = readFile(_fragmentPath);
const char *vertexSource = vertexString.c_str();
const char *fragmentSource = fragmentString.c_str();
glShaderSource(vertex, 1, &vertexSource, NULL);
glCompileShader(vertex);
checkShader(vertex);
glShaderSource(fragment, 1, &fragmentSource, NULL);
glCompileShader(fragment);
checkShader(fragment);
this->id = glCreateProgram();
glAttachShader(this->id, vertex);
glAttachShader(this->id, fragment);
glLinkProgram(this->id);
checkProgram(this->id);
glDeleteShader(vertex);
glDeleteShader(fragment);
}
void Object::Attach(Queue &queue) {
queue.names.push_back(this->name);
GLuint id = queue.getObject(this->name);
queue.shaderProgramIDs.insert(queue.shaderProgramIDs.begin()+id, this->shaderProgramID);
queue.vertices.insert(queue.vertices.begin()+id, this->vertices);
queue.indices.insert(queue.indices.begin()+id, this->indices);
queue.vertexAttribs.insert(queue.vertexAttribs.begin()+id, this->vertexAttribSizes);
glGenBuffers(1, &this->VBO);
glGenBuffers(1, &this->EBO);
glGenVertexArrays(1, &queue.VAO);
glBindVertexArray(queue.VAO);
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(this->vertices), &this->vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(this->indices), &this->indices, GL_STATIC_DRAW);
int stride = 3;
for (int i = 0; i < this->vertexAttribSizes.size(); i++) {
stride+=this->vertexAttribSizes[i];
}
// Positions
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Other attributes
int totalSize = 3;
for (int i = 0; i < this->vertexAttribSizes.size(); i++) {
glVertexAttribPointer(i+1, this->vertexAttribSizes[i], GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)(totalSize * sizeof(float)));
glEnableVertexAttribArray(i+1);
totalSize+=this->vertexAttribSizes[i];
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Object::Detach(Queue &queue) {
GLuint id = queue.getObject(this->name);
queue.names.erase(std::remove(queue.names.begin(), queue.names.end(), this->name), queue.names.end());
queue.vertices.erase(queue.vertices.begin()+id, queue.vertices.begin()+id+this->vertices.size());
queue.indices.erase(queue.indices.begin()+id, queue.indices.begin()+id+this->indices.size());
queue.vertexAttribs.erase(queue.vertexAttribs.begin()+id, queue.vertexAttribs.begin()+id+this->vertexAttribSizes.size());
glDeleteBuffers(1, &this->VBO);
glDeleteBuffers(1, &this->EBO);
}
void Object::Update(
std::vector<GLfloat> _vertices,
std::vector<GLuint> _indices,
int _shaderProgramID,
std::string _name,
std::vector<int> _vertexAttribSizes
){
// TODO: Clear all vectors, also detach and reattach automatically.
for (int i = 0; i < _vertices.size(); i++) {
vertices.push_back(_vertices[i]);
}
for (int i = 0; i < _indices.size(); i++) {
indices.push_back(_indices[i]);
}
for (int i = 0; i < _vertexAttribSizes.size(); i++) {
vertexAttribSizes.push_back(_vertexAttribSizes[i]);
}
shaderProgramID = _shaderProgramID;
name = _name;
}
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(this->vertices), &this->vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(this->indices), &this->indices, GL_STATIC_DRAW);
this->vertices is a std::vector. You are uploading raw pointer values where there should be actual data in the buffer.
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * this->vertices.size(), this->vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * this->indices.size(), this->indices.data(), GL_STATIC_DRAW);
I am currently following along on an openGL course and when organising my code into classes, I am getting an access violation error along with this on the console terminal.
SDL window creation failed! (I programmed it to output that when the window cannot be created)
Here's my code:
main.cpp
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <vector>
#include <GL/glew.h>
#define SDL_MAIN_HANDLED
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Window.h"
#include "Mesh.h"
#include "Shader.h"
//Window dimensions
const GLint width = 800, height = 600;
const float toRadians = 3.14159265f / 180.0f;
Window mainWindow;
std::vector<Mesh*> meshList;
std::vector<Shader*> shaderList;
bool direction = true;
float triOffSet = 0.0f;
float triMaxOffSet = 0.7f;
float triIncrement = 0.010f;
float curAngle = 0.0f;
bool sizeDirection = true;
float curSize = 0.4f;
float maxSize = 0.8f;
float minSize = 0.1f;
//Vertex shader
static const char* vShader = "Shaders/shader.vert";
//Fragment shader
static const char* fShader = "Shaders/shader.frag";
void CreateObjects() {
unsigned int indices[] = {
0, 3, 1,
1, 3, 2,
2, 3, 0,
0, 1, 2
};
GLfloat vertices[] = {
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 1.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
Mesh* obj1 = new Mesh();
obj1->CreateMesh(vertices, indices, 12, 12);
meshList.push_back(obj1);
Mesh* obj2 = new Mesh();
obj2->CreateMesh(vertices, indices, 12, 12);
meshList.push_back(obj2);
Mesh* obj3 = new Mesh();
obj3->CreateMesh(vertices, indices, 12, 12);
meshList.push_back(obj3);
}
void CreateShaders() {
Shader *shader1 = new Shader();
shader1->CreateFromFiles(vShader, fShader);
shaderList.push_back(shader1);
}
int main() {
mainWindow = Window(800, 600);
mainWindow.Initialise();
CreateObjects();
CreateShaders();
GLuint uniformProjection = 0, uniformModel = 0;
glm::mat4 projection = glm::perspective(45.0f, (GLfloat)mainWindow.getBufferWidth() / mainWindow.getBufferHeight(), 0.1f, 100.0f);
SDL_Event windowEvent;
while (true) {
if (SDL_PollEvent(&windowEvent)) {
if (windowEvent.type == SDL_QUIT) {
break;
}
}
if (direction) {
triOffSet += triIncrement;
}
else {
triOffSet -= triIncrement;
}
if (abs(triOffSet) >= triMaxOffSet) {
direction = !direction;
}
curAngle += 1.0f;
if (curAngle >= 360) {
curAngle -= 360;
}
if (direction) {
curSize += 0.001f;
}
else {
curSize -= 0.001f;
}
if (curSize >= maxSize || curSize <= minSize) {
sizeDirection = !sizeDirection;
}
//Clear window
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaderList[0]->UseShader();
uniformModel = shaderList[0]->GetModelLocation();
uniformProjection = shaderList[0]->GetProjectionLocation();
glm::mat4 model(1.0f);
model = glm::translate(model, glm::vec3(0.0f, 0.0f, -2.5f));
model = glm::rotate(model, curAngle * toRadians, glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(uniformProjection, 1, GL_FALSE, glm::value_ptr(projection));
meshList[0]->RenderMesh();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(-triOffSet, 1.0f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
meshList[1]->RenderMesh();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(triOffSet, -1.0f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
meshList[2]->RenderMesh();
glUseProgram(0);
mainWindow.swapWindows();
}
return 0;
}
Mesh.h
#pragma once
#include <GL/glew.h>
class Mesh
{
private:
GLuint VAO, VBO, IBO;
GLsizei indexCount;
public:
Mesh();
void CreateMesh(GLfloat *vertices, unsigned int *indices, unsigned int numOfVertices, unsigned int numOfIndices);
void RenderMesh();
void ClearMesh();
~Mesh();
};
Mesh.cpp
#include "Mesh.h"
#include <GL/glew.h>
Mesh::Mesh() {
VAO = 0;
VBO = 0;
IBO = 0;
indexCount = 0;
}
void Mesh::CreateMesh(GLfloat* vertices, unsigned int* indices, unsigned int numOfVertices, unsigned int numOfIndices) {
indexCount = numOfIndices;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * numOfIndices, indices, GL_STATIC_DRAW);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * numOfVertices, vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void Mesh::RenderMesh() {
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Mesh::ClearMesh() {
if (IBO != 0) {
glDeleteBuffers(1, &IBO);
IBO = 0;
}
if (VBO != 0) {
glDeleteBuffers(1, &VBO);
VBO = 0;
}
if (VAO != 0) {
glDeleteBuffers(1, &VAO);
VAO = 0;
}
indexCount = 0;
}
Mesh::~Mesh() {
ClearMesh();
}
Shader.h
#pragma once
#include <stdio.h>
#include <string>
#include <iostream>
#include <fstream>
#include <GL/glew.h>
class Shader
{
private:
GLuint shaderID, uniformProjection, uniformModel;
void CompileShader(const char* vertexCode, const char* fragmentCode);
void AddShader(GLuint theProgram, const char* shaderCode, GLenum shaderType);
public:
Shader();
void CreateFromString(const char* vertexCode, const char* fragmentCode);
void CreateFromFiles(const char* vertexLocation, const char* fragmentLocation);
std::string ReadFile(const char* fileLocation);
GLuint GetProjectionLocation();
GLuint GetModelLocation();
void UseShader();
void ClearShader();
~Shader();
};
Shader.cpp
#include "Shader.h"
Shader::Shader()
{
shaderID = 0;
uniformModel = 0;
uniformProjection = 0;
}
void Shader::CreateFromString(const char* vertexCode, const char* fragmentCode)
{
CompileShader(vertexCode, fragmentCode);
}
void Shader::CreateFromFiles(const char* vertexLocation, const char* fragmentLocation)
{
std::string vertexString = ReadFile(vertexLocation);
std::string fragmentString = ReadFile(fragmentLocation);
const char* vertexCode = vertexString.c_str();
const char* fragmentCode = fragmentString.c_str();
CompileShader(vertexCode, fragmentCode);
}
std::string Shader::ReadFile(const char* fileLocation)
{
std::string content;
std::ifstream fileStream(fileLocation, std::ios::in);
if (!fileStream.is_open()) {
printf("Failed to read %s! File doesn't exist.", fileLocation);
return "";
}
std::string line = "";
while (!fileStream.eof())
{
std::getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
void Shader::CompileShader(const char* vertexCode, const char* fragmentCode)
{
shaderID = glCreateProgram();
if (!shaderID)
{
printf("Error creating shader program!\n");
return;
}
AddShader(shaderID, vertexCode, GL_VERTEX_SHADER);
AddShader(shaderID, fragmentCode, GL_FRAGMENT_SHADER);
GLint result = 0;
GLchar eLog[1024] = { 0 };
glLinkProgram(shaderID);
glGetProgramiv(shaderID, GL_LINK_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(shaderID, sizeof(eLog), NULL, eLog);
printf("Error linking program: '%s'\n", eLog);
return;
}
glValidateProgram(shaderID);
glGetProgramiv(shaderID, GL_VALIDATE_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(shaderID, sizeof(eLog), NULL, eLog);
printf("Error validating program: '%s'\n", eLog);
return;
}
uniformProjection = glGetUniformLocation(shaderID, "projection");
uniformModel = glGetUniformLocation(shaderID, "model");
}
GLuint Shader::GetProjectionLocation()
{
return uniformProjection;
}
GLuint Shader::GetModelLocation()
{
return uniformModel;
}
void Shader::UseShader()
{
glUseProgram(shaderID);
}
void Shader::ClearShader()
{
if (shaderID != 0)
{
glDeleteProgram(shaderID);
shaderID = 0;
}
uniformModel = 0;
uniformProjection = 0;
}
void Shader::AddShader(GLuint theProgram, const char* shaderCode, GLenum shaderType)
{
GLuint theShader = glCreateShader(shaderType);
const GLchar* theCode[1];
theCode[0] = shaderCode;
GLint codeLength[1];
codeLength[0] = strlen(shaderCode);
glShaderSource(theShader, 1, theCode, codeLength);
glCompileShader(theShader);
GLint result = 0;
GLchar eLog[1024] = { 0 };
glGetShaderiv(theShader, GL_COMPILE_STATUS, &result);
if (!result)
{
glGetShaderInfoLog(theShader, sizeof(eLog), NULL, eLog);
printf("Error compiling the %d shader: '%s'\n", shaderType, eLog);
return;
}
glAttachShader(theProgram, theShader);
}
Shader::~Shader()
{
ClearShader();
}
Window.h
#pragma once
#include <stdio.h>
#include <GL/glew.h>
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
class Window
{
private:
SDL_Window* mainWindow;
SDL_Event windowEvent;
GLint width, height;
public:
Window();
Window(GLint windowWidth, GLint windowHeight);
int Initialise();
GLint getBufferWidth() { return width; }
GLint getBufferHeight() { return height; }
void swapWindows() { SDL_GL_SwapWindow(mainWindow); }
~Window();
};
Window.cpp
#include "Window.h"
Window::Window() {
width = 800;
height = 600;
}
Window::Window(GLint width, GLint height) {
width = width;
height = height;
}
int Window::Initialise() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL initialisation failed\n");
SDL_Quit();
return 1;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
mainWindow = SDL_CreateWindow("Test game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
if (!mainWindow) {
printf("SDL window creation failed!\n");
SDL_Quit();
return 1;
}
//Set context for GLEW to use
SDL_GLContext context = SDL_GL_CreateContext(mainWindow);
//Allow modern extension features
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
printf("GLEW initialization failed!\n");
SDL_DestroyWindow(mainWindow);
SDL_Quit();
return 1;
}
glEnable(GL_DEPTH_TEST);
//Setup viewport size
glViewport(0, 0, 800, 600);
}
Window::~Window() {
SDL_DestroyWindow(mainWindow);
SDL_Quit();
}
I've heard that a solution to this could be to put glewExperimental = GL_True before glewInit() but that hasn't worked because those two lines are in Window.cpp and I don't know how that could affect Mesh.cpp.
The debug reads this at the bottom:
Exception thrown at 0x00000000 in OpenGLCourseApp.exe: 0xC0000005: Access violation executing location 0x00000000.
Call stack
Your Window constructor does not actually initialize the fields of the Window object, which means you call SDL_CreateWindow with random width and height.
Use an initializer list instead, which does not suffer this problem:
Window::Window(int width, int height)
: width(width), height(height) {
}
Once you get past that, keep in mind that the statement
mainWindow = Window(800, 600);
will create a temporary Window object, assign it to mainWindow, and then immediately destroy it!
I suggest you change the type of mainWindow to Window* (or better yet a std::unique_ptr<Window>),
and change that line to
mainWindow = new Window(800, 600);
or
mainWindow = std::make_unique<Window>(800, 600);
I'm trying to learn OpenGL with this tutorial I tried to do the coding in OS X Mavericks but the result is just a black window. I believe there should be a white triangle but don't know what I'm missing.
Here's the code
glut_utils.h
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
void init();
void display();
void reshape (int w, int h);
void keyboard(uchar key, int x, int y);
glut_utils.cpp
#include <string>
#include <vector>
#include "glut_utils.h"
GLuint CreateShader(GLenum eShaderType, const std::string &strShaderFile)
{
GLuint shader = glCreateShader(eShaderType);
const char *strFileData = strShaderFile.c_str();
glShaderSource(shader, 1, &strFileData, NULL);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE)
{
GLint infoLogLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *strInfoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);
const char *strShaderType = NULL;
switch(eShaderType)
{
case GL_VERTEX_SHADER: strShaderType = "vertex"; break;
case GL_GEOMETRY_SHADER_EXT: strShaderType = "geometry"; break;
case GL_FRAGMENT_SHADER: strShaderType = "fragment"; break;
}
fprintf(stderr, "Compile failure in %s shader:\n%s\n", strShaderType, strInfoLog);
delete[] strInfoLog;
}
return shader;
}
GLuint CreateProgram(const std::vector<GLuint> &shaderList)
{
GLuint program = glCreateProgram();
for(size_t iLoop = 0; iLoop < shaderList.size(); iLoop++)
glAttachShader(program, shaderList[iLoop]);
glLinkProgram(program);
GLint status;
glGetProgramiv (program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
GLint infoLogLength;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *strInfoLog = new GLchar[infoLogLength + 1];
glGetProgramInfoLog(program, infoLogLength, NULL, strInfoLog);
fprintf(stderr, "Linker failure: %s\n", strInfoLog);
delete[] strInfoLog;
}
for(size_t iLoop = 0; iLoop < shaderList.size(); iLoop++)
glDetachShader(program, shaderList[iLoop]);
return program;
}
GLuint theProgram;
const std::string strVertexShader(
"#version 330\n"
"layout(location = 0) in vec4 position;\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
"}\n"
);
const std::string strFragmentShader(
"#version 330\n"
"out vec4 outputColor;\n"
"void main()\n"
"{\n"
" outputColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n"
"}\n"
);
void InitializeProgram()
{
std::vector<GLuint> shaderList;
shaderList.push_back(CreateShader(GL_VERTEX_SHADER, strVertexShader));
shaderList.push_back(CreateShader(GL_FRAGMENT_SHADER, strFragmentShader));
theProgram = CreateProgram(shaderList);
std::for_each(shaderList.begin(), shaderList.end(), glDeleteShader);
}
const float vertexPositions[] = {
0.75f, 0.75f, 0.0f, 1.0f,
0.75f, -0.75f, 0.0f, 1.0f,
-0.75f, -0.75f, 0.0f, 1.0f,
};
GLuint positionBufferObject;
GLuint vao;
void InitializeVertexBuffer()
{
glGenBuffers(1, &positionBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
void init()
{
InitializeProgram();
InitializeVertexBuffer();
glGenVertexArraysAPPLE(1, &vao);
glBindVertexArrayAPPLE(vao);
}
void display()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(theProgram);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glUseProgram(0);
glutSwapBuffers();
}
void reshape (int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glLoadIdentity();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(EXIT_SUCCESS);
return;
}
}
Tut01.cpp
#include "common.h"
#include "glut_utils.h"
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_3_2_CORE_PROFILE | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Hello Triangle");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
Try including the core profile header first:
#include <OpenGL/gl3.h>
#include <GLUT/glut.h>
Remove the APPLE suffix from glGenVertexArraysAPPLE and glBindVertexArrayAPPLE - they shouldn't be defined with the gl3.h header anyway.
OpenGl seems to be ignoring my shaders, not scalling, or changing the color.
Screenshot
I dont get any errors, throught the errorhandler either.
I have been at it for hours, what am i doing wrong?
im using freeglut and glew(dont know it that matters).
Im doing this with:
OpenGl 4.3
Radeon HD 6800
Windows 8.1 Enterprise
Vertex Shader:
#version 120
attribute vec3 position;
void main()
{
gl_Position = vec4(position*2.0,1.0);
}
Fragment Shader:
#version 120
void main()
{
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
Shader.cpp
#include "Shader.h"
#include <fstream>
#include "ErrorHandler.h"
namespace{
std::string VERTEX_SHADER_EXTENSION = ".vs";
std::string FRAGMENT_SHADER_EXTENSION = ".fs";
}
Shader::Shader(const std::string& fileName)
{
m_program = glCreateProgram();
m_shaders[0] = CreateShader(LoadShader(fileName + VERTEX_SHADER_EXTENSION), GL_VERTEX_SHADER);
m_shaders[1] = CreateShader(LoadShader(fileName + FRAGMENT_SHADER_EXTENSION), GL_FRAGMENT_SHADER);
for (unsigned int i = 0; i < NUM_SHADERS; i++)
{
glAttachShader(m_program, m_shaders[i]);
}
glBindAttribLocation(m_program, 0, "position");
glLinkProgram(m_program);
CheckShaderError(m_program, GL_LINK_STATUS, true, "Program linking failed: ");
glValidateProgram(m_program);
CheckShaderError(m_program, GL_VALIDATE_STATUS, true, "Program is invalid: ");
}
void Shader::Bind()
{
glUseProgram(m_program);
}
Shader::~Shader()
{
for (unsigned int i = 0; i < NUM_SHADERS; i++)
{
glDetachShader(m_program, m_shaders[i]);
glDeleteShader(m_shaders[i]);
}
glDeleteProgram(m_program);
}
GLuint Shader::CreateShader(const std::string& text, GLenum shaderType)
{
GLuint shader = glCreateShader(shaderType);
if (shader == 0)
{
ErrorHandler::LogError("Error: Shader creation failed!");
}
const GLchar* shaderSourceStrings[1];
GLint shaderSourceStringLength[1];
shaderSourceStringLength[0] = text.length();
shaderSourceStrings[0] = text.c_str();
glShaderSource(shader, 1, shaderSourceStrings, shaderSourceStringLength);
glCompileShader(shader);
CheckShaderError(shader, GL_COMPILE_STATUS, false, "Shader compilation failed: ");
return shader;
}
std::string Shader::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
{
ErrorHandler::LogError("Unable to load shader: " + fileName);
}
return output;
}
void Shader::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);
ErrorHandler::LogError(errorMessage + ": " + error + "'");
}
}
Game Loop:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Shaders[0].Bind();
Meshes[0].Draw();
glutSwapBuffers();
Mesh.cpp:
#include "Mesh.h"
Mesh::Mesh(Vertex* vertices, unsigned int numVertices)
{
m_drawCount = numVertices;
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(*m_vertexArrayBuffers);
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER,m_vertexArrayBuffers[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(vertices[0]), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
}
Mesh::~Mesh()
{
glDeleteVertexArrays(1, &m_vertexArrayObject);
}
void Mesh::Draw()
{
glBindVertexArray(m_vertexArrayObject);
glDrawArrays(GL_TRIANGLES, 0, m_drawCount);
glBindVertexArray(0);
}
main and init function:
int init(int argc, char** argv)
{
//init glut
glutInit(&argc, argv);
Display display(800, 600, "OpenGL Playground");
//init glew
GLenum err = glewInit();
if (GLEW_OK != err){
ErrorHandler::LogError(std::string(reinterpret_cast<const char*>(glewGetErrorString(err))));
return 1;
}
//bind functions
glutDisplayFunc(draw);//Drawloop
return 0;
}
int main(int argc, char** argv)
{
int i = init(argc, argv);
Vertex verts[3];
verts[0] = Vertex(Vector3f(-0.5f, -0.5f, 0.0f));
verts[1] = Vertex(Vector3f(0.0f, 0.5f, 0.0f));
verts[2] = Vertex(Vector3f(0.5f, -0.5f, 0.0f));
Meshes.push_back(Mesh(verts, (sizeof(verts)/sizeof(verts[0]))));
Shaders.push_back(Shader("./res/basicShader"));
if (i == 0)
{
glutMainLoop();
}
else
{
cin.ignore(1);
return 1;
}
return 0;
}
Display.cpp:
#include "Display.h"
#include <GL\glut.h>
#include <GL\freeglut.h>
#include <iostream>
#include "ErrorHandler.h"
Display::Display(int width, int height, const std::string& title)
{
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA | GLUT_MULTISAMPLE);
glutInitWindowSize(width, height);
glutInitWindowPosition(100, 100);
glutCreateWindow(title.c_str());
glClearColor(0.0f, 0.2f, 0.2f, 1.0f);
}
Display::~Display()
{
}
This code in your Mesh constructor does not look right:
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(*m_vertexArrayBuffers);
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
You probably meant to pass m_vertexArrayObject as the argument to glBindVertexArray().