Convert shaders in dali-demo to use shader compilation tool
[platform/core/uifw/dali-demo.git] / examples / rendering-textured-cube / rendering-textured-cube.cpp
1 /*
2  * Copyright (c) 2020 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/dali.h>
20
21 #include "generated/rendering-textured-cube-vert.h"
22 #include "generated/rendering-textured-cube-frag.h"
23
24 using namespace Dali;
25 using namespace Toolkit;
26
27 namespace
28 {
29
30 const char* TEXTURE_URL = DEMO_IMAGE_DIR "wood.png";
31
32 } // namespace
33
34 // This example shows how to create textured cube
35 //
36 class TexturedCubeController : public ConnectionTracker
37 {
38 public:
39   TexturedCubeController(Application& application)
40   : mApplication(application)
41   {
42     // Connect to the Application's Init signal
43     mApplication.InitSignal().Connect(this, &TexturedCubeController::Create);
44   }
45
46   ~TexturedCubeController()
47   {
48     // Nothing to do here;
49   }
50
51   // The Init signal is received once (only) during the Application lifetime
52   void Create(Application& application)
53   {
54     // Get a handle to the window
55     Window window = application.GetWindow();
56     window.SetBackgroundColor(Color::WHITE);
57
58     // Step 1. Create shader
59     CreateCubeShader();
60
61     // Step 2. Load a texture
62     CreateTexture();
63
64     // Step 3. Prepare geometry
65     CreateCubeGeometry();
66
67     // Step 4. Create a renderer
68     CreateRenderer();
69
70     // Step 5. Create an Actor
71     CreateActor();
72
73     // Step 6. Play animation to rotate the cube
74     PlayAnimation();
75
76     // Respond to a click anywhere on the window
77     window.GetRootLayer().TouchedSignal().Connect(this, &TexturedCubeController::OnTouch);
78
79     // Respond to key events
80     window.KeyEventSignal().Connect(this, &TexturedCubeController::OnKeyEvent);
81   }
82
83   bool OnTouch(Actor actor, const TouchEvent& touch)
84   {
85     // quit the application
86     mApplication.Quit();
87     return true;
88   }
89
90   /**
91    * @brief Called when any key event is received
92    *
93    * Will use this to quit the application if Back or the Escape key is received
94    * @param[in] event The key event information
95    */
96   void OnKeyEvent(const KeyEvent& event)
97   {
98     if(event.GetState() == KeyEvent::DOWN)
99     {
100       if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
101       {
102         mApplication.Quit();
103       }
104     }
105   }
106
107   /**
108    * @brief CreateCubeGeometry
109    * This function creates a cube geometry including texture coordinates.
110    * Also it demonstrates using the indexed draw feature by setting an index array.
111    */
112   void CreateCubeGeometry()
113   {
114     struct Vertex
115     {
116       Vector3 aPosition;
117       Vector2 aTexCoord;
118     };
119
120     Vertex vertices[] = {
121       {Vector3(1.0f, -1.0f, -1.0f), Vector2(1.0, 1.0)},
122       {Vector3(-1.0f, 1.0f, -1.0f), Vector2(0.0, 0.0)},
123       {Vector3(1.0f, 1.0f, -1.0f), Vector2(0.0, 1.0)},
124       {Vector3(-1.0f, 1.0f, 1.0f), Vector2(1.0, 1.0)},
125       {Vector3(1.0f, -1.0f, 1.0f), Vector2(0.0, 0.0)},
126       {Vector3(1.0f, 1.0f, 1.0f), Vector2(0.0, 1.0)},
127       {Vector3(1.0f, 1.0f, 1.0f), Vector2(1.0, 1.0)},
128       {Vector3(1.0f, -1.0f, -1.0f), Vector2(0.0, 0.0)},
129       {Vector3(1.0f, 1.0f, -1.0f), Vector2(0.0, 1.0)},
130       {Vector3(1.0f, -1.0f, 1.0f), Vector2(1.0, 1.0)},
131       {Vector3(-1.0f, -1.0f, -1.0f), Vector2(0.0, 0.0)},
132       {Vector3(1.0f, -1.0f, -1.0f), Vector2(0.0, 1.0)},
133       {Vector3(-1.0f, -1.0f, -1.0f), Vector2(1.0, 1.0)},
134       {Vector3(-1.0f, 1.0f, 1.0f), Vector2(0.0, 0.0)},
135       {Vector3(-1.0f, 1.0f, -1.0f), Vector2(0.0, 1.0)},
136       {Vector3(1.0f, 1.0f, -1.0f), Vector2(1.0, 1.0)},
137       {Vector3(-1.0f, 1.0f, 1.0f), Vector2(0.0, 0.0)},
138       {Vector3(1.0f, 1.0f, 1.0f), Vector2(0.0, 1.0)},
139       {Vector3(1.0f, -1.0f, -1.0f), Vector2(1.0, 1.0)},
140       {Vector3(-1.0f, -1.0f, -1.0f), Vector2(1.0, 0.0)},
141       {Vector3(-1.0f, 1.0f, -1.0f), Vector2(0.0, 0.0)},
142       {Vector3(-1.0f, 1.0f, 1.0f), Vector2(1.0, 1.0)},
143       {Vector3(-1.0f, -1.0f, 1.0f), Vector2(1.0, 0.0)},
144       {Vector3(1.0f, -1.0f, 1.0f), Vector2(0.0, 0.0)},
145       {Vector3(1.0f, 1.0f, 1.0f), Vector2(1.0, 1.0)},
146       {Vector3(1.0f, -1.0f, 1.0f), Vector2(1.0, 0.0)},
147       {Vector3(1.0f, -1.0f, -1.0f), Vector2(0.0, 0.0)},
148       {Vector3(1.0f, -1.0f, 1.0f), Vector2(1.0, 1.0)},
149       {Vector3(-1.0f, -1.0f, 1.0f), Vector2(1.0, 0.0)},
150       {Vector3(-1.0f, -1.0f, -1.0f), Vector2(0.0, 0.0)},
151       {Vector3(-1.0f, -1.0f, -1.0f), Vector2(1.0, 1.0)},
152       {Vector3(-1.0f, -1.0f, 1.0f), Vector2(1.0, 0.0)},
153       {Vector3(-1.0f, 1.0f, 1.0f), Vector2(0.0, 0.0)},
154       {Vector3(1.0f, 1.0f, -1.0f), Vector2(1.0, 1.0)},
155       {Vector3(-1.0f, 1.0f, -1.0f), Vector2(1.0, 0.0)},
156       {Vector3(-1.0f, 1.0f, 1.0f), Vector2(0.0, 0.0)},
157     };
158
159     VertexBuffer vertexBuffer = VertexBuffer::New(Property::Map()
160                                                     .Add("aPosition", Property::VECTOR3)
161                                                     .Add("aTexCoord", Property::VECTOR2));
162     vertexBuffer.SetData(vertices, sizeof(vertices) / sizeof(Vertex));
163
164     // create indices
165     const unsigned short INDEX_CUBE[] = {
166       2, 1, 0, 5, 4, 3, 8, 7, 6, 11, 10, 9, 14, 13, 12, 17, 16, 15, 20, 19, 18, 23, 22, 21, 26, 25, 24, 29, 28, 27, 32, 31, 30, 35, 34, 33};
167     mGeometry = Geometry::New();
168     mGeometry.AddVertexBuffer(vertexBuffer);
169     mGeometry.SetIndexBuffer(INDEX_CUBE,
170                              sizeof(INDEX_CUBE) / sizeof(INDEX_CUBE[0]));
171     mGeometry.SetType(Geometry::TRIANGLES);
172   }
173
174   /**
175    * Creates a shader using SHADER_RENDERING_TEXTURED_CUBE_VERT and SHADER_RENDERING_TEXTURED_CUBE_FRAG
176    *
177    * Shaders are very basic and all they do is transforming vertices and sampling
178    * a texture.
179    */
180   void CreateCubeShader()
181   {
182     mShader = Shader::New(SHADER_RENDERING_TEXTURED_CUBE_VERT, SHADER_RENDERING_TEXTURED_CUBE_FRAG);
183   }
184
185   /**
186    * This function loads a pixel data from a file. In order to load it we use SyncImageLoader utility.
187    * If loading succeeds returned PixelData object can be used to create a texture.
188    * Texture must be uploaded. In the end the texture must be set on the TextureSet object.
189    */
190   void CreateTexture()
191   {
192     // Load image from file
193     PixelData pixels = SyncImageLoader::Load(TEXTURE_URL);
194
195     Texture texture = Texture::New(TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight());
196     texture.Upload(pixels, 0, 0, 0, 0, pixels.GetWidth(), pixels.GetHeight());
197
198     // create TextureSet
199     mTextureSet = TextureSet::New();
200     mTextureSet.SetTexture(0, texture);
201   }
202
203   /**
204    * Function creates renderer. It turns on depth test and depth write.
205    */
206   void CreateRenderer()
207   {
208     mRenderer = Renderer::New(mGeometry, mShader);
209     mRenderer.SetTextures(mTextureSet);
210
211     // Face culling is enabled to hide the backwards facing sides of the cube
212     // This is sufficient to render a single object; for more complex scenes depth-testing might be required
213     mRenderer.SetProperty(Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK);
214   }
215
216   /**
217    * Creates new actor and attaches renderer.
218    */
219   void CreateActor()
220   {
221     Window window = mApplication.GetWindow();
222
223     float quarterWindowWidth = window.GetSize().GetWidth() * 0.25f;
224     mActor                   = Actor::New();
225     mActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
226     mActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
227     mActor.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, 0.0f));
228     mActor.SetProperty(Actor::Property::SIZE, Vector3(quarterWindowWidth, quarterWindowWidth, quarterWindowWidth));
229     mActor.AddRenderer(mRenderer);
230     window.Add(mActor);
231   }
232
233   /**
234    * Plays animation
235    */
236   void PlayAnimation()
237   {
238     mAnimation = Animation::New(5.0f);
239     mAnimation.SetLooping(true);
240     mAnimation.AnimateBy(Property(mActor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(360)), Vector3::ZAXIS));
241     mAnimation.AnimateBy(Property(mActor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(360)), Vector3::YAXIS));
242     mAnimation.AnimateBy(Property(mActor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(360)), Vector3::XAXIS));
243     mAnimation.Play();
244   }
245
246 private:
247   Application& mApplication;
248
249   Renderer   mRenderer;
250   Shader     mShader;
251   Geometry   mGeometry;
252   TextureSet mTextureSet;
253   Actor      mActor;
254   Animation  mAnimation;
255 };
256
257 int DALI_EXPORT_API main(int argc, char** argv)
258 {
259   Application            application = Application::New(&argc, &argv);
260   TexturedCubeController test(application);
261   application.MainLoop();
262   return 0;
263 }