Improved parallax mapping. Generate heightmaps on the fly.
authorRealBadAngel <maciej.kasatkin@o2.pl>
Sun, 14 Jun 2015 19:13:36 +0000 (21:13 +0200)
committerRealBadAngel <maciej.kasatkin@o2.pl>
Sun, 14 Jun 2015 19:13:36 +0000 (21:13 +0200)
client/shaders/nodes_shader/opengl_fragment.glsl
client/shaders/nodes_shader/opengl_vertex.glsl
client/shaders/water_surface_shader/opengl_fragment.glsl
client/shaders/water_surface_shader/opengl_vertex.glsl
minetest.conf.example
src/clientmap.cpp
src/defaultsettings.cpp
src/mapblock_mesh.cpp
src/mapblock_mesh.h
src/mesh.cpp
src/shader.cpp

index 6dc96eb48c1760a345f7f14f10d7925a3873d2db..066e49658aba2ad68244a2e22ca19df74673ca29 100644 (file)
@@ -8,6 +8,7 @@ uniform vec3 eyePosition;
 
 varying vec3 vPosition;
 varying vec3 worldPosition;
+varying float generate_heightmaps;
 
 varying vec3 eyeVec;
 varying vec3 tsEyeVec;
@@ -19,80 +20,135 @@ bool normalTexturePresent = false;
 const float e = 2.718281828459;
 const float BS = 10.0;
  
-float intensity (vec3 color){
+float intensity (vec3 color)
+{
        return (color.r + color.g + color.b) / 3.0;
 }
 
-float get_rgb_height (vec2 uv){
+float get_rgb_height (vec2 uv)
+{
        return intensity(texture2D(baseTexture,uv).rgb);
 }
 
-vec4 get_normal_map(vec2 uv){
+vec4 get_normal_map(vec2 uv)
+{
        vec4 bump = texture2D(normalTexture, uv).rgba;
-       bump.xyz = normalize(bump.xyz * 2.0 -1.0);
-       bump.y = -bump.y;
+       bump.xyz = normalize(bump.xyz * 2.0 - 1.0);
        return bump;
 }
 
+float find_intersection(vec2 dp, vec2 ds)
+{
+       const int linear_steps = 10;
+       const int binary_steps = 5;
+       const float depth_step = 1.0 / linear_steps;
+       float size = depth_step;
+       float depth = 1.0;
+       float best_depth = 1.0;
+       for (int i = 0 ; i < linear_steps - 1 ; ++i) {
+               vec4 t = texture2D(normalTexture, dp + ds * depth);
+               if (best_depth > 0.05)
+                       if (depth >= t.a)
+                               best_depth = depth;
+               depth -= size;
+       }
+       depth = best_depth - size;
+       for (int i = 0 ; i < binary_steps ; ++i) {
+               size *= 0.5;
+               vec4 t = texture2D(normalTexture, dp + ds * depth);
+               if (depth >= t.a) {
+                       best_depth = depth;
+                       depth -= 2 * size;
+               }
+               depth += size;
+       }
+       return best_depth;
+}
+
+float find_intersectionRGB(vec2 dp, vec2 ds) {
+       const float iterations = 24;
+       const float depth_step = 1.0 / iterations;
+       float depth = 1.0;
+       for (int i = 0 ; i < iterations ; i++) {
+               float h = get_rgb_height(dp + ds * depth);
+               if (h >= depth)
+                       break;
+               depth -= depth_step;
+       }
+       return depth;
+}
+
 void main (void)
 {
        vec3 color;
        vec4 bump;
        vec2 uv = gl_TexCoord[0].st;
        bool use_normalmap = false;
-       
+
 #ifdef USE_NORMALMAPS
-       if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
+       if (texture2D(useNormalmap,vec2(1.0, 1.0)).r > 0.0) {
                normalTexturePresent = true;
        }
 #endif
 
 #ifdef ENABLE_PARALLAX_OCCLUSION
-       if (normalTexturePresent){
-               vec3 tsEye = normalize(tsEyeVec);
-               float height = PARALLAX_OCCLUSION_SCALE * texture2D(normalTexture, uv).a - PARALLAX_OCCLUSION_BIAS;
-               uv = uv + texture2D(normalTexture, uv).z * height * vec2(tsEye.x,-tsEye.y);
+       vec3 eyeRay = normalize(tsEyeVec);
+#if PARALLAX_OCCLUSION_MODE == 0
+       // Parallax occlusion with slope information
+       if (normalTexturePresent) {
+               const float scale = PARALLAX_OCCLUSION_SCALE / PARALLAX_OCCLUSION_ITERATIONS;
+               const float bias = PARALLAX_OCCLUSION_BIAS / PARALLAX_OCCLUSION_ITERATIONS;
+               for(int i = 0; i < PARALLAX_OCCLUSION_ITERATIONS; i++) {
+                       vec4 normal = texture2D(normalTexture, uv.xy);
+                       float h = normal.a * scale - bias;
+                       uv += h * normal.z * eyeRay.xy;
+               }
+#endif
+#if PARALLAX_OCCLUSION_MODE == 1
+       // Relief mapping
+       if (normalTexturePresent) {
+               vec2 ds = eyeRay.xy * PARALLAX_OCCLUSION_SCALE;
+               float dist = find_intersection(uv, ds);
+               uv += dist * ds;
+#endif
+       } else if (generate_heightmaps > 0.0) {
+               vec2 ds = eyeRay.xy * PARALLAX_OCCLUSION_SCALE;
+               float dist = find_intersectionRGB(uv, ds);
+               uv += dist * ds;
        }
 #endif
 
 #ifdef USE_NORMALMAPS
-       if (normalTexturePresent){
+       if (normalTexturePresent) {
                bump = get_normal_map(uv);
                use_normalmap = true;
        } 
 #endif
-               
-#ifdef GENERATE_NORMALMAPS
-       if (use_normalmap == false){
-               float tl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y+SAMPLE_STEP));
-               float t  = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
-               float tr = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y+SAMPLE_STEP));
-               float r  = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y));
-               float br = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y-SAMPLE_STEP));
-               float b  = get_rgb_height (vec2(uv.x,uv.y-SAMPLE_STEP));
-               float bl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
-               float l  = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y));
+
+       if (GENERATE_NORMALMAPS == 1 && use_normalmap == false) {
+               float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP));
+               float t  = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP));
+               float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP));
+               float r  = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y));
+               float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP));
+               float b  = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP));
+               float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP));
+               float l  = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y));
                float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
                float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
-               bump = vec4 (normalize(vec3 (dX, -dY, NORMALMAPS_STRENGTH)),1.0);
+               bump = vec4(normalize(vec3 (-dX, -dY, NORMALMAPS_STRENGTH)), 1.0);
                use_normalmap = true;
        }
-#endif
 
-vec4 base = texture2D(baseTexture, uv).rgba;
-       
+       vec4 base = texture2D(baseTexture, uv).rgba;
+
 #ifdef ENABLE_BUMPMAPPING
-       if (use_normalmap){
+       if (use_normalmap) {
                vec3 L = normalize(lightVec);
-               vec3 E = normalize(eyeVec);
-               float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5); 
-               float diffuse = dot(E,bump.xyz);                
-               /* Mathematic optimization
-               * Original: color = 0.05*base.rgb + diffuse*base.rgb + 0.2*specular*base.rgb;
-               * This optimization save 2 multiplications (orig: 4 multiplications + 3 additions
-               * end: 2 multiplications + 3 additions)
-               */
-               color = (0.05 + diffuse + 0.2 * specular) * base.rgb;
+               vec3 E = normalize(-eyeVec);
+               float specular = pow(clamp(dot(reflect(L, bump.xyz), -E), 0.0, 1.0), 1.0);
+               float diffuse = dot(E,bump.xyz);
+               color = (diffuse + 0.1 * specular) * base.rgb;
        } else {
                color = base.rgb;
        }
@@ -104,7 +160,7 @@ vec4 base = texture2D(baseTexture, uv).rgba;
        float alpha = gl_Color.a;
        vec4 col = vec4(color.rgb, alpha);
        col *= gl_Color;
-       if(fogDistance != 0.0){
+       if (fogDistance != 0.0) {
                float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
                alpha = mix(alpha, 0.0, d);
        }
@@ -112,7 +168,7 @@ vec4 base = texture2D(baseTexture, uv).rgba;
 #else
        vec4 col = vec4(color.rgb, base.a);
        col *= gl_Color;
-       if(fogDistance != 0.0){
+       if (fogDistance != 0.0) {
                float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
                col = mix(col, skyBgColor, d);
        }
index 07684f6169f1479f7b95f4e6c141ca97fbeccf29..e5644b8b232cc1e02fb3980ebd1249156da96cf4 100644 (file)
@@ -14,25 +14,36 @@ varying vec3 eyeVec;
 varying vec3 lightVec;\r
 varying vec3 tsEyeVec;\r
 varying vec3 tsLightVec;\r
+varying float generate_heightmaps;\r
 \r
 const float e = 2.718281828459;\r
 const float BS = 10.0;\r
 \r
-float smoothCurve( float x ) {\r
-  return x * x *( 3.0 - 2.0 * x );\r
+float smoothCurve(float x)\r
+{\r
+       return x * x * (3.0 - 2.0 * x);\r
 }\r
-float triangleWave( float x ) {\r
-  return abs( fract( x + 0.5 ) * 2.0 - 1.0 );\r
+float triangleWave(float x)\r
+{\r
+       return abs(fract(x + 0.5) * 2.0 - 1.0);\r
 }\r
-float smoothTriangleWave( float x ) {\r
-  return smoothCurve( triangleWave( x ) ) * 2.0 - 1.0;\r
+float smoothTriangleWave(float x)\r
+{\r
+       return smoothCurve(triangleWave(x)) * 2.0 - 1.0;\r
 }\r
 \r
 void main(void)\r
 {\r
        gl_TexCoord[0] = gl_MultiTexCoord0;\r
-       \r
-#if (MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE) && ENABLE_WAVING_WATER\r
+       gl_TexCoord[0].y += 0.008;\r
+\r
+#if ((DRAW_TYPE == NDT_NORMAL || DRAW_TYPE == NDT_LIQUID || DRAW_TYPE == NDT_FLOWINGLIQUID) && GENERATE_NORMALMAPS)\r
+       generate_heightmaps = 1.0;\r
+#else \r
+       generate_heightmaps = 0.0;\r
+#endif\r
+\r
+#if ((MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE) && ENABLE_WAVING_WATER)\r
        vec4 pos = gl_Vertex;\r
        pos.y -= 2.0;\r
 \r
@@ -76,43 +87,33 @@ void main(void)
 \r
        vPosition = gl_Position.xyz;\r
        worldPosition = (mWorld * gl_Vertex).xyz;\r
+\r
+       // Don't generate heightmaps when too far from the eye\r
+       float dist = distance (worldPosition, eyePosition);\r
+       if (dist > 100.00) {\r
+               generate_heightmaps = 0.0;\r
+       }\r
+\r
        vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);\r
 \r
        vec3 normal, tangent, binormal;\r
        normal = normalize(gl_NormalMatrix * gl_Normal);\r
-       if (gl_Normal.x > 0.5) {\r
-               //  1.0,  0.0,  0.0\r
-               tangent  = normalize(gl_NormalMatrix * vec3( 0.0,  0.0, -1.0));\r
-               binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0,  0.0));\r
-       } else if (gl_Normal.x < -0.5) {\r
-               // -1.0,  0.0,  0.0\r
-               tangent  = normalize(gl_NormalMatrix * vec3( 0.0,  0.0,  1.0));\r
-               binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0,  0.0));\r
-       } else if (gl_Normal.y > 0.5) {\r
-               //  0.0,  1.0,  0.0\r
-               tangent  = normalize(gl_NormalMatrix * vec3( 1.0,  0.0,  0.0));\r
-               binormal = normalize(gl_NormalMatrix * vec3( 0.0,  0.0,  1.0));\r
-       } else if (gl_Normal.y < -0.5) {\r
-               //  0.0, -1.0,  0.0\r
-               tangent  = normalize(gl_NormalMatrix * vec3( 1.0,  0.0,  0.0));\r
-               binormal = normalize(gl_NormalMatrix * vec3( 0.0,  0.0,  1.0));\r
-       } else if (gl_Normal.z > 0.5) {\r
-               //  0.0,  0.0,  1.0\r
-               tangent  = normalize(gl_NormalMatrix * vec3( 1.0,  0.0,  0.0));\r
-               binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0,  0.0));\r
-       } else if (gl_Normal.z < -0.5) {\r
-               //  0.0,  0.0, -1.0\r
-               tangent  = normalize(gl_NormalMatrix * vec3(-1.0,  0.0,  0.0));\r
-               binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0,  0.0));\r
-       }\r
-       mat3 tbnMatrix = mat3(  tangent.x, binormal.x, normal.x,\r
-                                                       tangent.y, binormal.y, normal.y,\r
-                                                       tangent.z, binormal.z, normal.z);\r
+       tangent = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz);\r
+       binormal = normalize(gl_NormalMatrix * -gl_MultiTexCoord2.xyz);\r
+\r
+       vec3 v;\r
 \r
        lightVec = sunPosition - worldPosition;\r
-       tsLightVec = lightVec * tbnMatrix;\r
-       eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;\r
-       tsEyeVec = eyeVec * tbnMatrix;\r
+       v.x = dot(lightVec, tangent);\r
+       v.y = dot(lightVec, binormal);\r
+       v.z = dot(lightVec, normal);\r
+       tsLightVec = v;\r
+\r
+       eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz;\r
+       v.x = dot(eyeVec, tangent);\r
+       v.y = dot(eyeVec, binormal);\r
+       v.z = dot(eyeVec, normal);\r
+       tsEyeVec = v;\r
 \r
        vec4 color;\r
        float day = gl_Color.r;\r
index 6dc96eb48c1760a345f7f14f10d7925a3873d2db..386f7748650381641766cd0e3904e5e4fbad8709 100644 (file)
@@ -14,7 +14,7 @@ varying vec3 tsEyeVec;
 varying vec3 lightVec;
 varying vec3 tsLightVec;
 
-bool normalTexturePresent = false; 
+bool normalTexturePresent = false;
 
 const float e = 2.718281828459;
 const float BS = 10.0;
@@ -40,15 +40,15 @@ void main (void)
        vec4 bump;
        vec2 uv = gl_TexCoord[0].st;
        bool use_normalmap = false;
-       
+
 #ifdef USE_NORMALMAPS
-       if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
+       if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0) {
                normalTexturePresent = true;
        }
 #endif
 
 #ifdef ENABLE_PARALLAX_OCCLUSION
-       if (normalTexturePresent){
+       if (normalTexturePresent) {
                vec3 tsEye = normalize(tsEyeVec);
                float height = PARALLAX_OCCLUSION_SCALE * texture2D(normalTexture, uv).a - PARALLAX_OCCLUSION_BIAS;
                uv = uv + texture2D(normalTexture, uv).z * height * vec2(tsEye.x,-tsEye.y);
@@ -56,14 +56,13 @@ void main (void)
 #endif
 
 #ifdef USE_NORMALMAPS
-       if (normalTexturePresent){
+       if (normalTexturePresent) {
                bump = get_normal_map(uv);
                use_normalmap = true;
        } 
 #endif
-               
-#ifdef GENERATE_NORMALMAPS
-       if (use_normalmap == false){
+
+       if (GENERATE_NORMALMAPS == 1 && use_normalmap == false) {
                float tl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y+SAMPLE_STEP));
                float t  = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
                float tr = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y+SAMPLE_STEP));
@@ -77,16 +76,15 @@ void main (void)
                bump = vec4 (normalize(vec3 (dX, -dY, NORMALMAPS_STRENGTH)),1.0);
                use_normalmap = true;
        }
-#endif
 
 vec4 base = texture2D(baseTexture, uv).rgba;
-       
+
 #ifdef ENABLE_BUMPMAPPING
-       if (use_normalmap){
+       if (use_normalmap) {
                vec3 L = normalize(lightVec);
                vec3 E = normalize(eyeVec);
-               float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5); 
-               float diffuse = dot(E,bump.xyz);                
+               float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5);
+               float diffuse = dot(E,bump.xyz);
                /* Mathematic optimization
                * Original: color = 0.05*base.rgb + diffuse*base.rgb + 0.2*specular*base.rgb;
                * This optimization save 2 multiplications (orig: 4 multiplications + 3 additions
index 6e70bbc361b442b4de608873fe13a4d0ce68aac1..53678800d7c51293081db0af263002f2052b7841 100644 (file)
@@ -18,20 +18,23 @@ varying vec3 tsLightVec;
 const float e = 2.718281828459;\r
 const float BS = 10.0;\r
 \r
-float smoothCurve( float x ) {\r
-  return x * x *( 3.0 - 2.0 * x );\r
+float smoothCurve(float x)\r
+{\r
+       return x * x * (3.0 - 2.0 * x);\r
 }\r
-float triangleWave( float x ) {\r
-  return abs( fract( x + 0.5 ) * 2.0 - 1.0 );\r
+float triangleWave(float x)\r
+{\r
+       return abs(fract( x + 0.5 ) * 2.0 - 1.0);\r
 }\r
-float smoothTriangleWave( float x ) {\r
-  return smoothCurve( triangleWave( x ) ) * 2.0 - 1.0;\r
+float smoothTriangleWave(float x)\r
+{\r
+       return smoothCurve(triangleWave( x )) * 2.0 - 1.0;\r
 }\r
 \r
 void main(void)\r
 {\r
        gl_TexCoord[0] = gl_MultiTexCoord0;\r
-       \r
+\r
 #if (MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE) && ENABLE_WAVING_WATER\r
        vec4 pos = gl_Vertex;\r
        pos.y -= 2.0;\r
index 76f01bcfcb89f8d0c3a2023723edff3df766a271..f73dc3e27f48c163f561d0581bdabc307aab8562 100644 (file)
 #    Set to true to pre-generate all item visuals
 #preload_item_visuals = false
 #    Set to true to enable shaders. Disable them if video_driver = direct3d9/8.
+
 #enable_shaders = true
-#    Set to true to enable textures bumpmapping. Requires shaders enabled.
 #enable_bumpmapping = false
-#    Set to true enables parallax occlusion mapping. Requires shaders enabled.
+#    Set to true to enable textures bumpmapping. Requires shaders enabled.
 #generate_normalmaps = false
 #    Set to true enables on the fly normalmap generation (Emboss effect).
 #    Requires bumpmapping enabled.
 #normalmaps_strength = 0.6
 #    Strength of generated normalmaps
-#normalmaps_smooth = 1
+#normalmaps_smooth = 0
 #    Defines sampling step of texture (0 - 2).
 #    A higher value results in smoother normal maps.
+#parallax_occlusion_mode = 1
+#    0 = parallax occlusion with slope information (faster)
+#    1 = relief mapping (slower, more accurate)
 #enable_parallax_occlusion = false
-#    Scale of parallax occlusion effect
+#    Set to true enables parallax occlusion mapping. Requires shaders enabled.
+#parallax_occlusion_iterations = 4
+#    Number of parallax occlusion iterations
 #parallax_occlusion_scale = 0.08
-#    Bias of parallax occlusion effect, usually scale/2
+#    Overall scale of parallax occlusion effect
 #parallax_occlusion_bias = 0.04
-#    Set to true enables waving water. Requires shaders enabled.
+#    Overall bias of parallax occlusion effect, usually scale/2
 #enable_waving_water = false
+#    Set to true enables waving water. Requires shaders enabled.
 #    Parameters for waving water:
 #water_wave_height = 1.0
 #water_wave_length = 20.0
 #water_wave_speed = 5.0
-#    Set to true enables waving leaves. Requires shaders enabled.
 #enable_waving_leaves = false
-#    Set to true enables waving plants. Requires shaders enabled.
+#    Set to true enables waving leaves. Requires shaders enabled.
 #enable_waving_plants = false
-#    Enables caching of facedir rotated meshes
+#    Set to true enables waving plants. Requires shaders enabled.
 #ambient_occlusion_gamma = 2.2
 #    The strength (darkness) of node ambient-occlusion shading.
 #    Lower is darker, Higher is lighter. The valid range of values for this
 #    setting is 0.25 to 4.0 inclusive. If the value is out of range it will be
 #    set to the nearest valid value.
 #enable_mesh_cache = true
+#    Enables caching of facedir rotated meshes
+
 #    The time in seconds it takes between repeated
 #    right clicks when holding the right mouse button.
 #repeat_rightclick_time = 0.25
index 1a52ac4aba8ab03b7955cda6eef8c3c8b6d9b1ab..288a12135f0836ee7af796d5e858aa7adfa622bf 100644 (file)
@@ -539,7 +539,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
                        MapBlockMesh *mapBlockMesh = block->mesh;
                        assert(mapBlockMesh);
 
-                       scene::SMesh *mesh = mapBlockMesh->getMesh();
+                       scene::IMesh *mesh = mapBlockMesh->getMesh();
                        assert(mesh);
 
                        u32 c = mesh->getMeshBufferCount();
index 0cf1dd7706b590c11d923decb01eaa9326dcc97e..eab81009f35a3beb2e7ff86e0e0d65ea673f2f7a 100644 (file)
@@ -160,8 +160,10 @@ void set_default_settings(Settings *settings)
        settings->setDefault("generate_normalmaps", "false");
        settings->setDefault("normalmaps_strength", "0.6");
        settings->setDefault("normalmaps_smooth", "1");
-       settings->setDefault("parallax_occlusion_scale", "0.06");
-       settings->setDefault("parallax_occlusion_bias", "0.03");
+       settings->setDefault("parallax_occlusion_mode", "1");
+       settings->setDefault("parallax_occlusion_iterations", "4");
+       settings->setDefault("parallax_occlusion_scale", "0.08");
+       settings->setDefault("parallax_occlusion_bias", "0.04");
        settings->setDefault("enable_waving_water", "false");
        settings->setDefault("water_wave_height", "1.0");
        settings->setDefault("water_wave_length", "20.0");
index ab4b63f864aa06beffce28946dd35b2406a0f759..9c755b1026bc2888f783862c9d57345bfdeee9ae 100644 (file)
@@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "shader.h"
 #include "settings.h"
 #include "util/directiontables.h"
+#include <IMeshManipulator.h>
 
 static void applyFacesShading(video::SColor& color, float factor)
 {
@@ -1028,6 +1029,8 @@ static void updateAllFastFaceRows(MeshMakeData *data,
 MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
        m_mesh(new scene::SMesh()),
        m_gamedef(data->m_gamedef),
+       m_tsrc(m_gamedef->getTextureSource()),
+       m_shdrsrc(m_gamedef->getShaderSource()),
        m_animation_force_timer(0), // force initial animation
        m_last_crack(-1),
        m_crack_materials(),
@@ -1110,8 +1113,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
        /*
                Convert MeshCollector to SMesh
        */
-       ITextureSource *tsrc = m_gamedef->tsrc();
-       IShaderSource *shdrsrc = m_gamedef->getShaderSource();
 
        for(u32 i = 0; i < collector.prebuffers.size(); i++)
        {
@@ -1123,13 +1124,13 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
                {
                        // Find the texture name plus ^[crack:N:
                        std::ostringstream os(std::ios::binary);
-                       os<<tsrc->getTextureName(p.tile.texture_id)<<"^[crack";
+                       os<<m_tsrc->getTextureName(p.tile.texture_id)<<"^[crack";
                        if(p.tile.material_flags & MATERIAL_FLAG_CRACK_OVERLAY)
                                os<<"o";  // use ^[cracko
                        os<<":"<<(u32)p.tile.animation_frame_count<<":";
                        m_crack_materials.insert(std::make_pair(i, os.str()));
                        // Replace tile texture with the cracked one
-                       p.tile.texture = tsrc->getTextureForMesh(
+                       p.tile.texture = m_tsrc->getTextureForMesh(
                                        os.str()+"0",
                                        &p.tile.texture_id);
                }
@@ -1158,20 +1159,21 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 
                for(u32 j = 0; j < p.vertices.size(); j++)
                {
+                       video::S3DVertexTangents *vertex = &p.vertices[j];
                        // Note applyFacesShading second parameter is precalculated sqrt
                        // value for speed improvement
                        // Skip it for lightsources and top faces.
-                       video::SColor &vc = p.vertices[j].Color;
+                       video::SColor &vc = vertex->Color;
                        if (!vc.getBlue()) {
-                               if (p.vertices[j].Normal.Y < -0.5) {
+                               if (vertex->Normal.Y < -0.5) {
                                        applyFacesShading (vc, 0.447213);
-                               } else if (p.vertices[j].Normal.X > 0.5) {
+                               } else if (vertex->Normal.X > 0.5) {
                                        applyFacesShading (vc, 0.670820);
-                               } else if (p.vertices[j].Normal.X < -0.5) {
+                               } else if (vertex->Normal.X < -0.5) {
                                        applyFacesShading (vc, 0.670820);
-                               } else if (p.vertices[j].Normal.Z > 0.5) {
+                               } else if (vertex->Normal.Z > 0.5) {
                                        applyFacesShading (vc, 0.836660);
-                               } else if (p.vertices[j].Normal.Z < -0.5) {
+                               } else if (vertex->Normal.Z < -0.5) {
                                        applyFacesShading (vc, 0.836660);
                                }
                        }
@@ -1199,33 +1201,30 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
                        material.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
                } else {
                        if (m_enable_shaders) {
-                               material.MaterialType = shdrsrc->getShaderInfo(p.tile.shader_id).material;
+                               material.MaterialType = m_shdrsrc->getShaderInfo(p.tile.shader_id).material;
                                p.tile.applyMaterialOptionsWithShaders(material);
                                if (p.tile.normal_texture) {
                                        material.setTexture(1, p.tile.normal_texture);
-                                       material.setTexture(2, tsrc->getTextureForMesh("enable_img.png"));
+                                       material.setTexture(2, m_tsrc->getTextureForMesh("enable_img.png"));
                                } else {
-                                       material.setTexture(2, tsrc->getTextureForMesh("disable_img.png"));
+                                       material.setTexture(2, m_tsrc->getTextureForMesh("disable_img.png"));
                                }
                        } else {
                                p.tile.applyMaterialOptions(material);
                        }
                }
-
-               // Create meshbuffer
-               // This is a "Standard MeshBuffer",
-               // it's a typedeffed CMeshBuffer<video::S3DVertex>
-               scene::SMeshBuffer *buf = new scene::SMeshBuffer();
-               // Set material
-               buf->Material = material;
-               // Add to mesh
-               m_mesh->addMeshBuffer(buf);
-               // Mesh grabbed it
-               buf->drop();
-               buf->append(&p.vertices[0], p.vertices.size(),
-                               &p.indices[0], p.indices.size());
-       }
-
+       
+       // Create meshbuffer
+       scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents();
+       // Set material
+       buf->Material = material;
+       // Add to mesh
+       m_mesh->addMeshBuffer(buf);
+       // Mesh grabbed it
+       buf->drop();
+       buf->append(&p.vertices[0], p.vertices.size(),
+               &p.indices[0], p.indices.size());
+}
        m_camera_offset = camera_offset;
 
        /*
@@ -1234,6 +1233,11 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 
        translateMesh(m_mesh, intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS));
 
+       if (m_enable_shaders) {
+               scene::IMeshManipulator* meshmanip = m_gamedef->getSceneManager()->getMeshManipulator();
+               meshmanip->recalculateTangents(m_mesh, true, false, false);
+       }
+
        if(m_mesh)
        {
 #if 0
@@ -1272,7 +1276,6 @@ MapBlockMesh::~MapBlockMesh()
 
 bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_ratio)
 {
-
        if(!m_has_animation)
        {
                m_animation_force_timer = 100000;
@@ -1292,12 +1295,11 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
                        std::string basename = i->second;
 
                        // Create new texture name from original
-                       ITextureSource *tsrc = m_gamedef->getTextureSource();
                        std::ostringstream os;
                        os<<basename<<crack;
                        u32 new_texture_id = 0;
                        video::ITexture *new_texture =
-                               tsrc->getTextureForMesh(os.str(), &new_texture_id);
+                               m_tsrc->getTextureForMesh(os.str(), &new_texture_id);
                        buf->getMaterial().setTexture(0, new_texture);
 
                        // If the current material is also animated,
@@ -1333,16 +1335,15 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
                m_animation_frames[i->first] = frame;
 
                scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first);
-               ITextureSource *tsrc = m_gamedef->getTextureSource();
 
                FrameSpec animation_frame = tile.frames[frame];
                buf->getMaterial().setTexture(0, animation_frame.texture);
                if (m_enable_shaders) {
                        if (animation_frame.normal_texture) {
                                buf->getMaterial().setTexture(1, animation_frame.normal_texture);
-                               buf->getMaterial().setTexture(2, tsrc->getTextureForMesh("enable_img.png"));
+                               buf->getMaterial().setTexture(2, m_tsrc->getTextureForMesh("enable_img.png"));
                        } else {
-                               buf->getMaterial().setTexture(2, tsrc->getTextureForMesh("disable_img.png"));
+                               buf->getMaterial().setTexture(2, m_tsrc->getTextureForMesh("disable_img.png"));
                        }
                }
        }
@@ -1355,16 +1356,14 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
                                i != m_daynight_diffs.end(); i++)
                {
                        scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first);
-                       video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
+                       video::S3DVertexTangents *vertices = (video::S3DVertexTangents *)buf->getVertices();
                        for(std::map<u32, std::pair<u8, u8 > >::iterator
                                        j = i->second.begin();
                                        j != i->second.end(); j++)
                        {
-                               u32 vertexIndex = j->first;
                                u8 day = j->second.first;
                                u8 night = j->second.second;
-                               finalColorBlend(vertices[vertexIndex].Color,
-                                               day, night, daynight_ratio);
+                               finalColorBlend(vertices[j->first].Color, day, night, daynight_ratio);
                        }
                }
                m_last_daynight_ratio = daynight_ratio;
@@ -1388,7 +1387,7 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
                        i != m_highlighted_materials.end(); i++)
                {
                        scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(*i);
-                       video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
+                       video::S3DVertexTangents *vertices = (video::S3DVertexTangents*)buf->getVertices();
                        for (u32 j = 0; j < buf->getVertexCount() ;j++)
                                vertices[j].Color = hc;
                }
@@ -1413,42 +1412,40 @@ void MeshCollector::append(const TileSpec &tile,
                const video::S3DVertex *vertices, u32 numVertices,
                const u16 *indices, u32 numIndices)
 {
-       if(numIndices > 65535)
-       {
+       if (numIndices > 65535) {
                dstream<<"FIXME: MeshCollector::append() called with numIndices="<<numIndices<<" (limit 65535)"<<std::endl;
                return;
        }
 
        PreMeshBuffer *p = NULL;
-       for(u32 i=0; i<prebuffers.size(); i++)
-       {
+       for (u32 i = 0; i < prebuffers.size(); i++) {
                PreMeshBuffer &pp = prebuffers[i];
-               if(pp.tile != tile)
+               if (pp.tile != tile)
                        continue;
-               if(pp.indices.size() + numIndices > 65535)
+               if (pp.indices.size() + numIndices > 65535)
                        continue;
 
                p = &pp;
                break;
        }
 
-       if(p == NULL)
-       {
+       if (p == NULL) {
                PreMeshBuffer pp;
                pp.tile = tile;
                prebuffers.push_back(pp);
-               p = &prebuffers[prebuffers.size()-1];
+               p = &prebuffers[prebuffers.size() - 1];
        }
 
        u32 vertex_count = p->vertices.size();
-       for(u32 i=0; i<numIndices; i++)
-       {
+       for (u32 i = 0; i < numIndices; i++)    {
                u32 j = indices[i] + vertex_count;
                p->indices.push_back(j);
        }
-       for(u32 i=0; i<numVertices; i++)
-       {
-               p->vertices.push_back(vertices[i]);
+
+       for (u32 i = 0; i < numVertices; i++) {
+               video::S3DVertexTangents vert(vertices[i].Pos, vertices[i].Normal,
+                       vertices[i].Color, vertices[i].TCoords);
+               p->vertices.push_back(vert);
        }
 }
 
@@ -1461,15 +1458,13 @@ void MeshCollector::append(const TileSpec &tile,
                const u16 *indices, u32 numIndices,
                v3f pos, video::SColor c)
 {
-       if(numIndices > 65535)
-       {
+       if (numIndices > 65535) {
                dstream<<"FIXME: MeshCollector::append() called with numIndices="<<numIndices<<" (limit 65535)"<<std::endl;
                return;
        }
 
        PreMeshBuffer *p = NULL;
-       for(u32 i=0; i<prebuffers.size(); i++)
-       {
+       for (u32 i = 0; i < prebuffers.size(); i++) {
                PreMeshBuffer &pp = prebuffers[i];
                if(pp.tile != tile)
                        continue;
@@ -1480,25 +1475,22 @@ void MeshCollector::append(const TileSpec &tile,
                break;
        }
 
-       if(p == NULL)
-       {
+       if (p == NULL) {
                PreMeshBuffer pp;
                pp.tile = tile;
                prebuffers.push_back(pp);
-               p = &prebuffers[prebuffers.size()-1];
+               p = &prebuffers[prebuffers.size() - 1];
        }
 
        u32 vertex_count = p->vertices.size();
-       for(u32 i=0; i<numIndices; i++)
-       {
+       for (u32 i = 0; i < numIndices; i++) {
                u32 j = indices[i] + vertex_count;
                p->indices.push_back(j);
        }
-       for(u32 i=0; i<numVertices; i++)
-       {
-               video::S3DVertex vert = vertices[i];
-               vert.Pos += pos;
-               vert.Color = c;         
+
+       for (u32 i = 0; i < numVertices; i++) {
+               video::S3DVertexTangents vert(vertices[i].Pos + pos, vertices[i].Normal,
+                       c, vertices[i].TCoords);
                p->vertices.push_back(vert);
        }
 }
index b334ce46914c4fae321bdb9c5fa962574c63b7e6..72c90c3e5ef75847eda9ec85481d4f18fb8d6170 100644 (file)
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <map>
 
 class IGameDef;
+class IShaderSource;
 
 /*
        Mesh making stuff
@@ -123,6 +124,8 @@ public:
 private:
        scene::SMesh *m_mesh;
        IGameDef *m_gamedef;
+       ITextureSource *m_tsrc;
+       IShaderSource *m_shdrsrc;
 
        bool m_enable_shaders;
        bool m_enable_highlighting;
@@ -165,13 +168,12 @@ struct PreMeshBuffer
 {
        TileSpec tile;
        std::vector<u16> indices;
-       std::vector<video::S3DVertex> vertices;
+       std::vector<video::S3DVertexTangents> vertices;
 };
 
 struct MeshCollector
 {
        std::vector<PreMeshBuffer> prebuffers;
-
        void append(const TileSpec &material,
                        const video::S3DVertex *vertices, u32 numVertices,
                        const u16 *indices, u32 numIndices);
index e021e4c923718d8e16ef4a075e408663e8bdf11b..6c7c6d37bbeda5ce42679436ba1049ee7024db68 100644 (file)
@@ -94,26 +94,25 @@ scene::IAnimatedMesh* createCubeMesh(v3f scale)
 
 void scaleMesh(scene::IMesh *mesh, v3f scale)
 {
-       if(mesh == NULL)
+       if (mesh == NULL)
                return;
 
        core::aabbox3d<f32> bbox;
-       bbox.reset(0,0,0);
+       bbox.reset(0, 0, 0);
 
-       u16 mc = mesh->getMeshBufferCount();
-       for(u16 j=0; j<mc; j++)
-       {
+       u32 mc = mesh->getMeshBufferCount();
+       for (u32 j = 0; j < mc; j++) {
                scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
-               video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
-               u16 vc = buf->getVertexCount();
-               for(u16 i=0; i<vc; i++)
-               {
-                       vertices[i].Pos *= scale;
-               }
+               const u32 stride = getVertexPitchFromType(buf->getVertexType());
+               u32 vertex_count = buf->getVertexCount();
+               u8 *vertices = (u8 *)buf->getVertices();
+               for (u32 i = 0; i < vertex_count; i++) 
+                       ((video::S3DVertex *)(vertices + i * stride))->Pos *= scale;
+
                buf->recalculateBoundingBox();
 
                // calculate total bounding box
-               if(j == 0)
+               if (j == 0)
                        bbox = buf->getBoundingBox();
                else
                        bbox.addInternalBox(buf->getBoundingBox());
@@ -123,26 +122,25 @@ void scaleMesh(scene::IMesh *mesh, v3f scale)
 
 void translateMesh(scene::IMesh *mesh, v3f vec)
 {
-       if(mesh == NULL)
+       if (mesh == NULL)
                return;
 
        core::aabbox3d<f32> bbox;
-       bbox.reset(0,0,0);
+       bbox.reset(0, 0, 0);
 
-       u16 mc = mesh->getMeshBufferCount();
-       for(u16 j=0; j<mc; j++)
-       {
+       u32 mc = mesh->getMeshBufferCount();
+       for (u32 j = 0; j < mc; j++) {
                scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
-               video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
-               u16 vc = buf->getVertexCount();
-               for(u16 i=0; i<vc; i++)
-               {
-                       vertices[i].Pos += vec;
-               }
+               const u32 stride = getVertexPitchFromType(buf->getVertexType());
+               u32 vertex_count = buf->getVertexCount();
+               u8 *vertices = (u8 *)buf->getVertices();
+               for (u32 i = 0; i < vertex_count; i++) 
+                       ((video::S3DVertex *)(vertices + i * stride))->Pos += vec;
+
                buf->recalculateBoundingBox();
 
                // calculate total bounding box
-               if(j == 0)
+               if (j == 0)
                        bbox = buf->getBoundingBox();
                else
                        bbox.addInternalBox(buf->getBoundingBox());
@@ -150,21 +148,20 @@ void translateMesh(scene::IMesh *mesh, v3f vec)
        mesh->setBoundingBox(bbox);
 }
 
+
 void setMeshColor(scene::IMesh *mesh, const video::SColor &color)
 {
-       if(mesh == NULL)
+       if (mesh == NULL)
                return;
-       
-       u16 mc = mesh->getMeshBufferCount();
-       for(u16 j=0; j<mc; j++)
-       {
+
+       u32 mc = mesh->getMeshBufferCount();
+       for (u32 j = 0; j < mc; j++) {
                scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
-               video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
-               u16 vc = buf->getVertexCount();
-               for(u16 i=0; i<vc; i++)
-               {
-                       vertices[i].Color = color;
-               }
+               const u32 stride = getVertexPitchFromType(buf->getVertexType());
+               u32 vertex_count = buf->getVertexCount();
+               u8 *vertices = (u8 *)buf->getVertices();
+               for (u32 i = 0; i < vertex_count; i++) 
+                       ((video::S3DVertex *)(vertices + i * stride))->Color = color;
        }
 }
 
index a467c2ea96dae18568bb2a56fd099ed06a5eabcf..a6d18e1bef374881e8334a9bd127e38475b555df 100644 (file)
@@ -680,42 +680,54 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
        shaders_header += itos(drawtype);
        shaders_header += "\n";
 
-       if (g_settings->getBool("generate_normalmaps")){
-               shaders_header += "#define GENERATE_NORMALMAPS\n";
-               shaders_header += "#define NORMALMAPS_STRENGTH ";
-               shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
-               shaders_header += "\n";
-               float sample_step;
-               int smooth = (int)g_settings->getFloat("normalmaps_smooth");
-               switch (smooth){
-               case 0:
-                       sample_step = 0.0078125; // 1.0 / 128.0
-                       break;
-               case 1:
-                       sample_step = 0.00390625; // 1.0 / 256.0
-                       break;
-               case 2:
-                       sample_step = 0.001953125; // 1.0 / 512.0
-                       break;
-               default:
-                       sample_step = 0.0078125;
-                       break;
-               }
-               shaders_header += "#define SAMPLE_STEP ";
-               shaders_header += ftos(sample_step);
-               shaders_header += "\n";
+       if (g_settings->getBool("generate_normalmaps")) {
+               shaders_header += "#define GENERATE_NORMALMAPS 1\n";
+       } else {
+               shaders_header += "#define GENERATE_NORMALMAPS 0\n";
+       }
+       shaders_header += "#define NORMALMAPS_STRENGTH ";
+       shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
+       shaders_header += "\n";
+       float sample_step;
+       int smooth = (int)g_settings->getFloat("normalmaps_smooth");
+       switch (smooth){
+       case 0:
+               sample_step = 0.0078125; // 1.0 / 128.0
+               break;
+       case 1:
+               sample_step = 0.00390625; // 1.0 / 256.0
+               break;
+       case 2:
+               sample_step = 0.001953125; // 1.0 / 512.0
+               break;
+       default:
+               sample_step = 0.0078125;
+               break;
        }
+       shaders_header += "#define SAMPLE_STEP ";
+       shaders_header += ftos(sample_step);
+       shaders_header += "\n";
 
        if (g_settings->getBool("enable_bumpmapping"))
                shaders_header += "#define ENABLE_BUMPMAPPING\n";
 
        if (g_settings->getBool("enable_parallax_occlusion")){
+               int mode = g_settings->getFloat("parallax_occlusion_mode");
+               float scale = g_settings->getFloat("parallax_occlusion_scale");
+               float bias = g_settings->getFloat("parallax_occlusion_bias");
+               int iterations = g_settings->getFloat("parallax_occlusion_iterations");
                shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n";
+               shaders_header += "#define PARALLAX_OCCLUSION_MODE ";
+               shaders_header += itos(mode);
+               shaders_header += "\n";
                shaders_header += "#define PARALLAX_OCCLUSION_SCALE ";
-               shaders_header += ftos(g_settings->getFloat("parallax_occlusion_scale"));
+               shaders_header += ftos(scale);
                shaders_header += "\n";
                shaders_header += "#define PARALLAX_OCCLUSION_BIAS ";
-               shaders_header += ftos(g_settings->getFloat("parallax_occlusion_bias"));
+               shaders_header += ftos(bias);
+               shaders_header += "\n";
+               shaders_header += "#define PARALLAX_OCCLUSION_ITERATIONS ";
+               shaders_header += itos(iterations);
                shaders_header += "\n";
        }
 
@@ -755,7 +767,6 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
                vertex_program = shaders_header + vertex_program;
        if(geometry_program != "")
                geometry_program = shaders_header + geometry_program;
-
        // Call addHighLevelShaderMaterial() or addShaderMaterial()
        const c8* vertex_program_ptr = 0;
        const c8* pixel_program_ptr = 0;