From: Xiangyin Ma Date: Fri, 9 Jan 2015 18:33:42 +0000 (+0000) Subject: Added refraction effect demo X-Git-Tag: dali_1.0.25~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dccc1bd36adf3b35b357ecd199fbac4b5c078c88;p=platform%2Fcore%2Fuifw%2Fdali-demo.git Added refraction effect demo Change-Id: Ia9ec4763a764344f234b9d3ee3114ad9d91c7abb --- diff --git a/build/tizen/examples/Makefile.am b/build/tizen/examples/Makefile.am index 6365aa6..bb61a9c 100644 --- a/build/tizen/examples/Makefile.am +++ b/build/tizen/examples/Makefile.am @@ -29,6 +29,7 @@ bin_PROGRAMS = \ new-window.example \ page-turn-view.example \ radial-menu.example \ + refraction-effect.example \ scroll-view.example \ shadow-bone-lighting.example \ dali-builder \ @@ -131,6 +132,11 @@ radial_menu_example_CXXFLAGS = $(EXAMPLE_CXXFLAGS) radial_menu_example_DEPENDENCIES = $(EXAMPLE_DEPS) radial_menu_example_LDADD = $(EXAMPLE_LDADD) +refraction_effect_example_SOURCES = $(examples_src_dir)/shader-effect/refraction-effect-example.cpp +refraction_effect_example_CXXFLAGS = $(EXAMPLE_CXXFLAGS) +refraction_effect_example_DEPENDENCIES = $(EXAMPLE_DEPS) +refraction_effect_example_LDADD = $(EXAMPLE_LDADD) + scroll_view_example_SOURCES = $(examples_src_dir)/scroll-view/scroll-view-example.cpp scroll_view_example_CXXFLAGS = $(EXAMPLE_CXXFLAGS) scroll_view_example_DEPENDENCIES = $(EXAMPLE_DEPS) diff --git a/com.samsung.dali-demo.xml b/com.samsung.dali-demo.xml index 59deb65..14fe3a3 100644 --- a/com.samsung.dali-demo.xml +++ b/com.samsung.dali-demo.xml @@ -49,6 +49,9 @@ + + + diff --git a/demo/dali-demo.cpp b/demo/dali-demo.cpp index c8fb798..3209499 100644 --- a/demo/dali-demo.cpp +++ b/demo/dali-demo.cpp @@ -36,6 +36,7 @@ int main(int argc, char **argv) demo.AddExample(Example("motion-stretch.example", "Motion Stretch")); demo.AddExample(Example("page-turn-view.example", "Page Turn View")); demo.AddExample(Example("radial-menu.example", "Radial Menu")); + demo.AddExample(Example("refraction-effect.example", "Refraction")); demo.AddExample(Example("scroll-view.example", "Scroll View")); demo.AddExample(Example("shadow-bone-lighting.example", "Lights and shadows")); demo.AddExample(Example("builder.example", "Script Based UI")); diff --git a/demo/models/surface_pattern_v01.obj b/demo/models/surface_pattern_v01.obj new file mode 100755 index 0000000..8d78c45 --- /dev/null +++ b/demo/models/surface_pattern_v01.obj @@ -0,0 +1,176 @@ +# This file uses centimeters as units for non-parametric coordinates. + +v 41.569229 47.497040 -1.497040 +v 36.373077 50.500000 -1.500000 +v 51.961536 47.497040 -1.497040 +v 46.765385 50.500000 -1.500000 +v 62.349571 47.497536 -1.497533 +v 57.157692 50.500000 -1.500000 +v 36.373077 56.500000 -1.500000 +v 36.373077 50.500000 -1.500000 +v 46.765381 50.500000 -1.500000 +v 46.765381 56.500000 -1.500000 +v 41.569229 59.500000 -1.500000 +v 41.569229 53.500000 1.500000 +v 46.765385 56.500000 -1.500000 +v 46.765385 50.500000 -1.500000 +v 57.157688 50.500000 -1.500000 +v 57.157688 56.500000 -1.500000 +v 51.961536 59.500000 -1.500000 +v 51.961536 53.500000 1.500000 +v 57.157692 56.500000 -1.500000 +v 57.157692 50.500000 -1.500000 +v 62.353844 59.500000 -1.500000 +v 62.353844 53.500000 1.500000 +v 36.373077 56.500000 -1.500000 +v 41.569229 59.500000 -1.500000 +v 41.569229 65.500000 -1.500000 +v 36.373077 68.500000 -1.500000 +v 36.373077 62.500000 1.500000 +v 41.569233 65.500000 -1.500000 +v 41.569233 59.500000 -1.500000 +v 46.765385 56.500000 -1.500000 +v 51.961536 59.500000 -1.500000 +v 51.961536 65.500000 -1.500000 +v 46.765385 68.500000 -1.500000 +v 46.765385 62.500000 1.500000 +v 51.961540 65.500000 -1.500000 +v 51.961540 59.500000 -1.500000 +v 57.157692 56.500000 -1.500000 +v 62.353844 59.500000 -1.500000 +v 62.353844 65.500000 -1.500000 +v 57.157692 68.500000 -1.500000 +v 57.157692 62.500000 1.500000 +v 36.373077 74.500000 -1.500000 +v 36.373077 68.500000 -1.500000 +v 41.569229 65.500000 -1.500000 +v 46.765381 68.500000 -1.500000 +v 46.765381 74.500000 -1.500000 +v 41.569229 77.500000 -1.500000 +v 41.569229 71.500000 1.500000 +v 46.765385 74.500000 -1.500000 +v 46.765385 68.500000 -1.500000 +v 51.961536 65.500000 -1.500000 +v 57.157688 68.500000 -1.500000 +v 57.157688 74.500000 -1.500000 +v 51.961536 77.500000 -1.500000 +v 51.961536 71.500000 1.500000 +v 57.157692 74.500000 -1.500000 +v 57.157692 68.500000 -1.500000 +v 62.353844 65.500000 -1.500000 +v 62.353844 77.500000 -1.500000 +v 62.353844 71.500000 1.500000 +v 36.373077 74.500000 -1.500000 +v 41.569229 77.500000 -1.500000 +v 41.569229 83.500000 -1.500000 +v 36.373077 86.500000 -1.500000 +v 36.373077 80.500000 1.500000 +v 41.569233 83.500000 -1.500000 +v 41.569233 77.500000 -1.500000 +v 46.765385 74.500000 -1.500000 +v 51.961536 77.500000 -1.500000 +v 51.961536 83.500000 -1.500000 +v 46.765385 86.500000 -1.500000 +v 46.765385 80.500000 1.500000 +v 51.961540 83.500000 -1.500000 +v 51.961540 77.500000 -1.500000 +v 57.157692 74.500000 -1.500000 +v 62.353844 77.500000 -1.500000 +v 62.353844 83.500000 -1.500000 +v 57.157692 86.500000 -1.500000 +v 57.157692 80.500000 1.500000 +v 36.373077 86.500000 -1.500000 +v 41.569229 83.500000 -1.500000 +v 46.765381 86.500000 -1.500000 +v 41.569229 89.504967 1.495031 +v 46.765385 86.500000 -1.500000 +v 51.961536 83.500000 -1.500000 +v 57.157688 86.500000 -1.500000 +v 51.961540 89.504967 1.495031 +v 57.157692 86.500000 -1.500000 +v 62.353844 83.500000 -1.500000 +v 62.347389 89.503723 1.496273 +v 46.765381 89.507454 -1.500000 +v 57.157688 89.507454 -1.500000 +v 36.373077 89.507446 -1.500000 +v 46.765381 89.507446 -1.500000 +v 57.157692 89.507446 -1.500000 +v 36.373077 47.492599 0.003700 +v 46.765385 47.492599 0.003700 +v 57.157692 47.492599 0.003700 + +f 1 2 96 +f 3 4 97 +f 4 1 97 +f 6 98 5 +f 6 3 98 +f 7 8 12 +f 8 1 12 +f 1 9 12 +f 9 10 12 +f 10 11 12 +f 11 7 12 +f 13 14 18 +f 14 3 18 +f 3 15 18 +f 15 16 18 +f 16 17 18 +f 17 13 18 +f 19 20 22 +f 20 5 22 +f 21 19 22 +f 23 24 27 +f 24 25 27 +f 25 26 27 +f 28 29 34 +f 29 30 34 +f 30 31 34 +f 31 32 34 +f 32 33 34 +f 33 28 34 +f 35 36 41 +f 36 37 41 +f 37 38 41 +f 38 39 41 +f 39 40 41 +f 40 35 41 +f 42 43 48 +f 43 44 48 +f 44 45 48 +f 45 46 48 +f 46 47 48 +f 47 42 48 +f 49 50 55 +f 50 51 55 +f 51 52 55 +f 52 53 55 +f 53 54 55 +f 54 49 55 +f 56 57 60 +f 57 58 60 +f 59 56 60 +f 61 62 65 +f 62 63 65 +f 63 64 65 +f 66 67 72 +f 67 68 72 +f 68 69 72 +f 69 70 72 +f 70 71 72 +f 71 66 72 +f 73 74 79 +f 74 75 79 +f 75 76 79 +f 76 77 79 +f 77 78 79 +f 78 73 79 +f 80 81 83 +f 81 82 83 +f 82 91 83 +f 84 85 87 +f 85 86 87 +f 86 92 87 +f 88 89 90 +f 83 93 80 +f 87 94 84 +f 90 95 88 diff --git a/demo/models/surface_pattern_v02.obj b/demo/models/surface_pattern_v02.obj new file mode 100644 index 0000000..e153ed6 --- /dev/null +++ b/demo/models/surface_pattern_v02.obj @@ -0,0 +1,250 @@ +# WaveFront *.obj file (generated by CINEMA 4D) + +g Plane_2 +v 1315.930042 2533.151253 120.777515 +v 731.359001 2533.151253 0 +v -427.551489 2533.151253 0 +v 154.778338 2533.151253 120.777515 +v -1012.032694 2533.151253 120.777515 +v 1315.92994 2533.151253 120.777515 +v -1590.689836 1678.225832 94.229274 +v -1012.032796 1678.225832 157.523187 +v -427.55154 1678.225832 94.229274 +v 154.778235 1678.225832 157.523187 +v 731.358898 1678.225832 94.229274 +v 1315.92994 1678.225832 157.523187 +v -1590.689836 810.079751 0 +v -1012.032796 810.079751 120.777515 +v -427.55154 810.079751 0 +v 154.778235 810.079751 120.777515 +v 731.358898 810.079751 0 +v 1315.92994 810.079751 120.777515 +v -1590.689836 -58.06633 94.229274 +v -1012.032796 -58.06633 157.523187 +v -427.55154 -58.06633 94.229274 +v 154.778235 -58.06633 157.523187 +v 731.358898 -58.06633 94.229274 +v 1315.92994 -58.06633 157.523187 +v -1590.689836 -929.240781 0 +v -1012.032796 -929.240781 120.777515 +v -427.55154 -929.996013 0 +v 154.778235 -929.240781 120.777515 +v 731.358898 -929.240781 0 +v 1315.92994 -929.240781 120.777515 +v 1315.92994 -929.240781 120.777515 +v 1315.92994 -929.240781 120.777515 +v 1315.92994 -929.240781 120.777515 +v 1315.92994 -929.240781 120.777515 +v 1315.92994 -929.240781 120.777515 +v 1315.92994 -929.240781 120.777515 +v -1590.689836 -1803.293408 94.229274 +v -1012.032796 -1803.293408 157.523187 +v -427.55154 -1803.293408 94.229274 +v 154.778235 -1803.293408 157.523187 +v 731.358898 -1803.293408 94.229274 +v 1315.92994 -1803.293408 157.523187 +v -427.55154 1367.329985 0 +v -1590.689836 1974.544079 0 +v -427.55154 1986.607668 0 +v 731.358898 1367.329985 0 +v 731.358898 1988.163735 0 +v 154.778235 2244.138997 0 +v 1315.92994 2244.138997 0 +v -1012.032796 2252.046797 0 +v -1012.032796 1115.71757 0 +v 154.778235 1119.336098 0 +v 1315.92994 1112.099043 0 +v -427.55154 254.50799 0 +v 731.358898 243.652407 0 +v 1315.92994 504.186398 0 +v 154.778235 496.949343 0 +v -1012.032796 507.804926 0 +v -1590.689836 255.677565 0 +v 1315.92994 -630.008096 0 +v 731.358898 -367.878765 0 +v -427.55154 -367.878765 0 +v -1590.689836 -354.913145 0 +v 154.778235 -624.794228 0 +v -1012.032796 -1236.3254 0 +v -1012.032796 -617.557172 0 +v -427.55154 -1492.875613 0 +v 154.778235 -1233.431212 0 +v 1315.92994 -1234.216769 0 +v 731.358898 -1486.623941 0 +v 731.358898 -1486.623941 0 +v 731.358898 -1486.623941 0 +v 731.358898 -1486.623941 0 +v 731.358898 -1486.623941 0 +v 731.358898 -1486.623941 0 +v 731.358898 -1486.623941 0 +v 731.358898 -1486.623941 0 +v 731.358898 -1486.623941 0 +v -1590.689836 -1496.890407 0 +v -1590.689836 1373.417683 0 +v 731.359001 3706.233193 0 +v 1315.930042 3966.767184 0 +v 154.778338 3959.530129 0 +v -1012.032694 3970.385712 0 +v -1590.689733 3718.258351 0 +v -427.551437 3717.088776 0 +v 1315.930042 2832.57269 0 +v 731.359001 3094.702021 0 +v -427.551437 3094.702021 0 +v -1590.689733 3107.667641 0 +v 154.778338 2837.786558 0 +v -1012.032694 2845.023613 0 +v -1590.689733 4272.660537 0 +v -1012.032694 4272.660537 120.777515 +v -427.551437 4272.660537 0 +v 154.778338 4272.660537 120.777515 +v 731.359001 4272.660537 0 +v 1315.930042 4272.660537 120.777515 +v -1590.689733 3404.514456 94.229274 +v -1012.032694 3404.514456 157.523187 +v -427.551437 3404.514456 94.229274 +v 154.778338 3404.514456 157.523187 +v 731.359001 3404.514456 94.229274 +v 1315.930042 3404.514456 157.523187 +v -1590.689733 2533.151253 0 + +f 8/17 7/16 44/68 +f 3/10 45/69 8/17 +f 10/25 9/18 45/69 +f 2/3 47/71 10/20 +f 12/27 47/71 2/3 +f 8/17 51/75 13/28 +f 8/17 15/30 51/75 +f 15/30 10/24 52/77 +f 52/76 10/21 17/32 +f 12/27 53/78 17/32 +f 58/83 20/35 13/28 +f 15/30 54/79 20/35 +f 22/37 21/36 54/79 +f 17/32 22/37 57/82 +f 17/32 24/39 55/80 +f 20/35 63/88 19/34 +f 62/87 27/51 20/35 +f 64/89 28/52 27/50 +f 23/38 61/86 22/37 +f 60/85 30/54 29/53 +f 26/41 65/90 25/40 +f 65/90 26/41 27/49 +f 27/48 62/87 22/37 +f 29/53 70/96 40/64 +f 30/54 69/95 29/53 +f 17/32 55/80 22/37 +f 46/70 11/26 12/27 +f 27/47 26/41 66/91 +f 27/46 38/62 65/90 +f 17/32 18/33 56/81 +f 10/23 46/70 17/32 +f 10/20 3/10 48/72 +f 2/3 6/15 49/73 +f 10/20 48/72 2/3 +f 10/19 43/67 9/18 +f 20/35 58/83 15/30 +f 8/17 50/74 3/10 +f 13/28 80/106 8/17 +f 8/17 9/18 43/67 +f 105/132 5/14 50/74 +f 43/67 15/30 8/17 +f 44/68 105/132 8/17 +f 45/69 9/18 8/17 +f 45/69 3/10 10/22 +f 10/21 11/26 46/70 +f 47/71 11/26 10/20 +f 12/27 11/26 47/71 +f 48/72 4/12 2/3 +f 49/73 12/27 2/3 +f 3/10 4/12 48/72 +f 50/74 5/14 3/10 +f 50/74 8/17 105/132 +f 10/19 15/30 43/67 +f 12/27 17/32 46/70 +f 51/75 14/29 13/28 +f 15/30 14/29 51/75 +f 52/77 16/31 15/30 +f 17/32 16/31 52/76 +f 53/78 18/33 17/32 +f 15/30 16/31 57/82 +f 54/79 21/36 20/35 +f 55/80 23/38 22/37 +f 24/39 23/38 55/80 +f 56/81 24/39 17/32 +f 57/82 22/37 15/30 +f 57/82 16/31 17/32 +f 22/37 54/79 15/30 +f 14/29 58/83 13/28 +f 58/83 14/29 15/30 +f 20/35 19/34 59/84 +f 59/84 13/28 20/35 +f 29/53 64/89 22/37 +f 29/53 24/39 60/85 +f 61/86 23/38 24/39 +f 61/86 29/53 22/37 +f 24/39 29/53 61/86 +f 21/36 62/87 20/35 +f 62/87 21/36 22/37 +f 20/35 27/45 66/91 +f 66/91 26/41 25/40 +f 65/90 38/62 25/40 +f 27/44 67/92 38/62 +f 67/93 40/64 39/63 +f 27/43 22/37 64/89 +f 25/40 20/35 66/91 +f 29/53 28/52 64/89 +f 38/62 37/61 79/105 +f 67/93 27/42 40/64 +f 67/92 39/63 38/62 +f 27/42 28/52 68/94 +f 29/53 68/94 28/52 +f 68/94 40/64 27/42 +f 40/64 68/94 29/53 +f 29/53 42/66 70/96 +f 69/95 42/66 29/53 +f 70/96 41/65 40/64 +f 42/66 41/65 70/96 +f 79/105 25/40 38/62 +f 25/40 63/88 20/35 +f 80/106 7/16 8/17 +f 100/126 84/110 95/121 +f 82/108 104/130 97/123 +f 83/109 102/128 95/121 +f 83/109 96/122 97/123 +f 95/121 96/122 83/109 +f 102/128 86/112 95/121 +f 94/120 84/110 93/119 +f 84/110 94/120 95/121 +f 100/126 99/125 85/111 +f 85/111 93/119 100/126 +f 84/110 100/126 93/119 +f 95/121 86/112 100/126 +f 102/128 101/127 86/112 +f 97/123 102/128 83/109 +f 97/123 104/130 81/107 +f 100/126 90/116 99/125 +f 89/115 3/9 100/126 +f 91/117 4/11 3/8 +f 103/129 88/114 102/128 +f 87/113 1/1 2/2 +f 104/130 2/2 88/114 +f 101/127 89/115 100/126 +f 3/7 89/115 102/128 +f 89/115 101/127 102/128 +f 100/126 3/6 92/118 +f 92/118 5/13 105/131 +f 3/5 102/128 91/117 +f 105/131 100/126 92/118 +f 2/2 4/11 91/117 +f 105/131 90/116 100/126 +f 97/123 81/107 102/128 +f 2/2 91/117 102/128 +f 3/4 5/13 92/118 +f 2/2 104/130 87/113 +f 97/123 98/124 82/108 +f 88/114 103/129 104/130 +f 86/112 101/127 100/126 +f 81/107 103/129 102/128 +f 104/130 103/129 81/107 +f 88/114 2/2 102/128 + diff --git a/examples/shader-effect/refraction-effect-example.cpp b/examples/shader-effect/refraction-effect-example.cpp new file mode 100644 index 0000000..e9a1a9c --- /dev/null +++ b/examples/shader-effect/refraction-effect-example.cpp @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include "../shared/view.h" + +#include +#include + +using namespace Dali; + +namespace +{ +const char * const APPLICATION_TITLE( "Refraction Effect" ); +const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" ); +const char * const CHANGE_TEXTURE_ICON( DALI_IMAGE_DIR "icon-change.png" ); +const char * const CHANGE_MESH_ICON( DALI_IMAGE_DIR "icon-replace.png" ); + +const char* MESH_FILES[] = +{ + DALI_MODEL_DIR "surface_pattern_v01.obj", + DALI_MODEL_DIR "surface_pattern_v02.obj" +}; +const unsigned int NUM_MESH_FILES( sizeof( MESH_FILES ) / sizeof( MESH_FILES[0] ) ); + +const char* TEXTURE_IMAGES[]= +{ + DALI_IMAGE_DIR "background-1.jpg", + DALI_IMAGE_DIR "background-2.jpg", + DALI_IMAGE_DIR "background-3.jpg", + DALI_IMAGE_DIR "background-4.jpg" +}; +const unsigned int NUM_TEXTURE_IMAGES( sizeof( TEXTURE_IMAGES ) / sizeof( TEXTURE_IMAGES[0] ) ); + +#define MAKE_SHADER(A)#A + +struct LightOffsetConstraint +{ + LightOffsetConstraint( float radius ) + : mRadius( radius ) + { + } + + Vector2 operator()( const Vector2& current, const PropertyInput& spinAngleProperty) + { + float spinAngle = spinAngleProperty.GetFloat(); + return Vector2( cos(spinAngle ), sin( spinAngle ) ) * mRadius; + } + + float mRadius; +}; + +} // namespace + +/************************************************************************************************ + *** This shader is used when the MeshActor is not touched*** + ************************************************************************************************/ +class NoEffect : public ShaderEffect +{ +public: + /** + * Create an empty handle. + */ + NoEffect() + { + } + + /** + * Virtual destructor + */ + virtual ~NoEffect() + { + } + + /** + * Create a NoEffect object. + * @return A handle to a newly allocated NoEffect + */ + static NoEffect New() + { + std::string vertexShader = MAKE_SHADER( + uniform mediump vec4 uTextureRect;\n + void main()\n + {\n + gl_Position = uMvpMatrix * vec4( aPosition.xy, 0.0, 1.0 );\n + vTexCoord = aTexCoord.xy;\n + }\n + ); + std::string fragmentShader = MAKE_SHADER( + void main()\n + {\n + gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n + }\n + ); + ShaderEffect shaderEffect = ShaderEffect::New( vertexShader, fragmentShader, + GeometryType( GEOMETRY_TYPE_TEXTURED_MESH), + ShaderEffect::GeometryHints( ShaderEffect::HINT_NONE ) ); + NoEffect handle( shaderEffect ); + return handle; + } + +private: + /** + * Helper for New() + */ + NoEffect( ShaderEffect handle ) + : ShaderEffect( handle ) + { + } +}; + +/************************************************************/ +/* Custom refraction effect shader******************************/ +/************************************************************/ + +class RefractionEffect : public ShaderEffect +{ +public: + + /** + * Create an empty RefractionEffect handle. + */ + RefractionEffect() + { + } + + /** + * Virtual destructor + */ + virtual ~RefractionEffect() + { + } + + /** + * Create a RefractionEffect object. + * @return A handle to a newly allocated RefractionEffect + */ + static RefractionEffect New() + { + std::string vertexShader = MAKE_SHADER( + varying mediump vec2 vTextureOffset;\n + void main()\n + {\n + gl_Position = uMvpMatrix * vec4( aPosition.xy, 0.0, 1.0 );\n + vTexCoord = aTexCoord.xy;\n + + vNormal = aNormal;\n + vVertex = vec4( aPosition, 1.0 );\n + float length = max(0.01, length(aNormal.xy)) * 40.0;\n + vTextureOffset = aNormal.xy / length;\n + }\n + ); + + std::string fragmentShader = MAKE_SHADER( + uniform mediump float uEffectStrength;\n + uniform mediump vec3 uLightPosition;\n + uniform mediump vec2 uLightXYOffset;\n + uniform mediump vec2 uLightSpinOffset;\n + uniform mediump float uLightIntensity;\n + varying mediump vec2 vTextureOffset;\n + + vec3 rgb2hsl(vec3 rgb)\n + {\n + float epsilon = 1.0e-10;\n + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n + vec4 P = mix(vec4(rgb.bg, K.wz), vec4(rgb.gb, K.xy), step(rgb.b, rgb.g));\n + vec4 Q = mix(vec4(P.xyw, rgb.r), vec4(rgb.r, P.yzx), step(P.x, rgb.r));\n + \n + // RGB -> HCV + float value = Q.x;\n + float chroma = Q.x - min(Q.w, Q.y);\n + float hue = abs(Q.z + (Q.w-Q.y) / (6.0*chroma+epsilon));\n + // HCV -> HSL + float lightness = value - chroma*0.5;\n + return vec3( hue, chroma/max( 1.0-abs(lightness*2.0-1.0), 1.0e-1 ), lightness );\n + }\n + + vec3 hsl2rgb( vec3 hsl ) + { + // pure hue->RGB + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n + vec3 p = abs(fract(hsl.xxx + K.xyz) * 6.0 - K.www);\n + vec3 RGB = clamp(p - K.xxx, 0.0, 1.0);\n + \n + float chroma = ( 1.0 - abs( hsl.z*2.0-1.0 ) ) * hsl.y;\n + return ( RGB - 0.5 ) * chroma + hsl.z; + } + + void main()\n + {\n + vec3 normal = normalize( vNormal);\n + + vec3 lightPosition = uLightPosition + vec3(uLightXYOffset+uLightSpinOffset, 0.f);\n + mediump vec3 vecToLight = normalize( (lightPosition - vVertex.xyz) * 0.01 );\n + mediump float spotEffect = pow( max(0.05, vecToLight.z ) - 0.05, 8.0);\n + + spotEffect = spotEffect * uEffectStrength;\n + mediump float lightDiffuse = ( ( dot( vecToLight, normal )-0.75 ) *uLightIntensity ) * spotEffect;\n + + lowp vec4 color = texture2D( sTexture, vTexCoord + vTextureOffset * spotEffect );\n + vec3 lightedColor = hsl2rgb( rgb2hsl(color.rgb) + vec3(0.0,0.0,lightDiffuse) );\n + + gl_FragColor = vec4( lightedColor, color.a ) * uColor;\n + }\n + ); + + ShaderEffect shaderEffect = ShaderEffect::New( vertexShader, fragmentShader, + GeometryType( GEOMETRY_TYPE_TEXTURED_MESH), + ShaderEffect::GeometryHints( ShaderEffect::HINT_BLENDING ) ); + RefractionEffect handle( shaderEffect ); + + Vector2 stageSize = Stage::GetCurrent().GetSize(); + handle.SetLightPosition( Vector2(stageSize.x, 0.f) ); + handle.SetUniform( "uLightXYOffset", Vector2::ZERO ); + handle.SetUniform( "uLightSpinOffset", Vector2::ZERO ); + handle.SetUniform( "uEffectStrength", 0.f ); + handle.SetUniform( "uLightIntensity", 2.5f ); + + Property::Index index = handle.RegisterProperty( "uSpinAngle", 0.f ); + Constraint constraint = Constraint::New( handle.GetPropertyIndex("uLightSpinOffset"), + LocalSource(index), + LightOffsetConstraint(stageSize.x*0.1f)); + handle.ApplyConstraint( constraint ); + + return handle; + } + + void SetLightPosition( const Vector2& position ) + { + Vector2 stageHalfSize = Stage::GetCurrent().GetSize() * 0.5f; + SetUniform( "uLightPosition", Vector3( position.x - stageHalfSize.x, position.y - stageHalfSize.y, stageHalfSize.x ) ); + } + + void SetLightXYOffset( const Vector2& offset ) + { + SetUniform( "uLightXYOffset", offset ); + } + + void SetEffectStrength( float strength ) + { + SetUniform( "uEffectStrength", strength ); + } + + void SetLightIntensity( float intensity ) + { + SetUniform( "uLightIntensity", intensity ); + } + +private: + /** + * Helper for New() + */ + RefractionEffect( ShaderEffect handle ) + : ShaderEffect( handle ) + { + } +}; + +/*************************************************/ +/*Demo using RefractionEffect*****************/ +/*************************************************/ +class RefractionEffectExample : public ConnectionTracker +{ +public: + RefractionEffectExample( Application &application ) + : mApplication( application ), + mIsDown( false ), + mCurrentTextureId( 1 ), + mCurrentMeshId( 0 ) + { + // Connect to the Application's Init signal + application.InitSignal().Connect(this, &RefractionEffectExample::Create); + } + + ~RefractionEffectExample() + { + } + +private: + + // The Init signal is received once (only) during the Application lifetime + void Create(Application& application) + { + Stage stage = Stage::GetCurrent(); + mStageHalfSize = stage.GetSize() * 0.5f; + + stage.KeyEventSignal().Connect(this, &RefractionEffectExample::OnKeyEvent); + + // Creates a default view with a default tool bar. + // The view is added to the stage. + Toolkit::ToolBar toolBar; + Toolkit::View view; + mContent = DemoHelper::CreateView( application, + view, + toolBar, + "", + TOOLBAR_IMAGE, + APPLICATION_TITLE ); + + // Add a button to change background. (right of toolbar) + mChangeTextureButton = Toolkit::PushButton::New(); + mChangeTextureButton.SetBackgroundImage( Image::New( CHANGE_TEXTURE_ICON ) ); + mChangeTextureButton.ClickedSignal().Connect( this, &RefractionEffectExample::OnChangeTexture ); + toolBar.AddControl( mChangeTextureButton, + DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, + Toolkit::Alignment::HorizontalRight, + DemoHelper::DEFAULT_MODE_SWITCH_PADDING ); + // Add a button to change mesh pattern. ( left of bar ) + mChangeMeshButton = Toolkit::PushButton::New(); + mChangeMeshButton.SetBackgroundImage( Image::New( CHANGE_MESH_ICON ) ); + mChangeMeshButton.ClickedSignal().Connect( this, &RefractionEffectExample::OnChangeMesh ); + toolBar.AddControl( mChangeMeshButton, + DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, + Toolkit::Alignment::HorizontalLeft, + DemoHelper::DEFAULT_MODE_SWITCH_PADDING ); + + // creates the shader effects applied on the mesh actor + mRefractionEffect = RefractionEffect::New(); // used when the finger is touching the screen + mNoEffect = NoEffect::New(); // used in the other situations, basic render shader + // Create the mesh from the obj file and add to stage + mMaterial = Material::New( "Material" ) ; + mMaterial.SetDiffuseTexture(Image::New(TEXTURE_IMAGES[mCurrentTextureId])); + CreateSurface( MESH_FILES[mCurrentMeshId] ); + + // Connect the callback to the touch signal on the mesh actor + mContent.TouchedSignal().Connect( this, &RefractionEffectExample::OnTouch ); + + // the animation which spin the light around the finger touch position + mLightPosition = Vector2( mStageHalfSize.x*2.f, 0.f); + mLightAnimation = Animation::New(2.f); + mLightAnimation.AnimateTo( Property( mRefractionEffect, "uSpinAngle" ), Math::PI*2.f ); + mLightAnimation.SetLooping( true ); + mLightAnimation.Pause(); + } + + /** + * Create a mesh actor with different geometry to replace the current one + */ + bool OnChangeMesh( Toolkit::Button button ) + { + if( mMeshActor ) + { + UnparentAndReset( mMeshActor ); + } + + mCurrentMeshId = ( mCurrentMeshId + 1 ) % NUM_MESH_FILES; + CreateSurface( MESH_FILES[mCurrentMeshId] ); + + return true; + } + + bool OnChangeTexture( Toolkit::Button button ) + { + mCurrentTextureId = ( mCurrentTextureId + 1 ) % NUM_TEXTURE_IMAGES; + mMaterial.SetDiffuseTexture(Image::New(TEXTURE_IMAGES[mCurrentTextureId])); + + return true; + } + + bool OnTouch( Actor actor , const TouchEvent& event ) + { + const TouchPoint &point = event.GetPoint(0); + + switch(point.state) + { + case TouchPoint::Down: + { + mIsDown = true; + mDownPosition = point.screen; + + mLightAnimation.Play(); + + if( mStrenghAnimation ) + { + mStrenghAnimation.Clear(); + } + + mRefractionEffect.SetLightXYOffset( point.screen - mLightPosition ); + mMeshActor.SetShaderEffect( mRefractionEffect ); + mStrenghAnimation= Animation::New(0.5f); + mStrenghAnimation.AnimateTo( Property( mRefractionEffect, "uEffectStrength" ), 1.f ); + mStrenghAnimation.Play(); + + break; + } + case TouchPoint::Motion: + { + if(mIsDown) + { + // make the light position following the finger movement + mRefractionEffect.SetLightXYOffset( point.screen - mLightPosition ); + } + break; + } + case TouchPoint::Up: + case TouchPoint::Leave: + case TouchPoint::Interrupted: + { + if(mIsDown) + { + mLightAnimation.Pause(); + + if( mStrenghAnimation ) + { + mStrenghAnimation.Clear(); + } + mStrenghAnimation = Animation::New(0.5f); + mStrenghAnimation.AnimateTo( Property( mRefractionEffect, "uEffectStrength" ), 0.f ); + mStrenghAnimation.FinishedSignal().Connect( this, &RefractionEffectExample::OnTouchFinished ); + mStrenghAnimation.Play(); + } + + mIsDown = false; + break; + } + case TouchPoint::Stationary: + case TouchPoint::Last: + default: + { + break; + } + } + return true; + } + + void OnTouchFinished( Animation& source ) + { + mMeshActor.SetShaderEffect( mNoEffect ); + mRefractionEffect.SetLightXYOffset( Vector2::ZERO ); + } + + void CreateSurface( const std::string& objFileName ) + { + MeshData::VertexContainer vertices; + MeshData::FaceIndices faces; + MeshData meshData; + + std::vector boundingBox; + std::vector vertexPositions; + std::vector faceIndices; + // read the vertice and faces from the .obj file, and record the bounding box + ReadObjFile( objFileName, boundingBox, vertexPositions, faceIndices ); + + std::vector textureCoordinates; + // align the mesh, scale it to fit the screen size, and calculate the texture coordinate for each vertex + ShapeResizeAndTexureCoordinateCalculation( boundingBox, vertexPositions, textureCoordinates ); + + // re-organize the mesh, the vertices are duplicated, each vertex only belongs to one triangle. + // Without sharing vertex between triangle, so we can manipulate the texture offset on each triangle conveniently. + for( std::size_t i=0; i 0 ) + { + faces.push_back( i ); + faces.push_back( i+1 ); + faces.push_back( i+2 ); + } + else + { + normal *= -1.f; + faces.push_back( i ); + faces.push_back( i+2 ); + faces.push_back( i+1 ); + } + + vertices.push_back( MeshData::Vertex( vertexPositions[ faceIndices[i] ], textureCoordinates[ faceIndices[i] ], normal ) ); + vertices.push_back( MeshData::Vertex( vertexPositions[ faceIndices[i+1] ], textureCoordinates[ faceIndices[i+1] ], normal ) ); + vertices.push_back( MeshData::Vertex( vertexPositions[ faceIndices[i+2] ], textureCoordinates[ faceIndices[i+2] ], normal ) ); + + } + + // Now ready to construct the mesh actor + meshData.SetMaterial( mMaterial ); + meshData.SetVertices( vertices ); + meshData.SetFaceIndices( faces ); + meshData.SetHasTextureCoords(true); + meshData.SetHasNormals(true); + mMeshActor = MeshActor::New( Mesh::New( meshData ) ); + mMeshActor.SetParentOrigin(ParentOrigin::CENTER); + mMeshActor.SetAffectedByLighting( false ); + mMeshActor.SetShaderEffect( mNoEffect ); + mContent.Add( mMeshActor ); + } + + void ReadObjFile( const std::string& objFileName, + std::vector& boundingBox, + std::vector& vertexPositions, + std::vector& faceIndices) + { + std::ifstream ifs( objFileName.c_str(), std::ios::in ); + + boundingBox.resize( 6 ); + boundingBox[0]=boundingBox[2]=boundingBox[4] = std::numeric_limits::max(); + boundingBox[1]=boundingBox[3]=boundingBox[5] = -std::numeric_limits::max(); + + std::string line; + while( std::getline( ifs, line ) ) + { + if( line[0] == 'v' && std::isspace(line[1])) // vertex + { + std::istringstream iss(line.substr(2), std::istringstream::in); + unsigned int i = 0; + Vector3 vertex; + while( iss >> vertex[i++] && i < 3); + if( vertex.x < boundingBox[0] ) boundingBox[0] = vertex.x; + if( vertex.x > boundingBox[1] ) boundingBox[1] = vertex.x; + if( vertex.y < boundingBox[2] ) boundingBox[2] = vertex.y; + if( vertex.y > boundingBox[3] ) boundingBox[3] = vertex.y; + if( vertex.z < boundingBox[4] ) boundingBox[4] = vertex.z; + if( vertex.z > boundingBox[5] ) boundingBox[5] = vertex.z; + vertexPositions.push_back( vertex ); + } + else if( line[0] == 'f' ) //face + { + unsigned int numOfInt = 3; + while( true ) + { + std::size_t found = line.find('/'); + if( found == std::string::npos ) + { + break; + } + line[found] = ' '; + numOfInt++; + } + + std::istringstream iss(line.substr(2), std::istringstream::in); + int indices[ numOfInt ]; + unsigned int i=0; + while( iss >> indices[i++] && i < numOfInt); + unsigned int step = (i+1) / 3; + faceIndices.push_back( indices[0]-1 ); + faceIndices.push_back( indices[step]-1 ); + faceIndices.push_back( indices[2*step]-1 ); + } + } + + ifs.close(); + } + + void ShapeResizeAndTexureCoordinateCalculation( const std::vector& boundingBox, + std::vector& vertexPositions, + std::vector& textureCoordinates) + { + Vector3 bBoxSize( boundingBox[1] - boundingBox[0], boundingBox[3] - boundingBox[2], boundingBox[5] - boundingBox[4]); + Vector3 bBoxMinCorner( boundingBox[0], boundingBox[2], boundingBox[4] ); + + Vector2 stageSize = Stage::GetCurrent().GetSize(); + Vector3 scale( stageSize.x / bBoxSize.x, stageSize.y / bBoxSize.y, 1.f ); + scale.z = (scale.x + scale.y)/2.f; + + for( std::vector::iterator iter = vertexPositions.begin(); iter != vertexPositions.end(); iter++ ) + { + Vector3 newPosition( (*iter) - bBoxMinCorner ) ; + + Vector2 textureCoord( newPosition.x / bBoxSize.x, newPosition.y / bBoxSize.y ); + textureCoordinates.push_back( textureCoord ); + + newPosition -= bBoxSize * 0.5f; + (*iter) = newPosition * scale; + } + } + + /** + * Main key event handler + */ + void OnKeyEvent(const KeyEvent& event) + { + if(event.state == KeyEvent::Down) + { + if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) ) + { + mApplication.Quit(); + } + } + } + +private: + + Application& mApplication; + Layer mContent; + + bool mIsDown; + Vector2 mDownPosition; + Vector2 mLightPosition; + Vector2 mStageHalfSize; + + Material mMaterial; + MeshActor mMeshActor; + + RefractionEffect mRefractionEffect; + NoEffect mNoEffect; + Animation mLightAnimation; + Animation mStrenghAnimation; + + Toolkit::PushButton mChangeTextureButton; + Toolkit::PushButton mChangeMeshButton; + unsigned int mCurrentTextureId; + unsigned int mCurrentMeshId; +}; + +/*****************************************************************************/ + +static void +RunTest(Application& app) +{ + RefractionEffectExample theApp(app); + app.MainLoop(); +} + +/*****************************************************************************/ + +int +main(int argc, char **argv) +{ + Application app = Application::New(&argc, &argv); + + RunTest(app); + + return 0; +}