Alpha textures
This commit is contained in:
@@ -42,6 +42,7 @@ find_package(Python3 COMPONENTS Interpreter REQUIRED)
|
|||||||
|
|
||||||
if(NOT DEFINED DUSK_TARGET_SYSTEM)
|
if(NOT DEFINED DUSK_TARGET_SYSTEM)
|
||||||
set(DUSK_TARGET_SYSTEM "linux")
|
set(DUSK_TARGET_SYSTEM "linux")
|
||||||
|
# set(DUSK_TARGET_SYSTEM "psp")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Toolchains
|
# Toolchains
|
||||||
|
|||||||
@@ -193,22 +193,33 @@ errorret_t displayUpdate(void) {
|
|||||||
);
|
);
|
||||||
errorChain(sceneRender());
|
errorChain(sceneRender());
|
||||||
|
|
||||||
color_t colors[4 * 4] = {
|
texture_t texture;
|
||||||
COLOR_RED_4B, COLOR_GREEN_4B, COLOR_BLUE_4B, COLOR_YELLOW_4B,
|
|
||||||
COLOR_CYAN_4B, COLOR_MAGENTA_4B, COLOR_WHITE_4B, COLOR_BLACK_4B,
|
// color_t colors[4 * 4] = {
|
||||||
COLOR_ORANGE_4B, COLOR_PURPLE_4B, COLOR_GRAY_4B, COLOR_BROWN_4B,
|
// COLOR_RED_4B, COLOR_GREEN_4B, COLOR_BLUE_4B, COLOR_YELLOW_4B,
|
||||||
COLOR_PINK_4B, COLOR_LIME_4B, COLOR_NAVY_4B, COLOR_TEAL_4B
|
// COLOR_CYAN_4B, COLOR_MAGENTA_4B, COLOR_WHITE_4B, COLOR_BLACK_4B,
|
||||||
|
// COLOR_ORANGE_4B, COLOR_PURPLE_4B, COLOR_GRAY_4B, COLOR_BROWN_4B,
|
||||||
|
// COLOR_PINK_4B, COLOR_LIME_4B, COLOR_NAVY_4B, COLOR_TEAL_4B
|
||||||
|
// };
|
||||||
|
// texturedata_t data = {
|
||||||
|
// .rgba = { .colors = colors }
|
||||||
|
// };
|
||||||
|
// textureInit(&texture, 4, 4, TEXTURE_FORMAT_RGBA, data);
|
||||||
|
|
||||||
|
uint8_t alphaData[8 * 4] = {
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
0, 0, 255, 0, 0, 255, 0, 0,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
0, 0, 0, 255, 255, 0, 0, 0,
|
||||||
};
|
};
|
||||||
texturedata_t data = {
|
texturedata_t data = {
|
||||||
.rgba = { .colors = colors }
|
.alpha = { .data = alphaData }
|
||||||
};
|
};
|
||||||
|
textureInit(&texture, 8, 4, TEXTURE_FORMAT_ALPHA, data);
|
||||||
|
|
||||||
camera_t camera;
|
camera_t camera;
|
||||||
cameraInit(&camera);
|
cameraInit(&camera);
|
||||||
|
|
||||||
texture_t texture;
|
|
||||||
textureInit(&texture, 4, 4, TEXTURE_FORMAT_RGBA, data);
|
|
||||||
|
|
||||||
cameraPushMatrix(&camera);
|
cameraPushMatrix(&camera);
|
||||||
spriteBatchClear();
|
spriteBatchClear();
|
||||||
spriteBatchPush(
|
spriteBatchPush(
|
||||||
@@ -221,7 +232,6 @@ errorret_t displayUpdate(void) {
|
|||||||
);
|
);
|
||||||
spriteBatchFlush();
|
spriteBatchFlush();
|
||||||
cameraPopMatrix();
|
cameraPopMatrix();
|
||||||
textureDispose(&texture);
|
|
||||||
|
|
||||||
// Render UI
|
// Render UI
|
||||||
// uiRender();
|
// uiRender();
|
||||||
@@ -245,6 +255,7 @@ errorret_t displayUpdate(void) {
|
|||||||
// if(DISPLAY.screenMode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
|
// if(DISPLAY.screenMode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
textureDispose(&texture);
|
||||||
|
|
||||||
// For now, we just return an OK error.
|
// For now, we just return an OK error.
|
||||||
errorOk();
|
errorOk();
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
|
|
||||||
|
#if DOLPHIN
|
||||||
|
#include "display/texture.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
void meshInit(
|
void meshInit(
|
||||||
mesh_t *mesh,
|
mesh_t *mesh,
|
||||||
const meshprimitivetype_t primitiveType,
|
const meshprimitivetype_t primitiveType,
|
||||||
@@ -91,39 +95,7 @@ void meshDraw(
|
|||||||
GX_SetArray(GX_VA_CLR0, &mesh->vertices[offset].color, stride);
|
GX_SetArray(GX_VA_CLR0, &mesh->vertices[offset].color, stride);
|
||||||
GX_SetArray(GX_VA_TEX0, &mesh->vertices[offset].uv[0], stride);
|
GX_SetArray(GX_VA_TEX0, &mesh->vertices[offset].uv[0], stride);
|
||||||
|
|
||||||
// GX_SetNumChans(1);// How many color channels are used
|
textureDolphinUploadTEV();
|
||||||
// GX_SetNumTexGens(0);// How many texture coordinate generators are used
|
|
||||||
// GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0);
|
|
||||||
// GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
|
|
||||||
|
|
||||||
// Basically the shader setup
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
GX_SetNumTexGens(1);
|
|
||||||
GX_SetTexCoordGen(
|
|
||||||
GX_TEXCOORD0,
|
|
||||||
GX_TG_MTX2x4,
|
|
||||||
GX_TG_TEX0,
|
|
||||||
GX_IDENTITY
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
GX_SetTevOrder(
|
|
||||||
GX_TEVSTAGE0,
|
|
||||||
GX_TEXCOORD0,
|
|
||||||
GX_TEXMAP0,
|
|
||||||
GX_COLOR0A0
|
|
||||||
);
|
|
||||||
GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE);
|
|
||||||
|
|
||||||
GX_Begin(mesh->primitiveType, GX_VTXFMT0, (uint16_t)count);
|
GX_Begin(mesh->primitiveType, GX_VTXFMT0, (uint16_t)count);
|
||||||
for(u16 i = 0; i < (u16)count; ++i) {
|
for(u16 i = 0; i < (u16)count; ++i) {
|
||||||
|
|||||||
@@ -147,10 +147,19 @@ void textureInit(
|
|||||||
texture->ready = true;
|
texture->ready = true;
|
||||||
|
|
||||||
#elif DOLPHIN
|
#elif DOLPHIN
|
||||||
assertTrue((width % 4) == 0 && (height % 4) == 0, "RGB5A3 requires w/h multiple of 4 (or pad)");
|
texture->format = format;
|
||||||
|
|
||||||
|
switch(format) {
|
||||||
|
case TEXTURE_FORMAT_RGBA:
|
||||||
|
assertTrue(
|
||||||
|
(width % 4) == 0 && (height % 4) == 0,
|
||||||
|
"RGB5A3 requires w/h multiple of 4 (or pad)"
|
||||||
|
);
|
||||||
|
|
||||||
// Convert to RGB5A3 format
|
// Convert to RGB5A3 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");
|
||||||
|
|
||||||
for(uint32_t y = 0; y < height; ++y) {
|
for(uint32_t y = 0; y < height; ++y) {
|
||||||
for(uint32_t x = 0; x < width; ++x) {
|
for(uint32_t x = 0; x < width; ++x) {
|
||||||
@@ -188,8 +197,8 @@ void textureInit(
|
|||||||
texture->rgba[dest] = outCol;
|
texture->rgba[dest] = outCol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DCFlushRange(texture->rgba, rgbaSize);
|
|
||||||
|
|
||||||
|
DCFlushRange(texture->rgba, rgbaSize);
|
||||||
GX_InitTexObj(
|
GX_InitTexObj(
|
||||||
&texture->texObj,
|
&texture->texObj,
|
||||||
texture->rgba,
|
texture->rgba,
|
||||||
@@ -210,6 +219,67 @@ void textureInit(
|
|||||||
GX_FALSE,
|
GX_FALSE,
|
||||||
GX_ANISO_1
|
GX_ANISO_1
|
||||||
);
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEXTURE_FORMAT_ALPHA:
|
||||||
|
assertTrue(
|
||||||
|
(width % 4) == 0 && (height % 4) == 0,
|
||||||
|
"GX_TF_I8 requires w/h multiple of 4 (or pad)"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 1 byte per pixel (I8), GX expects 4x4 tiled layout
|
||||||
|
const size_t alphaSize = (size_t)width * (size_t)height;
|
||||||
|
|
||||||
|
texture->alpha = (u8*)memalign(32, alphaSize);
|
||||||
|
assertNotNull(texture->alpha, "Failed to allocate alpha texture data");
|
||||||
|
|
||||||
|
const u32 tilesPerRow = ((u32)width) >> 3; // /8
|
||||||
|
|
||||||
|
for (u32 y = 0; y < (u32)height; ++y) {
|
||||||
|
const u32 tileY = y >> 2; // /4
|
||||||
|
const u32 inTileY = (y & 3) << 3; // (y%4)*8
|
||||||
|
|
||||||
|
for (u32 x = 0; x < (u32)width; ++x) {
|
||||||
|
const u32 srcI = y * (u32)width + x;
|
||||||
|
const u8 srcA = data.alpha.data[srcI]; // linear input
|
||||||
|
|
||||||
|
const u32 tileX = x >> 3; // /8
|
||||||
|
const u32 tileIndex = tileY * tilesPerRow + tileX;
|
||||||
|
|
||||||
|
const u32 tileBase = tileIndex * 32; // 8*4*1 = 32 bytes per tile
|
||||||
|
const u32 inTile = inTileY + (x & 7); // (y%4)*8 + (x%8)
|
||||||
|
|
||||||
|
texture->alpha[tileBase + inTile] = 0xFF - srcA;// Fixes inverted alpha.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush CPU cache so GX sees the swizzled I8 texture data
|
||||||
|
DCFlushRange(texture->alpha, alphaSize);
|
||||||
|
|
||||||
|
// Initialize GX texture object with swizzled data
|
||||||
|
GX_InitTexObj(
|
||||||
|
&texture->texObj,
|
||||||
|
texture->alpha,
|
||||||
|
width, height,
|
||||||
|
GX_TF_I8,
|
||||||
|
GX_CLAMP, GX_CLAMP,
|
||||||
|
GX_FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
GX_InitTexObjLOD(
|
||||||
|
&texture->texObj,
|
||||||
|
GX_NEAR, GX_NEAR,
|
||||||
|
0.0f, 0.0f, 0.0f,
|
||||||
|
GX_FALSE,
|
||||||
|
GX_FALSE,
|
||||||
|
GX_ANISO_1
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assertUnreachable("Unsupported texture format for Dolphin");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
texture->ready = true;
|
texture->ready = true;
|
||||||
#endif
|
#endif
|
||||||
@@ -238,7 +308,6 @@ void textureBind(texture_t *texture) {
|
|||||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||||
#elif DOLPHIN
|
#elif DOLPHIN
|
||||||
GX_LoadTexObj(&texture->texObj, GX_TEXMAP0);
|
GX_LoadTexObj(&texture->texObj, GX_TEXMAP0);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
TEXTURE_BOUND = texture;
|
TEXTURE_BOUND = texture;
|
||||||
}
|
}
|
||||||
@@ -254,10 +323,126 @@ void textureDispose(texture_t *texture) {
|
|||||||
#if DISPLAY_SDL2
|
#if DISPLAY_SDL2
|
||||||
glDeleteTextures(1, &texture->id);
|
glDeleteTextures(1, &texture->id);
|
||||||
#elif DOLPHIN
|
#elif DOLPHIN
|
||||||
if(texture->rgba) {
|
switch(texture->format) {
|
||||||
|
case TEXTURE_FORMAT_RGBA:
|
||||||
free(texture->rgba);
|
free(texture->rgba);
|
||||||
texture->rgba = NULL;
|
break;
|
||||||
|
|
||||||
|
case TEXTURE_FORMAT_ALPHA:
|
||||||
|
free(texture->alpha);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memoryZero(texture, sizeof(texture_t));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DOLPHIN
|
||||||
|
void textureDolphinUploadTEV() {
|
||||||
|
// 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
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!TEXTURE_BOUND) {
|
||||||
|
GX_SetNumTexGens(0);
|
||||||
|
GX_SetNumTevStages(1);
|
||||||
|
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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_SetTevOrder(
|
||||||
|
GX_TEVSTAGE0,
|
||||||
|
GX_TEXCOORD0,
|
||||||
|
GX_TEXMAP0,
|
||||||
|
GX_COLOR0A0
|
||||||
|
);
|
||||||
|
GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEXTURE_FORMAT_ALPHA:
|
||||||
|
// One TEV stage: vertex color * texture color
|
||||||
|
GX_SetNumTevStages(1);
|
||||||
|
GX_SetTevOrder(
|
||||||
|
GX_TEVSTAGE0,
|
||||||
|
GX_TEXCOORD0,
|
||||||
|
GX_TEXMAP0,
|
||||||
|
GX_COLOR0A0
|
||||||
|
);
|
||||||
|
|
||||||
|
// Color = vertex color
|
||||||
|
GX_SetTevColorIn(
|
||||||
|
GX_TEVSTAGE0,
|
||||||
|
GX_CC_RASC,
|
||||||
|
GX_CC_ZERO,
|
||||||
|
GX_CC_ZERO,
|
||||||
|
GX_CC_ZERO
|
||||||
|
);
|
||||||
|
GX_SetTevColorOp(
|
||||||
|
GX_TEVSTAGE0,
|
||||||
|
GX_TEV_ADD,
|
||||||
|
GX_TB_ZERO,
|
||||||
|
GX_CS_SCALE_1,
|
||||||
|
GX_TRUE,
|
||||||
|
GX_TEVPREV
|
||||||
|
);
|
||||||
|
|
||||||
|
// Alpha = vertex alpha * I8 intensity
|
||||||
|
GX_SetTevAlphaIn(
|
||||||
|
GX_TEVSTAGE0,
|
||||||
|
GX_CA_RASA,
|
||||||
|
GX_CA_ZERO,
|
||||||
|
GX_CA_TEXA,
|
||||||
|
GX_CA_ZERO
|
||||||
|
);
|
||||||
|
GX_SetTevAlphaOp(
|
||||||
|
GX_TEVSTAGE0,
|
||||||
|
GX_TEV_ADD,
|
||||||
|
GX_TB_ZERO,
|
||||||
|
GX_CS_SCALE_1,
|
||||||
|
GX_TRUE,
|
||||||
|
GX_TEVPREV
|
||||||
|
);
|
||||||
|
|
||||||
|
GX_SetBlendMode(
|
||||||
|
GX_BM_BLEND,
|
||||||
|
GX_BL_SRCALPHA,
|
||||||
|
GX_BL_INVSRCALPHA,
|
||||||
|
GX_LO_CLEAR
|
||||||
|
);
|
||||||
|
|
||||||
|
GX_SetColorUpdate(GX_TRUE);
|
||||||
|
GX_SetAlphaUpdate(GX_TRUE);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assertUnreachable("Unknown texture format in meshDraw");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -26,9 +26,10 @@ typedef struct {
|
|||||||
GLuint id;
|
GLuint id;
|
||||||
#elif DOLPHIN
|
#elif DOLPHIN
|
||||||
GXTexObj texObj;
|
GXTexObj texObj;
|
||||||
|
textureformat_t format;
|
||||||
union {
|
union {
|
||||||
u16 *rgba;
|
u16 *rgba;
|
||||||
|
u8 *alpha;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -84,3 +85,10 @@ void textureBind(texture_t *texture);
|
|||||||
* @param texture The texture to dispose.
|
* @param texture The texture to dispose.
|
||||||
*/
|
*/
|
||||||
void textureDispose(texture_t *texture);
|
void textureDispose(texture_t *texture);
|
||||||
|
|
||||||
|
#if DOLPHIN
|
||||||
|
/**
|
||||||
|
* Uploads the TEV settings for the currently bound texture.
|
||||||
|
*/
|
||||||
|
void textureDolphinUploadTEV();
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user