1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
#version 420 compatibility
#extension GL_ARB_uniform_buffer_object : enable
//#extension GL_ARB_shading_language_420pack: enable
struct SDecal {
vec3 pos;
float rot;
vec4 texcoords;
vec2 size;
float alpha;
};
layout(binding=0) uniform sampler2D decalTex;
layout(binding=1) uniform sampler2D groundNormalsTex;
layout(binding=3) uniform sampler2D infoTex;
layout(binding=4) uniform sampler2D depthTex;
layout(binding=5) uniform sampler2D normalMap;
layout(binding=6) uniform sampler2D normalMap2;
uniform vec3 camPos;
uniform vec2 invScreenSize;
uniform vec2 invMapSize;
uniform vec2 invMapSizePO2; // 1.0f / (pwr2map{x,z} * SQUARE_SIZE) needed for infotex & shadingtex
layout(std140, binding=1) uniform SGroundLighting
{
uniform vec3 ambientColor;
uniform vec3 diffuseColor;
uniform vec3 specularColor;
uniform vec3 dir;
uniform vec3 fogColor;
uniform float fogEnd;
uniform float fogScale;
} groundLighting;
#ifdef HAVE_SHADOWS
uniform mat4 shadowMatrix;
uniform float shadowDensity;
layout(binding=2) uniform sampler2DShadow shadowTex;
#endif
flat in SDecal decal;
flat in mat2 rot;
vec3 ReconstructWorldPos() {
vec2 screenCoord = (gl_FragCoord.st + 0.5) * invScreenSize;
float z = texture2D(depthTex, screenCoord).x;
vec4 ppos;
ppos.xyz = vec3(screenCoord, z) * 2. - 1.;
ppos.w = 1.;
vec4 worldPos4 = gl_ModelViewProjectionMatrixInverse * ppos;
return worldPos4.xyz / worldPos4.w;
}
vec3 GetDiffuseLighting(vec3 worldPos, vec2 ntx) {
//vec3 normal = texture2D(normalMap, ntx).rgg;
vec3 normal = texture2D(normalMap, ntx).rgb;
normal = (normal * 2.0) - 1.0;
//normal.y = sqrt(1.0 - clamp(dot(normal.xz, normal.xz), 0.0, 1.0));
vec3 normal2 = texture2D(normalMap2, ntx * 5.789).rgb;
normal2 = (normal2 * 2.0) - 1.0;
//normal2.y = sqrt(1.0 - clamp(dot(normal2.xz, normal2.xz), 0.0, 1.0));
normal = normalize(normal * 1.0 + normal2);
normal = normal;
normal.xy = rot * normal.xy;
vec3 groundNormal;
groundNormal.xz = texture2D(groundNormalsTex, worldPos.xz * invMapSize).ra;
groundNormal.y = sqrt(1.0 - dot(groundNormal.xz, groundNormal.xz));
vec3 front = normalize(cross(groundNormal, vec3(-1.,0.,0.)));
vec3 right = cross(groundNormal, front);
groundNormal = groundNormal * normal.z + front * normal.y + right * normal.x;
groundNormal = normalize(groundNormal);
float normalSunCos = max(0.0, dot(groundNormal, groundLighting.dir));
vec3 diffuse = groundLighting.diffuseColor * normalSunCos;
return diffuse;
}
float GetShadowOcclusion(vec3 worldPos) {
float shadowInt = 1.0;
#ifdef HAVE_SHADOWS
vec4 vertexShadowPos = shadowMatrix * vec4(worldPos, 1.0);
vertexShadowPos.st += vec2(0.5, 0.5);
shadowInt = shadow2DProj(shadowTex, vertexShadowPos).r;
shadowInt = mix(1.0, shadowInt, shadowDensity);
#endif
return shadowInt;
}
void main() {
gl_FragColor = vec4(0.0);
// PROJECTION
vec3 worldPos = ReconstructWorldPos();
vec3 relPos = worldPos - decal.pos;
vec2 ntx; // range: -1 .. 0 .. +1
ntx.x = dot(relPos.xz, rot[0]) / decal.size.x;
ntx.y = dot(relPos.xz, rot[1]) / decal.size.y;
bool outside = any(greaterThan(abs(ntx), vec2(1.0)));
if (outside) {
// yeah, this branch is worth it and discard too (we neither rely on early-z/stencil, so it doesn't matter)
discard;
}
ntx = (ntx + 1.0) * 0.5; // range: 0..+1
vec2 tx = mix(decal.texcoords.st, decal.texcoords.pq, ntx);
// TEXTURING
vec4 albedo = texture2D(decalTex, tx);
albedo.a *= 1.0 - abs(relPos.y) / decal.size.x; // make transparent when terrain is higher or lower than the decal's pos
albedo.a *= decal.alpha;
vec3 diffuseTerm = GetDiffuseLighting(worldPos, ntx);
float shadowInt = GetShadowOcclusion(worldPos);
#ifdef HAVE_INFOTEX
diffuseTerm.rgb += texture2D(infoTex, worldPos.xz * invMapSizePO2).rgb;
diffuseTerm.rgb -= vec3(0.5, 0.5, 0.5);
#endif
vec3 lightCol = groundLighting.ambientColor + diffuseTerm * shadowInt;
gl_FragColor.rgb = albedo.rgb * lightCol;
gl_FragColor.a = albedo.a;
// FOG
float fogFactor = (groundLighting.fogEnd - length(worldPos - camPos)) * groundLighting.fogScale;
fogFactor = clamp(fogFactor, 0.0, 1.0);
gl_FragColor.rgb = mix(groundLighting.fogColor, gl_FragColor.rgb, fogFactor);
}
|