diff --git a/bind/v4k.lua b/bind/v4k.lua index b9519b9..987e7a8 100644 --- a/bind/v4k.lua +++ b/bind/v4k.lua @@ -1323,6 +1323,7 @@ enum MODEL_FLAGS { enum SHADING_MODE { SHADING_NONE, SHADING_PHONG, + SHADING_VERTEXLIT, SHADING_PBR, }; enum RENDER_PASS { @@ -1575,6 +1576,7 @@ typedef struct light_t { struct { float constant, linear, quadratic; } falloff; + float radius; float specularPower; float innerCone, outerCone; bool cached; @@ -1587,6 +1589,7 @@ typedef struct light_t { 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_radius(light_t* l, float radius); 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/art/shaders/fs_32_4_model.glsl b/engine/art/shaders/fs_32_4_model.glsl index a77329d..b78bad0 100644 --- a/engine/art/shaders/fs_32_4_model.glsl +++ b/engine/art/shaders/fs_32_4_model.glsl @@ -29,6 +29,7 @@ in vec4 v_color; in vec3 v_tangent; in vec3 v_binormal; in vec3 v_to_camera; +in vec3 v_vertcolor; out vec4 fragcolor; @@ -53,6 +54,7 @@ struct light_t { vec3 pos; vec3 dir; float power; + float radius; float innerCone; float outerCone; @@ -80,6 +82,11 @@ vec3 shading_phong(light_t l) { vec3 toLight = l.pos - v_position_ws; lightDir = normalize(toLight); float distance = length(toLight); + + /* fast-reject based on radius */ + if (l.radius != 0.0 && distance > l.radius) { + return vec3(0,0,0); + } attenuation = 1.0 / (l.constant + l.linear * distance + l.quadratic * (distance * distance)); if (l.type == LIGHT_SPOT) { @@ -452,6 +459,67 @@ void main() { #endif } #endif +#ifdef SHADING_VERTEXLIT +void main() { + vec3 n = normalize(v_normal_ws); + + vec4 lit = vec4(1.0, 1.0, 1.0, 1.0); + // SH lighting + if (!u_texlit) { + vec3 result = sh_lighting(n); + if( (result.x*result.x+result.y*result.y+result.z*result.z) > 0.0 ) lit = vec4(result, 1.0); + } + + lit += vec4(v_vertcolor, 0.0); + + // base + vec4 diffuse; + + if(u_matcaps) { + vec2 muv = vec2(view * vec4(v_normal_ws, 0))*0.5+vec2(0.5,0.5); // normal (model space) to view space + diffuse = texture(u_texture2d, vec2(muv.x, 1.0-muv.y)); + } else if(u_textured) { + diffuse = texture(u_texture2d, v_texcoord); + } else { + diffuse = u_diffuse; // * v_color; + } + + // vec4 vertcolor4 = vec4(v_vertcolor, 1.0); + // if (length(diffuse*v_color) > length(vertcolor4)) { + diffuse *= v_color; + // } + + if (u_texlit) { + vec4 litsample = texture(u_lightmap, v_texcoord); + + if (u_texmod) { + diffuse *= litsample; + } else { + diffuse += litsample; + } + + diffuse.rgb += sh_lighting(n); + } + + // lighting mix + fragcolor = diffuse * lit * shadowing(); + + // rimlight + #ifdef RIM + { + vec3 n = normalize(mat3(M) * v_normal); // convert normal to view space + vec3 p = (M * vec4(v_position,1.0)).xyz; // convert position to view space + vec3 v = vec3(0,-1,0); + if (!u_rimambient) { + v = normalize(u_rimpivot-p); + } + float rim = 1.0 - max(dot(v,n), 0.0); + vec3 col = u_rimcolor*(pow(smoothstep(1.0-u_rimrange.x,u_rimrange.y,rim), u_rimrange.z)); + fragcolor += vec4(col, 0.0); + } + #endif +} +#endif #ifdef SHADING_PBR void main(void) { diff --git a/engine/art/shaders/vs_323444143_16_3322_model.glsl b/engine/art/shaders/vs_323444143_16_3322_model.glsl index e2aa833..e150e69 100644 --- a/engine/art/shaders/vs_323444143_16_3322_model.glsl +++ b/engine/art/shaders/vs_323444143_16_3322_model.glsl @@ -46,7 +46,6 @@ uniform vec4 blend_weights[MAX_BLENDSHAPES]; // @todo: implement me uniform float f_num_blend_shapes; // @todo: implement me uniform MEDIUMP sampler2DArray blend_shapes; // @todo: implement me - in vec3 att_position; // @todo: reorder ass2iqe to emit p3 n3 u2 t3 b3 c4B i4 w4 instead in vec2 att_texcoord; in vec3 att_normal; @@ -66,9 +65,92 @@ out vec3 v_tangent; out vec3 v_binormal; out vec3 v_viewpos; out vec3 v_to_camera; +out vec3 v_vertcolor; + +// lights +#ifdef SHADING_VERTEXLIT +uniform int u_num_lights; + +struct light_t { + int type; + vec3 diffuse; + vec3 specular; + vec3 ambient; + vec3 pos; + vec3 dir; + float radius; + float power; + float innerCone; + float outerCone; + + // falloff + float constant; + float linear; + float quadratic; +}; + +#define MAX_LIGHTS 16 +const int LIGHT_DIRECTIONAL = 0; +const int LIGHT_POINT = 1; +const int LIGHT_SPOT = 2; +uniform light_t u_lights[MAX_LIGHTS]; +uniform vec3 u_cam_dir; + +vec3 shading_vertexlit(light_t l) { + vec3 lightDir; + float attenuation = 1.0; + + if (l.type == LIGHT_DIRECTIONAL) { + lightDir = normalize(-l.dir); + } else if (l.type == LIGHT_POINT || l.type == LIGHT_SPOT) { + vec3 toLight = l.pos - v_position_ws; + lightDir = normalize(toLight); + float distance = length(toLight); + + /* fast-reject based on radius */ + if (l.radius != 0.0 && distance > l.radius) { + return vec3(0,0,0); + } + attenuation = 1.0 / (l.constant + l.linear * distance + l.quadratic * (distance * distance)); + + if (l.type == LIGHT_SPOT) { + 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); + } else { + attenuation = 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(n, halfVec), 0.0), l.power); + + return (attenuation*l.ambient + diffuse*attenuation*l.diffuse + specular*attenuation*l.specular); +} + +#endif - +vec3 lighting() { + vec3 lit = vec3(0,0,0); +#ifdef SHADING_VERTEXLIT + for (int i=0; iprogram = shaderprog; model_init_uniforms(m); } @@ -387707,6 +387710,11 @@ void light_falloff(light_t* l, float constant, float linear, float quadratic) { l->falloff.quadratic = quadratic; } +void light_radius(light_t* l, float radius) { + l->cached = 0; + l->radius = radius; +} + void light_cone(light_t* l, float innerCone, float outerCone) { l->cached = 0; l->innerCone = acos(innerCone); @@ -387725,6 +387733,7 @@ void light_update(unsigned num_lights, light_t *lv) { 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].radius", i), lv[i].radius); 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 c6aaeb4..bdb421d 100644 --- a/engine/split/v4k_render.c +++ b/engine/split/v4k_render.c @@ -4384,7 +4384,7 @@ void model_shading(model_t *m, int shading) { const char *symbols[] = { "{{include-shadowmap}}", vfs_read("shaders/fs_0_0_shadowmap_lit.glsl") }; // #define RIM int shaderprog = shader(strlerp(1,symbols,vfs_read("shaders/vs_323444143_16_3322_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs, "att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent,att_texcoord2","fragColor", - va("%s,%s", shading == SHADING_PBR ? "SHADING_PBR" : "SHADING_PHONG", (flags&MODEL_RIMLIGHT)?"RIM":"")); + va("%s,%s", shading == SHADING_PBR ? "SHADING_PBR" : shading == SHADING_VERTEXLIT ? "SHADING_VERTEXLIT" : "SHADING_PHONG", (flags&MODEL_RIMLIGHT)?"RIM":"")); m->program = shaderprog; model_init_uniforms(m); } diff --git a/engine/split/v4k_render.h b/engine/split/v4k_render.h index de7a194..7c0fd51 100644 --- a/engine/split/v4k_render.h +++ b/engine/split/v4k_render.h @@ -602,6 +602,7 @@ enum MODEL_FLAGS { enum SHADING_MODE { SHADING_NONE, SHADING_PHONG, + SHADING_VERTEXLIT, SHADING_PBR, }; diff --git a/engine/split/v4k_scene.c b/engine/split/v4k_scene.c index 97a2ac4..c3a4dce 100644 --- a/engine/split/v4k_scene.c +++ b/engine/split/v4k_scene.c @@ -353,6 +353,11 @@ void light_falloff(light_t* l, float constant, float linear, float quadratic) { l->falloff.quadratic = quadratic; } +void light_radius(light_t* l, float radius) { + l->cached = 0; + l->radius = radius; +} + void light_cone(light_t* l, float innerCone, float outerCone) { l->cached = 0; l->innerCone = acos(innerCone); @@ -371,6 +376,7 @@ void light_update(unsigned num_lights, light_t *lv) { 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].radius", i), lv[i].radius); 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 9ba1da2..2964271 100644 --- a/engine/split/v4k_scene.h +++ b/engine/split/v4k_scene.h @@ -87,6 +87,7 @@ typedef struct light_t { struct { float constant, linear, quadratic; } falloff; + float radius; float specularPower; float innerCone, outerCone; //@todo: cookie, flare @@ -104,6 +105,7 @@ 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_radius(light_t* l, float radius); 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 1ad7916..13b12aa 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -21169,7 +21169,7 @@ void model_shading(model_t *m, int shading) { const char *symbols[] = { "{{include-shadowmap}}", vfs_read("shaders/fs_0_0_shadowmap_lit.glsl") }; // #define RIM int shaderprog = shader(strlerp(1,symbols,vfs_read("shaders/vs_323444143_16_3322_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs, "att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent,att_texcoord2","fragColor", - va("%s,%s", shading == SHADING_PBR ? "SHADING_PBR" : "SHADING_PHONG", (flags&MODEL_RIMLIGHT)?"RIM":"")); + va("%s,%s", shading == SHADING_PBR ? "SHADING_PBR" : shading == SHADING_VERTEXLIT ? "SHADING_VERTEXLIT" : "SHADING_PHONG", (flags&MODEL_RIMLIGHT)?"RIM":"")); m->program = shaderprog; model_init_uniforms(m); } @@ -22879,6 +22879,11 @@ void light_falloff(light_t* l, float constant, float linear, float quadratic) { l->falloff.quadratic = quadratic; } +void light_radius(light_t* l, float radius) { + l->cached = 0; + l->radius = radius; +} + void light_cone(light_t* l, float innerCone, float outerCone) { l->cached = 0; l->innerCone = acos(innerCone); @@ -22897,6 +22902,7 @@ void light_update(unsigned num_lights, light_t *lv) { 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].radius", i), lv[i].radius); 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 bac7c71..7dba52c 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -3636,6 +3636,7 @@ enum MODEL_FLAGS { enum SHADING_MODE { SHADING_NONE, SHADING_PHONG, + SHADING_VERTEXLIT, SHADING_PBR, }; @@ -3979,6 +3980,7 @@ typedef struct light_t { struct { float constant, linear, quadratic; } falloff; + float radius; float specularPower; float innerCone, outerCone; //@todo: cookie, flare @@ -3996,6 +3998,7 @@ 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_radius(light_t* l, float radius); 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);