4a6f7a30174b2fd73606655306219a6075df4114
[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 #include <dali/integration-api/debug.h>
24 #include <dali/devel-api/adaptor-framework/file-loader.h>
25
26 using namespace Dali;
27 using Dali::Toolkit::TextLabel;
28 using Dali::Toolkit::Control;
29 using Dali::Toolkit::ToolBar;
30
31 const char* BACKGROUND_IMAGE( "" );
32 const char* TOOLBAR_IMAGE( DEMO_IMAGE_DIR "top-bar.png" );
33 const char* APPLICATION_TITLE( "Ray Marching" );
34 const char* SHADER_NAME("raymarch_sphere_shaded");
35
36 /**
37  * @brief LoadShaderCode
38  * @param filename
39  * @param output
40  * @return
41  */
42 bool LoadShaderCode( const char* path, const char* filename, std::vector<char>& output )
43 {
44   std::string fullpath( path );
45   fullpath += filename;
46
47   std::streampos bufferSize = 0;
48   Dali::Vector<char> fileBuffer;
49   if( !Dali::FileLoader::ReadFile( fullpath, bufferSize, fileBuffer, Dali::FileLoader::FileType::BINARY ) )
50   {
51     return false;
52   }
53
54   FILE* file = fmemopen( &fileBuffer[0], bufferSize, "rb" );
55
56   bool retValue = false;
57   if( ! fseek( file, 0, SEEK_END ) )
58   {
59     long int size = ftell( file );
60
61     if( ( size != -1L ) &&
62         ( ! fseek( file, 0, SEEK_SET ) ) )
63     {
64       output.resize( size + 1 );
65       std::fill( output.begin(), output.end(), 0 );
66       ssize_t result = fread( output.data(), size, 1, file );
67
68       retValue = ( result >= 0 );
69     }
70   }
71
72   fclose( file );
73   return retValue;
74 }
75
76 /**
77  * @brief LoadShaders
78  * @param shaderName
79  * @return
80  */
81 Shader LoadShaders( const std::string& shaderName )
82 {
83   std::vector<char> bufV, bufF;
84   std::string shaderVSH( shaderName );
85   std::string shaderFSH( shaderName );
86   shaderVSH += ".vsh";
87   shaderFSH += ".fsh";
88
89   Shader shader;
90   if( LoadShaderCode( DEMO_SHADER_DIR, shaderVSH.c_str(), bufV ) &&
91       LoadShaderCode( DEMO_SHADER_DIR, shaderFSH.c_str(), bufF ) )
92   {
93     shader = Shader::New( bufV.data(), bufF.data() );
94   }
95   return shader;
96 }
97
98 // This example shows how to create a Ray Marching using a shader
99 //
100 class RayMarchingExample : public ConnectionTracker
101 {
102 public:
103
104   RayMarchingExample( Application& application )
105   : mApplication( application )
106   {
107     // Connect to the Application's Init signal
108     mApplication.InitSignal().Connect( this, &RayMarchingExample::Create );
109   }
110
111   ~RayMarchingExample()
112   {
113     // Nothing to do here;
114   }
115
116   // The Init signal is received once (only) during the Application lifetime
117   void Create( Application& application )
118   {
119     // Get a handle to the stage
120     Stage stage = Stage::GetCurrent();
121
122     stage.GetRootLayer().TouchSignal().Connect( this, &RayMarchingExample::OnTouch );
123
124     stage.KeyEventSignal().Connect(this, &RayMarchingExample::OnKeyEvent);
125
126     stage.SetBackgroundColor( Color::YELLOW );
127
128     // Hide the indicator bar
129     application.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
130
131     // Creates a default view with a default tool bar.
132     // The view is added to the stage.
133     mContentLayer = DemoHelper::CreateView( application,
134                                             mView,
135                                             mToolBar,
136                                             BACKGROUND_IMAGE,
137                                             TOOLBAR_IMAGE,
138                                             APPLICATION_TITLE );
139
140     // Add an extra space on the right to center the title text.
141     mToolBar.AddControl( Actor::New(), DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight );
142
143     AddContentLayer();
144
145   }
146   bool OnTouch( Actor actor, const TouchData& touch )
147   {
148     // quit the application
149     mApplication.Quit();
150     return true;
151   }
152
153   /**
154    * Main key event handler
155    */
156   void OnKeyEvent(const KeyEvent& event)
157   {
158     if(event.state == KeyEvent::Down)
159     {
160       if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
161       {
162         mApplication.Quit();
163       }
164     }
165   }
166
167   /**
168    * Creates quad renderer
169    */
170   Renderer CreateQuadRenderer()
171   {
172     // Create shader & geometry needed by Renderer
173     Shader shader = LoadShaders( SHADER_NAME );
174
175     Property::Map vertexFormat;
176     vertexFormat["aPosition"] = Property::VECTOR2;
177     PropertyBuffer vertexBuffer = PropertyBuffer::New( vertexFormat );
178
179     const float P( 0.5f );
180     const Vector2 vertices[] = {
181       Vector2( -P, -P ),
182       Vector2( +P, -P ),
183       Vector2( -P, +P ),
184       Vector2( +P, +P )
185     };
186
187     vertexBuffer.SetData( vertices, 4 );
188
189     // Instantiate quad geometry
190     Geometry geometry = Geometry::New();
191     geometry.AddVertexBuffer( vertexBuffer );
192     geometry.SetType( Geometry::TRIANGLE_STRIP );
193
194     // Create renderer
195     Renderer renderer = Renderer::New( geometry, shader );
196
197     renderer.RegisterProperty("uRadius", 0.0f );
198     renderer.RegisterProperty("uAdjuster", -4.0f );
199
200     //  Animate the sphere radius uniform and a generic uAdjust uniform currently used to move the light around
201     Animation animation = Animation::New(8.0f);
202     animation.AnimateTo( Property(renderer,"uRadius"), 1.2f, AlphaFunction::BOUNCE);
203     animation.AnimateTo( Property(renderer,"uAdjuster"), 4.0f, AlphaFunction::BOUNCE);
204     animation.SetLooping( true );
205     animation.Play();
206
207     return renderer;
208   }
209
210   void AddContentLayer()
211   {
212     Stage stage = Stage::GetCurrent();
213
214      //Create all the renderers
215     Renderer renderer = CreateQuadRenderer();
216
217     Actor actor = Actor::New();
218     actor.AddRenderer( renderer );
219
220     actor.SetAnchorPoint( Dali::AnchorPoint::CENTER );
221     actor.SetParentOrigin( Dali::ParentOrigin::CENTER );
222     actor.SetResizePolicy( Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS );
223
224     mContentLayer.Add( actor );
225   }
226
227 private:
228   Application&  mApplication;
229   Control mView;
230   Layer mContentLayer;
231   ToolBar mToolBar;
232 };
233
234 int DALI_EXPORT_API main( int argc, char **argv )
235 {
236   Application application = Application::New( &argc, &argv );
237   RayMarchingExample test( application );
238   application.MainLoop();
239   return 0;
240 }