blob: 6dfd9255b61224e82791d4297235033d46827c47 [file] [log] [blame]
ztenghui55bfb4e2013-12-03 10:38:55 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
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#define LOG_TAG "OpenGLRenderer"
18
19#include <math.h>
20#include <utils/Log.h>
21
22#include "AmbientShadow.h"
23#include "ShadowTessellator.h"
ztenghui7b4516e2014-01-07 10:42:55 -080024#include "SpotShadow.h"
ztenghui55bfb4e2013-12-03 10:38:55 -080025
26namespace android {
27namespace uirenderer {
28
ztenghui7b4516e2014-01-07 10:42:55 -080029template<typename T>
30static inline T max(T a, T b) {
31 return a > b ? a : b;
32}
33
ztenghui55bfb4e2013-12-03 10:38:55 -080034// TODO: Support path as the input of the polygon instead of the rect's width
ztenghui7b4516e2014-01-07 10:42:55 -080035// and height. And the z values need to be computed according to the
36// transformation for each vertex.
37/**
38 * Generate the polygon for the caster.
39 *
40 * @param width the width of the caster
41 * @param height the height of the caster
42 * @param casterTransform transformation info of the caster
43 * @param polygon return the caster's polygon
44 *
45 */
46void ShadowTessellator::generateCasterPolygon(float width, float height,
47 const mat4& casterTransform, int vertexCount, Vector3* polygon) {
Chris Craik7b3dfa42014-01-16 16:21:10 -080048 Rect blockRect(0, 0, width, height);
ztenghui55bfb4e2013-12-03 10:38:55 -080049 polygon[0].x = blockRect.left;
50 polygon[0].y = blockRect.top;
Chris Craik7b3dfa42014-01-16 16:21:10 -080051 polygon[0].z = 0;
ztenghui55bfb4e2013-12-03 10:38:55 -080052 polygon[1].x = blockRect.right;
53 polygon[1].y = blockRect.top;
Chris Craik7b3dfa42014-01-16 16:21:10 -080054 polygon[1].z = 0;
ztenghui55bfb4e2013-12-03 10:38:55 -080055 polygon[2].x = blockRect.right;
56 polygon[2].y = blockRect.bottom;
Chris Craik7b3dfa42014-01-16 16:21:10 -080057 polygon[2].z = 0;
ztenghui55bfb4e2013-12-03 10:38:55 -080058 polygon[3].x = blockRect.left;
59 polygon[3].y = blockRect.bottom;
Chris Craik7b3dfa42014-01-16 16:21:10 -080060 polygon[3].z = 0;
61 casterTransform.mapPoint3d(polygon[0]);
62 casterTransform.mapPoint3d(polygon[1]);
63 casterTransform.mapPoint3d(polygon[2]);
64 casterTransform.mapPoint3d(polygon[3]);
ztenghui7b4516e2014-01-07 10:42:55 -080065}
66
67void ShadowTessellator::tessellateAmbientShadow(float width, float height,
68 const mat4& casterTransform, VertexBuffer& shadowVertexBuffer) {
69
70 const int vertexCount = 4;
71 Vector3 polygon[vertexCount];
72 generateCasterPolygon(width, height, casterTransform, vertexCount, polygon);
ztenghui55bfb4e2013-12-03 10:38:55 -080073
74 // A bunch of parameters to tweak the shadow.
75 // TODO: Allow some of these changable by debug settings or APIs.
ztenghui7b4516e2014-01-07 10:42:55 -080076 const int rays = 128;
ztenghui55bfb4e2013-12-03 10:38:55 -080077 const int layers = 2;
78 const float strength = 0.5;
ztenghui7b4516e2014-01-07 10:42:55 -080079 const float heightFactor = 128;
80 const float geomFactor = 64;
ztenghui55bfb4e2013-12-03 10:38:55 -080081
82 AmbientShadow::createAmbientShadow(polygon, vertexCount, rays, layers, strength,
83 heightFactor, geomFactor, shadowVertexBuffer);
84
85}
86
ztenghui7b4516e2014-01-07 10:42:55 -080087void ShadowTessellator::tessellateSpotShadow(float width, float height,
ztenghuicc3c2562014-01-17 10:34:10 -080088 const Vector3& lightPosScale, const mat4& receiverTransform,
89 int screenWidth, int screenHeight, const mat4& casterTransform,
90 VertexBuffer& shadowVertexBuffer) {
ztenghui7b4516e2014-01-07 10:42:55 -080091 const int vertexCount = 4;
92 Vector3 polygon[vertexCount];
93 generateCasterPolygon(width, height, casterTransform, vertexCount, polygon);
94
95 // A bunch of parameters to tweak the shadow.
96 // TODO: Allow some of these changable by debug settings or APIs.
97 const int rays = 256;
98 const int layers = 2;
99 const float strength = 0.5;
100 int maximal = max(screenWidth, screenHeight);
ztenghuicc3c2562014-01-17 10:34:10 -0800101 Vector3 lightCenter(screenWidth * lightPosScale.x, screenHeight * lightPosScale.y,
102 maximal * lightPosScale.z);
ztenghui7b4516e2014-01-07 10:42:55 -0800103#if DEBUG_SHADOW
104 ALOGD("light center %f %f %f", lightCenter.x, lightCenter.y, lightCenter.z);
105#endif
Chris Craik3197cde2014-01-16 14:03:39 -0800106
107 // light position (because it's in local space) needs to compensate for receiver transform
108 // TODO: should apply to light orientation, not just position
109 Matrix4 reverseReceiverTransform;
110 reverseReceiverTransform.loadInverse(receiverTransform);
111 reverseReceiverTransform.mapPoint3d(lightCenter);
112
ztenghuicc3c2562014-01-17 10:34:10 -0800113 const float lightSize = maximal / 4;
ztenghui7b4516e2014-01-07 10:42:55 -0800114 const int lightVertexCount = 16;
115
116 SpotShadow::createSpotShadow(polygon, vertexCount, lightCenter, lightSize,
117 lightVertexCount, rays, layers, strength, shadowVertexBuffer);
118
119}
ztenghui55bfb4e2013-12-03 10:38:55 -0800120}; // namespace uirenderer
121}; // namespace android