Compare commits

2 Commits

Author SHA1 Message Date
9db902c024 netejat codi mort en screen.cpp 2025-10-16 13:29:25 +02:00
7fe2523221 fix: ja funcionen els shaders 2025-10-16 12:46:02 +02:00
6 changed files with 122 additions and 163 deletions

View File

@@ -59,14 +59,11 @@ Director::Director(int argc, const char* argv[]) {
// Carga las opciones desde un fichero // Carga las opciones desde un fichero
loadOptionsFromFile(Asset::get()->get("config.txt")); loadOptionsFromFile(Asset::get()->get("config.txt"));
// Inicializa SDL
initSDL();
// Inicializa JailAudio // Inicializa JailAudio
initJailAudio(); initJailAudio();
// Crea los objetos // Crea los objetos
Screen::init(window_, renderer_); Screen::init();
SDL_HideCursor(); SDL_HideCursor();
Resource::init(); Resource::init();
Notifier::init("", "8bithud"); Notifier::init("", "8bithud");
@@ -90,8 +87,6 @@ Director::~Director() {
Screen::destroy(); Screen::destroy();
Asset::destroy(); Asset::destroy();
SDL_DestroyRenderer(renderer_);
SDL_DestroyWindow(window_);
SDL_Quit(); SDL_Quit();
std::cout << "\nBye!" << std::endl; std::cout << "\nBye!" << std::endl;
@@ -256,77 +251,6 @@ void Director::initJailAudio() {
} }
} }
// Arranca SDL y crea la ventana
bool Director::initSDL() {
// Indicador de éxito
bool success = true;
// Inicializa SDL
if (!SDL_Init(SDL_INIT_VIDEO)) {
if (options.console) {
std::cout << "SDL could not initialize!\nSDL Error: " << SDL_GetError() << std::endl;
}
success = false;
} else {
// Inicia el generador de numeros aleatorios
std::srand(static_cast<unsigned int>(SDL_GetTicks()));
// Activa el render OpenGL
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl")) {
std::cout << "Warning: opengl not enabled!\n";
}
// Crea la ventana
const auto WINDOW_WIDTH = options.video.border.enabled ? options.game.width + options.video.border.width * 2 : options.game.width;
const auto WINDOW_HEIGHT = options.video.border.enabled ? options.game.height + options.video.border.height * 2 : options.game.height;
#ifdef __APPLE__
SDL_WindowFlags window_flags = SDL_WINDOW_METAL;
#else
SDL_WindowFlags window_flags = SDL_WINDOW_OPENGL;
#endif
if (options.video.fullscreen) {
window_flags |= SDL_WINDOW_FULLSCREEN;
}
window_ = SDL_CreateWindow(WINDOW_CAPTION, WINDOW_WIDTH * options.window.zoom, WINDOW_HEIGHT * options.window.zoom, window_flags);
if (window_ == nullptr) {
if (options.console) {
std::cout << "Window could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
success = false;
} else {
// Crea un renderizador para la ventana. El vsync se activa en funcion de las opciones
renderer_ = SDL_CreateRenderer(window_, nullptr);
if (renderer_ == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"FATAL: Failed to create renderer! SDL Error: %s",
SDL_GetError());
SDL_DestroyWindow(window_);
window_ = nullptr;
SDL_Quit();
return false;
} else {
// Configurar renderer
const int EXTRA_WIDTH = options.video.border.enabled ? options.video.border.width * 2 : 0;
const int EXTRA_HEIGHT = options.video.border.enabled ? options.video.border.height * 2 : 0;
SDL_SetRenderLogicalPresentation(
renderer_,
options.game.width + EXTRA_WIDTH,
options.game.height + EXTRA_HEIGHT,
options.video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX);
SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
SDL_SetRenderVSync(renderer_, options.video.vertical_sync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
}
}
}
if (options.console) {
std::cout << std::endl;
}
return success;
}
// Crea el indice de ficheros // Crea el indice de ficheros
bool Director::setFileList() { bool Director::setFileList() {
#ifdef MACOS_BUNDLE #ifdef MACOS_BUNDLE

View File

@@ -6,10 +6,6 @@
class Director { class Director {
private: private:
// Objetos y punteros
SDL_Window* window_; // La ventana donde dibujamos
SDL_Renderer* renderer_; // El renderizador de la ventana
// Variables // Variables
std::string executable_path_; // Path del ejecutable std::string executable_path_; // Path del ejecutable
std::string system_folder_; // Carpeta del sistema donde guardar datos std::string system_folder_; // Carpeta del sistema donde guardar datos
@@ -23,10 +19,7 @@ class Director {
// Inicializa jail_audio // Inicializa jail_audio
void initJailAudio(); void initJailAudio();
// Arranca SDL y crea la ventana // Inicializa el objeto Input
bool initSDL();
// Inicializa el objeto Input
void initInput(); void initInput();
// Crea el indice de ficheros // Crea el indice de ficheros

View File

@@ -208,8 +208,9 @@ struct OptionsStats {
// Estructura con opciones de la ventana // Estructura con opciones de la ventana
struct OptionsWindow { struct OptionsWindow {
int zoom; // Zoom de la ventana std::string caption = "JailDoctor's Dilemma"; // Texto que aparece en la barra de título de la ventana
int max_zoom; // Máximo tamaño de zoom para la ventana int zoom; // Zoom de la ventana
int max_zoom; // Máximo tamaño de zoom para la ventana
// Constructor por defecto // Constructor por defecto
OptionsWindow() OptionsWindow()

View File

@@ -46,7 +46,6 @@ void Resource::clear() {
// Carga todos los recursos // Carga todos los recursos
void Resource::load() { void Resource::load() {
calculateTotal(); calculateTotal();
Screen::get()->show();
Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK)); Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK));
std::cout << "** LOADING RESOURCES" << std::endl; std::cout << "** LOADING RESOURCES" << std::endl;
loadSounds(); loadSounds();

View File

@@ -22,8 +22,8 @@
Screen* Screen::screen_ = nullptr; Screen* Screen::screen_ = nullptr;
// [SINGLETON] Crearemos el objeto con esta función estática // [SINGLETON] Crearemos el objeto con esta función estática
void Screen::init(SDL_Window* window, SDL_Renderer* renderer) { void Screen::init() {
Screen::screen_ = new Screen(window, renderer); Screen::screen_ = new Screen();
} }
// [SINGLETON] Destruiremos el objeto con esta función estática // [SINGLETON] Destruiremos el objeto con esta función estática
@@ -37,16 +37,14 @@ Screen* Screen::get() {
} }
// Constructor // Constructor
Screen::Screen(SDL_Window* window, SDL_Renderer* renderer) Screen::Screen()
: window_(window), : palettes_(Asset::get()->getListByType(AssetType::PALETTE)) {
renderer_(renderer), // Arranca SDL VIDEO, crea la ventana y el renderizador
palettes_(Asset::get()->getListByType(AssetType::PALETTE)) { initSDLVideo();
// Inicializa variables
getDisplayInfo();
// Ajusta los tamaños // Ajusta los tamaños
game_surface_dstrect_ = {options.video.border.width, options.video.border.height, options.game.width, options.game.height}; game_surface_dstrect_ = {options.video.border.width, options.video.border.height, options.game.width, options.game.height};
adjustWindowSize(); //adjustWindowSize();
current_palette_ = findPalette(options.video.palette); current_palette_ = findPalette(options.video.palette);
// Define el color del borde para el modo de pantalla completa // Define el color del borde para el modo de pantalla completa
@@ -72,18 +70,6 @@ Screen::Screen(SDL_Window* window, SDL_Renderer* renderer)
} }
SDL_SetTextureScaleMode(border_texture_, SDL_SCALEMODE_NEAREST); SDL_SetTextureScaleMode(border_texture_, SDL_SCALEMODE_NEAREST);
// Crea la textura para los shaders
const int EXTRA_WIDTH = options.video.border.enabled ? options.video.border.width * 2 : 0;
const int EXTRA_HEIGHT = options.video.border.enabled ? options.video.border.height * 2 : 0;
shaders_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, options.game.width + EXTRA_WIDTH, options.game.height + EXTRA_HEIGHT);
if (!shaders_texture_) {
// Registrar el error si está habilitado
if (options.console) {
std::cerr << "Error: shaders_texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
SDL_SetTextureScaleMode(shaders_texture_, SDL_SCALEMODE_NEAREST);
// Crea la surface donde se dibujan los graficos del juego // Crea la surface donde se dibujan los graficos del juego
game_surface_ = std::make_shared<Surface>(options.game.width, options.game.height); game_surface_ = std::make_shared<Surface>(options.game.width, options.game.height);
game_surface_->setPalette(readPalFile(palettes_.at(current_palette_))); game_surface_->setPalette(readPalFile(palettes_.at(current_palette_)));
@@ -97,21 +83,22 @@ Screen::Screen(SDL_Window* window, SDL_Renderer* renderer)
// Establece la surface que actuará como renderer para recibir las llamadas a render() // Establece la surface que actuará como renderer para recibir las llamadas a render()
renderer_surface_ = std::make_shared<std::shared_ptr<Surface>>(game_surface_); renderer_surface_ = std::make_shared<std::shared_ptr<Surface>>(game_surface_);
// Establece el modo de video
setVideoMode(options.video.fullscreen);
// Muestra la ventana
show();
// Extrae el nombre de las paletas desde su ruta // Extrae el nombre de las paletas desde su ruta
processPaletteList(); processPaletteList();
// Renderizar una vez la textura vacía para que tenga contenido válido
// antes de inicializar los shaders (evita pantalla negra)
SDL_RenderTexture(renderer_, game_texture_, nullptr, nullptr);
SDL_RenderTexture(renderer_, border_texture_, nullptr, nullptr);
// Ahora sí inicializar los shaders
initShaders();
} }
// Destructor // Destructor
Screen::~Screen() { Screen::~Screen() {
SDL_DestroyTexture(game_texture_); SDL_DestroyTexture(game_texture_);
SDL_DestroyTexture(border_texture_); SDL_DestroyTexture(border_texture_);
SDL_DestroyTexture(shaders_texture_);
} }
// Limpia el renderer // Limpia el renderer
@@ -195,8 +182,8 @@ void Screen::setBorderColor(Uint8 color) {
// Cambia entre borde visible y no visible // Cambia entre borde visible y no visible
void Screen::toggleBorder() { void Screen::toggleBorder() {
options.video.border.enabled = !options.video.border.enabled; options.video.border.enabled = !options.video.border.enabled;
createShadersTexture();
setVideoMode(options.video.fullscreen); setVideoMode(options.video.fullscreen);
initShaders();
} }
// Dibuja las notificaciones // Dibuja las notificaciones
@@ -209,7 +196,7 @@ void Screen::renderNotifications() {
// Cambia el estado de los shaders // Cambia el estado de los shaders
void Screen::toggleShaders() { void Screen::toggleShaders() {
options.video.shaders = !options.video.shaders; options.video.shaders = !options.video.shaders;
setVideoMode(options.video.fullscreen); initShaders();
} }
// Actualiza la lógica de la clase // Actualiza la lógica de la clase
@@ -224,7 +211,6 @@ void Screen::adjustWindowSize() {
window_width_ = options.game.width + (options.video.border.enabled ? options.video.border.width * 2 : 0); window_width_ = options.game.width + (options.video.border.enabled ? options.video.border.width * 2 : 0);
window_height_ = options.game.height + (options.video.border.enabled ? options.video.border.height * 2 : 0); window_height_ = options.game.height + (options.video.border.enabled ? options.video.border.height * 2 : 0);
// Establece el nuevo tamaño // Establece el nuevo tamaño
if (options.video.fullscreen == 0) { if (options.video.fullscreen == 0) {
int old_width, old_height; int old_width, old_height;
@@ -311,9 +297,6 @@ void Screen::textureToRenderer() {
SDL_Texture* texture_to_render = options.video.border.enabled ? border_texture_ : game_texture_; SDL_Texture* texture_to_render = options.video.border.enabled ? border_texture_ : game_texture_;
if (options.video.shaders && shader_backend_) { if (options.video.shaders && shader_backend_) {
SDL_SetRenderTarget(renderer_, shaders_texture_);
SDL_RenderTexture(renderer_, texture_to_render, nullptr, nullptr);
SDL_SetRenderTarget(renderer_, nullptr);
shader_backend_->render(); shader_backend_->render();
} else { } else {
SDL_SetRenderTarget(renderer_, nullptr); SDL_SetRenderTarget(renderer_, nullptr);
@@ -342,24 +325,6 @@ size_t Screen::findPalette(const std::string& name) {
return static_cast<size_t>(0); return static_cast<size_t>(0);
} }
// Recrea la textura para los shaders
void Screen::createShadersTexture() {
if (shaders_texture_) {
SDL_DestroyTexture(shaders_texture_);
}
// Crea la textura donde se dibuja el borde que rodea el area de juego
const int EXTRA_WIDTH = options.video.border.enabled ? options.video.border.width * 2 : 0;
const int EXTRA_HEIGHT = options.video.border.enabled ? options.video.border.height * 2 : 0;
shaders_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, options.game.width + EXTRA_WIDTH, options.game.height + EXTRA_HEIGHT);
if (!shaders_texture_) {
// Registrar el error si está habilitado
if (options.console) {
std::cerr << "Error: shaders_texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
}
// Muestra información por pantalla // Muestra información por pantalla
void Screen::renderInfo() { void Screen::renderInfo() {
if (show_debug_info_ && Resource::get()) { if (show_debug_info_ && Resource::get()) {
@@ -476,7 +441,8 @@ void Screen::initShaders() {
if (!shader_backend_) { if (!shader_backend_) {
shader_backend_ = std::make_unique<Rendering::OpenGLShader>(); shader_backend_ = std::make_unique<Rendering::OpenGLShader>();
} }
shader_backend_->init(window_, game_texture_, vertex_shader_source_, fragment_shader_source_); shader_backend_->init(window_, options.video.border.enabled ? border_texture_ : game_texture_, vertex_shader_source_, fragment_shader_source_);
//shader_backend_->init(window_, shaders_texture_, vertex_shader_source_, fragment_shader_source_);
} }
#else #else
// En macOS, OpenGL está deprecated y rinde mal // En macOS, OpenGL está deprecated y rinde mal
@@ -490,19 +456,19 @@ void Screen::initShaders() {
void Screen::getDisplayInfo() { void Screen::getDisplayInfo() {
int i; int i;
int num_displays = 0; int num_displays = 0;
SDL_DisplayID *displays = SDL_GetDisplays(&num_displays); SDL_DisplayID* displays = SDL_GetDisplays(&num_displays);
if (displays != nullptr) { if (displays != nullptr) {
for (i = 0; i < num_displays; ++i) { for (i = 0; i < num_displays; ++i) {
SDL_DisplayID instance_id = displays[i]; SDL_DisplayID instance_id = displays[i];
const char *name = SDL_GetDisplayName(instance_id); const char* name = SDL_GetDisplayName(instance_id);
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Display %" SDL_PRIu32 ": %s", instance_id, (name != nullptr) ? name : "Unknown"); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Display %" SDL_PRIu32 ": %s", instance_id, (name != nullptr) ? name : "Unknown");
} }
const auto *dm = SDL_GetCurrentDisplayMode(displays[0]); const auto* dm = SDL_GetCurrentDisplayMode(displays[0]);
// Guarda información del monitor en display_monitor_ // Guarda información del monitor en display_monitor_
const char *first_display_name = SDL_GetDisplayName(displays[0]); const char* first_display_name = SDL_GetDisplayName(displays[0]);
display_monitor_.name = (first_display_name != nullptr) ? first_display_name : "Unknown"; display_monitor_.name = (first_display_name != nullptr) ? first_display_name : "Unknown";
display_monitor_.width = static_cast<int>(dm->w); display_monitor_.width = static_cast<int>(dm->w);
display_monitor_.height = static_cast<int>(dm->h); display_monitor_.height = static_cast<int>(dm->h);
@@ -529,4 +495,91 @@ void Screen::getDisplayInfo() {
SDL_free(displays); SDL_free(displays);
} }
}
// Arranca SDL VIDEO y crea la ventana
auto Screen::initSDLVideo() -> bool {
// Inicializar SDL
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"FATAL: Failed to initialize SDL_VIDEO! SDL Error: %s",
SDL_GetError());
return false;
}
// Obtener información de la pantalla
getDisplayInfo();
// Configurar hint para renderizado
#ifdef __APPLE__
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal")) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Warning: Failed to set Metal hint!");
}
#else
// Configurar hint de render driver
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl")) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Warning: Failed to set OpenGL hint!");
}
#ifdef _WIN32
// Windows: Pedir explícitamente OpenGL 3.3 Core Profile
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_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Solicitando OpenGL 3.3 Core Profile");
#else
// Linux: Dejar que SDL elija (Desktop 3.3 en PC, ES 3.0 en RPi automáticamente)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Usando OpenGL por defecto del sistema");
#endif
#endif
// Crear ventana
const auto WINDOW_WIDTH = options.video.border.enabled ? options.game.width + options.video.border.width * 2 : options.game.width;
const auto WINDOW_HEIGHT = options.video.border.enabled ? options.game.height + options.video.border.height * 2 : options.game.height;
#ifdef __APPLE__
SDL_WindowFlags window_flags = SDL_WINDOW_METAL;
#else
SDL_WindowFlags window_flags = SDL_WINDOW_OPENGL;
#endif
if (options.video.fullscreen) {
window_flags |= SDL_WINDOW_FULLSCREEN;
}
window_ = SDL_CreateWindow(options.window.caption.c_str(), WINDOW_WIDTH * options.window.zoom, WINDOW_HEIGHT * options.window.zoom, window_flags);
if (window_ == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"FATAL: Failed to create window! SDL Error: %s",
SDL_GetError());
SDL_Quit();
return false;
}
// Crear renderer
renderer_ = SDL_CreateRenderer(window_, nullptr);
if (renderer_ == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"FATAL: Failed to create renderer! SDL Error: %s",
SDL_GetError());
SDL_DestroyWindow(window_);
window_ = nullptr;
SDL_Quit();
return false;
}
// Configurar renderer
const int EXTRA_WIDTH = options.video.border.enabled ? options.video.border.width * 2 : 0;
const int EXTRA_HEIGHT = options.video.border.enabled ? options.video.border.height * 2 : 0;
SDL_SetRenderLogicalPresentation(
renderer_,
options.game.width + EXTRA_WIDTH,
options.game.height + EXTRA_HEIGHT,
options.video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX);
SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
SDL_SetRenderVSync(renderer_, options.video.vertical_sync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "** Video system initialized successfully");
return true;
} }

View File

@@ -24,7 +24,6 @@ class Screen {
// Constantes // Constantes
static constexpr int WINDOWS_DECORATIONS = 35; // Decoraciones de la ventana static constexpr int WINDOWS_DECORATIONS = 35; // Decoraciones de la ventana
struct DisplayMonitor { struct DisplayMonitor {
std::string name; std::string name;
int width; int width;
@@ -68,7 +67,6 @@ class Screen {
SDL_Renderer* renderer_; // El renderizador de la ventana SDL_Renderer* renderer_; // El renderizador de la ventana
SDL_Texture* game_texture_; // Textura donde se dibuja el juego SDL_Texture* game_texture_; // Textura donde se dibuja el juego
SDL_Texture* border_texture_; // Textura donde se dibuja el borde del juego SDL_Texture* border_texture_; // Textura donde se dibuja el borde del juego
SDL_Texture* shaders_texture_; // Textura para aplicar los shaders
std::shared_ptr<Surface> game_surface_; // Surface principal para manejar game_surface_data_ std::shared_ptr<Surface> game_surface_; // Surface principal para manejar game_surface_data_
std::shared_ptr<Surface> border_surface_; // Surface para pintar el el borde de la pantalla std::shared_ptr<Surface> border_surface_; // Surface para pintar el el borde de la pantalla
std::shared_ptr<std::shared_ptr<Surface>> renderer_surface_; // Puntero a la Surface que actua std::shared_ptr<std::shared_ptr<Surface>> renderer_surface_; // Puntero a la Surface que actua
@@ -118,27 +116,21 @@ class Screen {
// Localiza la paleta dentro del vector de paletas // Localiza la paleta dentro del vector de paletas
size_t findPalette(const std::string& name); size_t findPalette(const std::string& name);
// Recrea la textura para los shaders void initShaders(); // Inicializa los shaders
void createShadersTexture(); void loadShaders(); // Carga el contenido del archivo GLSL
void renderInfo(); // Muestra información por pantalla
void initShaders(); // Inicializa los shaders void getDisplayInfo(); // Obtiene información sobre la pantalla
void loadShaders(); // Carga el contenido del archivo GLSL auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana
// Muestra información por pantalla
void renderInfo();
// Obtiene información sobre la pantalla
void getDisplayInfo();
// Constructor // Constructor
Screen(SDL_Window* window, SDL_Renderer* renderer); Screen();
// Destructor // Destructor
~Screen(); ~Screen();
public: public:
// [SINGLETON] Crearemos el objeto con esta función estática // [SINGLETON] Crearemos el objeto con esta función estática
static void init(SDL_Window* window, SDL_Renderer* renderer); static void init();
// [SINGLETON] Destruiremos el objeto con esta función estática // [SINGLETON] Destruiremos el objeto con esta función estática
static void destroy(); static void destroy();
@@ -200,9 +192,6 @@ class Screen {
// Oculta la ventana // Oculta la ventana
void hide(); void hide();
// Obtiene el tamaño máximo de zoom posible para la ventana
int getMaxZoom();
// Establece el renderizador para las surfaces // Establece el renderizador para las surfaces
void setRendererSurface(std::shared_ptr<Surface> surface = nullptr); void setRendererSurface(std::shared_ptr<Surface> surface = nullptr);