Improve and correct support for light distance attenuation

This commit is contained in:
fincs 2015-11-26 12:28:09 +01:00
parent b7daa13f59
commit cd39c3b8d1
4 changed files with 43 additions and 15 deletions

View File

@ -118,5 +118,4 @@ void C3D_LightSpotEnable(C3D_Light* light, bool enable);
void C3D_LightSpotDir(C3D_Light* light, float x, float y, float z);
void C3D_LightSpotLut(C3D_Light* light, C3D_LightLut* lut);
void C3D_LightDistAttnEnable(C3D_Light* light, bool enable);
void C3D_LightDistAttn(C3D_Light* light, float bias, float scale);
void C3D_LightDistAttnLut(C3D_Light* light, C3D_LightLut* lut);
void C3D_LightDistAttn(C3D_Light* light, C3D_LightLutDA* lut);

View File

@ -7,9 +7,23 @@ typedef struct
u32 data[256];
} C3D_LightLut;
typedef struct
{
C3D_LightLut lut;
float bias, scale;
} C3D_LightLutDA;
typedef float (* C3D_LightLutFunc)(float x, float param);
typedef float (* C3D_LightLutFuncDA)(float dist, float arg0, float arg1);
static inline float quadratic_dist_attn(float dist, float linear, float quad)
{
return 1.0f / (1.0f + linear*dist + quad*dist*dist);
}
void LightLut_FromArray(C3D_LightLut* lut, float* data);
void LightLut_FromFunc(C3D_LightLut* lut, C3D_LightLutFunc func, float param, bool negative);
void LightLutDA_Create(C3D_LightLutDA* lut, C3D_LightLutFuncDA func, float from, float to, float arg0, float arg1);
#define LightLut_Phong(lut, shininess) LightLut_FromFunc((lut), powf, (shininess), false)
#define LightLutDA_Quadratic(lut, from, to, linear, quad) LightLutDA_Create((lut), quadratic_dist_attn, (from), (to), (linear), (quad))

View File

@ -92,7 +92,7 @@ static void C3Di_EnableCommon(C3D_Light* light, bool enable, u32 bit)
C3D_LightEnv* env = light->parent;
u32* var = &env->conf.config[1];
if ((*var & bit) ^ bit)
if (enable == !(*var & bit))
return;
if (!enable)
@ -134,19 +134,14 @@ void C3D_LightDistAttnEnable(C3D_Light* light, bool enable)
C3Di_EnableCommon(light, enable, GPU_LC1_ATTNBIT(light->id));
}
void C3D_LightDistAttn(C3D_Light* light, float bias, float scale)
{
C3Di_EnableCommon(light, true, GPU_LC1_ATTNBIT(light->id));
light->conf.distAttnBias = f32tof20(bias);
light->conf.distAttnScale = f32tof20(scale);
light->flags |= C3DF_Light_Dirty;
}
void C3D_LightDistAttnLut(C3D_Light* light, C3D_LightLut* lut)
void C3D_LightDistAttn(C3D_Light* light, C3D_LightLutDA* lut)
{
bool hasLut = lut != NULL;
C3Di_EnableCommon(light, hasLut, GPU_LC1_ATTNBIT(light->id));
light->lut_DA = lut;
if (hasLut)
light->flags |= C3DF_Light_DADirty;
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;
}

View File

@ -44,3 +44,23 @@ void LightLut_FromFunc(C3D_LightLut* lut, C3D_LightLutFunc func, float param, bo
}
LightLut_FromArray(lut, data);
}
void LightLutDA_Create(C3D_LightLutDA* lut, C3D_LightLutFuncDA func, float from, float to, float arg0, float arg1)
{
int i;
float data[512];
data[511] = 0;
lut->scale = 1.0f / (to-from);
lut->bias = -from*lut->scale;
for (i = 0; i < 256; i ++)
{
float dist = ((float)i/255 - lut->bias) / lut->scale;
data[i] = func(dist, arg0, arg1);
if (i > 0)
data[i+255] = data[i]-data[i-1];
}
LightLut_FromArray(&lut->lut, data);
}