File: DecalsFragGL4.glsl

package info (click to toggle)
spring 98.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 41,928 kB
  • ctags: 60,665
  • sloc: cpp: 356,167; ansic: 39,434; python: 12,228; java: 12,203; awk: 5,856; sh: 1,719; xml: 997; perl: 405; php: 253; objc: 194; makefile: 72; sed: 2
file content (141 lines) | stat: -rw-r--r-- 4,185 bytes parent folder | download
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);
}