Files
2021-08-29 02:20:53 -04:00

339 lines
8.9 KiB
GLSL

/*
(C) 2019 David Lettier
lettier.com
*/
#version 150
#define NUMBER_OF_LIGHTS 4
#define MAX_SHININESS 127.75
#define MAX_FRESNEL_POWER 5.0
uniform float osg_FrameTime;
uniform vec2 pi;
uniform vec2 gamma;
uniform mat4 trans_world_to_view;
uniform mat4 trans_view_to_world;
uniform sampler2D p3d_Texture0;
uniform sampler2D p3d_Texture1;
uniform sampler2D p3d_Texture2;
uniform sampler2D flowTexture;
uniform sampler2D ssaoBlurTexture;
uniform struct
{ vec4 ambient
; vec4 diffuse
; vec4 emission
; vec3 specular
; float shininess
;
} p3d_Material;
uniform struct
{ vec4 ambient
;
} p3d_LightModel;
uniform struct p3d_LightSourceParameters
{ vec4 color
; vec4 ambient
; vec4 diffuse
; vec4 specular
; vec4 position
; vec3 spotDirection
; float spotExponent
; float spotCutoff
; float spotCosCutoff
; float constantAttenuation
; float linearAttenuation
; float quadraticAttenuation
; vec3 attenuation
; sampler2DShadow shadowMap
; mat4 shadowViewMatrix
;
} p3d_LightSource[NUMBER_OF_LIGHTS];
uniform vec2 normalMapsEnabled;
uniform vec2 fresnelEnabled;
uniform vec2 rimLightEnabled;
uniform vec2 blinnPhongEnabled;
uniform vec2 celShadingEnabled;
uniform vec2 flowMapsEnabled;
uniform vec2 specularOnly;
uniform vec2 isParticle;
uniform vec2 isWater;
uniform vec2 sunPosition;
in vec4 vertexColor;
in vec4 vertexInShadowSpaces[NUMBER_OF_LIGHTS];
in vec4 vertexPosition;
in vec3 vertexNormal;
in vec3 binormal;
in vec3 tangent;
in vec2 diffuseCoord;
in vec2 normalCoord;
out vec4 out0;
out vec4 out1;
void main() {
vec3 shadowColor = pow(vec3(0.149, 0.220, 0.227), vec3(gamma.x));
int shadowSamples = 2;
vec4 diffuseColor;
if (isParticle.x == 1) {
diffuseColor = texture(p3d_Texture0, diffuseCoord) * vertexColor;
} else {
diffuseColor = texture(p3d_Texture0, diffuseCoord);
}
diffuseColor.rgb = pow(diffuseColor.rgb, vec3(gamma.x));
vec3 materialSpecularColor = p3d_Material.specular;
vec2 flow = texture(flowTexture, normalCoord).xy;
flow = (flow - 0.5) * 2.0;
flow.x = abs(flow.x) <= 0.02 ? 0.0 : flow.x;
flow.y = abs(flow.y) <= 0.02 ? 0.0 : flow.y;
vec4 normalTex =
texture
( p3d_Texture1
, vec2
( normalCoord.x + flowMapsEnabled.x * flow.x * osg_FrameTime
, normalCoord.y + flowMapsEnabled.y * flow.y * osg_FrameTime
)
);
vec3 normal;
if (isParticle.x == 1) {
normal = normalize((trans_world_to_view * vec4(0.0, 0.0, 1.0, 0.0)).xyz);
} else if (normalMapsEnabled.x == 1) {
vec3 normalRaw =
normalize
( normalTex.rgb
* 2.0
- 1.0
);
normal =
normalize
( mat3
( tangent
, binormal
, vertexNormal
)
* normalRaw
);
} else {
normal =
normalize(vertexNormal);
}
vec4 specularMap = texture(p3d_Texture2, diffuseCoord);
vec4 diffuse = vec4(0.0, 0.0, 0.0, diffuseColor.a);
vec4 specular = vec4(0.0, 0.0, 0.0, diffuseColor.a);
for (int i = 0; i < p3d_LightSource.length(); ++i) {
vec3 lightDirection =
p3d_LightSource[i].position.xyz
- vertexPosition.xyz
* p3d_LightSource[i].position.w;
vec3 unitLightDirection = normalize(lightDirection);
vec3 eyeDirection = normalize(-vertexPosition.xyz);
vec3 reflectedDirection = normalize(-reflect(unitLightDirection, normal));
vec3 halfwayDirection = normalize(unitLightDirection + eyeDirection);
float lightDistance = length(lightDirection);
float attenuation =
1.0
/ ( p3d_LightSource[i].constantAttenuation
+ p3d_LightSource[i].linearAttenuation
* lightDistance
+ p3d_LightSource[i].quadraticAttenuation
* (lightDistance * lightDistance)
);
if (attenuation <= 0.0) { continue; }
float diffuseIntensity = dot(normal, unitLightDirection);
if (diffuseIntensity < 0.0) { continue; }
diffuseIntensity =
celShadingEnabled.x == 1
? smoothstep(0.1, 0.2, diffuseIntensity)
: diffuseIntensity;
vec4 lightDiffuseColor = p3d_LightSource[i].diffuse;
lightDiffuseColor.rgb = pow(lightDiffuseColor.rgb, vec3(gamma.x));
vec4 diffuseTemp =
vec4
( clamp
( diffuseColor.rgb
* lightDiffuseColor.rgb
* diffuseIntensity
, 0.0
, 1.0
)
, diffuseColor.a
);
float specularIntensity =
( blinnPhongEnabled.x == 1
? clamp(dot(normal, halfwayDirection), 0.0, 1.0)
: clamp(dot(eyeDirection, reflectedDirection), 0.0, 1.0)
);
specularIntensity =
( celShadingEnabled.x == 1
? smoothstep(0.9, 1.0, specularIntensity)
: specularIntensity
);
vec4 lightSpecularColor = p3d_LightSource[i].specular;
lightSpecularColor.rgb = pow(lightSpecularColor.rgb, vec3(gamma.x));
vec4 materialSpecularColor = vec4(vec3(specularMap.r), diffuseColor.a);
if (fresnelEnabled.x == 1) {
float fresnelFactor = dot((blinnPhongEnabled.x == 1 ? halfwayDirection : normal), eyeDirection);
fresnelFactor = max(fresnelFactor, 0.0);
fresnelFactor = 1.0 - fresnelFactor;
fresnelFactor = pow(fresnelFactor, specularMap.b * MAX_FRESNEL_POWER);
materialSpecularColor.rgb = mix(materialSpecularColor.rgb, vec3(1.0), clamp(fresnelFactor, 0.0, 1.0));
}
vec4 specularTemp = vec4(vec3(0.0), diffuseColor.a);
specularTemp.rgb = lightSpecularColor.rgb * pow(specularIntensity, specularMap.g * MAX_SHININESS);
specularTemp.rgb *= materialSpecularColor.rgb;
specularTemp.rgb *= (1 - isParticle.x);
specularTemp.rgb = clamp(specularTemp.rgb, 0.0, 1.0);
float unitLightDirectionDelta =
dot
( normalize(p3d_LightSource[i].spotDirection)
, -unitLightDirection
);
if (unitLightDirectionDelta < p3d_LightSource[i].spotCosCutoff) { continue; }
float spotExponent = p3d_LightSource[i].spotExponent;
diffuseTemp.rgb *= (spotExponent <= 0.0 ? 1.0 : pow(unitLightDirectionDelta, spotExponent));
vec2 shadowMapSize = textureSize(p3d_LightSource[i].shadowMap, 0);
float inShadow = 0.0;
float count = 0.0;
for ( int si = -shadowSamples; si <= shadowSamples; ++si) {
for (int sj = -shadowSamples; sj <= shadowSamples; ++sj) {
inShadow +=
( 1.0
- textureProj
( p3d_LightSource[i].shadowMap
, vertexInShadowSpaces[i] + vec4(vec2(si, sj) / shadowMapSize, vec2(0.0))
)
);
count += 1.0;
}
}
inShadow /= count;
vec3 shadow =
mix
( vec3(1.0)
, shadowColor
, inShadow
);
diffuseTemp.rgb *= mix(shadow, vec3(1.0), isParticle.x);
specularTemp.rgb *= mix(shadow, vec3(1.0), isParticle.x);
diffuseTemp.rgb *= attenuation;
specularTemp.rgb *= attenuation;
diffuse.rgb += diffuseTemp.rgb;
specular.rgb += specularTemp.rgb;
}
vec4 rimLight = vec4(vec3(0.0), diffuseColor.a);
if (rimLightEnabled.x == 1) {
rimLight.rgb =
vec3
( 1.0
- max
( 0.0
, dot(normalize(-vertexPosition.xyz), normalize(normal))
)
);
rimLight.rgb =
( celShadingEnabled.x == 1
? smoothstep(0.3, 0.4, rimLight.rgb)
: pow(rimLight.rgb, vec3(2.0)) * 1.2
);
rimLight.rgb *= diffuse.rgb;
}
vec2 ssaoBlurTexSize = textureSize(ssaoBlurTexture, 0).xy;
vec2 ssaoBlurTexCoord = gl_FragCoord.xy / ssaoBlurTexSize;
vec3 ssao = texture(ssaoBlurTexture, ssaoBlurTexCoord).rgb;
ssao = mix(shadowColor, vec3(1.0), clamp(ssao.r, 0.0, 1.0));
float sunPosition = sin(sunPosition.x * pi.y);
float sunMixFactor = 1.0 - (sunPosition / 2.0 + 0.5);
vec3 ambientCool = pow(vec3(0.302, 0.451, 0.471), vec3(gamma.x)) * max(0.5, sunMixFactor);
vec3 ambientWarm = pow(vec3(0.765, 0.573, 0.400), vec3(gamma.x)) * max(0.5, sunMixFactor);
vec3 skyLight = mix(ambientCool, ambientWarm, sunMixFactor);
vec3 groundLight = mix(ambientWarm, ambientCool, sunMixFactor);
vec3 worldNormal = normalize((trans_view_to_world * vec4(normal, 0.0)).xyz);
vec3 ambientLight =
mix
( groundLight
, skyLight
, 0.5 * (1.0 + dot(worldNormal, vec3(0, 0, 1)))
);
vec3 ambient =
ambientLight.rgb
* diffuseColor.rgb
* ssao;
vec3 emission = p3d_Material.emission.rgb * max(0.1, pow(sunPosition, 0.4));
out0.a = diffuseColor.a;
out0.rgb = ambient.rgb
+ diffuse.rgb
+ rimLight.rgb
+ emission.rgb;
if (isWater.x == 1) { out0.a = 0.0; }
out1.a = diffuseColor.a;
out1.rgb = specular.rgb;
if (isParticle.x == 1) { out1.rgb = vec3(0.0); }
}