Convert shaders in dali-demo to use shader compilation tool
[platform/core/uifw/dali-demo.git] / examples / animated-shapes / animated-shapes-example.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 #include "shared/view.h"
21 #include "generated/animated-shapes-vert.h"
22 #include "generated/animated-shapes-frag.h"
23
24 #include <sstream>
25
26 using namespace Dali;
27 using namespace Dali::Toolkit;
28
29 namespace
30 {
31 const char* APPLICATION_TITLE("Animated Shapes");
32
33 Shader CreateShader(unsigned int pointCount)
34 {
35   std::ostringstream vertexShader;
36   vertexShader << "#define MAX_POINT_COUNT " << pointCount << "\n"
37                << SHADER_ANIMATED_SHAPES_VERT;
38
39   std::ostringstream fragmentShader;
40   fragmentShader << "#extension GL_OES_standard_derivatives : enable "
41                  << "\n"
42                  << SHADER_ANIMATED_SHAPES_FRAG;
43
44   Shader shader = Shader::New(vertexShader.str(), fragmentShader.str());
45   for(unsigned int i(0); i < pointCount; ++i)
46   {
47     std::ostringstream propertyName;
48     propertyName << "uPosition[" << i << "]";
49     shader.RegisterProperty(propertyName.str(), Vector3(0.0f, 0.0f, 0.0f));
50   }
51
52   return shader;
53 }
54
55 } //unnamed namespace
56
57 // This example shows resolution independent rendering and animation of curves using the gpu.
58 //
59 class AnimatedShapesExample : public ConnectionTracker
60 {
61 public:
62   AnimatedShapesExample(Application& application)
63   : mApplication(application)
64   {
65     // Connect to the Application's Init signal
66     mApplication.InitSignal().Connect(this, &AnimatedShapesExample::Create);
67   }
68
69   ~AnimatedShapesExample() = default;
70
71   // The Init signal is received once (only) during the Application lifetime
72   void Create(Application& application)
73   {
74     Window        window     = application.GetWindow();
75     const Vector2 windowSize = window.GetSize();
76
77     // Creates the background gradient
78     Toolkit::Control background                = Dali::Toolkit::Control::New();
79     background[Actor::Property::ANCHOR_POINT]  = Dali::AnchorPoint::CENTER;
80     background[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::CENTER;
81     background.SetResizePolicy(Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS);
82
83     Dali::Property::Map map;
84     map.Insert(Toolkit::Visual::Property::TYPE, Visual::GRADIENT);
85     Property::Array stopOffsets;
86     stopOffsets.PushBack(0.0f);
87     stopOffsets.PushBack(1.0f);
88     map.Insert(GradientVisual::Property::STOP_OFFSET, stopOffsets);
89     Property::Array stopColors;
90     stopColors.PushBack(Vector4(0.0f, 0.0f, 1.0f, 1.0f));
91     stopColors.PushBack(Vector4(1.0f, 1.0f, 1.0f, 1.0f));
92     map.Insert(GradientVisual::Property::STOP_COLOR, stopColors);
93     Vector2 halfWindowSize = windowSize * 0.5f;
94     map.Insert(GradientVisual::Property::START_POSITION, Vector2(0.0f, -halfWindowSize.y));
95     map.Insert(GradientVisual::Property::END_POSITION, Vector2(0.0f, halfWindowSize.y));
96     map.Insert(GradientVisual::Property::UNITS, GradientVisual::Units::USER_SPACE);
97     background[Dali::Toolkit::Control::Property::BACKGROUND] = map;
98     window.Add(background);
99
100     // Create a TextLabel for the application title.
101     Toolkit::TextLabel label                                  = Toolkit::TextLabel::New(APPLICATION_TITLE);
102     label[Actor::Property::ANCHOR_POINT]                      = AnchorPoint::TOP_CENTER;
103     label[Actor::Property::PARENT_ORIGIN]                     = Vector3(0.5f, 0.0f, 0.5f);
104     label[Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT] = "CENTER";
105     label[Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT]   = "CENTER";
106     label[Toolkit::TextLabel::Property::TEXT_COLOR]           = Color::WHITE;
107     window.Add(label);
108
109     CreateTriangleMorph(Vector3(windowSize.x * 0.5f, windowSize.y * 0.15f, 0.0f), 100.0f);
110     CreateCircleMorph(Vector3(windowSize.x * 0.5f, windowSize.y * 0.5f, 0.0f), 55.0f);
111     CreateQuadMorph(Vector3(windowSize.x * 0.5f, windowSize.y * 0.85f, 0.0f), 60.0f);
112
113     window.KeyEventSignal().Connect(this, &AnimatedShapesExample::OnKeyEvent);
114   }
115
116   void CreateTriangleMorph(Vector3 center, float side)
117   {
118     float h = (side * 0.5f) / 0.866f;
119
120     Vector3 v0 = Vector3(-h, h, 0.0f);
121     Vector3 v1 = Vector3(0.0f, -side * 0.366f, 0.0f);
122     Vector3 v2 = Vector3(h, h, 0.0f);
123
124     Vector3 v3 = v0 + ((v1 - v0) * 0.5f);
125     Vector3 v4 = v1 + ((v2 - v1) * 0.5f);
126     Vector3 v5 = v2 + ((v0 - v2) * 0.5f);
127
128     Shader shader          = CreateShader(12);
129     shader["uPosition[0]"] = v0;
130     shader["uPosition[1]"] = v3;
131     shader["uPosition[2]"] = v1;
132
133     shader["uPosition[3]"] = v1;
134     shader["uPosition[4]"] = v4;
135     shader["uPosition[5]"] = v2;
136
137     shader["uPosition[6]"] = v2;
138     shader["uPosition[7]"] = v5;
139     shader["uPosition[8]"] = v0;
140
141     shader["uPosition[9]"]  = v0;
142     shader["uPosition[10]"] = v1;
143     shader["uPosition[11]"] = v2;
144
145     //Create geometry
146     static const Vector3 vertexData[] = {Dali::Vector3(0.0f, 0.0f, 0.0f),
147                                          Dali::Vector3(0.5f, 0.0f, 1.0f),
148                                          Dali::Vector3(1.0f, 1.0f, 2.0f),
149
150                                          Dali::Vector3(0.0f, 0.0f, 3.0f),
151                                          Dali::Vector3(0.5f, 0.0f, 4.0f),
152                                          Dali::Vector3(1.0f, 1.0f, 5.0f),
153
154                                          Dali::Vector3(0.0f, 0.0f, 6.0f),
155                                          Dali::Vector3(0.5f, 0.0f, 7.0f),
156                                          Dali::Vector3(1.0f, 1.0f, 8.0f),
157
158                                          Dali::Vector3(0.0f, 1.0f, 9.0f),
159                                          Dali::Vector3(0.0f, 1.0f, 10.0f),
160                                          Dali::Vector3(0.0f, 1.0f, 11.0f)};
161
162     unsigned short indexData[] = {0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10};
163
164     //Create a vertex buffer for vertex positions and texture coordinates
165     Dali::Property::Map vertexFormat;
166     vertexFormat["aCoefficient"]    = Dali::Property::VECTOR3;
167     Dali::VertexBuffer vertexBuffer = Dali::VertexBuffer::New(vertexFormat);
168     vertexBuffer.SetData(vertexData, sizeof(vertexData) / sizeof(vertexData[0]));
169
170     //Create the geometry
171     Dali::Geometry geometry = Dali::Geometry::New();
172     geometry.AddVertexBuffer(vertexBuffer);
173     geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
174
175     Renderer renderer                        = Renderer::New(geometry, shader);
176     renderer[Renderer::Property::BLEND_MODE] = BlendMode::ON;
177
178     Actor actor                          = Actor::New();
179     actor[Actor::Property::SIZE]         = Vector2(400.0f, 400.0f);
180     actor[Actor::Property::POSITION]     = center;
181     actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
182     actor[Actor::Property::COLOR]        = Color::YELLOW;
183     actor.AddRenderer(renderer);
184
185     Window window = mApplication.GetWindow();
186     window.Add(actor);
187
188     //Animation
189     Animation animation = Animation::New(5.0f);
190     KeyFrames k0        = KeyFrames::New();
191     k0.Add(0.0f, v3);
192     k0.Add(0.5f, v3 + Vector3(-150.0f, -150.0f, 0.0f));
193     k0.Add(1.0f, v3);
194     animation.AnimateBetween(Property(shader, "uPosition[1]"), k0, AlphaFunction::EASE_IN_OUT_SINE);
195
196     k0 = KeyFrames::New();
197     k0.Add(0.0f, v4);
198     k0.Add(0.5f, v4 + Vector3(150.0f, -150.0f, 0.0f));
199     k0.Add(1.0f, v4);
200     animation.AnimateBetween(Property(shader, "uPosition[4]"), k0, AlphaFunction::EASE_IN_OUT_SINE);
201
202     k0 = KeyFrames::New();
203     k0.Add(0.0f, v5);
204     k0.Add(0.5f, v5 + Vector3(0.0, 150.0f, 0.0f));
205     k0.Add(1.0f, v5);
206     animation.AnimateBetween(Property(shader, "uPosition[7]"), k0, AlphaFunction::EASE_IN_OUT_SINE);
207     animation.SetLooping(true);
208     animation.Play();
209   }
210
211   void CreateCircleMorph(Vector3 center, float radius)
212   {
213     Shader shader          = CreateShader(16);
214     shader["uPosition[0]"] = Vector3(-radius, -radius, 0.0f);
215     shader["uPosition[1]"] = Vector3(0.0f, -radius, 0.0f);
216     shader["uPosition[2]"] = Vector3(radius, -radius, 0.0f);
217
218     shader["uPosition[3]"] = Vector3(radius, -radius, 0.0f);
219     shader["uPosition[4]"] = Vector3(radius, 0.0f, 0.0f);
220     shader["uPosition[5]"] = Vector3(radius, radius, 0.0f);
221
222     shader["uPosition[6]"] = Vector3(radius, radius, 0.0f);
223     shader["uPosition[7]"] = Vector3(0.0f, radius, 0.0f);
224     shader["uPosition[8]"] = Vector3(-radius, radius, 0.0f);
225
226     shader["uPosition[9]"]  = Vector3(-radius, radius, 0.0f);
227     shader["uPosition[10]"] = Vector3(-radius, 0.0f, 0.0f);
228     shader["uPosition[11]"] = Vector3(-radius, -radius, 0.0f);
229
230     shader["uPosition[12]"] = Vector3(-radius, -radius, 0.0f);
231     shader["uPosition[13]"] = Vector3(radius, -radius, 0.0f);
232     shader["uPosition[14]"] = Vector3(radius, radius, 0.0f);
233     shader["uPosition[15]"] = Vector3(-radius, radius, 0.0f);
234
235     //shader["uLineWidth"), 2.0] ;
236
237     static const Vector3 vertexData[] = {Vector3(0.0f, 0.0f, 0.0f),
238                                          Vector3(0.5f, 0.0f, 1.0f),
239                                          Vector3(1.0f, 1.0f, 2.0f),
240                                          Vector3(0.0f, 0.0f, 3.0f),
241                                          Vector3(0.5f, 0.0f, 4.0f),
242                                          Vector3(1.0f, 1.0f, 5.0f),
243                                          Vector3(0.0f, 0.0f, 6.0f),
244                                          Vector3(0.5f, 0.0f, 7.0f),
245                                          Vector3(1.0f, 1.0f, 8.0f),
246                                          Vector3(0.0f, 0.0f, 9.0f),
247                                          Vector3(0.5f, 0.0f, 10.0f),
248                                          Vector3(1.0f, 1.0f, 11.0f),
249                                          Vector3(0.0f, 1.0f, 12.0f),
250                                          Vector3(0.0f, 1.0f, 13.0f),
251                                          Vector3(0.0f, 1.0f, 14.0f),
252                                          Vector3(0.0f, 1.0f, 15.0f)};
253
254     short unsigned int indexData[] = {0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 13, 14, 12, 14, 15};
255
256     //Create a vertex buffer for vertex positions and texture coordinates
257     Dali::Property::Map vertexFormat;
258     vertexFormat["aCoefficient"]    = Dali::Property::VECTOR3;
259     Dali::VertexBuffer vertexBuffer = Dali::VertexBuffer::New(vertexFormat);
260     vertexBuffer.SetData(vertexData, sizeof(vertexData) / sizeof(vertexData[0]));
261
262     //Create the geometry
263     Dali::Geometry geometry = Dali::Geometry::New();
264     geometry.AddVertexBuffer(vertexBuffer);
265     geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
266
267     Renderer renderer                        = Renderer::New(geometry, shader);
268     renderer[Renderer::Property::BLEND_MODE] = BlendMode::ON;
269
270     Actor actor                          = Actor::New();
271     actor[Actor::Property::SIZE]         = Vector2(400.0f, 400.0f);
272     actor[Actor::Property::POSITION]     = center;
273     actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
274     actor.AddRenderer(renderer);
275
276     Window window = mApplication.GetWindow();
277     window.Add(actor);
278
279     //Animation
280     Animation animation = Animation::New(5.0f);
281     KeyFrames k0        = KeyFrames::New();
282     k0.Add(0.0f, Vector3(0.0f, -radius * 1.85, 0.0f));
283     k0.Add(0.5f, Vector3(-radius * 1.85, -radius * 3.0f, 0.0f));
284     k0.Add(1.0f, Vector3(0.0f, -radius * 1.85, 0.0f));
285     animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[1]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
286
287     k0 = KeyFrames::New();
288     k0.Add(0.0f, Vector3(radius * 1.85, 0.0f, 0.0f));
289     k0.Add(0.5f, Vector3(radius * 3.0f, -radius * 1.85, 0.0f));
290     k0.Add(1.0f, Vector3(radius * 1.85, 0.0f, 0.0f));
291     animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[4]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
292
293     k0 = KeyFrames::New();
294     k0.Add(0.0f, Vector3(0.0f, radius * 1.85, 0.0f));
295     k0.Add(0.5f, Vector3(radius * 1.85, radius * 3.0f, 0.0f));
296     k0.Add(1.0f, Vector3(0.0f, radius * 1.85, 0.0f));
297     animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[7]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
298
299     k0 = KeyFrames::New();
300     k0.Add(0.0f, Vector3(-radius * 1.85, 0.0f, 0.0f));
301     k0.Add(0.5f, Vector3(-radius * 3.0f, radius * 1.85, 0.0f));
302     k0.Add(1.0f, Vector3(-radius * 1.85, 0.0f, 0.0f));
303     animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[10]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
304
305     animation.AnimateBy(Property(actor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(-90.0f)), Vector3::ZAXIS));
306     animation.SetLooping(true);
307     animation.Play();
308   }
309
310   void CreateQuadMorph(Vector3 center, float radius)
311   {
312     Shader shader          = CreateShader(16);
313     shader["uPosition[0]"] = Vector3(-radius, -radius, 0.0f);
314     shader["uPosition[1]"] = Vector3(0.0f, -radius, 0.0f);
315     shader["uPosition[2]"] = Vector3(radius, -radius, 0.0f);
316
317     shader["uPosition[3]"] = Vector3(radius, -radius, 0.0f);
318     shader["uPosition[4]"] = Vector3(radius, 0.0f, 0.0f);
319     shader["uPosition[5]"] = Vector3(radius, radius, 0.0f);
320
321     shader["uPosition[6]"] = Vector3(radius, radius, 0.0f);
322     shader["uPosition[7]"] = Vector3(0.0f, radius, 0.0f);
323     shader["uPosition[8]"] = Vector3(-radius, radius, 0.0f);
324
325     shader["uPosition[9]"]  = Vector3(-radius, radius, 0.0f);
326     shader["uPosition[10]"] = Vector3(-radius, 0.0f, 0.0f);
327     shader["uPosition[11]"] = Vector3(-radius, -radius, 0.0f);
328
329     shader["uPosition[12]"] = Vector3(-radius, -radius, 0.0f);
330     shader["uPosition[13]"] = Vector3(radius, -radius, 0.0f);
331     shader["uPosition[14]"] = Vector3(radius, radius, 0.0f);
332     shader["uPosition[15]"] = Vector3(-radius, radius, 0.0f);
333
334     static const Vector3 vertexData[] = {Dali::Vector3(0.0f, 0.0f, 0.0f),
335                                          Dali::Vector3(0.5f, 0.0f, 1.0f),
336                                          Dali::Vector3(1.0f, 1.0f, 2.0f),
337
338                                          Dali::Vector3(0.0f, 0.0f, 3.0f),
339                                          Dali::Vector3(0.5f, 0.0f, 4.0f),
340                                          Dali::Vector3(1.0f, 1.0f, 5.0f),
341
342                                          Dali::Vector3(0.0f, 0.0f, 6.0f),
343                                          Dali::Vector3(0.5f, 0.0f, 7.0f),
344                                          Dali::Vector3(1.0f, 1.0f, 8.0f),
345
346                                          Dali::Vector3(0.0f, 0.0f, 9.0f),
347                                          Dali::Vector3(0.5f, 0.0f, 10.0f),
348                                          Dali::Vector3(1.0f, 1.0f, 11.0f),
349
350                                          Dali::Vector3(0.0f, 1.0f, 12.0f),
351                                          Dali::Vector3(0.0f, 1.0f, 13.0f),
352                                          Dali::Vector3(0.0f, 1.0f, 14.0f),
353                                          Dali::Vector3(0.0f, 1.0f, 15.0f)};
354
355     short unsigned int indexData[] = {0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 15, 14, 12, 14, 13};
356
357     //Create a vertex buffer for vertex positions and texture coordinates
358     Dali::Property::Map vertexFormat;
359     vertexFormat["aCoefficient"]    = Dali::Property::VECTOR3;
360     Dali::VertexBuffer vertexBuffer = Dali::VertexBuffer::New(vertexFormat);
361     vertexBuffer.SetData(vertexData, sizeof(vertexData) / sizeof(vertexData[0]));
362
363     //Create the geometry
364     Dali::Geometry geometry = Dali::Geometry::New();
365     geometry.AddVertexBuffer(vertexBuffer);
366     geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
367
368     Renderer renderer                        = Renderer::New(geometry, shader);
369     renderer[Renderer::Property::BLEND_MODE] = BlendMode::ON;
370
371     Actor actor                          = Actor::New();
372     actor[Actor::Property::SIZE]         = Vector2(400.0f, 400.0f);
373     actor[Actor::Property::POSITION]     = center;
374     actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
375     actor[Actor::Property::COLOR]        = Color::RED;
376     actor.AddRenderer(renderer);
377
378     Window window = mApplication.GetWindow();
379     window.Add(actor);
380
381     //Animation
382     Animation animation = Animation::New(5.0f);
383     KeyFrames k0        = KeyFrames::New();
384     k0.Add(0.0f, Vector3(0.0f, -radius, 0.0f));
385     k0.Add(0.5f, Vector3(0.0f, -radius * 4.0f, 0.0f));
386     k0.Add(1.0f, Vector3(0.0f, -radius, 0.0f));
387     animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[1]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
388
389     k0 = KeyFrames::New();
390     k0.Add(0.0f, Vector3(radius, 0.0f, 0.0f));
391     k0.Add(0.5f, Vector3(radius * 4.0f, 0.0f, 0.0f));
392     k0.Add(1.0f, Vector3(radius, 0.0f, 0.0f));
393     animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[4]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
394
395     k0 = KeyFrames::New();
396     k0.Add(0.0f, Vector3(0.0f, radius, 0.0f));
397     k0.Add(0.5f, Vector3(0.0f, radius * 4.0f, 0.0f));
398     k0.Add(1.0f, Vector3(0.0f, radius, 0.0f));
399     animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[7]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
400
401     k0 = KeyFrames::New();
402     k0.Add(0.0f, Vector3(-radius, 0.0f, 0.0f));
403     k0.Add(0.5f, Vector3(-radius * 4.0f, 0.0f, 0.0f));
404     k0.Add(1.0f, Vector3(-radius, 0.0f, 0.0f));
405     animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[10]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
406
407     animation.AnimateBy(Property(actor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(90.0f)), Vector3::ZAXIS));
408     animation.SetLooping(true);
409     animation.Play();
410   }
411
412   /**
413    * Main key event handler
414    */
415   void OnKeyEvent(const KeyEvent& event)
416   {
417     if(event.GetState() == KeyEvent::DOWN && (IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK)))
418     {
419       mApplication.Quit();
420     }
421   }
422
423 private:
424   Application& mApplication;
425 };
426
427 int DALI_EXPORT_API main(int argc, char** argv)
428 {
429   Application           application = Application::New(&argc, &argv);
430   AnimatedShapesExample test(application);
431   application.MainLoop();
432   return 0;
433 }