mirror of
https://github.com/koel/koel
synced 2024-12-23 11:03:05 +00:00
300 lines
8.4 KiB
TypeScript
300 lines
8.4 KiB
TypeScript
export const blobFrag =
|
|
`
|
|
|
|
varying float v_noise;
|
|
|
|
uniform float u_audio_high;
|
|
uniform float u_audio_mid;
|
|
uniform float u_audio_bass;
|
|
uniform float u_audio_level;
|
|
uniform float u_audio_history;
|
|
|
|
vec3 norm(in vec3 _v){
|
|
return length(_v) > .0 ? normalize(_v) : vec3(.0);
|
|
}
|
|
|
|
#if defined(IS_POINTS)
|
|
uniform sampler2D tex_sprite;
|
|
#endif
|
|
|
|
#if defined(IS_PBR) && defined(HAS_CUBEMAP)
|
|
uniform samplerCube cubemap;
|
|
uniform samplerCube cubemap_b;
|
|
uniform float cross_fader;
|
|
|
|
uniform sampler2D tex_normal;
|
|
uniform sampler2D tex_roughness;
|
|
uniform sampler2D tex_metallic;
|
|
|
|
uniform float u_normal;
|
|
uniform float u_roughness;
|
|
uniform float u_metallic;
|
|
uniform float u_exposure;
|
|
uniform float u_gamma;
|
|
|
|
varying vec3 v_world_normal;
|
|
varying vec3 v_object_pos;
|
|
varying vec3 v_eye_pos;
|
|
varying vec3 v_pos;
|
|
varying vec3 v_normal;
|
|
varying vec3 v_world_pos;
|
|
varying vec2 v_uv;
|
|
|
|
#define PI 3.1415926535897932384626433832795
|
|
|
|
// Filmic tonemapping from
|
|
// http://filmicgames.com/archives/75
|
|
const float A = 0.15;
|
|
const float B = 0.50;
|
|
const float C = 0.10;
|
|
const float D = 0.20;
|
|
const float E = 0.02;
|
|
const float F = 0.30;
|
|
|
|
vec3 Uncharted2Tonemap( vec3 x )
|
|
{
|
|
return ((x*(A*x+C*B)+D*E)/((x*(A*x+B)+D*F) + .00001))-E/F;
|
|
}
|
|
|
|
// https://www.unrealengine.com/blog/physically-based-shading-on-mobile
|
|
vec3 EnvBRDFApprox( vec3 SpecularColor, float Roughness, float NoV )
|
|
{
|
|
const vec4 c0 = vec4( -1, -0.0275, -0.572, 0.022 );
|
|
const vec4 c1 = vec4( 1, 0.0425, 1.04, -0.04 );
|
|
vec4 r = Roughness * c0 + c1;
|
|
float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
|
|
vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
|
|
return SpecularColor * AB.x + AB.y;
|
|
}
|
|
|
|
|
|
// http://the-witness.net/news/2012/02/seamless-cube-map-filtering/
|
|
vec3 fix_cube_lookup( vec3 v, float cube_size, float lod ) {
|
|
float M = max(max(abs(v.x), abs(v.y)), abs(v.z));
|
|
float scale = 1. - exp2(lod) / (cube_size + .00001);
|
|
if (abs(v.x) != M) v.x *= scale;
|
|
if (abs(v.y) != M) v.y *= scale;
|
|
if (abs(v.z) != M) v.z *= scale;
|
|
return v;
|
|
}
|
|
|
|
// Normal Blending
|
|
// Source adapted from http://blog.selfshadow.com/publications/blending-in-detail/
|
|
vec3 blendNormalsUnity( vec3 baseNormal, vec3 detailsNormal )
|
|
{
|
|
vec3 n1 = baseNormal;
|
|
vec3 n2 = detailsNormal;
|
|
mat3 nBasis = mat3(
|
|
vec3(n1.z, n1.y, -n1.x), // +90 degree rotation around y axis
|
|
vec3(n1.x, n1.z, -n1.y), // -90 degree rotation around x axis
|
|
vec3(n1.x, n1.y, n1.z));
|
|
return norm(n2.x*nBasis[0] + n2.y*nBasis[1] + n2.z*nBasis[2]);
|
|
}
|
|
vec3 blendNormals( vec3 n1, vec3 n2 )
|
|
{
|
|
return blendNormalsUnity( n1, n2 );
|
|
}
|
|
#endif
|
|
|
|
#if defined(HAS_SHADOW)
|
|
uniform sampler2D u_shadow_map;
|
|
uniform vec3 u_light_pos;
|
|
uniform bool u_debug_shadow;
|
|
varying vec4 v_shadow_coord;
|
|
|
|
float sample_shadow( vec4 sc )
|
|
{
|
|
float s = 1./1024.;
|
|
|
|
vec2 unproj2D = vec2 (sc.s / (sc.q + .00001),
|
|
sc.t / (sc.q + .00001));
|
|
|
|
float shadow = 0.0;
|
|
shadow += texture2D( u_shadow_map, unproj2D + vec2(-s,-s) ).r;
|
|
shadow += texture2D( u_shadow_map, unproj2D + vec2(-s, 0.) ).r;
|
|
shadow += texture2D( u_shadow_map, unproj2D + vec2(-s, s) ).r;
|
|
shadow += texture2D( u_shadow_map, unproj2D + vec2( 0.,-s) ).r;
|
|
shadow += texture2D( u_shadow_map, unproj2D + vec2( 0., 0.) ).r;
|
|
shadow += texture2D( u_shadow_map, unproj2D + vec2( 0., s) ).r;
|
|
shadow += texture2D( u_shadow_map, unproj2D + vec2( s,-s) ).r;
|
|
shadow += texture2D( u_shadow_map, unproj2D + vec2( s, 0.) ).r;
|
|
shadow += texture2D( u_shadow_map, unproj2D + vec2( s, s) ).r;
|
|
|
|
return shadow/9.0;;
|
|
}
|
|
#endif
|
|
|
|
|
|
void main(){
|
|
float m_noise = v_noise;
|
|
float m_noise_inv = 1.-v_noise;
|
|
|
|
vec3 m_diffuse = vec3(0.);
|
|
m_diffuse.r += m_noise_inv + m_noise;
|
|
m_diffuse.g += m_noise*1.5;
|
|
//m_diffuse.b += m_noise;
|
|
m_diffuse -= pow(abs(1.-m_noise), 4.)*.95; //<- darken peak
|
|
m_diffuse = clamp(m_diffuse, vec3(0.), vec3(2.));
|
|
|
|
m_diffuse *= pow(u_audio_level, 2.);
|
|
|
|
vec3 m_col = m_diffuse;
|
|
|
|
|
|
#if defined(IS_SHADOW)
|
|
gl_FragColor = vec4(m_col, 1.);
|
|
|
|
return;
|
|
#endif
|
|
|
|
|
|
#if defined(IS_PBR) && defined(HAS_CUBEMAP)
|
|
vec3 N = norm( v_world_normal );
|
|
|
|
// blend with PBR's
|
|
N = blendNormals( N, texture2D( tex_normal, v_uv ).xyz );
|
|
|
|
vec3 V = norm( v_eye_pos );
|
|
|
|
// fresnel
|
|
float m_fresnel = pow(1. + dot(norm(v_world_pos - v_eye_pos), v_world_normal), 8.);
|
|
|
|
#if defined(HAS_SHADOW)
|
|
// Light direction
|
|
vec3 L = norm( u_light_pos - v_world_pos.xyz );
|
|
// Surface reflection vector
|
|
vec3 R = norm( -reflect( L, N ) );
|
|
#endif
|
|
|
|
// sample the roughness and metallic textures
|
|
float roughnessMask = texture2D( tex_roughness, v_uv ).r;
|
|
float metallicMask = texture2D( tex_metallic, v_uv ).r;
|
|
|
|
// deduce the diffuse and specular color from the baseColor and how metallic the material is
|
|
vec3 m_specular_col = vec3(m_diffuse)*8.;
|
|
vec3 m_diffuse_col = vec3(m_diffuse)*8.;
|
|
vec3 diffuseColor = m_diffuse_col - m_diffuse_col * u_metallic * metallicMask;
|
|
vec3 specularColor = mix( vec3( 0.08 * m_specular_col ), m_diffuse_col, u_metallic * metallicMask );
|
|
|
|
// sample the pre-filtered cubemap at the corresponding mipmap level
|
|
int numMips = 6;
|
|
float mip = float(numMips) - 1. + log2( u_roughness * roughnessMask );
|
|
vec3 lookup = -reflect( V, N );
|
|
|
|
vec3 cube_a_rad = pow( abs(textureCube( cubemap, fix_cube_lookup( lookup, 2048., mip ) ).rgb), vec3( 2.2 ) );
|
|
vec3 cube_b_rad = pow( abs(textureCube( cubemap_b, fix_cube_lookup( lookup, 2048., mip ) ).rgb), vec3( 2.2 ) );
|
|
vec3 cube_a_irr = pow( abs(textureCube( cubemap, fix_cube_lookup( N, 2048., 0. ) ).rgb), vec3( 2.2 ) );
|
|
vec3 cube_b_irr = pow( abs(textureCube( cubemap_b, fix_cube_lookup( N, 2048., 0. ) ).rgb), vec3( 2.2 ) );
|
|
|
|
vec3 radiance = mix(cube_a_rad, cube_b_rad, cross_fader);
|
|
vec3 irradiance = mix(cube_a_irr, cube_b_irr, cross_fader);
|
|
|
|
// get the approximate reflectance
|
|
// float NoV = saturate( dot( N, V ) );
|
|
float NoV = clamp( dot( N, V ), 0., 1. );
|
|
vec3 reflectance = EnvBRDFApprox( specularColor, pow( abs(u_roughness * roughnessMask), 4.0 ), NoV );
|
|
|
|
// combine the specular IBL and the BRDF
|
|
vec3 diffuse = diffuseColor * radiance;
|
|
vec3 specular = radiance * reflectance;
|
|
m_col = (diffuse + specular)*u_audio_level*(1.-min(m_fresnel, .99));
|
|
|
|
#if defined(HAS_SHADOW)
|
|
// from light source
|
|
vec3 m_light_diffuse_color = vec3(m_diffuse)*3.;
|
|
vec3 m_light_specular_color = vec3(m_diffuse)*3.;
|
|
float m_light_diffuse_intensity = 30.;
|
|
float m_light_specular_intensity = 30.;
|
|
float m_light_diffuse_pow = 150.;
|
|
float m_light_specular_pow = 120.;
|
|
|
|
// Diffuse factor
|
|
float NdotL = max( dot( N, L ), 0.0 );
|
|
vec3 D = vec3( NdotL );
|
|
D = pow(abs(D), vec3(m_light_diffuse_pow));
|
|
D *= m_light_diffuse_color * m_light_diffuse_intensity;
|
|
|
|
// Specular factor
|
|
vec3 S = pow( max( dot( R, V ), 0.0 ), m_light_specular_pow ) * vec3(1.);
|
|
S *= m_light_specular_color * m_light_specular_intensity;
|
|
|
|
m_col += (D + S)*u_audio_level*(1.-min(m_fresnel, .99));
|
|
|
|
// cal shadow
|
|
float m_shadow = 1.;
|
|
vec4 m_shadow_coord = v_shadow_coord;
|
|
m_shadow_coord.z += .0003; // <- bias
|
|
|
|
m_shadow = sample_shadow(m_shadow_coord);
|
|
m_col *= (m_shadow + m_col*.2 + m_diffuse*.5);
|
|
#endif
|
|
|
|
// add noise diffuse
|
|
m_col += pow(abs(m_diffuse), vec3(10.))*8.;
|
|
|
|
// apply the tone-mapping
|
|
m_col = Uncharted2Tonemap( m_col * u_exposure );
|
|
// white balance
|
|
m_col = m_col * ( 1. / (Uncharted2Tonemap( vec3( 20. ) ) + .00001) );
|
|
|
|
// gamma correction
|
|
m_col = pow( abs(m_col), vec3( 1. / (u_gamma + .00001) ) );
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(IS_WIRE) || defined(IS_POINTS)
|
|
m_col.b -= m_col.g;
|
|
|
|
// inner ziggle
|
|
m_col *= .4 * pow(abs(m_noise), 6.);
|
|
|
|
// outter ziggle
|
|
m_col.rg += .2 * pow(abs(m_noise_inv), 4.);
|
|
m_col.g *= .5;
|
|
|
|
// treble burn
|
|
m_col += pow(abs(u_audio_high), 3.) * 1.;
|
|
|
|
// on&off
|
|
m_col *= u_audio_level;
|
|
|
|
#if defined(IS_WIRE)
|
|
m_col *= .7;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
gl_FragColor = vec4(m_col, 1.);
|
|
|
|
#if defined(HAS_SHADOW)
|
|
if(u_debug_shadow)
|
|
gl_FragColor = vec4(vec3(m_shadow), 1.);
|
|
#endif
|
|
|
|
|
|
#if defined(IS_POINTS)
|
|
gl_FragColor *= texture2D(tex_sprite, gl_PointCoord);
|
|
#endif
|
|
|
|
|
|
#if defined(IS_POP) || defined(IS_POP_OUT)
|
|
gl_FragColor.rgb = pow(abs(gl_FragColor.rgb), vec3(1.2));
|
|
|
|
#if defined(IS_POINTS) && defined(IS_POP)
|
|
gl_FragColor.rgb *= pow(u_audio_level, 2.);
|
|
gl_FragColor.rgb *= 50.;
|
|
#endif
|
|
|
|
#if defined(IS_WIRE)
|
|
gl_FragColor.rgb *= 2.;
|
|
|
|
#if defined(IS_POP_OUT)
|
|
gl_FragColor.rgb *= .2;
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
}
|
|
`
|