Code:
#include <GL/gl.h>
#include <GL/glu.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
GLuint LoadShader(GLenum type, const char *shaderSrc)
{
GLuint shader;
GLint compiled;
// Create the shader object
shader = glCreateShader(type);
if(shader == 0)
{
return 0;
}
// Load the shader source
glShaderSource(shader, 1, &shaderSrc, NULL);
glCompileShader(shader);
// Check the compile status
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if(!compiled)
{
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = (char*) malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
printf("Error compiling shader:\n%s\n", infoLog);
free(infoLog);
}
glDeleteShader(shader);
return 0;
}
return shader;
}
GLuint programObject_;
GLuint vertexBuffer_;
GLuint indexBuffer_;
GLuint vertexArray_;
/*
* Initialize the shader and program object.
* Initialize the triangle data buffers.
*/
bool Init(int width, int height)
{
// Set the viewport
glViewport(0, 0, width, height);
GLchar vShaderStr[] =
"#version 420\n"
"in vec3 vPosition;\n"
"out vec3 vertexColor;\n"
"void main()\n"
"{\n"
" vertexColor = vPosition + vec3(0.5, 0.5, 0.5) / 2;\n"
" gl_Position = vec4(vPosition, 1.0);\n"
"}\n";
GLchar fShaderStr[] =
"#version 420\n"
"in vec3 vertexColor;\n"
"out vec4 finalColor;\n"
""
"void main()\n"
"{\n"
" finalColor = vec4(vertexColor, 1.0);\n"
"}\n";
GLuint vertexShader;
GLuint fragmentShader;
GLuint programObject;
GLint linked;
// Load the vertex/fragment shaders
vertexShader = LoadShader(GL_VERTEX_SHADER, vShaderStr);
fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fShaderStr);
if (vertexShader == 0 || fragmentShader == 0)
{
return false;
}
programObject = glCreateProgram();
glAttachShader(programObject, vertexShader);
glAttachShader(programObject, fragmentShader);
// Bind vPosition to attribute 0
glBindAttribLocation(programObject, 0, "vPosition");
glLinkProgram(programObject);
// Check the link status
glGetProgramiv(programObject, GL_LINK_STATUS, &linked);
if(!linked)
{
GLint infoLen = 0;
glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = (char*) malloc(sizeof(char) * infoLen);
glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);
printf("Error linking program:\n%s\n", infoLog);
free(infoLog);
}
glDeleteProgram(programObject);
return false;
}
programObject_ = programObject;
// set the background color when clear
glClearColor(0.0f, 0.4f, 0.6f, 1.0f);
GLfloat vVertices[] = {
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};
GLshort vIndices[] = {0, 1, 2};
GLuint vertexBuffer;
GLuint indexBuffer;
glGenBuffers(1, &vertexBuffer);
glGenBuffers(1, &indexBuffer);
GLuint vertexArray;
glGenVertexArrays(1, &vertexArray);
// store the vertices of the triangle
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices), vVertices, GL_STATIC_DRAW);
// store the vertex indices of the triangle
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vIndices), vIndices, GL_STATIC_DRAW);
glBindVertexArray(vertexArray);
// start to store vertex binding information into VertexArray
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
// Specify the data format of attribute channel 0
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
// end of storing vertex binding information into VertexArray
glBindVertexArray(0);
glDisableVertexAttribArray(0);
vertexBuffer_ = vertexBuffer;
indexBuffer_ = indexBuffer;
vertexArray_ = vertexArray;
return true;
}
/*
* Draw a triangle using the shader pair created in Init()
*/
void Draw()
{
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
// Use the program object
glUseProgram(programObject_);
// use the vertex bind information we bind previously
glBindVertexArray(vertexArray_);
// draw the triangle by index
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
// unbind the vertex array to avoid it modified somewhere else
glBindVertexArray(0);
// CODE OMITTED: here are the code to swap buffers
}
int main() {
GLFWwindow* window;
if (!glfwInit())
return -1;
window = glfwCreateWindow(800, 600, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
while (!glfwWindowShouldClose(window))
{
int width = 600;
int height = 500;
if (!Init(width, height))
{
return 0;
}
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}