1
0
Fork 0
Univerxel/content/shaders/Main.fs

178 lines
6.6 KiB
GLSL

#version 330 core
// Ouput data
layout(location = 0) out vec4 color;
uniform sampler2DArray TextureAtlas;
uniform sampler2DArray NormalAtlas;
uniform sampler2DArray HOSAtlas;
uniform mat4 View;
uniform vec4 FogColor;
#ifdef GEOMETRY
in GeometryData
#else
in VertexData
#endif
{
vec3 Position_modelspace;
#ifdef GEOMETRY
flat uint Materials[3];
vec3 MaterialRatio;
#else
flat uint Material;
#endif
vec3 FaceNormal_modelspace;
#ifdef PBR
vec3 FaceNormal_worldspace;
vec3 EyeDirection_cameraspace;
vec3 LightDirection_cameraspace;
#endif
#ifdef FOG
float Depth;
#endif
} vs;
vec3 expand(vec3 v) {
return (v - 0.5) * 2;
}
vec4 getTexture(sampler2DArray sample, vec2 UV) {
#ifdef GEOMETRY
#ifdef BLEND
vec4 colx = texture(sample, vec3(UV, vs.Materials[0]));
if(vs.Materials[1] == vs.Materials[0]) {
return vs.Materials[2] == vs.Materials[0] ? colx :
mix(colx, texture(sample, vec3(UV, vs.Materials[2])), vs.MaterialRatio.z);
} else {
vec4 coly = texture(sample, vec3(UV, vs.Materials[1]));
return vs.Materials[2] == vs.Materials[0] ? mix(colx, coly, vs.MaterialRatio.y) : (
vs.Materials[2] == vs.Materials[1] ? mix(coly, colx, vs.MaterialRatio.x) :
colx * vs.MaterialRatio.x + coly * vs.MaterialRatio.y + texture(sample, vec3(UV, vs.Materials[2])) * vs.MaterialRatio.z);
}
#else
int mainMaterial = vs.MaterialRatio.x >= vs.MaterialRatio.y ?
(vs.MaterialRatio.x >= vs.MaterialRatio.z ? 0 : 2) :
(vs.MaterialRatio.y >= vs.MaterialRatio.z ? 1 : 2);
return texture(sample, vec3(UV, vs.Materials[mainMaterial]));
#endif
#else
return texture(sample, vec3(UV, vs.Material));
#endif
}
vec4 getTriTexture(sampler2DArray sample, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) {
return getTexture(sample, crdx) * weights.x +
getTexture(sample, crdy) * weights.y +
getTexture(sample, crdz) * weights.z;
}
void main() {
float texScale = .5;
#ifdef TRIPLANAR
// Triplanar
float plateauSize = 0.001;
float transitionSpeed = 2;
vec3 blendWeights = abs(vs.FaceNormal_modelspace);
blendWeights = blendWeights - plateauSize;
blendWeights = pow(max(blendWeights, 0), vec3(transitionSpeed));
vec2 UVx = vs.Position_modelspace.yz * texScale;
vec2 UVy = vs.Position_modelspace.zx * texScale;
vec2 UVz = vs.Position_modelspace.xy * texScale;
vec4 tex = getTriTexture(TextureAtlas, UVx, UVy, UVz, blendWeights);
#ifdef PBR
// Whiteout normal blend
vec3 texNx = expand(getTexture(NormalAtlas, UVx).rgb);
vec3 texNy = expand(getTexture(NormalAtlas, UVy).rgb);
vec3 texNz = expand(getTexture(NormalAtlas, UVz).rgb);
// Swizzle world normals into tangent space and apply Whiteout blend
texNx = vec3(texNx.xy + vs.FaceNormal_worldspace.zy, abs(texNx.z) * vs.FaceNormal_worldspace.x);
texNy = vec3(texNy.xy + vs.FaceNormal_worldspace.xz, abs(texNy.z) * vs.FaceNormal_worldspace.y);
texNz = vec3(texNz.xy + vs.FaceNormal_worldspace.xy, abs(texNz.z) * vs.FaceNormal_worldspace.z);
// Swizzle tangent normals to match world orientation and triblend
vec3 worldNormal = normalize(texNx.zyx * blendWeights.x + texNy.xzy * blendWeights.y +texNz.xyz * blendWeights.z);
vec3 texHOS = getTriTexture(HOSAtlas, UVx, UVy, UVz, blendWeights).rgb;
#endif
#else
// Cheap planar
vec3 blendWeights = abs(vs.FaceNormal_modelspace);
vec3 nrm = normalize(pow(blendWeights, vec3(80)));
vec2 UV = (vec2(vs.Position_modelspace.xy * nrm.z) + vec2(vs.Position_modelspace.yz * nrm.x) + vec2(vs.Position_modelspace.zx * nrm.y)) * texScale;
vec4 tex = getTexture(TextureAtlas, UV);
#ifdef PBR
vec3 texN = expand(getTexture(NormalAtlas, UV).rgb);
// Swizzle world normals into tangent space and apply Whiteout blend
// Swizzle tangent normals to match world orientation and triblend
vec3 worldNormal = normalize(vec3(texN.xy + vs.FaceNormal_worldspace.zy, abs(texN.z) * vs.FaceNormal_worldspace.x).zyx * blendWeights.x +
vec3(texN.xy + vs.FaceNormal_worldspace.xz, abs(texN.z) * vs.FaceNormal_worldspace.y).xzy * blendWeights.y +
vec3(texN.xy + vs.FaceNormal_worldspace.xy, abs(texN.z) * vs.FaceNormal_worldspace.z).xyz * blendWeights.z);
vec3 texHOS = getTexture(HOSAtlas, UV).rgb;
#endif
#endif
// Colors
#ifdef PBR
// Material properties
vec3 MaterialDiffuseColor = tex.rgb;
vec3 MaterialAmbientColor = vec3(.1) * MaterialDiffuseColor * texHOS.y;
vec3 MaterialSpecularColor = vec3(.8) * texHOS.z;
vec3 Normal_cameraspace = normalize((View * vec4(worldNormal,0)).xyz);
// Light emission properties
// You probably want to put them as uniforms
vec3 LightColor = vec3(1, 0.9, 0.9);
float LightPower = 1.2f;
// Distance to the light
float distance = 1.0f;//length( LightPosition_worldspace - Position_worldspace );
// Direction of the light (from the fragment to the light)
vec3 l = normalize(vs.LightDirection_cameraspace);
// Cosine of the angle between the normal and the light direction,
// clamped above 0
// - light is at the vertical of the triangle -> 1
// - light is perpendiular to the triangle -> 0
// - light is behind the triangle -> 0
float cosTheta = clamp(dot(Normal_cameraspace,l), 0,1 );
// Eye vector (towards the camera)
vec3 E = normalize(vs.EyeDirection_cameraspace);
// Direction in which the triangle reflects the light
vec3 R = reflect(-l,Normal_cameraspace);
// Cosine of the angle between the Eye vector and the Reflect vector,
// clamped to 0
// - Looking into the reflection -> 1
// - Looking elsewhere -> < 1
float cosAlpha = clamp( dot( E,R ), 0,1 );
float visibility=1.0;
// MAYBE: shadow
color =
vec4(
// Ambient : simulates indirect lighting
MaterialAmbientColor +
// Diffuse : "color" of the object
visibility * MaterialDiffuseColor * LightColor * LightPower * cosTheta / (distance * distance) +
// Specular : reflective highlight, like a mirror
visibility * MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance * distance),
tex.a
);
#else
color = tex;
#endif
#if FOG
float ratio = exp(vs.Depth * 0.69)-1;
color = mix(color, pow(FogColor, vec4(2.2)), clamp(ratio, 0, 1));
#endif
color = pow(color, vec4(1.0 / 2.2));
}