Acabat de repasar jail_shader.cpp

This commit is contained in:
2025-03-16 09:39:24 +01:00
parent 96680dae0f
commit e7359a1467
3 changed files with 94 additions and 88 deletions

View File

@@ -1,8 +1,8 @@
#include "jail_shader.h"
#include <SDL2/SDL.h> // para SDL_Point
#include <stdlib.h> // para NULL, free, malloc, exit
#include <string.h> // para strncmp
#include <iostream> // para basic_ostream, char_traits, operator<<
#include <cstdlib> // para NULL, free, malloc, exit
#include <cstring> // para strncmp
#include <iostream> // para std::cout, std::endl
#ifdef __APPLE__
#include "CoreFoundation/CoreFoundation.h"
@@ -10,10 +10,11 @@
#if ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#include <OpenGL/gl3.h>
#else // NOT ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#else // NO ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#include <OpenGL/gl.h>
#endif // ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#else // NOT __APPLE__
#else // SI NO ES __APPLE__
#include <SDL2/SDL_opengl.h>
#endif // __APPLE__
@@ -25,12 +26,10 @@ namespace shader
SDL_Texture *backBuffer = nullptr;
SDL_Point win_size = {320 * 4, 256 * 4};
SDL_Point tex_size = {320, 256};
bool usingOpenGL;
bool usingOpenGL = false;
#ifndef __APPLE__
// I'm avoiding the use of GLEW or some extensions handler, but that
// doesn't mean you should...
// Declaración de funciones de extensión de OpenGL (evitando GLEW)
PFNGLCREATESHADERPROC glCreateShader;
PFNGLSHADERSOURCEPROC glShaderSource;
PFNGLCOMPILESHADERPROC glCompileShader;
@@ -66,119 +65,125 @@ namespace shader
glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog &&
glUseProgram;
}
#endif
GLuint compileShader(const char *source, GLuint shaderType)
// Función para compilar un shader a partir de un std::string
GLuint compileShader(const std::string &source, GLuint shaderType)
{
// Create ID for shader
GLuint result = glCreateShader(shaderType);
// Add define depending on shader type
const char *sources[2] = {shaderType == GL_VERTEX_SHADER ? "#define VERTEX\n" : "#define FRAGMENT\n", source};
// Define shader text
glShaderSource(result, 2, sources, nullptr);
// Compile shader
glCompileShader(result);
// Check vertex shader for errors
GLint shaderCompiled = GL_FALSE;
glGetShaderiv(result, GL_COMPILE_STATUS, &shaderCompiled);
if (shaderCompiled != GL_TRUE)
if (source.empty())
{
std::cout << "Error en la compilación: " << result << "!" << std::endl;
GLint logLength;
glGetShaderiv(result, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(result, logLength, &logLength, log);
std::cout << "Shader compile log:" << log << std::endl;
free(log);
}
glDeleteShader(result);
result = 0;
throw std::runtime_error("ERROR FATAL: El código fuente del shader está vacío.");
}
return result;
// Crear identificador del shader
GLuint resultado = glCreateShader(shaderType);
// Agregar una directiva según el tipo de shader
std::string directiva = (shaderType == GL_VERTEX_SHADER)
? "#define VERTEX\n"
: "#define FRAGMENT\n";
const char *sources[2] = {directiva.c_str(), source.c_str()};
// Especificar el código fuente del shader
glShaderSource(resultado, 2, sources, nullptr);
// Compilar el shader
glCompileShader(resultado);
// Verificar si la compilación fue exitosa
GLint compiladoCorrectamente = GL_FALSE;
glGetShaderiv(resultado, GL_COMPILE_STATUS, &compiladoCorrectamente);
if (compiladoCorrectamente != GL_TRUE)
{
std::cout << "Error en la compilación del shader (" << resultado << ")!" << std::endl;
GLint longitudLog;
glGetShaderiv(resultado, GL_INFO_LOG_LENGTH, &longitudLog);
if (longitudLog > 0)
{
std::vector<GLchar> log(longitudLog);
glGetShaderInfoLog(resultado, longitudLog, &longitudLog, log.data());
std::cout << "Registro de compilación del shader: " << log.data() << std::endl;
}
glDeleteShader(resultado);
resultado = 0;
}
return resultado;
}
GLuint compileProgram(const char *vertexShaderSource, const char *fragmentShaderSource)
// Función para compilar un programa de shaders (vertex y fragment) a partir de std::string
GLuint compileProgram(const std::string &vertexShaderSource, const std::string &fragmentShaderSource)
{
GLuint programId = 0;
GLuint vtxShaderId, fragShaderId;
GLuint idPrograma = glCreateProgram();
programId = glCreateProgram();
// Si el fragment shader está vacío, reutilizamos el código del vertex shader
GLuint idShaderVertice = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
GLuint idShaderFragmento = compileShader(fragmentShaderSource.empty() ? vertexShaderSource : fragmentShaderSource, GL_FRAGMENT_SHADER);
vtxShaderId = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
fragShaderId = compileShader(fragmentShaderSource ? fragmentShaderSource : vertexShaderSource, GL_FRAGMENT_SHADER);
if (vtxShaderId && fragShaderId)
if (idShaderVertice && idShaderFragmento)
{
// Associate shader with program
glAttachShader(programId, vtxShaderId);
glAttachShader(programId, fragShaderId);
glLinkProgram(programId);
glValidateProgram(programId);
// Asociar los shaders al programa
glAttachShader(idPrograma, idShaderVertice);
glAttachShader(idPrograma, idShaderFragmento);
glLinkProgram(idPrograma);
glValidateProgram(idPrograma);
// Check the status of the compile/link
GLint logLen;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen);
if (logLen > 0)
// Verificar el estado del enlace
GLint longitudLog;
glGetProgramiv(idPrograma, GL_INFO_LOG_LENGTH, &longitudLog);
if (longitudLog > 0)
{
char *log = (char *)malloc(logLen * sizeof(char));
// Show any errors as appropriate
glGetProgramInfoLog(programId, logLen, &logLen, log);
std::cout << "Prog Info Log: " << std::endl
<< log << std::endl;
free(log);
std::vector<char> log(longitudLog);
glGetProgramInfoLog(idPrograma, longitudLog, &longitudLog, log.data());
std::cout << "Registro de información del programa:" << std::endl
<< log.data() << std::endl;
}
}
if (vtxShaderId)
if (idShaderVertice)
{
glDeleteShader(vtxShaderId);
glDeleteShader(idShaderVertice);
}
if (fragShaderId)
if (idShaderFragmento)
{
glDeleteShader(fragShaderId);
glDeleteShader(idShaderFragmento);
}
return programId;
return idPrograma;
}
const bool init(SDL_Window *win, SDL_Texture *backBuffer, const char *vertexShader, const char *fragmentShader)
bool init(SDL_Window *ventana, SDL_Texture *texturaBackBuffer, const std::string &vertexShader, const std::string &fragmentShader)
{
shader::win = win;
shader::renderer = SDL_GetRenderer(win);
shader::backBuffer = backBuffer;
SDL_GetWindowSize(win, &win_size.x, &win_size.y);
int access;
SDL_QueryTexture(backBuffer, nullptr, &access, &tex_size.x, &tex_size.y);
if (access != SDL_TEXTUREACCESS_TARGET)
shader::win = ventana;
shader::renderer = SDL_GetRenderer(ventana);
shader::backBuffer = texturaBackBuffer;
SDL_GetWindowSize(ventana, &win_size.x, &win_size.y);
int acceso;
SDL_QueryTexture(texturaBackBuffer, nullptr, &acceso, &tex_size.x, &tex_size.y);
if (acceso != SDL_TEXTUREACCESS_TARGET)
{
throw std::runtime_error("ERROR FATAL: La textura debe tener SDL_TEXTUREACCESS_TARGET definido.");
throw std::runtime_error("ERROR FATAL: La textura debe tener definido SDL_TEXTUREACCESS_TARGET.");
}
SDL_RendererInfo rendererInfo;
SDL_GetRendererInfo(renderer, &rendererInfo);
SDL_RendererInfo infoRenderer;
SDL_GetRendererInfo(renderer, &infoRenderer);
if (!strncmp(rendererInfo.name, "opengl", 6))
// Verificar que el renderer sea OpenGL
if (!strncmp(infoRenderer.name, "opengl", 6))
{
#ifndef __APPLE__
if (!initGLExtensions())
{
std::cout << "WARNING: No s'han pogut inicialitzar les extensions d'OpenGL!" << std::endl;
std::cout << "ADVERTENCIA: No se han podido inicializar las extensiones de OpenGL." << std::endl;
usingOpenGL = false;
return false;
}
#endif
// Compilar el shader y dejarlo listo para usar.
// Compilar el programa de shaders utilizando std::string
programId = compileProgram(vertexShader, fragmentShader);
}
else
{
std::cout << "WARNING: El driver del renderer no es OpenGL." << std::endl;
std::cout << "ADVERTENCIA: El driver del renderer no es OpenGL." << std::endl;
usingOpenGL = false;
return false;
}
@@ -249,6 +254,7 @@ namespace shader
// Configurar la proyección ortográfica usando el espacio lógico
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Queremos que el origen esté en la esquina superior izquierda del espacio lógico.
glOrtho(0, static_cast<GLdouble>(logicalW), static_cast<GLdouble>(logicalH), 0, -1, 1);
glMatrixMode(GL_MODELVIEW);

View File

@@ -2,6 +2,7 @@
#include <SDL2/SDL_render.h> // para SDL_Texture
#include <SDL2/SDL_video.h> // para SDL_Window
#include <string>
// TIPS:
// =======================================================================
@@ -38,8 +39,7 @@
namespace shader
{
const bool init(SDL_Window *win, SDL_Texture *backBuffer,
const char *vertexShader, const char *fragmentShader = nullptr);
//const bool init(SDL_Window *ventana, SDL_Texture *texturaBackBuffer, const char *vertexShader, const char *fragmentShader = nullptr);
bool init(SDL_Window *ventana, SDL_Texture *texturaBackBuffer, const std::string &vertexShader, const std::string &fragmentShader = "");
void render();
}

View File

@@ -327,7 +327,7 @@ void Screen::initShaders()
{
loadShaders();
}
shader::init(window_, game_canvas_, shaderSource.c_str());
shader::init(window_, game_canvas_, shaderSource);
}
// Calcula el tamaño de la ventana