4f8d579422847b11fbc21a3f19756f5580fd095a
[platform/core/uifw/dali-core.git] / automated-tests / src / dali-internal / utc-Dali-Internal-FrustumCulling.cpp
1 /*
2  * Copyright (c) 2014 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 <iostream>
19 #include <algorithm>
20 #include <stdlib.h>
21 #include <dali/public-api/dali-core.h>
22 #include <dali-test-suite-utils.h>
23 #include <dali/devel-api/object/property-buffer.h>
24 #include <dali/devel-api/rendering/geometry.h>
25 #include <dali/devel-api/rendering/texture-set.h>
26 #include <dali/devel-api/rendering/renderer.h>
27 #include <dali/devel-api/rendering/sampler.h>
28 #include <dali/devel-api/rendering/shader.h>
29
30 using namespace Dali;
31
32 #define MAKE_SHADER(A)#A
33
34 const char* VERTEX_SHADER = MAKE_SHADER(
35 attribute mediump vec2    aPosition;
36 attribute mediump vec2    aTexCoord;
37 uniform   mediump mat4    uMvpMatrix;
38 uniform   mediump vec3    uSize;
39 varying   mediump vec2    vTexCoord;
40
41 void main()
42 {
43   mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
44   vertexPosition.xyz *= uSize;
45   vertexPosition = uMvpMatrix * vertexPosition;
46   vTexCoord = aTexCoord;
47   gl_Position = vertexPosition;
48 }
49 );
50
51 const char* FRAGMENT_SHADER = MAKE_SHADER(
52 uniform Sampler2D sTexture;
53 varying mediump vec2 vTexCoord;
54 void main()
55 {
56   gl_FragColor = texture2D( sTexture, vTexCoord );
57 }
58 );
59
60 Geometry CreateGeometry()
61 {
62   const float halfQuadSize = .5f;
63   struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; };
64   TexturedQuadVertex texturedQuadVertexData[4] = {
65     { Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f) },
66     { Vector2( halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f) },
67     { Vector2(-halfQuadSize,  halfQuadSize), Vector2(0.f, 1.f) },
68     { Vector2( halfQuadSize,  halfQuadSize), Vector2(1.f, 1.f) } };
69
70   Property::Map texturedQuadVertexFormat;
71   texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
72   texturedQuadVertexFormat["aTexCoord"] = Property::VECTOR2;
73   PropertyBuffer texturedQuadVertices = PropertyBuffer::New( texturedQuadVertexFormat );
74   texturedQuadVertices.SetData( texturedQuadVertexData, 4 );
75
76   // Create indices
77   unsigned int indexData[6] = { 0, 3, 1, 0, 2, 3 };
78   Property::Map indexFormat;
79   indexFormat["indices"] = Property::INTEGER;
80   PropertyBuffer indices = PropertyBuffer::New( indexFormat );
81   indices.SetData( indexData, sizeof(indexData)/sizeof(indexData[0]) );
82
83   // Create the geometry object
84   Geometry texturedQuadGeometry = Geometry::New();
85   texturedQuadGeometry.AddVertexBuffer( texturedQuadVertices );
86   texturedQuadGeometry.SetIndexBuffer( indices );
87
88   return texturedQuadGeometry;
89 }
90
91 Actor CreateMeshActorToStage( TestApplication& application, Vector3 parentOrigin = ParentOrigin::CENTER, Vector3 anchorPoint = AnchorPoint::CENTER, Shader::ShaderHints shaderHints = Shader::HINT_NONE )
92 {
93   PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ];
94   BufferImage image = BufferImage::New( pixelBuffer, 1, 1 );
95
96   Geometry geometry = CreateGeometry();
97   Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER, shaderHints );
98   TextureSet textureSet = TextureSet::New();
99   textureSet.SetImage( 0u, image );
100   Renderer renderer = Renderer::New( geometry, shader );
101   renderer.SetTextures( textureSet );
102
103   Actor meshActor = Actor::New();
104   meshActor.AddRenderer( renderer );
105   meshActor.SetSize( Vector3( 400.0f, 400.0f, 0.1f ) );
106   meshActor.SetParentOrigin( parentOrigin );
107   meshActor.SetAnchorPoint( anchorPoint );
108   Stage::GetCurrent().Add( meshActor );
109
110   application.SendNotification();
111   application.Render( 16 );
112
113   return meshActor;
114 }
115
116 bool GetCameraDepths( TestApplication& application, float& nearPlane, float& farPlane, float& cameraDepth )
117 {
118   RenderTaskList renderTasks = Stage::GetCurrent().GetRenderTaskList();
119   CameraActor cameraActor;
120   for( unsigned int i = 0; i < renderTasks.GetTaskCount(); ++i )
121   {
122     RenderTask task = renderTasks.GetTask( i );
123     cameraActor = task.GetCameraActor();
124     if( cameraActor )
125     {
126       break;
127     }
128   }
129   if( cameraActor )
130   {
131     application.SendNotification();
132     application.Render( 16 );
133
134     nearPlane = cameraActor.GetNearClippingPlane();
135     farPlane = cameraActor.GetFarClippingPlane();
136     cameraDepth = cameraActor.GetCurrentPosition().z;
137   }
138
139   return !!cameraActor;
140 }
141
142 int UtcFrustumCullN(void)
143 {
144   TestApplication application;
145   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
146   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
147   drawTrace.Enable( true );
148
149   CreateMeshActorToStage( application );
150
151   drawTrace.Reset();
152   application.SendNotification();
153   application.Render( 16 );
154
155   DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
156
157   END_TEST;
158 }
159
160 int UtcFrustumLeftCullP(void)
161 {
162   TestApplication application;
163   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
164   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
165   drawTrace.Enable( true );
166
167   float offset = -0.01f;
168   Actor meshActor = CreateMeshActorToStage( application, Vector3( offset, 0.5f, 0.5f ), AnchorPoint::CENTER_RIGHT );
169
170   float radius = meshActor.GetTargetSize().Length() * 0.5f;
171   Vector2 stageSize = Stage::GetCurrent().GetSize();
172   meshActor.SetParentOrigin( Vector3( -radius / stageSize.width + offset, 0.5f, 0.5f ) );
173   meshActor.SetAnchorPoint( AnchorPoint::CENTER );
174
175   drawTrace.Reset();
176   application.SendNotification();
177   application.Render( 16 );
178
179   // This will be sphere culled
180   DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
181
182   END_TEST;
183 }
184
185 int UtcFrustumLeftCullN(void)
186 {
187   TestApplication application;
188   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
189   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
190   drawTrace.Enable( true );
191
192   float offset = 0.01f;
193   Actor meshActor = CreateMeshActorToStage( application, Vector3( offset, 0.5f, 0.5f ), AnchorPoint::CENTER_RIGHT );
194
195   drawTrace.Reset();
196   application.SendNotification();
197   application.Render( 16 );
198
199   DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
200
201   END_TEST;
202 }
203
204 int UtcFrustumRightCullP(void)
205 {
206   TestApplication application;
207   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
208   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
209   drawTrace.Enable( true );
210
211   float offset = 1.01f;
212   Actor meshActor = CreateMeshActorToStage( application, Vector3( offset, 0.5f, 0.5f ), AnchorPoint::CENTER_LEFT );
213
214   float radius = meshActor.GetTargetSize().Length() * 0.5f;
215   Vector2 stageSize = Stage::GetCurrent().GetSize();
216
217   meshActor.SetParentOrigin( Vector3( radius / stageSize.width + offset, 0.5f, 0.5f ) );
218   meshActor.SetAnchorPoint( AnchorPoint::CENTER );
219
220   drawTrace.Reset();
221   application.SendNotification();
222   application.Render( 16 );
223
224   // This will be sphere culled
225   DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
226
227   END_TEST;
228 }
229
230 int UtcFrustumRightCullN(void)
231 {
232   TestApplication application;
233   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
234   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
235   drawTrace.Enable( true );
236
237   float offset = 0.99f;
238   Actor meshActor = CreateMeshActorToStage( application, Vector3( offset, 0.5f, 0.5f ), AnchorPoint::CENTER_LEFT );
239
240   drawTrace.Reset();
241   application.SendNotification();
242   application.Render( 16 );
243
244   DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
245
246   END_TEST;
247 }
248
249 int UtcFrustumTopCullP(void)
250 {
251   TestApplication application;
252   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
253   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
254   drawTrace.Enable( true );
255
256   float offset = -0.01f;
257   Actor meshActor = CreateMeshActorToStage( application, Vector3( 0.5f, offset, 0.5f ), AnchorPoint::BOTTOM_CENTER );
258
259   float radius = meshActor.GetTargetSize().Length() * 0.5f;
260   Vector2 stageSize = Stage::GetCurrent().GetSize();
261
262   meshActor.SetParentOrigin( Vector3( 0.5f, -radius / stageSize.width + offset, 0.5f ) );
263   meshActor.SetAnchorPoint( AnchorPoint::CENTER );
264
265   drawTrace.Reset();
266   application.SendNotification();
267   application.Render( 16 );
268
269   // This will be sphere culled
270   DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
271
272   END_TEST;
273 }
274
275 int UtcFrustumTopCullN(void)
276 {
277   TestApplication application;
278   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
279   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
280   drawTrace.Enable( true );
281
282   float offset = 0.01f;
283   Actor meshActor = CreateMeshActorToStage( application, Vector3( 0.5f, offset, 0.5f ), AnchorPoint::BOTTOM_CENTER );
284
285   drawTrace.Reset();
286   application.SendNotification();
287   application.Render( 16 );
288
289   // This will be box culled
290   DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
291
292   END_TEST;
293 }
294
295 int UtcFrustumBottomCullP(void)
296 {
297   TestApplication application;
298   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
299   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
300   drawTrace.Enable( true );
301
302   float offset = 1.01f;
303   Actor meshActor = CreateMeshActorToStage( application, Vector3( 0.5f, offset, 0.5f ), AnchorPoint::TOP_CENTER );
304
305   float radius = meshActor.GetTargetSize().Length() * 0.5f;
306   Vector2 stageSize = Stage::GetCurrent().GetSize();
307
308   meshActor.SetParentOrigin( Vector3( 0.5f, radius / stageSize.width + offset, 0.5f ) );
309   meshActor.SetAnchorPoint( AnchorPoint::CENTER );
310
311   drawTrace.Reset();
312   application.SendNotification();
313   application.Render( 16 );
314
315   // This will be sphere culled
316   DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
317
318   END_TEST;
319 }
320
321 int UtcFrustumBottomCullN(void)
322 {
323   TestApplication application;
324   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
325   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
326   drawTrace.Enable( true );
327
328   float offset = 0.99f;
329   Actor meshActor = CreateMeshActorToStage( application, Vector3( 0.5f, offset, 0.5f ), AnchorPoint::TOP_CENTER );
330
331   drawTrace.Reset();
332   application.SendNotification();
333   application.Render( 16 );
334
335   DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
336
337   END_TEST;
338 }
339
340 int UtcFrustumNearCullP(void)
341 {
342   TestApplication application;
343   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
344   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
345   drawTrace.Enable( true );
346
347   float nearPlane, farPlane, cameraDepth;
348   DALI_TEST_CHECK( GetCameraDepths( application, nearPlane, farPlane, cameraDepth ) );
349
350   Actor meshActor = CreateMeshActorToStage( application );
351   Vector3 meshPosition = meshActor.GetCurrentPosition();
352
353   float radius = meshActor.GetTargetSize().Length() * 0.5f;
354   float offset = radius + 0.1f;
355   meshPosition.z = cameraDepth - nearPlane + offset;
356   meshActor.SetPosition( meshPosition );
357
358   drawTrace.Reset();
359   application.SendNotification();
360   application.Render( 16 );
361
362   // This will be sphere culled
363   DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
364
365   END_TEST;
366 }
367
368 int UtcFrustumNearCullN(void)
369 {
370   TestApplication application;
371   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
372   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
373   drawTrace.Enable( true );
374
375   float nearPlane, farPlane, cameraDepth;
376   DALI_TEST_CHECK( GetCameraDepths( application, nearPlane, farPlane, cameraDepth ) );
377
378   Actor meshActor = CreateMeshActorToStage( application );
379   Vector3 meshPosition = meshActor.GetCurrentPosition();
380
381   float offset = meshActor.GetTargetSize().z - 0.1f;
382   meshPosition.z = cameraDepth - nearPlane + offset;
383   meshActor.SetPosition( meshPosition );
384
385   drawTrace.Reset();
386   application.SendNotification();
387   application.Render( 16 );
388
389   DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
390
391   END_TEST;
392 }
393
394 int UtcFrustumFarCullP(void)
395 {
396   TestApplication application;
397   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
398   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
399   drawTrace.Enable( true );
400
401   float nearPlane, farPlane, cameraDepth;
402   DALI_TEST_CHECK( GetCameraDepths( application, nearPlane, farPlane, cameraDepth ) );
403
404   Actor meshActor = CreateMeshActorToStage( application );
405   Vector3 meshPosition = meshActor.GetCurrentPosition();
406
407   float radius = meshActor.GetTargetSize().Length() * 0.5f;
408   float offset = radius + 0.1f;
409   meshPosition.z = cameraDepth - farPlane - offset;
410   meshActor.SetPosition( meshPosition );
411
412   drawTrace.Reset();
413   application.SendNotification();
414   application.Render( 16 );
415
416   // This will be sphere culled
417   DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
418
419   END_TEST;
420 }
421
422 int UtcFrustumFarCullN(void)
423 {
424   TestApplication application;
425   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
426   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
427   drawTrace.Enable( true );
428
429   float nearPlane, farPlane, cameraDepth;
430   DALI_TEST_CHECK( GetCameraDepths( application, nearPlane, farPlane, cameraDepth ) );
431
432   Actor meshActor = CreateMeshActorToStage( application );
433   Vector3 meshPosition = meshActor.GetCurrentPosition();
434
435   float offset = meshActor.GetTargetSize().z - 0.1f;
436   meshPosition.z = cameraDepth - farPlane - offset;
437   meshActor.SetPosition( meshPosition );
438
439   drawTrace.Reset();
440   application.SendNotification();
441   application.Render( 16 );
442
443   DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
444
445   END_TEST;
446 }
447
448 int UtcFrustumCullDisabledP(void)
449 {
450   TestApplication application;
451   TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
452   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
453   drawTrace.Enable( true );
454
455   CreateMeshActorToStage( application, Vector3( 7.0f, 0.5f, 0.5f ), AnchorPoint::CENTER, Shader::HINT_MODIFIES_GEOMETRY );
456
457   drawTrace.Reset();
458   application.SendNotification();
459   application.Render( 16 );
460
461   // This should not be culled
462   DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
463
464   END_TEST;
465 }