Minimal OpenGL Example
A (hopefully) compiling version of this example can be found here.
Vertex Shader
#version 330
in vec2 position;
void main()
{
gl_Position = vec4(position, 0.0, 1.0);
};
Fragment Shader
#version 330
out vec4 outColor;
void main()
{
outColor = vec4(1.0, 1.0, 1.0, 1.0);
}
Source
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
// Helper function to print out the compiler errors from GLSL
void PrintShaderInfoLog(GLint const Shader)
{
int InfoLogLength = 0;
int CharsWritten = 0;
glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, & InfoLogLength);
if (InfoLogLength > 0)
{
GLchar * InfoLog = new GLchar[InfoLogLength];
glGetShaderInfoLog(Shader, InfoLogLength, & CharsWritten, InfoLog);
std::cout << "Shader Info Log:" << std::endl << InfoLog << std::endl;
delete [] InfoLog;
}
}
int main()
{
//////////////////////////////////
// Create Window to render into //
//////////////////////////////////
GLFWwindow * window = nullptr;
if (! glfwInit())
{
return -1;
}
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (! window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (! gladLoadGL())
{
return -1;
}
//////////
// Data //
//////////
// Load shader files
char const * VertexShaderSource = LoadFromFile("shader.vert");
char const * FragmentShaderSource = LoadFromFile("fragment.vert");
// Vertex data
GLfloat const Vertices[] = {
0.0f, 0.5f,
0.5f, -0.5f,
-0.5f, -0.5f
};
// Index data
GLuint const Indices[] = {
0, 1, 2
};
////////////////////
// OpenGL Objects //
////////////////////
// Create Vertex Array Object
GLuint VAO;
glGenVertexArrays(1, & VAO);
glBindVertexArray(VAO);
// Create Vertex Buffer Object
GLuint VBO;
glGenBuffers(1, & VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Create Index Buffer Object
GLuint IBO;
glGenBuffers(1, & IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
/////////////////////
// Compile Shaders //
/////////////////////
// Compile vertex shader
GLint Compiled;
GLuint VertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(VertexShader, 1, & VertexShaderSource, NULL);
glCompileShader(VertexShader);
glGetShaderiv(VertexShader, GL_COMPILE_STATUS, & Compiled);
if (! Compiled)
{
std::cerr << "Failed to compile vertex shader!" << std::endl;
PrintShaderInfoLog(VertexShader);
}
// Compile fragment shader
GLuint FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(FragmentShader, 1, & FragmentShaderSource, NULL);
glCompileShader(FragmentShader);
glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, & Compiled);
if (! Compiled)
{
std::cerr << "Failed to compile fragment shader!" << std::endl;
PrintShaderInfoLog(FragmentShader);
}
// Compile shader
GLuint ShaderProgram = glCreateProgram();
glAttachShader(ShaderProgram, VertexShader);
glAttachShader(ShaderProgram, FragmentShader);
glBindFragDataLocation(ShaderProgram, 0, "outColor");
glLinkProgram(ShaderProgram);
glUseProgram(ShaderProgram);
// Enable the attribute from our VBO
GLint PositionAttribute = glGetAttribLocation(ShaderProgram, "position");
glEnableVertexAttribArray(PositionAttribute);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(PositionAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
///////////////
// Main Loop //
///////////////
while (! glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
/////////////
// Cleanup //
/////////////
glDeleteProgram(ShaderProgram);
glDeleteShader(FragmentShader);
glDeleteShader(VertexShader);
glDeleteBuffers(1, & IBO);
glDeleteBuffers(1, & VBO);
glDeleteVertexArrays(1, & VAO);
return 0;
}