Moved texture setting around

This commit is contained in:
2026-03-28 09:48:24 -05:00
parent 9474a68995
commit 9ba0ceb000
8 changed files with 213 additions and 126 deletions

View File

@@ -7,6 +7,7 @@
#include "assert.h" #include "assert.h"
#include "log/log.h" #include "log/log.h"
#include "util/string.h"
#ifndef DUSK_ASSERTIONS_FAKED #ifndef DUSK_ASSERTIONS_FAKED
#ifdef DUSK_TEST_ASSERT #ifdef DUSK_TEST_ASSERT
@@ -98,4 +99,14 @@
) { ) {
assertUnreachableImpl(file, line, message); assertUnreachableImpl(file, line, message);
} }
void assertStringEqualImpl(
const char *file,
const int32_t line,
const char *a,
const char *b,
const char *message
) {
assertTrueImpl(file, line, stringCompare(a, b) == 0, message);
}
#endif #endif

View File

@@ -104,6 +104,23 @@
const char *message const char *message
); );
/**
* Asserts two strings to be equal.
*
* @param file File that the assertion is being made from.
* @param line Line that the assertion is being made from.
* @param a First string to compare.
* @param b Second string to compare.
* @param message Message to throw against assertion failure.
*/
void assertStringEqualImpl(
const char *file,
const int32_t line,
const char *a,
const char *b,
const char *message
);
/** /**
* Asserts a given value to be true. * Asserts a given value to be true.
* *
@@ -178,6 +195,16 @@
#define assertStrLenMin(str, len, message) \ #define assertStrLenMin(str, len, message) \
assertTrue(strlen(str) >= len, message) assertTrue(strlen(str) >= len, message)
/**
* Asserts two strings to be equal.
*
* @param a First string to compare.
* @param b Second string to compare.
* @param message Message to throw against assertion failure.
*/
#define assertStringEqual(a, b, message) \
assertStringEqualImpl(__FILE__, __LINE__, a, b, message)
#else #else
// If assertions are faked, we define the macros to do nothing. // If assertions are faked, we define the macros to do nothing.
#define assertTrue(x, message) ((void)0) #define assertTrue(x, message) ((void)0)

View File

@@ -22,12 +22,9 @@
display_t DISPLAY = { 0 }; display_t DISPLAY = { 0 };
texture_t TEXTURE; texture_t PALETTE_TEXTURE;
texture_t UNCOMPRESSED_TEXTURE;
uint8_t indices[2 * 2] = { texture_t COMPRESSED_TEXTURE;
0, 1,
2, 3
};
errorret_t displayInit(void) { errorret_t displayInit(void) {
memoryZero(&DISPLAY, sizeof(DISPLAY)); memoryZero(&DISPLAY, sizeof(DISPLAY));
@@ -50,17 +47,32 @@ errorret_t displayInit(void) {
PALETTES[0].count = 4; PALETTES[0].count = 4;
errorChain(textureInit( errorChain(textureInit(
&TEXTURE, &PALETTE_TEXTURE,
2, 2, 2, 2,
TEXTURE_FORMAT_PALETTE, TEXTURE_FORMAT_PALETTE,
(texturedata_t){ (texturedata_t){
.paletted = { .paletted = {
.indices = indices, .indices = (uint8_t[]){
0, 1,
2, 3
},
.palette = &PALETTES[0] .palette = &PALETTES[0]
} }
} }
)); ));
errorChain(textureInit(
&UNCOMPRESSED_TEXTURE,
2, 2,
TEXTURE_FORMAT_RGBA,
(texturedata_t){
.rgbaColors = (color_t[]){
COLOR_RED, COLOR_GREEN,
COLOR_BLUE, COLOR_WHITE
}
}
));
errorOk(); errorOk();
} }
@@ -100,7 +112,7 @@ errorret_t displayUpdate(void) {
errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_PROJECTION, proj)); errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_PROJECTION, proj));
errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_VIEW, view)); errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_VIEW, view));
errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, model)); errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, model));
errorChain(shaderSetTexture(&SHADER_UNLIT, SHADER_UNLIT_TEXTURE, &TEXTURE)); errorChain(shaderSetTexture(&SHADER_UNLIT, SHADER_UNLIT_TEXTURE, &UNCOMPRESSED_TEXTURE));
errorChain(spriteBatchPush( errorChain(spriteBatchPush(
0.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f,

View File

@@ -26,6 +26,7 @@ typedef union texturedata_u {
palette_t *palette; palette_t *palette;
} paletted; } paletted;
color_t *rgbaColors; color_t *rgbaColors;
uint8_t *compressedData;
} texturedata_t; } texturedata_t;
/** /**

View File

@@ -28,6 +28,11 @@ errorret_t shaderInitGL(shadergl_t *shader, const shaderdefinitiongl_t *def) {
SHADER_LEGACY.boundShader = NULL; SHADER_LEGACY.boundShader = NULL;
errorOk(); errorOk();
#else #else
assertNotNull(def->vert, "Vertex shader source cannot be null");
assertNotNull(def->frag, "Fragment shader source cannot be null");
shader->setTexture = def->setTexture;
// Create vertex shader // Create vertex shader
shader->vertexShaderId = glCreateShader(GL_VERTEX_SHADER); shader->vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
errorret_t err = errorGLCheck(); errorret_t err = errorGLCheck();
@@ -212,6 +217,12 @@ errorret_t shaderSetTextureGL(
assertStrLenMin(name, 1, "Uniform name cannot be empty"); assertStrLenMin(name, 1, "Uniform name cannot be empty");
#ifdef DUSK_OPENGL_LEGACY #ifdef DUSK_OPENGL_LEGACY
assertStringEqual(
name,
SHADER_UNLIT_TEXTURE,
"Only one texture supported in legacy opengl."
)
if(texture == NULL) { if(texture == NULL) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
errorChain(errorGLCheck()); errorChain(errorGLCheck());
@@ -226,44 +237,10 @@ errorret_t shaderSetTextureGL(
errorChain(errorGLCheck()); errorChain(errorGLCheck());
#else #else
if(texture == NULL) { if(shader->setTexture == NULL) {
glActiveTexture(GL_TEXTURE0); assertUnreachable("Shader does not support setting textures.");
errorChain(errorGLCheck());
glBindTexture(GL_TEXTURE_2D, 0);
errorChain(errorGLCheck());
errorOk();
} }
errorChain(shader->setTexture(shader, name, texture));
GLint location;
errorChain(shaderParamGetLocationGL(shader, name, &location));
glActiveTexture(GL_TEXTURE0);
errorChain(errorGLCheck());
glBindTexture(GL_TEXTURE_2D, texture->id);
errorChain(errorGLCheck());
glUniform1i(location, 0);
errorChain(errorGLCheck());
if(texture->format == TEXTURE_FORMAT_PALETTE) {
shaderParamGetLocationGL(shader, "u_ColorCount", &location);
glUniform1i(location, texture->palette->count);
errorChain(errorGLCheck());
shaderParamGetLocationGL(shader, "u_Colors", &location);
GLuint paletteData[texture->palette->count];
for(size_t i = 0; i < texture->palette->count; i++) {
color_t color = texture->palette->colors[i];
paletteData[i] = (
((uint32_t)color.r << 24) |
((uint32_t)color.g << 16) |
((uint32_t)color.b << 8) |
((uint32_t)color.a << 0)
);
}
glUniform1uiv(location, texture->palette->count, paletteData);
errorChain(errorGLCheck());
}
#endif #endif
errorOk(); errorOk();

View File

@@ -9,28 +9,35 @@
#include "error/errorgl.h" #include "error/errorgl.h"
#include "display/texture/texture.h" #include "display/texture/texture.h"
typedef struct { typedef struct shadergl_s shadergl_t;
typedef errorret_t (*shadersettexturefn_t)(
shadergl_t *,
const char_t *,
texture_t *
);
typedef struct shadergl_s {
#ifdef DUSK_OPENGL_LEGACY #ifdef DUSK_OPENGL_LEGACY
void *nothing; mat4 view;
mat4 proj;
mat4 model;
#else #else
GLuint shaderProgramId; GLuint shaderProgramId;
GLuint vertexShaderId; GLuint vertexShaderId;
GLuint fragmentShaderId; GLuint fragmentShaderId;
#endif shadersettexturefn_t setTexture;
#if DUSK_OPENGL_LEGACY
mat4 view;
mat4 proj;
mat4 model;
#endif #endif
} shadergl_t; } shadergl_t;
typedef struct { typedef struct {
#ifdef DUSK_OPENGL_LEGACY #ifdef DUSK_OPENGL_LEGACY
void *nothing; void *nothing;
#else #else
const char_t *vert; const char_t *vert;
const char_t *frag; const char_t *frag;
shadersettexturefn_t setTexture;
#endif #endif
} shaderdefinitiongl_t; } shaderdefinitiongl_t;

View File

@@ -6,58 +6,87 @@
*/ */
#include "display/shader/shaderunlit.h" #include "display/shader/shaderunlit.h"
#include "assert/assertgl.h"
#ifdef DUSK_OPENGL_LEGACY #ifdef DUSK_OPENGL_LEGACY
shaderdefinition_t SHADER_UNLIT_DEFINITION = { 0 }; shaderdefinition_t SHADER_UNLIT_DEFINITION = { 0 };
#elif defined(DUSK_OPENGL_ES)
shaderdefinition_t SHADER_UNLIT_DEFINITION = {
.vert =
"#version 300 es\n"
"layout(location = 0) in vec3 a_Pos;\n"
"layout(location = 1) in vec2 a_TexCoord;\n"
"layout(location = 2) in vec4 a_Color;\n"
"uniform mat4 u_Proj;\n"
"uniform mat4 u_View;\n"
"uniform mat4 u_Model;\n"
"out vec4 v_Color;\n"
"out vec2 v_TexCoord;\n"
"void main() {\n"
" gl_Position = u_Proj * u_View * u_Model * vec4(a_Pos, 1.0);\n"
" v_Color = a_Color;\n"
" v_TexCoord = a_TexCoord;\n"
"}\n",
.frag =
"#version 300 es\n"
"precision mediump float;\n"
"uniform sampler2D u_Texture;\n"
"uniform uint u_Colors[256];\n"
"uniform int u_ColorCount;\n"
"in vec4 v_Color;\n"
"in vec2 v_TexCoord;\n"
"out vec4 FragColor;\n"
"void main() {\n"
" vec4 texColor = texture(u_Texture, v_TexCoord);\n"
" uint index = uint(clamp(texColor.r * 255.0 + 0.5, 0.0, 255.0));\n"
" uint palColor = u_Colors[index];\n"
" float r = float((palColor >> 24) & 0xFFu) / 255.0;\n"
" float g = float((palColor >> 16) & 0xFFu) / 255.0;\n"
" float b = float((palColor >> 8) & 0xFFu) / 255.0;\n"
" float a = float((palColor >> 0) & 0xFFu) / 255.0;\n"
" vec4 paletteColor = vec4(r, g, b, a);\n"
" FragColor = paletteColor;\n"
"}\n"
};
#else #else
errorret_t shaderUnlitSetTextureGL(
shadergl_t *shader,
const char_t *name,
texture_t *texture
) {
assertNotNull(shader, "Shader cannot be null");
assertStrLenMin(name, 1, "Uniform name cannot be empty");
assertStringEqual(
name,
SHADER_UNLIT_TEXTURE,
"Only one texture supported in unlit shader."
);
GLint locTexture, locType, locColorCount, locColors;
errorChain(shaderParamGetLocationGL(shader, "u_TextureType", &locType));
// NULL textures
if(texture == NULL) {
glUniform1i(locType, 0);
errorChain(errorGLCheck());
errorOk();
}
// Set texture.
glActiveTexture(GL_TEXTURE0);
errorChain(errorGLCheck());
glBindTexture(GL_TEXTURE_2D, texture->id);
errorChain(errorGLCheck());
errorChain(shaderParamGetLocationGL(shader, name, &locTexture));
glUniform1i(locTexture, 0);
errorChain(errorGLCheck());
// Set texture type
if(texture->format == TEXTURE_FORMAT_PALETTE) {
shaderParamGetLocationGL(shader, "u_ColorCount", &locColorCount);
glUniform1i(locColorCount, texture->palette->count);
errorChain(errorGLCheck());
shaderParamGetLocationGL(shader, "u_Colors", &locColors);
GLuint paletteData[texture->palette->count];
for(size_t i = 0; i < texture->palette->count; i++) {
color_t color = texture->palette->colors[i];
paletteData[i] = (
((uint32_t)color.r << 24) |
((uint32_t)color.g << 16) |
((uint32_t)color.b << 8) |
((uint32_t)color.a << 0)
);
}
glUniform1uiv(locColors, texture->palette->count, paletteData);
errorChain(errorGLCheck());
} else {
glUniform1i(locType, 1);
errorChain(errorGLCheck());
}
errorOk();
}
shaderdefinition_t SHADER_UNLIT_DEFINITION = { shaderdefinition_t SHADER_UNLIT_DEFINITION = {
.vert = .vert =
#ifdef DUSK_OPENGL_ES
#else
"#version 330 core\n" "#version 330 core\n"
// Attributes
"layout(location = 0) in vec3 a_Pos;\n" "layout(location = 0) in vec3 a_Pos;\n"
"layout(location = 1) in vec2 a_TexCoord;\n" "layout(location = 1) in vec2 a_TexCoord;\n"
"layout(location = 2) in vec4 a_Color;\n" "layout(location = 2) in vec4 a_Color;\n"
// Uniforms
"uniform mat4 u_Proj;\n" "uniform mat4 u_Proj;\n"
"uniform mat4 u_View;\n" "uniform mat4 u_View;\n"
"uniform mat4 u_Model;\n" "uniform mat4 u_Model;\n"
// Vertex shader outputs
"out vec4 v_Color;\n" "out vec4 v_Color;\n"
"out vec2 v_TexCoord;\n" "out vec2 v_TexCoord;\n"
"void main() {\n" "void main() {\n"
@@ -65,16 +94,32 @@
" v_Color = a_Color;\n" " v_Color = a_Color;\n"
" v_TexCoord = a_TexCoord;\n" " v_TexCoord = a_TexCoord;\n"
"}\n", "}\n",
#endif
.frag = .frag =
#ifdef DUSK_OPENGL_ES
#else
"#version 330 core\n" "#version 330 core\n"
// Uniforms
"uniform sampler2D u_Texture;\n" "uniform sampler2D u_Texture;\n"
"uniform uint u_Colors[256];\n" "uniform int u_TextureType;\n"
"uniform uint u_Colors[256];\n"// For paletted textures.
"uniform int u_ColorCount;\n" "uniform int u_ColorCount;\n"
// Fragment shader inputs
"in vec4 v_Color;\n" "in vec4 v_Color;\n"
"in vec2 v_TexCoord;\n" "in vec2 v_TexCoord;\n"
// Fragment shader output
"out vec4 FragColor;\n" "out vec4 FragColor;\n"
"void main() {\n" "void main() {\n"
" if(u_TextureType == 0) {\n"// No texture
" FragColor = v_Color;\n"
" return;\n"
" }\n"
" if(u_TextureType == 1) {\n"// Regular texture
" FragColor = texture(u_Texture, v_TexCoord) * v_Color;\n"
" return;\n"
" }\n"
" if(u_TextureType == 2) {\n"// Paletted texture
" vec4 texColor = texture(u_Texture, v_TexCoord);\n" " vec4 texColor = texture(u_Texture, v_TexCoord);\n"
" uint index = uint(floor(texColor.r * 255.0));\n" " uint index = uint(floor(texColor.r * 255.0));\n"
" uint palColor = u_Colors[index];\n" " uint palColor = u_Colors[index];\n"
@@ -84,6 +129,12 @@
" float a = float((palColor >> 0) & 0xFFu) / 255.0;\n" " float a = float((palColor >> 0) & 0xFFu) / 255.0;\n"
" vec4 paletteColor = vec4(r, g, b, a);\n" " vec4 paletteColor = vec4(r, g, b, a);\n"
" FragColor = paletteColor;\n" " FragColor = paletteColor;\n"
" return;\n"
" }\n" " }\n"
" FragColor = v_Color;\n"// Unknown texture type?
"}\n",
#endif
.setTexture = shaderUnlitSetTextureGL
}; };
#endif #endif

View File

@@ -13,6 +13,7 @@ typedef union texturedata_u texturedata_t;
typedef enum { typedef enum {
TEXTURE_FORMAT_RGBA = GL_RGBA, TEXTURE_FORMAT_RGBA = GL_RGBA,
TEXTURE_FORMAT_PALETTE = GL_COLOR_INDEX8_EXT, TEXTURE_FORMAT_PALETTE = GL_COLOR_INDEX8_EXT,
// TEXTURE_FORMAT_DXT5 = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
} textureformatgl_t; } textureformatgl_t;
typedef struct { typedef struct {