SHOW:
|
|
- or go back to the newest paste.
1 | /** | |
2 | * @file terrain.vert | |
3 | * @brief A Vertex shader for a geo-mipmapped terrain. | |
4 | * It is called for a flat plane, it gets offseted in the Y direction | |
5 | * by a height value, that is fetched from a texture. The normals of | |
6 | * the terrain is approximated here, from the gradient. Characters (up to 4) | |
7 | * cast shadow on the terrain, with shadow mapping. | |
8 | */ | |
9 | #version 330 core | |
10 | ||
11 | // Actually this number might be modified in the C++ | |
12 | // program's runtime, but before shader compilation. | |
13 | #define SHADOW_MAP_NUM 4 | |
14 | ||
15 | layout(location = 0) in ivec2 vPosition; | |
16 | ||
17 | uniform mat4 uProjectionMatrix, uCameraMatrix; | |
18 | uniform ivec2 uOffset; | |
19 | uniform vec3 uScales; | |
20 | uniform sampler2D uHeightMap; | |
21 | uniform int uMipmapLevel; | |
22 | ||
23 | uniform mat4 uShadowCP[SHADOW_MAP_NUM]; | |
24 | uniform int uNumUsedShadowMaps; | |
25 | ||
26 | out VertexData { | |
27 | vec3 w_normal; | |
28 | vec3 c_pos, w_pos; | |
29 | vec2 texcoord; | |
30 | vec4 shadowCoord[SHADOW_MAP_NUM]; | |
31 | float scInvalid[SHADOW_MAP_NUM]; | |
32 | float invalid; | |
33 | mat3 NormalMatrix; | |
34 | } vout; | |
35 | ||
36 | ||
37 | float fetchHeight(ivec2 texCoord) { | |
38 | return texelFetch(uHeightMap, texCoord, 0).r * 255; | |
39 | } | |
40 | ||
41 | void main() { | |
42 | vec2 w_offsPos = (vPosition + uOffset) / 2.0; | |
43 | ||
44 | ivec2 tex_size = textureSize(uHeightMap, 0); | |
45 | - | if(abs(int(w_offsPos.x)) - 1 >= tex_size.x / 2 || abs(int(w_offsPos.y)) - 1 >= tex_size.x / 2) { |
45 | + | if(abs(int(w_offsPos.x)) - 1 >= tex_size.x / 2 || abs(int(w_offsPos.y)) - 1 >= tex_size.y / 2) { |
46 | vout.invalid = 1e10; | |
47 | gl_Position = vec4(0.0); | |
48 | return; | |
49 | } else { | |
50 | vout.invalid = 0.0; | |
51 | } | |
52 | ||
53 | ivec2 iTexcoord = ivec2(w_offsPos) + tex_size / 2; | |
54 | vout.texcoord = iTexcoord / vec2(tex_size); | |
55 | ||
56 | float height = fetchHeight(iTexcoord); | |
57 | vout.w_pos = uScales * vec3(w_offsPos.x, height, w_offsPos.y); | |
58 | vout.c_pos = (uCameraMatrix * vec4(vout.w_pos, 1.0)).xyz; | |
59 | vec4 w_pos = vec4(vout.w_pos, 1.0); | |
60 | ||
61 | // The performance drop is because of this loop. | |
62 | - | for(int i = 0; i < max(uNumUsedShadowMaps, SHADOW_MAP_NUM); ++i) { |
62 | + | for(int i = 0; i < min(uNumUsedShadowMaps, SHADOW_MAP_NUM); ++i) { |
63 | vec4 sc = uShadowCP[i] * w_pos; | |
64 | vout.shadowCoord[i] = sc; | |
65 | if(sc.w == 0) { | |
66 | vout.scInvalid[i] = 1e10; | |
67 | } else { | |
68 | sc.xyz /= sc.w; | |
69 | if(abs(sc.x) > 1.0 || abs(sc.y) > 1.0 || abs(sc.z) > 1.0) { | |
70 | vout.scInvalid[i] = 1e10; | |
71 | } else { | |
72 | vout.scInvalid[i] = 0.0; | |
73 | } | |
74 | } | |
75 | } | |
76 | ||
77 | // -------======{[ Normals ]}======------- | |
78 | ||
79 | const ivec2 iNeighbours[6] = ivec2[6]( | |
80 | ivec2(1, 2), ivec2(2, 0), ivec2(1, -2), | |
81 | ivec2(-1, -2), ivec2(-2, 0), ivec2(-1, 2) | |
82 | ); | |
83 | ||
84 | vec3 neighbours[6]; | |
85 | for(int i = 0; i < 6; i++) { | |
86 | ivec2 nPos = (vPosition + uOffset + ((1 << (uMipmapLevel + 1)) * iNeighbours[i])) / 2; | |
87 | ivec2 nTexcoord = nPos + tex_size / 2; | |
88 | neighbours[i] = uScales * vec3(nPos.x, fetchHeight(nTexcoord), nPos.y) - vout.w_pos; | |
89 | } | |
90 | ||
91 | vec3 temp_normal = vec3(0.0); | |
92 | for(int i = 0; i < 6; i++) { | |
93 | temp_normal += normalize(cross(neighbours[i], neighbours[(i+1) % 6])); | |
94 | } | |
95 | ||
96 | vout.w_normal = normalize(temp_normal); | |
97 | ||
98 | vout.NormalMatrix[0] = cross(vec3(0.0, 0.0, 1.0), vout.w_normal); // tangent - approximately (1, 0, 0) | |
99 | vout.NormalMatrix[1] = cross(vout.w_normal, vout.NormalMatrix[0]); // bitangent - approximately (0, 0, 1) | |
100 | vout.NormalMatrix[2] = vout.w_normal; // normal - approximately (0, 1, 0) | |
101 | ||
102 | gl_Position = uProjectionMatrix * vec4(vout.c_pos, 1.0); | |
103 | } |