Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-demo.git] / examples / ray-marching / ray-marching-example.cpp
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <dali-toolkit/dali-toolkit.h>
19 #include <dali-toolkit/devel-api/controls/tool-bar/tool-bar.h>
20 #include "shared/view.h"
21 #include "shared/utility.h"
22 #include <stdio.h>
23
24 using namespace Dali;
25 using Dali::Toolkit::TextLabel;
26 using Dali::Toolkit::Control;
27 using Dali::Toolkit::ToolBar;
28
29 const char* BACKGROUND_IMAGE( "" );
30 const char* TOOLBAR_IMAGE( DEMO_IMAGE_DIR "top-bar.png" );
31 const char* APPLICATION_TITLE( "Ray Marching" );
32 const char* SHADER_NAME("raymarch_sphere_shaded");
33
34 /**
35  * @brief LoadShaderCode
36  * @param filename
37  * @param output
38  * @return
39  */
40 bool LoadShaderCode( const char* path, const char* filename, std::vector<char>& output )
41 {
42   std::string fullpath( path );
43   fullpath += filename;
44   FILE* file = fopen( fullpath.c_str(), "rb" );
45   if( ! file )
46   {
47     return false;
48   }
49
50   bool retValue = false;
51   if( ! fseek( file, 0, SEEK_END ) )
52   {
53     long int size = ftell( file );
54
55     if( ( size != -1L ) &&
56         ( ! fseek( file, 0, SEEK_SET ) ) )
57     {
58       output.resize( size + 1 );
59       std::fill( output.begin(), output.end(), 0 );
60       ssize_t result = fread( output.data(), size, 1, file );
61
62       retValue = ( result >= 0 );
63     }
64   }
65
66   fclose( file );
67   return retValue;
68 }
69
70 /**
71  * @brief LoadShaders
72  * @param shaderName
73  * @return
74  */
75 Shader LoadShaders( const std::string& shaderName )
76 {
77   std::vector<char> bufV, bufF;
78   std::string shaderVSH( shaderName );
79   std::string shaderFSH( shaderName );
80   shaderVSH += ".vsh";
81   shaderFSH += ".fsh";
82
83   Shader shader;
84   if( LoadShaderCode( DEMO_SHADER_DIR, shaderVSH.c_str(), bufV ) &&
85       LoadShaderCode( DEMO_SHADER_DIR, shaderFSH.c_str(), bufF ) )
86   {
87     shader = Shader::New( bufV.data(), bufF.data() );
88   }
89   return shader;
90 }
91
92 // This example shows how to create a Ray Marching using a shader
93 //
94 class RayMarchingExample : public ConnectionTracker
95 {
96 public:
97
98   RayMarchingExample( Application& application )
99   : mApplication( application )
100   {
101     // Connect to the Application's Init signal
102     mApplication.InitSignal().Connect( this, &RayMarchingExample::Create );
103   }
104
105   ~RayMarchingExample()
106   {
107     // Nothing to do here;
108   }
109
110   // The Init signal is received once (only) during the Application lifetime
111   void Create( Application& application )
112   {
113     // Get a handle to the stage
114     Stage stage = Stage::GetCurrent();
115
116     stage.GetRootLayer().TouchSignal().Connect( this, &RayMarchingExample::OnTouch );
117
118     stage.KeyEventSignal().Connect(this, &RayMarchingExample::OnKeyEvent);
119
120     stage.SetBackgroundColor( Color::YELLOW );
121
122     // Hide the indicator bar
123     application.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
124
125     // Creates a default view with a default tool bar.
126     // The view is added to the stage.
127     mContentLayer = DemoHelper::CreateView( application,
128                                             mView,
129                                             mToolBar,
130                                             BACKGROUND_IMAGE,
131                                             TOOLBAR_IMAGE,
132                                             APPLICATION_TITLE );
133
134     // Add an extra space on the right to center the title text.
135     mToolBar.AddControl( Actor::New(), DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight );
136
137     AddContentLayer();
138
139   }
140   bool OnTouch( Actor actor, const TouchData& touch )
141   {
142     // quit the application
143     mApplication.Quit();
144     return true;
145   }
146
147   /**
148    * Main key event handler
149    */
150   void OnKeyEvent(const KeyEvent& event)
151   {
152     if(event.state == KeyEvent::Down)
153     {
154       if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
155       {
156         mApplication.Quit();
157       }
158     }
159   }
160
161   /**
162    * Creates quad renderer
163    */
164   Renderer CreateQuadRenderer()
165   {
166     // Create shader & geometry needed by Renderer
167     Shader shader = LoadShaders( SHADER_NAME );
168
169     Property::Map vertexFormat;
170     vertexFormat["aPosition"] = Property::VECTOR2;
171     PropertyBuffer vertexBuffer = PropertyBuffer::New( vertexFormat );
172
173     const float P( 0.5f );
174     const Vector2 vertices[] = {
175       Vector2( -P, -P ),
176       Vector2( +P, -P ),
177       Vector2( -P, +P ),
178       Vector2( +P, +P )
179     };
180
181     vertexBuffer.SetData( vertices, 4 );
182
183     // Instantiate quad geometry
184     Geometry geometry = Geometry::New();
185     geometry.AddVertexBuffer( vertexBuffer );
186     geometry.SetType( Geometry::TRIANGLE_STRIP );
187
188     // Create renderer
189     Renderer renderer = Renderer::New( geometry, shader );
190
191     renderer.RegisterProperty("uRadius", 0.0f );
192     renderer.RegisterProperty("uAdjuster", -4.0f );
193
194     //  Animate the sphere radius uniform and a generic uAdjust uniform currently used to move the light around
195     Animation animation = Animation::New(8.0f);
196     animation.AnimateTo( Property(renderer,"uRadius"), 1.2f, AlphaFunction::BOUNCE);
197     animation.AnimateTo( Property(renderer,"uAdjuster"), 4.0f, AlphaFunction::BOUNCE);
198     animation.SetLooping( true );
199     animation.Play();
200
201     return renderer;
202   }
203
204   void AddContentLayer()
205   {
206     Stage stage = Stage::GetCurrent();
207
208      //Create all the renderers
209     Renderer renderer = CreateQuadRenderer();
210
211     Actor actor = Actor::New();
212     actor.AddRenderer( renderer );
213
214     actor.SetAnchorPoint( Dali::AnchorPoint::CENTER );
215     actor.SetParentOrigin( Dali::ParentOrigin::CENTER );
216     actor.SetResizePolicy( Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS );
217
218     mContentLayer.Add( actor );
219   }
220
221 private:
222   Application&  mApplication;
223   Control mView;
224   Layer mContentLayer;
225   ToolBar mToolBar;
226 };
227
228 int DALI_EXPORT_API main( int argc, char **argv )
229 {
230   Application application = Application::New( &argc, &argv );
231   RayMarchingExample test( application );
232   application.MainLoop();
233   return 0;
234 }