blob: 4873479fdf17ab967c17bb657ea5f227149d56cc [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
ztenghuid5e8ade2014-08-13 15:48:02 -070019/**
20 * Extra vertices for the corner for smoother corner.
21 * Only for outer vertices.
22 * Note that we use such extra memory to avoid an extra loop.
23 */
24// For half circle, we could add EXTRA_VERTEX_PER_PI vertices.
25// Set to 1 if we don't want to have any.
26#define EXTRA_CORNER_VERTEX_PER_PI 12
27
28// For the whole polygon, the sum of all the deltas b/t normals is 2 * M_PI,
29// therefore, the maximum number of extra vertices will be twice bigger.
30#define MAX_EXTRA_CORNER_VERTEX_NUMBER (2 * EXTRA_CORNER_VERTEX_PER_PI)
31
32// For each RADIANS_DIVISOR, we would allocate one more vertex b/t the normals.
33#define CORNER_RADIANS_DIVISOR (M_PI / EXTRA_CORNER_VERTEX_PER_PI)
34
35/**
36 * Extra vertices for the Edge for interpolation artifacts.
37 * Same value for both inner and outer vertices.
38 */
39#define EXTRA_EDGE_VERTEX_PER_PI 50
40
41#define MAX_EXTRA_EDGE_VERTEX_NUMBER (2 * EXTRA_EDGE_VERTEX_PER_PI)
42
43#define EDGE_RADIANS_DIVISOR (M_PI / EXTRA_EDGE_VERTEX_PER_PI)
44
45/**
46 * Other constants:
47 */
48// For the edge of the penumbra, the opacity is 0.
49#define OUTER_OPACITY (0.0f)
50
51// Once the alpha difference is greater than this threshold, we will allocate extra
52// edge vertices.
53// If this is set to negative value, then all the edge will be tessellated.
54#define ALPHA_THRESHOLD (0.1f / 255.0f)
55
ztenghui55bfb4e2013-12-03 10:38:55 -080056#include <math.h>
57#include <utils/Log.h>
Chris Craik564acf72014-01-02 16:46:18 -080058#include <utils/Vector.h>
ztenghui55bfb4e2013-12-03 10:38:55 -080059
60#include "AmbientShadow.h"
ztenghui63d41ab2014-02-14 13:13:41 -080061#include "ShadowTessellator.h"
ztenghui55bfb4e2013-12-03 10:38:55 -080062#include "Vertex.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
85inline float getTransformedAlphaFromAlpha(float alpha) {
86 return acosf(1.0f - 2.0f * alpha);
87}
88
89// The output is ranged from 0 to M_PI.
90inline float getTransformedAlphaFromFactoredZ(float factoredZ) {
91 return getTransformedAlphaFromAlpha(getAlphaFromFactoredZ(factoredZ));
92}
93
94inline int getExtraVertexNumber(const Vector2& vector1, const Vector2& vector2,
95 float divisor) {
ztenghui26131362014-09-01 17:19:51 -070096 // When there is no distance difference, there is no need for extra vertices.
97 if (vector1.lengthSquared() == 0 || vector2.lengthSquared() == 0) {
98 return 0;
99 }
ztenghuid5e8ade2014-08-13 15:48:02 -0700100 // The formula is :
101 // extraNumber = floor(acos(dot(n1, n2)) / (M_PI / EXTRA_VERTEX_PER_PI))
102 // The value ranges for each step are:
103 // dot( ) --- [-1, 1]
104 // acos( ) --- [0, M_PI]
105 // floor(...) --- [0, EXTRA_VERTEX_PER_PI]
106 float dotProduct = vector1.dot(vector2);
107 // TODO: Use look up table for the dotProduct to extraVerticesNumber
108 // computation, if needed.
109 float angle = acosf(dotProduct);
110 return (int) floor(angle / divisor);
111}
112
113inline void checkOverflow(int used, int total, const char* bufferName) {
114 LOG_ALWAYS_FATAL_IF(used > total, "Error: %s overflow!!! used %d, total %d",
115 bufferName, used, total);
116}
117
118inline int getEdgeExtraAndUpdateSpike(Vector2* currentSpike,
119 const Vector3& secondVertex, const Vector3& centroid) {
120 Vector2 secondSpike = {secondVertex.x - centroid.x, secondVertex.y - centroid.y};
121 secondSpike.normalize();
122
123 int result = getExtraVertexNumber(secondSpike, *currentSpike, EDGE_RADIANS_DIVISOR);
124 *currentSpike = secondSpike;
125 return result;
126}
127
128// Given the caster's vertex count, compute all the buffers size depending on
129// whether or not the caster is opaque.
130inline void computeBufferSize(int* totalVertexCount, int* totalIndexCount,
131 int* totalUmbraCount, int casterVertexCount, bool isCasterOpaque) {
132 // Compute the size of the vertex buffer.
133 int outerVertexCount = casterVertexCount * 2 + MAX_EXTRA_CORNER_VERTEX_NUMBER +
134 MAX_EXTRA_EDGE_VERTEX_NUMBER;
135 int innerVertexCount = casterVertexCount + MAX_EXTRA_EDGE_VERTEX_NUMBER;
136 *totalVertexCount = outerVertexCount + innerVertexCount;
137
138 // Compute the size of the index buffer.
139 *totalIndexCount = 2 * outerVertexCount + 2;
140
141 // Compute the size of the umber buffer.
142 // For translucent object, keep track of the umbra(inner) vertex in order to draw
143 // inside. We only need to store the index information.
144 *totalUmbraCount = 0;
145 if (!isCasterOpaque) {
146 // Add the centroid if occluder is translucent.
147 *totalVertexCount++;
148 *totalIndexCount += 2 * innerVertexCount + 1;
149 *totalUmbraCount = innerVertexCount;
150 }
151}
152
153inline bool needsExtraForEdge(float firstAlpha, float secondAlpha) {
154 return abs(firstAlpha - secondAlpha) > ALPHA_THRESHOLD;
155}
156
157/**
ztenghui55bfb4e2013-12-03 10:38:55 -0800158 * Calculate the shadows as a triangle strips while alpha value as the
159 * shadow values.
160 *
ztenghui50ecf842014-03-11 16:52:30 -0700161 * @param isCasterOpaque Whether the caster is opaque.
ztenghui55bfb4e2013-12-03 10:38:55 -0800162 * @param vertices The shadow caster's polygon, which is represented in a Vector3
163 * array.
164 * @param vertexCount The length of caster's polygon in terms of number of
165 * vertices.
ztenghui63d41ab2014-02-14 13:13:41 -0800166 * @param centroid3d The centroid of the shadow caster.
ztenghui55bfb4e2013-12-03 10:38:55 -0800167 * @param heightFactor The factor showing the higher the object, the lighter the
168 * shadow.
169 * @param geomFactor The factor scaling the geometry expansion along the normal.
170 *
171 * @param shadowVertexBuffer Return an floating point array of (x, y, a)
172 * triangle strips mode.
ztenghuid5e8ade2014-08-13 15:48:02 -0700173 *
174 * An simple illustration:
175 * For now let's mark the outer vertex as Pi, the inner as Vi, the centroid as C.
176 *
177 * First project the occluder to the Z=0 surface.
178 * Then we got all the inner vertices. And we compute the normal for each edge.
179 * According to the normal, we generate outer vertices. E.g: We generate P1 / P4
180 * as extra corner vertices to make the corner looks round and smoother.
181 *
182 * Due to the fact that the alpha is not linear interpolated along the inner
183 * edge, when the alpha is different, we may add extra vertices such as P2.1, P2.2,
184 * V0.1, V0.2 to avoid the visual artifacts.
185 *
186 * (P3)
187 * (P2) (P2.1) (P2.2) | ' (P4)
188 * (P1)' | | | | '
189 * ' | | | | '
190 * (P0) ------------------------------------------------(P5)
191 * | (V0) (V0.1) (V0.2) |(V1)
192 * | |
193 * | |
194 * | (C) |
195 * | |
196 * | |
197 * | |
198 * | |
199 * (V3)-----------------------------------(V2)
ztenghui55bfb4e2013-12-03 10:38:55 -0800200 */
Chris Craik05f3d6e2014-06-02 16:27:04 -0700201void AmbientShadow::createAmbientShadow(bool isCasterOpaque,
ztenghuid5e8ade2014-08-13 15:48:02 -0700202 const Vector3* casterVertices, int casterVertexCount, const Vector3& centroid3d,
ztenghui50ecf842014-03-11 16:52:30 -0700203 float heightFactor, float geomFactor, VertexBuffer& shadowVertexBuffer) {
ztenghuid5e8ade2014-08-13 15:48:02 -0700204 shadowVertexBuffer.setMode(VertexBuffer::kIndices);
ztenghui55bfb4e2013-12-03 10:38:55 -0800205
ztenghuid5e8ade2014-08-13 15:48:02 -0700206 // In order to computer the outer vertices in one loop, we need pre-compute
207 // the normal by the vertex (n - 1) to vertex 0, and the spike and alpha value
208 // for vertex 0.
209 Vector2 previousNormal = getNormalFromVertices(casterVertices,
210 casterVertexCount - 1 , 0);
211 Vector2 currentSpike = {casterVertices[0].x - centroid3d.x,
212 casterVertices[0].y - centroid3d.y};
213 currentSpike.normalize();
214 float currentAlpha = getAlphaFromFactoredZ(casterVertices[0].z * heightFactor);
ztenghui55bfb4e2013-12-03 10:38:55 -0800215
ztenghuid5e8ade2014-08-13 15:48:02 -0700216 // Preparing all the output data.
217 int totalVertexCount, totalIndexCount, totalUmbraCount;
218 computeBufferSize(&totalVertexCount, &totalIndexCount, &totalUmbraCount,
219 casterVertexCount, isCasterOpaque);
ztenghui50ecf842014-03-11 16:52:30 -0700220 AlphaVertex* shadowVertices =
ztenghuid5e8ade2014-08-13 15:48:02 -0700221 shadowVertexBuffer.alloc<AlphaVertex>(totalVertexCount);
222 int vertexBufferIndex = 0;
223 uint16_t* indexBuffer = shadowVertexBuffer.allocIndices<uint16_t>(totalIndexCount);
224 int indexBufferIndex = 0;
225 uint16_t umbraVertices[totalUmbraCount];
226 int umbraIndex = 0;
ztenghui55bfb4e2013-12-03 10:38:55 -0800227
ztenghuid5e8ade2014-08-13 15:48:02 -0700228 for (int i = 0; i < casterVertexCount; i++) {
229 // Corner: first figure out the extra vertices we need for the corner.
230 const Vector3& innerVertex = casterVertices[i];
231 Vector2 currentNormal = getNormalFromVertices(casterVertices, i,
232 (i + 1) % casterVertexCount);
ztenghui55bfb4e2013-12-03 10:38:55 -0800233
ztenghuid5e8ade2014-08-13 15:48:02 -0700234 int extraVerticesNumber = getExtraVertexNumber(currentNormal, previousNormal,
235 CORNER_RADIANS_DIVISOR);
ztenghui55bfb4e2013-12-03 10:38:55 -0800236
ztenghuid5e8ade2014-08-13 15:48:02 -0700237 float expansionDist = innerVertex.z * heightFactor * geomFactor;
238 const int cornerSlicesNumber = extraVerticesNumber + 1; // Minimal as 1.
ztenghui55bfb4e2013-12-03 10:38:55 -0800239#if DEBUG_SHADOW
ztenghuid5e8ade2014-08-13 15:48:02 -0700240 ALOGD("cornerSlicesNumber is %d", cornerSlicesNumber);
ztenghui63d41ab2014-02-14 13:13:41 -0800241#endif
ztenghui55bfb4e2013-12-03 10:38:55 -0800242
ztenghuid5e8ade2014-08-13 15:48:02 -0700243 // Corner: fill the corner Vertex Buffer(VB) and Index Buffer(IB).
244 // We fill the inner vertex first, such that we can fill the index buffer
245 // inside the loop.
246 int currentInnerVertexIndex = vertexBufferIndex;
247 if (!isCasterOpaque) {
248 umbraVertices[umbraIndex++] = vertexBufferIndex;
ztenghui7940dc52014-04-22 11:21:49 -0700249 }
ztenghuid5e8ade2014-08-13 15:48:02 -0700250 AlphaVertex::set(&shadowVertices[vertexBufferIndex++], casterVertices[i].x,
251 casterVertices[i].y,
252 getTransformedAlphaFromAlpha(currentAlpha));
ztenghui7940dc52014-04-22 11:21:49 -0700253
ztenghuid5e8ade2014-08-13 15:48:02 -0700254 const Vector3& innerStart = casterVertices[i];
ztenghui7940dc52014-04-22 11:21:49 -0700255
ztenghuid5e8ade2014-08-13 15:48:02 -0700256 // outerStart is the first outer vertex for this inner vertex.
257 // outerLast is the last outer vertex for this inner vertex.
258 Vector2 outerStart = {0, 0};
259 Vector2 outerLast = {0, 0};
260 // This will create vertices from [0, cornerSlicesNumber] inclusively,
261 // which means minimally 2 vertices even without the extra ones.
262 for (int j = 0; j <= cornerSlicesNumber; j++) {
263 Vector2 averageNormal =
264 previousNormal * (cornerSlicesNumber - j) + currentNormal * j;
265 averageNormal /= cornerSlicesNumber;
266 averageNormal.normalize();
267 Vector2 outerVertex;
268 outerVertex.x = innerVertex.x + averageNormal.x * expansionDist;
269 outerVertex.y = innerVertex.y + averageNormal.y * expansionDist;
ztenghui7940dc52014-04-22 11:21:49 -0700270
ztenghuid5e8ade2014-08-13 15:48:02 -0700271 indexBuffer[indexBufferIndex++] = vertexBufferIndex;
272 indexBuffer[indexBufferIndex++] = currentInnerVertexIndex;
273 AlphaVertex::set(&shadowVertices[vertexBufferIndex++], outerVertex.x,
274 outerVertex.y, OUTER_OPACITY);
ztenghui7940dc52014-04-22 11:21:49 -0700275
ztenghuid5e8ade2014-08-13 15:48:02 -0700276 if (j == 0) {
277 outerStart = outerVertex;
278 } else if (j == cornerSlicesNumber) {
279 outerLast = outerVertex;
ztenghui7940dc52014-04-22 11:21:49 -0700280 }
281 }
ztenghuid5e8ade2014-08-13 15:48:02 -0700282 previousNormal = currentNormal;
ztenghui55bfb4e2013-12-03 10:38:55 -0800283
ztenghuid5e8ade2014-08-13 15:48:02 -0700284 // Edge: first figure out the extra vertices needed for the edge.
285 const Vector3& innerNext = casterVertices[(i + 1) % casterVertexCount];
286 float nextAlpha = getAlphaFromFactoredZ(innerNext.z * heightFactor);
287 if (needsExtraForEdge(currentAlpha, nextAlpha)) {
288 // TODO: See if we can / should cache this outer vertex across the loop.
289 Vector2 outerNext;
290 float expansionDist = innerNext.z * heightFactor * geomFactor;
291 outerNext.x = innerNext.x + currentNormal.x * expansionDist;
292 outerNext.y = innerNext.y + currentNormal.y * expansionDist;
293
294 // Compute the angle and see how many extra points we need.
295 int extraVerticesNumber = getEdgeExtraAndUpdateSpike(&currentSpike,
296 innerNext, centroid3d);
ztenghui7940dc52014-04-22 11:21:49 -0700297#if DEBUG_SHADOW
ztenghuid5e8ade2014-08-13 15:48:02 -0700298 ALOGD("extraVerticesNumber %d for edge %d", extraVerticesNumber, i);
ztenghui7940dc52014-04-22 11:21:49 -0700299#endif
ztenghuid5e8ade2014-08-13 15:48:02 -0700300 // Edge: fill the edge's VB and IB.
301 // This will create vertices pair from [1, extraVerticesNumber - 1].
302 // If there is no extra vertices created here, the edge will be drawn
303 // as just 2 triangles.
304 for (int k = 1; k < extraVerticesNumber; k++) {
305 int startWeight = extraVerticesNumber - k;
306 Vector2 currentOuter =
307 (outerLast * startWeight + outerNext * k) / extraVerticesNumber;
308 indexBuffer[indexBufferIndex++] = vertexBufferIndex;
309 AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentOuter.x,
310 currentOuter.y, OUTER_OPACITY);
ztenghui55bfb4e2013-12-03 10:38:55 -0800311
ztenghuid5e8ade2014-08-13 15:48:02 -0700312 if (!isCasterOpaque) {
313 umbraVertices[umbraIndex++] = vertexBufferIndex;
ztenghui55bfb4e2013-12-03 10:38:55 -0800314 }
ztenghuid5e8ade2014-08-13 15:48:02 -0700315 Vector3 currentInner =
316 (innerStart * startWeight + innerNext * k) / extraVerticesNumber;
317 indexBuffer[indexBufferIndex++] = vertexBufferIndex;
318 AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentInner.x,
319 currentInner.y,
320 getTransformedAlphaFromFactoredZ(currentInner.z * heightFactor));
ztenghui55bfb4e2013-12-03 10:38:55 -0800321 }
322 }
ztenghuid5e8ade2014-08-13 15:48:02 -0700323 currentAlpha = nextAlpha;
ztenghui55bfb4e2013-12-03 10:38:55 -0800324 }
ztenghui55bfb4e2013-12-03 10:38:55 -0800325
ztenghuid5e8ade2014-08-13 15:48:02 -0700326 indexBuffer[indexBufferIndex++] = 1;
327 indexBuffer[indexBufferIndex++] = 0;
ztenghui55bfb4e2013-12-03 10:38:55 -0800328
ztenghuid5e8ade2014-08-13 15:48:02 -0700329 if (!isCasterOpaque) {
330 // Add the centroid as the last one in the vertex buffer.
331 float centroidOpacity =
332 getTransformedAlphaFromFactoredZ(centroid3d.z * heightFactor);
333 int centroidIndex = vertexBufferIndex;
334 AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid3d.x,
335 centroid3d.y, centroidOpacity);
336
337 for (int i = 0; i < umbraIndex; i++) {
338 // Note that umbraVertices[0] is always 0.
339 // So the start and the end of the umbra are using the "0".
340 // And penumbra ended with 0, so a degenerated triangle is formed b/t
341 // the umbra and penumbra.
342 indexBuffer[indexBufferIndex++] = umbraVertices[i];
343 indexBuffer[indexBufferIndex++] = centroidIndex;
344 }
345 indexBuffer[indexBufferIndex++] = 0;
ztenghui55bfb4e2013-12-03 10:38:55 -0800346 }
ztenghuid5e8ade2014-08-13 15:48:02 -0700347
348 // At the end, update the real index and vertex buffer size.
349 shadowVertexBuffer.updateVertexCount(vertexBufferIndex);
350 shadowVertexBuffer.updateIndexCount(indexBufferIndex);
351
352 checkOverflow(vertexBufferIndex, totalVertexCount, "Vertex Buffer");
353 checkOverflow(indexBufferIndex, totalIndexCount, "Index Buffer");
354 checkOverflow(umbraIndex, totalUmbraCount, "Umbra Buffer");
355
356#if DEBUG_SHADOW
357 for (int i = 0; i < vertexBufferIndex; i++) {
358 ALOGD("vertexBuffer i %d, (%f, %f %f)", i, shadowVertices[i].x, shadowVertices[i].y,
359 shadowVertices[i].alpha);
360 }
361 for (int i = 0; i < indexBufferIndex; i++) {
362 ALOGD("indexBuffer i %d, indexBuffer[i] %d", i, indexBuffer[i]);
363 }
364#endif
ztenghui55bfb4e2013-12-03 10:38:55 -0800365}
366
367}; // namespace uirenderer
368}; // namespace android