Refactor and compress code

This commit is contained in:
Nathan Chapman 2025-07-02 13:11:46 -06:00
parent d10cb1cdc5
commit 8978d581d7
9 changed files with 259 additions and 163 deletions

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.12) cmake_minimum_required(VERSION 3.19)
project(OpenGLTest CXX) project(OpenGLTest CXX)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
@ -8,7 +8,8 @@ find_package(GLEW REQUIRED)
find_package(glm REQUIRED) find_package(glm REQUIRED)
find_package(glfw3 REQUIRED) find_package(glfw3 REQUIRED)
add_executable(opengl_test src/main.cpp) file(GLOB SOURCES src/*.h src/*.cpp)
add_executable(opengl_test ${SOURCES})
target_link_libraries(opengl_test target_link_libraries(opengl_test
OpenGL::GL OpenGL::GL

23
src/geometry.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "geometry.h"
void create_triangle(GLuint *VAO, GLuint *VBO) {
GLfloat vertices[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
glGenVertexArrays(1, VAO);
glBindVertexArray(*VAO);
glGenBuffers(1, VBO);
glBindBuffer(GL_ARRAY_BUFFER, *VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
// Unbinding
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}

4
src/geometry.h Normal file
View File

@ -0,0 +1,4 @@
#pragma once
#include <GL/glew.h>
void create_triangle(GLuint *VAO, GLuint *VBO);

View File

@ -1,5 +1,3 @@
#include <stdio.h>
#include <string.h>
#include <GL/glew.h> #include <GL/glew.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <cmath> #include <cmath>
@ -7,11 +5,31 @@
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
// Window dimensions #include "shader.h"
const GLint WIDTH = 800, HEIGHT = 600; #include "geometry.h"
#include "math.h"
#include "window.h"
// Vertex Shader // Window dimensions
static const char *vertex_shader = " \n\
int main() {
GLuint VAO, VBO, shader_program, uniform_model;
bool direction = true;
float tri_offset = 0.0f;
float tri_max_offset = 0.7f;
float tri_increment = 0.005f;
float current_angle = 0.0f;
bool size_direction = true;
float current_size = 0.4f;
float max_size = 0.9f;
float min_size = 0.1f;
Window window;
bool success = setup_window(&window);
Shader vertex_shader;
vertex_shader.type = VERTEX;
vertex_shader.raw_code = " \n\
#version 330 \n\ #version 330 \n\
\n\ \n\
layout (location = 0) in vec3 pos; \n\ layout (location = 0) in vec3 pos; \n\
@ -19,11 +37,12 @@ layout (location = 0) in vec3 pos; \n\
uniform mat4 model; \n\ uniform mat4 model; \n\
\n\ \n\
void main() { \n\ void main() { \n\
gl_Position = model * vec4(pos.x, pos.y, pos.z, 1.0); \n\ gl_Position = model * vec4(pos, 1.0); \n\
}"; }";
// Fragment shader Shader fragment_shader;
static const char *fragment_shader = " \n\ fragment_shader.type = FRAGMENT;
fragment_shader.raw_code = " \n\
#version 330 \n\ #version 330 \n\
\n\ \n\
out vec4 color; \n\ out vec4 color; \n\
@ -32,158 +51,12 @@ void main() { \n\
color = vec4(1.0, 0.0, 0.0, 1.0); \n\ color = vec4(1.0, 0.0, 0.0, 1.0); \n\
}"; }";
bool add_shader(GLuint *program, const char *shader_code, GLenum shader_type) {
GLuint shader = glCreateShader(shader_type);
const GLchar *code[1];
code[0] = shader_code;
GLint code_length[1];
code_length[0] = strlen(shader_code);
glShaderSource(shader, 1, code, code_length);
glCompileShader(shader);
GLint result = 0;
GLchar errors[1024] = { 0 };
glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
if (!result) {
glGetShaderInfoLog(shader, sizeof(errors), NULL, errors);
printf("Error compiling the %d shader: '%s'\n", shader_type, errors);
return false;
}
glAttachShader(*program, shader);
return true;
}
bool compile_shaders(GLuint *shader_program, GLuint *uniform_model) {
*shader_program = glCreateProgram();
if (!shader_program) {
printf("Error creating shader program!\n");
return false;
}
add_shader(shader_program, vertex_shader, GL_VERTEX_SHADER);
add_shader(shader_program, fragment_shader, GL_FRAGMENT_SHADER);
GLint result = 0;
GLchar errors[1024] = { 0 };
glLinkProgram(*shader_program);
glGetProgramiv(*shader_program, GL_LINK_STATUS, &result);
if (!result) {
glGetProgramInfoLog(*shader_program, sizeof(errors), NULL, errors);
printf("Error linking program: '%s'\n", errors);
return false;
}
glValidateProgram(*shader_program);
glGetProgramiv(*shader_program, GL_VALIDATE_STATUS, &result);
if (!result) {
glGetProgramInfoLog(*shader_program, sizeof(errors), NULL, errors);
printf("Error validating program: '%s'\n", errors);
return false;
}
*uniform_model = glGetUniformLocation(*shader_program, "model");
return true;
}
void create_triangle(GLuint *VAO, GLuint *VBO) {
GLfloat vertices[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
glGenVertexArrays(1, VAO);
glBindVertexArray(*VAO);
glGenBuffers(1, VBO);
glBindBuffer(GL_ARRAY_BUFFER, *VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
// Unbinding
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
int main() {
GLuint VAO, VBO, shader_program, uniform_model;
bool direction = true;
float tri_offset = 0.0f;
float tri_max_offset = 0.7f;
float tri_increment = 0.05f;
// Initialize GLFW
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_WAYLAND);
if (!glfwInit()) {
printf("GLFW initialization failed!");
glfwTerminate();
return 1;
}
// Setup GLFW window properties
// OpenGL version
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
// Core profile means it will not be backwards compatible
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Test Window", NULL, NULL);
if (!window) {
const char *desc;
int code = glfwGetError(&desc);
printf("GLFW window creation failed!");
printf("GLFW error code: %d, description: %s\n", code, desc ? desc : "No description given");
glfwTerminate();
return 1;
}
// Get Buffer size information
int buffer_width, buffer_height;
glfwGetFramebufferSize(window, &buffer_width, &buffer_height);
// Set context for GLEW to use
glfwMakeContextCurrent(window);
glGetError();
// Allow modern extension features
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (err != GLEW_OK && err != GLEW_ERROR_NO_GLX_DISPLAY) {
printf("OpenGL version: %s\n", glGetString(GL_VERSION));
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
printf("glewInit() returned: %d\n", err);
glfwDestroyWindow(window);
glfwTerminate();
return 1;
}
// Setup viewport size
glViewport(0, 0, buffer_width, buffer_height);
// Create our triangle // Create our triangle
create_triangle(&VAO, &VBO); create_triangle(&VAO, &VBO);
compile_shaders(&shader_program, &uniform_model); compile_shaders(&shader_program, &uniform_model, &vertex_shader, &fragment_shader);
// Loop until window is closed // Loop until window is closed
while (!glfwWindowShouldClose(window)) { while (!glfwWindowShouldClose(window.gl_window)) {
// Get and handle user input events // Get and handle user input events
glfwPollEvents(); glfwPollEvents();
@ -197,14 +70,36 @@ int main() {
direction = !direction; direction = !direction;
} }
current_angle += 0.1f;
// This isn't necessary except for safety reasons
// the program will still run correctly, but if left open too
// long the number will overflow.
if (current_angle >= 360) {
current_angle -= 360;
}
if (size_direction) {
current_size += 0.01f;
} else {
current_size -= 0.01f;
}
if (current_size >= max_size || current_size <= min_size) {
size_direction = !size_direction;
}
// Clear window // Clear window
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader_program); glUseProgram(shader_program);
glm::mat4 model = glm::mat4(1.0f); Matrix4 model = Matrix4(1.0f);
model = glm::translate(model, glm::vec3(tri_offset, 0.0f, 0.0f)); // The order of these matter
model = glm::translate(model, Vector3(tri_offset, 0.0f, 0.0f));
model = glm::scale(model, Vector3(current_size, 0.4f, 1.0f));
model = glm::rotate(model, current_angle * RADIAN_FACTOR, Vector3(0.0f, 0.0f, 1.0f));
glUniformMatrix4fv(uniform_model, 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(uniform_model, 1, GL_FALSE, glm::value_ptr(model));
@ -214,14 +109,13 @@ int main() {
glBindVertexArray(0); glBindVertexArray(0);
glUseProgram(0); glUseProgram(0);
// We usually have two buffers, the first is hidden and that's // We usually have two buffers, the first is hidden and that's
// the one we draw to. The second is the one we display, so // the one we draw to. The second is the one we display, so
// when we're done drawing we call this glfwSwapBuffers() to // when we're done drawing we call this glfwSwapBuffers() to
// swap the buffers to show the one we've been drawing to so // swap the buffers to show the one we've been drawing to so
// that it now shows. We then can start drawing on the other // that it now shows. We then can start drawing on the other
// buffer. // buffer.
glfwSwapBuffers(window); glfwSwapBuffers(window.gl_window);
} }
return 0; return 0;

11
src/math.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using Matrix4 = glm::mat4;
using Vector3 = glm::vec3;
const float RADIAN_FACTOR = 3.14159265f / 180.0f;

66
src/shader.cpp Normal file
View File

@ -0,0 +1,66 @@
#include <stdio.h>
#include <string.h>
#include "shader.h"
bool add_shader(GLuint *program, Shader *shader) {
shader->gl = glCreateShader(shader->type);
const GLchar *code[1];
code[0] = shader->raw_code;
GLint code_length[1];
code_length[0] = strlen(shader->raw_code);
glShaderSource(shader->gl, 1, code, code_length);
glCompileShader(shader->gl);
GLint result = 0;
GLchar errors[1024] = { 0 };
glGetShaderiv(shader->gl, GL_COMPILE_STATUS, &result);
if (!result) {
glGetShaderInfoLog(shader->gl, sizeof(errors), NULL, errors);
printf("Error compiling the %d shader->gl: '%s'\n", shader->type, errors);
return false;
}
glAttachShader(*program, shader->gl);
return true;
}
bool compile_shaders(GLuint *program, GLuint *uniform_model, Shader *vertex_shader, Shader *fragment_shader) {
*program = glCreateProgram();
if (!program) {
printf("Error creating shader program!\n");
return false;
}
add_shader(program, vertex_shader);
add_shader(program, fragment_shader);
GLint result = 0;
GLchar errors[1024] = { 0 };
glLinkProgram(*program);
glGetProgramiv(*program, GL_LINK_STATUS, &result);
if (!result) {
glGetProgramInfoLog(*program, sizeof(errors), NULL, errors);
printf("Error linking program: '%s'\n", errors);
return false;
}
glValidateProgram(*program);
glGetProgramiv(*program, GL_VALIDATE_STATUS, &result);
if (!result) {
glGetProgramInfoLog(*program, sizeof(errors), NULL, errors);
printf("Error validating program: '%s'\n", errors);
return false;
}
*uniform_model = glGetUniformLocation(*program, "model");
return true;
}

19
src/shader.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include <GL/glew.h>
#include <GL/gl.h>
enum Shader_Type : unsigned int {
VERTEX = GL_VERTEX_SHADER,
FRAGMENT = GL_FRAGMENT_SHADER
};
struct Shader {
Shader_Type type;
const char *raw_code;
GLuint gl;
};
bool add_shader(GLuint *program, Shader *shader, const char *raw_code);
bool compile_shaders(GLuint *shader_program, GLuint *uniform_model, Shader *vertex_shader, Shader *fragment_shader);

67
src/window.cpp Normal file
View File

@ -0,0 +1,67 @@
#include <stdio.h>
#include <string.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <cmath>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "window.h"
bool setup_window(Window *window) {
// Initialize GLFW
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_WAYLAND);
if (!glfwInit()) {
printf("GLFW initialization failed!");
glfwTerminate();
return false;
}
// Setup GLFW window properties
// OpenGL version
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
// Core profile means it will not be backwards compatible
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
window->gl_window = glfwCreateWindow(window->width, window->height, "Test Window", NULL, NULL);
if (!window) {
const char *desc;
int code = glfwGetError(&desc);
printf("GLFW window creation failed!");
printf("GLFW error code: %d, description: %s\n", code, desc ? desc : "No description given");
glfwTerminate();
return false;
}
// Get Buffer size information
int buffer_width, buffer_height;
glfwGetFramebufferSize(window->gl_window, &buffer_width, &buffer_height);
// Set context for GLEW to use
glfwMakeContextCurrent(window->gl_window);
glGetError();
// Allow modern extension features
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (err != GLEW_OK && err != GLEW_ERROR_NO_GLX_DISPLAY) {
printf("OpenGL version: %s\n", glGetString(GL_VERSION));
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
printf("glewInit() returned: %d\n", err);
glfwDestroyWindow(window->gl_window);
glfwTerminate();
return false;
}
// Setup viewport size
glViewport(0, 0, buffer_width, buffer_height);
return true;
}

11
src/window.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include <GLFW/glfw3.h>
struct Window {
GLint width = 800, height = 600;
GLFWwindow *gl_window = nullptr;
};
bool setup_window(Window *window);