From cd39c3b8d1ac4e4866460aeee1bc85c2ad070958 Mon Sep 17 00:00:00 2001 From: fincs Date: Thu, 26 Nov 2015 12:28:09 +0100 Subject: [PATCH] Improve and correct support for light distance attenuation --- include/c3d/light.h | 3 +-- include/c3d/lightlut.h | 14 ++++++++++++++ source/light.c | 21 ++++++++------------- source/lightlut.c | 20 ++++++++++++++++++++ 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/include/c3d/light.h b/include/c3d/light.h index f91f910..f07141c 100644 --- a/include/c3d/light.h +++ b/include/c3d/light.h @@ -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); diff --git a/include/c3d/lightlut.h b/include/c3d/lightlut.h index b718b97..b9e0a5b 100644 --- a/include/c3d/lightlut.h +++ b/include/c3d/lightlut.h @@ -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)) diff --git a/source/light.c b/source/light.c index 99252c5..f9e4b96 100644 --- a/source/light.c +++ b/source/light.c @@ -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; } diff --git a/source/lightlut.c b/source/lightlut.c index 400af86..b49534a 100644 --- a/source/lightlut.c +++ b/source/lightlut.c @@ -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); +}