Files
starruler-linux/data/shaders/source/pbr_ship_ps.txt
T
2018-07-17 14:15:37 +02:00

332 lines
13 KiB
Plaintext

#version 120
const int nLightCount = 2;
const float pi = 3.14159265358;
uniform sampler2D diffuse, normalAOlights, shield, masks;
uniform samplerCube skybox;
uniform vec4 ownerColor;
uniform vec3 glowColor;
uniform float thrust;
uniform float camDist;
uniform float time, nodeScale;
float teamNumber = 5;
//varying vec4 shadowCoord[nLightCount];
varying vec3 forward, right;
varying vec3 normal, binormal, tangent;
varying vec3 npos;
varying vec2 uv, uv2, uv3;
varying vec4 vertPaint;
vec3 light[nLightCount];
float dist[nLightCount];
/*
//Skybox sampling call
vec2 skyboxSample(vec3 dir) {
float x = dot(dir, forward);
float z = dot(dir, right);
float y = dot(dir, cross(forward,right));
return vec2(atan(-x,z) / 6.28318530718, (y + 1.0) * 0.5);
}
*/
//Engine heat color call
float mixRange(float x, float low, float hi) {
return clamp((x - low) / (hi - low), 0.0, 1.0);
}
vec3 blackBody(float temp) {
vec3 c;
c.r = mix(1.0, 0.6234, mixRange(temp, 6400.0, 29800.0));
c.b = mix(0.0, 1.0, mixRange(temp, 2800.0, 7600.0));
if(temp < 6600.0)
c.g = mix(0.22, 0.976, mixRange(temp, 1000.0, 6600.0));
else
c.g = mix(0.976, 0.75, mixRange(temp, 6600.0, 29800.0));
return c;
}
float D_GGX(float HdotN, float Roughness)
{
float m = Roughness * Roughness;
float m2 = m * m;
float denominator = HdotN * HdotN * (m2 - 1.0) + 1.0;
float D = m2 /( pi * denominator * denominator);
return D;
}
// Schlick GGX approximation
float V_SchlickforGGX(float Roughness, float NdotV, float NdotL)
{
float k = Roughness * Roughness * 0.5f;
float G1V = NdotV * (1.0 - k) + k;
float G1L = NdotL * (1.0 - k) + k;
return 0.25f / (G1V * G1L);
}
vec3 Fresnel(vec3 substance, vec3 l, vec3 h)
{
return substance + (1.0 - substance) * pow(1.0 - clamp((dot(l, h)), 0.0, 1.0), 5.0);
}
vec3 Fresnel2(vec3 substance, float dotProduct, float roughness)
{
return substance + (1.0 - substance) * pow((1.0 - dotProduct), 5.0) / (6.0 - 5.0 * roughness);
}
float RoughToSPow(float fRoughness)
{
return (2.0 / (fRoughness * fRoughness)) - 2.0;
}
const float k0 = 0.00098f, k1 = 0.9921f;
const float g_fMaxT = (exp2(-10.0 / sqrt((2.0 / (0.0014f * 0.0014f)) - 2.0)) - 0.00098f) / 0.9921f;
float GetSpecPowToMip(float fSpecPow, int nMips)
{
float fSmulMaxT = (exp2( -10.0 / sqrt(fSpecPow)) - k0) / k1;
return float(nMips - 1) * (1.0 - clamp(fSmulMaxT / g_fMaxT, 0.0, 1.0 ));
}
void main() {
vec4 diffuse = texture2D(diffuse, uv.xy);
vec4 normAO = texture2D(normalAOlights, uv.xy);
vec3 maskSamp = texture2D(masks, uv.xy).rgb;
float paintSamp = texture2D(masks, uv2.xy).w;
float flagSamp = texture2D(masks, uv2.xy + vec2((1.0/32.0) * teamNumber, 0.0)).w;
vec3 vertMasksPrimary = vertPaint.rgb; // .a unused
//float texSamp7 = texture2D(shield, uv2.xy * 10);
//float texSamp8 = texture2D(shield, uv2.xy - time * 80.0);
float texSamp5 = texture2D(shield, uv2.xy - 8.0 * 24.0).r;
float texSamp6 = texture2D(shield, uv2.xy + time * 24.0).g;
// Normal map setup
vec3 normMap = normAO.xyz * 2.0 - vec3(1.0);
// Vertex masks setup
vec3 vertMasksSecondary = (clamp(vertMasksPrimary, 0.5, 1.0) - 0.5) * 2.0; // shield r, windows g, engine b
vertMasksPrimary = clamp(((1.0 - vertMasksPrimary) - 0.5)* 2.0, 0.0, 1.0); // flags g, warp b, transparency on r
// Texture masks setup
float paintMask = (flagSamp * vertMasksPrimary.g + paintSamp * (1.0-vertMasksPrimary.g)) * maskSamp.b;
float plateMask = maskSamp.b * (1.0-paintMask);
float roughnessTweakMask = plateMask * (1.0-paintMask);
float lightsOne = (clamp(1.0 - normAO.w, 0.5, 1.0) - 0.5) * 2.0;
float lightsTwo = (clamp(normAO.w, 0.5, 1.0) - 0.5) * 2.0;
// Emissive lights setup
vec3 lights = vec3(0.0);
float lightMask = 1.0 - vertMasksSecondary.r - vertMasksSecondary.g - vertMasksSecondary.b - vertMasksPrimary.b; // filter for no-special lights
// Primary and secondary lights are added - should be selectable, as owner and inverted owner is not always nice
lights += vec3(lightsOne * lightMask * ownerColor.rgb * 2.0);
lights += vec3(lightsTwo * lightMask * (1.0 - ownerColor.rgb) * 2.0);
// Warp drive is added - currently no models contains the mask.
float engineGlow = texSamp5 * texSamp6;
// lights += vec3(2.0, 0.0, 2.0) * (1.0 + engineGlow) * lightsTwo * vertMasksPrimary.b;
// Windows are added
lights += glowColor * vertMasksSecondary.g * lightsOne;
// Engine animation is created
engineGlow = lightsOne * (/*lightsOne * 2.0 + */engineGlow * 2.0) * vertMasksSecondary.b;
// Gives nice intensity and falloff transitions.
lights = pow(lights + (lightsOne + lightsTwo) * 1.0, vec3(1.5)) * (1.0 - vertMasksPrimary.r);
// Transparency setup
float transparency = min(clamp((clamp(diffuse.w,0.25, 0.5) - 0.25), 0.0, 0.25) * 4 + 0.25, 1.0-vertMasksPrimary.r);
// Transparency and ao extractionsetup
float ao = (1.0-((1.0-transparency) * 0.5 + diffuse.w))*2.0;
// Engine setup
float thrustIntensity = pow(thrust * 1.0, 2.0) * engineGlow;
lights += (blackBody(1000.0 + 5000.0 * thrustIntensity) * thrustIntensity);
// Player color setup - move the PBR values to external source!
// float playerMetal = 0.01; //PBR gold
// vec3 playerMetalCol = vec3(1.0, 0.77, 0.33); //PBR gold
// float playerMetal = 0.25; //PBR bronze
// vec3 playerMetalCol = vec3(0.99, 0.64, 0.34); //PBR bronze
// float playerMetal = 0.13; //PBR brass
// vec3 playerMetalCol = vec3(0.98, 0.87, 0.41); //PBR brass
// float playerMetal = 0.35; //PBR Copper
// vec3 playerMetalCol = vec3(0.98, 0.60, 0.52); //PBR Copper
// float playerMetal = 0.10; //PBR Silver
// vec3 playerMetalCol = vec3(0.97, 0.96, 0.91); //PBR Silver
// float playerMetal = 0.01; //PBR Chrome
// vec3 playerMetalCol = vec3(0.91, 0.95, 0.97); //PBR Chrome
// float playerMetal = 0.45; //PBR Titanium
// vec3 playerMetalCol = vec3(0.54, 0.49, 0.46); //PBR Titanium
// float playerMetal = 0.15; //PBR Bright Steel
// vec3 playerMetalCol = vec3(0.84, 0.85, 0.90); //PBR Bright Steel
// float playerMetal = 0.75; //PBR Dull Steel
// vec3 playerMetalCol = vec3(0.56, 0.57, 0.58); //PBR Dull Steel
// float playerMetal = 0.25; //PBR Dark Steel
// vec3 playerMetalCol = vec3(0.48, 0.45, 0.42) ; //PBR Dark Steel
// float playerMetal = 0.27; //PBR Gallium
// vec3 playerMetalCol = vec3(0.88, 0.93, 0.56); //PBR Gallium
// float playerMetal = 0.35; //PBR Molybdenum
// vec3 playerMetalCol = vec3(0.16, 0.22, 0.15); //PBR Molybdenum
// float playerMetal = 0.33; //PBR Niobium
// vec3 playerMetalCol = vec3(0.38, 0.34, 0.62); //PBR Niobium
// float playerMetal = 0.35; //PBR Vanadium
// vec3 playerMetalCol = vec3(0.08, 0.10, 0.09); //PBR Vanadium
// float playerMetal = 0.25; //PBR Adamantium
// vec3 playerMetalCol = vec3(0.26, 0.18, 0.25); //PBR Adamantium
// float playerMetal = 0.07; //PBR Tritinium
// vec3 playerMetalCol = vec3(0.54, 0.49, 0.62); //PBR Tritinium
// float playerMetal = 0.03; //PBR Zentronium
// vec3 playerMetalCol = vec3(0.96, 0.48, 0.43); //PBR Zentronium
// float playerMetal = 0.16; //PBR Xintinium
// vec3 playerMetalCol = vec3(0.48, 0.96, 0.96); //PBR Xintinium
// float playerMetal = 0.15; //PBR Duranium
// vec3 playerMetalCol = vec3(0.94, 0.24, 0.02); //PBR Duranium
// float playerMetal = 1.0; //PBR Carbon Fibre Complimentary
// vec3 playerMetalCol = vec3(1.0 - ownerColor) * 0.25; //PBR Carbon Fibre Complimentary
// float playerMetal = 0.9; //PBR Ceramic Complimentary
// vec3 playerMetalCol = vec3(1.0 - ownerColor) * 0.64 + vec3(0.32); //PBR Ceramic Complimentary
// float playerMetal = 1.0; //PBR Paint Complimentary
// vec3 playerMetalCol = vec3(1.0 - ownerColor); //PBR Paint Complimentary
float playerMetal = 0.15; //PBR Metal Complimentary
vec3 playerMetalCol = vec3(1.0 - ownerColor) * 0.5 + vec3(0.5); //PBR Metal Complimentary
vec4 playerPlateProfile = vec4(playerMetalCol, playerMetal);
// PBR mixer
playerMetal = clamp(playerMetal, 0.001, 1.0) * plateMask;
vec3 paintColor = ownerColor.rgb * (1.0-paintMask);
float metalness = clamp(maskSamp.g * max(0.5, 1.0-paintMask), 0.0, 1.0);
// Roughness setup
float orgRoughness = maskSamp.r * (1.0-plateMask) + plateMask * (plateMask * playerPlateProfile.w);
// Albedo setup
vec3 albedo = mix(diffuse.rgb * plateMask * playerMetalCol, ownerColor.rgb * diffuse.rgb, paintMask);
albedo = mix(diffuse.rgb, albedo, maskSamp.b);
// Shield setup.
lights *= (1.0 - vertMasksSecondary.r);
//vertMasksSecondary.r * (1.0 - abs(texSamp5 * texSamp6 * 2.0 - 1.0)) * vec3(0.33, 0.99, 2.0);
// transparency *= vertMasksSecondary.r * (1.0 - abs(texSamp5 * texSamp6 * 2.0 - 1.0)) * 0.66;
transparency *= clamp(1.0 - vertMasksSecondary.r * 0.5, 0.0, 1.0);
transparency += (texSamp5 * texSamp6);// * vertMasksSecondary.r;
lights += transparency * vec3(0.33, 0.99, 2.0) * vertMasksSecondary.r;
//Adjust all other PBR textures accordingly
ao *= 1.0 - vertMasksSecondary.r;
orgRoughness *= 1.0 - vertMasksSecondary.r;
metalness *= 1.0 - vertMasksSecondary.r;
albedo *= 1.0-vertMasksSecondary.r;
normMap = normalize(mix(normMap, vec3(0.0,0.0,1.0), vertMasksSecondary.r));
// Normal setup
vec3 n = normalize(normal) * normMap.z;
n += normalize(binormal) * normMap.y;
n += normalize(tangent) * normMap.x;
n = normalize(n);
vec3 v = normalize(npos);
vec3 r = normalize(reflect(-v, n));
// Substance setup and Albedo adjust
vec3 substance = clamp((0.04 - 0.04 * metalness) + albedo * metalness,0.0, 1.0);
albedo -= substance;
// Light model specials setup
float NdotV = clamp(dot(n, v), 0.0, 1.0);
float roughnessV = (orgRoughness + 1.0)/2.0; // roughness remapping
if(nLightCount > 0) {
const int i = 0;
light[i] = gl_LightSource[i].position.xyz + npos;
dist[i] = length(light[i]);
light[i] = light[i] / dist[i];
}
if(nLightCount > 1) {
const int i = 1;
light[i] = gl_LightSource[i].position.xyz + npos;
dist[i] = length(light[i]);
light[i] = light[i] / dist[i];
}
//Zoom-out highlight setup
float highlight = 0.0;
if(camDist > 1.0)
highlight += smoothstep(0.0, 500.0, camDist / sqrt(nodeScale)) * 0.2;
vec3 color = vec3(highlight);
// Ambient reflections
float fakeLysSpecularPower=RoughToSPow(orgRoughness);
float lysMipMap = GetSpecPowToMip(fakeLysSpecularPower,8);
color += textureCube(skybox, r, lysMipMap).rgb * Fresnel2(substance,NdotV,orgRoughness);
// use this if you want a cheaper reflection cubemap calculation. If so, remember to remove the GetSpecPowToMip() and RoughToSPow()
// color += textureCube(skybox, r,8.0 - (8.0*(1.0-orgRoughness))).rgb * reflectionFresnel;
// Ambient light
color += textureCube(skybox, n, 7.0).rgb * albedo * (1.0 - Fresnel2(substance,NdotV,orgRoughness));
if(nLightCount > 0) {
//light
const int i = 0;
// float falloff = 1.0 / (1.0 + (gl_LightSource[i].quadraticAttenuation * dist[i] * dist[i]));
// float NdotL = clamp(dot(n,light[i]) + 0.2,0.0, 1.0);
// fakes disc lights up close to a star.
float falloff = 1.0 / (0.25 + (gl_LightSource[i].quadraticAttenuation * dist[i] * dist[i]));
float NdotL = clamp(dot(n,light[i]) + 0.2,0.0, 1.0);
float intensity = falloff * NdotL;
vec3 L=light[i];
L = normalize(L);
vec3 VplusL = L + v;
vec3 halfVec = normalize(VplusL);
float HdotN = clamp(dot(halfVec,n), 0.0, 0.98);
vec3 F = Fresnel(substance, L, halfVec);
float D = D_GGX(HdotN, roughnessV);
float V = V_SchlickforGGX(roughnessV, NdotV, NdotL);
color += ao * ((D * V * F) + (1.0 - F) * NdotL * albedo) * gl_LightSource[i].diffuse.rgb * intensity;
}
if(nLightCount > 1) {
//light
const int i = 1;
// float falloff = 1.0 / (1.0 + (gl_LightSource[i].quadraticAttenuation * dist[i] * dist[i]));
// float NdotL = clamp(dot(n,light[i]) + 0.2,0.0, 1.0);
// fakes disc lights up close to a star.
float falloff = 1.0 / (0.25 + (gl_LightSource[i].quadraticAttenuation * dist[i] * dist[i]));
float NdotL = clamp(dot(n,light[i]) + 0.2,0.0, 1.0);
float intensity = falloff * NdotL;
vec3 L=light[i];
L = normalize(L);
vec3 VplusL = L + v;
vec3 halfVec = normalize(VplusL);
float HdotN = clamp(dot(halfVec,n), 0.0, 1.0);
vec3 F = Fresnel(substance, L, halfVec);
float D = D_GGX(HdotN, roughnessV);
float V = V_SchlickforGGX(roughnessV, NdotV, NdotL);
color += ao * ((D * V * F) + (1.0 - F) * NdotL * albedo) * gl_LightSource[i].diffuse.rgb * intensity;
}
gl_FragColor.rgb = color + lights;
gl_FragColor.a = transparency + 1.0;
}