cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=1b142d09d951a53e44ce2f1a98b5cc85616756f9

commit 1b142d09d951a53e44ce2f1a98b5cc85616756f9
Author: Dmytro Dadyka <d.dad...@samsung.com>
Date:   Mon Feb 23 14:25:49 2015 +0100

    evas: Evas_3D - add parallax occlusion shading.
    
    Reviewers: Hermet, cedric
    
    Reviewed By: cedric
    
    Subscribers: cedric
    
    Differential Revision: https://phab.enlightenment.org/D2018
---
 src/Makefile_Evas.am                               |   2 +
 src/examples/evas/evas-3d-parallax-occlusion.c     | 276 ++++++++++++++++
 src/examples/evas/four_NM_height.tga               | Bin 0 -> 262188 bytes
 src/examples/evas/rocks.jpg                        | Bin 0 -> 128423 bytes
 src/examples/evas/rocks_NM_height.tga              | Bin 0 -> 262188 bytes
 src/examples/evas/wood.jpg                         | Bin 0 -> 94417 bytes
 src/lib/evas/Evas_Eo.h                             |   2 +
 src/modules/evas/engines/gl_common/evas_gl_3d.c    |   8 +-
 .../gl_common/shader_3d/evas_gl_3d_shaders.x       | 368 ++++++++++++++++++++-
 .../gl_common/shader_3d/normal_map_frag.shd        |   8 +-
 ...al_map_frag.shd => parallax_occlusion_frag.shd} | 122 ++++---
 .../shader_3d/parallax_occlusion_vert.shd          | 151 +++++++++
 12 files changed, 882 insertions(+), 55 deletions(-)

diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am
index d7b62a7..f88560b 100644
--- a/src/Makefile_Evas.am
+++ b/src/Makefile_Evas.am
@@ -747,6 +747,8 @@ 
modules/evas/engines/gl_common/shader_3d/shadow_map_vert.shd \
 modules/evas/engines/gl_common/shader_3d/shadow_map_frag.shd \
 modules/evas/engines/gl_common/shader_3d/color_pick_vert.shd \
 modules/evas/engines/gl_common/shader_3d/color_pick_frag.shd \
+modules/evas/engines/gl_common/shader_3d/parallax_occlusion_vert.shd \
+modules/evas/engines/gl_common/shader_3d/parallax_occlusion_frag.shd \
 $(NULL)
 
 EXTRA_DIST += \
diff --git a/src/examples/evas/evas-3d-parallax-occlusion.c 
b/src/examples/evas/evas-3d-parallax-occlusion.c
new file mode 100644
index 0000000..ca25b1f
--- /dev/null
+++ b/src/examples/evas/evas-3d-parallax-occlusion.c
@@ -0,0 +1,276 @@
+/**
+ * Example illustrating usage of parallax occlusion shading and texture 
animation.
+ *
+ * Press "n" for use normal mapping shading. Pres "p" for use parallax 
occlusion mapping shading.
+ *
+ * @verbatim
+ * gcc -o evas-3d-parallax-occlusion evas-3d-parallax-occlusion.c 
evas-3d-primitives.c `pkg-config --libs --cflags evas ecore ecore-evas eo`-lm
+ * @endverbatim
+ */
+
+#define EFL_EO_API_SUPPORT
+#define EFL_BETA_API_SUPPORT
+
+#include <Eo.h>
+#include <Evas.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include "evas-3d-primitives.h"
+
+#define  WIDTH          400
+#define  HEIGHT         400
+
+typedef struct _Scene_Data
+{
+   Eo *scene;
+   Eo *root_node;
+   Eo *camera_node;
+   Eo *light_node;
+   Eo *mesh_node;
+
+   Eo *camera;
+   Eo *light;
+   Eo *mesh;
+   Eo *material_rocks;
+   Eo *material_wood;
+   Eo *texture_rocks;
+   Eo *texture_rocks_n;
+   Eo *texture_wood;
+   Eo *texture_four_n;
+} Scene_Data;
+
+static Ecore_Evas *ecore_evas = NULL;
+static Evas *evas = NULL;
+static Eo *background = NULL;
+static Eo *image = NULL;
+
+static void
+_on_key_down(void *data, Evas *e EINA_UNUSED, Evas_Object *eo EINA_UNUSED, 
void *event_info)
+{
+   Scene_Data *scene = (Scene_Data *)data;
+   Evas_Event_Key_Down *ev = event_info;
+
+   if (!strcmp("n", ev->key))
+     eo_do(scene->mesh, 
evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_NORMAL_MAP));
+
+   if (!strcmp("p", ev->key))
+     eo_do(scene->mesh, 
evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_PARALLAX_OCCLUSION));
+}
+
+static void
+_on_delete(Ecore_Evas *ee EINA_UNUSED)
+{
+   ecore_main_loop_quit();
+}
+
+static void
+_on_canvas_resize(Ecore_Evas *ee)
+{
+   int w, h;
+
+   ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+   eo_do(background, evas_obj_size_set(w, h));
+   eo_do(image, evas_obj_size_set(w, h));
+}
+
+static Eina_Bool
+_animate_scene(void *data)
+{
+   static float angle = 0.0f;
+   Scene_Data *scene = (Scene_Data *)data;
+
+   angle += 0.5;
+
+   eo_do(scene->mesh_node,
+         evas_3d_node_orientation_angle_axis_set(angle, 0.0, 1.0, 0.0));
+
+   eo_do(scene->mesh_node, evas_3d_node_mesh_frame_set(scene->mesh, 50 * (1 + 
sin(angle / 180.0 * M_PI))));
+   /* Rotate */
+   if (angle > 360.0) angle = 0.0f;
+
+   return EINA_TRUE;
+}
+
+static void
+_camera_setup(Scene_Data *data)
+{
+   data->camera = eo_add(EVAS_3D_CAMERA_CLASS, evas);
+
+   eo_do(data->camera,
+         evas_3d_camera_projection_perspective_set(60.0, 1.0, 2.0, 50.0));
+
+   data->camera_node = eo_add(EVAS_3D_NODE_CLASS, evas,
+                              
evas_3d_node_constructor(EVAS_3D_NODE_TYPE_CAMERA));
+   eo_do(data->camera_node,
+         evas_3d_node_camera_set(data->camera),
+         evas_3d_node_position_set(0.0, 0.0, 10.0),
+         evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 0.0,
+                                  EVAS_3D_SPACE_PARENT, 0.0, 1.0, 0.0));
+   eo_do(data->root_node, evas_3d_node_member_add(data->camera_node));
+}
+
+static void
+_light_setup(Scene_Data *data)
+{
+   data->light = eo_add(EVAS_3D_LIGHT_CLASS, evas);
+   eo_do(data->light,
+         evas_3d_light_ambient_set(0.2, 0.2, 0.2, 1.0),
+         evas_3d_light_diffuse_set(1.0, 1.0, 1.0, 1.0),
+         evas_3d_light_specular_set(1.0, 1.0, 1.0, 1.0));
+
+   data->light_node = eo_add(EVAS_3D_NODE_CLASS, evas,
+                             
evas_3d_node_constructor(EVAS_3D_NODE_TYPE_LIGHT));
+   eo_do(data->light_node,
+         evas_3d_node_light_set(data->light),
+         evas_3d_node_position_set(-20.0, 20.0, 50.0),
+         evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 0.0,
+                                  EVAS_3D_SPACE_PARENT, 0.0, 1.0, 0.0));
+   eo_do(data->root_node, evas_3d_node_member_add(data->light_node));
+}
+
+static void
+_mesh_setup(Scene_Data *data)
+{
+   /* Setup material. */
+   data->material_rocks = eo_add(EVAS_3D_MATERIAL_CLASS, evas);
+
+   data->texture_rocks = eo_add(EVAS_3D_TEXTURE_CLASS, evas);
+   data->texture_rocks_n = eo_add(EVAS_3D_TEXTURE_CLASS, evas);
+   eo_do(data->texture_rocks, evas_3d_texture_file_set("rocks.jpg", NULL),
+         evas_3d_texture_wrap_set(EVAS_3D_WRAP_MODE_REPEAT,
+                                  EVAS_3D_WRAP_MODE_REPEAT));
+   eo_do(data->texture_rocks_n, 
evas_3d_texture_file_set("rocks_NM_height.tga", NULL),
+         evas_3d_texture_wrap_set(EVAS_3D_WRAP_MODE_REPEAT,
+                                  EVAS_3D_WRAP_MODE_REPEAT));
+
+   eo_do(data->material_rocks,
+         evas_3d_material_texture_set(EVAS_3D_MATERIAL_NORMAL, 
data->texture_rocks_n),
+         evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, 
data->texture_rocks),
+         evas_3d_material_texture_set(EVAS_3D_MATERIAL_AMBIENT, 
data->texture_rocks),
+         evas_3d_material_texture_set(EVAS_3D_MATERIAL_SPECULAR, 
data->texture_rocks),
+         evas_3d_material_enable_set(EVAS_3D_MATERIAL_AMBIENT, EINA_TRUE),
+         evas_3d_material_enable_set(EVAS_3D_MATERIAL_NORMAL, EINA_TRUE),
+         evas_3d_material_enable_set(EVAS_3D_MATERIAL_DIFFUSE, EINA_TRUE),
+         evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE),
+
+         evas_3d_material_color_set(EVAS_3D_MATERIAL_AMBIENT, 0.1, 0.1, 0.1, 
1.0),
+         evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE, 1.0, 1.0, 1.0, 
1.0),
+         evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR, 1.0, 1.0, 1.0, 
1.0),
+         evas_3d_material_shininess_set(100.0));
+
+   data->material_wood = eo_add(EVAS_3D_MATERIAL_CLASS, evas);
+
+   data->texture_wood = eo_add(EVAS_3D_TEXTURE_CLASS, evas);
+   data->texture_four_n = eo_add(EVAS_3D_TEXTURE_CLASS, evas);
+   eo_do(data->texture_wood, evas_3d_texture_file_set("wood.jpg", NULL),
+         evas_3d_texture_wrap_set(EVAS_3D_WRAP_MODE_REPEAT,
+                                  EVAS_3D_WRAP_MODE_REPEAT));
+   eo_do(data->texture_four_n, evas_3d_texture_file_set("four_NM_height.tga", 
NULL),
+         evas_3d_texture_wrap_set(EVAS_3D_WRAP_MODE_REPEAT,
+                                  EVAS_3D_WRAP_MODE_REPEAT));
+
+   eo_do(data->material_wood,
+         evas_3d_material_texture_set(EVAS_3D_MATERIAL_NORMAL, 
data->texture_four_n),
+         evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, 
data->texture_wood),
+         evas_3d_material_texture_set(EVAS_3D_MATERIAL_AMBIENT, 
data->texture_wood),
+         evas_3d_material_texture_set(EVAS_3D_MATERIAL_SPECULAR, 
data->texture_wood),
+         evas_3d_material_enable_set(EVAS_3D_MATERIAL_AMBIENT, EINA_TRUE),
+         evas_3d_material_enable_set(EVAS_3D_MATERIAL_NORMAL, EINA_TRUE),
+         evas_3d_material_enable_set(EVAS_3D_MATERIAL_DIFFUSE, EINA_TRUE),
+         evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE),
+
+         evas_3d_material_color_set(EVAS_3D_MATERIAL_AMBIENT, 0.1, 0.1, 0.1, 
1.0),
+         evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE, 1.0, 1.0, 1.0, 
1.0),
+         evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR, 1.0, 1.0, 1.0, 
1.0),
+         evas_3d_material_shininess_set(100.0));
+
+   /* Setup mesh. */
+   data->mesh = eo_add(EVAS_3D_MESH_CLASS, evas);
+   evas_3d_add_cube_frame(data->mesh, 0);
+
+   evas_3d_add_cube_frame(data->mesh, 100);
+   eo_do(data->mesh,
+         evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_PARALLAX_OCCLUSION),
+         evas_3d_mesh_frame_material_set(0, data->material_rocks));
+
+   eo_do(data->mesh,
+         evas_3d_mesh_frame_material_set(100, data->material_wood));
+
+   data->mesh_node = eo_add(EVAS_3D_NODE_CLASS, evas,
+                            evas_3d_node_constructor(EVAS_3D_NODE_TYPE_MESH));
+   eo_do(data->root_node, evas_3d_node_member_add(data->mesh_node));
+   eo_do(data->mesh_node, evas_3d_node_mesh_add(data->mesh),
+         evas_3d_node_scale_set(3, 3, 3));
+}
+
+static void
+_scene_setup(Scene_Data *data)
+{
+   data->scene = eo_add(EVAS_3D_SCENE_CLASS, evas);
+   eo_do(data->scene,
+         evas_3d_scene_size_set(WIDTH, HEIGHT);
+         evas_3d_scene_background_color_set(0.0, 0.0, 0.0, 0.0));
+
+   data->root_node = eo_add(EVAS_3D_NODE_CLASS, evas,
+                            evas_3d_node_constructor(EVAS_3D_NODE_TYPE_NODE));
+
+   _camera_setup(data);
+   _light_setup(data);
+   _mesh_setup(data);
+
+   eo_do(data->scene,
+         evas_3d_scene_root_node_set(data->root_node),
+         evas_3d_scene_camera_node_set(data->camera_node));
+}
+
+int
+main(void)
+{
+   //Unless Evas 3D supports Software renderer, we set gl backened forcely.
+   setenv("ECORE_EVAS_ENGINE", "opengl_x11", 1);
+
+   Scene_Data data;
+
+   if (!ecore_evas_init()) return 0;
+
+   ecore_evas = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
+
+   if (!ecore_evas) return 0;
+
+   ecore_evas_callback_delete_request_set(ecore_evas, _on_delete);
+   ecore_evas_callback_resize_set(ecore_evas, _on_canvas_resize);
+   ecore_evas_show(ecore_evas);
+
+   evas = ecore_evas_get(ecore_evas);
+
+   _scene_setup(&data);
+
+   /* Add a background rectangle objects. */
+   background = eo_add(EVAS_RECTANGLE_CLASS, evas);
+   eo_do(background,
+         evas_obj_color_set(0, 0, 0, 255),
+         evas_obj_size_set(WIDTH, HEIGHT),
+         evas_obj_visibility_set(EINA_TRUE));
+
+   /* Add an image object for 3D scene rendering. */
+   image = evas_object_image_filled_add(evas);
+   eo_do(image,
+         evas_obj_size_set(WIDTH, HEIGHT),
+         evas_obj_visibility_set(EINA_TRUE),
+         evas_object_focus_set(image, EINA_TRUE));
+
+   /* Set the image object as render target for 3D scene. */
+   eo_do(image, evas_obj_image_scene_set(data.scene));
+
+   /* Add animation timer callback. */
+   ecore_timer_add(0.01, _animate_scene, &data);
+   evas_object_event_callback_add(image, EVAS_CALLBACK_KEY_DOWN, _on_key_down, 
&data);
+
+   /* Enter main loop. */
+   ecore_main_loop_begin();
+
+   ecore_evas_free(ecore_evas);
+   ecore_evas_shutdown();
+
+   return 0;
+}
diff --git a/src/examples/evas/four_NM_height.tga 
b/src/examples/evas/four_NM_height.tga
new file mode 100644
index 0000000..08bb3a2
Binary files /dev/null and b/src/examples/evas/four_NM_height.tga differ
diff --git a/src/examples/evas/rocks.jpg b/src/examples/evas/rocks.jpg
new file mode 100644
index 0000000..7383271
Binary files /dev/null and b/src/examples/evas/rocks.jpg differ
diff --git a/src/examples/evas/rocks_NM_height.tga 
b/src/examples/evas/rocks_NM_height.tga
new file mode 100644
index 0000000..7c8ee3b
Binary files /dev/null and b/src/examples/evas/rocks_NM_height.tga differ
diff --git a/src/examples/evas/wood.jpg b/src/examples/evas/wood.jpg
new file mode 100644
index 0000000..cff2cb2
Binary files /dev/null and b/src/examples/evas/wood.jpg differ
diff --git a/src/lib/evas/Evas_Eo.h b/src/lib/evas/Evas_Eo.h
index 4ee08aa..f82dbed 100644
--- a/src/lib/evas/Evas_Eo.h
+++ b/src/lib/evas/Evas_Eo.h
@@ -781,6 +781,8 @@ typedef enum _Evas_3D_Shade_Mode
    EVAS_3D_SHADE_MODE_SHADOW_MAP_RENDER,
    /**< rendering to additional frame bufer*/
    EVAS_3D_SHADE_MODE_COLOR_PICK,
+   /**< Per-pixel parallax occlusion map shading */
+   EVAS_3D_SHADE_MODE_PARALLAX_OCCLUSION,
 } Evas_3D_Shade_Mode;
 
 /**
diff --git a/src/modules/evas/engines/gl_common/evas_gl_3d.c 
b/src/modules/evas/engines/gl_common/evas_gl_3d.c
index eab4351..9e7dfd0 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_3d.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_3d.c
@@ -1240,7 +1240,8 @@ _mesh_draw_data_build(E3D_Draw_Data *data,
         if (_flags_need_tex_coord(data->flags))
           BUILD(vertex_attrib,     VERTEX_TEXCOORD,     EINA_FALSE);
      }
-   else if (pdmesh->shade_mode == EVAS_3D_SHADE_MODE_NORMAL_MAP)
+   else if ((pdmesh->shade_mode == EVAS_3D_SHADE_MODE_NORMAL_MAP) ||
+            (pdmesh->shade_mode == EVAS_3D_SHADE_MODE_PARALLAX_OCCLUSION))
      {
         BUILD(vertex_attrib,     VERTEX_POSITION,     EINA_TRUE);
         BUILD(vertex_attrib,     VERTEX_NORMAL,       EINA_TRUE);
@@ -1248,6 +1249,11 @@ _mesh_draw_data_build(E3D_Draw_Data *data,
         BUILD(material_texture,  MATERIAL_NORMAL,     EINA_TRUE);
         BUILD(vertex_attrib,     VERTEX_TANGENT,      EINA_FALSE);
 
+
+        if (pdmesh->shade_mode == EVAS_3D_SHADE_MODE_NORMAL_MAP)
+          BUILD(vertex_attrib,     VERTEX_TANGENT,      EINA_FALSE);
+        else BUILD(vertex_attrib,     VERTEX_TANGENT,      EINA_TRUE);
+
         BUILD(material_color,    MATERIAL_AMBIENT,    EINA_FALSE);
         BUILD(material_color,    MATERIAL_DIFFUSE,    EINA_FALSE);
         BUILD(material_color,    MATERIAL_SPECULAR,   EINA_FALSE);
diff --git a/src/modules/evas/engines/gl_common/shader_3d/evas_gl_3d_shaders.x 
b/src/modules/evas/engines/gl_common/shader_3d/evas_gl_3d_shaders.x
index f1d347e..cae8825 100644
--- a/src/modules/evas/engines/gl_common/shader_3d/evas_gl_3d_shaders.x
+++ b/src/modules/evas/engines/gl_common/shader_3d/evas_gl_3d_shaders.x
@@ -930,11 +930,11 @@ static const char const normal_map_frag_glsl[] =
    "   vec3  normal;\n"
    "   vec4  color;\n"
    "#ifdef NORMAL_TEXTURE_BLEND\n"
-   "   normal = texture2D(uTextureNormal0, vTexCoord).rgb * 
uTextureNormalWeight;\n"
-   "   normal += texture2D(uTextureNormal1, vTexCoord).rgb *\n"
+   "   normal = texture2D(uTextureNormal0, vTexCoord).rgb * 
uTextureNormalWeight / texture2D(uTextureNormal0, vTexCoord).a;\n"
+   "   normal += texture2D(uTextureNormal1, vTexCoord).rgb / 
texture2D(uTextureNormal1, vTexCoord).a *\n"
    "   (1.0 - uTextureNormalWeight);\n"
    "#else\n"
-   "   normal = texture2D(uTextureNormal0, vTexCoord).rgb;\n"
+   "   normal = texture2D(uTextureNormal0, vTexCoord).rgb / 
texture2D(uTextureNormal0, vTexCoord).a;\n"
    "#endif //NORMAL_TEXTURE_BLEND\n"
    "   normal = 2.0 * normal - 1.0;\n"
    "#ifndef VERTEX_TANGENT\n"
@@ -1029,7 +1029,7 @@ static const char const normal_map_frag_glsl[] =
    "   shadow = 0.0;\n"
    "   for (i = -4.0; i < 4.0; i++)\n"
    "     for (j = -4.0; j < 4.0; j++)\n"
-   "        shadow += float(smcoord.z <= texture2D(uShadowMap, smcoord.xy 
+vec2(i / 8.0, j / 8.0)*size).x);\n"
+   "       shadow += float(smcoord.z <= texture2D(uShadowMap, smcoord.xy + 
vec2(i / 8.0, j / 8.0)*size).x);\n"
    "   return shadow / 64.0;\n"
    "}\n"
    "#endif //SHADOWED\n"
@@ -1105,6 +1105,364 @@ static const char const color_pick_frag_glsl[] =
    "   gl_FragColor = vec4(uColorPick);\n"
    "}\n";
 
+static const char const parallax_occlusion_vert_glsl[] =
+   "uniform  mat4  uMatrixMvp;\n"
+   "uniform  mat3  uMatrixNormal;\n"
+   "uniform  mat4  uMatrixModelview;\n"
+   "uniform  vec4  uLightPosition;\n"
+   "varying  vec3  vLightVector;\n"
+   "varying  vec3  vLightHalfVector;\n"
+   "varying  vec3  vEyeVector;\n"
+   "#ifdef SHADOWED\n"
+   "uniform mat4 uMatrixLight;\n"
+   "varying vec4 vLightPosition;\n"
+   "#endif //SHADOWED\n"
+   "#ifdef VERTEX_POSITION\n"
+   "attribute   vec4  aPosition0;\n"
+   "#endif //VERTEX_POSITION\n"
+   "#ifdef VERTEX_POSITION_BLEND\n"
+   "attribute   vec4  aPosition1;\n"
+   "uniform     float uPositionWeight;\n"
+   "#endif //VERTEX_POSITION_BLEND\n"
+   "#ifdef VERTEX_NORMAL\n"
+   "attribute   vec4  aNormal0;\n"
+   "#endif //VERTEX_NORMAL\n"
+   "#ifdef VERTEX_NORMAL_BLEND\n"
+   "attribute   vec4  aNormal1;\n"
+   "uniform     float uNormalWeight;\n"
+   "#endif //VERTEX_NORMAL_BLEND\n"
+   "#ifdef VERTEX_TANGENT\n"
+   "attribute   vec4  aTangent0;\n"
+   "#endif //VERTEX_TANGENT\n"
+   "#ifdef VERTEX_TANGENT_BLEND\n"
+   "attribute   vec4  aTangent1;\n"
+   "uniform     float uTangentWeight;\n"
+   "#endif //VERTEX_TANGENT_BLEND\n"
+   "#ifdef VERTEX_TEXCOORD\n"
+   "attribute   vec4  aTexCoord0;\n"
+   "#endif //VERTEX_TEXCOORD\n"
+   "#ifdef VERTEX_TEXCOORD_BLEND\n"
+   "attribute   vec4  aTexCoord1;\n"
+   "uniform     float uTexCoordWeight;\n"
+   "#endif //VERTEX_TEXCOORD_BLEND\n"
+   "#ifdef NEED_TEX_COORD\n"
+   "varying vec2 vTexCoord;\n"
+   "#endif //NEED_TEX_COORD\n"
+   "#ifdef LIGHT_ATTENUATION\n"
+   "varying  float vLightDist;\n"
+   "#endif //LIGHT_ATTENUATION\n"
+   "void vertexParallaxOcclusion(vec4 position, vec3 normal, vec3 tangent)\n"
+   "{\n"
+   "   vec3 n = normalize(uMatrixNormal * normal);\n"
+   "   vec3 t = normalize(uMatrixNormal * tangent);\n"
+   "   vec3 b = cross(n, t);\n"
+   "   vec3 tmp;\n"
+   "   position = uMatrixModelview * position;\n"
+   "#ifdef LIGHT_DIRECTIONAL\n"
+   "   vec3 lightDir = uLightPosition.xyz;\n"
+   "#else\n"
+   "   vec3 lightDir = uLightPosition.xyz - position.xyz;\n"
+   "#ifdef LIGHT_ATTENUATION\n"
+   "   vLightDist = length(lightDir);\n"
+   "#endif //LIGHT_ATTENUATION\n"
+   "   lightDir = normalize(lightDir);\n"
+   "#endif //LIGHT_DIRECTIONAL\n"
+   "   tmp.x = dot(lightDir, t);\n"
+   "   tmp.y = dot(lightDir, b);\n"
+   "   tmp.z = dot(lightDir, n);\n"
+   "   vLightVector = tmp;\n"
+   "   tmp.x = dot(position.xyz, t);\n"
+   "   tmp.y = dot(position.xyz, b);\n"
+   "   tmp.z = dot(position.xyz, n);\n"
+   "   vEyeVector = normalize(tmp);\n"
+   "   vec3 hv = normalize(normalize(-position.xyz) + lightDir);\n"
+   "   tmp.x = dot(hv, t);\n"
+   "   tmp.y = dot(hv, b);\n"
+   "   tmp.z = dot(hv, n);\n"
+   "   vLightHalfVector = tmp;\n"
+   "}\n"
+   "void main()\n"
+   "{\n"
+   "#ifdef VERTEX_POSITION_BLEND\n"
+   "   vec4 position = aPosition0 * uPositionWeight +\n"
+   "   aPosition1 * (1.0 - uPositionWeight);\n"
+   "   position = vec4(position.xyz, 1.0);\n"
+   "#else\n"
+   "#ifdef VERTEX_POSITION\n"
+   "   vec4 position = vec4(aPosition0.xyz, 1.0);\n"
+   "#endif // VERTEX_POSITION\n"
+   "#endif //VERTEX_POSITION_BLEND\n"
+   "#ifdef VERTEX_NORMAL_BLEND\n"
+   "   vec3 normal = aNormal0.xyz * uNormalWeight +\n"
+   "   aNormal1.xyz * (1.0 - uNormalWeight);\n"
+   "#else\n"
+   "#ifdef VERTEX_NORMAL\n"
+   "   vec3 normal = aNormal0.xyz;\n"
+   "#endif //VERTEX_NORMAL\n"
+   "#endif //VERTEX_NORMAL_BLEND\n"
+   "#ifdef VERTEX_TANGENT_BLEND\n"
+   "   vec3 tangent = aTangent0.xyz * uTangentWeight +\n"
+   "   aTangent1.xyz * (1.0 - uTangentWeight);\n"
+   "#else\n"
+   "#ifdef VERTEX_TANGENT\n"
+   "   vec3 tangent = aTangent0.xyz;\n"
+   "#endif //VERTEX_TANGENT\n"
+   "#endif //VERTEX_TANGENT_BLEND\n"
+   "#ifdef VERTEX_TEXCOORD_BLEND\n"
+   "   vTexCoord = aTexCoord0.st * uTexCoordWeight +\n"
+   "   aTexCoord1.st * (1.0 - uTexCoordWeight);\n"
+   "#else\n"
+   "#ifdef VERTEX_TEXCOORD\n"
+   "   vTexCoord = aTexCoord0.st;\n"
+   "#endif //VERTEX_TEXCOORD\n"
+   "#endif //VERTEX_TEXCOORD_BLEND\n"
+   "   gl_Position = uMatrixMvp * position;\n"
+   "   vertexParallaxOcclusion(position, normal, tangent);\n"
+   "#ifdef SHADOWED\n"
+   "   vLightPosition = uMatrixLight * position;\n"
+   "#endif //SHADOWED\n"
+   "}\n";
+
+static const char const parallax_occlusion_frag_glsl[] =
+   "varying  vec3        vLightVector;\n"
+   "varying  vec3        vLightHalfVector;\n"
+   "uniform  sampler2D   uTextureNormal0;\n"
+   "varying  vec3        vEyeVector;\n"
+   "#ifdef NEED_TEX_COORD\n"
+   "varying vec2   vTexCoord;\n"
+   "#endif //TEX_COORD\n"
+   "#ifdef FOG_ENABLED\n"
+   "uniform float uFogFactor;\n"
+   "uniform vec4  uFogColor;\n"
+   "#endif //FOG_ENABLED\n"
+   "#ifdef  SHADOWED\n"
+   "varying vec4 vLightPosition;\n"
+   "uniform sampler2D uShadowMap;\n"
+   "float shadow;\n"
+   "#endif //SHADOWED\n"
+   "#ifdef NORMAL_TEXTURE_BLEND\n"
+   "uniform  sampler2D  uTextureNormal1;\n"
+   "uniform  float      uTextureNormalWeight;\n"
+   "#endif //NORMAL_TEXTURE_BLEND\n"
+   "#ifdef DIFFUSE\n"
+   "uniform   vec4        uMaterialDiffuse;\n"
+   "uniform   vec4        uLightDiffuse;\n"
+   "#ifdef DIFFUSE_TEXTURE\n"
+   "uniform sampler2D  uTextureDiffuse0;\n"
+   "#endif //DIFFUSE_TEXTURE\n"
+   "#ifdef DIFFUSE_TEXTURE_BLEND\n"
+   "uniform sampler2D  uTextureDiffuse1;\n"
+   "uniform float      uTextureDiffuseWeight;\n"
+   "#endif //DIFFUSE_TEXTURE_BLEND\n"
+   "#endif //DIFFUSE\n"
+   "#ifdef SPECULAR\n"
+   "uniform   vec4     uLightSpecular;\n"
+   "uniform   float    uMaterialShininess;\n"
+   "uniform   vec4     uMaterialSpecular;\n"
+   "#ifdef SPECULAR_TEXTURE\n"
+   "uniform sampler2D  uTextureSpecular0;\n"
+   "#endif //SPECULAR_TEXTURE\n"
+   "#ifdef SPECULAR_TEXTURE_BLEND\n"
+   "uniform sampler2D  uTextureSpecular1;\n"
+   "uniform float      uTextureSpecularWeight;\n"
+   "#endif //SPECULAR_TEXTURE_BLEND\n"
+   "#endif //SPECULAR\n"
+   "#ifdef AMBIENT\n"
+   "uniform  vec4       uMaterialAmbient;\n"
+   "uniform  vec4       uLightAmbient;\n"
+   "#ifdef AMBIENT_TEXTURE\n"
+   "uniform sampler2D  uTextureAmbient0;\n"
+   "#endif //AMBIENT_TEXTURE\n"
+   "#ifdef AMBIENT_TEXTURE_BLEND\n"
+   "uniform sampler2D  uTextureAmbient1;\n"
+   "uniform float      uTextureAmbientWeight;\n"
+   "#endif //AMBIENT_TEXTURE_BLEND\n"
+   "#endif //AMBIENT\n"
+   "#ifdef EMISSION\n"
+   "uniform vec4       uMaterialEmission;\n"
+   "#ifdef EMISSION_TEXTURE\n"
+   "uniform sampler2D  uTextureEmission0;\n"
+   "#endif //EMISSION_TEXTURE\n"
+   "#ifdef EMISSION_TEXTURE_BLEND\n"
+   "uniform sampler2D  uTextureEmission1;\n"
+   "uniform float      uTextureEmissionWeight;\n"
+   "#endif //EMISSION_TEXTURE_BLEND\n"
+   "#endif //EMISSION\n"
+   "#ifdef LIGHT_SPOT\n"
+   "uniform   vec3  uLightSpotDir;\n"
+   "uniform   float uLightSpotExp;\n"
+   "uniform   float uLightSpotCutoffCos;\n"
+   "#endif //LIGHT_SPOT\n"
+   "#ifdef LIGHT_ATTENUATION\n"
+   "varying   float    vLightDist;\n"
+   "#endif //LIGHT_ATTENUATION\n"
+   "const float parallaxScale = 0.2;\n"
+   "vec2 parallaxMapping(in vec3 view, in vec2 tex, out float 
parallaxHeight)\n"
+   "{\n"
+   "   const float minLayers = 10.0;\n"
+   "   const float maxLayers = 30.0;\n"
+   "   float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0, 0, 1), 
view)));\n"
+   "   vec2 texStep = parallaxScale * view.xy / view.z / numLayers;\n"
+   "   float layerHeight = 1.0 / numLayers;\n"
+   "   float curLayerHeight = 0.0;\n"
+   "   vec2 dtex = parallaxScale * view.xy / view.z / numLayers;\n"
+   "   vec2 currentTextureCoords = tex;\n"
+   "#ifdef NORMAL_TEXTURE_BLEND\n"
+   "   float heightFromTexture = (1.0 - texture2D(uTextureNormal0, 
currentTextureCoords).a) * uTextureNormalWeight;\n"
+   "   heightFromTexture += (1.0 - texture2D(uTextureNormal1, 
currentTextureCoords).a) *\n"
+   "   (1.0 - uTextureNormalWeight);\n"
+   "#else\n"
+   "   float heightFromTexture = 1.0 - texture2D(uTextureNormal0, 
currentTextureCoords).a;\n"
+   "#endif //NORMAL_TEXTURE_BLEND\n"
+   "   while(heightFromTexture > curLayerHeight)\n"
+   "   {\n"
+   "      curLayerHeight += layerHeight;\n"
+   "      currentTextureCoords -= dtex;\n"
+   "#ifdef NORMAL_TEXTURE_BLEND\n"
+   "      heightFromTexture = (1.0 - texture2D(uTextureNormal0, 
currentTextureCoords).a) * uTextureNormalWeight;\n"
+   "      heightFromTexture += (1.0 - texture2D(uTextureNormal1, 
currentTextureCoords).a) *\n"
+   "      (1.0 - uTextureNormalWeight);\n"
+   "#else\n"
+   "      heightFromTexture = 1.0 - texture2D(uTextureNormal0, 
currentTextureCoords).a;\n"
+   "#endif //NORMAL_TEXTURE_BLEND\n"
+   "   }\n"
+   "   vec2 prevTCoords = currentTextureCoords + texStep;\n"
+   "   float nextH = heightFromTexture - curLayerHeight;\n"
+   "#ifdef NORMAL_TEXTURE_BLEND\n"
+   "   float prevH = (1.0 - texture2D(uTextureNormal0, prevTCoords).a\n"
+   "                           - curLayerHeight + layerHeight) * 
uTextureNormalWeight;\n"
+   "   prevH += (1.0 - texture2D(uTextureNormal1, prevTCoords).a\n"
+   "                           - curLayerHeight + layerHeight) * (1.0 - 
uTextureNormalWeight);\n"
+   "#else\n"
+   "   float prevH = 1.0 - texture2D(uTextureNormal0, prevTCoords).a\n"
+   "                           - curLayerHeight + layerHeight;\n"
+   "#endif //NORMAL_TEXTURE_BLEND\n"
+   "   float weight = nextH / (nextH - prevH);\n"
+   "   vec2 finalTexCoords = prevTCoords * weight + currentTextureCoords * 
(1.0-weight);\n"
+   "   parallaxHeight = curLayerHeight + prevH * weight + nextH * (1.0 - 
weight);\n"
+   "   return finalTexCoords;\n"
+   "}\n"
+   "void fragmentParallaxMap()\n"
+   "{\n"
+   "   float factor;\n"
+   "   vec3  normal;\n"
+   "   vec4  color;\n"
+   "   float parallaxHeight;\n"
+   "   vec2 tex = parallaxMapping(vEyeVector, vTexCoord, parallaxHeight);\n"
+   "   vec3  lv = normalize(vLightVector);\n"
+   "#ifdef NORMAL_TEXTURE_BLEND\n"
+   "   normal = texture2D(uTextureNormal0, tex).rgb * uTextureNormalWeight / 
texture2D(uTextureNormal0, tex).a;\n"
+   "   normal += texture2D(uTextureNormal1, tex).rgb *\n"
+   "   (1.0 - uTextureNormalWeight) / texture2D(uTextureNormal1, tex).a;\n"
+   "#else\n"
+   "   normal = texture2D(uTextureNormal0, tex).rgb / 
texture2D(uTextureNormal0, tex).a;\n"
+   "#endif //NORMAL_TEXTURE_BLEND\n"
+   "   normal = 2.0 * normal - 1.0;\n"
+   "   normal = normalize(normal);\n"
+   "   factor = dot(lv, normal);\n"
+   "#ifdef LIGHT_SPOT\n"
+   "   float f = dot(-lv, normalize(uLightSpotDir));\n"
+   "   if (f > uLightSpotCutoffCos)\n"
+   "     factor *= pow(f, uLightSpotExp);\n"
+   "   else\n"
+   "     factor = 0.0;\n"
+   "#endif //LIGHT_SPOT\n"
+   "   if (factor > 0.0)\n"
+   "     {\n"
+   "#ifdef DIFFUSE\n"
+   "#ifdef DIFFUSE_TEXTURE_BLEND\n"
+   "        color = texture2D(uTextureDiffuse0, tex) * uTextureDiffuseWeight 
+\n"
+   "        texture2D(uTextureDiffuse1, tex) * (1.0 - 
uTextureDiffuseWeight);\n"
+   "#else\n"
+   "#ifdef DIFFUSE_TEXTURE\n"
+   "        color = texture2D(uTextureDiffuse0, tex);\n"
+   "#else\n"
+   "        color = uMaterialDiffuse;\n"
+   "#endif //DIFFUSE_TEXTURE\n"
+   "#endif //DIFFUSE_TEXTURE_BLEND\n"
+   "        gl_FragColor = uLightDiffuse * color * factor;\n"
+   "#else\n"
+   "        gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n"
+   "#endif //DIFFUSE\n"
+   "#ifdef SPECULAR\n"
+   "        factor = dot(normalize(vLightHalfVector), normal);\n"
+   "        if (factor > 0.0)\n"
+   "          {\n"
+   "             factor = pow(factor, uMaterialShininess);\n"
+   "#ifdef SPECULAR_TEXTURE_BLEND\n"
+   "             color = texture2D(uTextureSpecular0, tex) * 
uTextureSpecularWeight +\n"
+   "             texture2D(uTextureSpecular1, tex) * (1.0 - 
uTextureSpecularWeight);\n"
+   "#else\n"
+   "#ifdef SPECULAR_TEXTURE\n"
+   "             color = texture2D(uTextureSpecular0, tex);\n"
+   "#else\n"
+   "             color = uMaterialSpecular;\n"
+   "#endif //SPECULAR_TEXTURE\n"
+   "#endif //SPECULAR_TEXTURE_BLEND\n"
+   "             gl_FragColor += uLightSpecular * color * factor;\n"
+   "          }\n"
+   "#endif //SPECULAR\n"
+   "#ifdef SHADOWED\n"
+   "        gl_FragColor *= shadow;\n"
+   "#endif //SHADOWED\n"
+   "     }\n"
+   "   else\n"
+   "     gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n"
+   "#ifdef AMBIENT\n"
+   "#ifdef AMBIENT_TEXTURE_BLEND\n"
+   "   color = texture2D(uTextureAmbient0, tex) * uTextureAmbientWeight +\n"
+   "   texture2D(uTextureAmbient1, tex) * (1.0 - uTextureAmbientWeight);\n"
+   "#else\n"
+   "#ifdef AMBIENT_TEXTURE\n"
+   "   color = texture2D(uTextureAmbient0, tex);\n"
+   "#else\n"
+   "   color = uMaterialAmbient;\n"
+   "#endif //AMBIENT_TEXTURE\n"
+   "#endif //AMBIENT_TEXTURE_BLEND\n"
+   "   gl_FragColor += uLightAmbient * color;\n"
+   "#endif //AMBIENT\n"
+   "#ifdef LIGHT_ATTENUATION\n"
+   "   gl_FragColor /= dot(uLightAtten, vec3(1.0, vLightDist, vLightDist * 
vLightDist));\n"
+   "#endif //LIGHT_ATTENUATION\n"
+   "#ifdef EMISSION\n"
+   "#ifdef EMISSION_TEXTURE_BLEND\n"
+   "   color = texture2D(uTextureEmission0, tex) * uTextureEmissionWeight +\n"
+   "   texture2D(uTextureEmission1, tex) * (1.0 - uTextureEmissionWeight);\n"
+   "#else\n"
+   "#ifdef EMISSION_TEXTURE\n"
+   "   color = texture2D(uTextureEmission0, tex);\n"
+   "#else\n"
+   "   color = uMaterialEmission;\n"
+   "#endif //EMISSION_TEXTURE\n"
+   "#endif //EMISSION_TEXTURE_BLEND\n"
+   "   gl_FragColor += color;\n"
+   "#endif //EMISSION\n"
+   "}\n"
+   "#ifdef SHADOWED\n"
+   "float pcf(vec4 lpos, float size)\n"
+   "{\n"
+   "   vec3 smcoord = lpos.xyz / lpos.w * 0.5 + 0.5;\n"
+   "   float i, j, randx, randy, shadow;\n"
+   "   shadow = 0.0;\n"
+   "   for (i = -4.0; i < 4.0; i++)\n"
+   "     for (j = -4.0; j < 4.0; j++)\n"
+   "        shadow += float(smcoord.z <= texture2D(uShadowMap, smcoord.xy 
+vec2(i / 8.0, j / 8.0)*size).x);\n"
+   "   return shadow / 64.0;\n"
+   "}\n"
+   "#endif //SHADOWED\n"
+   "void main() {\n"
+   "#ifdef SHADOWED\n"
+   "   shadow = pcf(vLightPosition, 1.0 / 200.0);\n"
+   "#endif //SHADOWED\n"
+   "   fragmentParallaxMap();\n"
+   "#ifdef FOG_ENABLED\n"
+   "   float z = gl_FragCoord.z / gl_FragCoord.w;\n"
+   "   float fogFactor = exp2( -uFogFactor * uFogFactor * z * z * 1.44);\n"
+   "   fogFactor = clamp(fogFactor, 0.0, 1.0);\n"
+   "   gl_FragColor = mix(uFogColor, gl_FragColor, fogFactor);\n"
+   "#endif //FOG_ENABLED\n"
+   "}\n";
+
 static const char *vertex_shaders[] =
 {
     vertex_color_vert_glsl,
@@ -1114,6 +1472,7 @@ static const char *vertex_shaders[] =
     normal_map_vert_glsl,
     shadow_map_vert_glsl,
     color_pick_vert_glsl,
+    parallax_occlusion_vert_glsl,
 };
 
 static const char *fragment_shaders[] =
@@ -1125,4 +1484,5 @@ static const char *fragment_shaders[] =
     normal_map_frag_glsl,
     shadow_map_frag_glsl,
     color_pick_frag_glsl,
+    parallax_occlusion_frag_glsl,
 };
diff --git a/src/modules/evas/engines/gl_common/shader_3d/normal_map_frag.shd 
b/src/modules/evas/engines/gl_common/shader_3d/normal_map_frag.shd
index 766e07f..4e2d826 100644
--- a/src/modules/evas/engines/gl_common/shader_3d/normal_map_frag.shd
+++ b/src/modules/evas/engines/gl_common/shader_3d/normal_map_frag.shd
@@ -127,11 +127,11 @@ void fragmentNormalMap()
    vec4  color;
 
 #ifdef NORMAL_TEXTURE_BLEND
-   normal = texture2D(uTextureNormal0, vTexCoord).rgb * uTextureNormalWeight;
-   normal += texture2D(uTextureNormal1, vTexCoord).rgb *
+   normal = texture2D(uTextureNormal0, vTexCoord).rgb * uTextureNormalWeight / 
texture2D(uTextureNormal0, vTexCoord).a;
+   normal += texture2D(uTextureNormal1, vTexCoord).rgb / 
texture2D(uTextureNormal1, vTexCoord).a *
    (1.0 - uTextureNormalWeight);
 #else
-   normal = texture2D(uTextureNormal0, vTexCoord).rgb;
+   normal = texture2D(uTextureNormal0, vTexCoord).rgb / 
texture2D(uTextureNormal0, vTexCoord).a;
 #endif //NORMAL_TEXTURE_BLEND
 
    normal = 2.0 * normal - 1.0;
@@ -259,7 +259,7 @@ float pcf(vec4 lpos, float size)
    shadow = 0.0;
    for (i = -4.0; i < 4.0; i++)
      for (j = -4.0; j < 4.0; j++)
-        shadow += float(smcoord.z <= texture2D(uShadowMap, smcoord.xy +vec2(i 
/ 8.0, j / 8.0)*size).x);
+       shadow += float(smcoord.z <= texture2D(uShadowMap, smcoord.xy + vec2(i 
/ 8.0, j / 8.0)*size).x);
    return shadow / 64.0;
 }
 #endif //SHADOWED
diff --git a/src/modules/evas/engines/gl_common/shader_3d/normal_map_frag.shd 
b/src/modules/evas/engines/gl_common/shader_3d/parallax_occlusion_frag.shd
similarity index 57%
copy from src/modules/evas/engines/gl_common/shader_3d/normal_map_frag.shd
copy to src/modules/evas/engines/gl_common/shader_3d/parallax_occlusion_frag.shd
index 766e07f..3356829 100644
--- a/src/modules/evas/engines/gl_common/shader_3d/normal_map_frag.shd
+++ b/src/modules/evas/engines/gl_common/shader_3d/parallax_occlusion_frag.shd
@@ -23,10 +23,6 @@ uniform  sampler2D  uTextureNormal1;
 uniform  float      uTextureNormalWeight;
 #endif //NORMAL_TEXTURE_BLEND
 
-#ifndef VERTEX_TANGENT
-varying  vec3        vNormal;
-#endif //VERTEX_TANGENT
-
 #ifdef DIFFUSE
 uniform   vec4        uMaterialDiffuse;
 uniform   vec4        uLightDiffuse;
@@ -97,50 +93,84 @@ uniform   float uLightSpotCutoffCos;
 varying   float    vLightDist;
 #endif //LIGHT_ATTENUATION
 
-#ifndef VERTEX_TANGENT
+const float parallaxScale = 0.2;
 
-mat3 cotangent_frame(vec3 n, vec3 p, vec2 uv)
+vec2 parallaxMapping(in vec3 view, in vec2 tex, out float parallaxHeight)
 {
-   vec3 dp1 = dFdx(p);
-   vec3 dp2 = dFdy(p);
-   vec2 duv1 = dFdx(uv);
-   vec2 duv2 = dFdy(uv);
-   vec3 dp2perp = cross(dp2, n);
-   vec3 dp1perp = cross(n, dp1);
-   vec3 t = dp2perp * duv1.x + dp1perp * duv2.x;
-   vec3 b = dp2perp * duv1.y + dp1perp * duv2.y;
-   float invmax = inversesqrt(max(dot(t, t), dot(b, b)));
-   return mat3(t * invmax, b * invmax, n);
-}
+   const float minLayers = 10.0;
+   const float maxLayers = 30.0;
+   float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0, 0, 1), view)));
+   vec2 texStep = parallaxScale * view.xy / view.z / numLayers;
 
-vec3 perturb_normal(vec3 normal)
-{
-   mat3 tbn = cotangent_frame(vNormal, -vEyeVector, vTexCoord);
-   return normalize(tbn * normal);
+   float layerHeight = 1.0 / numLayers;
+   float curLayerHeight = 0.0;
+   vec2 dtex = parallaxScale * view.xy / view.z / numLayers;
+
+   vec2 currentTextureCoords = tex;
+
+#ifdef NORMAL_TEXTURE_BLEND
+   float heightFromTexture = (1.0 - texture2D(uTextureNormal0, 
currentTextureCoords).a) * uTextureNormalWeight;
+   heightFromTexture += (1.0 - texture2D(uTextureNormal1, 
currentTextureCoords).a) *
+   (1.0 - uTextureNormalWeight);
+#else
+   float heightFromTexture = 1.0 - texture2D(uTextureNormal0, 
currentTextureCoords).a;
+#endif //NORMAL_TEXTURE_BLEND
+
+   while(heightFromTexture > curLayerHeight)
+   {
+      curLayerHeight += layerHeight;
+      currentTextureCoords -= dtex;
+
+#ifdef NORMAL_TEXTURE_BLEND
+      heightFromTexture = (1.0 - texture2D(uTextureNormal0, 
currentTextureCoords).a) * uTextureNormalWeight;
+      heightFromTexture += (1.0 - texture2D(uTextureNormal1, 
currentTextureCoords).a) *
+      (1.0 - uTextureNormalWeight);
+#else
+      heightFromTexture = 1.0 - texture2D(uTextureNormal0, 
currentTextureCoords).a;
+#endif //NORMAL_TEXTURE_BLEND
+   }
+
+   vec2 prevTCoords = currentTextureCoords + texStep;
+   float nextH = heightFromTexture - curLayerHeight;
+
+#ifdef NORMAL_TEXTURE_BLEND
+   float prevH = (1.0 - texture2D(uTextureNormal0, prevTCoords).a
+                           - curLayerHeight + layerHeight) * 
uTextureNormalWeight;
+   prevH += (1.0 - texture2D(uTextureNormal1, prevTCoords).a
+                           - curLayerHeight + layerHeight) * (1.0 - 
uTextureNormalWeight);
+#else
+   float prevH = 1.0 - texture2D(uTextureNormal0, prevTCoords).a
+                           - curLayerHeight + layerHeight;
+#endif //NORMAL_TEXTURE_BLEND
+
+   float weight = nextH / (nextH - prevH);
+   vec2 finalTexCoords = prevTCoords * weight + currentTextureCoords * 
(1.0-weight);
+   parallaxHeight = curLayerHeight + prevH * weight + nextH * (1.0 - weight);
+
+   return finalTexCoords;
 }
-#endif //VERTEX_TANGENT
 
-void fragmentNormalMap()
+void fragmentParallaxMap()
 {
    float factor;
    vec3  normal;
    vec4  color;
 
+   float parallaxHeight;
+   vec2 tex = parallaxMapping(vEyeVector, vTexCoord, parallaxHeight);
+
+   vec3  lv = normalize(vLightVector);
+
 #ifdef NORMAL_TEXTURE_BLEND
-   normal = texture2D(uTextureNormal0, vTexCoord).rgb * uTextureNormalWeight;
-   normal += texture2D(uTextureNormal1, vTexCoord).rgb *
-   (1.0 - uTextureNormalWeight);
+   normal = texture2D(uTextureNormal0, tex).rgb * uTextureNormalWeight / 
texture2D(uTextureNormal0, tex).a;
+   normal += texture2D(uTextureNormal1, tex).rgb *
+   (1.0 - uTextureNormalWeight) / texture2D(uTextureNormal1, tex).a;
 #else
-   normal = texture2D(uTextureNormal0, vTexCoord).rgb;
+   normal = texture2D(uTextureNormal0, tex).rgb / texture2D(uTextureNormal0, 
tex).a;
 #endif //NORMAL_TEXTURE_BLEND
 
    normal = 2.0 * normal - 1.0;
 
-#ifndef VERTEX_TANGENT
-   normal = perturb_normal(normal);
-#endif //VERTEX_TANGENT
-
-   vec3  lv = normalize(vLightVector);
    normal = normalize(normal);
 
    factor = dot(lv, normal);
@@ -160,12 +190,12 @@ void fragmentNormalMap()
 #ifdef DIFFUSE
 
 #ifdef DIFFUSE_TEXTURE_BLEND
-        color = texture2D(uTextureDiffuse0, vTexCoord) * uTextureDiffuseWeight 
+
-        texture2D(uTextureDiffuse1, vTexCoord) * (1.0 - uTextureDiffuseWeight);
+        color = texture2D(uTextureDiffuse0, tex) * uTextureDiffuseWeight +
+        texture2D(uTextureDiffuse1, tex) * (1.0 - uTextureDiffuseWeight);
 #else
 
 #ifdef DIFFUSE_TEXTURE
-        color = texture2D(uTextureDiffuse0, vTexCoord);
+        color = texture2D(uTextureDiffuse0, tex);
 #else
         color = uMaterialDiffuse;
 #endif //DIFFUSE_TEXTURE
@@ -186,11 +216,11 @@ void fragmentNormalMap()
              factor = pow(factor, uMaterialShininess);
 
 #ifdef SPECULAR_TEXTURE_BLEND
-             color = texture2D(uTextureSpecular0, vTexCoord) * 
uTextureSpecularWeight +
-             texture2D(uTextureSpecular1, vTexCoord) * (1.0 - 
uTextureSpecularWeight);
+             color = texture2D(uTextureSpecular0, tex) * 
uTextureSpecularWeight +
+             texture2D(uTextureSpecular1, tex) * (1.0 - 
uTextureSpecularWeight);
 #else
 #ifdef SPECULAR_TEXTURE
-             color = texture2D(uTextureSpecular0, vTexCoord);
+             color = texture2D(uTextureSpecular0, tex);
 #else
              color = uMaterialSpecular;
 #endif //SPECULAR_TEXTURE
@@ -212,19 +242,19 @@ void fragmentNormalMap()
 
 #ifdef AMBIENT
 #ifdef AMBIENT_TEXTURE_BLEND
-   color = texture2D(uTextureAmbient0, vTexCoord) * uTextureAmbientWeight +
-   texture2D(uTextureAmbient1, vTexCoord) * (1.0 - uTextureAmbientWeight);
+   color = texture2D(uTextureAmbient0, tex) * uTextureAmbientWeight +
+   texture2D(uTextureAmbient1, tex) * (1.0 - uTextureAmbientWeight);
 #else
 
 #ifdef AMBIENT_TEXTURE
-   color = texture2D(uTextureAmbient0, vTexCoord);
+   color = texture2D(uTextureAmbient0, tex);
 #else
    color = uMaterialAmbient;
 #endif //AMBIENT_TEXTURE
 
 #endif //AMBIENT_TEXTURE_BLEND
 
-     gl_FragColor += uLightAmbient * color;
+   gl_FragColor += uLightAmbient * color;
 #endif //AMBIENT
 
 #ifdef LIGHT_ATTENUATION
@@ -234,12 +264,12 @@ void fragmentNormalMap()
 #ifdef EMISSION
 
 #ifdef EMISSION_TEXTURE_BLEND
-   color = texture2D(uTextureEmission0, vTexCoord) * uTextureEmissionWeight +
-   texture2D(uTextureEmission1, vTexCoord) * (1.0 - uTextureEmissionWeight);
+   color = texture2D(uTextureEmission0, tex) * uTextureEmissionWeight +
+   texture2D(uTextureEmission1, tex) * (1.0 - uTextureEmissionWeight);
 #else
 
 #ifdef EMISSION_TEXTURE
-   color = texture2D(uTextureEmission0, vTexCoord);
+   color = texture2D(uTextureEmission0, tex);
 #else
    color = uMaterialEmission;
 #endif //EMISSION_TEXTURE
@@ -270,7 +300,7 @@ void main() {
    shadow = pcf(vLightPosition, 1.0 / 200.0);
 #endif //SHADOWED
 
-   fragmentNormalMap();
+   fragmentParallaxMap();
 
 #ifdef FOG_ENABLED
    float z = gl_FragCoord.z / gl_FragCoord.w;
diff --git 
a/src/modules/evas/engines/gl_common/shader_3d/parallax_occlusion_vert.shd 
b/src/modules/evas/engines/gl_common/shader_3d/parallax_occlusion_vert.shd
new file mode 100644
index 0000000..aec49a2
--- /dev/null
+++ b/src/modules/evas/engines/gl_common/shader_3d/parallax_occlusion_vert.shd
@@ -0,0 +1,151 @@
+uniform  mat4  uMatrixMvp;
+uniform  mat3  uMatrixNormal;
+uniform  mat4  uMatrixModelview;
+uniform  vec4  uLightPosition;
+varying  vec3  vLightVector;
+varying  vec3  vLightHalfVector;
+varying  vec3  vEyeVector;
+
+#ifdef SHADOWED
+uniform mat4 uMatrixLight;
+varying vec4 vLightPosition;
+#endif //SHADOWED
+
+#ifdef VERTEX_POSITION
+attribute   vec4  aPosition0;
+#endif //VERTEX_POSITION
+
+#ifdef VERTEX_POSITION_BLEND
+attribute   vec4  aPosition1;
+uniform     float uPositionWeight;
+#endif //VERTEX_POSITION_BLEND
+
+#ifdef VERTEX_NORMAL
+attribute   vec4  aNormal0;
+#endif //VERTEX_NORMAL
+
+#ifdef VERTEX_NORMAL_BLEND
+attribute   vec4  aNormal1;
+uniform     float uNormalWeight;
+#endif //VERTEX_NORMAL_BLEND
+
+#ifdef VERTEX_TANGENT
+attribute   vec4  aTangent0;
+#endif //VERTEX_TANGENT
+
+#ifdef VERTEX_TANGENT_BLEND
+attribute   vec4  aTangent1;
+uniform     float uTangentWeight;
+#endif //VERTEX_TANGENT_BLEND
+
+#ifdef VERTEX_TEXCOORD
+attribute   vec4  aTexCoord0;
+#endif //VERTEX_TEXCOORD
+
+#ifdef VERTEX_TEXCOORD_BLEND
+attribute   vec4  aTexCoord1;
+uniform     float uTexCoordWeight;
+#endif //VERTEX_TEXCOORD_BLEND
+
+#ifdef NEED_TEX_COORD
+varying vec2 vTexCoord;
+#endif //NEED_TEX_COORD
+
+#ifdef LIGHT_ATTENUATION
+varying  float vLightDist;
+#endif //LIGHT_ATTENUATION
+
+void vertexParallaxOcclusion(vec4 position, vec3 normal, vec3 tangent)
+{
+   vec3 n = normalize(uMatrixNormal * normal);
+   vec3 t = normalize(uMatrixNormal * tangent);
+   vec3 b = cross(n, t);
+   vec3 tmp;
+
+   position = uMatrixModelview * position;
+
+#ifdef LIGHT_DIRECTIONAL
+   vec3 lightDir = uLightPosition.xyz;
+#else
+   vec3 lightDir = uLightPosition.xyz - position.xyz;
+
+#ifdef LIGHT_ATTENUATION
+   vLightDist = length(lightDir);
+#endif //LIGHT_ATTENUATION
+
+   lightDir = normalize(lightDir);
+#endif //LIGHT_DIRECTIONAL
+
+   tmp.x = dot(lightDir, t);
+   tmp.y = dot(lightDir, b);
+   tmp.z = dot(lightDir, n);
+   vLightVector = tmp;
+
+   tmp.x = dot(position.xyz, t);
+   tmp.y = dot(position.xyz, b);
+   tmp.z = dot(position.xyz, n);
+   vEyeVector = normalize(tmp);
+
+   vec3 hv = normalize(normalize(-position.xyz) + lightDir);
+   tmp.x = dot(hv, t);
+   tmp.y = dot(hv, b);
+   tmp.z = dot(hv, n);
+   vLightHalfVector = tmp;
+}
+
+void main()
+{
+
+#ifdef VERTEX_POSITION_BLEND
+   vec4 position = aPosition0 * uPositionWeight +
+   aPosition1 * (1.0 - uPositionWeight);
+   position = vec4(position.xyz, 1.0);
+#else
+
+#ifdef VERTEX_POSITION
+   vec4 position = vec4(aPosition0.xyz, 1.0);
+#endif // VERTEX_POSITION
+
+#endif //VERTEX_POSITION_BLEND
+
+#ifdef VERTEX_NORMAL_BLEND
+   vec3 normal = aNormal0.xyz * uNormalWeight +
+   aNormal1.xyz * (1.0 - uNormalWeight);
+#else
+
+#ifdef VERTEX_NORMAL
+   vec3 normal = aNormal0.xyz;
+#endif //VERTEX_NORMAL
+
+#endif //VERTEX_NORMAL_BLEND
+
+#ifdef VERTEX_TANGENT_BLEND
+   vec3 tangent = aTangent0.xyz * uTangentWeight +
+   aTangent1.xyz * (1.0 - uTangentWeight);
+#else
+
+#ifdef VERTEX_TANGENT
+   vec3 tangent = aTangent0.xyz;
+#endif //VERTEX_TANGENT
+
+#endif //VERTEX_TANGENT_BLEND
+
+#ifdef VERTEX_TEXCOORD_BLEND
+   vTexCoord = aTexCoord0.st * uTexCoordWeight +
+   aTexCoord1.st * (1.0 - uTexCoordWeight);
+#else
+
+#ifdef VERTEX_TEXCOORD
+   vTexCoord = aTexCoord0.st;
+#endif //VERTEX_TEXCOORD
+
+#endif //VERTEX_TEXCOORD_BLEND
+
+   gl_Position = uMatrixMvp * position;
+
+   vertexParallaxOcclusion(position, normal, tangent);
+
+#ifdef SHADOWED
+   vLightPosition = uMatrixLight * position;
+#endif //SHADOWED
+}

-- 


Reply via email to