// vert // out vec3 view_dir, world_dir; uniform vec4 view_corners[4], world_corners[4]; void main(void) { qgl_FragTexture = qgl_Texture; gl_Position = qgl_ftransform(); view_dir = view_corners [gl_VertexID].xyz; world_dir = world_corners[gl_VertexID].xyz; } // frag // in vec3 view_dir, world_dir; uniform vec2 dt; uniform float z_near; uniform sampler2D tex_coeffs[2]; uniform sampler2D tex_0, tex_1, tex_2, tex_3, tex_4; uniform samplerCube tex_env; uniform int lights_start, lights_count; uniform vec4 fog_color = vec4(0.5, 0.5, 0.5, 1); uniform float fog_decay = 10, fog_density = 0; uniform mat3 view_mat; const vec3 luma = vec3(0.299, 0.587, 0.114); const float _min_rough = 1.e-8, max_lod = 8; vec4 pos, lpos, shp; vec3 li, si, ldir, halfV, bn, bn2, lwdir; //vec3 vds, vds2; float rough_diff, rough_spec, dist, NdotL, NdotH, spot, ldist, diff, spec, sdist, shadow; void calcLight(in int index, in vec3 n, in vec3 v) { lpos = qgl_light_position[index].position; ldir = lpos.xyz - (pos.xyz * lpos.w); ldist = length(ldir); ldir = normalize(ldir); //ldir = vec3(0,0,1); halfV = normalize(ldir + v); NdotL = max(dot(n, ldir), 1E-8); NdotH = max(dot(n, halfV), 1E-8); spot = step(1.001E-8, NdotL) * qgl_light_parameter[index].decay_intensity.w; #ifdef SPOT float scos = max(dot(-ldir, qgl_light_position[index].direction.xyz), 0.); spot *= scos * step(qgl_light_parameter[index].angles.w, scos); spot *= smoothstep(qgl_light_parameter[index].angles.w, qgl_light_parameter[index].angles.y, scos); /*//lwdir = mat3(mat_viewi) * qgl_Light[index].direction.xyz; //bn = normalize(cross(lwdir, vec3(1, 0, 0))); //bn2 = normalize(cross(lwdir, bn)); float ds = ldist/200.;//max(abs(sdist) / 5000, 0.02); //spot *= clamp(1. - sdist, 0, 1); vds = ds * bn.xyz; vds2 = ds * bn2.xyz; float shadow = getShadow(index, pos.xyz, vec3(0)) * 3.; shadow += getShadow(index, pos.xyz, vds ) * 2.; shadow += getShadow(index, pos.xyz, - vds ) * 2.; shadow += getShadow(index, pos.xyz, - vds2 ) * 2.; shadow += getShadow(index, pos.xyz, + vds2 ) * 2.; //shadow += getShadow(index, pos.xyz, vds - vds2 ) * 1.5; //shadow += getShadow(index, pos.xyz, vds + vds2 ) * 1.5; //shadow += getShadow(index, pos.xyz, - vds - vds2 ) * 1.5; //shadow += getShadow(index, pos.xyz, - vds + vds2 ) * 1.5; //shadow += getShadow(index, pos.xyz, vds + vds ); //shadow += getShadow(index, pos.xyz, - vds - vds ); //shadow += getShadow(index, pos.xyz, - vds2 - vds2); //shadow += getShadow(index, pos.xyz, + vds2 + vds2); //shadow += getShadow(index, pos.xyz, vds + vds - vds2 ); //shadow += getShadow(index, pos.xyz, - vds - vds - vds2 ); //shadow += getShadow(index, pos.xyz, vds + vds + vds2 ); //shadow += getShadow(index, pos.xyz, - vds - vds + vds2 ); //shadow += getShadow(index, pos.xyz, vds - vds2 - vds2); //shadow += getShadow(index, pos.xyz, vds + vds2 + vds2); //shadow += getShadow(index, pos.xyz, - vds - vds2 - vds2); //shadow += getShadow(index, pos.xyz, - vds + vds2 + vds2); //shadow += shadow += getShadow(index, pos.xyz, vds+vds2)*10; spot *= mix(1., shadow / 11., shadow_on);*/ #endif vec3 dist_decay = vec3(1, ldist, ldist*ldist); spot /= dot(qgl_light_parameter[index].decay_intensity.xyz, dist_decay); float NdotLs = NdotL*NdotL; float NdotHs = NdotH*NdotH; float ndlc = (1. - NdotLs) / NdotLs; diff = 2. / (1. + sqrt(1. + (1. - rough_diff) * ndlc)); //diff = texture(tex_coeffs[0], vec2(roughness, (NdotLs))).r; li += spot * diff * qgl_light_parameter[index].color.rgb; ndlc = (1. - NdotHs) / NdotHs; float der = NdotHs * (rough_spec + ndlc); spec = rough_spec / (der*der) / 3.1416; //spec = texture(tex_coeffs[1], vec2(roughness, (NdotHs))).r; si += spot * spec * qgl_light_parameter[index].color.rgb; } float GeometrySchlickGGX(float NdotV, float roughness) { float a = roughness; float k = (a * a) / 2.0; float nom = NdotV; float denom = NdotV * (1.0 - k) + k; return nom / denom; } // ---------------------------------------------------------------------------- float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { float NdotV = max(dot(N, V), 0.0); float NdotL = max(dot(N, L), 0.0); float ggx2 = GeometrySchlickGGX(NdotV, roughness); float ggx1 = GeometrySchlickGGX(NdotL, roughness); return ggx1 * ggx2; } void main(void) { ivec2 tc = ivec2(gl_FragCoord.xy); vec4 v1 = texelFetch(tex_1, tc, 0); float z = v1.w; if (z == 1.) { discard; } pos.w = 1; pos.xyz = view_dir * z; vec3 v = normalize(-pos.xyz); vec4 v0 = texelFetch(tex_0, tc, 0), v2 = texelFetch(tex_2, tc, 0), v3 = texelFetch(tex_3, tc, 0), v4 = texelFetch(tex_4, tc, 0); vec3 diffuse = v0.rgb; vec3 normal = v1.xyz; vec3 emission = v3.rgb; float alpha = v0.a; float metalness = v2.r; float roughness = v2.g; float reflectivity = v2.b; float NdotV = dot(normal, v); float roughness3 = roughness*roughness*roughness; //bn = normalize(vec3(v3.w, v4.zw)); //bn2 = normalize(cross(n, bn)); rough_diff = max(roughness, _min_rough); rough_spec = max(roughness3, _min_rough); float shlick = clamp(metalness + (1 - metalness) * pow(1 - NdotV, 5), 0, 1); li = vec3(0.);//qgl_AmbientLight.color.rgb * qgl_AmbientLight.intensity; si = vec3(0.); for (int i = 0; i < lights_count; ++i) calcLight(lights_start + i, normal, v); si *= shlick; li *= (1 - shlick); alpha = min(1, alpha * (1 + shlick)); vec2 brdf = texture(tex_coeffs[0], vec2(NdotV*0.99, roughness*0.995)).rg; float env_spec = shlick * brdf.x + brdf.y; vec3 spec_col = mix(vec3(1), diffuse, metalness); vec3 env_dir = view_mat * reflect(-v, normal); vec3 env_col = textureLod(tex_env, env_dir, sqrt(roughness) * max_lod).rgb * spec_col; vec3 res_col = max(vec3(0), li * diffuse + si * spec_col + emission); res_col = mix(res_col, env_col, env_spec * reflectivity); float plen = length(pos.xyz); float fog = 1 - exp(-plen / fog_decay); fog = clamp(fog * fog_color.a * fog_density, 0, 1); res_col = mix(res_col, fog_color.rgb, fog); qgl_FragColor = vec4(res_col, alpha); //vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y); //qgl_FragColor.rgb = vec3(shlick * brdf.x + brdf.y); //qgl_FragColor.rgb = vec3(alpha); //qgl_FragColor.rgb = vec3(textureLod(tex_env, world_dir, 0).rgb); //qgl_FragColor.a = 1.; }