#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include <stdbool.h>
#include <assert.h>
static const GLint WIDTH = 800, HEIGHT = 600;
GLuint VAO, VBO, shader;
static const char* vertexShader =
"#version 460\n"
"layout(location = 0) in vec3 vertex_position;"
"layout(location = 1) in vec3 vertex_color;"
"out vec3 color;"
"void main()"
"{"
"color = vertex_color;"
"gl_Position = vec4(vertex_position, 1.0);"
"}";
static const char* fragmentShader =
"#version 460\n"
"in vec3 color;"
"out vec4 FragmentColor;"
"void main()"
"{"
" FragmentColor = vec4(color, 1.0);"
"}";
static const char OPENGL_LOG_FILE[11] = "opengl.log";
bool start_opengl_log_file() {
FILE* file = fopen(OPENGL_LOG_FILE, "w");
if (!file) {
fprintf(stderr, "ERROR: could not open: %s\n", OPENGL_LOG_FILE);
return false;
}
time_t now = time(NULL);
char* date = ctime(&now);
fprintf(file, "time: %s\n", date);
fclose(file);
return true;
}
bool write_to_opengl_log(const char* message, ...) {
va_list valist;
FILE* file = fopen(OPENGL_LOG_FILE, "a");
if (!file) {
fprintf(stderr, "ERROR: could not open: %s\n", OPENGL_LOG_FILE);
return false;
}
va_start(valist, message);
vfprintf(file, message, valist);
va_end(valist);
fclose(file);
return true;
}
bool write_error_to_opengl_log_file(const char* message, ...) {
va_list valist;
FILE* file = fopen(OPENGL_LOG_FILE, "a");
if (!file) {
fprintf(stderr, "ERROR: could not open: %s\n", OPENGL_LOG_FILE);
return false;
}
va_start(valist, message);
vfprintf(file, message, valist);
va_end(valist);
va_start(valist, message);
vfprintf(stderr, message, valist);
va_end(valist);
fclose(file);
return true;
}
void glfw_error_callback(int error, const char* description) {
write_error_to_opengl_log_file("GLFW ERROR: code %i msg: %s\n", error, description);
}
void CreateTriangle() {
float vertices[] = {
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f
};
float colors[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
// VBO
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint vbo_colors = 0;
glGenBuffers(1, &vbo_colors);
glBindBuffer(GL_ARRAY_BUFFER, vbo_colors);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
// VAO
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, vbo_colors);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
}
void AddShader(GLuint program, const char* shaderCode, GLenum shaderType) {
GLuint theShader = glCreateShader(shaderType);
const GLchar* theCode[1]; // Array of pointers
theCode[0] = shaderCode;
GLint codeLength[1];
codeLength[0] = (GLint)strlen(shaderCode);
glShaderSource(theShader, 1, theCode, codeLength);
glCompileShader(theShader);
GLint result = 0;
GLchar error[1024] = { 0 };
glGetShaderiv(theShader, GL_COMPILE_STATUS, &result);
if (!result) {
glGetShaderInfoLog(theShader, sizeof(error), NULL, error);
printf("Error compiling the %d shader: %s", shaderType, error);
return;
}
glAttachShader(program, theShader);
}
void CompileShaders() {
shader = glCreateProgram();
if (!shader) {
printf("glCreateProgram() Error");
return;
}
AddShader(shader, vertexShader, GL_VERTEX_SHADER);
AddShader(shader, fragmentShader, GL_FRAGMENT_SHADER);
glBindAttribLocation(shader, 0, "vertex_position");
glBindAttribLocation(shader, 1, "vertex_color");
GLint result = 0;
GLchar error[1024] = { 0 };
glLinkProgram(shader);
glGetProgramiv(shader, GL_LINK_STATUS, &result);
if (!result) {
glGetProgramInfoLog(shader, sizeof(error), NULL, error);
printf("glLinkProgram() Error: %s", error);
return;
}
}
int main(void)
{
assert(start_opengl_log_file());
write_to_opengl_log("starting GLFW version: %s\n", glfwGetVersionString());
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit()) {
fprintf(stderr, "glfwInit() Error\n");
return 1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "window title", NULL, NULL);
if (!window) {
printf("glfwCreateWindow() Error");
glfwTerminate();
return 1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
printf("glewInit() Error");
glfwDestroyWindow(window);
glfwTerminate();
}
CreateTriangle();
CompileShaders();
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, 1);
}
glClearColor(1.0f, 0.5f, 0.25f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
/*
run:
*/