Compare commits

..

2 Commits

Author SHA1 Message Date
63d0770b42 readme 2025-07-12 02:17:59 +01:00
ce44dfc950 pain 2025-07-12 02:12:46 +01:00
11 changed files with 428 additions and 170 deletions

45
include/graphics.hpp Normal file
View File

@ -0,0 +1,45 @@
#ifndef GRAPHICS_HPP
#define GRAPHICS_HPP
#define GL_GLEXT_PROTOTYPES
// Includes
#include "imgui.h"
#include "imgui_impl_sdl3.h"
#include "imgui_impl_opengl3.h"
#include <SDL3/SDL_opengl.h>
#include "window.hpp"
// 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;
extern ImGuiIO& io;
extern ImGuiStyle& style;
// Functions
int initialize_opengl();
void cleanup_opengl();
// ImGui
int initialize_imgui();
void cleanup_imgui();
void new_frame_imgui();
void frame_time_ui();
// Frame time calculation
void calc_frame_time();
// Shader management
unsigned int compile_shader(const char* shader_source, GLenum shader_type);
unsigned int create_program(unsigned int vertex_shader, unsigned int fragment_shader);
#endif

View File

@ -1,44 +1,16 @@
#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"
// 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();
#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

22
include/window.hpp Normal file
View File

@ -0,0 +1,22 @@
#ifndef WINDOW_HPP
#define WINDOW_HPP
// Includes
#include "iostream"
#include <SDL3/SDL.h>
// Constants
const int window_width = 800;
const int window_height = 600;
// 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;
// Functions
int initialize_sdl();
void cleanup_sdl();
#endif

View File

@ -21,6 +21,7 @@ Cus I cant think of a name and im uncreative.
# Features
- FPS counter
- !!! RGB RECTANGLE !!!
- Thats about it rly ¯\\_(ツ)\_/¯
# Requirements
@ -35,3 +36,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"

8
shaders/triangle.frag Normal file
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); // Set the fragment color to the input color
}

9
shaders/triangle.vert Normal file
View File

@ -0,0 +1,9 @@
#version 330 core
layout(location = 0) in vec3 position; // Vertex position
out vec3 color; // Output color to the fragment shader
void main() {
gl_Position = vec4(position, 1.0); // Set the position of the vertex
color = position + vec3(0.5); // Set the color based on the vertex position
}

158
src/graphics.cpp Normal file
View File

@ -0,0 +1,158 @@
#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;
}
unsigned int compile_shader(const char* shader_source, GLenum shader_type) {
unsigned int shader = glCreateShader(shader_type);
if (shader == 0) {
std::cerr << "Failed to create shader." << std::endl;
return 0; // Shader creation failed
}
glShaderSource(shader, 1, &shader_source, nullptr);
glCompileShader(shader);
// Check for 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 << "Shader compilation error: " << info_log << std::endl;
glDeleteShader(shader);
return 0; // Shader compilation failed
}
return shader; // Shader compiled successfully
}
unsigned int create_program(unsigned int vertex_shader, unsigned int fragment_shader) {
unsigned int program = glCreateProgram();
if (program == 0) {
std::cerr << "Failed to create shader program." << std::endl;
return 0; // Program creation failed
}
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
// Check for linking errors
int success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success) {
char info_log[512];
glGetProgramInfoLog(program, sizeof(info_log), nullptr, info_log);
std::cerr << "Shader program linking error: " << info_log << std::endl;
glDeleteProgram(program);
return 0; // Program linking failed
}
return program; // Program created successfully
}
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 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
}
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();
}

View File

@ -1,170 +1,135 @@
#include "main.hpp"
#include <GL/glu.h>
// Init
int initialize() {
// Initialize SDL
if (!SDL_Init(SDL_INIT_VIDEO)) {
std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
return 1; // Initialization failed
}
// 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 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 (!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
}
// 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);
}
// Destroy window
if (window) {
SDL_DestroyWindow(window);
window = nullptr;
}
// Quit SDL
SDL_Quit();
std::cout << "Cleanup successful." << std::endl;
}
// Variables
bool running = true;
// Main
int main(int argc, char* argv[]) {
// Initialize
if (initialize() != 0) {
std::cerr << "Initialization failed." << std::endl;
return -1; // Initialization failed
// Initialize SDL
if (initialize_sdl() != 0) {
std::cerr << "SDL initialization failed." << std::endl;
return 1; // SDL initialization failed
}
// Initialize OpenGL
if (initialize_opengl() != 0) {
std::cerr << "OpenGL initialization failed." << std::endl;
cleanup_sdl();
return 1; // OpenGL initialization failed
}
// Initialize ImGui
if (initialize_imgui() != 0) {
std::cerr << "ImGui initialization failed." << std::endl;
cleanup_opengl();
cleanup_sdl();
return 1; // ImGui initialization failed
}
// Triangle vertices
float vertices[] = {
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
// Vertex buffer object (VBO) and vertex array object (VAO) and element buffer object (EBO)
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO); // Generate a vertex array object
glGenBuffers(1, &VBO); // Generate a vertex buffer object
glGenBuffers(1, &EBO); // Generate an element 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
// Upload vertex data to the buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Set up vertex attributes
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0); // Unbind the vertex array object
// Load shaders
const char* vertex_shader_source = read_file("shaders/triangle.vert");
const char* fragment_shader_source = read_file("shaders/triangle.frag");
unsigned int vertex_shader = compile_shader(vertex_shader_source, GL_VERTEX_SHADER);
unsigned int fragment_shader = compile_shader(fragment_shader_source, GL_FRAGMENT_SHADER);
unsigned int shader_program = create_program(vertex_shader, fragment_shader);
// Set the shader program
glUseProgram(shader_program);
// Wireframe toggle
bool wireframe_mode = false;
// Main loop
running = true;
last_time = SDL_GetTicks();
while (running) {
// Handle events
while (SDL_PollEvent(&event)) {
ImGui_ImplSDL3_ProcessEvent(&event);
ImGui_ImplSDL3_ProcessEvent(&event); // Process ImGui events
if (event.type == SDL_EVENT_QUIT) {
running = false; // Exit loop on quit event
}
}
// Start the ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
new_frame_imgui();
// 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
// Frame time UI
frame_time_ui();
// Toggle wireframe mode ui
ImGui::Begin("Wireframe Mode");
if (ImGui::Checkbox("Enable 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();
// 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();
// 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);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO); // Bind the vertex array object
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // Draw the triangles
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();
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glDeleteProgram(shader_program);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
free((void*)vertex_shader_source);
free((void*)fragment_shader_source);
cleanup_imgui();
cleanup_opengl();
cleanup_sdl();
std::cout << "Application exited successfully." << std::endl;
return 0; // Exit code
}

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;
}

37
src/window.cpp Normal file
View File

@ -0,0 +1,37 @@
#include "window.hpp"
// Variables
float main_scale;
SDL_Window* window;
SDL_Event event;
// 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;
}