Added Rendering tutorials
[platform/core/uifw/dali-demo.git] / examples / rendering-cube / rendering-cube.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/dali.h>
19 #include <dali-toolkit/dali-toolkit.h>
20
21 using namespace Dali;
22 using namespace Toolkit;
23
24 namespace
25 {
26
27 /*
28  * Vertex shader
29  */
30 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
31 attribute mediump vec3 aPosition;\n // DALi shader builtin
32 attribute mediump vec3 aColor;\n // DALi shader builtin
33 uniform   mediump mat4 uMvpMatrix;\n // DALi shader builtin
34 uniform   mediump vec3 uSize;\n // DALi shader builtin
35 \n
36 varying mediump vec4 vColor;\n
37 \n
38 void main()\n
39 {\n
40   mediump vec4 vertexPosition = vec4(aPosition, 1.0);\n
41   vertexPosition.xyz *= uSize;\n
42   vColor = vec4( aColor, 1.0 );\n
43   gl_Position = uMvpMatrix * vertexPosition;\n
44 }\n
45 );
46
47 /*
48  * Fragment shader
49  */
50 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
51 varying mediump vec4 vColor;\n
52 \n
53 void main()\n
54 {\n
55   gl_FragColor = vColor;\n
56 }\n
57 );
58
59 }
60
61 // This example shows how to create a cube with colors on each side
62 //
63 class DrawCubeController : public ConnectionTracker
64 {
65 public:
66
67   DrawCubeController( Application& application )
68   : mApplication( application )
69   {
70     // Connect to the Application's Init signal
71     mApplication.InitSignal().Connect( this, &DrawCubeController::Create );
72   }
73
74   ~DrawCubeController()
75   {
76     // Nothing to do here;
77   }
78
79   // The Init signal is received once (only) during the Application lifetime
80   void Create( Application& application )
81   {
82     // Get a handle to the stage
83     Stage stage = Stage::GetCurrent();
84     stage.SetBackgroundColor( Color::WHITE );
85
86     // Step 1. Create shader
87     CreateCubeShader();
88
89     // Step 2. Prepare geometry
90     CreateCubeGeometry();
91
92     // Step 3. Create a renderer
93     CreateRenderer();
94
95     // Step 4. Create an Actor
96     CreateActor();
97
98     // Step 5. Play animation to rotate the cube
99     PlayAnimation();
100
101     // Respond to a click anywhere on the stage
102     stage.GetRootLayer().TouchSignal().Connect( this, &DrawCubeController::OnTouch );
103   }
104
105   bool OnTouch( Actor actor, const TouchData& touch )
106   {
107     // quit the application
108     mApplication.Quit();
109     return true;
110   }
111
112   /**
113    * This function creates a cube geometry including texture coordinates.
114    * Also it demonstrates using the indexed draw feature by setting an index array.
115    */
116   void CreateCubeGeometry()
117   {
118     struct Vertex
119     {
120       Vector3 aPosition;
121       Vector3 aColor;
122     };
123
124     const Vector3 COLOR0( 1.0f, 1.0f, 0.0f );
125     const Vector3 COLOR1( 0.0f, 1.0f, 1.0f );
126     const Vector3 COLOR2( 1.0f, 0.0f, 1.0f );
127     const Vector3 COLOR3( 0.0f, 1.0f, 0.0f );
128     const Vector3 COLOR4( 0.0f, 0.0f, 1.0f );
129     const Vector3 COLOR5( 1.0f, 0.0f, 0.0f );
130
131     Vertex vertices[] = {
132       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR5 },
133       { Vector3( -1.0f, 1.0f,-1.0f ), COLOR5 },
134       { Vector3(  1.0f, 1.0f,-1.0f ), COLOR5 },
135       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR3 },
136       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR3 },
137       { Vector3(  1.0f, 1.0f, 1.0f ), COLOR3 },
138       { Vector3(  1.0f, 1.0f, 1.0f ), COLOR4 },
139       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR4 },
140       { Vector3(  1.0f, 1.0f,-1.0f ), COLOR4 },
141       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR1 },
142       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR1 },
143       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR1 },
144       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR0 },
145       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR0 },
146       { Vector3( -1.0f, 1.0f,-1.0f ), COLOR0 },
147       { Vector3(  1.0f, 1.0f,-1.0f ), COLOR2 },
148       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR2 },
149       { Vector3(  1.0f, 1.0f, 1.0f ), COLOR2 },
150       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR5 },
151       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR5 },
152       { Vector3( -1.0f, 1.0f,-1.0f ), COLOR5 },
153       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR3 },
154       { Vector3( -1.0f,-1.0f, 1.0f ), COLOR3 },
155       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR3 },
156       { Vector3(  1.0f, 1.0f, 1.0f ), COLOR4 },
157       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR4 },
158       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR4 },
159       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR1 },
160       { Vector3( -1.0f,-1.0f, 1.0f ), COLOR1 },
161       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR1 },
162       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR0 },
163       { Vector3( -1.0f,-1.0f, 1.0f ), COLOR0 },
164       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR0 },
165       { Vector3(  1.0f, 1.0f,-1.0f ), COLOR2 },
166       { Vector3( -1.0f, 1.0f,-1.0f ), COLOR2 },
167       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR2 },
168     };
169
170     Property::Map map;
171     map[ "aPosition" ] = Property::VECTOR3;
172     map[ "aColor" ] = Property::VECTOR3;
173     PropertyBuffer vertexBuffer = PropertyBuffer::New( map );
174
175     vertexBuffer.SetData( vertices, sizeof(vertices) / sizeof(Vertex) );
176
177     // create indices
178     const unsigned short INDEX_CUBE[] = {
179       2, 1, 0,
180       5, 4, 3,
181       8, 7, 6,
182       11, 10, 9,
183       14, 13, 12,
184       17, 16, 15,
185       20, 19, 18,
186       23, 22, 21,
187       26, 25, 24,
188       29, 28, 27,
189       32, 31, 30,
190       35, 34, 33
191     };
192     mGeometry = Geometry::New();
193     mGeometry.AddVertexBuffer( vertexBuffer );
194     mGeometry.SetIndexBuffer( INDEX_CUBE,
195                               sizeof(INDEX_CUBE)/sizeof(INDEX_CUBE[0])
196         );
197     mGeometry.SetType( Geometry::TRIANGLES );
198   }
199
200   /**
201    * Creates a shader using inlined variable VERTEX_SHADER and FRAGMENT_SHADER
202    *
203    * Shaders are very basic and all they do is transforming vertices and interpolating
204    * input per-vertex color.
205    */
206   void CreateCubeShader()
207   {
208     mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
209   }
210
211   /**
212    * Function creates renderer. It turns on depth test and depth write.
213    */
214   void CreateRenderer()
215   {
216     mRenderer = Renderer::New( mGeometry, mShader );
217
218     // Face culling is enabled to hide the backwards facing sides of the cube
219     // This is sufficient to render a single object; for more complex scenes depth-testing might be required
220     mRenderer.SetProperty( Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK );
221   }
222
223   /**
224    * Creates new actor and attaches renderer.
225    */
226   void CreateActor()
227   {
228     Stage stage = Stage::GetCurrent();
229
230     float quarterStageWidth = stage.GetSize().x * 0.25f;
231     mActor = Actor::New();
232     mActor.SetAnchorPoint( AnchorPoint::CENTER );
233     mActor.SetParentOrigin( ParentOrigin::CENTER );
234     mActor.SetPosition( Vector3( 0.0f, 0.0f, 0.0f ) );
235     mActor.SetSize( Vector3( quarterStageWidth, quarterStageWidth, quarterStageWidth ) );
236     mActor.AddRenderer( mRenderer );
237     stage.Add( mActor );
238   }
239
240   /**
241    * Plays animation
242    */
243   void PlayAnimation()
244   {
245     mAnimation = Animation::New( 5.0f );
246     mAnimation.SetLooping( true );
247     mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::ZAXIS ) );
248     mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::YAXIS ) );
249     mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::XAXIS ) );
250     mAnimation.Play();
251   }
252
253 private:
254   Application&  mApplication;
255
256   Renderer mRenderer;
257   Shader mShader;
258   Geometry mGeometry;
259   Actor mActor;
260   Animation mAnimation;
261 };
262
263 void RunTest( Application& application )
264 {
265   DrawCubeController test( application );
266
267   application.MainLoop();
268 }
269
270 // Entry point for Linux & Tizen applications
271 //
272 int DALI_EXPORT_API main( int argc, char **argv )
273 {
274   Application application = Application::New( &argc, &argv );
275
276   RunTest( application );
277
278   return 0;
279 }