afegits altres shaders
pantalla completa tecla esc readme.md
This commit is contained in:
328
src/main.cpp
328
src/main.cpp
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user