afegits altres shaders

pantalla completa
tecla esc
readme.md
This commit is contained in:
2025-10-21 18:38:43 +02:00
parent bcaa64d22c
commit 4a339c09d1
7 changed files with 592 additions and 105 deletions

View File

@@ -1,11 +1,42 @@
// src/main.cpp
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <type_traits>
#include <filesystem>
#include <SDL3/SDL.h>
#include <glad/glad.h>
// Vertex shader: genera posiciones de pantalla y una coordenada uv en [0,1]
static const char *vertexShaderSrc = R"glsl(
// Simple logger compatible con el estilo que usas
struct Logger {
static void info(const std::string& s) { std::cout << "[INFO] " << s << '\n'; }
static void error(const std::string& s) { std::cerr << "[ERROR] " << s << '\n'; }
};
// Opciones mínimas parecidas a las tuyas
struct VideoOptions {
bool fullscreen = false;
} Options_video;
// Estructura para guardar info del display
struct DisplayMonitor {
std::string name;
int width = 0;
int height = 0;
int refresh_rate = 0;
};
// Globales simplificados (tu proyecto puede integrarlo en clases)
static DisplayMonitor display_monitor_;
static SDL_Window* window_ = nullptr;
// Constante por defecto del fragment shader
static constexpr const char* DEFAULT_FRAG = "shaders/test.frag.glsl";
// Vertex shader embebido
static const char* vertexShaderSrc = R"glsl(
#version 330 core
layout(location = 0) in vec2 aPos;
out vec2 vUV;
@@ -15,146 +46,230 @@ void main() {
}
)glsl";
// Fragment shader: adapta tu shader de Shadertoy
static const char *fragmentShaderSrc = R"glsl(
#version 330 core
out vec4 FragColor;
in vec2 vUV;
uniform vec2 iResolution;
uniform float iTime;
vec3 palette( float t) {
vec3 a = vec3(1.0, 0.5, 0.5);
vec3 b = vec3(1.0, 0.5, 0.5);
vec3 c = vec3(1.0, 1.0, 1.0);
vec3 d = vec3(0.263, 0.416, 0.557);
return a + b * cos( 6.28318 * (c * t * d) );
// Helpers de carga
static bool loadFileToString(const std::filesystem::path& path, std::string& out) {
std::ifstream ifs(path, std::ios::in | std::ios::binary);
if (!ifs) return false;
std::ostringstream ss;
ss << ifs.rdbuf();
out = ss.str();
return true;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
float d = length(uv);
vec3 col = palette(d);
d = sin(d * 8.0 + iTime) / 8.0;
d = abs(d);
d = 0.02 / d;
col *= d;
fragColor = vec4(col, 1.0);
}
void main() {
vec2 fragCoordPixels = vUV * iResolution;
vec4 outColor;
mainImage(outColor, fragCoordPixels);
FragColor = outColor;
}
)glsl";
// helpers
static GLuint compileShader(GLenum type, const char *src)
{
static GLuint compileShader(GLenum type, const char* src) {
GLuint s = glCreateShader(type);
glShaderSource(s, 1, &src, nullptr);
glCompileShader(s);
GLint ok = 0;
glGetShaderiv(s, GL_COMPILE_STATUS, &ok);
if (!ok)
{
if (!ok) {
GLint len = 0;
glGetShaderiv(s, GL_INFO_LOG_LENGTH, &len);
std::string log(len, ' ');
std::string log(len > 0 ? len : 1, ' ');
glGetShaderInfoLog(s, len, nullptr, &log[0]);
std::cerr << "Shader compile error: " << log << '\n';
Logger::error("Shader compile error: " + log);
glDeleteShader(s);
return 0;
}
return s;
}
static GLuint linkProgram(GLuint vs, GLuint fs)
{
static GLuint linkProgram(GLuint vs, GLuint fs) {
GLuint p = glCreateProgram();
glAttachShader(p, vs);
glAttachShader(p, fs);
glLinkProgram(p);
GLint ok = 0;
glGetProgramiv(p, GL_LINK_STATUS, &ok);
if (!ok)
{
if (!ok) {
GLint len = 0;
glGetProgramiv(p, GL_INFO_LOG_LENGTH, &len);
std::string log(len, ' ');
std::string log(len > 0 ? len : 1, ' ');
glGetProgramInfoLog(p, len, nullptr, &log[0]);
std::cerr << "Program link error: " << log << '\n';
Logger::error("Program link error: " + log);
glDeleteProgram(p);
return 0;
}
return p;
}
int main(int argc, char **argv)
{
if (!SDL_Init(SDL_INIT_VIDEO))
{
std::cerr << "SDL_Init error: " << SDL_GetError() << '\n';
return -1;
// --- Funciones basadas en tu código ---
void getDisplayInfo() {
int num_displays = 0;
SDL_DisplayID* displays = SDL_GetDisplays(&num_displays);
if (displays != nullptr && num_displays > 0) {
for (int i = 0; i < num_displays; ++i) {
SDL_DisplayID instance_id = displays[i];
const char* name = SDL_GetDisplayName(instance_id);
Logger::info(std::string("Display ") + std::to_string(instance_id) + ": " + (name != nullptr ? name : "Unknown"));
}
const SDL_DisplayMode* dm = SDL_GetCurrentDisplayMode(displays[0]);
const char* first_display_name = SDL_GetDisplayName(displays[0]);
display_monitor_.name = (first_display_name != nullptr) ? first_display_name : "Unknown";
if (dm) {
display_monitor_.width = static_cast<int>(dm->w);
display_monitor_.height = static_cast<int>(dm->h);
display_monitor_.refresh_rate = static_cast<int>(dm->refresh_rate);
} else {
Logger::info("SDL_GetCurrentDisplayMode returned null");
}
} else {
Logger::info("No displays found or SDL_GetDisplays failed");
}
}
void setFullscreenMode() {
// SDL3: la API acepta un bool para fullscreen (true = fullscreen desktop / exclusive depending on param)
// En tu repos tienes Options::video.fullscreen (bool), así lo usamos:
if (!window_) return;
// Si se pide fullscreen = true, preferimos fullscreen exclusivo si se puede ajustar tamaño
if (Options_video.fullscreen) {
// Si conocemos la resolución nativa, forzamos tamaño de ventana y pedimos fullscreen exclusivo
if (display_monitor_.width > 0 && display_monitor_.height > 0) {
SDL_SetWindowSize(window_, display_monitor_.width, display_monitor_.height);
// SDL3 acepta SDL_SetWindowFullscreen(window, true) para fullscreen; algunos drivers pueden ofrecer exclusive/fullscreen desktop.
if (SDL_SetWindowFullscreen(window_, true) != 0) {
// fallback: intentar fullscreen desktop (true funciona como desktop fullscreen en muchas implementaciones)
Logger::info("SDL_SetWindowFullscreen(exclusive) failed, fallback to fullscreen desktop");
SDL_SetWindowFullscreen(window_, true); // ya es el mismo en SDL3; dejamos registro
}
} else {
// desconocemos resolución, pedimos fullscreen desktop
SDL_SetWindowFullscreen(window_, true);
}
} else {
// volver a ventana
SDL_SetWindowFullscreen(window_, false);
}
}
void toggleFullscreen() {
Options_video.fullscreen = !Options_video.fullscreen;
setFullscreenMode();
}
// Manejo de teclas de debug (adaptado a tu estilo)
void handleDebugEvents(const SDL_Event& event) {
// evitar repetición de teclas: event.key.repeat disponible en SDL3
if (event.type == SDL_EVENT_KEY_DOWN && static_cast<int>(event.key.repeat) == 0) {
switch (event.key.key) {
case SDLK_1: {
Logger::info("Key 1 pressed (action placeholder)");
break;
}
case SDLK_2: {
static bool deploy_balloons_ = true;
deploy_balloons_ = !deploy_balloons_;
Logger::info(std::string("Toggle balloons: ") + (deploy_balloons_ ? "on" : "off"));
break;
}
case SDLK_F11: {
toggleFullscreen();
break;
}
default:
break;
}
}
}
// --- main (integra todo y soporta -F y argv[1] para shader path) ---
int main(int argc, char** argv) {
std::string shaderPath;
bool fullscreenFlag = false;
for (int i = 1; i < argc; ++i) {
std::string a = argv[i];
if (a == "-F" || a == "--fullscreen") { fullscreenFlag = true; continue; }
if (shaderPath.empty()) shaderPath = a;
}
if (shaderPath.empty()) shaderPath = DEFAULT_FRAG;
Options_video.fullscreen = fullscreenFlag;
// Inicializar SDL3
auto initResult = SDL_Init(SDL_INIT_VIDEO);
if constexpr (std::is_same_v<decltype(initResult), bool>) {
if (!initResult) { Logger::error(SDL_GetError()); return -1; }
} else {
if (initResult != 0) { Logger::error(SDL_GetError()); return -1; }
}
// Pedir contexto OpenGL 3.3 Core
// Obtener información del display antes de crear ventana
getDisplayInfo();
// Atributos GL
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);
// Crear ventana
int winW = 800, winH = 800;
// SDL3: SDL_CreateWindow signature es (title, w, h, flags)
SDL_Window *window = SDL_CreateWindow("Shadertoy SDL3 + OpenGL",
winW, winH,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (!window)
{
std::cerr << "SDL_CreateWindow error: " << SDL_GetError() << '\n';
window_ = SDL_CreateWindow("Shadertoy SDL3 + OpenGL", winW, winH, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (!window_) { Logger::error(std::string("SDL_CreateWindow error: ") + SDL_GetError()); SDL_Quit(); return -1; }
// Aplicar fullscreen si el flag estaba activado
setFullscreenMode();
// Crear contexto GL
SDL_GLContext glContext = SDL_GL_CreateContext(window_);
if (!glContext) {
Logger::error(std::string("SDL_GL_CreateContext error: ") + SDL_GetError());
SDL_DestroyWindow(window_);
SDL_Quit();
return -1;
}
SDL_GLContext glContext = SDL_GL_CreateContext(window);
if (!glContext)
{
std::cerr << "SDL_GL_CreateContext error: " << SDL_GetError() << '\n';
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
{
std::cerr << "Failed to initialize GL loader\n";
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) {
Logger::error("Failed to initialize GL loader");
SDL_GL_DestroyContext(glContext);
SDL_DestroyWindow(window);
SDL_DestroyWindow(window_);
SDL_Quit();
return -1;
}
// Localizar y cargar el fragment shader (intenta rutas comunes)
std::vector<std::filesystem::path> candidates;
candidates.emplace_back(shaderPath);
candidates.emplace_back(std::filesystem::path("..") / shaderPath);
candidates.emplace_back(std::filesystem::path(".") / shaderPath);
if (argc > 0 && argv[0]) {
std::filesystem::path exe = argv[0];
if (exe.has_parent_path()) {
candidates.emplace_back(exe.parent_path() / shaderPath);
candidates.emplace_back(exe.parent_path() / ".." / shaderPath);
}
}
std::string fragSrc;
std::filesystem::path found;
for (auto &p : candidates) {
if (loadFileToString(p, fragSrc)) { found = p; break; }
}
if (found.empty()) {
Logger::error("Failed to load fragment shader file. Tried paths:");
for (auto &p : candidates) Logger::error(" " + p.string());
SDL_GL_DestroyContext(glContext);
SDL_DestroyWindow(window_);
SDL_Quit();
return -1;
}
Logger::info("Loaded fragment shader from: " + found.string());
GLuint vs = compileShader(GL_VERTEX_SHADER, vertexShaderSrc);
GLuint fs = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSrc);
if (!vs || !fs)
return -1;
GLuint fs = compileShader(GL_FRAGMENT_SHADER, fragSrc.c_str());
if (!vs || !fs) { SDL_GL_DestroyContext(glContext); SDL_DestroyWindow(window_); SDL_Quit(); return -1; }
GLuint program = linkProgram(vs, fs);
glDeleteShader(vs);
glDeleteShader(fs);
if (!program)
return -1;
if (!program) { SDL_GL_DestroyContext(glContext); SDL_DestroyWindow(window_); SDL_Quit(); return -1; }
// Quad setup
float quadVertices[] = {
-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 vao = 0, vbo = 0;
@@ -164,7 +279,7 @@ int main(int argc, char **argv)
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
@@ -174,28 +289,30 @@ int main(int argc, char **argv)
bool running = true;
Uint32 startTicks = SDL_GetTicks();
while (running)
{
while (running) {
SDL_Event e;
while (SDL_PollEvent(&e))
{
if (e.type == SDL_EVENT_QUIT)
running = false;
if (e.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED)
running = false;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_EVENT_QUIT) running = false;
else if (e.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) running = false;
else if (e.type == SDL_EVENT_KEY_DOWN) {
// Escape cierra la app
if (e.key.key == SDLK_ESCAPE) running = false;
// handle your debug keys
handleDebugEvents(e);
} else if (e.type == SDL_EVENT_WINDOW_RESIZED) {
// opcional: podrías actualizar algo con new size
}
}
int w, h;
SDL_GetWindowSize(window, &w, &h);
SDL_GetWindowSize(window_, &w, &h);
glViewport(0, 0, w, h);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
if (locRes >= 0)
glUniform2f(locRes, float(w), float(h));
if (locTime >= 0)
{
if (locRes >= 0) glUniform2f(locRes, float(w), float(h));
if (locTime >= 0) {
float t = (SDL_GetTicks() - startTicks) / 1000.0f;
glUniform1f(locTime, t);
}
@@ -204,16 +321,17 @@ int main(int argc, char **argv)
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
SDL_GL_SwapWindow(window);
SDL_GL_SwapWindow(window_);
SDL_Delay(1);
}
// Cleanup
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
glDeleteProgram(program);
SDL_GL_DestroyContext(glContext);
SDL_DestroyWindow(window);
SDL_DestroyWindow(window_);
SDL_Quit();
return 0;
}