Re-implement RGBA textures

This commit is contained in:
2026-03-28 15:21:33 -05:00
parent 6823a4ddb5
commit 87d2d9123e
7 changed files with 270 additions and 187 deletions

View File

@@ -61,17 +61,17 @@ errorret_t displayInit(void) {
7,7,7,7,7,7,7,7 7,7,7,7,7,7,7,7
}; };
errorChain(textureInit( // errorChain(textureInit(
&PALETTE_TEXTURE, // &PALETTE_TEXTURE,
8, 8, // 8, 8,
TEXTURE_FORMAT_PALETTE, // TEXTURE_FORMAT_PALETTE,
(texturedata_t){ // (texturedata_t){
.paletted = { // .paletted = {
.indices = indices, // .indices = indices,
.palette = &PALETTES[0] // .palette = &PALETTES[0]
} // }
} // }
)); // ));
errorChain(textureInit( errorChain(textureInit(
&UNCOMPRESSED_TEXTURE, &UNCOMPRESSED_TEXTURE,

View File

@@ -47,8 +47,6 @@ errorret_t meshDrawDolphin(
assertTrue(offsetof(meshvertex_t, uv) == 4, "uv offset wrong"); assertTrue(offsetof(meshvertex_t, uv) == 4, "uv offset wrong");
assertTrue(offsetof(meshvertex_t, pos) == 12, "pos offset wrong"); assertTrue(offsetof(meshvertex_t, pos) == 12, "pos offset wrong");
textureDolphinUploadTEV();
DCFlushRange( DCFlushRange(
(void*)&mesh->vertices[vertexOffset], (void*)&mesh->vertices[vertexOffset],
sizeof(meshvertex_t) * vertexCount sizeof(meshvertex_t) * vertexCount

View File

@@ -77,6 +77,88 @@ errorret_t shaderSetMatrixDolphin(
errorOk(); errorOk();
} }
errorret_t shaderSetTextureDolphin(
shaderdolphin_t *shader,
const char_t *name,
texture_t *texture
) {
assertNotNull(shader, "Shader must not be null");
assertNotNull(name, "Uniform name must not be null");
assertStrLenMin(name, 1, "Uniform name cannot be empty");
if(texture == NULL) {
// GX_SetNumChans(0);
GX_SetNumChans(1);
GX_SetChanCtrl(
GX_COLOR0A0,
GX_DISABLE,
GX_SRC_REG,
GX_SRC_VTX,
GX_LIGHTNULL,
GX_DF_NONE,
GX_AF_NONE
);
GX_SetChanAmbColor(GX_COLOR0A0, (GXColor){ 0, 0, 0, 0 });
GX_SetChanMatColor(GX_COLOR0A0, (GXColor){ 255, 255, 255, 255 });
GX_SetNumTexGens(0);
GX_SetNumTevStages(1);
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
GX_SetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR);
GX_SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
errorOk();
}
// Add channel for vertex color
GX_LoadTexObj(&texture->texObj, GX_TEXMAP0);
GX_SetNumChans(1);
GX_SetChanCtrl(
GX_COLOR0A0,// Store in color channel 0
GX_DISABLE,// Lighting disabled
GX_SRC_REG,// Ambient color?
GX_SRC_VTX,// Material color?
GX_LIGHTNULL,// Light Mask
GX_DF_NONE,// Diffuse function
GX_AF_NONE// Attenuation function
);
// One set of UVs
GX_SetNumTexGens(1);
GX_SetTexCoordGen(
GX_TEXCOORD0,
GX_TG_MTX2x4,
GX_TG_TEX0,
GX_IDENTITY
);
// Basically the shader setup
switch(texture->format) {
case TEXTURE_FORMAT_RGBA:
// One TEV stage: vertex color * texture color
GX_SetNumTevStages(1);
GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE);
GX_SetTevOrder(
GX_TEVSTAGE0,
GX_TEXCOORD0,
GX_TEXMAP0,
GX_COLOR0A0
);
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
GX_SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
break;
default:
assertUnreachable("Unknown texture format in meshDraw");
break;
}
errorOk();
}
errorret_t shaderDisposeDolphin(shaderdolphin_t *shader) { errorret_t shaderDisposeDolphin(shaderdolphin_t *shader) {
assertNotNull(shader, "Shader must not be null"); assertNotNull(shader, "Shader must not be null");

View File

@@ -6,7 +6,7 @@
*/ */
#pragma once #pragma once
#include "error/error.h" #include "display/texture/texture.h"
typedef struct { typedef struct {
mat4 view; mat4 view;
@@ -66,6 +66,20 @@ errorret_t shaderSetMatrixDolphin(
mat4 matrix mat4 matrix
); );
/**
* Sets a texture uniform in the dolphin shader. Basically does nothing.
*
* @param shader Shader to set the texture in.
* @param name Name of the uniform to set.
* @param texture Texture to set.
* @return Error code if failure.
*/
errorret_t shaderSetTextureDolphin(
shaderdolphin_t *shader,
const char_t *name,
texture_t *texture
);
/** /**
* Disposes a dolphin shader. Basically does nothing. * Disposes a dolphin shader. Basically does nothing.
* *

View File

@@ -14,5 +14,5 @@ typedef shaderdefinitiondolphin_t shaderdefinitionplatform_t;
#define shaderInitPlatform shaderInitDolphin #define shaderInitPlatform shaderInitDolphin
#define shaderBindPlatform shaderBindDolphin #define shaderBindPlatform shaderBindDolphin
#define shaderSetMatrixPlatform shaderSetMatrixDolphin #define shaderSetMatrixPlatform shaderSetMatrixDolphin
// #define shaderSetTexturePlatform shaderSetTextureDolphin #define shaderSetTexturePlatform shaderSetTextureDolphin
#define shaderDisposePlatform shaderDisposeDolphin #define shaderDisposePlatform shaderDisposeDolphin

View File

@@ -7,6 +7,7 @@
#include "display/texture/texture.h" #include "display/texture/texture.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "util/memory.h"
errorret_t textureInitDolphin( errorret_t textureInitDolphin(
texturedolphin_t *texture, texturedolphin_t *texture,
@@ -15,14 +16,73 @@ errorret_t textureInitDolphin(
const textureformatdolphin_t format, const textureformatdolphin_t format,
const texturedata_t data const texturedata_t data
) { ) {
// switch(format) { switch(format) {
// case TEXTURE_FORMAT_RGBA: case TEXTURE_FORMAT_RGBA: {
size_t rgbaSize = width * height * sizeof(uint8_t) * 4;
// Dolphin takes the RGBA data as 4x4 tiled layout.
texture->rgba = memoryAllocate(rgbaSize);
for(uint32_t y = 0; y < height; ++y) {
for(uint32_t x = 0; x < width; ++x) {
const int src = y * width + x;
const int tileX = x >> 2;
const int tileY = y >> 2;
const int tilesPerRow = width >> 2;
const int tileIndex = tileY * tilesPerRow + tileX;
const int inTile = ((y & 3) << 2) + (x & 3);
const int tileBase = tileIndex * 64;
color_t col = data.rgbaColors[src];
// AR plane
texture->rgba[tileBase + inTile * 2 + 0] = col.a;
texture->rgba[tileBase + inTile * 2 + 1] = col.r;
// GB plane
texture->rgba[tileBase + 32 + inTile * 2 + 0] = col.g;
texture->rgba[tileBase + 32 + inTile * 2 + 1] = col.b;
}
}
DCFlushRange(texture->rgba, rgbaSize);
GX_InitTexObj(
&texture->texObj,
texture->rgba,
width, height,
format,
GX_REPEAT, GX_REPEAT,
GX_FALSE
);
DCFlushRange(texture->rgba, rgbaSize);
GX_InvalidateTexAll();
GX_InitTexObjLOD(
&texture->texObj,
GX_NEAR, GX_NEAR,
0.0f, 0.0f, 0.0f,
GX_FALSE,
GX_FALSE,
GX_ANISO_1
);
break;
}
case TEXTURE_FORMAT_RGB4A3: {
assertUnreachable("RGB4A3 texture format not yet implemented");
}
case TEXTURE_FORMAT_RGB5: {
assertUnreachable("RGB5 texture format not yet implemented");
}
// assertTrue( // assertTrue(
// (width % 4) == 0 && (height % 4) == 0, // (width % 4) == 0 && (height % 4) == 0,
// "RGB5A3 requires w/h multiple of 4 (or pad)" // "RGB4A3 requires w/h multiple of 4 (or pad)"
// ); // );
// // Convert to RGB5A3 format // // Convert to RGB4A3 format
// size_t rgbaSize = width * height * sizeof(u16); // size_t rgbaSize = width * height * sizeof(u16);
// texture->rgba = (u16*)memalign(32, rgbaSize); // texture->rgba = (u16*)memalign(32, rgbaSize);
// assertNotNull(texture->rgba, "Failed to allocate texture RGBA data"); // assertNotNull(texture->rgba, "Failed to allocate texture RGBA data");
@@ -39,7 +99,7 @@ errorret_t textureInitDolphin(
// const int inTile = ((y & 3) << 2) + (x & 3); // const int inTile = ((y & 3) << 2) + (x & 3);
// const int dest = tileBaseWords + inTile; // const int dest = tileBaseWords + inTile;
// color4b_t col = data.rgba.colors[src]; // color4b_t col = data.rgbaColors[src];
// u16 outCol; // u16 outCol;
// if(col.a < 255) { // if(col.a < 255) {
@@ -85,121 +145,49 @@ errorret_t textureInitDolphin(
// GX_FALSE, // GX_FALSE,
// GX_ANISO_1 // GX_ANISO_1
// ); // );
// break;
// case TEXTURE_FORMAT_PALETTE: { case TEXTURE_FORMAT_PALETTE: {
// // Not supported, convert to RGBA using lookup assertUnreachable("Paletted textures not yet implemented for Dolphin");
// color_t* formatted = memoryAllocate(width * height * sizeof(color_t)); break;
// for(int32_t i = 0; i < width * height; i++) { }
// uint8_t index = data.palette.data[i];
// assertTrue(
// index < data.palette.palette->colorCount,
// "Palette index out of range"
// );
// formatted[i] = data.palette.palette->colors[index];
// }
// textureInit( default: {
// texture, width, height, TEXTURE_FORMAT_RGBA, assertUnreachable("Unsupported texture format for Dolphin");
// (texturedata_t){ break;
// .rgba = { .colors = formatted } }
// } }
// );
// memoryFree(formatted);
// break;
// }
// default:
// assertUnreachable("Unsupported texture format for Dolphin");
// break;
// }
// texture->ready = true;
errorOk(); errorOk();
} }
errorret_t textureBindDolphin(texturedolphin_t *texture) {
if(texture == NULL) {
GX_SetNumChans(0);
errorOk();
}
GX_SetNumChans(1);
GX_LoadTexObj(&texture->texObj, GX_TEXMAP0);
errorOk();
}
errorret_t textureDisposeDolphin(texturedolphin_t *texture) { errorret_t textureDisposeDolphin(texturedolphin_t *texture) {
switch(texture->format) {
case TEXTURE_FORMAT_RGBA: {
if(texture->rgba) {
memoryFree(texture->rgba);
texture->rgba = NULL;
}
break;
}
case TEXTURE_FORMAT_RGB4A3: {
assertUnreachable("RGB4A3 texture format not yet implemented");
}
case TEXTURE_FORMAT_RGB5: {
assertUnreachable("RGB5 texture format not yet implemented");
}
case TEXTURE_FORMAT_PALETTE: {
assertUnreachable("Paletted textures not yet implemented for Dolphin");
break;
}
default: {
assertUnreachable("Unsupported texture format for Dolphin");
break;
}
}
errorOk(); errorOk();
} }
void textureDolphinUploadTEV(void) {
if(TEXTURE_BOUND == NULL) {
GX_SetNumChans(1);
GX_SetChanCtrl(
GX_COLOR0A0,
GX_DISABLE,
GX_SRC_REG,
GX_SRC_VTX,
GX_LIGHTNULL,
GX_DF_NONE,
GX_AF_NONE
);
GX_SetChanAmbColor(GX_COLOR0A0, (GXColor){0, 0, 0, 0});
GX_SetChanMatColor(GX_COLOR0A0, (GXColor){255, 255, 255, 255});
GX_SetNumTexGens(0);
GX_SetNumTevStages(1);
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
GX_SetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR);
GX_SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
return;
}
// Add channel for vertex color
GX_SetNumChans(1);
GX_SetChanCtrl(
GX_COLOR0A0,// Store in color channel 0
GX_DISABLE,// Lighting disabled
GX_SRC_REG,// Ambient color?
GX_SRC_VTX,// Material color?
GX_LIGHTNULL,// Light Mask
GX_DF_NONE,// Diffuse function
GX_AF_NONE// Attenuation function
);
// One set of UVs
GX_SetNumTexGens(1);
GX_SetTexCoordGen(
GX_TEXCOORD0,
GX_TG_MTX2x4,
GX_TG_TEX0,
GX_IDENTITY
);
// Basically the shader setup
switch(TEXTURE_BOUND->format) {
case TEXTURE_FORMAT_RGBA:
// One TEV stage: vertex color * texture color
GX_SetNumTevStages(1);
GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE);
GX_SetTevOrder(
GX_TEVSTAGE0,
GX_TEXCOORD0,
GX_TEXMAP0,
GX_COLOR0A0
);
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
GX_SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
break;
default:
assertUnreachable("Unknown texture format in meshDraw");
break;
}
}

View File

@@ -13,6 +13,8 @@ typedef union texturedata_u texturedata_t;
typedef enum { typedef enum {
TEXTURE_FORMAT_RGBA = GX_TF_RGBA8, TEXTURE_FORMAT_RGBA = GX_TF_RGBA8,
TEXTURE_FORMAT_PALETTE = GX_TF_CI8, TEXTURE_FORMAT_PALETTE = GX_TF_CI8,
TEXTURE_FORMAT_RGB4A3 = GX_TF_RGB5A3,
TEXTURE_FORMAT_RGB5 = GX_TF_RGB565,
} textureformatdolphin_t; } textureformatdolphin_t;
typedef struct { typedef struct {
@@ -20,6 +22,11 @@ typedef struct {
textureformatdolphin_t format; textureformatdolphin_t format;
int32_t width; int32_t width;
int32_t height; int32_t height;
union {
uint8_t *rgba;
// u16 *rgba;
};
} texturedolphin_t; } texturedolphin_t;
/** /**
@@ -55,9 +62,3 @@ errorret_t textureBindDolphin(texturedolphin_t *texture);
* @return An error if the texture failed to dispose, otherwise success. * @return An error if the texture failed to dispose, otherwise success.
*/ */
errorret_t textureDisposeDolphin(texturedolphin_t *texture); errorret_t textureDisposeDolphin(texturedolphin_t *texture);
/**
* Internal method that uploads the texture environment variables to the GPU
* for rendering. This is basically uploading the shader information.
*/
void textureDolphinUploadTEV(void);