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.
Related
Simple and short question but I don't know why it is not working. When I call glViewport in the window frame buffer callback nothing changes. Error code is 1282 (0x502). I already googled and found no helpful article. Some said I should use glScissor in addition but does not work either.
Here an MCVE with an oscillating quad for visualization:
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "glm/vec3.hpp"
#include <thread>
#include <iostream>
#include <vector>
#include <chrono>
#include <Windows.h>
#include <wingdi.h>
int createShaders() {
const char* vertex = R"(
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
uniform float scale;
void main() {
gl_Position = vec4(vertexPosition_modelspace, 1.0) * vec4(vec3(scale), 1.0f);
}
)";
const char* fragment = R"(
#version 330 core
void main() {
gl_FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
}
)";
int vertexID, fragmentID, pid;
vertexID = glCreateShader(GL_VERTEX_SHADER);
const GLchar* source = (const GLchar*)vertex;
glShaderSource(vertexID, 1, &source, 0);
glCompileShader(vertexID);
int isCompiled = 0;
glGetShaderiv(vertexID, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
int maxLength = 0;
glGetShaderiv(vertexID, GL_INFO_LOG_LENGTH, &maxLength);
char* infoLog = new char[maxLength];
glGetShaderInfoLog(vertexID, maxLength, &maxLength, infoLog);
std::cout << infoLog << std::endl;
glDeleteShader(vertexID);
return 0;
}
fragmentID = glCreateShader(GL_FRAGMENT_SHADER);
source = (const GLchar*)fragment;
glShaderSource(fragmentID, 1, &source, 0);
glCompileShader(fragmentID);
glGetShaderiv(fragmentID, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
int maxLength = 0;
glGetShaderiv(fragmentID, GL_INFO_LOG_LENGTH, &maxLength);
char* infoLog = new char[maxLength];
glGetShaderInfoLog(fragmentID, maxLength, &maxLength, infoLog);
std::cout << infoLog << std::endl;
glDeleteShader(fragmentID);
glDeleteShader(vertexID);
return 0;
}
pid = glCreateProgram();
glAttachShader(pid, vertexID);
glAttachShader(pid, fragmentID);
glLinkProgram(pid);
int isLinked = 0;
glGetProgramiv(pid, GL_LINK_STATUS, (int*)&isLinked);
if (isLinked == GL_FALSE)
{
int maxLength = 0;
glGetProgramiv(pid, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> infoLog(maxLength);
glGetProgramInfoLog(pid, maxLength, &maxLength, &infoLog[0]);
glDeleteProgram(pid);
glDeleteShader(vertexID);
glDeleteShader(fragmentID);
return 0;
}
glDetachShader(pid, vertexID);
glDetachShader(pid, fragmentID);
return pid;
}
unsigned int createVertexArray() {
std::vector<glm::vec3> vertices = {
glm::vec3(0.5f, 0.5f, 0.0f),
glm::vec3(0.5f, -0.5f, 0.0f),
glm::vec3(-0.5f, -0.5f, 0.0f),
glm::vec3(-0.5f, 0.5f, 0.0f)
};
unsigned int arrayID, id;
glGenVertexArrays(1, &arrayID);
glBindVertexArray(arrayID);
glGenBuffers(1, &id);
glBindBuffer(GL_ARRAY_BUFFER, id);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
return arrayID;
}
int main() {
if (!glfwInit())
return 1;
GLFWwindow* window = glfwCreateWindow(960, 520, "MCVE", NULL, NULL);
glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
});
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
return 1;
wglMakeCurrent(NULL, NULL);
std::thread mainLoopThread([window]() {
glfwMakeContextCurrent(window);
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
int shaderID = createShaders();
int vertexID = createVertexArray();
while (!glfwWindowShouldClose(window)) {
std::chrono::steady_clock::time_point current = std::chrono::steady_clock::now();
std::chrono::microseconds time = std::chrono::duration_cast<std::chrono::microseconds>(current - start);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderID);
float s = sin(time.count() / 1000000.0f * 2.0f);
glUniform1f(glGetUniformLocation(shaderID, "scale"), s);
glBindVertexArray(vertexID);
glDrawArrays(GL_QUADS, 0, 4);
glfwSwapBuffers(window);
}
});
while (!glfwWindowShouldClose(window))
glfwWaitEvents();
mainLoopThread.join();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
You try to call a OpenGL instruction without a current OpenGL Context.
The callback is executed in the main thread. However the OpenGL Context is not current in the main thread. The OpenGL context is current in the mainLoopThread thread.
Set a state in the callback function (e.g. std::atomic<bool>) and invoke glViewport in the mainLoopThread thread, once the state is set.
I tried to use my own vertex shader and fragment shader in my OpenGL project.
Both the program itself and the shader programs were compiled and linked successfully but neither the vertex shader nor the fragment shader worked. I managed to make some changes in the shader code but nothing happened, and the two shaders still refused to take part in the rendering process.
Below's my code:
#include<GL\glew.h>
#include<GL\freeglut.h>
#include<iostream>
#include<fstream>
#include<string>
#include<assert.h>
using namespace std;
static GLuint VBO_handle = 0;
static GLfloat val = 1.5f;
static GLuint Unif_handle = 0;
static GLuint Program_handle = 0;
static GLuint Shader_handle = 0;
static GLuint Shader_handle2 = 0;
void init()
{
glGenBuffers(1, &VBO_handle);
glBindBuffer(GL_ARRAY_BUFFER, VBO_handle);
GLfloat vertices[] = { 0.0f, 0.8f, 0.0f, -0.8f, -0.8f, 0.0f, 0.8f, -0.8f, 0.0f };
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
}
void Rendering();
void callback_register()
{
glutDisplayFunc(Rendering);
glutIdleFunc(Rendering);
}
void Rendering()
{
glClear(GL_COLOR_BUFFER_BIT);
glUniform1f(Unif_handle, val);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glutSwapBuffers();
}
void ShaderReading()
{
Program_handle = glCreateProgram();
Shader_handle = glCreateShader(GL_VERTEX_SHADER);
std::fstream fin("vertex.vert", std::ios::in);
std::string temp;
while (fin.good())
{
string templine;
getline(fin, templine);
temp += templine;
temp.push_back('\n');
}
fin.close();
const GLchar* p[1];
p[0] = temp.c_str();
GLint Lengths[1];
Lengths[0] = temp.size();
glShaderSource(Shader_handle, 1, p, Lengths);
glCompileShader(Shader_handle);
GLint success;
glGetShaderiv(Shader_handle, GL_COMPILE_STATUS, &success);
if (!success) {
GLchar InfoLog[1024];
glGetShaderInfoLog(Shader_handle, 1024, NULL, InfoLog);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", GL_VERTEX_SHADER, InfoLog);
exit(1);
}
glAttachShader(Program_handle, Shader_handle);
GLint Success = 0;
GLchar ErrorLog[1024] = { 0 };
Shader_handle2 = glCreateShader(GL_FRAGMENT_SHADER);
fin.open("fragment.frag", std::ios::in);
temp.clear();
while (fin.good())
{
string templine;
getline(fin, templine);
temp += templine;
temp.push_back('\n');
}
fin.close();
p[0] = temp.c_str();
Lengths[0] = temp.size();
glShaderSource(Shader_handle2, 1, p, Lengths);
glCompileShader(Shader_handle2);
glGetShaderiv(Shader_handle2, GL_COMPILE_STATUS, &success);
if (!success) {
GLchar InfoLog[1024];
glGetShaderInfoLog(Shader_handle2, 1024, NULL, InfoLog);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", GL_VERTEX_SHADER, InfoLog);
exit(1);
}
glAttachShader(Program_handle, Shader_handle2);
Success = 0;
glLinkProgram(Program_handle);
glGetProgramiv(Program_handle, GL_LINK_STATUS, &Success);
if (Success == 0) {
glGetProgramInfoLog(Program_handle, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
exit(1);
}
glValidateProgram(Program_handle);
glGetProgramiv(Program_handle, GL_VALIDATE_STATUS, &Success);
if (!Success) {
glGetProgramInfoLog(Program_handle, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
exit(1);
}
glUseProgram(Shader_handle);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(600, 600);
glutInitWindowPosition(100, 100);
glutCreateWindow("6666");
callback_register();
GLenum res = glewInit();
if (res != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
return 1;
}
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
init();
ShaderReading();
glutMainLoop();
return 0;
}
Here's the shader programs below, very simple indeed:(
vertex shader:
#version 330
layout (location = 0) in vec3 Position;
uniform float gScale;
void main()
{
gl_Position = vec4(gScale*Position.x, Position.y, Position.z, 1.0);
}
fragment shader:
#version 330
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
You have some small mistake here:
glUseProgram(Shader_handle);
This actually should be Program_handle. The above code should just produce some GL error and have no effect. Since you are in a compatibility/legacy profile, you will draw with the fixed function pipeline, and attribute 0 will alias the vertex positions. The default color will be white, so that is why you see a white triangle.
As I already noted in the comments, you also never query the location for your uniform and assume it is zero. Since you are using only one uniform, this is somewhat likely - however, it is not guaranteed by the GL spec at all. You also should really add that.
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().
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).
I have a program like below:
#include <iostream>
#include <fstream>
#include <sstream>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
GLuint prog, verShader, fragShader;
GLint attrPos, attrNor;
GLint uniModelView, uniProjection, uniModelViewTransposeInverse;
glm::mat4 modelMatrix, viewMatrix, projectionMatrix, MV, MVP;
glm::mat3 MVI;
const string loadFile(string name)
{
ifstream in(name.c_str(), ios::in);
if (in.fail()) {
cout << "File: '" << name << "' could not exist!!" << endl;
return "";
}
stringstream data;
data << in.rdbuf();
in.close();
return data.str();
}
GLuint createShader(GLenum type, const string name)
{
GLint isCompileOk;
GLuint shader;
string shaderText, shaderType;
const char *shaderSource;
switch(type)
{
case GL_VERTEX_SHADER:
shaderType = "GL_VERTEX_SHADER";
break;
case GL_FRAGMENT_SHADER:
shaderType = "GL_FRAGMENT_SHADER";
break;
}
shaderText = loadFile(name);
shaderSource = shaderText.c_str();
shader = glCreateShader(type);
glShaderSource(shader, 1, &shaderSource, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompileOk);
if (isCompileOk == GL_FALSE) {
char *shaderErr;
int errLength, errRetrieve;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &errLength);
shaderErr = new char [errLength + 1];
glGetShaderInfoLog(shader, errLength, &errRetrieve, shaderErr);
cout << "Compile '" << shaderType << "' error:" << endl;
cout << shaderErr << endl;
delete [] shaderErr;
return 0;
} else {
cout << "Compile '" << shaderType << "' ok!" << endl;
}
return shader;
}
bool makeShader()
{
GLint isLinkOk;
verShader = createShader(GL_VERTEX_SHADER, "vert.glsl");
fragShader = createShader(GL_FRAGMENT_SHADER, "frag.glsl");
prog = glCreateProgram();
glAttachShader(prog, verShader);
glAttachShader(prog, fragShader);
glLinkProgram(prog);
glGetProgramiv(prog, GL_LINK_STATUS, &isLinkOk);
if (isLinkOk == GL_FALSE) {
char *progErr;
int errLenght, errRetrieve;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &errLenght);
progErr = new char[errLenght + 1];
glGetProgramInfoLog(prog, errLenght, &errRetrieve, progErr);
cout << "Link program error:" << endl;
cout << progErr << endl;
delete [] progErr;
return false;
} else {
cout << "Link program Ok!" << endl;
}
attrPos = glGetAttribLocation(prog, "position");
uniModelView = glGetUniformLocation(prog, "ModelViewMatrix");
uniProjection = glGetUniformLocation(prog, "ProjectionMatrix");
uniModelViewTransposeInverse = glGetUniformLocation(prog, "ModelViewTransposeInverseMatrix");
return true;
}
float vertexs[] = {
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f
};
unsigned short indicates[] = {
0, 1, 2,
2, 3, 0
};
GLuint vao, vbo, ibo;
void display()
{
MV = viewMatrix * modelMatrix;
MVP = projectionMatrix * MV;
MVI = glm::transpose(glm::inverse(glm::mat3(MV)));
glUseProgram(prog);
glUniformMatrix4fv(uniModelView, 1, GL_FALSE, glm::value_ptr(MV));
glUniformMatrix3fv(uniModelViewTransposeInverse, 1, GL_FALSE, glm::value_ptr(MVI));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, sizeof(indicates)/sizeof(unsigned short), GL_UNSIGNED_SHORT, 0);
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
projectionMatrix = glm::perspective(45.0f, float(w)/h, 0.1f, 1000.0f);
glUseProgram(prog);
glUniformMatrix4fv(uniProjection, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
}
void idle()
{
glutPostRedisplay();
}
void Init()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
modelMatrix = glm::mat4(1.0f);
viewMatrix = glm::lookAt(
glm::vec3(0.0f, 5.0f, 10.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f)
);
projectionMatrix = glm::mat4(1.0f);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs), vertexs, GL_STATIC_DRAW);
glVertexAttribPointer(attrPos, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
glEnableVertexAttribArray(attrPos);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicates), indicates, GL_STATIC_DRAW);
glBindVertexArray(0);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow("Rectangle!");
if (glewInit() != GLEW_OK) {
cout << "glewInit() fail!" << endl;
return -1;
}
if (!makeShader()) {
cout << "makeShader() error!!" << endl;
return -1;
}
Init();
reshape(WINDOW_WIDTH, WINDOW_HEIGHT);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
glutMainLoop();
return 0;
}
when i adds VAO buffer, freeglut going to crash in glutMainLoop(), if i removes glGenVertexArrays call (of couse, removed what relatives to VAO too), it run ok, so my guess is problem in freeglut with glGenVertexArrays.
Question: What is my problem?
ps: My graphic cal support opengl 2.1, i use Visual Studio 2008.
Update: With VAO, above program work well but only crash when i close freeglut window.
Update shader: My shaders is very simple:
Vertex shader:
#version 120
attribute vec3 position;
// attribute vec3 normal;
uniform mat4 ModelViewMatrix;
uniform mat3 ModelViewTransposeInverseMatrix;
uniform mat4 ProjectionMatrix;
void main(void)
{
gl_Position = ProjectionMatrix * ModelViewMatrix * vec4(position, 1.0);
}
Fragment shader:
#version 120
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
glVertexAttribPointer(attrPos, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
Your vertex data is tightly packed. Use a stride of 0 instead of sizeof(float) * 3.
My graphic cal support opengl 2.1
Also, VAOs only became core in 3.0. You should check for ARB_vertex_array_object support before using that functionality.