156 lines
3.8 KiB
C
156 lines
3.8 KiB
C
#include "internal.h"
|
|
|
|
void C3Di_LightMtlBlend(C3D_Light* light)
|
|
{
|
|
int i;
|
|
C3D_Material* mtl = &light->parent->material;
|
|
C3D_LightMatConf* conf = &light->conf.material;
|
|
memset(conf, 0, sizeof(*conf));
|
|
|
|
for (i = 0; i < 3; i ++)
|
|
{
|
|
conf->specular0 |= ((u32)(255*(mtl->specular0[i]*light->color[i]))) << (i*10);
|
|
conf->specular1 |= ((u32)(255*(mtl->specular1[i]*light->color[i]))) << (i*10);
|
|
conf->diffuse |= ((u32)(255*(mtl->diffuse[i] *light->color[i]))) << (i*10);
|
|
conf->ambient |= ((u32)(255*(mtl->ambient[i] *light->color[i]))) << (i*10);
|
|
}
|
|
}
|
|
|
|
int C3D_LightInit(C3D_Light* light, C3D_LightEnv* env)
|
|
{
|
|
int i;
|
|
memset(light, 0, sizeof(*light));
|
|
|
|
for (i = 0; i < 8; i ++)
|
|
if (!env->lights[i])
|
|
break;
|
|
if (i == 8) return -1;
|
|
|
|
env->lights[i] = light;
|
|
light->flags = C3DF_Light_Enabled | C3DF_Light_Dirty | C3DF_Light_MatDirty;
|
|
light->id = i;
|
|
light->parent = env;
|
|
|
|
env->flags |= C3DF_LightEnv_LCDirty;
|
|
return i;
|
|
}
|
|
|
|
void C3D_LightEnable(C3D_Light* light, bool enable)
|
|
{
|
|
if ((light->flags & C3DF_Light_Enabled) == (enable?C3DF_Light_Enabled:0))
|
|
return;
|
|
|
|
if (enable)
|
|
light->flags |= C3DF_Light_Enabled;
|
|
else
|
|
light->flags &= ~C3DF_Light_Enabled;
|
|
|
|
light->parent->flags |= C3DF_LightEnv_LCDirty;
|
|
}
|
|
|
|
void C3D_LightTwoSideDiffuse(C3D_Light* light, bool enable)
|
|
{
|
|
if (enable)
|
|
light->conf.config |= BIT(1);
|
|
else
|
|
light->conf.config &= ~BIT(1);
|
|
light->flags |= C3DF_Light_Dirty;
|
|
}
|
|
|
|
void C3D_LightGeoFactor(C3D_Light* light, int id, bool enable)
|
|
{
|
|
id = 2 + (id&1);
|
|
if (enable)
|
|
light->conf.config |= BIT(id);
|
|
else
|
|
light->conf.config &= ~BIT(id);
|
|
light->flags |= C3DF_Light_Dirty;
|
|
}
|
|
|
|
void C3D_LightColor(C3D_Light* light, float r, float g, float b)
|
|
{
|
|
light->color[0] = b;
|
|
light->color[1] = g;
|
|
light->color[2] = r;
|
|
light->flags |= C3DF_Light_MatDirty;
|
|
}
|
|
|
|
void C3D_LightPosition(C3D_Light* light, C3D_FVec* pos)
|
|
{
|
|
// Enable/disable positional light depending on W coordinate
|
|
light->conf.config &= ~BIT(0);
|
|
light->conf.config |= (pos->w == 0.0f);
|
|
light->conf.position[0] = f32tof16(pos->x);
|
|
light->conf.position[1] = f32tof16(pos->y);
|
|
light->conf.position[2] = f32tof16(pos->z);
|
|
light->flags |= C3DF_Light_Dirty;
|
|
}
|
|
|
|
static void C3Di_EnableCommon(C3D_Light* light, bool enable, u32 bit)
|
|
{
|
|
C3D_LightEnv* env = light->parent;
|
|
u32* var = &env->conf.config[1];
|
|
|
|
if (enable == !(*var & bit))
|
|
return;
|
|
|
|
if (!enable)
|
|
*var |= bit;
|
|
else
|
|
*var &= ~bit;
|
|
|
|
env->flags |= C3DF_LightEnv_Dirty;
|
|
}
|
|
|
|
void C3D_LightShadowEnable(C3D_Light* light, bool enable)
|
|
{
|
|
C3Di_EnableCommon(light, enable, GPU_LC1_SHADOWBIT(light->id));
|
|
}
|
|
|
|
void C3D_LightSpotEnable(C3D_Light* light, bool enable)
|
|
{
|
|
C3Di_EnableCommon(light, enable, GPU_LC1_SPOTBIT(light->id));
|
|
}
|
|
|
|
static inline u16 floattofix2_11(float x)
|
|
{
|
|
return (u16)((s32)(x * (1U<<11)) & 0x1FFF);
|
|
}
|
|
|
|
void C3D_LightSpotDir(C3D_Light* light, float x, float y, float z)
|
|
{
|
|
C3Di_EnableCommon(light, true, GPU_LC1_SPOTBIT(light->id));
|
|
C3D_FVec vec = FVec3_New(-x, -y, -z);
|
|
vec = FVec3_Normalize(vec);
|
|
light->conf.spotDir[0] = floattofix2_11(vec.x);
|
|
light->conf.spotDir[1] = floattofix2_11(vec.y);
|
|
light->conf.spotDir[2] = floattofix2_11(vec.z);
|
|
light->flags |= C3DF_Light_Dirty;
|
|
}
|
|
|
|
void C3D_LightSpotLut(C3D_Light* light, C3D_LightLut* lut)
|
|
{
|
|
bool hasLut = lut != NULL;
|
|
C3Di_EnableCommon(light, hasLut, GPU_LC1_SPOTBIT(light->id));
|
|
light->lut_SP = lut;
|
|
if (hasLut)
|
|
light->flags |= C3DF_Light_SPDirty;
|
|
}
|
|
|
|
void C3D_LightDistAttnEnable(C3D_Light* light, bool enable)
|
|
{
|
|
C3Di_EnableCommon(light, enable, GPU_LC1_ATTNBIT(light->id));
|
|
}
|
|
|
|
void C3D_LightDistAttn(C3D_Light* light, C3D_LightLutDA* lut)
|
|
{
|
|
bool hasLut = lut != NULL;
|
|
C3Di_EnableCommon(light, hasLut, GPU_LC1_ATTNBIT(light->id));
|
|
if (!hasLut) return;
|
|
|
|
light->conf.distAttnBias = f32tof20(lut->bias);
|
|
light->conf.distAttnScale = f32tof20(lut->scale);
|
|
light->lut_DA = &lut->lut;
|
|
light->flags |= C3DF_Light_Dirty | C3DF_Light_DADirty;
|
|
}
|