Commit b15bfd014dc5256883442603549fdc10b5002a8f

Authored by György Straub
1 parent d743a745

Added Deferred Shading example.

Change-Id: I4a74037a3587d466a913e0a90e0e9a45a62424a0
Signed-off-by: György Straub <g.straub@partner.samsung.com>
com.samsung.dali-demo.xml
@@ -70,6 +70,9 @@ @@ -70,6 +70,9 @@
70 <ui-application appid="dali-builder" exec="/usr/apps/com.samsung.dali-demo/bin/dali-builder" nodisplay="true" multiple="false" type="c++app" taskmanage="true"> 70 <ui-application appid="dali-builder" exec="/usr/apps/com.samsung.dali-demo/bin/dali-builder" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
71 <label>Builder</label> 71 <label>Builder</label>
72 </ui-application> 72 </ui-application>
  73 + <ui-application appid="deferred-shading" exec="/usr/apps/com.samsung.dali-demo/bin/deferred-shading" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
  74 + <label>Deferred Shading</label>
  75 + </ui-application>
73 <ui-application appid="dissolve-effect.example" exec="/usr/apps/com.samsung.dali-demo/bin/dissolve-effect.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true"> 76 <ui-application appid="dissolve-effect.example" exec="/usr/apps/com.samsung.dali-demo/bin/dissolve-effect.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
74 <label>Dissolve effect</label> 77 <label>Dissolve effect</label>
75 </ui-application> 78 </ui-application>
examples-reel/dali-examples-reel.cpp
@@ -47,6 +47,7 @@ int DALI_EXPORT_API main(int argc, char **argv) @@ -47,6 +47,7 @@ int DALI_EXPORT_API main(int argc, char **argv)
47 demo.AddExample(Example("buttons.example", DALI_DEMO_STR_TITLE_BUTTONS)); 47 demo.AddExample(Example("buttons.example", DALI_DEMO_STR_TITLE_BUTTONS));
48 demo.AddExample(Example("clipping.example", DALI_DEMO_STR_TITLE_CLIPPING)); 48 demo.AddExample(Example("clipping.example", DALI_DEMO_STR_TITLE_CLIPPING));
49 demo.AddExample(Example("clipping-draw-order.example", DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER)); 49 demo.AddExample(Example("clipping-draw-order.example", DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER));
  50 + demo.AddExample(Example("deferred-shading.example", DALI_DEMO_STR_TITLE_DEFERRED_SHADING));
50 demo.AddExample(Example("dissolve-effect.example", DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION)); 51 demo.AddExample(Example("dissolve-effect.example", DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION));
51 demo.AddExample(Example("drag-and-drop.example", DALI_DEMO_STR_TITLE_DRAG_AND_DROP)); 52 demo.AddExample(Example("drag-and-drop.example", DALI_DEMO_STR_TITLE_DRAG_AND_DROP));
52 demo.AddExample(Example("effects-view.example", DALI_DEMO_STR_TITLE_EFFECTS_VIEW)); 53 demo.AddExample(Example("effects-view.example", DALI_DEMO_STR_TITLE_EFFECTS_VIEW));
@@ -74,6 +75,7 @@ int DALI_EXPORT_API main(int argc, char **argv) @@ -74,6 +75,7 @@ int DALI_EXPORT_API main(int argc, char **argv)
74 demo.AddExample(Example("pivot.example", DALI_DEMO_STR_TITLE_PIVOT)); 75 demo.AddExample(Example("pivot.example", DALI_DEMO_STR_TITLE_PIVOT));
75 demo.AddExample(Example("primitive-shapes.example", DALI_DEMO_STR_TITLE_PRIMITIVE_SHAPES)); 76 demo.AddExample(Example("primitive-shapes.example", DALI_DEMO_STR_TITLE_PRIMITIVE_SHAPES));
76 demo.AddExample(Example("progress-bar.example", DALI_DEMO_STR_TITLE_PROGRESS_BAR)); 77 demo.AddExample(Example("progress-bar.example", DALI_DEMO_STR_TITLE_PROGRESS_BAR));
  78 + demo.AddExample(Example("remote-image-loading.example", DALI_DEMO_STR_TITLE_REMOTE_IMAGE));
77 demo.AddExample(Example("rendering-basic-light.example", DALI_DEMO_STR_TITLE_BASIC_LIGHT)); 79 demo.AddExample(Example("rendering-basic-light.example", DALI_DEMO_STR_TITLE_BASIC_LIGHT));
78 demo.AddExample(Example("rendering-line.example", DALI_DEMO_STR_TITLE_RENDERING_DRAW_LINE)); 80 demo.AddExample(Example("rendering-line.example", DALI_DEMO_STR_TITLE_RENDERING_DRAW_LINE));
79 demo.AddExample(Example("rendering-triangle.example", DALI_DEMO_STR_TITLE_RENDERING_DRAW_TRIANGLE)); 81 demo.AddExample(Example("rendering-triangle.example", DALI_DEMO_STR_TITLE_RENDERING_DRAW_TRIANGLE));
@@ -91,7 +93,6 @@ int DALI_EXPORT_API main(int argc, char **argv) @@ -91,7 +93,6 @@ int DALI_EXPORT_API main(int argc, char **argv)
91 demo.AddExample(Example("text-label-multi-language.example", DALI_DEMO_STR_TITLE_TEXT_LABEL_MULTI_LANGUAGE)); 93 demo.AddExample(Example("text-label-multi-language.example", DALI_DEMO_STR_TITLE_TEXT_LABEL_MULTI_LANGUAGE));
92 demo.AddExample(Example("text-label-emojis.example", DALI_DEMO_STR_TITLE_EMOJI_TEXT)); 94 demo.AddExample(Example("text-label-emojis.example", DALI_DEMO_STR_TITLE_EMOJI_TEXT));
93 demo.AddExample(Example("text-scrolling.example", DALI_DEMO_STR_TITLE_TEXT_SCROLLING)); 95 demo.AddExample(Example("text-scrolling.example", DALI_DEMO_STR_TITLE_TEXT_SCROLLING));
94 - demo.AddExample(Example("remote-image-loading.example", DALI_DEMO_STR_TITLE_REMOTE_IMAGE));  
95 demo.AddExample(Example("textured-mesh.example", DALI_DEMO_STR_TITLE_TEXTURED_MESH)); 96 demo.AddExample(Example("textured-mesh.example", DALI_DEMO_STR_TITLE_TEXTURED_MESH));
96 demo.AddExample(Example("tilt.example", DALI_DEMO_STR_TITLE_TILT_SENSOR)); 97 demo.AddExample(Example("tilt.example", DALI_DEMO_STR_TITLE_TILT_SENSOR));
97 demo.AddExample(Example("tooltip.example", DALI_DEMO_STR_TITLE_TOOLTIP)); 98 demo.AddExample(Example("tooltip.example", DALI_DEMO_STR_TITLE_TOOLTIP));
examples/deferred-shading/deferred-shading.cpp 0 → 100644
  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 +#include "dali/dali.h"
  18 +#include "dali/public-api/actors/actor.h"
  19 +#include "dali/public-api/rendering/renderer.h"
  20 +#include <random>
  21 +#include <iostream>
  22 +#include <cstring>
  23 +
  24 +using namespace Dali;
  25 +
  26 +namespace
  27 +{
  28 +//=============================================================================
  29 +// Demonstrates deferred shading with multiple render targets (for color,
  30 +// position, and normal), a Phong lighting model and 32 point lights.
  31 +//
  32 +// Invoked with the --show-lights it will render a mesh at each light position.
  33 +//=============================================================================
  34 +
  35 +#define QUOTE(x) DALI_COMPOSE_SHADER(x)
  36 +
  37 +#define MAX_LIGHTS 32
  38 +
  39 +#define DEFINE_MAX_LIGHTS "const int kMaxLights = " QUOTE(MAX_LIGHTS) ";"
  40 +
  41 +#define DEFINE(x) "#define " DALI_COMPOSE_SHADER(x) DALI_COMPOSE_SHADER(\n)
  42 +
  43 +//=============================================================================
  44 +// PRE-PASS
  45 +//=============================================================================
  46 +const char* const PREPASS_VSH = DALI_COMPOSE_SHADER(#version 300 es\n
  47 +precision mediump float;)
  48 + DALI_COMPOSE_SHADER(
  49 +
  50 +// DALI uniforms
  51 +uniform mat4 uMvpMatrix;
  52 +uniform mat3 uNormalMatrix;
  53 +uniform vec3 uSize;
  54 +
  55 +uniform vec3 uDepth_InvDepth_Near;\n)
  56 + DEFINE(DEPTH uDepth_InvDepth_Near.x)
  57 + DEFINE(INV_DEPTH uDepth_InvDepth_Near.y)
  58 + DEFINE(NEAR uDepth_InvDepth_Near.z)
  59 + DALI_COMPOSE_SHADER(
  60 +
  61 +in vec3 aPosition;
  62 +in vec3 aNormal;
  63 +
  64 +out vec4 vPosition;
  65 +out vec3 vNormal;
  66 +
  67 +vec4 Map(vec4 v) // projection space -> texture
  68 +{
  69 + return vec4(v.xyz / (2.f * v.w) + vec3(.5f), (v.w - NEAR) * INV_DEPTH);
  70 +}
  71 +
  72 +void main()
  73 +{
  74 + vec4 position = uMvpMatrix * vec4(aPosition * uSize, 1.f);
  75 + vPosition = Map(position);
  76 + gl_Position = position;
  77 +
  78 + vNormal = normalize(uNormalMatrix * aNormal);
  79 +});
  80 +
  81 +//=============================================================================
  82 +const char* const PREPASS_FSH = DALI_COMPOSE_SHADER(#version 300 es\n
  83 +precision mediump float;
  84 +
  85 +// DALI uniform
  86 +uniform vec4 uColor;
  87 +
  88 +in vec4 vPosition;
  89 +in vec3 vNormal;
  90 +
  91 +// These are our outputs.
  92 +layout(location = 0) out vec3 oNormal;
  93 +layout(location = 1) out vec4 oPosition;
  94 +layout(location = 2) out vec3 oColor;
  95 +
  96 +void main()
  97 +{
  98 + oColor = uColor.rgb;
  99 + oPosition = vPosition;
  100 + oNormal = normalize(vNormal) * .5f + .5f;
  101 +});
  102 +
  103 +//=============================================================================
  104 +// MAIN (LIGHTING) PASS
  105 +//=============================================================================
  106 +const char* const MAINPASS_VSH = DALI_COMPOSE_SHADER(#version 300 es\n
  107 +precision mediump float;
  108 +
  109 +// DALI uniforms
  110 +uniform mat4 uMvpMatrix;
  111 +uniform vec3 uSize;
  112 +
  113 +in vec3 aPosition;
  114 +in vec2 aTexCoord;
  115 +
  116 +out vec2 vUv;
  117 +
  118 +void main()
  119 +{
  120 + vec4 position = uMvpMatrix * vec4(aPosition * uSize, 1.f);
  121 + vUv = aTexCoord;
  122 +
  123 + gl_Position = position;
  124 +});
  125 +
  126 +//=============================================================================
  127 +const char* const MAINPASS_FSH = DALI_COMPOSE_SHADER(#version 300 es\n
  128 +precision mediump float;\n)
  129 + DEFINE_MAX_LIGHTS
  130 + DALI_COMPOSE_SHADER(
  131 +
  132 +const float kAttenuationConst = .05f;
  133 +const float kAttenuationLinear = .1f;
  134 +const float kAttenuationQuadratic = .15f;
  135 +
  136 +// G-buffer
  137 +uniform sampler2D uTextureNormal;
  138 +uniform sampler2D uTexturePosition;
  139 +uniform sampler2D uTextureColor;
  140 +
  141 +uniform mat4 uInvProjection;
  142 +
  143 +uniform vec3 uDepth_InvDepth_Near;\n)
  144 + DEFINE(DEPTH uDepth_InvDepth_Near.x)
  145 + DEFINE(INV_DEPTH uDepth_InvDepth_Near.y)
  146 + DEFINE(NEAR uDepth_InvDepth_Near.z)
  147 + DALI_COMPOSE_SHADER(
  148 +
  149 +// Light source uniforms
  150 +struct Light
  151 +{
  152 + vec3 position; // view space
  153 + float radius;
  154 + vec3 color;
  155 +};
  156 +
  157 +uniform Light uLights[kMaxLights];
  158 +
  159 +in vec2 vUv;
  160 +
  161 +out vec4 oColor;
  162 +
  163 +vec4 Unmap(vec4 m) // texture -> projection
  164 +{
  165 + m.w = m.w * DEPTH + NEAR;
  166 + m.xyz = (m.xyz - vec3(.5)) * (2.f * m.w);
  167 + return m;
  168 +}
  169 +
  170 +vec3 CalculateLighting(vec3 pos, vec3 normal)
  171 +{
  172 + vec3 viewDir = normalize(pos);
  173 + vec3 viewDirRefl = -reflect(viewDir, normal);
  174 +
  175 + vec3 light = vec3(0.04f); // fake ambient term
  176 + for (int i = 0; i < kMaxLights; ++i)
  177 + {
  178 + vec3 rel = pos - uLights[i].position;
  179 + float distance = length(rel);
  180 + rel /= distance;
  181 +
  182 + float a = uLights[i].radius / (kAttenuationConst + kAttenuationLinear * distance +
  183 + kAttenuationQuadratic * distance * distance); // attenuation
  184 +
  185 + float l = max(0.f, dot(normal, rel)); // lambertian
  186 + float s = pow(max(0.f, dot(viewDirRefl, rel)), 256.f); // specular
  187 +
  188 + light += (uLights[i].color * (l + s)) * a;
  189 + }
  190 +
  191 + return light;
  192 +}
  193 +
  194 +void main()
  195 +{
  196 + vec3 normSample = texture(uTextureNormal, vUv).xyz;
  197 + if (dot(normSample, normSample) == 0.f)
  198 + {
  199 + discard; // if we didn't write this texel, don't bother lighting it.
  200 + }
  201 +
  202 + vec3 normal = normalize(normSample - .5f);
  203 +
  204 + vec4 posSample = texture(uTexturePosition, vUv);
  205 + vec3 pos = (uInvProjection * Unmap(posSample)).xyz;
  206 +
  207 + vec3 color = texture(uTextureColor, vUv).rgb;
  208 + vec3 finalColor = color * CalculateLighting(pos, normal);
  209 +
  210 + oColor = vec4(finalColor, 1.f);
  211 +});
  212 +
  213 +//=============================================================================
  214 +// PRNG for floats.
  215 +struct FloatRand
  216 +{
  217 + std::random_device mDevice;
  218 + std::mt19937 mMersenneTwister;
  219 + std::uniform_real_distribution<float> mDistribution;
  220 +
  221 + FloatRand()
  222 + : mMersenneTwister(mDevice()),
  223 + mDistribution(0., 1.)
  224 + {}
  225 +
  226 + float operator()()
  227 + {
  228 + return mDistribution(mMersenneTwister);
  229 + }
  230 +};
  231 +
  232 +//=============================================================================
  233 +float FastFloor(float x)
  234 +{
  235 + return static_cast<int>(x) - static_cast<int>(x < 0);
  236 +}
  237 +
  238 +//=============================================================================
  239 +Vector3 FromHueSaturationLightness(Vector3 hsl)
  240 +{
  241 + Vector3 rgb;
  242 + if (hsl.y * hsl.y > 0.f)
  243 + {
  244 + if(hsl.x >= 360.f)
  245 + {
  246 + hsl.x -= 360.f;
  247 + }
  248 + hsl.x /= 60.f;
  249 +
  250 + int i = FastFloor(hsl.x);
  251 + float ff = hsl.x - i;
  252 + float p = hsl.z * (1.0 - hsl.y);
  253 + float q = hsl.z * (1.0 - (hsl.y * ff));
  254 + float t = hsl.z * (1.0 - (hsl.y * (1.f - ff)));
  255 +
  256 + switch (i)
  257 + {
  258 + case 0:
  259 + rgb.r = hsl.z;
  260 + rgb.g = t;
  261 + rgb.b = p;
  262 + break;
  263 +
  264 + case 1:
  265 + rgb.r = q;
  266 + rgb.g = hsl.z;
  267 + rgb.b = p;
  268 + break;
  269 +
  270 + case 2:
  271 + rgb.r = p;
  272 + rgb.g = hsl.z;
  273 + rgb.b = t;
  274 + break;
  275 +
  276 + case 3:
  277 + rgb.r = p;
  278 + rgb.g = q;
  279 + rgb.b = hsl.z;
  280 + break;
  281 +
  282 + case 4:
  283 + rgb.r = t;
  284 + rgb.g = p;
  285 + rgb.b = hsl.z;
  286 + break;
  287 +
  288 + case 5:
  289 + default:
  290 + rgb.r = hsl.z;
  291 + rgb.g = p;
  292 + rgb.b = q;
  293 + break;
  294 + }
  295 + }
  296 + else
  297 + {
  298 + rgb = Vector3::ONE * hsl.z;
  299 + }
  300 +
  301 + return rgb;
  302 +}
  303 +
  304 +//=============================================================================
  305 +Geometry CreateTexturedQuadGeometry(bool flipV)
  306 +{
  307 + // Create geometry -- unit square with whole of the texture mapped to it.
  308 + struct Vertex
  309 + {
  310 + Vector3 aPosition;
  311 + Vector2 aTexCoord;
  312 + };
  313 +
  314 + Vertex vertexData[] = {
  315 + { Vector3(-.5f, .5f, .0f), Vector2(.0f, 1.0f) },
  316 + { Vector3(.5f, .5f, .0f), Vector2(1.0f, 1.0f) },
  317 + { Vector3(-.5f, -.5f, .0f), Vector2(.0f, .0f) },
  318 + { Vector3(.5f, -.5f, .0f), Vector2(1.0f, .0f) },
  319 + };
  320 +
  321 + if (flipV)
  322 + {
  323 + std::swap(vertexData[0].aTexCoord, vertexData[2].aTexCoord);
  324 + std::swap(vertexData[1].aTexCoord, vertexData[3].aTexCoord);
  325 + }
  326 +
  327 + PropertyBuffer vertexBuffer = PropertyBuffer::New( Property::Map()
  328 + .Add( "aPosition", Property::VECTOR3 )
  329 + .Add( "aTexCoord", Property::VECTOR2 ) );
  330 + vertexBuffer.SetData( vertexData, std::extent<decltype(vertexData)>::value );
  331 +
  332 + Geometry geometry = Geometry::New();
  333 + geometry.AddVertexBuffer( vertexBuffer );
  334 + geometry.SetType( Geometry::TRIANGLE_STRIP );
  335 + return geometry;
  336 +}
  337 +
  338 +//=============================================================================
  339 +Geometry CreateOctahedron(bool invertNormals)
  340 +{
  341 + Vector3 positions[] = {
  342 + Vector3{ -1.f, 0.f, 0.f },
  343 + Vector3{ 1.f, 0.f, 0.f },
  344 + Vector3{ 0.f, -1.f, 0.f },
  345 + Vector3{ 0.f, 1.f, 0.f },
  346 + Vector3{ 0.f, 0.f, -1.f },
  347 + Vector3{ 0.f, 0.f, 1.f },
  348 + };
  349 +
  350 + struct Vertex
  351 + {
  352 + Vector3 position;
  353 + Vector3 normal;
  354 + };
  355 + Vertex vertexData[] = {
  356 + { positions[0] },
  357 + { positions[3] },
  358 + { positions[5] },
  359 +
  360 + { positions[5] },
  361 + { positions[3] },
  362 + { positions[1] },
  363 +
  364 + { positions[1] },
  365 + { positions[3] },
  366 + { positions[4] },
  367 +
  368 + { positions[4] },
  369 + { positions[3] },
  370 + { positions[0] },
  371 +
  372 + { positions[0] },
  373 + { positions[5] },
  374 + { positions[2] },
  375 +
  376 + { positions[5] },
  377 + { positions[1] },
  378 + { positions[2] },
  379 +
  380 + { positions[1] },
  381 + { positions[4] },
  382 + { positions[2] },
  383 +
  384 + { positions[4] },
  385 + { positions[0] },
  386 + { positions[2] },
  387 + };
  388 +
  389 + // Calculate normals
  390 + for (uint32_t i = 0; i < std::extent<decltype(vertexData)>::value / 3; ++i)
  391 + {
  392 + uint32_t idx = i * 3;
  393 +
  394 + Vector3 normal = (vertexData[idx + 2].position - vertexData[idx].position).
  395 + Cross(vertexData[idx + 1].position - vertexData[idx].position);
  396 + normal.Normalize();
  397 + normal *= invertNormals * 2.f - 1.f;
  398 +
  399 + vertexData[idx++].normal = normal;
  400 + vertexData[idx++].normal = normal;
  401 + vertexData[idx].normal = normal;
  402 + }
  403 +
  404 + // Configure property buffers and create geometry.
  405 + PropertyBuffer vertexBuffer = PropertyBuffer::New(Property::Map()
  406 + .Add("aPosition", Property::VECTOR3)
  407 + .Add("aNormal", Property::VECTOR3));
  408 + vertexBuffer.SetData(vertexData, std::extent<decltype(vertexData)>::value);
  409 +
  410 + Geometry geometry = Geometry::New();
  411 + geometry.AddVertexBuffer( vertexBuffer );
  412 + geometry.SetType( Geometry::TRIANGLES );
  413 + return geometry;
  414 +}
  415 +
  416 +//=============================================================================
  417 +enum RendererOptions
  418 +{
  419 + OPTION_NONE = 0x0,
  420 + OPTION_BLEND = 0x01,
  421 + OPTION_DEPTH_TEST = 0x02,
  422 + OPTION_DEPTH_WRITE = 0x04
  423 +};
  424 +
  425 +Renderer CreateRenderer(TextureSet textures, Geometry geometry, Shader shader, uint32_t options = OPTION_NONE)
  426 +{
  427 + Renderer renderer = Renderer::New(geometry, shader);
  428 + renderer.SetProperty(Renderer::Property::BLEND_MODE,
  429 + (options & OPTION_BLEND) ? BlendMode::ON : BlendMode::OFF);
  430 + renderer.SetProperty(Renderer::Property::DEPTH_TEST_MODE,
  431 + (options & OPTION_DEPTH_TEST) ? DepthTestMode::ON : DepthTestMode::OFF);
  432 + renderer.SetProperty(Renderer::Property::DEPTH_WRITE_MODE,
  433 + (options & OPTION_DEPTH_WRITE) ? DepthWriteMode::ON : DepthWriteMode::OFF);
  434 + renderer.SetProperty(Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK);
  435 +
  436 + if (!textures)
  437 + {
  438 + textures = TextureSet::New();
  439 + }
  440 +
  441 + renderer.SetTextures(textures);
  442 + return renderer;
  443 +}
  444 +
  445 +//=============================================================================
  446 +void CenterActor(Actor actor)
  447 +{
  448 + actor.SetAnchorPoint( AnchorPoint::CENTER );
  449 + actor.SetParentOrigin( ParentOrigin::CENTER );
  450 +}
  451 +
  452 +//=============================================================================
  453 +void RegisterDepthProperties(float depth, float near, Handle& h)
  454 +{
  455 + h.RegisterProperty("uDepth_InvDepth_Near", Vector3(depth, 1.f / depth, near));
  456 +}
  457 +
  458 +}
  459 +
  460 +//=============================================================================
  461 +class DeferredShadingExample : public ConnectionTracker
  462 +{
  463 +public:
  464 + struct Options
  465 + {
  466 + enum
  467 + {
  468 + NONE = 0x0,
  469 + SHOW_LIGHTS = 0x1,
  470 + };
  471 + };
  472 +
  473 + DeferredShadingExample(Application& app, uint32_t options = Options::NONE)
  474 + : mApp(app),
  475 + mOptions(options)
  476 + {
  477 + app.InitSignal().Connect( this, &DeferredShadingExample::Create );
  478 + app.TerminateSignal().Connect( this, &DeferredShadingExample::Destroy );
  479 + }
  480 +
  481 +private:
  482 + void Create(Application& app)
  483 + {
  484 + // Grab stage, configure layer
  485 + Stage stage = Stage::GetCurrent();
  486 + auto rootLayer = stage.GetRootLayer();
  487 + rootLayer.SetBehavior(Layer::LAYER_3D);
  488 +
  489 + auto stageSize = stage.GetSize();
  490 + auto stageHalfSize = stageSize * .5f;
  491 + auto invStageHalfSize = Vector2::ONE / stageHalfSize;
  492 +
  493 + float unit = stageSize.y / 24.f;
  494 +
  495 + // Get camera - we'll be re-using the same old camera in the two passes.
  496 + RenderTaskList tasks = stage.GetRenderTaskList();
  497 + CameraActor camera = tasks.GetTask(0).GetCameraActor();
  498 +
  499 + auto zCameraPos = camera.GetProperty(Actor::Property::POSITION_Z).Get<float>();
  500 + camera.SetFarClippingPlane(zCameraPos + stageSize.y * .5f);
  501 + camera.SetNearClippingPlane(zCameraPos - stageSize.y * .5f);
  502 +
  503 + const float zNear = camera.GetNearClippingPlane();
  504 + const float zFar = camera.GetFarClippingPlane();
  505 + const float depth = zFar - zNear;
  506 +
  507 + // Create root of scene that shall be rendered off-screen.
  508 + auto sceneRoot = Actor::New();
  509 + CenterActor(sceneRoot);
  510 +
  511 + mSceneRoot = sceneRoot;
  512 + stage.Add(sceneRoot);
  513 +
  514 + // Create an axis to spin our actors around.
  515 + auto axis = Actor::New();
  516 + CenterActor(axis);
  517 + sceneRoot.Add(axis);
  518 + mAxis = axis;
  519 +
  520 + // Create an octahedral mesh for our main actors and to visualise the light sources.
  521 + Geometry mesh = CreateOctahedron(false);
  522 +
  523 + // Create main actors
  524 + Shader preShader = Shader::New(PREPASS_VSH, PREPASS_FSH);
  525 + TextureSet noTexturesThanks = TextureSet::New();
  526 + Renderer meshRenderer = CreateRenderer(noTexturesThanks, mesh, preShader,
  527 + OPTION_DEPTH_TEST | OPTION_DEPTH_WRITE);
  528 + meshRenderer.SetProperty(Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK);
  529 + meshRenderer.RegisterProperty("uInvStageHalfSize", invStageHalfSize);
  530 + RegisterDepthProperties(depth, zNear, meshRenderer);
  531 + float c = 1.f;
  532 + for (auto v: {
  533 + Vector3{ -c, -c, -c },
  534 + Vector3{ c, -c, -c },
  535 + Vector3{ -c, c, -c },
  536 + Vector3{ c, c, -c },
  537 + Vector3{ -c, -c, c },
  538 + Vector3{ c, -c, c },
  539 + Vector3{ -c, c, c },
  540 + Vector3{ c, c, c },
  541 +
  542 + Vector3{ 0.f, -c, -c },
  543 + Vector3{ 0.f, c, -c },
  544 + Vector3{ 0.f, -c, c },
  545 + Vector3{ 0.f, c, c },
  546 +
  547 + Vector3{ -c, 0.f, -c },
  548 + Vector3{ c, 0.f, -c },
  549 + Vector3{ -c, 0.f, c },
  550 + Vector3{ c, 0.f, c },
  551 +
  552 + Vector3{ -c, -c, 0.f },
  553 + Vector3{ c, -c, 0.f },
  554 + Vector3{ -c, c, 0.f },
  555 + Vector3{ c, c, 0.f },
  556 + })
  557 + {
  558 + Actor a = Actor::New();
  559 + CenterActor(a);
  560 +
  561 + Vector3 position{ v * unit * 5.f };
  562 + a.SetPosition(position);
  563 +
  564 + float scale = (c + ((v.x + v.y + v.z) + c * 3.f) * .5f) / (c * 4.f);
  565 + Vector3 size{ Vector3::ONE * scale * unit * 2.f };
  566 + a.SetSize(size);
  567 +
  568 + a.SetColor(Color::WHITE * .25f +
  569 + (Color::RED * (v.x + c) / (c * 2.f) +
  570 + Color::GREEN * (v.y + c) / (c * 2.f) +
  571 + Color::BLUE * (v.z + c) / (c * 2.f)) * .015625f);
  572 + a.AddRenderer(meshRenderer);
  573 +
  574 + axis.Add(a);
  575 + }
  576 +
  577 + // Create off-screen textures, fbo and render task.
  578 + uint32_t width = static_cast<uint32_t>(stageSize.x);
  579 + uint32_t height = static_cast<uint32_t>(stageSize.y);
  580 +
  581 + Texture rttNormal = Texture::New(TextureType::TEXTURE_2D, Pixel::Format::RGB888,
  582 + width, height);
  583 + Texture rttPosition = Texture::New(TextureType::TEXTURE_2D, Pixel::Format::RGBA8888,
  584 + width, height);
  585 + Texture rttColor = Texture::New(TextureType::TEXTURE_2D, Pixel::Format::RGB888,
  586 + width, height);
  587 + FrameBuffer fbo = FrameBuffer::New(width, height, FrameBuffer::Attachment::DEPTH);
  588 + fbo.AttachColorTexture(rttNormal);
  589 + fbo.AttachColorTexture(rttPosition);
  590 + fbo.AttachColorTexture(rttColor);
  591 +
  592 + RenderTask sceneRender = tasks.CreateTask();
  593 + sceneRender.SetViewportSize(stageSize);
  594 + sceneRender.SetFrameBuffer(fbo);
  595 + sceneRender.SetCameraActor(camera);
  596 + sceneRender.SetSourceActor(sceneRoot);
  597 + sceneRender.SetInputEnabled(false);
  598 + sceneRender.SetCullMode(false);
  599 + sceneRender.SetClearEnabled(true);
  600 + sceneRender.SetClearColor(Color::BLACK);
  601 + sceneRender.SetExclusive(true);
  602 +
  603 + mSceneRender = sceneRender;
  604 +
  605 + // Create final image for deferred shading
  606 + auto finalImage = Actor::New();
  607 + CenterActor(finalImage);
  608 + finalImage.SetSize(stageSize);
  609 +
  610 + TextureSet finalImageTextures = TextureSet::New();
  611 + finalImageTextures.SetTexture(0, rttNormal);
  612 + finalImageTextures.SetTexture(1, rttPosition);
  613 + finalImageTextures.SetTexture(2, rttColor);
  614 +
  615 + Sampler sampler = Sampler::New();
  616 + sampler.SetFilterMode(FilterMode::NEAREST, FilterMode::NEAREST);
  617 + finalImageTextures.SetSampler(0, sampler);
  618 + finalImageTextures.SetSampler(1, sampler);
  619 + finalImageTextures.SetSampler(2, sampler);
  620 +
  621 + Shader shdMain = Shader::New(MAINPASS_VSH, MAINPASS_FSH);
  622 + Geometry finalImageGeom = CreateTexturedQuadGeometry(true);
  623 + Renderer finalImageRenderer = CreateRenderer(finalImageTextures, finalImageGeom, shdMain);
  624 + finalImageRenderer.RegisterProperty("uStageHalfSize", stageHalfSize);
  625 + RegisterDepthProperties(depth, zNear, finalImageRenderer);
  626 +
  627 + auto propInvProjection = finalImageRenderer.RegisterProperty("uInvProjection", Matrix::IDENTITY);
  628 + Constraint cnstrInvProjection = Constraint::New<Matrix>(finalImageRenderer, propInvProjection,
  629 + [zCameraPos, zNear, depth](Matrix& output, const PropertyInputContainer& input) {
  630 + output = input[0]->GetMatrix();
  631 + DALI_ASSERT_ALWAYS(output.Invert() && "Failed to invert projection matrix.");
  632 + });
  633 + cnstrInvProjection.AddSource(Source(camera, CameraActor::Property::PROJECTION_MATRIX));
  634 + cnstrInvProjection.AddSource(Source(camera, CameraActor::Property::VIEW_MATRIX));
  635 + cnstrInvProjection.Apply();
  636 +
  637 + finalImage.AddRenderer(finalImageRenderer);
  638 +
  639 + mFinalImage = finalImage;
  640 + stage.Add(finalImage);
  641 +
  642 + // Create a node for our lights
  643 + auto lights = Actor::New();
  644 + CenterActor(lights);
  645 + sceneRoot.Add(lights);
  646 +
  647 + // Create Lights
  648 + const bool showLights = mOptions & Options::SHOW_LIGHTS;
  649 + Renderer lightRenderer;
  650 + if (showLights)
  651 + {
  652 + Geometry lightMesh = CreateOctahedron(true);
  653 + lightRenderer = CreateRenderer(noTexturesThanks, lightMesh, preShader,
  654 + OPTION_DEPTH_TEST | OPTION_DEPTH_WRITE);
  655 + lightRenderer.SetProperty(Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::FRONT);
  656 + }
  657 +
  658 + Vector3 lightPos{ unit * 12.f, 0.f, 0.f };
  659 + float theta = M_PI * 2.f / MAX_LIGHTS;
  660 + float cosTheta = std::cos(theta);
  661 + float sinTheta = std::sin(theta);
  662 + for (int i = 0; i < MAX_LIGHTS; ++i)
  663 + {
  664 + Vector3 color = FromHueSaturationLightness(Vector3((360.f * i) / MAX_LIGHTS, .5f, 1.f));
  665 +
  666 + Actor light = CreateLight(lightPos * (1 + (i % 8)) / 8.f, unit * 16.f, color, camera, finalImageRenderer);
  667 +
  668 + float z = (((i & 1) << 1) - 1) * unit * 8.f;
  669 + lightPos = Vector3(cosTheta * lightPos.x - sinTheta * lightPos.y, sinTheta * lightPos.x + cosTheta * lightPos.y, z);
  670 +
  671 + if (showLights)
  672 + {
  673 + light.SetProperty(Actor::Property::SIZE, Vector3::ONE * unit / 8.f);
  674 + light.AddRenderer(lightRenderer);
  675 + }
  676 +
  677 + lights.Add(light);
  678 + }
  679 +
  680 + // Take them for a spin.
  681 + Animation animLights = Animation::New(40.f);
  682 + animLights.SetLooping(true);
  683 + animLights.AnimateBy(Property(lights, Actor::Property::ORIENTATION), Quaternion(Radian(M_PI * 2.f), Vector3::YAXIS));
  684 + animLights.Play();
  685 +
  686 + // Event handling
  687 + stage.KeyEventSignal().Connect(this, &DeferredShadingExample::OnKeyEvent);
  688 +
  689 + mPanDetector = PanGestureDetector::New();
  690 + mPanDetector.DetectedSignal().Connect(this, &DeferredShadingExample::OnPan);
  691 + mPanDetector.Attach(stage.GetRootLayer());
  692 + }
  693 +
  694 + void Destroy(Application& app)
  695 + {
  696 + Stage::GetCurrent().GetRenderTaskList().RemoveTask(mSceneRender);
  697 + mSceneRender.Reset();
  698 +
  699 + UnparentAndReset(mSceneRoot);
  700 + UnparentAndReset(mFinalImage);
  701 + }
  702 +
  703 + Actor CreateLight(Vector3 position, float radius, Vector3 color, CameraActor camera, Renderer renderer)
  704 + {
  705 + Actor light = Actor::New();
  706 + CenterActor(light);
  707 + light.SetProperty(Actor::Property::COLOR, Color::WHITE);
  708 + light.SetProperty(Actor::Property::POSITION, position);
  709 +
  710 + auto iPropRadius = light.RegisterProperty("radius", radius);
  711 + auto iPropLightColor = light.RegisterProperty("lightcolor", color);
  712 +
  713 + // Create light source uniforms on lighting shader.
  714 + char buffer[128];
  715 + char* writep = buffer + sprintf(buffer, "uLights[%d].", mNumLights);
  716 + ++mNumLights;
  717 +
  718 + strcpy(writep, "position");
  719 + auto oPropLightPos = renderer.RegisterProperty(buffer, position);
  720 +
  721 + strcpy(writep, "radius");
  722 + auto oPropLightRadius = renderer.RegisterProperty(buffer, radius);
  723 +
  724 + strcpy(writep, "color");
  725 + auto oPropLightColor = renderer.RegisterProperty(buffer, color);
  726 +
  727 + // Constrain the light position, radius and color to lighting shader uniforms.
  728 + // Convert light position to view space;
  729 + Constraint cLightPos = Constraint::New<Vector3>(renderer, oPropLightPos, [](Vector3& output, const PropertyInputContainer& input)
  730 + {
  731 + Vector4 worldPos(input[0]->GetVector3());
  732 + worldPos.w = 1.f;
  733 +
  734 + worldPos = input[1]->GetMatrix() * worldPos;
  735 + output = Vector3(worldPos);
  736 + });
  737 + cLightPos.AddSource(Source(light, Actor::Property::WORLD_POSITION));
  738 + cLightPos.AddSource(Source(camera, CameraActor::Property::VIEW_MATRIX));
  739 + cLightPos.Apply();
  740 +
  741 + Constraint cLightRadius = Constraint::New<float>(renderer, oPropLightRadius,
  742 + EqualToConstraint());
  743 + cLightRadius.AddSource(Source(light, iPropRadius));
  744 + cLightRadius.Apply();
  745 +
  746 + Constraint cLightColor = Constraint::New<Vector3>(renderer, oPropLightColor,
  747 + EqualToConstraint());
  748 + cLightColor.AddSource(Source(light, iPropLightColor));
  749 + cLightColor.Apply();
  750 +
  751 + return light;
  752 + }
  753 +
  754 + void OnPan(Actor, PanGesture const& gesture)
  755 + {
  756 + Quaternion q = mAxis.GetProperty(Actor::Property::ORIENTATION).Get<Quaternion>();
  757 + Quaternion qx(Radian(Degree(gesture.screenDisplacement.y) * -.5f), Vector3::XAXIS);
  758 + Quaternion qy(Radian(Degree(gesture.screenDisplacement.x) * .5f), Vector3::YAXIS);
  759 + mAxis.SetProperty(Actor::Property::ORIENTATION, qy * qx * q);
  760 + }
  761 +
  762 + void OnKeyEvent(const KeyEvent& event)
  763 + {
  764 + if(event.state == KeyEvent::Down)
  765 + {
  766 + if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
  767 + {
  768 + mApp.Quit();
  769 + }
  770 + }
  771 + }
  772 +
  773 + Application& mApp;
  774 + uint32_t mOptions;
  775 +
  776 + Actor mSceneRoot;
  777 + Actor mAxis;
  778 +
  779 + RenderTask mSceneRender;
  780 + Actor mFinalImage;
  781 +
  782 + int mNumLights = 0;
  783 +
  784 + PanGestureDetector mPanDetector;
  785 +};
  786 +
  787 +
  788 +int main(int argc, char** argv)
  789 +{
  790 + const bool showLights = [](int argc, char** argv)
  791 + {
  792 + auto endArgs = argv + argc;
  793 + return std::find_if(argv, endArgs, [](const char* arg)
  794 + {
  795 + return strcmp(arg, "--show-lights") == 0;
  796 + }) != endArgs;
  797 + }(argc, argv);
  798 +
  799 + Application app = Application::New(&argc, &argv);
  800 + DeferredShadingExample example(app, (showLights ? DeferredShadingExample::Options::SHOW_LIGHTS : 0));
  801 + app.MainLoop();
  802 + return 0;
  803 +}
resources/po/en_GB.po
@@ -58,6 +58,9 @@ msgstr &quot;Contact Cards&quot; @@ -58,6 +58,9 @@ msgstr &quot;Contact Cards&quot;
58 msgid "DALI_DEMO_STR_TITLE_CUBE_TRANSITION" 58 msgid "DALI_DEMO_STR_TITLE_CUBE_TRANSITION"
59 msgstr "Cube Effect" 59 msgstr "Cube Effect"
60 60
  61 +msgid "DALI_DEMO_STR_TITLE_DEFERRED_SHADING"
  62 +msgstr "Deferred Shading"
  63 +
61 msgid "DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION" 64 msgid "DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION"
62 msgstr "Dissolve Effect" 65 msgstr "Dissolve Effect"
63 66
resources/po/en_US.po
@@ -43,6 +43,9 @@ msgstr &quot;Clipping&quot; @@ -43,6 +43,9 @@ msgstr &quot;Clipping&quot;
43 msgid "DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER" 43 msgid "DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER"
44 msgstr "Clipping Draw Order" 44 msgstr "Clipping Draw Order"
45 45
  46 +msgid "DALI_DEMO_STR_TITLE_DEFERRED_SHADING"
  47 +msgstr "Deferred Shading"
  48 +
46 msgid "DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW" 49 msgid "DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW"
47 msgstr "Gaussian Blur" 50 msgstr "Gaussian Blur"
48 51
shared/dali-demo-strings.h
@@ -49,6 +49,7 @@ extern &quot;C&quot; @@ -49,6 +49,7 @@ extern &quot;C&quot;
49 #define DALI_DEMO_STR_TITLE_CARD_ACTIVE dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CARD_ACTIVE") 49 #define DALI_DEMO_STR_TITLE_CARD_ACTIVE dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CARD_ACTIVE")
50 #define DALI_DEMO_STR_TITLE_CLIPPING dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CLIPPING") 50 #define DALI_DEMO_STR_TITLE_CLIPPING dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CLIPPING")
51 #define DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER") 51 #define DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER")
  52 +#define DALI_DEMO_STR_TITLE_DEFERRED_SHADING dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_DEFERRED_SHADING")
52 #define DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW") 53 #define DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_GAUSSIAN_BLUR_VIEW")
53 #define DALI_DEMO_STR_TITLE_GESTURES dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_GESTURES") 54 #define DALI_DEMO_STR_TITLE_GESTURES dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_GESTURES")
54 #define DALI_DEMO_STR_TITLE_COLOR_GRADIENT dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_GRADIENT") 55 #define DALI_DEMO_STR_TITLE_COLOR_GRADIENT dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_GRADIENT")
@@ -153,6 +154,7 @@ extern &quot;C&quot; @@ -153,6 +154,7 @@ extern &quot;C&quot;
153 #define DALI_DEMO_STR_TITLE_COMPRESSED_TEXTURE_FORMATS "Compressed Texture Formats" 154 #define DALI_DEMO_STR_TITLE_COMPRESSED_TEXTURE_FORMATS "Compressed Texture Formats"
154 #define DALI_DEMO_STR_TITLE_CONTACT_CARDS "Contact Cards" 155 #define DALI_DEMO_STR_TITLE_CONTACT_CARDS "Contact Cards"
155 #define DALI_DEMO_STR_TITLE_CUBE_TRANSITION "Cube Effect" 156 #define DALI_DEMO_STR_TITLE_CUBE_TRANSITION "Cube Effect"
  157 +#define DALI_DEMO_STR_TITLE_DEFERRED_SHADING "Deferred Shading"
156 #define DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION "Dissolve Effect" 158 #define DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION "Dissolve Effect"
157 #define DALI_DEMO_STR_TITLE_DRAG_AND_DROP "Drag and Drop" 159 #define DALI_DEMO_STR_TITLE_DRAG_AND_DROP "Drag and Drop"
158 #define DALI_DEMO_STR_TITLE_EFFECTS_VIEW "Effects View" 160 #define DALI_DEMO_STR_TITLE_EFFECTS_VIEW "Effects View"