revamp all shaders
parent
444285ca59
commit
2eca87099a
|
@ -1,3 +1,5 @@
|
|||
#include "brdf.glsl"
|
||||
|
||||
uniform int u_num_lights;
|
||||
|
||||
struct light_t {
|
||||
|
@ -25,8 +27,16 @@ const int LIGHT_SPOT = 2;
|
|||
|
||||
uniform light_t u_lights[MAX_LIGHTS];
|
||||
|
||||
#ifdef SHADING_PHONG
|
||||
vec3 shading_phong(light_t l) {
|
||||
struct material_t {
|
||||
vec3 albedo;
|
||||
vec3 normal;
|
||||
vec3 F0;
|
||||
float roughness;
|
||||
float metallic;
|
||||
float alpha;
|
||||
};
|
||||
|
||||
vec3 shading_light(light_t l, material_t m) {
|
||||
vec3 lightDir;
|
||||
float attenuation = 1.0;
|
||||
|
||||
|
@ -59,6 +69,7 @@ vec3 shading_phong(light_t l) {
|
|||
return vec3(0,0,0);
|
||||
}
|
||||
|
||||
#ifdef SHADING_PHONG
|
||||
vec3 n = normalize(v_normal_ws);
|
||||
|
||||
float diffuse = max(dot(n, lightDir), 0.0);
|
||||
|
@ -67,42 +78,8 @@ vec3 shading_phong(light_t l) {
|
|||
float specular = pow(max(dot(n, halfVec), 0.0), l.power);
|
||||
|
||||
return (attenuation*l.ambient + diffuse*attenuation*l.diffuse + specular*attenuation*l.specular);
|
||||
}
|
||||
#endif
|
||||
#ifdef SHADING_VERTEXLIT
|
||||
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);
|
||||
|
@ -111,25 +88,42 @@ vec3 shading_vertexlit(light_t l) {
|
|||
float specular = pow(max(dot(n, halfVec), 0.0), l.power);
|
||||
|
||||
return (attenuation*l.ambient + diffuse*attenuation*l.diffuse + specular*attenuation*l.specular);
|
||||
#endif
|
||||
#ifdef SHADING_PBR
|
||||
vec3 radiance = l.diffuse * BOOST_LIGHTING;
|
||||
vec3 V = normalize( v_to_camera );
|
||||
vec3 N = m.normal;
|
||||
vec3 L = normalize( lightDir );
|
||||
vec3 H = normalize( V + L );
|
||||
|
||||
vec3 F = fresnel_schlick( H, V, m.F0 );
|
||||
vec3 kS = F;
|
||||
vec3 kD = vec3(1.0) - kS;
|
||||
kD *= 1.0 - m.metallic;
|
||||
|
||||
// Premultiplied alpha applied to the diffuse component only
|
||||
kD *= m.alpha;
|
||||
|
||||
float D = distribution_ggx( N, H, m.roughness );
|
||||
float G = geometry_smith( N, V, L, m.roughness );
|
||||
|
||||
vec3 num = D * F * G;
|
||||
float denom = 4. * max( 0., dot( N, V ) ) * max( 0., dot( N, L ) );
|
||||
|
||||
vec3 specular = kS * (num / max( 0.001, denom ));
|
||||
|
||||
float NdotL = max( 0., dot( N, L ) );
|
||||
|
||||
return ( kD * ( m.albedo / PI ) + specular ) * radiance * NdotL * attenuation;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
vec3 lighting() {
|
||||
vec3 lighting(material_t m) {
|
||||
vec3 lit = vec3(0,0,0);
|
||||
#ifndef SHADING_NONE
|
||||
#ifdef SHADING_PHONG
|
||||
for (int i=0; i<u_num_lights; i++) {
|
||||
lit += shading_phong(u_lights[i]);
|
||||
lit += shading_light(u_lights[i], m);
|
||||
}
|
||||
#endif
|
||||
#ifdef SHADING_VERTEXLIT
|
||||
for (int i=0; i<u_num_lights; i++) {
|
||||
lit += shading_vertexlit(u_lights[i]);
|
||||
}
|
||||
#endif
|
||||
#ifdef SHADING_PBR
|
||||
#endif
|
||||
#endif
|
||||
return lit;
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ vec3 get_object_pos() {
|
|||
return objPos;
|
||||
}
|
||||
|
||||
void setup_billboards(mat4 modelView, mat4 l_model) {
|
||||
void setup_billboard(mat4 modelView, mat4 l_model) {
|
||||
if(u_billboard > 0) {
|
||||
vec3 cameraPosition = -transpose(mat3(view)) * view[3].xyz;
|
||||
vec3 lookDir = normalize(cameraPosition - v_position_ws);
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
vec3 get_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));
|
||||
return col;
|
||||
#else
|
||||
return vec3(0);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
#include "sh_lighting.glsl"
|
||||
#include "rimlight.glsl"
|
||||
#include "light.glsl"
|
||||
|
||||
struct surface_t {
|
||||
vec3 normal;
|
||||
vec4 albedo;
|
||||
vec4 fragcolor;
|
||||
vec3 light_direct;
|
||||
vec3 light_indirect;
|
||||
vec3 emissive;
|
||||
float roughness;
|
||||
float metallic;
|
||||
float ao;
|
||||
float alpha;
|
||||
};
|
||||
|
||||
surface_t surface() {
|
||||
surface_t s;
|
||||
|
||||
s.normal = normalize(v_normal_ws);
|
||||
s.light_direct = vec3(0.0, 0.0, 0.0);
|
||||
s.light_indirect = vec3(1.0, 1.0, 1.0);
|
||||
s.albedo = vec4(0.5, 0.5, 0.5, 1.0);
|
||||
s.emissive = vec3(0.0, 0.0, 0.0);
|
||||
s.roughness = 1.0;
|
||||
s.metallic = 0.0;
|
||||
s.ao = 1.0;
|
||||
s.alpha = 1.0;
|
||||
|
||||
// SH lighting
|
||||
if (!u_texlit) {
|
||||
vec3 result = sh_lighting(s.normal);
|
||||
if( (result.x*result.x+result.y*result.y+result.z*result.z) > 0.0 ) s.light_indirect = result;
|
||||
}
|
||||
|
||||
#ifdef SHADING_PHONG
|
||||
material_t dummy_mat;
|
||||
s.light_direct = lighting(dummy_mat);
|
||||
#endif
|
||||
|
||||
#ifdef SHADING_VERTEXLIT
|
||||
s.light_direct = v_vertcolor;
|
||||
#endif
|
||||
|
||||
#ifdef SHADING_PBR
|
||||
vec4 baseColor_alpha;
|
||||
if ( map_albedo.has_tex )
|
||||
baseColor_alpha = sample_colormap( map_albedo, v_texcoord );
|
||||
else
|
||||
baseColor_alpha = sample_colormap( map_diffuse, v_texcoord );
|
||||
s.albedo = baseColor_alpha;
|
||||
|
||||
if( map_metallic.has_tex && map_roughness.has_tex ) {
|
||||
s.metallic = sample_colormap( map_metallic, v_texcoord ).x;
|
||||
s.roughness = sample_colormap( map_roughness, v_texcoord ).x;
|
||||
}
|
||||
else if( map_roughness.has_tex ) {
|
||||
s.metallic = sample_colormap( map_roughness, v_texcoord ).b;
|
||||
s.roughness = sample_colormap( map_roughness, v_texcoord ).g;
|
||||
}
|
||||
|
||||
if ( map_ao.has_tex )
|
||||
s.ao = sample_colormap( map_ao, v_texcoord ).x;
|
||||
else if ( map_ambient.has_tex )
|
||||
s.ao = sample_colormap( map_ambient, v_texcoord ).x;
|
||||
|
||||
s.emissive = sample_colormap( map_emissive, v_texcoord ).rgb;
|
||||
|
||||
vec3 normalmap = texture( map_normals_tex, v_texcoord ).xyz * vec3(2.0) - vec3(1.0);
|
||||
float normalmap_mip = textureQueryLod( map_normals_tex, v_texcoord ).x;
|
||||
float normalmap_length = length(normalmap);
|
||||
normalmap /= normalmap_length;
|
||||
|
||||
s.normal = v_normal_ws;
|
||||
|
||||
if ( map_normals.has_tex )
|
||||
{
|
||||
// Mikkelsen's tangent space normal map decoding. See http://mikktspace.com/ for rationale.
|
||||
vec3 bi = cross( v_normal_ws, v_tangent );
|
||||
vec3 nmap = normalmap.xyz;
|
||||
s.normal = nmap.x * v_tangent + nmap.y * bi + nmap.z * v_normal_ws;
|
||||
}
|
||||
|
||||
s.normal = normalize( s.normal );
|
||||
|
||||
if (USE_NORMAL_VARIATION_TO_ROUGHNESS)
|
||||
{
|
||||
// Try to reduce specular aliasing by increasing roughness when minified normal maps have high variation.
|
||||
float variation = 1. - pow( normalmap_length, 8. );
|
||||
float minification = clamp( normalmap_mip - 2., 0., 1. );
|
||||
s.roughness = mix( s.roughness, 1.0, variation * minification );
|
||||
}
|
||||
|
||||
vec3 N = s.normal;
|
||||
vec3 V = normalize( v_to_camera );
|
||||
|
||||
vec3 Lo = vec3(0.);
|
||||
vec3 F0 = vec3(0.04);
|
||||
F0 = mix( F0, s.albedo.rgb, s.metallic );
|
||||
|
||||
bool use_ibl = has_tex_skysphere;
|
||||
|
||||
material_t pbr_mat;
|
||||
pbr_mat.albedo = s.albedo.rgb;
|
||||
pbr_mat.normal = N;
|
||||
pbr_mat.F0 = F0;
|
||||
pbr_mat.roughness = s.roughness;
|
||||
pbr_mat.metallic = s.metallic;
|
||||
pbr_mat.alpha = s.alpha;
|
||||
|
||||
// Lo += lighting(pbr_mat);
|
||||
|
||||
s.light_indirect = sample_colormap( map_ambient, v_texcoord ).xyz;
|
||||
vec3 diffuse_ambient;
|
||||
vec3 specular_ambient;
|
||||
|
||||
if ( use_ibl )
|
||||
{
|
||||
// Image based lighting.
|
||||
// Based on https://learnopengl.com/PBR/IBL/Diffuse-irradiance
|
||||
|
||||
vec3 irradiance = vec3(0.);
|
||||
|
||||
if ( USE_BRUTEFORCE_IRRADIANCE )
|
||||
{
|
||||
irradiance = sample_irradiance_slow( N, v_tangent );
|
||||
}
|
||||
else
|
||||
{
|
||||
irradiance = sample_irradiance_fast( N, v_tangent );
|
||||
}
|
||||
|
||||
// Compute the Fresnel term for a perfect mirror reflection with L = R.
|
||||
// In this case the halfway vector H = N.
|
||||
//
|
||||
// We use a modified Fresnel function that dampens specular reflections of very
|
||||
// rough surfaces to avoid too bright pixels at grazing angles.
|
||||
vec3 F = fresnel_schlick_roughness( N, V, F0, s.roughness );
|
||||
vec3 kS = F;
|
||||
|
||||
// Subtract the amount of reflected light (specular) to get the energy left for
|
||||
// absorbed (diffuse) light.
|
||||
vec3 kD = vec3(1.) - kS;
|
||||
|
||||
// Metallic surfaces have only a specular reflection.
|
||||
kD *= 1.0 - s.metallic;
|
||||
|
||||
// Premultiplied alpha applied to the diffuse component only
|
||||
kD *= s.alpha;
|
||||
|
||||
// Modulate the incoming lighting with the diffuse color: some wavelengths get absorbed.
|
||||
diffuse_ambient = irradiance * s.albedo.rgb;
|
||||
|
||||
// Ambient light also has a specular part.
|
||||
specular_ambient = specular_ibl( V, N, s.roughness, F );
|
||||
|
||||
// Ambient occlusion tells us the fraction of sky light that reaches this point.
|
||||
if (USE_SPECULAR_AO_ATTENUATION)
|
||||
{
|
||||
s.light_indirect += s.ao * (kD * diffuse_ambient + specular_ambient);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't attenuate specular_ambient ambient here with AO which might cause flickering in dark cavities.
|
||||
s.light_indirect += s.ao * (kD * diffuse_ambient) + specular_ambient;
|
||||
}
|
||||
}
|
||||
#else
|
||||
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
|
||||
s.albedo = texture(u_texture2d, vec2(muv.x, 1.0-muv.y));
|
||||
} else if(u_textured) {
|
||||
s.albedo = texture(u_texture2d, v_texcoord);
|
||||
} else {
|
||||
s.albedo = u_diffuse;
|
||||
}
|
||||
|
||||
if (u_texlit) {
|
||||
vec4 litsample = texture(u_lightmap, v_texcoord);
|
||||
|
||||
if (u_texmod) {
|
||||
s.albedo *= litsample;
|
||||
} else {
|
||||
s.albedo += litsample;
|
||||
}
|
||||
|
||||
s.albedo.rgb += sh_lighting(s.normal);
|
||||
}
|
||||
#endif
|
||||
|
||||
s.albedo *= v_color;
|
||||
|
||||
s.fragcolor = s.albedo;
|
||||
s.fragcolor.rgb *= s.light_direct + s.light_indirect;
|
||||
s.fragcolor.rgb += s.emissive;
|
||||
s.fragcolor *= shadowing();
|
||||
s.fragcolor.rgb += get_rimlight();
|
||||
|
||||
return s;
|
||||
}
|
|
@ -1,387 +1,10 @@
|
|||
#include "model_fs.glsl"
|
||||
#include "light.glsl"
|
||||
#include "brdf.glsl"
|
||||
#include "sh_lighting.glsl"
|
||||
#include "lightmap.glsl"
|
||||
#include "surface.glsl"
|
||||
|
||||
#ifdef SHADING_PHONG
|
||||
#ifndef LIGHTMAP_BAKING
|
||||
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);
|
||||
}
|
||||
|
||||
// analytical lights
|
||||
lit += vec4(lighting(), 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;
|
||||
}
|
||||
|
||||
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
|
||||
surface_t surf = surface();
|
||||
fragcolor = surf.fragcolor;
|
||||
}
|
||||
#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)
|
||||
{
|
||||
vec3 baseColor = vec3( 0.5, 0.5, 0.5 );
|
||||
float roughness = 1.0;
|
||||
float metallic = 0.0;
|
||||
float ao = 1.0;
|
||||
float alpha = 1.0;
|
||||
|
||||
vec4 baseColor_alpha;
|
||||
if ( map_albedo.has_tex )
|
||||
baseColor_alpha = sample_colormap( map_albedo, v_texcoord );
|
||||
else
|
||||
baseColor_alpha = sample_colormap( map_diffuse, v_texcoord );
|
||||
baseColor = baseColor_alpha.xyz;
|
||||
alpha = baseColor_alpha.w;
|
||||
|
||||
if( map_metallic.has_tex && map_roughness.has_tex ) {
|
||||
metallic = sample_colormap( map_metallic, v_texcoord ).x;
|
||||
roughness = sample_colormap( map_roughness, v_texcoord ).x;
|
||||
}
|
||||
else if( map_roughness.has_tex ) {
|
||||
//< @r-lyeh, metalness B, roughness G, (@todo: self-shadowing occlusion R; for now, any of R/B are metallic)
|
||||
metallic = sample_colormap( map_roughness, v_texcoord ).b;// + sample_colormap( map_roughness, v_texcoord ).r;
|
||||
roughness = sample_colormap( map_roughness, v_texcoord ).g;
|
||||
}
|
||||
|
||||
if ( map_ao.has_tex )
|
||||
ao = sample_colormap( map_ao, v_texcoord ).x;
|
||||
else if ( map_ambient.has_tex )
|
||||
ao = sample_colormap( map_ambient, v_texcoord ).x;
|
||||
|
||||
vec3 emissive = sample_colormap( map_emissive, v_texcoord ).rgb;
|
||||
|
||||
vec3 normalmap = texture( map_normals_tex, v_texcoord ).xyz * vec3(2.0) - vec3(1.0);
|
||||
float normalmap_mip = textureQueryLod( map_normals_tex, v_texcoord ).x;
|
||||
float normalmap_length = length(normalmap);
|
||||
normalmap /= normalmap_length;
|
||||
|
||||
vec3 normal = v_normal_ws;
|
||||
|
||||
if ( map_normals.has_tex )
|
||||
{
|
||||
// Mikkelsen's tangent space normal map decoding. See http://mikktspace.com/ for rationale.
|
||||
vec3 bi = cross( v_normal_ws, v_tangent );
|
||||
vec3 nmap = normalmap.xyz;
|
||||
normal = nmap.x * v_tangent + nmap.y * bi + nmap.z * v_normal_ws;
|
||||
}
|
||||
|
||||
normal = normalize( normal );
|
||||
|
||||
if( USE_MAP_DEBUGGING && !USE_AMBIENT_DEBUGGING )
|
||||
{
|
||||
vec3 c = vec3(1., 0., 0.);
|
||||
float x = gl_FragCoord.x / resolution.x;
|
||||
float y = gl_FragCoord.y / resolution.y;
|
||||
if ( y < (7.0/7.0) ) c = vec3(.5) + .5*v_normal_ws;
|
||||
if ( y < (6.0/7.0) ) c = vec3(.5) + .5*normalmap;
|
||||
if ( y < (5.0/7.0) ) c = vec3(ao);
|
||||
if ( y < (4.0/7.0) ) c = vec3(emissive);
|
||||
if ( y < (3.0/7.0) ) c = vec3(metallic);
|
||||
if ( y < (2.0/7.0) ) c = vec3(roughness);
|
||||
if ( y < (1.0/7.0) ) c = baseColor;
|
||||
fragcolor = vec4(c, 1.);
|
||||
return;
|
||||
}
|
||||
|
||||
if (USE_NORMAL_VARIATION_TO_ROUGHNESS)
|
||||
{
|
||||
// Try to reduce specular aliasing by increasing roughness when minified normal maps have high variation.
|
||||
float variation = 1. - pow( normalmap_length, 8. );
|
||||
float minification = clamp( normalmap_mip - 2., 0., 1. );
|
||||
roughness = mix( roughness, 1.0, variation * minification );
|
||||
}
|
||||
|
||||
fragcolor = baseColor_alpha;
|
||||
|
||||
|
||||
vec3 N = normal;
|
||||
vec3 V = normalize( v_to_camera );
|
||||
|
||||
vec3 Lo = vec3(0.);
|
||||
vec3 F0 = vec3(0.04);
|
||||
F0 = mix( F0, baseColor, metallic );
|
||||
|
||||
bool use_ibl = has_tex_skysphere;
|
||||
// use_ibl = false;
|
||||
|
||||
// Add contributions from analytic lights.
|
||||
|
||||
{
|
||||
for ( int i = 0; i < u_num_lights; i++ )
|
||||
{
|
||||
light_t l = u_lights[i];
|
||||
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);
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
|
||||
vec3 radiance = l.diffuse * BOOST_LIGHTING;
|
||||
|
||||
vec3 L = normalize( lightDir );
|
||||
vec3 H = normalize( V + L );
|
||||
|
||||
vec3 F = fresnel_schlick( H, V, F0 );
|
||||
vec3 kS = F;
|
||||
vec3 kD = vec3(1.0) - kS;
|
||||
kD *= 1.0 - metallic;
|
||||
|
||||
// Premultiplied alpha applied to the diffuse component only
|
||||
kD *= alpha;
|
||||
|
||||
float D = distribution_ggx( N, H, roughness );
|
||||
float G = geometry_smith( N, V, L, roughness );
|
||||
|
||||
vec3 num = D * F * G;
|
||||
float denom = 4. * max( 0., dot( N, V ) ) * max( 0., dot( N, L ) );
|
||||
|
||||
vec3 specular = kS * (num / max( 0.001, denom ));
|
||||
|
||||
float NdotL = max( 0., dot( N, L ) );
|
||||
|
||||
Lo += ( kD * ( baseColor / PI ) + specular ) * radiance * NdotL * attenuation;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 ambient = sample_colormap( map_ambient, v_texcoord ).xyz;
|
||||
vec3 diffuse_ambient;
|
||||
vec3 specular_ambient;
|
||||
|
||||
if ( use_ibl )
|
||||
{
|
||||
// Image based lighting.
|
||||
// Based on https://learnopengl.com/PBR/IBL/Diffuse-irradiance
|
||||
|
||||
vec3 irradiance = vec3(0.);
|
||||
|
||||
if ( USE_BRUTEFORCE_IRRADIANCE )
|
||||
{
|
||||
irradiance = sample_irradiance_slow( normal, v_tangent );
|
||||
}
|
||||
else
|
||||
{
|
||||
irradiance = sample_irradiance_fast( normal, v_tangent );
|
||||
}
|
||||
|
||||
// Compute the Fresnel term for a perfect mirror reflection with L = R.
|
||||
// In this case the halfway vector H = N.
|
||||
//
|
||||
// We use a modified Fresnel function that dampens specular reflections of very
|
||||
// rough surfaces to avoid too bright pixels at grazing angles.
|
||||
vec3 F = fresnel_schlick_roughness( N, V, F0, roughness );
|
||||
vec3 kS = F;
|
||||
|
||||
// Subtract the amount of reflected light (specular) to get the energy left for
|
||||
// absorbed (diffuse) light.
|
||||
vec3 kD = vec3(1.) - kS;
|
||||
|
||||
// Metallic surfaces have only a specular reflection.
|
||||
kD *= 1.0 - metallic;
|
||||
|
||||
// Premultiplied alpha applied to the diffuse component only
|
||||
kD *= alpha;
|
||||
|
||||
// Modulate the incoming lighting with the diffuse color: some wavelengths get absorbed.
|
||||
diffuse_ambient = irradiance * baseColor;
|
||||
|
||||
// Ambient light also has a specular part.
|
||||
specular_ambient = specular_ibl( V, normal, roughness, F );
|
||||
|
||||
// Ambient occlusion tells us the fraction of sky light that reaches this point.
|
||||
if (USE_SPECULAR_AO_ATTENUATION)
|
||||
{
|
||||
ambient = ao * (kD * diffuse_ambient + specular_ambient);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't attenuate specular_ambient ambient here with AO which might cause flickering in dark cavities.
|
||||
ambient = ao * (kD * diffuse_ambient) + specular_ambient;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 color = (ambient + Lo) + emissive;
|
||||
|
||||
if ( USE_AMBIENT_DEBUGGING )
|
||||
{
|
||||
float y = gl_FragCoord.y / resolution.y;
|
||||
if( USE_MAP_DEBUGGING && y > 0.5 )
|
||||
{
|
||||
if ( (y-0.5) < (7.0/7.0/2.0) ) color = vec3(.5) + .5*v_normal_ws;
|
||||
if ( (y-0.5) < (6.0/7.0/2.0) ) color = vec3(.5) + .5*normalmap;
|
||||
if ( (y-0.5) < (5.0/7.0/2.0) ) color = vec3(ao);
|
||||
if ( (y-0.5) < (4.0/7.0/2.0) ) color = vec3(emissive);
|
||||
if ( (y-0.5) < (3.0/7.0/2.0) ) color = vec3(metallic);
|
||||
if ( (y-0.5) < (2.0/7.0/2.0) ) color = vec3(roughness);
|
||||
if ( (y-0.5) < (1.0/7.0/2.0) ) color = baseColor;
|
||||
} else {
|
||||
float x = gl_FragCoord.x / resolution.x;
|
||||
if ( x < 0.33 )
|
||||
color = specular_ambient;
|
||||
else if( x > 0.66 )
|
||||
color = diffuse_ambient;
|
||||
}
|
||||
}
|
||||
|
||||
// dither with noise.
|
||||
// float dither = random( uvec3( floatBitsToUint( gl_FragCoord.xy ), frame_count ) );
|
||||
// color += BOOST_NOISE * vec3( (-1.0/256.) + (2./256.) * dither );
|
||||
|
||||
#if 0 // original
|
||||
// basic tonemap and gamma correction
|
||||
color = color / ( vec3(1.) + color );
|
||||
color = pow( color, vec3(1. / 2.2) );
|
||||
#elif 0
|
||||
// filmic tonemapper
|
||||
vec3 linearColor = color;
|
||||
vec3 x = max(vec3(0.0), linearColor - 0.004);
|
||||
color = (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06);
|
||||
// gamma correction
|
||||
// color = pow( color, vec3(1. / 2.2) );
|
||||
#elif 0
|
||||
// aces film (CC0, src: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/)
|
||||
vec3 x = color;
|
||||
float a = 2.51f;
|
||||
float b = 0.03f;
|
||||
float c = 2.43f;
|
||||
float d = 0.59f;
|
||||
float e = 0.14f;
|
||||
color = clamp((x*(a*x+b))/(x*(c*x+d)+e), 0.0, 1.0);
|
||||
// gamma correction
|
||||
#endif
|
||||
// color = pow( color, vec3(1. / 2.2) );
|
||||
|
||||
// Technically this alpha may be too transparent, if there is a lot of reflected light we wouldn't
|
||||
// see the background, maybe we can approximate it well enough by adding a fresnel term
|
||||
fragcolor = vec4( color * shadowing().xyz, alpha );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,31 +16,19 @@ void main() {
|
|||
mat4 l_model = att_instanced_matrix;
|
||||
v_position_ws = (l_model * vec4( objPos, 1.0 )).xyz;
|
||||
|
||||
setup_billboards(modelView, l_model);
|
||||
setup_billboard(modelView, l_model);
|
||||
|
||||
v_position_ws = (l_model * vec4( objPos, 1.0 )).xyz;
|
||||
v_tangent = normalize(mat3(att_instanced_matrix) * att_tangent.xyz);
|
||||
|
||||
#if 0
|
||||
// compute tangent T and bitangent B
|
||||
vec3 Q1 = dFdx(att_position);
|
||||
vec3 Q2 = dFdy(att_position);
|
||||
vec2 st1 = dFdx(att_texcoord);
|
||||
vec2 st2 = dFdy(att_texcoord);
|
||||
|
||||
vec3 T = normalize(Q1*st2.t - Q2*st1.t);
|
||||
vec3 B = normalize(-Q1*st2.s + Q2*st1.s);
|
||||
vec3 binormal = B;
|
||||
#else
|
||||
vec3 binormal = cross(att_normal, att_tangent.xyz) * att_tangent.w;
|
||||
#endif
|
||||
|
||||
v_binormal = normalize(mat3(att_instanced_matrix) * binormal);
|
||||
|
||||
vec4 finalPos = modelView * vec4( objPos, 1.0 );
|
||||
vec3 to_camera = normalize( -finalPos.xyz );
|
||||
v_to_camera = mat3( inv_view ) * to_camera;
|
||||
v_vertcolor = lighting();
|
||||
material_t dummy_mat;
|
||||
v_vertcolor = lighting(dummy_mat);
|
||||
gl_Position = P * finalPos;
|
||||
do_shadow();
|
||||
}
|
|
@ -381964,11 +381964,13 @@ char *shader_preprocess(const char *src, const char *defines) {
|
|||
"#define textureQueryLod(t,uv) vec2(0.,0.)\n" // "#extension GL_EXT_texture_query_lod : enable\n"
|
||||
"#define MEDIUMP mediump\n"
|
||||
"precision MEDIUMP float;\n";
|
||||
const char *desktop = strstr(src, "textureQueryLod") ? "#version 400\n#define MEDIUMP\n" : "#version 330\n#define MEDIUMP\n";
|
||||
|
||||
char *processed_src = shader_process_includes(src);
|
||||
const char *desktop = strstr(processed_src, "textureQueryLod") ? "#version 400\n#define MEDIUMP\n" : "#version 330\n#define MEDIUMP\n";
|
||||
const char *glsl_version = ifdef(ems, gles, desktop);
|
||||
|
||||
// detect GLSL version if set
|
||||
if (src[0] == '#' && src[1] == 'v') {
|
||||
if (processed_src[0] == '#' && processed_src[1] == 'v') {
|
||||
#if 0
|
||||
const char *end = strstri(src, "\n");
|
||||
glsl_version = va("%.*s", (int)(end-src), src);
|
||||
|
@ -381978,7 +381980,6 @@ char *shader_preprocess(const char *src, const char *defines) {
|
|||
#endif
|
||||
}
|
||||
|
||||
char *processed_src = shader_process_includes(src);
|
||||
|
||||
return va("%s\n%s\n%s", glsl_version, defines ? defines : "", processed_src);
|
||||
}
|
||||
|
@ -384600,7 +384601,8 @@ bool colormap( colormap_t *cm, const char *texture_name, bool load_as_srgb ) {
|
|||
FREE(cm->texture), cm->texture = NULL;
|
||||
}
|
||||
|
||||
int srgb = load_as_srgb ? TEXTURE_SRGB : 0;
|
||||
// int srgb = load_as_srgb ? TEXTURE_SRGB : 0;
|
||||
int srgb = 0;
|
||||
int hdr = strendi(texture_name, ".hdr") ? TEXTURE_FLOAT|TEXTURE_RGBA : 0;
|
||||
texture_t t = texture_compressed(texture_name, TEXTURE_LINEAR | TEXTURE_ANISOTROPY | TEXTURE_MIPMAPS | TEXTURE_REPEAT | hdr | srgb);
|
||||
|
||||
|
@ -385447,7 +385449,7 @@ static char* strcpy_safe(char *d, const char *s) {
|
|||
static
|
||||
void model_load_pbr_layer(material_layer_t *layer, const char *texname, bool load_as_srgb) {
|
||||
strcpy_safe(layer->texname, texname);
|
||||
colormap(&layer->map, texname, false);
|
||||
colormap(&layer->map, texname, load_as_srgb);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
|
@ -308,11 +308,13 @@ char *shader_preprocess(const char *src, const char *defines) {
|
|||
"#define textureQueryLod(t,uv) vec2(0.,0.)\n" // "#extension GL_EXT_texture_query_lod : enable\n"
|
||||
"#define MEDIUMP mediump\n"
|
||||
"precision MEDIUMP float;\n";
|
||||
const char *desktop = strstr(src, "textureQueryLod") ? "#version 400\n#define MEDIUMP\n" : "#version 330\n#define MEDIUMP\n";
|
||||
|
||||
char *processed_src = shader_process_includes(src);
|
||||
const char *desktop = strstr(processed_src, "textureQueryLod") ? "#version 400\n#define MEDIUMP\n" : "#version 330\n#define MEDIUMP\n";
|
||||
const char *glsl_version = ifdef(ems, gles, desktop);
|
||||
|
||||
// detect GLSL version if set
|
||||
if (src[0] == '#' && src[1] == 'v') {
|
||||
if (processed_src[0] == '#' && processed_src[1] == 'v') {
|
||||
#if 0
|
||||
const char *end = strstri(src, "\n");
|
||||
glsl_version = va("%.*s", (int)(end-src), src);
|
||||
|
@ -322,7 +324,6 @@ char *shader_preprocess(const char *src, const char *defines) {
|
|||
#endif
|
||||
}
|
||||
|
||||
char *processed_src = shader_process_includes(src);
|
||||
|
||||
return va("%s\n%s\n%s", glsl_version, defines ? defines : "", processed_src);
|
||||
}
|
||||
|
@ -2944,7 +2945,8 @@ bool colormap( colormap_t *cm, const char *texture_name, bool load_as_srgb ) {
|
|||
FREE(cm->texture), cm->texture = NULL;
|
||||
}
|
||||
|
||||
int srgb = load_as_srgb ? TEXTURE_SRGB : 0;
|
||||
// int srgb = load_as_srgb ? TEXTURE_SRGB : 0;
|
||||
int srgb = 0;
|
||||
int hdr = strendi(texture_name, ".hdr") ? TEXTURE_FLOAT|TEXTURE_RGBA : 0;
|
||||
texture_t t = texture_compressed(texture_name, TEXTURE_LINEAR | TEXTURE_ANISOTROPY | TEXTURE_MIPMAPS | TEXTURE_REPEAT | hdr | srgb);
|
||||
|
||||
|
@ -3791,7 +3793,7 @@ static char* strcpy_safe(char *d, const char *s) {
|
|||
static
|
||||
void model_load_pbr_layer(material_layer_t *layer, const char *texname, bool load_as_srgb) {
|
||||
strcpy_safe(layer->texname, texname);
|
||||
colormap(&layer->map, texname, false);
|
||||
colormap(&layer->map, texname, load_as_srgb);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
12
engine/v4k.c
12
engine/v4k.c
|
@ -17107,11 +17107,13 @@ char *shader_preprocess(const char *src, const char *defines) {
|
|||
"#define textureQueryLod(t,uv) vec2(0.,0.)\n" // "#extension GL_EXT_texture_query_lod : enable\n"
|
||||
"#define MEDIUMP mediump\n"
|
||||
"precision MEDIUMP float;\n";
|
||||
const char *desktop = strstr(src, "textureQueryLod") ? "#version 400\n#define MEDIUMP\n" : "#version 330\n#define MEDIUMP\n";
|
||||
|
||||
char *processed_src = shader_process_includes(src);
|
||||
const char *desktop = strstr(processed_src, "textureQueryLod") ? "#version 400\n#define MEDIUMP\n" : "#version 330\n#define MEDIUMP\n";
|
||||
const char *glsl_version = ifdef(ems, gles, desktop);
|
||||
|
||||
// detect GLSL version if set
|
||||
if (src[0] == '#' && src[1] == 'v') {
|
||||
if (processed_src[0] == '#' && processed_src[1] == 'v') {
|
||||
#if 0
|
||||
const char *end = strstri(src, "\n");
|
||||
glsl_version = va("%.*s", (int)(end-src), src);
|
||||
|
@ -17121,7 +17123,6 @@ char *shader_preprocess(const char *src, const char *defines) {
|
|||
#endif
|
||||
}
|
||||
|
||||
char *processed_src = shader_process_includes(src);
|
||||
|
||||
return va("%s\n%s\n%s", glsl_version, defines ? defines : "", processed_src);
|
||||
}
|
||||
|
@ -19743,7 +19744,8 @@ bool colormap( colormap_t *cm, const char *texture_name, bool load_as_srgb ) {
|
|||
FREE(cm->texture), cm->texture = NULL;
|
||||
}
|
||||
|
||||
int srgb = load_as_srgb ? TEXTURE_SRGB : 0;
|
||||
// int srgb = load_as_srgb ? TEXTURE_SRGB : 0;
|
||||
int srgb = 0;
|
||||
int hdr = strendi(texture_name, ".hdr") ? TEXTURE_FLOAT|TEXTURE_RGBA : 0;
|
||||
texture_t t = texture_compressed(texture_name, TEXTURE_LINEAR | TEXTURE_ANISOTROPY | TEXTURE_MIPMAPS | TEXTURE_REPEAT | hdr | srgb);
|
||||
|
||||
|
@ -20590,7 +20592,7 @@ static char* strcpy_safe(char *d, const char *s) {
|
|||
static
|
||||
void model_load_pbr_layer(material_layer_t *layer, const char *texname, bool load_as_srgb) {
|
||||
strcpy_safe(layer->texname, texname);
|
||||
colormap(&layer->map, texname, false);
|
||||
colormap(&layer->map, texname, load_as_srgb);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
Loading…
Reference in New Issue