]> git.lizzy.rs Git - dragonfireclient.git/blob - client/shaders/nodes_shader/opengl_fragment.glsl
Speed up and make more accurate relief mapping
[dragonfireclient.git] / client / shaders / nodes_shader / opengl_fragment.glsl
1 uniform sampler2D baseTexture;
2 uniform sampler2D normalTexture;
3 uniform sampler2D textureFlags;
4
5 uniform vec4 skyBgColor;
6 uniform float fogDistance;
7 uniform vec3 eyePosition;
8
9 varying vec3 vPosition;
10 varying vec3 worldPosition;
11 varying float area_enable_parallax;
12
13 varying vec3 eyeVec;
14 varying vec3 tsEyeVec;
15 varying vec3 lightVec;
16 varying vec3 tsLightVec;
17
18 bool normalTexturePresent = false;
19
20 const float e = 2.718281828459;
21 const float BS = 10.0;
22
23 void get_texture_flags()
24 {
25         vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
26         if (flags.r > 0.5) {
27                 normalTexturePresent = true;
28         }
29 }
30
31 float intensity(vec3 color)
32 {
33         return (color.r + color.g + color.b) / 3.0;
34 }
35
36 float get_rgb_height(vec2 uv)
37 {
38         return intensity(texture2D(baseTexture, uv).rgb);
39 }
40
41 vec4 get_normal_map(vec2 uv)
42 {
43         vec4 bump = texture2D(normalTexture, uv).rgba;
44         bump.xyz = normalize(bump.xyz * 2.0 - 1.0);
45         return bump;
46 }
47
48 float find_intersection(vec2 dp, vec2 ds)
49 {
50         float depth = 1.0;
51         float best_depth = 0.0;
52         float size = 0.0625;
53         for (int i = 0; i < 15; i++) {
54                 depth -= size;
55                 float h = texture2D(normalTexture, dp + ds * depth).a;
56                 if (depth <= h) {
57                         best_depth = depth;
58                         break;
59                 }
60         }
61         depth = best_depth;
62         for (int i = 0; i < 4; i++) {
63                 size *= 0.5;
64                 float h = texture2D(normalTexture,dp + ds * depth).a;
65                 if (depth <= h) {
66                         best_depth = depth;
67                         depth += size;
68                 } else {
69                         depth -= size;
70                 }
71         }
72         return best_depth;
73 }
74
75 float find_intersectionRGB(vec2 dp, vec2 ds)
76 {
77         const float depth_step = 1.0 / 24.0;
78         float depth = 1.0;
79         for (int i = 0 ; i < 24 ; i++) {
80                 float h = get_rgb_height(dp + ds * depth);
81                 if (h >= depth)
82                         break;
83                 depth -= depth_step;
84         }
85         return depth;
86 }
87
88 void main(void)
89 {
90         vec3 color;
91         vec4 bump;
92         vec2 uv = gl_TexCoord[0].st;
93         bool use_normalmap = false;
94         get_texture_flags();
95
96 #ifdef ENABLE_PARALLAX_OCCLUSION
97         vec2 eyeRay = vec2 (tsEyeVec.x, -tsEyeVec.y);
98         const float scale = PARALLAX_OCCLUSION_SCALE / PARALLAX_OCCLUSION_ITERATIONS;
99         const float bias = PARALLAX_OCCLUSION_BIAS / PARALLAX_OCCLUSION_ITERATIONS;
100
101 #if PARALLAX_OCCLUSION_MODE == 0
102         // Parallax occlusion with slope information
103         if (normalTexturePresent && area_enable_parallax > 0.0) {
104                 for (int i = 0; i < PARALLAX_OCCLUSION_ITERATIONS; i++) {
105                         vec4 normal = texture2D(normalTexture, uv.xy);
106                         float h = normal.a * scale - bias;
107                         uv += h * normal.z * eyeRay;
108                 }
109 #endif
110
111 #if PARALLAX_OCCLUSION_MODE == 1
112         // Relief mapping
113         if (normalTexturePresent && area_enable_parallax > 0.0) {
114                 vec2 ds = eyeRay * PARALLAX_OCCLUSION_SCALE;
115                 float dist = find_intersection(uv, ds);
116                 uv += dist * ds;
117 #endif
118         } else if (GENERATE_NORMALMAPS == 1 && area_enable_parallax > 0.0) {
119                 vec2 ds = eyeRay * PARALLAX_OCCLUSION_SCALE;
120                 float dist = find_intersectionRGB(uv, ds);
121                 uv += dist * ds;
122         }
123 #endif
124
125 #if USE_NORMALMAPS == 1
126         if (normalTexturePresent) {
127                 bump = get_normal_map(uv);
128                 use_normalmap = true;
129         }
130 #endif
131
132         if (GENERATE_NORMALMAPS == 1 && normalTexturePresent == false) {
133                 float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP));
134                 float t  = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP));
135                 float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP));
136                 float r  = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y));
137                 float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP));
138                 float b  = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP));
139                 float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP));
140                 float l  = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y));
141                 float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
142                 float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
143                 bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0);
144                 use_normalmap = true;
145         }
146
147         vec4 base = texture2D(baseTexture, uv).rgba;
148
149 #ifdef ENABLE_BUMPMAPPING
150         if (use_normalmap) {
151                 vec3 L = normalize(lightVec);
152                 vec3 E = normalize(eyeVec);
153                 float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0), 1.0);
154                 float diffuse = dot(-E,bump.xyz);
155                 color = (diffuse + 0.1 * specular) * base.rgb;
156         } else {
157                 color = base.rgb;
158         }
159 #else
160         color = base.rgb;
161 #endif
162
163 #if MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE
164         float alpha = gl_Color.a;
165         vec4 col = vec4(color.rgb, alpha);
166         col *= gl_Color;
167         if (fogDistance != 0.0) {
168                 float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
169                 alpha = mix(alpha, 0.0, d);
170         }
171         gl_FragColor = vec4(col.rgb, alpha);
172 #else
173         vec4 col = vec4(color.rgb, base.a);
174         col *= gl_Color;
175         if (fogDistance != 0.0) {
176                 float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
177                 col = mix(col, skyBgColor, d);
178         }
179         gl_FragColor = vec4(col.rgb, base.a);
180 #endif
181 }