327 lines
7.6 KiB
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, ¤t_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;
|
|
} |