Begin adding Gas rendering support {incomplete/not fully RE'd}

This commit is contained in:
fincs 2017-07-13 21:53:18 +02:00
parent 52cdcb351a
commit 81ca5d3575
4 changed files with 203 additions and 4 deletions

View File

@ -7,6 +7,12 @@ typedef struct
u32 data[128];
} C3D_FogLut;
typedef struct
{
u32 diff[8];
u32 color[8];
} C3D_GasLut;
static inline float FogLut_CalcZ(float depth, float near, float far)
{
return far*near/(depth*(far-near)+near);
@ -18,3 +24,14 @@ void FogLut_Exp(C3D_FogLut* lut, float density, float gradient, float near, floa
void C3D_FogGasMode(GPU_FOGMODE fogMode, GPU_GASMODE gasMode, bool zFlip);
void C3D_FogColor(u32 color);
void C3D_FogLutBind(C3D_FogLut* lut);
void GasLut_FromArray(C3D_GasLut* lut, const u32 data[9]);
void C3D_GasAttn(float value);
void C3D_GasAccMax(float value);
void C3D_GasDeltaZ(float value);
void C3D_GasLightPlanar(float min, float max, float attn);
void C3D_GasLightView(float min, float max, float attn);
void C3D_GasLightDirection(float dotp);
void C3D_GasLutInput(GPU_GASLUTINPUT input);
void C3D_GasLutBind(C3D_GasLut* lut);

View File

@ -36,6 +36,11 @@ __attribute__((weak)) void C3Di_ProcTexDirty(C3D_Context* ctx)
(void)ctx;
}
__attribute__((weak)) void C3Di_GasUpdate(C3D_Context* ctx)
{
(void)ctx;
}
static void C3Di_AptEventHook(APT_HookType hookType, C3D_UNUSED void* param)
{
C3D_Context* ctx = C3Di_GetContext();
@ -51,7 +56,7 @@ static void C3Di_AptEventHook(APT_HookType hookType, C3D_UNUSED void* param)
{
ctx->flags |= C3DiF_AttrInfo | C3DiF_BufInfo | C3DiF_Effect | C3DiF_FrameBuf
| C3DiF_Viewport | C3DiF_Scissor | C3DiF_Program | C3DiF_VshCode | C3DiF_GshCode
| C3DiF_TexAll | C3DiF_TexEnvBuf | C3DiF_TexEnvAll | C3DiF_LightEnv;
| C3DiF_TexAll | C3DiF_TexEnvBuf | C3DiF_TexEnvAll | C3DiF_LightEnv | C3DiF_Gas;
C3Di_DirtyUniforms(GPU_VERTEX_SHADER);
C3Di_DirtyUniforms(GPU_GEOMETRY_SHADER);
@ -61,6 +66,8 @@ static void C3Di_AptEventHook(APT_HookType hookType, C3D_UNUSED void* param)
C3D_LightEnv* env = ctx->lightEnv;
if (ctx->fogLut)
ctx->flags |= C3DiF_FogLut;
if (ctx->gasLut)
ctx->flags |= C3DiF_GasLut;
if (env)
C3Di_LightEnvDirty(env);
C3Di_ProcTexDirty(ctx);
@ -233,9 +240,14 @@ void C3Di_UpdateContext(void)
if (ctx->flags & C3DiF_TexStatus)
{
ctx->flags &= ~C3DiF_TexStatus;
GPUCMD_AddWrite(GPUREG_TEXUNIT_CONFIG, ctx->texConfig);
GPUCMD_AddMaskedWrite(GPUREG_TEXUNIT_CONFIG, 0xB, ctx->texConfig);
// Clear texture cache if requested *after* configuring texture units
if (ctx->texConfig & BIT(16))
{
ctx->texConfig &= ~BIT(16);
GPUCMD_AddMaskedWrite(GPUREG_TEXUNIT_CONFIG, 0x4, BIT(16));
}
GPUCMD_AddWrite(GPUREG_TEXUNIT0_SHADOW, ctx->texShadow);
ctx->texConfig &= ~BIT(16); // Remove clear-texture-cache flag
}
if (ctx->flags & (C3DiF_ProcTex | C3DiF_ProcTexColorLut | C3DiF_ProcTexLutAll))
@ -249,7 +261,7 @@ void C3Di_UpdateContext(void)
GPUCMD_AddWrite(GPUREG_FOG_COLOR, ctx->fogClr);
}
if (ctx->flags & C3DiF_FogLut)
if ((ctx->flags & C3DiF_FogLut) && (ctx->texEnvBuf&7) != GPU_NO_FOG)
{
ctx->flags &= ~C3DiF_FogLut;
if (ctx->fogLut)
@ -259,6 +271,9 @@ void C3Di_UpdateContext(void)
}
}
if ((ctx->texEnvBuf&7) == GPU_GAS)
C3Di_GasUpdate(ctx);
if (ctx->flags & C3DiF_TexEnvAll)
{
for (i = 0; i < 6; i ++)

160
source/gas.c Normal file
View File

@ -0,0 +1,160 @@
#include "internal.h"
static inline u32 calc_diff(u32 a, u32 b, int pos)
{
float fa = ((a>>pos)&0xFF)/255.0f;
float fb = ((b>>pos)&0xFF)/255.0f;
float x = fb-fa;
u32 diff = 0;
if (x < 0)
{
diff = 0x80;
x = -x;
}
diff |= (u32)(x*0x7F);
return diff<<pos;
}
static inline u32 conv_u8(float x, int pos)
{
if (x < 0.0f) x = 0.0f;
else if (x > 1.0f) x = 1.0f;
return ((u32)x*255)<<pos;
}
static inline u32 color_diff(u32 a, u32 b)
{
return calc_diff(a,b,0) | calc_diff(a,b,8) | calc_diff(a,b,16);
}
void GasLut_FromArray(C3D_GasLut* lut, const u32 data[9])
{
int i;
for (i = 0; i <= 8; i ++)
{
if (i < 8)
lut->color[i] = data[i];
if (i > 0)
lut->diff[i-1] = color_diff(data[i-1], data[i]);
}
}
void C3D_GasAttn(float value)
{
C3D_Context* ctx = C3Di_GetContext();
if (!(ctx->flags & C3DiF_Active))
return;
ctx->flags |= C3DiF_Gas;
ctx->gasAttn = f32tof16(value);
}
void C3D_GasAccMax(float value)
{
C3D_Context* ctx = C3Di_GetContext();
if (!(ctx->flags & C3DiF_Active))
return;
ctx->flags |= C3DiF_Gas;
ctx->gasAccMax = f32tof16(1.0f / value);
}
void C3D_GasDeltaZ(float value)
{
C3D_Context* ctx = C3Di_GetContext();
if (!(ctx->flags & C3DiF_Active))
return;
ctx->flags |= C3DiF_Gas;
ctx->gasDeltaZ = (u32)(value*0x100) & 0xFFFFFF;
ctx->gasDeltaZ |= 2<<24;
}
void C3D_GasLightPlanar(float min, float max, float attn)
{
C3D_Context* ctx = C3Di_GetContext();
if (!(ctx->flags & C3DiF_Active))
return;
ctx->flags |= C3DiF_Gas;
ctx->gasLightXY = conv_u8(min,0) | conv_u8(max,8) | conv_u8(attn,16);
}
void C3D_GasLightView(float min, float max, float attn)
{
C3D_Context* ctx = C3Di_GetContext();
if (!(ctx->flags & C3DiF_Active))
return;
ctx->flags |= C3DiF_Gas;
ctx->gasLightZ = conv_u8(min,0) | conv_u8(max,8) | conv_u8(attn,16);
}
void C3D_GasLightDirection(float dotp)
{
C3D_Context* ctx = C3Di_GetContext();
if (!(ctx->flags & C3DiF_Active))
return;
ctx->flags |= C3DiF_Gas;
ctx->gasLightZColor &= ~0xFF;
ctx->gasLightZColor |= conv_u8(dotp,0);
}
void C3D_GasLutInput(GPU_GASLUTINPUT input)
{
C3D_Context* ctx = C3Di_GetContext();
if (!(ctx->flags & C3DiF_Active))
return;
ctx->flags |= C3DiF_Gas;
ctx->gasLightZColor &= ~0x100;
ctx->gasLightZColor |= (input&1)<<8;
}
void C3D_GasLutBind(C3D_GasLut* lut)
{
C3D_Context* ctx = C3Di_GetContext();
if (!(ctx->flags & C3DiF_Active))
return;
if (lut)
{
ctx->flags |= C3DiF_GasLut;
ctx->gasLut = lut;
} else
ctx->flags &= ~C3DiF_GasLut;
}
void C3Di_GasUpdate(C3D_Context* ctx)
{
//__builtin_printf("updgasstate %08lX\n", ctx->flags);
//for(;;);
if (ctx->flags & C3DiF_Gas)
{
ctx->flags &= ~C3DiF_Gas;
GPUCMD_AddWrite(GPUREG_GAS_ATTENUATION, ctx->gasAttn);
//GPUCMD_AddWrite(GPUREG_GAS_ACCMAX, ctx->gasAccMax);
GPUCMD_AddWrite(GPUREG_GAS_LIGHT_XY, ctx->gasLightXY);
GPUCMD_AddWrite(GPUREG_GAS_LIGHT_Z, ctx->gasLightZ);
GPUCMD_AddWrite(GPUREG_GAS_LIGHT_Z_COLOR, ctx->gasLightZColor);
GPUCMD_AddWrite(GPUREG_GAS_DELTAZ_DEPTH, ctx->gasDeltaZ);
}
if (ctx->flags & C3DiF_GasLut)
{
ctx->flags &= ~C3DiF_GasLut;
if (ctx->gasLut)
{
GPUCMD_AddWrite(GPUREG_GAS_LUT_INDEX, 0);
GPUCMD_AddWrites(GPUREG_GAS_LUT_DATA, (u32*)ctx->gasLut, 16);
}
}
}

View File

@ -52,6 +52,10 @@ typedef struct
u32 fogClr;
C3D_FogLut* fogLut;
u16 gasAttn, gasAccMax;
u32 gasLightXY, gasLightZ, gasLightZColor, gasDeltaZ;
C3D_GasLut* gasLut;
C3D_ProcTex* procTex;
C3D_ProcTexLut* procTexLut[3];
C3D_ProcTexColorLut* procTexColorLut;
@ -83,6 +87,8 @@ enum
C3DiF_ProcTex = BIT(15),
C3DiF_ProcTexColorLut = BIT(16),
C3DiF_FogLut = BIT(17),
C3DiF_Gas = BIT(18),
C3DiF_GasLut = BIT(19),
#define C3DiF_ProcTexLut(n) BIT(20+(n))
C3DiF_ProcTexLutAll = 7 << 20,
@ -115,6 +121,7 @@ void C3Di_FrameBufBind(C3D_FrameBuf* fb);
void C3Di_TexEnvBind(int id, C3D_TexEnv* env);
void C3Di_SetTex(int unit, C3D_Tex* tex);
void C3Di_EffectBind(C3D_Effect* effect);
void C3Di_GasUpdate(C3D_Context* ctx);
void C3Di_LightMtlBlend(C3D_Light* light);