From 9731ca611cb83d40d9615ef1ab035c521754cf48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Sat, 23 Sep 2023 22:00:22 +0200 Subject: [PATCH] render: finalize phong shader --- demos/99-material.c | 5 ++++- engine/art/shaders/fs_32_4_model.glsl | 17 ++++++++++++----- engine/bind/v4k.lua | 2 ++ engine/joint/v4k.h | 18 ++++++++++++++---- engine/split/v4k_render.c | 8 ++++---- engine/split/v4k_scene.c | 8 ++++++++ engine/split/v4k_scene.h | 2 ++ engine/v4k.c | 16 ++++++++++++---- engine/v4k.h | 2 ++ 9 files changed, 60 insertions(+), 18 deletions(-) diff --git a/demos/99-material.c b/demos/99-material.c index 0fd5413..f5e16ef 100644 --- a/demos/99-material.c +++ b/demos/99-material.c @@ -42,6 +42,9 @@ int main() { // create point light light_t* l = scene_spawn_light(); light_type(l, LIGHT_SPOT); + light_ambient(l, vec3(0.03,0.03,0.06)); + light_specular(l, scale3(vec3(1,1.0,0.2), 2.5f)); + light_power(l, 56.f); while(window_swap() && !input(KEY_ESC)) { // draw environment @@ -51,7 +54,7 @@ int main() { // update video video_decode( v ); - // update light position + // update light data light_teleport(l, cam.position); light_dir(l, cam.look); diff --git a/engine/art/shaders/fs_32_4_model.glsl b/engine/art/shaders/fs_32_4_model.glsl index e90bf22..a85f0b7 100644 --- a/engine/art/shaders/fs_32_4_model.glsl +++ b/engine/art/shaders/fs_32_4_model.glsl @@ -41,6 +41,7 @@ struct light_t { vec3 ambient; vec3 pos; vec3 dir; + float power; float innerCone; float outerCone; @@ -75,8 +76,7 @@ vec3 shading_phong(light_t l) { float distance = length(toLight); attenuation = 1.0 / (l.constant + l.linear * distance + l.quadratic * (distance * distance)); - // Calculate spotlight effect - float angle = dot(l.dir, normalize(-lightDir)); + float angle = dot(l.dir, -lightDir); if (angle > l.outerCone) { float intensity = (angle-l.outerCone)/(l.innerCone-l.outerCone); attenuation *= clamp(intensity, 0.0, 1.0); @@ -85,10 +85,17 @@ vec3 shading_phong(light_t l) { } } - float diffuse = max(dot(v_normal, lightDir), 0.0); + // fast-rejection for faraway vertices + if (attenuation <= 0.01) { + return vec3(0,0,0); + } + + vec3 n = normalize(v_normal_ws); + + float diffuse = max(dot(n, lightDir), 0.0); vec3 halfVec = normalize(lightDir + u_cam_dir); - float specular = pow(max(dot(v_normal, halfVec), 0.0), 32); + float specular = pow(max(dot(n, halfVec), 0.0), l.power); return (attenuation*l.ambient + diffuse*attenuation*l.diffuse + specular*attenuation*l.specular); } @@ -107,7 +114,7 @@ vec3 lighting() { } void main() { - vec3 n = /*normalize*/(v_normal); + vec3 n = normalize(v_normal_ws); vec4 lit = vec4(1.0, 1.0, 1.0, 1.0); // SH lighting diff --git a/engine/bind/v4k.lua b/engine/bind/v4k.lua index 44d7396..fadf326 100644 --- a/engine/bind/v4k.lua +++ b/engine/bind/v4k.lua @@ -2706,6 +2706,7 @@ vec3 pos, dir; struct { float constant, linear, quadratic; } falloff; +float specularPower; float innerCone, outerCone; bool cached; } light_t; @@ -2716,6 +2717,7 @@ bool cached; void light_ambient(light_t* l, vec3 color); void light_teleport(light_t* l, vec3 pos); void light_dir(light_t* l, vec3 dir); + void light_power(light_t* l, float power); void light_falloff(light_t* l, float constant, float linear, float quadratic); void light_cone(light_t* l, float innerCone, float outerCone); void light_update(unsigned num_lights, light_t *lv); diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 7183959..23770d4 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -17177,6 +17177,7 @@ typedef struct light_t { struct { float constant, linear, quadratic; } falloff; + float specularPower; float innerCone, outerCone; //@todo: cookie, flare @@ -17192,6 +17193,7 @@ API void light_specular(light_t* l, vec3 color); API void light_ambient(light_t* l, vec3 color); API void light_teleport(light_t* l, vec3 pos); API void light_dir(light_t* l, vec3 dir); +API void light_power(light_t* l, float power); API void light_falloff(light_t* l, float constant, float linear, float quadratic); API void light_cone(light_t* l, float innerCone, float outerCone); API void light_update(unsigned num_lights, light_t *lv); @@ -343307,21 +343309,21 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view, glUniformMatrix4fv( loc, 1, GL_FALSE, vp); } if( (loc = glGetUniformLocation(shader, "u_cam_pos")) >= 0 ) { - vec3 pos = vec3(view[3], view[6], view[9]); + vec3 pos = vec3(view[12], view[13], view[14]); glUniform3fv( loc, 1, &pos.x ); } else if( (loc = glGetUniformLocation(shader, "cam_pos")) >= 0 ) { - vec3 pos = vec3(view[3], view[6], view[9]); + vec3 pos = vec3(view[12], view[13], view[14]); glUniform3fv( loc, 1, &pos.x ); } if( (loc = glGetUniformLocation(shader, "u_cam_dir")) >= 0 ) { - vec3 dir = vec3(view[0], view[1], view[2]); + vec3 dir = norm3(vec3(view[2], view[6], view[10])); glUniform3fv( loc, 1, &dir.x ); } else if( (loc = glGetUniformLocation(shader, "cam_dir")) >= 0 ) { - vec3 dir = vec3(view[0], view[1], view[2]); + vec3 dir = norm3(vec3(view[2], view[6], view[10])); glUniform3fv( loc, 1, &dir.x ); } #if 0 @@ -345235,6 +345237,7 @@ light_t light() { l.falloff.constant = 1.0f; l.falloff.linear = 0.09f; l.falloff.quadratic = 0.0032f; + l.specularPower = 32.f; l.innerCone = 0.9f; // 25 deg l.outerCone = 0.85f; // 31 deg @@ -345271,6 +345274,11 @@ void light_dir(light_t* l, vec3 dir) { l->dir = dir; } +void light_power(light_t* l, float power) { + l->cached = 0; + l->specularPower = power; +} + void light_falloff(light_t* l, float constant, float linear, float quadratic) { l->cached = 0; l->falloff.constant = constant; @@ -345279,6 +345287,7 @@ void light_falloff(light_t* l, float constant, float linear, float quadratic) { } void light_cone(light_t* l, float innerCone, float outerCone) { + l->cached = 0; l->innerCone = acos(innerCone); l->outerCone = acos(outerCone); } @@ -345294,6 +345303,7 @@ void light_update(unsigned num_lights, light_t *lv) { shader_vec3(va("u_lights[%d].diffuse", i), lv[i].diffuse); shader_vec3(va("u_lights[%d].specular", i), lv[i].specular); shader_vec3(va("u_lights[%d].ambient", i), lv[i].ambient); + shader_float(va("u_lights[%d].power", i), lv[i].specularPower); shader_float(va("u_lights[%d].constant", i), lv[i].falloff.constant); shader_float(va("u_lights[%d].linear", i), lv[i].falloff.linear); shader_float(va("u_lights[%d].quadratic", i), lv[i].falloff.quadratic); diff --git a/engine/split/v4k_render.c b/engine/split/v4k_render.c index 4329f23..fb6f05d 100644 --- a/engine/split/v4k_render.c +++ b/engine/split/v4k_render.c @@ -3684,21 +3684,21 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view, glUniformMatrix4fv( loc, 1, GL_FALSE, vp); } if( (loc = glGetUniformLocation(shader, "u_cam_pos")) >= 0 ) { - vec3 pos = vec3(view[3], view[6], view[9]); + vec3 pos = vec3(view[12], view[13], view[14]); glUniform3fv( loc, 1, &pos.x ); } else if( (loc = glGetUniformLocation(shader, "cam_pos")) >= 0 ) { - vec3 pos = vec3(view[3], view[6], view[9]); + vec3 pos = vec3(view[12], view[13], view[14]); glUniform3fv( loc, 1, &pos.x ); } if( (loc = glGetUniformLocation(shader, "u_cam_dir")) >= 0 ) { - vec3 dir = vec3(view[0], view[1], view[2]); + vec3 dir = norm3(vec3(view[2], view[6], view[10])); glUniform3fv( loc, 1, &dir.x ); } else if( (loc = glGetUniformLocation(shader, "cam_dir")) >= 0 ) { - vec3 dir = vec3(view[0], view[1], view[2]); + vec3 dir = norm3(vec3(view[2], view[6], view[10])); glUniform3fv( loc, 1, &dir.x ); } #if 0 diff --git a/engine/split/v4k_scene.c b/engine/split/v4k_scene.c index ee8e6c9..7e5bf67 100644 --- a/engine/split/v4k_scene.c +++ b/engine/split/v4k_scene.c @@ -248,6 +248,7 @@ light_t light() { l.falloff.constant = 1.0f; l.falloff.linear = 0.09f; l.falloff.quadratic = 0.0032f; + l.specularPower = 32.f; l.innerCone = 0.9f; // 25 deg l.outerCone = 0.85f; // 31 deg @@ -284,6 +285,11 @@ void light_dir(light_t* l, vec3 dir) { l->dir = dir; } +void light_power(light_t* l, float power) { + l->cached = 0; + l->specularPower = power; +} + void light_falloff(light_t* l, float constant, float linear, float quadratic) { l->cached = 0; l->falloff.constant = constant; @@ -292,6 +298,7 @@ void light_falloff(light_t* l, float constant, float linear, float quadratic) { } void light_cone(light_t* l, float innerCone, float outerCone) { + l->cached = 0; l->innerCone = acos(innerCone); l->outerCone = acos(outerCone); } @@ -307,6 +314,7 @@ void light_update(unsigned num_lights, light_t *lv) { shader_vec3(va("u_lights[%d].diffuse", i), lv[i].diffuse); shader_vec3(va("u_lights[%d].specular", i), lv[i].specular); shader_vec3(va("u_lights[%d].ambient", i), lv[i].ambient); + shader_float(va("u_lights[%d].power", i), lv[i].specularPower); shader_float(va("u_lights[%d].constant", i), lv[i].falloff.constant); shader_float(va("u_lights[%d].linear", i), lv[i].falloff.linear); shader_float(va("u_lights[%d].quadratic", i), lv[i].falloff.quadratic); diff --git a/engine/split/v4k_scene.h b/engine/split/v4k_scene.h index 480fe39..f827f0e 100644 --- a/engine/split/v4k_scene.h +++ b/engine/split/v4k_scene.h @@ -71,6 +71,7 @@ typedef struct light_t { struct { float constant, linear, quadratic; } falloff; + float specularPower; float innerCone, outerCone; //@todo: cookie, flare @@ -86,6 +87,7 @@ API void light_specular(light_t* l, vec3 color); API void light_ambient(light_t* l, vec3 color); API void light_teleport(light_t* l, vec3 pos); API void light_dir(light_t* l, vec3 dir); +API void light_power(light_t* l, float power); API void light_falloff(light_t* l, float constant, float linear, float quadratic); API void light_cone(light_t* l, float innerCone, float outerCone); API void light_update(unsigned num_lights, light_t *lv); diff --git a/engine/v4k.c b/engine/v4k.c index e314d03..4932ce8 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -13948,21 +13948,21 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view, glUniformMatrix4fv( loc, 1, GL_FALSE, vp); } if( (loc = glGetUniformLocation(shader, "u_cam_pos")) >= 0 ) { - vec3 pos = vec3(view[3], view[6], view[9]); + vec3 pos = vec3(view[12], view[13], view[14]); glUniform3fv( loc, 1, &pos.x ); } else if( (loc = glGetUniformLocation(shader, "cam_pos")) >= 0 ) { - vec3 pos = vec3(view[3], view[6], view[9]); + vec3 pos = vec3(view[12], view[13], view[14]); glUniform3fv( loc, 1, &pos.x ); } if( (loc = glGetUniformLocation(shader, "u_cam_dir")) >= 0 ) { - vec3 dir = vec3(view[0], view[1], view[2]); + vec3 dir = norm3(vec3(view[2], view[6], view[10])); glUniform3fv( loc, 1, &dir.x ); } else if( (loc = glGetUniformLocation(shader, "cam_dir")) >= 0 ) { - vec3 dir = vec3(view[0], view[1], view[2]); + vec3 dir = norm3(vec3(view[2], view[6], view[10])); glUniform3fv( loc, 1, &dir.x ); } #if 0 @@ -15876,6 +15876,7 @@ light_t light() { l.falloff.constant = 1.0f; l.falloff.linear = 0.09f; l.falloff.quadratic = 0.0032f; + l.specularPower = 32.f; l.innerCone = 0.9f; // 25 deg l.outerCone = 0.85f; // 31 deg @@ -15912,6 +15913,11 @@ void light_dir(light_t* l, vec3 dir) { l->dir = dir; } +void light_power(light_t* l, float power) { + l->cached = 0; + l->specularPower = power; +} + void light_falloff(light_t* l, float constant, float linear, float quadratic) { l->cached = 0; l->falloff.constant = constant; @@ -15920,6 +15926,7 @@ void light_falloff(light_t* l, float constant, float linear, float quadratic) { } void light_cone(light_t* l, float innerCone, float outerCone) { + l->cached = 0; l->innerCone = acos(innerCone); l->outerCone = acos(outerCone); } @@ -15935,6 +15942,7 @@ void light_update(unsigned num_lights, light_t *lv) { shader_vec3(va("u_lights[%d].diffuse", i), lv[i].diffuse); shader_vec3(va("u_lights[%d].specular", i), lv[i].specular); shader_vec3(va("u_lights[%d].ambient", i), lv[i].ambient); + shader_float(va("u_lights[%d].power", i), lv[i].specularPower); shader_float(va("u_lights[%d].constant", i), lv[i].falloff.constant); shader_float(va("u_lights[%d].linear", i), lv[i].falloff.linear); shader_float(va("u_lights[%d].quadratic", i), lv[i].falloff.quadratic); diff --git a/engine/v4k.h b/engine/v4k.h index 64cb9fa..1aa4eeb 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -3260,6 +3260,7 @@ typedef struct light_t { struct { float constant, linear, quadratic; } falloff; + float specularPower; float innerCone, outerCone; //@todo: cookie, flare @@ -3275,6 +3276,7 @@ API void light_specular(light_t* l, vec3 color); API void light_ambient(light_t* l, vec3 color); API void light_teleport(light_t* l, vec3 pos); API void light_dir(light_t* l, vec3 dir); +API void light_power(light_t* l, float power); API void light_falloff(light_t* l, float constant, float linear, float quadratic); API void light_cone(light_t* l, float innerCone, float outerCone); API void light_update(unsigned num_lights, light_t *lv);