cg1_tut_bin/src/main.c

327 lines
7.6 KiB
C

#include <GL/glew.h>
#include <GL/gl.h>
#include <GLFW/glfw3.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "shader.h"
#include "log.h"
#include "shader.h"
#include "matrix-math.h"
#define STATUS_INTERVAL 0.5
#define PI 3.14159f
GLuint program;
GLuint vertexArrayObject;
GLuint indexBuffer;
GLuint initialWindowWidth = 800;
GLuint initialWindowHeight = 600;
GLfloat aspect;
mat4 projectionMatrix;
int frameCount = 0;
struct timespec last_time, current_time;
typedef struct ColorRGB {
GLfloat r;
GLfloat g;
GLfloat b;
} ColorRGB;
// Color Conversion Functions from https://gist.github.com/ciembor/1494530
GLfloat hueToRgb(GLfloat p, GLfloat q, GLfloat t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1./6) return p + (q - p) * 6 * t;
if (t < 1./2) return q;
if (t < 2./3) return p + (q - p) * (2./3 - t) * 6;
return p;
}
// Color Conversion Functions from https://gist.github.com/ciembor/1494530
ColorRGB hslToRgb(GLfloat h, GLfloat s, GLfloat l) {
ColorRGB result = {0, 0, 0};
if(0 == s) {
result.r = result.g = result.b = l; // achromatic
} else {
float q = l < 0.5 ? l * (1 + s) : l + s - l * s;
float p = 2 * l - q;
result.r = hueToRgb(p, q, h + 1./3);
result.g = hueToRgb(p, q, h);
result.b = hueToRgb(p, q, h - 1./3);
}
return result;
}
void initialiseStatusDisplay() {
clock_gettime(CLOCK_MONOTONIC, &last_time);
}
void updateStatusDisplay() {
frameCount++;
clock_gettime(CLOCK_MONOTONIC, &current_time);
double elapsed = (current_time.tv_sec - last_time.tv_sec) +
(current_time.tv_nsec - last_time.tv_nsec) / 1e9;
if (elapsed >= STATUS_INTERVAL) {
double fps = frameCount / elapsed;
frameCount = 0;
last_time = current_time;
printf("\rFPS: %.2f ", fps);
fflush(stdout);
}
}
void recalculateProjectionMatrix() {
mat4BuildPerspective(projectionMatrix, 60 * M_PI / 180, aspect, 0.1, 10);
DEBUG("Recalculating Projection Matrix");
}
void init(void) {
INFO("Compiling Shaders...");
// create and compile vertex shader
INFO("Compiling Vertex Shader...");
ShaderCompileResult vertexShader = readAndCompileShaderFromFile("src/shaders/vertex.glsl", GL_VERTEX_SHADER);
if (!vertexShader.success) {
FATAL("Failed to compile Vertex Shader");
exit(1);
}
// create and compile fragment shader
INFO("Compiling Fragment Shader...");
ShaderCompileResult fragmentShader = readAndCompileShaderFromFile("src/shaders/fragment.glsl", GL_FRAGMENT_SHADER);
if (!fragmentShader.success) {
FATAL("Failed to compile Fragment Shader");
exit(1);
}
// create and link shader program
INFO("Linking Shader Program...");
ProgramLinkResult linkResult = linkShaderProgram(vertexShader.shader, fragmentShader.shader);
if (!linkResult.success) {
FATAL("Failed to link Program");
exit(1);
}
program = linkResult.program;
INFO("Shader Program Done.");
// create triangle buffer
/**
* -0.35 0.35
* | -0.2 0.2 |
* | | | |
*
* 0----1 4----5 --- 0.6
* | | | |
* | | | |
* | 2--------3 | --- 0.1
* | |
* | 9--------8 | --- -0.1
* | | | |
* | | | |
* 11---10 7----6 --- -0.6
*
* 12-----------------13 --- -0.7
* | |
* 15-----------------14 --- -0.9
*
*/
GLfloat vertices[] = {
// X // Y
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
};
GLuint restart = 128;
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(restart);
GLuint indices[] = {
1, 0, 2,
1, 2, 3,
4, 0, 1,
5, 4, 1,
5, 1, 7,
1, 3, 7,
5, 7, 6,
4, 5, 6,
0, 4, 6,
2, 0, 6,
3, 2, 6,
7, 3, 6
};
DEBUG("Creating vertext buffer");
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
DEBUG("Creating vertex array object");
// create vertex array object
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
// vertex position data
glVertexAttribPointer(
0, // shader location
3, // number of values to read
GL_FLOAT, // type of value
GL_FALSE, // if values are normalised
3 * sizeof(GLfloat), // stride - distance between vertices
0 // start offset
);
glEnableVertexAttribArray(0);
DEBUG("Creating index buffer");
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glClearColor(0.0f, 0.0f, 0.0f, 0.3f);
glViewport(0, 0, initialWindowWidth, initialWindowHeight);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glEnable(GL_DEPTH_TEST);
initialiseStatusDisplay();
recalculateProjectionMatrix();
INFO("--- Initialisation done ---");
}
GLfloat currentHue = 0.0f;
void draw(void) {
updateStatusDisplay();
currentHue += 0.0005f;
if (currentHue > 1.0) currentHue = 0.0f;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
mat4 transformMatrix;
vec3 scale = {0.2f, 0.2f, 0.2f};
vec3 position = {0.0f, 0.0f, -1.0f};
mat4Identity(transformMatrix);
mat4Scale(transformMatrix, transformMatrix, scale);
mat4RotateZ(transformMatrix, transformMatrix, currentHue * PI * 2);
mat4RotateY(transformMatrix, transformMatrix, currentHue * PI * 2);
mat4Translate(transformMatrix, transformMatrix, position);
mat4 viewMatrix;
mat4Identity(viewMatrix);
vec3 cameraPos = {0.0f, 0.0f, 0.0f};
vec3 cameraLookAt = {0.0f, 0.0f, -1.0f};
vec3 cameraUp = {0.0f, 1.0f, 0.0f};
mat4BuildLookAt(viewMatrix, cameraPos, cameraLookAt, cameraUp);
mat4 modelViewMatrix;
mat4Multiply(modelViewMatrix, viewMatrix, transformMatrix);
GLuint modelViewLocation = glGetUniformLocation(program, "uModelView");
glUniformMatrix4fv(modelViewLocation, 1, GL_FALSE, modelViewMatrix);
GLuint projectionLocation = glGetUniformLocation(program, "uProjection");
glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, projectionMatrix);
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glDrawElements(GL_TRIANGLES, 48, GL_UNSIGNED_INT, 0);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
aspect = (float)width / height;
recalculateProjectionMatrix();
}
int main(int argc, char const *argv[])
{
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-v") == 0) {
logLevel = LOG_LEVEL_INFO;
}
if (strcmp(argv[i], "-vv") == 0) {
logLevel = LOG_LEVEL_DEBUG;
}
}
INFO("Creating GLFW Window");
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER , GLFW_TRUE);
GLFWwindow* window = glfwCreateWindow(initialWindowWidth, initialWindowHeight, "CG1", NULL, NULL);
aspect = (float)initialWindowWidth / initialWindowHeight;
if (!window) {
FATAL("Failed to open window");
glfwTerminate();
return 1;
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwMakeContextCurrent(window);
glewInit();
init();
while (!glfwWindowShouldClose(window)) {
draw();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}