Skip to content

Commit 43fcfbf

Browse files
committedJun 14, 2015
Improved parallax mapping. Generate heightmaps on the fly.
1 parent d105bf2 commit 43fcfbf

11 files changed

+310
-241
lines changed
 

‎client/shaders/nodes_shader/opengl_fragment.glsl

+95-39
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ uniform vec3 eyePosition;
88

99
varying vec3 vPosition;
1010
varying vec3 worldPosition;
11+
varying float generate_heightmaps;
1112

1213
varying vec3 eyeVec;
1314
varying vec3 tsEyeVec;
@@ -19,80 +20,135 @@ bool normalTexturePresent = false;
1920
const float e = 2.718281828459;
2021
const float BS = 10.0;
2122

22-
float intensity (vec3 color){
23+
float intensity (vec3 color)
24+
{
2325
return (color.r + color.g + color.b) / 3.0;
2426
}
2527

26-
float get_rgb_height (vec2 uv){
28+
float get_rgb_height (vec2 uv)
29+
{
2730
return intensity(texture2D(baseTexture,uv).rgb);
2831
}
2932

30-
vec4 get_normal_map(vec2 uv){
33+
vec4 get_normal_map(vec2 uv)
34+
{
3135
vec4 bump = texture2D(normalTexture, uv).rgba;
32-
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
33-
bump.y = -bump.y;
36+
bump.xyz = normalize(bump.xyz * 2.0 - 1.0);
3437
return bump;
3538
}
3639

40+
float find_intersection(vec2 dp, vec2 ds)
41+
{
42+
const int linear_steps = 10;
43+
const int binary_steps = 5;
44+
const float depth_step = 1.0 / linear_steps;
45+
float size = depth_step;
46+
float depth = 1.0;
47+
float best_depth = 1.0;
48+
for (int i = 0 ; i < linear_steps - 1 ; ++i) {
49+
vec4 t = texture2D(normalTexture, dp + ds * depth);
50+
if (best_depth > 0.05)
51+
if (depth >= t.a)
52+
best_depth = depth;
53+
depth -= size;
54+
}
55+
depth = best_depth - size;
56+
for (int i = 0 ; i < binary_steps ; ++i) {
57+
size *= 0.5;
58+
vec4 t = texture2D(normalTexture, dp + ds * depth);
59+
if (depth >= t.a) {
60+
best_depth = depth;
61+
depth -= 2 * size;
62+
}
63+
depth += size;
64+
}
65+
return best_depth;
66+
}
67+
68+
float find_intersectionRGB(vec2 dp, vec2 ds) {
69+
const float iterations = 24;
70+
const float depth_step = 1.0 / iterations;
71+
float depth = 1.0;
72+
for (int i = 0 ; i < iterations ; i++) {
73+
float h = get_rgb_height(dp + ds * depth);
74+
if (h >= depth)
75+
break;
76+
depth -= depth_step;
77+
}
78+
return depth;
79+
}
80+
3781
void main (void)
3882
{
3983
vec3 color;
4084
vec4 bump;
4185
vec2 uv = gl_TexCoord[0].st;
4286
bool use_normalmap = false;
43-
87+
4488
#ifdef USE_NORMALMAPS
45-
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
89+
if (texture2D(useNormalmap,vec2(1.0, 1.0)).r > 0.0) {
4690
normalTexturePresent = true;
4791
}
4892
#endif
4993

5094
#ifdef ENABLE_PARALLAX_OCCLUSION
51-
if (normalTexturePresent){
52-
vec3 tsEye = normalize(tsEyeVec);
53-
float height = PARALLAX_OCCLUSION_SCALE * texture2D(normalTexture, uv).a - PARALLAX_OCCLUSION_BIAS;
54-
uv = uv + texture2D(normalTexture, uv).z * height * vec2(tsEye.x,-tsEye.y);
95+
vec3 eyeRay = normalize(tsEyeVec);
96+
#if PARALLAX_OCCLUSION_MODE == 0
97+
// Parallax occlusion with slope information
98+
if (normalTexturePresent) {
99+
const float scale = PARALLAX_OCCLUSION_SCALE / PARALLAX_OCCLUSION_ITERATIONS;
100+
const float bias = PARALLAX_OCCLUSION_BIAS / PARALLAX_OCCLUSION_ITERATIONS;
101+
for(int i = 0; i < PARALLAX_OCCLUSION_ITERATIONS; i++) {
102+
vec4 normal = texture2D(normalTexture, uv.xy);
103+
float h = normal.a * scale - bias;
104+
uv += h * normal.z * eyeRay.xy;
105+
}
106+
#endif
107+
#if PARALLAX_OCCLUSION_MODE == 1
108+
// Relief mapping
109+
if (normalTexturePresent) {
110+
vec2 ds = eyeRay.xy * PARALLAX_OCCLUSION_SCALE;
111+
float dist = find_intersection(uv, ds);
112+
uv += dist * ds;
113+
#endif
114+
} else if (generate_heightmaps > 0.0) {
115+
vec2 ds = eyeRay.xy * PARALLAX_OCCLUSION_SCALE;
116+
float dist = find_intersectionRGB(uv, ds);
117+
uv += dist * ds;
55118
}
56119
#endif
57120

58121
#ifdef USE_NORMALMAPS
59-
if (normalTexturePresent){
122+
if (normalTexturePresent) {
60123
bump = get_normal_map(uv);
61124
use_normalmap = true;
62125
}
63126
#endif
64-
65-
#ifdef GENERATE_NORMALMAPS
66-
if (use_normalmap == false){
67-
float tl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y+SAMPLE_STEP));
68-
float t = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
69-
float tr = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y+SAMPLE_STEP));
70-
float r = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y));
71-
float br = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y-SAMPLE_STEP));
72-
float b = get_rgb_height (vec2(uv.x,uv.y-SAMPLE_STEP));
73-
float bl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
74-
float l = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y));
127+
128+
if (GENERATE_NORMALMAPS == 1 && use_normalmap == false) {
129+
float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP));
130+
float t = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP));
131+
float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP));
132+
float r = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y));
133+
float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP));
134+
float b = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP));
135+
float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP));
136+
float l = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y));
75137
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
76138
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
77-
bump = vec4 (normalize(vec3 (dX, -dY, NORMALMAPS_STRENGTH)),1.0);
139+
bump = vec4(normalize(vec3 (-dX, -dY, NORMALMAPS_STRENGTH)), 1.0);
78140
use_normalmap = true;
79141
}
80-
#endif
81142

82-
vec4 base = texture2D(baseTexture, uv).rgba;
83-
143+
vec4 base = texture2D(baseTexture, uv).rgba;
144+
84145
#ifdef ENABLE_BUMPMAPPING
85-
if (use_normalmap){
146+
if (use_normalmap) {
86147
vec3 L = normalize(lightVec);
87-
vec3 E = normalize(eyeVec);
88-
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5);
89-
float diffuse = dot(E,bump.xyz);
90-
/* Mathematic optimization
91-
* Original: color = 0.05*base.rgb + diffuse*base.rgb + 0.2*specular*base.rgb;
92-
* This optimization save 2 multiplications (orig: 4 multiplications + 3 additions
93-
* end: 2 multiplications + 3 additions)
94-
*/
95-
color = (0.05 + diffuse + 0.2 * specular) * base.rgb;
148+
vec3 E = normalize(-eyeVec);
149+
float specular = pow(clamp(dot(reflect(L, bump.xyz), -E), 0.0, 1.0), 1.0);
150+
float diffuse = dot(E,bump.xyz);
151+
color = (diffuse + 0.1 * specular) * base.rgb;
96152
} else {
97153
color = base.rgb;
98154
}
@@ -104,15 +160,15 @@ vec4 base = texture2D(baseTexture, uv).rgba;
104160
float alpha = gl_Color.a;
105161
vec4 col = vec4(color.rgb, alpha);
106162
col *= gl_Color;
107-
if(fogDistance != 0.0){
163+
if (fogDistance != 0.0) {
108164
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
109165
alpha = mix(alpha, 0.0, d);
110166
}
111167
gl_FragColor = vec4(col.rgb, alpha);
112168
#else
113169
vec4 col = vec4(color.rgb, base.a);
114170
col *= gl_Color;
115-
if(fogDistance != 0.0){
171+
if (fogDistance != 0.0) {
116172
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
117173
col = mix(col, skyBgColor, d);
118174
}

‎client/shaders/nodes_shader/opengl_vertex.glsl

+40-39
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,36 @@ varying vec3 eyeVec;
1414
varying vec3 lightVec;
1515
varying vec3 tsEyeVec;
1616
varying vec3 tsLightVec;
17+
varying float generate_heightmaps;
1718

1819
const float e = 2.718281828459;
1920
const float BS = 10.0;
2021

21-
float smoothCurve( float x ) {
22-
return x * x *( 3.0 - 2.0 * x );
22+
float smoothCurve(float x)
23+
{
24+
return x * x * (3.0 - 2.0 * x);
2325
}
24-
float triangleWave( float x ) {
25-
return abs( fract( x + 0.5 ) * 2.0 - 1.0 );
26+
float triangleWave(float x)
27+
{
28+
return abs(fract(x + 0.5) * 2.0 - 1.0);
2629
}
27-
float smoothTriangleWave( float x ) {
28-
return smoothCurve( triangleWave( x ) ) * 2.0 - 1.0;
30+
float smoothTriangleWave(float x)
31+
{
32+
return smoothCurve(triangleWave(x)) * 2.0 - 1.0;
2933
}
3034

3135
void main(void)
3236
{
3337
gl_TexCoord[0] = gl_MultiTexCoord0;
34-
35-
#if (MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE) && ENABLE_WAVING_WATER
38+
gl_TexCoord[0].y += 0.008;
39+
40+
#if ((DRAW_TYPE == NDT_NORMAL || DRAW_TYPE == NDT_LIQUID || DRAW_TYPE == NDT_FLOWINGLIQUID) && GENERATE_NORMALMAPS)
41+
generate_heightmaps = 1.0;
42+
#else
43+
generate_heightmaps = 0.0;
44+
#endif
45+
46+
#if ((MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE) && ENABLE_WAVING_WATER)
3647
vec4 pos = gl_Vertex;
3748
pos.y -= 2.0;
3849

@@ -76,43 +87,33 @@ void main(void)
7687

7788
vPosition = gl_Position.xyz;
7889
worldPosition = (mWorld * gl_Vertex).xyz;
90+
91+
// Don't generate heightmaps when too far from the eye
92+
float dist = distance (worldPosition, eyePosition);
93+
if (dist > 100.00) {
94+
generate_heightmaps = 0.0;
95+
}
96+
7997
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
8098

8199
vec3 normal, tangent, binormal;
82100
normal = normalize(gl_NormalMatrix * gl_Normal);
83-
if (gl_Normal.x > 0.5) {
84-
// 1.0, 0.0, 0.0
85-
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, -1.0));
86-
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
87-
} else if (gl_Normal.x < -0.5) {
88-
// -1.0, 0.0, 0.0
89-
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
90-
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
91-
} else if (gl_Normal.y > 0.5) {
92-
// 0.0, 1.0, 0.0
93-
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
94-
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
95-
} else if (gl_Normal.y < -0.5) {
96-
// 0.0, -1.0, 0.0
97-
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
98-
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
99-
} else if (gl_Normal.z > 0.5) {
100-
// 0.0, 0.0, 1.0
101-
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
102-
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
103-
} else if (gl_Normal.z < -0.5) {
104-
// 0.0, 0.0, -1.0
105-
tangent = normalize(gl_NormalMatrix * vec3(-1.0, 0.0, 0.0));
106-
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
107-
}
108-
mat3 tbnMatrix = mat3( tangent.x, binormal.x, normal.x,
109-
tangent.y, binormal.y, normal.y,
110-
tangent.z, binormal.z, normal.z);
101+
tangent = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz);
102+
binormal = normalize(gl_NormalMatrix * -gl_MultiTexCoord2.xyz);
103+
104+
vec3 v;
111105

112106
lightVec = sunPosition - worldPosition;
113-
tsLightVec = lightVec * tbnMatrix;
114-
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
115-
tsEyeVec = eyeVec * tbnMatrix;
107+
v.x = dot(lightVec, tangent);
108+
v.y = dot(lightVec, binormal);
109+
v.z = dot(lightVec, normal);
110+
tsLightVec = v;
111+
112+
eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz;
113+
v.x = dot(eyeVec, tangent);
114+
v.y = dot(eyeVec, binormal);
115+
v.z = dot(eyeVec, normal);
116+
tsEyeVec = v;
116117

117118
vec4 color;
118119
float day = gl_Color.r;

‎client/shaders/water_surface_shader/opengl_fragment.glsl

+11-13
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ varying vec3 tsEyeVec;
1414
varying vec3 lightVec;
1515
varying vec3 tsLightVec;
1616

17-
bool normalTexturePresent = false;
17+
bool normalTexturePresent = false;
1818

1919
const float e = 2.718281828459;
2020
const float BS = 10.0;
@@ -40,30 +40,29 @@ void main (void)
4040
vec4 bump;
4141
vec2 uv = gl_TexCoord[0].st;
4242
bool use_normalmap = false;
43-
43+
4444
#ifdef USE_NORMALMAPS
45-
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
45+
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0) {
4646
normalTexturePresent = true;
4747
}
4848
#endif
4949

5050
#ifdef ENABLE_PARALLAX_OCCLUSION
51-
if (normalTexturePresent){
51+
if (normalTexturePresent) {
5252
vec3 tsEye = normalize(tsEyeVec);
5353
float height = PARALLAX_OCCLUSION_SCALE * texture2D(normalTexture, uv).a - PARALLAX_OCCLUSION_BIAS;
5454
uv = uv + texture2D(normalTexture, uv).z * height * vec2(tsEye.x,-tsEye.y);
5555
}
5656
#endif
5757

5858
#ifdef USE_NORMALMAPS
59-
if (normalTexturePresent){
59+
if (normalTexturePresent) {
6060
bump = get_normal_map(uv);
6161
use_normalmap = true;
6262
}
6363
#endif
64-
65-
#ifdef GENERATE_NORMALMAPS
66-
if (use_normalmap == false){
64+
65+
if (GENERATE_NORMALMAPS == 1 && use_normalmap == false) {
6766
float tl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y+SAMPLE_STEP));
6867
float t = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
6968
float tr = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y+SAMPLE_STEP));
@@ -77,16 +76,15 @@ void main (void)
7776
bump = vec4 (normalize(vec3 (dX, -dY, NORMALMAPS_STRENGTH)),1.0);
7877
use_normalmap = true;
7978
}
80-
#endif
8179

8280
vec4 base = texture2D(baseTexture, uv).rgba;
83-
81+
8482
#ifdef ENABLE_BUMPMAPPING
85-
if (use_normalmap){
83+
if (use_normalmap) {
8684
vec3 L = normalize(lightVec);
8785
vec3 E = normalize(eyeVec);
88-
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5);
89-
float diffuse = dot(E,bump.xyz);
86+
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5);
87+
float diffuse = dot(E,bump.xyz);
9088
/* Mathematic optimization
9189
* Original: color = 0.05*base.rgb + diffuse*base.rgb + 0.2*specular*base.rgb;
9290
* This optimization save 2 multiplications (orig: 4 multiplications + 3 additions

‎client/shaders/water_surface_shader/opengl_vertex.glsl

+10-7
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,23 @@ varying vec3 tsLightVec;
1818
const float e = 2.718281828459;
1919
const float BS = 10.0;
2020

21-
float smoothCurve( float x ) {
22-
return x * x *( 3.0 - 2.0 * x );
21+
float smoothCurve(float x)
22+
{
23+
return x * x * (3.0 - 2.0 * x);
2324
}
24-
float triangleWave( float x ) {
25-
return abs( fract( x + 0.5 ) * 2.0 - 1.0 );
25+
float triangleWave(float x)
26+
{
27+
return abs(fract( x + 0.5 ) * 2.0 - 1.0);
2628
}
27-
float smoothTriangleWave( float x ) {
28-
return smoothCurve( triangleWave( x ) ) * 2.0 - 1.0;
29+
float smoothTriangleWave(float x)
30+
{
31+
return smoothCurve(triangleWave( x )) * 2.0 - 1.0;
2932
}
3033

3134
void main(void)
3235
{
3336
gl_TexCoord[0] = gl_MultiTexCoord0;
34-
37+
3538
#if (MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE) && ENABLE_WAVING_WATER
3639
vec4 pos = gl_Vertex;
3740
pos.y -= 2.0;

‎minetest.conf.example

+16-9
Original file line numberDiff line numberDiff line change
@@ -225,40 +225,47 @@
225225
# Set to true to pre-generate all item visuals
226226
#preload_item_visuals = false
227227
# Set to true to enable shaders. Disable them if video_driver = direct3d9/8.
228+
228229
#enable_shaders = true
229-
# Set to true to enable textures bumpmapping. Requires shaders enabled.
230230
#enable_bumpmapping = false
231-
# Set to true enables parallax occlusion mapping. Requires shaders enabled.
231+
# Set to true to enable textures bumpmapping. Requires shaders enabled.
232232
#generate_normalmaps = false
233233
# Set to true enables on the fly normalmap generation (Emboss effect).
234234
# Requires bumpmapping enabled.
235235
#normalmaps_strength = 0.6
236236
# Strength of generated normalmaps
237-
#normalmaps_smooth = 1
237+
#normalmaps_smooth = 0
238238
# Defines sampling step of texture (0 - 2).
239239
# A higher value results in smoother normal maps.
240+
#parallax_occlusion_mode = 1
241+
# 0 = parallax occlusion with slope information (faster)
242+
# 1 = relief mapping (slower, more accurate)
240243
#enable_parallax_occlusion = false
241-
# Scale of parallax occlusion effect
244+
# Set to true enables parallax occlusion mapping. Requires shaders enabled.
245+
#parallax_occlusion_iterations = 4
246+
# Number of parallax occlusion iterations
242247
#parallax_occlusion_scale = 0.08
243-
# Bias of parallax occlusion effect, usually scale/2
248+
# Overall scale of parallax occlusion effect
244249
#parallax_occlusion_bias = 0.04
245-
# Set to true enables waving water. Requires shaders enabled.
250+
# Overall bias of parallax occlusion effect, usually scale/2
246251
#enable_waving_water = false
252+
# Set to true enables waving water. Requires shaders enabled.
247253
# Parameters for waving water:
248254
#water_wave_height = 1.0
249255
#water_wave_length = 20.0
250256
#water_wave_speed = 5.0
251-
# Set to true enables waving leaves. Requires shaders enabled.
252257
#enable_waving_leaves = false
253-
# Set to true enables waving plants. Requires shaders enabled.
258+
# Set to true enables waving leaves. Requires shaders enabled.
254259
#enable_waving_plants = false
255-
# Enables caching of facedir rotated meshes
260+
# Set to true enables waving plants. Requires shaders enabled.
256261
#ambient_occlusion_gamma = 2.2
257262
# The strength (darkness) of node ambient-occlusion shading.
258263
# Lower is darker, Higher is lighter. The valid range of values for this
259264
# setting is 0.25 to 4.0 inclusive. If the value is out of range it will be
260265
# set to the nearest valid value.
261266
#enable_mesh_cache = true
267+
# Enables caching of facedir rotated meshes
268+
262269
# The time in seconds it takes between repeated
263270
# right clicks when holding the right mouse button.
264271
#repeat_rightclick_time = 0.25

‎src/clientmap.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
539539
MapBlockMesh *mapBlockMesh = block->mesh;
540540
assert(mapBlockMesh);
541541

542-
scene::SMesh *mesh = mapBlockMesh->getMesh();
542+
scene::IMesh *mesh = mapBlockMesh->getMesh();
543543
assert(mesh);
544544

545545
u32 c = mesh->getMeshBufferCount();

‎src/defaultsettings.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,10 @@ void set_default_settings(Settings *settings)
160160
settings->setDefault("generate_normalmaps", "false");
161161
settings->setDefault("normalmaps_strength", "0.6");
162162
settings->setDefault("normalmaps_smooth", "1");
163-
settings->setDefault("parallax_occlusion_scale", "0.06");
164-
settings->setDefault("parallax_occlusion_bias", "0.03");
163+
settings->setDefault("parallax_occlusion_mode", "1");
164+
settings->setDefault("parallax_occlusion_iterations", "4");
165+
settings->setDefault("parallax_occlusion_scale", "0.08");
166+
settings->setDefault("parallax_occlusion_bias", "0.04");
165167
settings->setDefault("enable_waving_water", "false");
166168
settings->setDefault("water_wave_height", "1.0");
167169
settings->setDefault("water_wave_length", "20.0");

‎src/mapblock_mesh.cpp

+59-67
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3030
#include "shader.h"
3131
#include "settings.h"
3232
#include "util/directiontables.h"
33+
#include <IMeshManipulator.h>
3334

3435
static void applyFacesShading(video::SColor& color, float factor)
3536
{
@@ -1028,6 +1029,8 @@ static void updateAllFastFaceRows(MeshMakeData *data,
10281029
MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
10291030
m_mesh(new scene::SMesh()),
10301031
m_gamedef(data->m_gamedef),
1032+
m_tsrc(m_gamedef->getTextureSource()),
1033+
m_shdrsrc(m_gamedef->getShaderSource()),
10311034
m_animation_force_timer(0), // force initial animation
10321035
m_last_crack(-1),
10331036
m_crack_materials(),
@@ -1110,8 +1113,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
11101113
/*
11111114
Convert MeshCollector to SMesh
11121115
*/
1113-
ITextureSource *tsrc = m_gamedef->tsrc();
1114-
IShaderSource *shdrsrc = m_gamedef->getShaderSource();
11151116

11161117
for(u32 i = 0; i < collector.prebuffers.size(); i++)
11171118
{
@@ -1123,13 +1124,13 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
11231124
{
11241125
// Find the texture name plus ^[crack:N:
11251126
std::ostringstream os(std::ios::binary);
1126-
os<<tsrc->getTextureName(p.tile.texture_id)<<"^[crack";
1127+
os<<m_tsrc->getTextureName(p.tile.texture_id)<<"^[crack";
11271128
if(p.tile.material_flags & MATERIAL_FLAG_CRACK_OVERLAY)
11281129
os<<"o"; // use ^[cracko
11291130
os<<":"<<(u32)p.tile.animation_frame_count<<":";
11301131
m_crack_materials.insert(std::make_pair(i, os.str()));
11311132
// Replace tile texture with the cracked one
1132-
p.tile.texture = tsrc->getTextureForMesh(
1133+
p.tile.texture = m_tsrc->getTextureForMesh(
11331134
os.str()+"0",
11341135
&p.tile.texture_id);
11351136
}
@@ -1158,20 +1159,21 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
11581159

11591160
for(u32 j = 0; j < p.vertices.size(); j++)
11601161
{
1162+
video::S3DVertexTangents *vertex = &p.vertices[j];
11611163
// Note applyFacesShading second parameter is precalculated sqrt
11621164
// value for speed improvement
11631165
// Skip it for lightsources and top faces.
1164-
video::SColor &vc = p.vertices[j].Color;
1166+
video::SColor &vc = vertex->Color;
11651167
if (!vc.getBlue()) {
1166-
if (p.vertices[j].Normal.Y < -0.5) {
1168+
if (vertex->Normal.Y < -0.5) {
11671169
applyFacesShading (vc, 0.447213);
1168-
} else if (p.vertices[j].Normal.X > 0.5) {
1170+
} else if (vertex->Normal.X > 0.5) {
11691171
applyFacesShading (vc, 0.670820);
1170-
} else if (p.vertices[j].Normal.X < -0.5) {
1172+
} else if (vertex->Normal.X < -0.5) {
11711173
applyFacesShading (vc, 0.670820);
1172-
} else if (p.vertices[j].Normal.Z > 0.5) {
1174+
} else if (vertex->Normal.Z > 0.5) {
11731175
applyFacesShading (vc, 0.836660);
1174-
} else if (p.vertices[j].Normal.Z < -0.5) {
1176+
} else if (vertex->Normal.Z < -0.5) {
11751177
applyFacesShading (vc, 0.836660);
11761178
}
11771179
}
@@ -1199,33 +1201,30 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
11991201
material.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
12001202
} else {
12011203
if (m_enable_shaders) {
1202-
material.MaterialType = shdrsrc->getShaderInfo(p.tile.shader_id).material;
1204+
material.MaterialType = m_shdrsrc->getShaderInfo(p.tile.shader_id).material;
12031205
p.tile.applyMaterialOptionsWithShaders(material);
12041206
if (p.tile.normal_texture) {
12051207
material.setTexture(1, p.tile.normal_texture);
1206-
material.setTexture(2, tsrc->getTextureForMesh("enable_img.png"));
1208+
material.setTexture(2, m_tsrc->getTextureForMesh("enable_img.png"));
12071209
} else {
1208-
material.setTexture(2, tsrc->getTextureForMesh("disable_img.png"));
1210+
material.setTexture(2, m_tsrc->getTextureForMesh("disable_img.png"));
12091211
}
12101212
} else {
12111213
p.tile.applyMaterialOptions(material);
12121214
}
12131215
}
1214-
1215-
// Create meshbuffer
1216-
// This is a "Standard MeshBuffer",
1217-
// it's a typedeffed CMeshBuffer<video::S3DVertex>
1218-
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
1219-
// Set material
1220-
buf->Material = material;
1221-
// Add to mesh
1222-
m_mesh->addMeshBuffer(buf);
1223-
// Mesh grabbed it
1224-
buf->drop();
1225-
buf->append(&p.vertices[0], p.vertices.size(),
1226-
&p.indices[0], p.indices.size());
1227-
}
1228-
1216+
1217+
// Create meshbuffer
1218+
scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents();
1219+
// Set material
1220+
buf->Material = material;
1221+
// Add to mesh
1222+
m_mesh->addMeshBuffer(buf);
1223+
// Mesh grabbed it
1224+
buf->drop();
1225+
buf->append(&p.vertices[0], p.vertices.size(),
1226+
&p.indices[0], p.indices.size());
1227+
}
12291228
m_camera_offset = camera_offset;
12301229

12311230
/*
@@ -1234,6 +1233,11 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
12341233

12351234
translateMesh(m_mesh, intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS));
12361235

1236+
if (m_enable_shaders) {
1237+
scene::IMeshManipulator* meshmanip = m_gamedef->getSceneManager()->getMeshManipulator();
1238+
meshmanip->recalculateTangents(m_mesh, true, false, false);
1239+
}
1240+
12371241
if(m_mesh)
12381242
{
12391243
#if 0
@@ -1272,7 +1276,6 @@ MapBlockMesh::~MapBlockMesh()
12721276

12731277
bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_ratio)
12741278
{
1275-
12761279
if(!m_has_animation)
12771280
{
12781281
m_animation_force_timer = 100000;
@@ -1292,12 +1295,11 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
12921295
std::string basename = i->second;
12931296

12941297
// Create new texture name from original
1295-
ITextureSource *tsrc = m_gamedef->getTextureSource();
12961298
std::ostringstream os;
12971299
os<<basename<<crack;
12981300
u32 new_texture_id = 0;
12991301
video::ITexture *new_texture =
1300-
tsrc->getTextureForMesh(os.str(), &new_texture_id);
1302+
m_tsrc->getTextureForMesh(os.str(), &new_texture_id);
13011303
buf->getMaterial().setTexture(0, new_texture);
13021304

13031305
// If the current material is also animated,
@@ -1333,16 +1335,15 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
13331335
m_animation_frames[i->first] = frame;
13341336

13351337
scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first);
1336-
ITextureSource *tsrc = m_gamedef->getTextureSource();
13371338

13381339
FrameSpec animation_frame = tile.frames[frame];
13391340
buf->getMaterial().setTexture(0, animation_frame.texture);
13401341
if (m_enable_shaders) {
13411342
if (animation_frame.normal_texture) {
13421343
buf->getMaterial().setTexture(1, animation_frame.normal_texture);
1343-
buf->getMaterial().setTexture(2, tsrc->getTextureForMesh("enable_img.png"));
1344+
buf->getMaterial().setTexture(2, m_tsrc->getTextureForMesh("enable_img.png"));
13441345
} else {
1345-
buf->getMaterial().setTexture(2, tsrc->getTextureForMesh("disable_img.png"));
1346+
buf->getMaterial().setTexture(2, m_tsrc->getTextureForMesh("disable_img.png"));
13461347
}
13471348
}
13481349
}
@@ -1355,16 +1356,14 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
13551356
i != m_daynight_diffs.end(); i++)
13561357
{
13571358
scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first);
1358-
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
1359+
video::S3DVertexTangents *vertices = (video::S3DVertexTangents *)buf->getVertices();
13591360
for(std::map<u32, std::pair<u8, u8 > >::iterator
13601361
j = i->second.begin();
13611362
j != i->second.end(); j++)
13621363
{
1363-
u32 vertexIndex = j->first;
13641364
u8 day = j->second.first;
13651365
u8 night = j->second.second;
1366-
finalColorBlend(vertices[vertexIndex].Color,
1367-
day, night, daynight_ratio);
1366+
finalColorBlend(vertices[j->first].Color, day, night, daynight_ratio);
13681367
}
13691368
}
13701369
m_last_daynight_ratio = daynight_ratio;
@@ -1388,7 +1387,7 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
13881387
i != m_highlighted_materials.end(); i++)
13891388
{
13901389
scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(*i);
1391-
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
1390+
video::S3DVertexTangents *vertices = (video::S3DVertexTangents*)buf->getVertices();
13921391
for (u32 j = 0; j < buf->getVertexCount() ;j++)
13931392
vertices[j].Color = hc;
13941393
}
@@ -1413,42 +1412,40 @@ void MeshCollector::append(const TileSpec &tile,
14131412
const video::S3DVertex *vertices, u32 numVertices,
14141413
const u16 *indices, u32 numIndices)
14151414
{
1416-
if(numIndices > 65535)
1417-
{
1415+
if (numIndices > 65535) {
14181416
dstream<<"FIXME: MeshCollector::append() called with numIndices="<<numIndices<<" (limit 65535)"<<std::endl;
14191417
return;
14201418
}
14211419

14221420
PreMeshBuffer *p = NULL;
1423-
for(u32 i=0; i<prebuffers.size(); i++)
1424-
{
1421+
for (u32 i = 0; i < prebuffers.size(); i++) {
14251422
PreMeshBuffer &pp = prebuffers[i];
1426-
if(pp.tile != tile)
1423+
if (pp.tile != tile)
14271424
continue;
1428-
if(pp.indices.size() + numIndices > 65535)
1425+
if (pp.indices.size() + numIndices > 65535)
14291426
continue;
14301427

14311428
p = &pp;
14321429
break;
14331430
}
14341431

1435-
if(p == NULL)
1436-
{
1432+
if (p == NULL) {
14371433
PreMeshBuffer pp;
14381434
pp.tile = tile;
14391435
prebuffers.push_back(pp);
1440-
p = &prebuffers[prebuffers.size()-1];
1436+
p = &prebuffers[prebuffers.size() - 1];
14411437
}
14421438

14431439
u32 vertex_count = p->vertices.size();
1444-
for(u32 i=0; i<numIndices; i++)
1445-
{
1440+
for (u32 i = 0; i < numIndices; i++) {
14461441
u32 j = indices[i] + vertex_count;
14471442
p->indices.push_back(j);
14481443
}
1449-
for(u32 i=0; i<numVertices; i++)
1450-
{
1451-
p->vertices.push_back(vertices[i]);
1444+
1445+
for (u32 i = 0; i < numVertices; i++) {
1446+
video::S3DVertexTangents vert(vertices[i].Pos, vertices[i].Normal,
1447+
vertices[i].Color, vertices[i].TCoords);
1448+
p->vertices.push_back(vert);
14521449
}
14531450
}
14541451

@@ -1461,15 +1458,13 @@ void MeshCollector::append(const TileSpec &tile,
14611458
const u16 *indices, u32 numIndices,
14621459
v3f pos, video::SColor c)
14631460
{
1464-
if(numIndices > 65535)
1465-
{
1461+
if (numIndices > 65535) {
14661462
dstream<<"FIXME: MeshCollector::append() called with numIndices="<<numIndices<<" (limit 65535)"<<std::endl;
14671463
return;
14681464
}
14691465

14701466
PreMeshBuffer *p = NULL;
1471-
for(u32 i=0; i<prebuffers.size(); i++)
1472-
{
1467+
for (u32 i = 0; i < prebuffers.size(); i++) {
14731468
PreMeshBuffer &pp = prebuffers[i];
14741469
if(pp.tile != tile)
14751470
continue;
@@ -1480,25 +1475,22 @@ void MeshCollector::append(const TileSpec &tile,
14801475
break;
14811476
}
14821477

1483-
if(p == NULL)
1484-
{
1478+
if (p == NULL) {
14851479
PreMeshBuffer pp;
14861480
pp.tile = tile;
14871481
prebuffers.push_back(pp);
1488-
p = &prebuffers[prebuffers.size()-1];
1482+
p = &prebuffers[prebuffers.size() - 1];
14891483
}
14901484

14911485
u32 vertex_count = p->vertices.size();
1492-
for(u32 i=0; i<numIndices; i++)
1493-
{
1486+
for (u32 i = 0; i < numIndices; i++) {
14941487
u32 j = indices[i] + vertex_count;
14951488
p->indices.push_back(j);
14961489
}
1497-
for(u32 i=0; i<numVertices; i++)
1498-
{
1499-
video::S3DVertex vert = vertices[i];
1500-
vert.Pos += pos;
1501-
vert.Color = c;
1490+
1491+
for (u32 i = 0; i < numVertices; i++) {
1492+
video::S3DVertexTangents vert(vertices[i].Pos + pos, vertices[i].Normal,
1493+
c, vertices[i].TCoords);
15021494
p->vertices.push_back(vert);
15031495
}
15041496
}

‎src/mapblock_mesh.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2626
#include <map>
2727

2828
class IGameDef;
29+
class IShaderSource;
2930

3031
/*
3132
Mesh making stuff
@@ -123,6 +124,8 @@ class MapBlockMesh
123124
private:
124125
scene::SMesh *m_mesh;
125126
IGameDef *m_gamedef;
127+
ITextureSource *m_tsrc;
128+
IShaderSource *m_shdrsrc;
126129

127130
bool m_enable_shaders;
128131
bool m_enable_highlighting;
@@ -165,13 +168,12 @@ struct PreMeshBuffer
165168
{
166169
TileSpec tile;
167170
std::vector<u16> indices;
168-
std::vector<video::S3DVertex> vertices;
171+
std::vector<video::S3DVertexTangents> vertices;
169172
};
170173

171174
struct MeshCollector
172175
{
173176
std::vector<PreMeshBuffer> prebuffers;
174-
175177
void append(const TileSpec &material,
176178
const video::S3DVertex *vertices, u32 numVertices,
177179
const u16 *indices, u32 numIndices);

‎src/mesh.cpp

+32-35
Original file line numberDiff line numberDiff line change
@@ -94,26 +94,25 @@ scene::IAnimatedMesh* createCubeMesh(v3f scale)
9494

9595
void scaleMesh(scene::IMesh *mesh, v3f scale)
9696
{
97-
if(mesh == NULL)
97+
if (mesh == NULL)
9898
return;
9999

100100
core::aabbox3d<f32> bbox;
101-
bbox.reset(0,0,0);
101+
bbox.reset(0, 0, 0);
102102

103-
u16 mc = mesh->getMeshBufferCount();
104-
for(u16 j=0; j<mc; j++)
105-
{
103+
u32 mc = mesh->getMeshBufferCount();
104+
for (u32 j = 0; j < mc; j++) {
106105
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
107-
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
108-
u16 vc = buf->getVertexCount();
109-
for(u16 i=0; i<vc; i++)
110-
{
111-
vertices[i].Pos *= scale;
112-
}
106+
const u32 stride = getVertexPitchFromType(buf->getVertexType());
107+
u32 vertex_count = buf->getVertexCount();
108+
u8 *vertices = (u8 *)buf->getVertices();
109+
for (u32 i = 0; i < vertex_count; i++)
110+
((video::S3DVertex *)(vertices + i * stride))->Pos *= scale;
111+
113112
buf->recalculateBoundingBox();
114113

115114
// calculate total bounding box
116-
if(j == 0)
115+
if (j == 0)
117116
bbox = buf->getBoundingBox();
118117
else
119118
bbox.addInternalBox(buf->getBoundingBox());
@@ -123,48 +122,46 @@ void scaleMesh(scene::IMesh *mesh, v3f scale)
123122

124123
void translateMesh(scene::IMesh *mesh, v3f vec)
125124
{
126-
if(mesh == NULL)
125+
if (mesh == NULL)
127126
return;
128127

129128
core::aabbox3d<f32> bbox;
130-
bbox.reset(0,0,0);
129+
bbox.reset(0, 0, 0);
131130

132-
u16 mc = mesh->getMeshBufferCount();
133-
for(u16 j=0; j<mc; j++)
134-
{
131+
u32 mc = mesh->getMeshBufferCount();
132+
for (u32 j = 0; j < mc; j++) {
135133
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
136-
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
137-
u16 vc = buf->getVertexCount();
138-
for(u16 i=0; i<vc; i++)
139-
{
140-
vertices[i].Pos += vec;
141-
}
134+
const u32 stride = getVertexPitchFromType(buf->getVertexType());
135+
u32 vertex_count = buf->getVertexCount();
136+
u8 *vertices = (u8 *)buf->getVertices();
137+
for (u32 i = 0; i < vertex_count; i++)
138+
((video::S3DVertex *)(vertices + i * stride))->Pos += vec;
139+
142140
buf->recalculateBoundingBox();
143141

144142
// calculate total bounding box
145-
if(j == 0)
143+
if (j == 0)
146144
bbox = buf->getBoundingBox();
147145
else
148146
bbox.addInternalBox(buf->getBoundingBox());
149147
}
150148
mesh->setBoundingBox(bbox);
151149
}
152150

151+
153152
void setMeshColor(scene::IMesh *mesh, const video::SColor &color)
154153
{
155-
if(mesh == NULL)
154+
if (mesh == NULL)
156155
return;
157-
158-
u16 mc = mesh->getMeshBufferCount();
159-
for(u16 j=0; j<mc; j++)
160-
{
156+
157+
u32 mc = mesh->getMeshBufferCount();
158+
for (u32 j = 0; j < mc; j++) {
161159
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
162-
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
163-
u16 vc = buf->getVertexCount();
164-
for(u16 i=0; i<vc; i++)
165-
{
166-
vertices[i].Color = color;
167-
}
160+
const u32 stride = getVertexPitchFromType(buf->getVertexType());
161+
u32 vertex_count = buf->getVertexCount();
162+
u8 *vertices = (u8 *)buf->getVertices();
163+
for (u32 i = 0; i < vertex_count; i++)
164+
((video::S3DVertex *)(vertices + i * stride))->Color = color;
168165
}
169166
}
170167

‎src/shader.cpp

+38-27
Original file line numberDiff line numberDiff line change
@@ -680,42 +680,54 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
680680
shaders_header += itos(drawtype);
681681
shaders_header += "\n";
682682

683-
if (g_settings->getBool("generate_normalmaps")){
684-
shaders_header += "#define GENERATE_NORMALMAPS\n";
685-
shaders_header += "#define NORMALMAPS_STRENGTH ";
686-
shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
687-
shaders_header += "\n";
688-
float sample_step;
689-
int smooth = (int)g_settings->getFloat("normalmaps_smooth");
690-
switch (smooth){
691-
case 0:
692-
sample_step = 0.0078125; // 1.0 / 128.0
693-
break;
694-
case 1:
695-
sample_step = 0.00390625; // 1.0 / 256.0
696-
break;
697-
case 2:
698-
sample_step = 0.001953125; // 1.0 / 512.0
699-
break;
700-
default:
701-
sample_step = 0.0078125;
702-
break;
703-
}
704-
shaders_header += "#define SAMPLE_STEP ";
705-
shaders_header += ftos(sample_step);
706-
shaders_header += "\n";
683+
if (g_settings->getBool("generate_normalmaps")) {
684+
shaders_header += "#define GENERATE_NORMALMAPS 1\n";
685+
} else {
686+
shaders_header += "#define GENERATE_NORMALMAPS 0\n";
687+
}
688+
shaders_header += "#define NORMALMAPS_STRENGTH ";
689+
shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
690+
shaders_header += "\n";
691+
float sample_step;
692+
int smooth = (int)g_settings->getFloat("normalmaps_smooth");
693+
switch (smooth){
694+
case 0:
695+
sample_step = 0.0078125; // 1.0 / 128.0
696+
break;
697+
case 1:
698+
sample_step = 0.00390625; // 1.0 / 256.0
699+
break;
700+
case 2:
701+
sample_step = 0.001953125; // 1.0 / 512.0
702+
break;
703+
default:
704+
sample_step = 0.0078125;
705+
break;
707706
}
707+
shaders_header += "#define SAMPLE_STEP ";
708+
shaders_header += ftos(sample_step);
709+
shaders_header += "\n";
708710

709711
if (g_settings->getBool("enable_bumpmapping"))
710712
shaders_header += "#define ENABLE_BUMPMAPPING\n";
711713

712714
if (g_settings->getBool("enable_parallax_occlusion")){
715+
int mode = g_settings->getFloat("parallax_occlusion_mode");
716+
float scale = g_settings->getFloat("parallax_occlusion_scale");
717+
float bias = g_settings->getFloat("parallax_occlusion_bias");
718+
int iterations = g_settings->getFloat("parallax_occlusion_iterations");
713719
shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n";
720+
shaders_header += "#define PARALLAX_OCCLUSION_MODE ";
721+
shaders_header += itos(mode);
722+
shaders_header += "\n";
714723
shaders_header += "#define PARALLAX_OCCLUSION_SCALE ";
715-
shaders_header += ftos(g_settings->getFloat("parallax_occlusion_scale"));
724+
shaders_header += ftos(scale);
716725
shaders_header += "\n";
717726
shaders_header += "#define PARALLAX_OCCLUSION_BIAS ";
718-
shaders_header += ftos(g_settings->getFloat("parallax_occlusion_bias"));
727+
shaders_header += ftos(bias);
728+
shaders_header += "\n";
729+
shaders_header += "#define PARALLAX_OCCLUSION_ITERATIONS ";
730+
shaders_header += itos(iterations);
719731
shaders_header += "\n";
720732
}
721733

@@ -755,7 +767,6 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
755767
vertex_program = shaders_header + vertex_program;
756768
if(geometry_program != "")
757769
geometry_program = shaders_header + geometry_program;
758-
759770
// Call addHighLevelShaderMaterial() or addShaderMaterial()
760771
const c8* vertex_program_ptr = 0;
761772
const c8* pixel_program_ptr = 0;

2 commit comments

Comments
 (2)

ShadowNinja commented on Jun 15, 2015

@ShadowNinja
Contributor

In minetest.conf.example comments are supposed to be above the settings they document -- same as the C++ and Lua style.

HybridDog commented on Jun 19, 2015

@HybridDog
Contributor

@RealBadAngel l disabled parallax occlusion but the textures are repeating, e.g. at places where they shouldn't:
White stripes on the bottom of dirt with snow:
screenshot_20150619_165308

Please sign in to comment.