Compare commits

...

5 Commits

Author SHA1 Message Date
a03c7c85b8 sent from android 2025-07-30 13:14:22 +01:00
15aa9d54ea it still broke 2025-07-12 02:27:23 +01:00
41bb6b503d fix readme 2025-07-12 02:26:26 +01:00
63d0770b42 readme 2025-07-12 02:17:59 +01:00
ce44dfc950 pain 2025-07-12 02:12:46 +01:00
28 changed files with 2482 additions and 183 deletions

BIN
assets/crate.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

38
assets/cube.obj Normal file
View File

@@ -0,0 +1,38 @@
# Blender 4.5.0
# www.blender.org
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.375000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.500000
vt 0.625000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 1.000000
vt 0.125000 0.750000
vt 0.125000 0.500000
vt 0.875000 0.500000
vt 0.625000 1.000000
vt 0.875000 0.750000
s 0
f 2/1 3/2 1/3
f 4/4 7/5 3/2
f 8/6 5/7 7/5
f 6/8 1/9 5/7
f 7/5 1/10 3/11
f 4/12 6/8 8/6
f 2/1 4/4 3/2
f 4/4 8/6 7/5
f 8/6 6/8 5/7
f 6/8 2/13 1/9
f 7/5 5/7 1/10
f 4/12 2/14 6/8

BIN
assets/meow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

1479
assets/monkey.obj Normal file

File diff suppressed because it is too large Load Diff

45
include/geometry.hpp Normal file
View File

@@ -0,0 +1,45 @@
#ifndef GEOMETRY_HPP
#define GEOMETRY_HPP
// Includes
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "graphics.hpp"
// Object class
class Object {
public:
Object(
float *vertices, unsigned int vertex_size,
unsigned int *indices, unsigned int index_size,
float *normals = nullptr, unsigned int normal_size = 0,
float *texcoords = nullptr, unsigned int texcoord_size = 0
);
~Object();
void draw();
private:
unsigned int VAO, VBO, EBO, NBO, TBO; // Vertex Array Object, Vertex Buffer Object, Element Buffer Object, Normal Buffer Object, Texture Buffer Object
unsigned int vertex_count;
unsigned int index_count;
};
class UntexturedObject {
public:
UntexturedObject(
float *vertices, unsigned int vertex_size,
unsigned int *indices, unsigned int index_size,
float *normals = nullptr, unsigned int normal_size = 0,
float *texcoords = nullptr, unsigned int texcoord_size = 0
);
~UntexturedObject();
void draw();
private:
unsigned int VAO, VBO, EBO, NBO, TBO; // Vertex Array Object, Vertex Buffer Object, Element Buffer Object, Normal Buffer Object, Texture Buffer Object
unsigned int vertex_count;
unsigned int index_count;
};
#endif

33
include/graphics.hpp Normal file
View File

@@ -0,0 +1,33 @@
#ifndef GRAPHICS_HPP
#define GRAPHICS_HPP
#define GL_GLEXT_PROTOTYPES
// Includes
#include <SDL3/SDL_opengl.h>
#include "window.hpp"
#include "shader.hpp"
#include "texture.hpp"
#include <iostream>
// Constants
const int open_gl_major_version = 3;
const int open_gl_minor_version = 3;
const int enable_vsync = 1;
// Variables
extern Uint32 last_time;
extern Uint32 current_time;
extern float frame_time;
extern float fps;
extern float frame_time_graph[100];
extern SDL_GLContext gl_context;
#define delta_time frame_time
// Functions
int initialize_opengl();
void cleanup_opengl();
// Frame time calculation
void calc_frame_time();
#endif

23
include/gui.hpp Normal file
View File

@@ -0,0 +1,23 @@
#ifndef GUI_HPP
#define GUI_HPP
// Includes
#include "imgui.h"
#include "imgui_impl_sdl3.h"
#include "imgui_impl_opengl3.h"
#include "window.hpp"
#include "graphics.hpp"
#include <iostream>
// Variables
extern ImGuiIO& io;
extern ImGuiStyle& style;
extern
// Functions
int initialize_imgui();
void cleanup_imgui();
void new_frame_imgui();
void frame_time_ui();
#endif

23
include/loader.hpp Normal file
View File

@@ -0,0 +1,23 @@
#ifndef LOADER_HPP
#define LOADER_HPP
// Includes
#include <fstream>
#include <iostream>
// Obj struct
struct Obj {
float* vertices; // Pointer to vertex data
size_t vertex_count; // Number of vertices
float* normals; // Pointer to normal data
size_t normal_count; // Number of normals
float* texcoords; // Pointer to texture coordinate data
size_t texcoord_count; // Number of texture coordinates
unsigned int* indices; // Pointer to index data
size_t index_count; // Number of indices
};
// Function to load an OBJ file
Obj load_obj(const std::string& filename);
#endif // LOADER_HPP

View File

@@ -1,44 +1,22 @@
#ifndef MAIN_HPP
#define MAIN_HPP
// ImGui
#include "imgui.h"
#include "imgui_impl_sdl3.h"
#include "imgui_impl_opengl3.h"
// SDL3 and OpenGL
#include <SDL3/SDL.h>
#include <SDL3/SDL_opengl.h>
// C++ Standard Library
// Includes
#include <iostream>
#include <string>
#include <vector>
// Structs
#include "window.hpp"
#include "graphics.hpp"
#include "utils.hpp"
#include "gui.hpp"
#include "geometry.hpp"
#include "loader.hpp"
// Variables
int window_width = 1920;
int window_height = 1080;
float main_scale;
SDL_WindowFlags window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY;
SDL_Window* window;
bool running;
SDL_Event event;
Uint32 last_time;
Uint32 current_time;
float frame_time;
float fps;
float frame_time_graph[100] = {0.0f};
extern bool running;
// Functions
int main(int argc, char* argv[]);
int initialize();
void cleanup();
void init(); // Initialize SDL, OpenGL, and ImGui
void handle_events(); // Handle SDL events
void handle_keyboard_input(); // Handle keyboard input for camera movement
#endif

24
include/shader.hpp Normal file
View File

@@ -0,0 +1,24 @@
#ifndef SHADER_HPP
#define SHADER_HPP
#define GL_GLEXT_PROTOTYPES
// Includes
#include "utils.hpp"
#include <iostream>
#include <SDL3/SDL_opengl.h>
#include "geometry.hpp"
// Shader class
class Shader {
public:
unsigned int ID;
Shader(const char* vertexPath, const char* fragmentPath);
void use() const;
void setBool(const std::string &name, bool value) const;
void setInt(const std::string &name, int value) const;
void setFloat(const std::string &name, float value) const;
void setMat4(const std::string &name, const glm::mat4 &mat) const;
~Shader();
};
#endif

24
include/texture.hpp Normal file
View File

@@ -0,0 +1,24 @@
#ifndef TEXTURE_HPP
#define TEXTURE_HPP
#define GL_GLEXT_PROTOTYPES
// Includes
#include <SDL3_image/SDL_image.h>
#include <SDL3/SDL_opengl.h>
#include <iostream>
// Functions
void flip_surface(SDL_Surface* surface);
// Classes
class Texture {
public:
unsigned int ID;
Texture(const char* file_path);
~Texture();
void bind() const;
void bind(unsigned int unit) const;
void unbind() const;
};
#endif

11
include/utils.hpp Normal file
View File

@@ -0,0 +1,11 @@
#ifndef UTILS_HPP
#define UTILS_HPP
// Includes
#include <fstream>
#include <iostream>
// Function
char* read_file(const char* file_path);
#endif

20
include/window.hpp Normal file
View File

@@ -0,0 +1,20 @@
#ifndef WINDOW_HPP
#define WINDOW_HPP
// Includes
#include <iostream>
#include <SDL3/SDL.h>
// Variables
const SDL_WindowFlags window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY;
extern float main_scale;
extern SDL_Window* window;
extern SDL_Event event;
extern int window_width;
extern int window_height;
// Functions
int initialize_sdl();
void cleanup_sdl();
#endif

View File

@@ -10,10 +10,10 @@ IMGUI_DIR = imgui
CXX = g++
# Libs
LIBS = -lGL `pkg-config --libs sdl3`
LIBS = -lGL -lglm `pkg-config --libs sdl3 sdl3-image`
# Compiler and linker settings
CXXFLAGS = `pkg-config --cflags sdl3` -std=c++17 -I $(INCLUDE_DIR)
CXXFLAGS = -std=c++17 -I $(INCLUDE_DIR)
# If ImGui directory is set, include its source files
ifdef IMGUI_DIR
@@ -51,6 +51,10 @@ dirs:
@mkdir -p $(BUILD_DIR)
@mkdir -p $(OBJ_DIR)
# Clear build directory
clear:
@find $(OBJ_DIR) -type f -name '*.o' ! -name 'imgui*.o' -exec rm -f {} +
# Pattern rule for source files in src directory
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
@@ -64,7 +68,7 @@ $(OBJ_DIR)/%.o: $(IMGUI_DIR)/backends/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
endif
all: dirs $(BIN)
all: dirs clear $(BIN)
@echo Build complete
$(BIN): $(OBJS)

View File

@@ -3,24 +3,26 @@
### Why is this called "Untitled"?
Cus I cant think of a name and im uncreative.
<pre>
⡴⠒⣄⣼⠉⠳⡆
⣇⠰⠉⢙⡄⠀⠀⣴⠖⢦⠘⣆⠁⠙⡆
⠘⡇⢠⠞⠉⠙⣾⠃⢀⡼⠀⠀⠀⠀⠀⠀⠀⢀⣼⡀⠄⢷⣄⣀⠀⠀⠀⠀⠀⠀⠀⠰⠒⠲⡄⠀⣏⣆⣀⡍
⢠⡏⠀⡤⠒⠃⠀⡜⠀⠀⠀⠀⠀⢀⣴⠾⠛⡁⠀⠀⢀⣈⡉⠙⠳⣤⡀⠀⠀⠀⠘⣆⠀⣇⡼⢋⠀⠀⢱
⠘⣇⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⡴⢋⡣⠊⡩⠋⠀⠀⠀⠣⡉⠲⣄⠀⠙⢆⠀⠀⠀⣸⠀⢉⠀⢀⠿⠀⢸
⠸⡄⠀⠈⢳⣄⡇⠀⠀⢀⡞⠀⠈⠀⢀⣴⣾⣿⣿⣿⣿⣦⡀⠀⠀⠀⠈⢧⠀⠀⢳⣰⠁⠀⠀⠀⣠⠃
⠘⢄⣀⣸⠃⠀⠀⠀⡸⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀⠈⣇⠀⠀⠙⢄⣀⠤⠚⠁⠀
⠀⠀⠀⠀⠀⠀⡇⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⢹⠀⠀⠀⠀⠀⠀
⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡀⠀⠀⢘
⡇⠀⢰⣿⣿⣿⡿⠛⠁⠀⠉⠛⢿⣿⣿⣿⣧⠀⠀⣼
⢠⡀⣸⣿⣿⠟⠀⠀⣿⣿⣿⡀⢀⠇
⠘⡇⠹⠿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⡿⠁⡏
⠻⣤⣞⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢢⣀⣠⠇
⠙⠲⢤⣀⣀⠀⢀⣀⣀⠤⠒⠉⠀⠀
⠀⢀⣀⡀⠀⠀⣀⣀⣀⠀⠀
⢰⡿⠋⠙⠦⣄⡀⠀⠀⠀⣀⡀⢸⡋⠀⠀⢳⣄⠀
⠸⣧⠀⠀⠀⠈⣷⣤⣤⠛⠋⠛⣦⠀⠀⠀⠀⠀⠀⠀⣀⠀⢀⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣤⣤⣷⡄⠀⠀⠛⡆
⠙⣷⠀⠀⠀⠀⠀⡇⠀⠀⣴⠛⠀⠀⠀⠀⠀⣠⣴⡿⠓⠛⠛⢿⣟⠒⢤⣄⠀⠀⠀⠀⢾⡏⠀⠈⢿⣿⠃⠀⠠⠀⢸
⠀⢸⡄⠀⠀⠚⠋⠁⠀⣼⠁⠀⠀⠀⢀⡴⠛⠛⣋⣤⣄⠀⠠⠤⢤⣀⠀⠈⠳⢦⡀⠀⠈⢳⡀⠀⣾⠃⠀⣀⡀⠀⢺
⠀⢿⡀⠀⠀⠀⡀⠀⣿⠀⠀⠀⣴⠋⠡⠂⠉⠀⠀⠀⣀⣀⡀⠀⠉⠙⠀⠀⠈⠱⣆⠀⢸⡇⢀⠀⠀⠠⠋⠁⢀⡿
⠈⢧⡀⠀⠀⠈⣰⠏⠀⠀⡾⠁⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⣷⣦⡀⠀⠀⠀⠀⠙⡆⠸⣦⡀⠀⠀⠀⢀⣠⠟⠁
⠙⢦⣤⣴⠟⠀⠀⣸⠁⠀⠀⠀⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⢿⡄⠈⠻⣦⣤⠾⠋
⠀⣿⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⢸⣧
⠀⣿⠀⠀⠀⣾⣿⣿⣿⡿⠟⠛⠛⠿⣿⣿⣿⣿⣷⡀⠀⠀⢸⡏
⠀⠻⡄⠀⣸⣿⣿⡿⠋⠈⠻⣿⣿⣿⣇⠀⠀⣿⠁
⠀⠀⣷⠀⢻⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⣿⠀⣴⠃
⠀⠘⣇⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⢀⣿⠀
⠈⠉⠛⠶⣄⡀⠀⠀⠀⠀⠀⠀⠀⣠⣴⠞⠿⠋⠁
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⠉⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
</pre>
# Features
- FPS counter
- !!! RGB RECTANGLE !!!
- Thats about it rly ¯\\_(ツ)\_/¯
# Requirements
@@ -35,3 +37,9 @@ Cus I cant think of a name and im uncreative.
6. If it runs, enjoy the FPS counter
\* we dont like clang here (idk why, i just dont like it cus y not)
# Notes
OpenGl is scary >.<
# License
"yes"

12
shaders/triangle.frag Normal file
View File

@@ -0,0 +1,12 @@
#version 330 core
out vec4 FragColor;
in vec3 color; // Input color from the vertex shader
in vec2 TexCoord;
uniform sampler2D texture1; // Texture sampler
uniform sampler2D texture2; // Second texture sampler
void main() {
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.3) * vec4(color, 1.0); // Mix the two textures and apply the color
}

16
shaders/triangle.vert Normal file
View File

@@ -0,0 +1,16 @@
#version 330 core
layout(location = 0) in vec3 position; // Vertex position
layout(location = 1) in vec2 texCoords; // Texture coordinates
out vec3 color; // Output color to the fragment shader
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
gl_Position = projection * view * model * vec4(position, 1.0); // Apply transformation matrices
color = position + vec3(0.5); // Set the color based on the vertex position
TexCoord = texCoords; // Pass texture coordinates to the fragment shader
}

View File

@@ -0,0 +1,8 @@
#version 330 core
out vec4 FragColor;
in vec3 color; // Input color from the vertex shader
void main() {
FragColor = vec4(color, 1.0); // Apply the color
}

View File

@@ -0,0 +1,13 @@
#version 330 core
layout(location = 0) in vec3 position; // Vertex position
out vec3 color; // Output color to the fragment shader
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
gl_Position = projection * view * model * vec4(position, 1.0); // Apply transformation matrices
color = position + vec3(0.5); // Set the color based on the vertex position
}

120
src/geometry.cpp Normal file
View File

@@ -0,0 +1,120 @@
#include "geometry.hpp"
Object::Object(
float *vertices, unsigned int vertex_size,
unsigned int *indices, unsigned int index_size,
float *normals, unsigned int normal_size,
float *texcoords, unsigned int texcoord_size
) {
glGenVertexArrays(1, &VAO); // Generate a vertex array object
glGenBuffers(1, &VBO); // Generate a vertex buffer object
glGenBuffers(1, &EBO); // Generate an element buffer object
glGenBuffers(1, &NBO); // Generate a normal buffer object
glGenBuffers(1, &TBO); // Generate a texture buffer object
glBindVertexArray(VAO); // Bind the vertex array object
glBindBuffer(GL_ARRAY_BUFFER, VBO); // Bind the vertex buffer object
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // Bind the element buffer object
glBufferData(GL_ARRAY_BUFFER, vertex_size, vertices, GL_STATIC_DRAW); // Upload vertex data to the buffer
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_size, indices, GL_STATIC_DRAW); // Upload index data to the buffer
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); // Set up vertex attributes
glEnableVertexAttribArray(0); // Enable vertex attribute 0
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); // Set up texture coordinates
glEnableVertexAttribArray(1); // Enable vertex attribute 1
if (normals && normal_size > 0) {
glBindBuffer(GL_ARRAY_BUFFER, NBO); // Bind the normal buffer object
glBufferData(GL_ARRAY_BUFFER, normal_size, normals, GL_STATIC_DRAW); // Upload normal data to the buffer
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); // Set up normal attributes
glEnableVertexAttribArray(2); // Enable vertex attribute 2
}
if (texcoords && texcoord_size > 0) {
glBindBuffer(GL_ARRAY_BUFFER, TBO); // Bind the texture buffer object
glBufferData(GL_ARRAY_BUFFER, texcoord_size, texcoords, GL_STATIC_DRAW); // Upload texture coordinate data to the buffer
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); // Set up texture coordinate attributes
glEnableVertexAttribArray(3); // Enable vertex attribute 3
}
glBindVertexArray(0); // Unbind the vertex array object
glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind the vertex buffer object
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // Unbind the element buffer object
this->vertex_count = vertex_size / (5 * sizeof(float)); // Calculate vertex count based on size
this->index_count = index_size / sizeof(unsigned int); // Calculate index count based on size
}
Object::~Object() {
glDeleteVertexArrays(1, &VAO); // Delete the vertex array object
glDeleteBuffers(1, &VBO); // Delete the vertex buffer object
glDeleteBuffers(1, &EBO); // Delete the element buffer object
glDeleteBuffers(1, &NBO); // Delete the normal buffer object
glDeleteBuffers(1, &TBO); // Delete the texture buffer object
}
void Object::draw() {
glBindVertexArray(VAO); // Bind the vertex array object
glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT, 0); // Draw the object using the element buffer
glBindVertexArray(0); // Unbind the vertex array object
}
UntexturedObject::UntexturedObject(
float *vertices, unsigned int vertex_size,
unsigned int *indices, unsigned int index_size,
float *normals, unsigned int normal_size,
float *texcoords, unsigned int texcoord_size
) {
glGenVertexArrays(1, &VAO); // Generate a vertex array object
glGenBuffers(1, &VBO); // Generate a vertex buffer object
glGenBuffers(1, &EBO); // Generate an element buffer object
glGenBuffers(1, &NBO); // Generate a normal buffer object
glGenBuffers(1, &TBO); // Generate a texture buffer object
glBindVertexArray(VAO); // Bind the vertex array object
glBindBuffer(GL_ARRAY_BUFFER, VBO); // Bind the vertex buffer object
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // Bind the element buffer object
glBufferData(GL_ARRAY_BUFFER, vertex_size, vertices, GL_STATIC_DRAW); // Upload vertex data to the buffer
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_size, indices, GL_STATIC_DRAW); // Upload index data to the buffer
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); // Set up vertex attributes
glEnableVertexAttribArray(0); // Enable vertex attribute 0
if (normals && normal_size > 0) {
glBindBuffer(GL_ARRAY_BUFFER, NBO); // Bind the normal buffer object
glBufferData(GL_ARRAY_BUFFER, normal_size, normals, GL_STATIC_DRAW); // Upload normal data to the buffer
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); // Set up normal attributes
glEnableVertexAttribArray(1); // Enable vertex attribute 1
}
if (texcoords && texcoord_size > 0) {
glBindBuffer(GL_ARRAY_BUFFER, TBO); // Bind the texture buffer object
glBufferData(GL_ARRAY_BUFFER, texcoord_size, texcoords, GL_STATIC_DRAW); // Upload texture coordinate data to the buffer
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); // Set up texture coordinate attributes
glEnableVertexAttribArray(2); // Enable vertex attribute 2
}
glBindVertexArray(0); // Unbind the vertex array object
glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind the vertex buffer object
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // Unbind the element buffer object
this->vertex_count = vertex_size / (5 * sizeof(float)); // Calculate vertex count based on size
this->index_count = index_size / sizeof(unsigned int); // Calculate index count based on
}
UntexturedObject::~UntexturedObject() {
glDeleteVertexArrays(1, &VAO); // Delete the vertex array object
glDeleteBuffers(1, &VBO); // Delete the vertex buffer object
glDeleteBuffers(1, &EBO); // Delete the element buffer object
glDeleteBuffers(1, &NBO); // Delete the normal buffer object
glDeleteBuffers(1, &TBO); // Delete the texture buffer object
}
void UntexturedObject::draw() {
glBindVertexArray(VAO); // Bind the vertex array object
glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT, 0); // Draw the object using the element buffer
glBindVertexArray(0); // Unbind the vertex array object
}

58
src/graphics.cpp Normal file
View File

@@ -0,0 +1,58 @@
#include "graphics.hpp"
// Variables
Uint32 last_time;
Uint32 current_time;
float frame_time;
float fps;
float frame_time_graph[100];
SDL_GLContext gl_context;
// Functions
int initialize_opengl() {
// Initialize OpenGL
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, open_gl_major_version);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, open_gl_minor_version);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
// Initialize OpenGL context
gl_context = SDL_GL_CreateContext(window);
if (!gl_context) {
std::cerr << "OpenGL context could not be created! SDL_Error: " << SDL_GetError() << std::endl;
return 1; // OpenGL context creation failed
}
// Initialize OpenGL settings for the window
SDL_GL_MakeCurrent(window, gl_context);
SDL_GL_SetSwapInterval(enable_vsync);
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window);
glViewport(0, 0, (int)(window_width * main_scale), (int)(window_height * main_scale));
return 0; // OpenGL initialization successful
}
void cleanup_opengl() {
// Destroy OpenGL context
if (gl_context) {
SDL_GL_MakeCurrent(NULL, NULL);
SDL_GL_DestroyContext(gl_context);
gl_context = nullptr;
}
std::cout << "OpenGL cleanup successful." << std::endl;
}
void calc_frame_time() {
// Calculate frame time
current_time = SDL_GetTicks();
frame_time = (current_time - last_time) / 1000.0f; // Convert milliseconds to seconds
fps = 1.0f / frame_time;
last_time = current_time;
// Update frame time graph
for (int i = 99; i > 0; --i) {
frame_time_graph[i] = frame_time_graph[i - 1]; // Shift old values
}
frame_time_graph[0] = frame_time; // Add new frame time
}

51
src/gui.cpp Normal file
View File

@@ -0,0 +1,51 @@
#include "gui.hpp"
int initialize_imgui() {
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
ImGui::StyleColorsDark();
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale);
style.FontScaleDpi = main_scale;
if (!ImGui_ImplSDL3_InitForOpenGL(window, gl_context)) {
std::cerr << "ImGui_ImplSDL3_InitForOpenGL failed!" << std::endl;
return 1; // Initialization failed
}
char glsl_version[32];
snprintf(glsl_version, sizeof(glsl_version), "#version %d%d0", open_gl_major_version, open_gl_minor_version);
if (!ImGui_ImplOpenGL3_Init(glsl_version)) {
std::cerr << "ImGui_ImplOpenGL3_Init failed!" << std::endl;
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
return 1; // Initialization failed
}
return 0;
}
void cleanup_imgui() {
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
std::cout << "ImGui cleanup successful." << std::endl;
}
void new_frame_imgui() {
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
}
void frame_time_ui() {
ImGui::Begin("Frame Time");
ImGui::Text("Current FPS: %.2f", fps);
ImGui::Text("Current Frame Time: %.3f ms", frame_time * 1000.0f);
ImGui::PlotLines("##Frame Time Graph", frame_time_graph, 100, 0, "Frame Time (ms)", 0.0f, 0.1f, ImVec2(200, 80));
ImGui::End();
}

48
src/loader.cpp Normal file
View File

@@ -0,0 +1,48 @@
#include "loader.hpp"
Obj load_obj(const std::string& filename) {
Obj obj;
obj.vertices = nullptr;
obj.vertex_count = 0;
obj.indices = nullptr;
obj.index_count = 0;
obj.normals = nullptr;
obj.normal_count = 0;
obj.texcoords = nullptr;
obj.texcoord_count = 0;
std::ifstream file(filename);
if (!file.is_open()) {
std::cerr << "Failed to open OBJ file: " << filename << std::endl;
return obj;
}
// Read the file and populate the obj structure
std::string line;
while (std::getline(file, line)) {
// Parse the line and extract vertex, normal, and index data
if (line.substr(0, 2) == "v ") {
// Vertex position
obj.vertex_count++;
obj.vertices = (float*)realloc(obj.vertices, obj.vertex_count * 3 * sizeof(float));
sscanf(line.c_str() + 2, "%f %f %f", &obj.vertices[(obj.vertex_count - 1) * 3], &obj.vertices[(obj.vertex_count - 1) * 3 + 1], &obj.vertices[(obj.vertex_count - 1) * 3 + 2]);
} else if (line.substr(0, 2) == "f ") {
// Face indices
unsigned int index1,
} else if (line.substr(0, 2) == "vn") {
// Vertex normal
obj.normal_count++;
obj.normals = (float*)realloc(obj.normals, obj.normal_count * 3 * sizeof(float));
sscanf(line.c_str() + 3, "%f %f %f", &obj.normals[(obj.normal_count - 1) * 3], &obj.normals[(obj.normal_count - 1) * 3 + 1], &obj.normals[(obj.normal_count - 1) * 3 + 2]);
} else if (line.substr(0, 2) == "vt") {
// Vertex texture coordinate
obj.texcoord_count++;
obj.texcoords = (float*)realloc(obj.texcoords, obj.texcoord_count * 2 * sizeof(float));
sscanf(line.c_str() + 3, "%f %f", &obj.texcoords[(obj.texcoord_count - 1) * 2], &obj.texcoords[(obj.texcoord_count - 1) * 2 + 1]);
}
}
file.close();
return obj;
}

View File

@@ -1,170 +1,205 @@
#include "main.hpp"
// Variables
bool running = true;
float fov = 45.0f; // Field of view
float camera_move_speed = 10.0f; // Camera movement speed
bool wireframe_mode = false; // Wireframe mode toggle
glm::mat4 viewMatrix = glm::mat4(1.0f); // View matrix
glm::mat4 projectionMatrix = glm::perspective(glm::radians(fov), (float)window_width / (float)window_height, 0.1f, 100.0f); // Perspective projection matrix
glm::vec3 camera_position = glm::vec3(0.0f, 0.0f, 3.0f); // Initial camera position
glm::vec3 camera_front = glm::vec3(0.0f, 0.0f, -1.0f); // Camera front vector
glm::vec3 camera_up = glm::vec3(0.0f, 1.0f, 0.0f); // Camera up vector
float camera_pitch = 0.0f; // Pitch angle
float camera_yaw = -90.0f; // Yaw angle
float camera_turn_speed = 1.0f; // Camera turn speed
// Init
int initialize() {
void init() {
// Initialize SDL
if (!SDL_Init(SDL_INIT_VIDEO)) {
std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
return 1; // Initialization failed
if (initialize_sdl() != 0) {
std::cerr << "SDL initialization failed." << std::endl;
return;
}
// Create a window with OpenGL context
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
window = SDL_CreateWindow("Untitled", (int)(window_width * main_scale), (int)(window_height * main_scale), window_flags);
if (!window) {
std::cerr << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1; // Window creation failed
// Initialize OpenGL
if (initialize_opengl() != 0) {
std::cerr << "OpenGL initialization failed." << std::endl;
cleanup_sdl();
return;
}
// Initialize OpenGL context
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
if (!gl_context) {
std::cerr << "OpenGL context could not be created! SDL_Error: " << SDL_GetError() << std::endl;
SDL_DestroyWindow(window);
SDL_Quit();
return 1; // OpenGL context creation failed
}
SDL_GL_MakeCurrent(window, gl_context);
SDL_GL_SetSwapInterval(1); // Enable VSync
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window);
// Initialize ImGui
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
// Setup Dear ImGui style
ImGui::StyleColorsDark();
// Setup scale
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale);
style.FontScaleDpi = main_scale;
// Setup Platform/Renderer bindings
if (!ImGui_ImplSDL3_InitForOpenGL(window, gl_context)) {
std::cerr << "ImGui_ImplSDL3_InitForOpenGL failed!" << std::endl;
SDL_GL_DestroyContext(gl_context);
SDL_DestroyWindow(window);
SDL_Quit();
return 1; // Initialization failed
if (initialize_imgui() != 0) {
std::cerr << "ImGui initialization failed." << std::endl;
cleanup_opengl();
cleanup_sdl();
return;
}
if (!ImGui_ImplOpenGL3_Init("#version 330")) {
std::cerr << "ImGui_ImplOpenGL3_Init failed!" << std::endl;
ImGui_ImplSDL3_Shutdown();
SDL_GL_DestroyContext(gl_context);
SDL_DestroyWindow(window);
SDL_Quit();
return 1; // Initialization failed
}
return 0; // Initialization successful
glEnable(GL_DEPTH_TEST);
}
// Event handling
void handle_events() {
while (SDL_PollEvent(&event)) {
ImGui_ImplSDL3_ProcessEvent(&event); // Process ImGui events
switch (event.type) {
case SDL_EVENT_QUIT:
running = false; // Exit loop on quit event
break;
case SDL_EVENT_WINDOW_RESIZED:
// Handle window resize
SDL_GetWindowSize(window, &window_width, &window_height);
glViewport(0, 0, window_width, window_height); // Update OpenGL
break;
// Cleanup
void cleanup() {
// Shutdown ImGui
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
// Destroy OpenGL context
SDL_GLContext gl_context = SDL_GL_GetCurrentContext();
if (gl_context) {
SDL_GL_MakeCurrent(NULL, NULL);
SDL_GL_DestroyContext(gl_context);
default:
break;
}
}
// Destroy window
if (window) {
SDL_DestroyWindow(window);
window = nullptr;
}
// Quit SDL
SDL_Quit();
std::cout << "Cleanup successful." << std::endl;
}
// Handle keyboard input
void handle_keyboard_input() {
const bool *keyboard_state = SDL_GetKeyboardState(NULL);
// Handle keyboard input for camera movement
if (keyboard_state[SDL_SCANCODE_W]) {
camera_position += camera_move_speed * delta_time * camera_front; // Move forward
}
if (keyboard_state[SDL_SCANCODE_S]) {
camera_position -= camera_move_speed * delta_time * camera_front; // Move backward
}
if (keyboard_state[SDL_SCANCODE_A]) {
camera_position -= glm::normalize(glm::cross(camera_front, camera_up)) * camera_move_speed * delta_time; // Move left
}
if (keyboard_state[SDL_SCANCODE_D]) {
camera_position += glm::normalize(glm::cross(camera_front, camera_up)) * camera_move_speed * delta_time; // Move right
}
if (keyboard_state[SDL_SCANCODE_SPACE]) {
camera_position += camera_up * camera_move_speed * delta_time; // Move up
}
if (keyboard_state[SDL_SCANCODE_LCTRL]) {
camera_position -= camera_up * camera_move_speed * delta_time; // Move down
}
if (keyboard_state[SDL_SCANCODE_LEFT]) {
camera_yaw -= camera_turn_speed; // Turn left
if (camera_yaw < -180.0f) camera_yaw += 360.0f; // Wrap yaw
}
if (keyboard_state[SDL_SCANCODE_RIGHT]) {
camera_yaw += camera_turn_speed; // Turn right
if (camera_yaw > 180.0f) camera_yaw -= 360.0f; // Wrap yaw
}
if (keyboard_state[SDL_SCANCODE_UP]) {
camera_pitch += camera_turn_speed; // Look up
if (camera_pitch > 89.0f) camera_pitch = 89.0f; // Clamp pitch
}
if (keyboard_state[SDL_SCANCODE_DOWN]) {
camera_pitch -= camera_turn_speed; // Look down
if (camera_pitch < -89.0f) camera_pitch = -89.0f; // Clamp pitch
}
}
// ImGui frame
void imgui_frame() {
new_frame_imgui();
frame_time_ui();
ImGui::Begin("Control Panel");
ImGui::Text("Camera Position: (%.2f, %.2f, %.2f)", camera_position.x, camera_position.y, camera_position.z);
ImGui::Text("Camera Front: (%.2f, %.2f, %.2f)", camera_front.x, camera_front.y, camera_front.z);
ImGui::Text("Camera Up: (%.2f, %.2f, %.2f)", camera_up.x, camera_up.y, camera_up.z);
ImGui::Text("Camera Pitch: %.2f degrees", camera_pitch);
ImGui::Text("Camera Yaw: %.2f degrees", camera_yaw);
ImGui::SliderFloat("Field of View", &fov, 1.0f, 120.0f, "%.1f degrees");
ImGui::SliderFloat("Camera Speed", &camera_move_speed, 0.1f, 10.0f, "%.1f units/s");
ImGui::SliderFloat("Camera Turn Speed", &camera_turn_speed, 1.0f, 5.0f, "%.2f units/s");
ImGui::Checkbox("Wireframe Mode", &wireframe_mode);
if (wireframe_mode) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Enable wireframe mode
} else {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Disable wireframe mode
}
ImGui::End();
}
// Main
int main(int argc, char* argv[]) {
// Initialize
if (initialize() != 0) {
std::cerr << "Initialization failed." << std::endl;
return -1; // Initialization failed
}
// Initialize SDL, OpenGL, and ImGui
init();
// Load shader program
Shader shader_program("shaders/triangle_untextured.vert", "shaders/triangle_untextured.frag");
// Generate and set up textures
Texture texture1("assets/crate.jpg");
Texture texture2("assets/meow.png");
shader_program.use();
shader_program.setInt("texture1", 0);
shader_program.setInt("texture2", 1);
// Load an OBJ file
Obj obj = load_obj("assets/cube.obj");
// print vertex and index counts
std::cout << "Loaded OBJ file: " << obj.vertex_count << " vertices, " << obj.index_count << " indices." << std::endl;
// Create the object and set up its geometry
UntexturedObject object(
obj.vertices, obj.vertex_count * 3 * sizeof(float),
obj.indices, obj.index_count * sizeof(unsigned int)
);
glm::mat4 modelMatrix = glm::mat4(1.0f);
// Main loop
running = true;
last_time = SDL_GetTicks();
while (running) {
// Handle events
while (SDL_PollEvent(&event)) {
ImGui_ImplSDL3_ProcessEvent(&event);
if (event.type == SDL_EVENT_QUIT) {
running = false; // Exit loop on quit event
}
}
handle_events();
handle_keyboard_input();
// Start the ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
// Show a simple ImGui window
ImGui::Begin("Hello, World!");
ImGui::Text("This is a simple ImGui window.");
if (ImGui::Button("Close")) {
running = false; // Close button clicked
}
ImGui::End();
// Display FPS in the ImGui window
ImGui::Begin("FPS Counter");
ImGui::Text("Current FPS: %.2f", fps);
// Frame time graph
ImGui::PlotLines("##FrameTime", frame_time_graph, 100, 0, "Frame Time (ms)", 0.0f, 0.1f, ImVec2(200, 80));
ImGui::Text("Current Time: %u ms", current_time);
ImGui::End();
// ImGui frame
imgui_frame();
// Update the projection and view matrices
projectionMatrix = glm::perspective(glm::radians(fov), (float)window_width / (float)window_height, 0.1f, 100.0f);
camera_front = glm::vec3(
cos(glm::radians(camera_yaw)) * cos(glm::radians(camera_pitch)),
sin(glm::radians(camera_pitch)),
sin(glm::radians(camera_yaw)) * cos(glm::radians(camera_pitch))
);
viewMatrix = glm::lookAt(camera_position, camera_position + camera_front, camera_up);
// Render
ImGui::Render();
glViewport(0, 0, (int)(window_width * main_scale), (int)(window_height * main_scale));
glClearColor(0.45f, 0.55f, 0.60f, 1.00f);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use the shader program
shader_program.use();
shader_program.setMat4("view", viewMatrix); // Set the view matrix
shader_program.setMat4("projection", projectionMatrix); // Set the projection matrix
shader_program.setMat4("model", modelMatrix); // Set the model matrix
texture1.bind(0); // Bind texture 1 to unit 0
texture2.bind(1); // Bind texture 2 to unit 1
object.draw(); // Draw the object
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
SDL_GL_SwapWindow(window);
// Calculate FPS
current_time = SDL_GetTicks();
frame_time = (current_time - last_time) / 1000.0f; // Convert milliseconds to seconds
fps = 1.0f / frame_time;
last_time = current_time;
// Update frame time graph
for (int i = 99; i > 0; --i) {
frame_time_graph[i] = frame_time_graph[i - 1]; // Shift old values
}
frame_time_graph[0] = frame_time; // Add new frame time
calc_frame_time();
}
// Cleanup
cleanup();
cleanup_imgui();
cleanup_opengl();
cleanup_sdl();
std::cout << "Application exited successfully." << std::endl;
return 0; // Exit code
}

97
src/shader.cpp Normal file
View File

@@ -0,0 +1,97 @@
#include "shader.hpp"
Shader::Shader(const char* vertexPath, const char* fragmentPath) {
// Load and compile vertex shader
unsigned int shader = glCreateShader(GL_VERTEX_SHADER);
if (shader == 0) {
std::cerr << "Failed to create shader." << std::endl;
}
const char* vertex_shader_source = read_file(vertexPath);
glShaderSource(shader, 1, &vertex_shader_source, nullptr);
glCompileShader(shader);
// Check for vertex shader compilation errors
int success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
char info_log[512];
glGetShaderInfoLog(shader, sizeof(info_log), nullptr, info_log);
std::cerr << "Vertex shader compilation error: " << info_log << std::endl;
glDeleteShader(shader);
}
// Load and compile fragment shader
unsigned int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
if (fragment_shader == 0) {
std::cerr << "Failed to create shader." << std::endl;
}
const char* fragment_shader_source = read_file(fragmentPath);
glShaderSource(fragment_shader, 1, &fragment_shader_source, nullptr);
glCompileShader(fragment_shader);
// Check for fragment shader compilation errors
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
if (!success) {
char info_log[512];
glGetShaderInfoLog(fragment_shader, sizeof(info_log), nullptr, info_log);
std::cerr << "Fragment shader compilation error: " << info_log << std::endl;
glDeleteShader(fragment_shader);
}
// Create shader program
ID = glCreateProgram();
if (ID == 0) {
std::cerr << "Failed to create shader program." << std::endl;
}
glAttachShader(ID, shader);
glAttachShader(ID, fragment_shader);
glLinkProgram(ID);
// Check for linking errors
glGetProgramiv(ID, GL_LINK_STATUS, &success);
if (!success) {
char info_log[512];
glGetProgramInfoLog(ID, sizeof(info_log), nullptr, info_log);
std::cerr << "Shader program linking error: " << info_log << std::endl;
glDeleteProgram(ID);
ID = 0; // Reset ID to indicate failure
}
// Clean up shaders as they are no longer needed
glDeleteShader(shader);
glDeleteShader(fragment_shader);
}
void Shader::use() const {
if (ID != 0) {
glUseProgram(ID);
} else {
std::cerr << "Shader program not initialized." << std::endl;
}
}
void Shader::setBool(const std::string &name, bool value) const {
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}
void Shader::setInt(const std::string &name, int value) const {
glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}
void Shader::setFloat(const std::string &name, float value) const {
glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}
void Shader::setMat4(const std::string &name, const glm::mat4 &mat) const {
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
Shader::~Shader() {
if (ID != 0) {
glDeleteProgram(ID);
ID = 0; // Reset ID to indicate the shader program has been deleted
}
}

68
src/texture.cpp Normal file
View File

@@ -0,0 +1,68 @@
#include "texture.hpp"
void flip_surface(SDL_Surface* surface) {
if (!surface) {
std::cerr << "Surface is null, cannot flip" << std::endl;
return;
}
int pitch = surface->pitch;
Uint8* pixels = static_cast<Uint8*>(surface->pixels);
int height = surface->h;
for (int y = 0; y < height / 2; ++y) {
Uint8* top_row = pixels + y * pitch;
Uint8* bottom_row = pixels + (height - y - 1) * pitch;
for (int x = 0; x < pitch; ++x) {
std::swap(top_row[x], bottom_row[x]);
}
}
}
Texture::Texture(const char* file_path) {
ID = 0;
SDL_Surface* surface = IMG_Load(file_path);
if (!surface) {
std::cerr << "Failed to load texture: " << SDL_GetError() << std::endl;
return; // Texture loading failed
}
GLenum format = (surface->format == SDL_PIXELFORMAT_RGBA32) ? GL_RGBA : GL_RGB;
flip_surface(surface); // Flip the surface vertically
glGenTextures(1, &ID);
glBindTexture(GL_TEXTURE_2D, ID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, format, surface->w, surface->h, 0, format, GL_UNSIGNED_BYTE, surface->pixels);
glGenerateMipmap(GL_TEXTURE_2D);
SDL_DestroySurface(surface); // Free the surface after uploading texture data
}
Texture::~Texture() {
if (ID != 0) {
glDeleteTextures(1, &ID);
}
}
void Texture::bind() const {
glBindTexture(GL_TEXTURE_2D, ID);
}
void Texture::bind(unsigned int unit) const {
if (unit >= GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS) {
std::cerr << "Texture unit out of range: " << unit << std::endl;
return; // Invalid texture unit
}
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_2D, ID);
}
void Texture::unbind() const {
glBindTexture(GL_TEXTURE_2D, 0);
}

24
src/utils.cpp Normal file
View File

@@ -0,0 +1,24 @@
#include "utils.hpp"
char* read_file(const char* file_path) {
std::ifstream file(file_path);
if (!file) {
std::cerr << "Could not open file: " << file_path << std::endl;
return nullptr; // Return null if file cannot be opened
}
file.seekg(0, std::ios::end);
size_t file_size = file.tellg();
file.seekg(0, std::ios::beg);
char* buffer = new char[file_size + 1];
if (!buffer) {
std::cerr << "Memory allocation failed" << std::endl;
return nullptr;
}
file.read(buffer, file_size);
buffer[file_size] = '\0'; // Null-terminate the string
return buffer;
}

39
src/window.cpp Normal file
View File

@@ -0,0 +1,39 @@
#include "window.hpp"
// Variables
float main_scale;
SDL_Window* window;
SDL_Event event;
int window_width = 850; // Default window width
int window_height = 850; // Default window height
// Functions
int initialize_sdl() {
// Initialize SDL
if (!SDL_Init(SDL_INIT_VIDEO)) {
std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
return 1; // Initialization failed
}
main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
window = SDL_CreateWindow("Untitled", (int)(window_width * main_scale), (int)(window_height * main_scale), window_flags);
if (!window) {
std::cerr << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1; // Window creation failed
}
return 0; // Initialization successful
}
void cleanup_sdl() {
if (window) {
// Destroy window
SDL_DestroyWindow(window);
window = nullptr;
}
// Quit SDL
SDL_Quit();
std::cout << "SDL cleanup successful." << std::endl;
}