Add Fog rendering support
This commit is contained in:
parent
53111971e0
commit
35d82d95be
20
include/c3d/fog.h
Normal file
20
include/c3d/fog.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
#include <math.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 data[128];
|
||||
} C3D_FogLut;
|
||||
|
||||
static inline float FogLut_CalcZ(float depth, float near, float far)
|
||||
{
|
||||
return far*near/(depth*(far-near)+near);
|
||||
}
|
||||
|
||||
void FogLut_FromArray(C3D_FogLut* lut, const float data[256]);
|
||||
void FogLut_Exp(C3D_FogLut* lut, float density, float gradient, float near, float far);
|
||||
|
||||
void C3D_FogGasMode(GPU_FOGMODE fogMode, GPU_GASMODE gasMode, bool zFlip);
|
||||
void C3D_FogColor(u32 color);
|
||||
void C3D_FogLutBind(C3D_FogLut* lut);
|
@ -24,6 +24,7 @@ extern "C" {
|
||||
#include "c3d/proctex.h"
|
||||
#include "c3d/light.h"
|
||||
#include "c3d/lightlut.h"
|
||||
#include "c3d/fog.h"
|
||||
|
||||
#include "c3d/framebuffer.h"
|
||||
#include "c3d/renderbuffer.h" // Deprecated
|
||||
|
@ -59,6 +59,8 @@ static void C3Di_AptEventHook(APT_HookType hookType, C3D_UNUSED void* param)
|
||||
ctx->fixedAttribDirty |= ctx->fixedAttribEverDirty;
|
||||
|
||||
C3D_LightEnv* env = ctx->lightEnv;
|
||||
if (ctx->fogLut)
|
||||
ctx->flags |= C3DiF_FogLut;
|
||||
if (env)
|
||||
C3Di_LightEnvDirty(env);
|
||||
C3Di_ProcTexDirty(ctx);
|
||||
@ -115,6 +117,8 @@ bool C3D_Init(size_t cmdBufSize)
|
||||
ctx->texShadow = BIT(0);
|
||||
ctx->texEnvBuf = 0;
|
||||
ctx->texEnvBufClr = 0xFFFFFFFF;
|
||||
ctx->fogClr = 0;
|
||||
ctx->fogLut = NULL;
|
||||
|
||||
for (i = 0; i < 3; i ++)
|
||||
ctx->tex[i] = NULL;
|
||||
@ -240,8 +244,19 @@ void C3Di_UpdateContext(void)
|
||||
if (ctx->flags & C3DiF_TexEnvBuf)
|
||||
{
|
||||
ctx->flags &= ~C3DiF_TexEnvBuf;
|
||||
GPUCMD_AddMaskedWrite(GPUREG_TEXENV_UPDATE_BUFFER, 0x2, ctx->texEnvBuf);
|
||||
GPUCMD_AddMaskedWrite(GPUREG_TEXENV_UPDATE_BUFFER, 0x7, ctx->texEnvBuf);
|
||||
GPUCMD_AddWrite(GPUREG_TEXENV_BUFFER_COLOR, ctx->texEnvBufClr);
|
||||
GPUCMD_AddWrite(GPUREG_FOG_COLOR, ctx->fogClr);
|
||||
}
|
||||
|
||||
if (ctx->flags & C3DiF_FogLut)
|
||||
{
|
||||
ctx->flags &= ~C3DiF_FogLut;
|
||||
if (ctx->fogLut)
|
||||
{
|
||||
GPUCMD_AddWrite(GPUREG_FOG_LUT_INDEX, 0);
|
||||
GPUCMD_AddWrites(GPUREG_FOG_LUT_DATA0, ctx->fogLut->data, 128);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->flags & C3DiF_TexEnvAll)
|
||||
|
82
source/fog.c
Normal file
82
source/fog.c
Normal file
@ -0,0 +1,82 @@
|
||||
#include "internal.h"
|
||||
|
||||
void FogLut_FromArray(C3D_FogLut* lut, const float data[256])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 128; i ++)
|
||||
{
|
||||
float in = data[i], diff = data[i+128];
|
||||
|
||||
u32 val = 0;
|
||||
if (in > 0.0f)
|
||||
{
|
||||
in *= 0x800;
|
||||
val = (in < 0x800) ? (u32)in : 0x7FF;
|
||||
}
|
||||
|
||||
u32 val2 = 0;
|
||||
if (diff != 0.0f)
|
||||
{
|
||||
diff *= 0x800;
|
||||
if (diff < -0x1000) diff = -0x1000;
|
||||
else if (diff > 0xFFF) diff = 0xFFF;
|
||||
val2 = (s32)diff & 0x1FFF;
|
||||
}
|
||||
|
||||
lut->data[i] = val2 | (val << 13);
|
||||
}
|
||||
}
|
||||
|
||||
void FogLut_Exp(C3D_FogLut* lut, float density, float gradient, float near, float far)
|
||||
{
|
||||
int i;
|
||||
float data[256];
|
||||
for (i = 0; i <= 128; i ++)
|
||||
{
|
||||
float x = FogLut_CalcZ(i/128.0f, near, far);
|
||||
float val = expf(-powf(density*x, gradient));
|
||||
if (i < 128)
|
||||
data[i] = val;
|
||||
if (i > 0)
|
||||
data[i+127] = val-data[i-1];
|
||||
}
|
||||
FogLut_FromArray(lut, data);
|
||||
}
|
||||
|
||||
void C3D_FogGasMode(GPU_FOGMODE fogMode, GPU_GASMODE gasMode, bool zFlip)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
ctx->flags |= C3DiF_TexEnvBuf;
|
||||
ctx->texEnvBuf &= ~0x100FF;
|
||||
ctx->texEnvBuf |= (fogMode&7) | ((gasMode&1)<<3) | (zFlip ? BIT(16) : 0);
|
||||
}
|
||||
|
||||
void C3D_FogColor(u32 color)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
ctx->flags |= C3DiF_TexEnvBuf;
|
||||
ctx->fogClr = color;
|
||||
}
|
||||
|
||||
void C3D_FogLutBind(C3D_FogLut* lut)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
if (lut)
|
||||
{
|
||||
ctx->flags |= C3DiF_FogLut;
|
||||
ctx->fogLut = lut;
|
||||
} else
|
||||
ctx->flags &= ~C3DiF_FogLut;
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
#include <c3d/light.h>
|
||||
#include <c3d/framebuffer.h>
|
||||
#include <c3d/texenv.h>
|
||||
#include <c3d/fog.h>
|
||||
|
||||
#define C3D_UNUSED __attribute__((unused))
|
||||
|
||||
@ -48,6 +49,8 @@ typedef struct
|
||||
C3D_TexEnv texEnv[6];
|
||||
|
||||
u32 texEnvBuf, texEnvBufClr;
|
||||
u32 fogClr;
|
||||
C3D_FogLut* fogLut;
|
||||
|
||||
C3D_ProcTex* procTex;
|
||||
C3D_ProcTexLut* procTexLut[3];
|
||||
@ -79,6 +82,7 @@ enum
|
||||
C3DiF_TexStatus = BIT(14),
|
||||
C3DiF_ProcTex = BIT(15),
|
||||
C3DiF_ProcTexColorLut = BIT(16),
|
||||
C3DiF_FogLut = BIT(17),
|
||||
|
||||
#define C3DiF_ProcTexLut(n) BIT(20+(n))
|
||||
C3DiF_ProcTexLutAll = 7 << 20,
|
||||
|
Loading…
Reference in New Issue
Block a user