blob: f8debcb2883494c83f6598433967bdb226db786e [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
ztenghuid5e8ade2014-08-13 15:48:02 -070017/**
18 * Extra vertices for the corner for smoother corner.
19 * Only for outer vertices.
20 * Note that we use such extra memory to avoid an extra loop.
21 */
22// For half circle, we could add EXTRA_VERTEX_PER_PI vertices.
23// Set to 1 if we don't want to have any.
24#define EXTRA_CORNER_VERTEX_PER_PI 12
25
26// For the whole polygon, the sum of all the deltas b/t normals is 2 * M_PI,
27// therefore, the maximum number of extra vertices will be twice bigger.
28#define MAX_EXTRA_CORNER_VERTEX_NUMBER (2 * EXTRA_CORNER_VERTEX_PER_PI)
29
30// For each RADIANS_DIVISOR, we would allocate one more vertex b/t the normals.
31#define CORNER_RADIANS_DIVISOR (M_PI / EXTRA_CORNER_VERTEX_PER_PI)
32
33/**
34 * Extra vertices for the Edge for interpolation artifacts.
35 * Same value for both inner and outer vertices.
36 */
37#define EXTRA_EDGE_VERTEX_PER_PI 50
38
39#define MAX_EXTRA_EDGE_VERTEX_NUMBER (2 * EXTRA_EDGE_VERTEX_PER_PI)
40
41#define EDGE_RADIANS_DIVISOR (M_PI / EXTRA_EDGE_VERTEX_PER_PI)
42
43/**
44 * Other constants:
45 */
ztenghuiecf091e2015-02-17 13:26:10 -080046// For the edge of the penumbra, the opacity is 0. After transform (1 - alpha),
47// it is 1.
48#define TRANSFORMED_OUTER_OPACITY (1.0f)
ztenghuid5e8ade2014-08-13 15:48:02 -070049
50// Once the alpha difference is greater than this threshold, we will allocate extra
51// edge vertices.
52// If this is set to negative value, then all the edge will be tessellated.
53#define ALPHA_THRESHOLD (0.1f / 255.0f)
54
ztenghui55bfb4e2013-12-03 10:38:55 -080055#include <math.h>
56#include <utils/Log.h>
Chris Craik564acf72014-01-02 16:46:18 -080057#include <utils/Vector.h>
ztenghui55bfb4e2013-12-03 10:38:55 -080058
59#include "AmbientShadow.h"
ztenghui63d41ab2014-02-14 13:13:41 -080060#include "ShadowTessellator.h"
ztenghui55bfb4e2013-12-03 10:38:55 -080061#include "Vertex.h"
Tom Hudson2dc236b2014-10-15 15:46:42 -040062#include "VertexBuffer.h"
ztenghuid5e8ade2014-08-13 15:48:02 -070063#include "utils/MathUtils.h"
ztenghui55bfb4e2013-12-03 10:38:55 -080064
65namespace android {
66namespace uirenderer {
67
68/**
ztenghuid5e8ade2014-08-13 15:48:02 -070069 * Local utility functions.
70 */
71inline Vector2 getNormalFromVertices(const Vector3* vertices, int current, int next) {
72 // Convert from Vector3 to Vector2 first.
73 Vector2 currentVertex = { vertices[current].x, vertices[current].y };
74 Vector2 nextVertex = { vertices[next].x, vertices[next].y };
75
76 return ShadowTessellator::calculateNormal(currentVertex, nextVertex);
77}
78
79// The input z value will be converted to be non-negative inside.
80// The output must be ranged from 0 to 1.
81inline float getAlphaFromFactoredZ(float factoredZ) {
82 return 1.0 / (1 + MathUtils::max(factoredZ, 0.0f));
83}
84
ztenghuiecf091e2015-02-17 13:26:10 -080085// The shader is using gaussian function e^-(1-x)*(1-x)*4, therefore, we transform
86// the alpha value to (1 - alpha)
ztenghuid5e8ade2014-08-13 15:48:02 -070087inline float getTransformedAlphaFromAlpha(float alpha) {
ztenghuiecf091e2015-02-17 13:26:10 -080088 return 1.0f - alpha;
ztenghuid5e8ade2014-08-13 15:48:02 -070089}
90
ztenghuiecf091e2015-02-17 13:26:10 -080091// The output is ranged from 0 to 1.
ztenghuid5e8ade2014-08-13 15:48:02 -070092inline float getTransformedAlphaFromFactoredZ(float factoredZ) {
93 return getTransformedAlphaFromAlpha(getAlphaFromFactoredZ(factoredZ));
94}
95
ztenghuid5e8ade2014-08-13 15:48:02 -070096inline int getEdgeExtraAndUpdateSpike(Vector2* currentSpike,
97 const Vector3& secondVertex, const Vector3& centroid) {
98 Vector2 secondSpike = {secondVertex.x - centroid.x, secondVertex.y - centroid.y};
99 secondSpike.normalize();
100
ztenghui512e6432014-09-10 13:08:20 -0700101 int result = ShadowTessellator::getExtraVertexNumber(secondSpike, *currentSpike,
102 EDGE_RADIANS_DIVISOR);
ztenghuid5e8ade2014-08-13 15:48:02 -0700103 *currentSpike = secondSpike;
104 return result;
105}
106
107// Given the caster's vertex count, compute all the buffers size depending on
108// whether or not the caster is opaque.
109inline void computeBufferSize(int* totalVertexCount, int* totalIndexCount,
110 int* totalUmbraCount, int casterVertexCount, bool isCasterOpaque) {
111 // Compute the size of the vertex buffer.
112 int outerVertexCount = casterVertexCount * 2 + MAX_EXTRA_CORNER_VERTEX_NUMBER +
113 MAX_EXTRA_EDGE_VERTEX_NUMBER;
114 int innerVertexCount = casterVertexCount + MAX_EXTRA_EDGE_VERTEX_NUMBER;
115 *totalVertexCount = outerVertexCount + innerVertexCount;
116
117 // Compute the size of the index buffer.
118 *totalIndexCount = 2 * outerVertexCount + 2;
119
120 // Compute the size of the umber buffer.
121 // For translucent object, keep track of the umbra(inner) vertex in order to draw
122 // inside. We only need to store the index information.
123 *totalUmbraCount = 0;
124 if (!isCasterOpaque) {
125 // Add the centroid if occluder is translucent.
Andreas Gampeedaecc12014-11-10 20:54:07 -0800126 (*totalVertexCount)++;
ztenghuid5e8ade2014-08-13 15:48:02 -0700127 *totalIndexCount += 2 * innerVertexCount + 1;
128 *totalUmbraCount = innerVertexCount;
129 }
130}
131
132inline bool needsExtraForEdge(float firstAlpha, float secondAlpha) {
Bernhard Rosenkränzerc44958c72014-11-17 21:48:46 +0100133 return fabsf(firstAlpha - secondAlpha) > ALPHA_THRESHOLD;
ztenghuid5e8ade2014-08-13 15:48:02 -0700134}
135
136/**
ztenghui55bfb4e2013-12-03 10:38:55 -0800137 * Calculate the shadows as a triangle strips while alpha value as the
138 * shadow values.
139 *
ztenghui50ecf842014-03-11 16:52:30 -0700140 * @param isCasterOpaque Whether the caster is opaque.
ztenghui55bfb4e2013-12-03 10:38:55 -0800141 * @param vertices The shadow caster's polygon, which is represented in a Vector3
142 * array.
143 * @param vertexCount The length of caster's polygon in terms of number of
144 * vertices.
ztenghui63d41ab2014-02-14 13:13:41 -0800145 * @param centroid3d The centroid of the shadow caster.
ztenghui55bfb4e2013-12-03 10:38:55 -0800146 * @param heightFactor The factor showing the higher the object, the lighter the
147 * shadow.
148 * @param geomFactor The factor scaling the geometry expansion along the normal.
149 *
150 * @param shadowVertexBuffer Return an floating point array of (x, y, a)
151 * triangle strips mode.
ztenghuid5e8ade2014-08-13 15:48:02 -0700152 *
153 * An simple illustration:
154 * For now let's mark the outer vertex as Pi, the inner as Vi, the centroid as C.
155 *
156 * First project the occluder to the Z=0 surface.
157 * Then we got all the inner vertices. And we compute the normal for each edge.
158 * According to the normal, we generate outer vertices. E.g: We generate P1 / P4
159 * as extra corner vertices to make the corner looks round and smoother.
160 *
161 * Due to the fact that the alpha is not linear interpolated along the inner
162 * edge, when the alpha is different, we may add extra vertices such as P2.1, P2.2,
163 * V0.1, V0.2 to avoid the visual artifacts.
164 *
165 * (P3)
166 * (P2) (P2.1) (P2.2) | ' (P4)
167 * (P1)' | | | | '
168 * ' | | | | '
169 * (P0) ------------------------------------------------(P5)
170 * | (V0) (V0.1) (V0.2) |(V1)
171 * | |
172 * | |
173 * | (C) |
174 * | |
175 * | |
176 * | |
177 * | |
178 * (V3)-----------------------------------(V2)
ztenghui55bfb4e2013-12-03 10:38:55 -0800179 */
Chris Craik05f3d6e2014-06-02 16:27:04 -0700180void AmbientShadow::createAmbientShadow(bool isCasterOpaque,
ztenghuid5e8ade2014-08-13 15:48:02 -0700181 const Vector3* casterVertices, int casterVertexCount, const Vector3& centroid3d,
ztenghui50ecf842014-03-11 16:52:30 -0700182 float heightFactor, float geomFactor, VertexBuffer& shadowVertexBuffer) {
Chris Craik117bdbc2015-02-05 10:12:38 -0800183 shadowVertexBuffer.setMeshFeatureFlags(VertexBuffer::kAlpha | VertexBuffer::kIndices);
ztenghui55bfb4e2013-12-03 10:38:55 -0800184
ztenghuid5e8ade2014-08-13 15:48:02 -0700185 // In order to computer the outer vertices in one loop, we need pre-compute
186 // the normal by the vertex (n - 1) to vertex 0, and the spike and alpha value
187 // for vertex 0.
188 Vector2 previousNormal = getNormalFromVertices(casterVertices,
189 casterVertexCount - 1 , 0);
190 Vector2 currentSpike = {casterVertices[0].x - centroid3d.x,
191 casterVertices[0].y - centroid3d.y};
192 currentSpike.normalize();
193 float currentAlpha = getAlphaFromFactoredZ(casterVertices[0].z * heightFactor);
ztenghui55bfb4e2013-12-03 10:38:55 -0800194
ztenghuid5e8ade2014-08-13 15:48:02 -0700195 // Preparing all the output data.
196 int totalVertexCount, totalIndexCount, totalUmbraCount;
197 computeBufferSize(&totalVertexCount, &totalIndexCount, &totalUmbraCount,
198 casterVertexCount, isCasterOpaque);
ztenghui50ecf842014-03-11 16:52:30 -0700199 AlphaVertex* shadowVertices =
ztenghuid5e8ade2014-08-13 15:48:02 -0700200 shadowVertexBuffer.alloc<AlphaVertex>(totalVertexCount);
201 int vertexBufferIndex = 0;
202 uint16_t* indexBuffer = shadowVertexBuffer.allocIndices<uint16_t>(totalIndexCount);
203 int indexBufferIndex = 0;
204 uint16_t umbraVertices[totalUmbraCount];
205 int umbraIndex = 0;
ztenghui55bfb4e2013-12-03 10:38:55 -0800206
ztenghuid5e8ade2014-08-13 15:48:02 -0700207 for (int i = 0; i < casterVertexCount; i++) {
208 // Corner: first figure out the extra vertices we need for the corner.
209 const Vector3& innerVertex = casterVertices[i];
210 Vector2 currentNormal = getNormalFromVertices(casterVertices, i,
211 (i + 1) % casterVertexCount);
ztenghui55bfb4e2013-12-03 10:38:55 -0800212
ztenghui512e6432014-09-10 13:08:20 -0700213 int extraVerticesNumber = ShadowTessellator::getExtraVertexNumber(currentNormal,
214 previousNormal, CORNER_RADIANS_DIVISOR);
ztenghui55bfb4e2013-12-03 10:38:55 -0800215
ztenghuid5e8ade2014-08-13 15:48:02 -0700216 float expansionDist = innerVertex.z * heightFactor * geomFactor;
217 const int cornerSlicesNumber = extraVerticesNumber + 1; // Minimal as 1.
ztenghui55bfb4e2013-12-03 10:38:55 -0800218#if DEBUG_SHADOW
ztenghuid5e8ade2014-08-13 15:48:02 -0700219 ALOGD("cornerSlicesNumber is %d", cornerSlicesNumber);
ztenghui63d41ab2014-02-14 13:13:41 -0800220#endif
ztenghui55bfb4e2013-12-03 10:38:55 -0800221
ztenghuid5e8ade2014-08-13 15:48:02 -0700222 // Corner: fill the corner Vertex Buffer(VB) and Index Buffer(IB).
223 // We fill the inner vertex first, such that we can fill the index buffer
224 // inside the loop.
225 int currentInnerVertexIndex = vertexBufferIndex;
226 if (!isCasterOpaque) {
227 umbraVertices[umbraIndex++] = vertexBufferIndex;
ztenghui7940dc52014-04-22 11:21:49 -0700228 }
ztenghuid5e8ade2014-08-13 15:48:02 -0700229 AlphaVertex::set(&shadowVertices[vertexBufferIndex++], casterVertices[i].x,
230 casterVertices[i].y,
231 getTransformedAlphaFromAlpha(currentAlpha));
ztenghui7940dc52014-04-22 11:21:49 -0700232
ztenghuid5e8ade2014-08-13 15:48:02 -0700233 const Vector3& innerStart = casterVertices[i];
ztenghui7940dc52014-04-22 11:21:49 -0700234
ztenghuid5e8ade2014-08-13 15:48:02 -0700235 // outerStart is the first outer vertex for this inner vertex.
236 // outerLast is the last outer vertex for this inner vertex.
237 Vector2 outerStart = {0, 0};
238 Vector2 outerLast = {0, 0};
239 // This will create vertices from [0, cornerSlicesNumber] inclusively,
240 // which means minimally 2 vertices even without the extra ones.
241 for (int j = 0; j <= cornerSlicesNumber; j++) {
242 Vector2 averageNormal =
243 previousNormal * (cornerSlicesNumber - j) + currentNormal * j;
244 averageNormal /= cornerSlicesNumber;
245 averageNormal.normalize();
246 Vector2 outerVertex;
247 outerVertex.x = innerVertex.x + averageNormal.x * expansionDist;
248 outerVertex.y = innerVertex.y + averageNormal.y * expansionDist;
ztenghui7940dc52014-04-22 11:21:49 -0700249
ztenghuid5e8ade2014-08-13 15:48:02 -0700250 indexBuffer[indexBufferIndex++] = vertexBufferIndex;
251 indexBuffer[indexBufferIndex++] = currentInnerVertexIndex;
252 AlphaVertex::set(&shadowVertices[vertexBufferIndex++], outerVertex.x,
ztenghuiecf091e2015-02-17 13:26:10 -0800253 outerVertex.y, TRANSFORMED_OUTER_OPACITY);
ztenghui7940dc52014-04-22 11:21:49 -0700254
ztenghuid5e8ade2014-08-13 15:48:02 -0700255 if (j == 0) {
256 outerStart = outerVertex;
257 } else if (j == cornerSlicesNumber) {
258 outerLast = outerVertex;
ztenghui7940dc52014-04-22 11:21:49 -0700259 }
260 }
ztenghuid5e8ade2014-08-13 15:48:02 -0700261 previousNormal = currentNormal;
ztenghui55bfb4e2013-12-03 10:38:55 -0800262
ztenghuid5e8ade2014-08-13 15:48:02 -0700263 // Edge: first figure out the extra vertices needed for the edge.
264 const Vector3& innerNext = casterVertices[(i + 1) % casterVertexCount];
265 float nextAlpha = getAlphaFromFactoredZ(innerNext.z * heightFactor);
266 if (needsExtraForEdge(currentAlpha, nextAlpha)) {
267 // TODO: See if we can / should cache this outer vertex across the loop.
268 Vector2 outerNext;
269 float expansionDist = innerNext.z * heightFactor * geomFactor;
270 outerNext.x = innerNext.x + currentNormal.x * expansionDist;
271 outerNext.y = innerNext.y + currentNormal.y * expansionDist;
272
273 // Compute the angle and see how many extra points we need.
274 int extraVerticesNumber = getEdgeExtraAndUpdateSpike(&currentSpike,
275 innerNext, centroid3d);
ztenghui7940dc52014-04-22 11:21:49 -0700276#if DEBUG_SHADOW
ztenghuid5e8ade2014-08-13 15:48:02 -0700277 ALOGD("extraVerticesNumber %d for edge %d", extraVerticesNumber, i);
ztenghui7940dc52014-04-22 11:21:49 -0700278#endif
ztenghuid5e8ade2014-08-13 15:48:02 -0700279 // Edge: fill the edge's VB and IB.
280 // This will create vertices pair from [1, extraVerticesNumber - 1].
281 // If there is no extra vertices created here, the edge will be drawn
282 // as just 2 triangles.
283 for (int k = 1; k < extraVerticesNumber; k++) {
284 int startWeight = extraVerticesNumber - k;
285 Vector2 currentOuter =
286 (outerLast * startWeight + outerNext * k) / extraVerticesNumber;
287 indexBuffer[indexBufferIndex++] = vertexBufferIndex;
288 AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentOuter.x,
ztenghuiecf091e2015-02-17 13:26:10 -0800289 currentOuter.y, TRANSFORMED_OUTER_OPACITY);
ztenghui55bfb4e2013-12-03 10:38:55 -0800290
ztenghuid5e8ade2014-08-13 15:48:02 -0700291 if (!isCasterOpaque) {
292 umbraVertices[umbraIndex++] = vertexBufferIndex;
ztenghui55bfb4e2013-12-03 10:38:55 -0800293 }
ztenghuid5e8ade2014-08-13 15:48:02 -0700294 Vector3 currentInner =
295 (innerStart * startWeight + innerNext * k) / extraVerticesNumber;
296 indexBuffer[indexBufferIndex++] = vertexBufferIndex;
297 AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentInner.x,
298 currentInner.y,
299 getTransformedAlphaFromFactoredZ(currentInner.z * heightFactor));
ztenghui55bfb4e2013-12-03 10:38:55 -0800300 }
301 }
ztenghuid5e8ade2014-08-13 15:48:02 -0700302 currentAlpha = nextAlpha;
ztenghui55bfb4e2013-12-03 10:38:55 -0800303 }
ztenghui55bfb4e2013-12-03 10:38:55 -0800304
ztenghuid5e8ade2014-08-13 15:48:02 -0700305 indexBuffer[indexBufferIndex++] = 1;
306 indexBuffer[indexBufferIndex++] = 0;
ztenghui55bfb4e2013-12-03 10:38:55 -0800307
ztenghuid5e8ade2014-08-13 15:48:02 -0700308 if (!isCasterOpaque) {
309 // Add the centroid as the last one in the vertex buffer.
310 float centroidOpacity =
311 getTransformedAlphaFromFactoredZ(centroid3d.z * heightFactor);
312 int centroidIndex = vertexBufferIndex;
313 AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid3d.x,
314 centroid3d.y, centroidOpacity);
315
316 for (int i = 0; i < umbraIndex; i++) {
317 // Note that umbraVertices[0] is always 0.
318 // So the start and the end of the umbra are using the "0".
319 // And penumbra ended with 0, so a degenerated triangle is formed b/t
320 // the umbra and penumbra.
321 indexBuffer[indexBufferIndex++] = umbraVertices[i];
322 indexBuffer[indexBufferIndex++] = centroidIndex;
323 }
324 indexBuffer[indexBufferIndex++] = 0;
ztenghui55bfb4e2013-12-03 10:38:55 -0800325 }
ztenghuid5e8ade2014-08-13 15:48:02 -0700326
327 // At the end, update the real index and vertex buffer size.
328 shadowVertexBuffer.updateVertexCount(vertexBufferIndex);
329 shadowVertexBuffer.updateIndexCount(indexBufferIndex);
Chris Craik4ac36f82014-12-09 16:54:03 -0800330 shadowVertexBuffer.computeBounds<AlphaVertex>();
ztenghuid5e8ade2014-08-13 15:48:02 -0700331
ztenghuid2dcd6f2014-10-29 16:04:29 -0700332 ShadowTessellator::checkOverflow(vertexBufferIndex, totalVertexCount, "Ambient Vertex Buffer");
333 ShadowTessellator::checkOverflow(indexBufferIndex, totalIndexCount, "Ambient Index Buffer");
334 ShadowTessellator::checkOverflow(umbraIndex, totalUmbraCount, "Ambient Umbra Buffer");
ztenghuid5e8ade2014-08-13 15:48:02 -0700335
336#if DEBUG_SHADOW
337 for (int i = 0; i < vertexBufferIndex; i++) {
338 ALOGD("vertexBuffer i %d, (%f, %f %f)", i, shadowVertices[i].x, shadowVertices[i].y,
339 shadowVertices[i].alpha);
340 }
341 for (int i = 0; i < indexBufferIndex; i++) {
342 ALOGD("indexBuffer i %d, indexBuffer[i] %d", i, indexBuffer[i]);
343 }
344#endif
ztenghui55bfb4e2013-12-03 10:38:55 -0800345}
346
347}; // namespace uirenderer
348}; // namespace android