View difference between Paste ID: LK5CNJPD and Ssu9EDUm
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
}