I am attempting to learn some OpenGL, and I have become a bit stuck. I have been playing with the tutorials at open.gl, and while working on the drawing polygons section, I got stumped while making a few changes. I have gotten everything into the section to work when compiling under C via MinGW, but after moving over to Eclipse (still using MinGW), and rewriting some of the code using C++, I cannot get anything to display to the screen. Before, I had a multi-colored triangle, as the tutorial intended, but now I just get a black window. I have been compiling with -std=c++0x, so I thought I might have done something unforgivable in C++11, but when I set another Eclipse project up with the same settings, and then cut and pasted the code from the C version in, it worked fine (it did throw some compiler warnings). I have been over the code several times, comparing it to the strictly C code that I used at first, and I cannot find where I went wrong. I did rewrite a few things based off tutorials and posts from other places, such as the code for loading the shaders.
The current version of the code is as follows:
[source lang="cpp"]
/*
* main.cpp
*
* Created on: Oct 23, 2013
*/
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
/* Shader Load
*/
bool getShader(std::string filename, GLchar ** contents) {
std::ifstream file;
file.open(filename.c_str(), std::ifstream::in);
if (!file) {
return (false);
}
std::stringstream stream;
stream << file.rdbuf();
file.close();
std::string tStr;
tStr = stream.str();
*contents = (GLchar*)tStr.c_str();
return (true);
}
int main(void) {
/* Initialization */
if (!glfwInit()) {
std::cout << "GLFW initialization error.\n";
// TODO Add error message output.
}
else {
std::cout << "GLFW Initialized. Using version:" << glfwGetVersionString() << "\n";
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
/* Create Window */
GLFWwindow * window = glfwCreateWindow(800, 600, "Basic OpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err) {
std::cout << "GLEW initialization failed. Error: " << glewGetErrorString(err) << "\n";
}
else {
std::cout << "Using GLEW " << glewGetString(GLEW_VERSION) << "\n";
}
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
std::cout << "Vertex Array: " << vao << "\n";
// REVIEW Find out exactly what I am outputting here.
GLfloat verticies[] = {
0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f
};
GLuint vbo;
glGenBuffers(1, &vbo);
std::cout << "Vertex Buffer: " << vbo << "\n";
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(verticies), verticies, GL_STATIC_DRAW);
GLuint elements[] = {
0, 1, 2
};
GLuint ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
std::cout << "Element Buffer: " << ebo << "\n";
/* Load shader files */
GLchar * vC;
GLchar * fC;
if (!getShader("vShad.vert", &vC)) {
std::cout << "Vertex shader load source failed.\n";
}
else {
std::cout << "Vertex shader source loaded.\n";
}
if (!getShader("fShad.frag", &fC)) {
std::cout << "Fragment shader source load failed.\n";
}
else {
std::cout << "Fragment shader source loaded.\n";
}
const GLchar * vert = vC;
const GLchar * frag = fC;
/* Compile Shaders */
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vert, nullptr);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &frag, nullptr);
glCompileShader(fragmentShader);
//std::cout << "Vertex Shader Source:\n" << vert;
//std::cout << "Fragment Shader Source:\n" << frag;
/* Shader compilation status */
GLint status;
char errBuffer[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
std::cout << "Vertex shader compilation failed.\n";
glGetShaderInfoLog(vertexShader, 512, nullptr, errBuffer);
std::cout << errBuffer << "\n";
}
else {
std::cout << "Vertex shader compiled.\n";
}
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
std::cout << "Fragment shader compilation failed.\n";
glGetShaderInfoLog(fragmentShader, 512, nullptr, errBuffer);
std::cout << errBuffer << "\n";
}
else {
std::cout << "Fragment shader compiled.\n";
}
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE,
5 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
glDeleteProgram(shaderProgram);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
glDeleteBuffers(1, &ebo);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
glfwDestroyWindow(window);
glfwTerminate();
return (0);
}
[/source]
The shader files that I am using are:
Vertex Shader:
[source]
#version 150
in vec2 position;
in vec3 color;
out vec3 Color;
void main() {
Color = color;
gl_Position = vec4(position, 0.0f, 1.0f);
}
[/source]
Fragment Shader:
[source]
#version 150
in vec3 Color;
out vec4 outColor;
void main() {
outColor = vec4(Color, 1.0f);
}
[/source]
In case it is relevant, I am linking:
-lmingw32 -lglew32s -lglfw3 -lopengl32 -lgdi32
and compiler options are:
-fmessage-length=0 -std=c++0x (I am not really sure about message length, it was the default, and I have left it alone so far).
Compiler is MinGW 4.7.2
The program builds in Eclipse, and runs with a black screen. It may be worth noting that I have a warning:
Warning: .drectve `/DEFAULTLIB:"LIBCMT" /DEFAULTLIB:"OLDNAMES" ' unrecognized
I have not tracked the cause of that down yet, and have been trying on and off to determine the exact cause, since I would prefer no warnings at all, even if the program runs with them. One post I read somewhere I cannot recall mentioned that those errors are related to the Microsoft compilers, but I don't yet really know more than libcmt being part of the multithread c library for them (please correct me if I am wrong).
I was worried if the shaders were loading correctly, as a friend had issues with the program where I did not (I still have not been able to figure that one out, it was with the C code I used originally), but after adding the code to print the loaded shader code in the console, I was able to determine that they are loading properly.
The terminal output when running the program is:
GLFW Initialized. Using version:3.0.3 Win32 WGL MinGW LoadLibrary(winmm)
Using GLEW 1.10.0
Vertex Array: 1
Vertex Buffer: 1
Element Buffer: 2
Vertex shader source loaded.
Fragment shader source loaded.
Vertex shader compiled.
Fragment shader compiled.
I am still getting a blank screen though. I cannot figure out what I am overlooking.
Additionally, I am not what you would call well-versed with programming. I have been playing with various languages for years, but never very seriously. That being said, I am always happy to hear about any...unconventional practices...that may cause me problems in the future as well.
Thanks