diff options
Diffstat (limited to 'libs/hwui/AmbientShadow.cpp')
-rw-r--r-- | libs/hwui/AmbientShadow.cpp | 329 |
1 files changed, 0 insertions, 329 deletions
diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp deleted file mode 100644 index aa96698c1e53..000000000000 --- a/libs/hwui/AmbientShadow.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Extra vertices for the corner for smoother corner. - * Only for outer vertices. - * Note that we use such extra memory to avoid an extra loop. - */ -// For half circle, we could add EXTRA_VERTEX_PER_PI vertices. -// Set to 1 if we don't want to have any. -#define EXTRA_CORNER_VERTEX_PER_PI 12 - -// For the whole polygon, the sum of all the deltas b/t normals is 2 * M_PI, -// therefore, the maximum number of extra vertices will be twice bigger. -#define MAX_EXTRA_CORNER_VERTEX_NUMBER (2 * EXTRA_CORNER_VERTEX_PER_PI) - -// For each RADIANS_DIVISOR, we would allocate one more vertex b/t the normals. -#define CORNER_RADIANS_DIVISOR (M_PI / EXTRA_CORNER_VERTEX_PER_PI) - -/** - * Extra vertices for the Edge for interpolation artifacts. - * Same value for both inner and outer vertices. - */ -#define EXTRA_EDGE_VERTEX_PER_PI 50 - -#define MAX_EXTRA_EDGE_VERTEX_NUMBER (2 * EXTRA_EDGE_VERTEX_PER_PI) - -#define EDGE_RADIANS_DIVISOR (M_PI / EXTRA_EDGE_VERTEX_PER_PI) - -/** - * Other constants: - */ -#define OUTER_ALPHA (0.0f) - -// Once the alpha difference is greater than this threshold, we will allocate extra -// edge vertices. -// If this is set to negative value, then all the edge will be tessellated. -#define ALPHA_THRESHOLD (0.1f / 255.0f) - -#include "AmbientShadow.h" - -#include "ShadowTessellator.h" -#include "Vertex.h" -#include "VertexBuffer.h" - -#include <utils/Log.h> -#include <algorithm> - -namespace android { -namespace uirenderer { - -/** - * Local utility functions. - */ -inline Vector2 getNormalFromVertices(const Vector3* vertices, int current, int next) { - // Convert from Vector3 to Vector2 first. - Vector2 currentVertex = {vertices[current].x, vertices[current].y}; - Vector2 nextVertex = {vertices[next].x, vertices[next].y}; - - return ShadowTessellator::calculateNormal(currentVertex, nextVertex); -} - -// The input z value will be converted to be non-negative inside. -// The output must be ranged from 0 to 1. -inline float getAlphaFromFactoredZ(float factoredZ) { - return 1.0 / (1 + std::max(factoredZ, 0.0f)); -} - -inline int getEdgeExtraAndUpdateSpike(Vector2* currentSpike, const Vector3& secondVertex, - const Vector3& centroid) { - Vector2 secondSpike = {secondVertex.x - centroid.x, secondVertex.y - centroid.y}; - secondSpike.normalize(); - - int result = ShadowTessellator::getExtraVertexNumber(secondSpike, *currentSpike, - EDGE_RADIANS_DIVISOR); - *currentSpike = secondSpike; - return result; -} - -// Given the caster's vertex count, compute all the buffers size depending on -// whether or not the caster is opaque. -inline void computeBufferSize(int* totalVertexCount, int* totalIndexCount, int* totalUmbraCount, - int casterVertexCount, bool isCasterOpaque) { - // Compute the size of the vertex buffer. - int outerVertexCount = - casterVertexCount * 2 + MAX_EXTRA_CORNER_VERTEX_NUMBER + MAX_EXTRA_EDGE_VERTEX_NUMBER; - int innerVertexCount = casterVertexCount + MAX_EXTRA_EDGE_VERTEX_NUMBER; - *totalVertexCount = outerVertexCount + innerVertexCount; - - // Compute the size of the index buffer. - *totalIndexCount = 2 * outerVertexCount + 2; - - // Compute the size of the umber buffer. - // For translucent object, keep track of the umbra(inner) vertex in order to draw - // inside. We only need to store the index information. - *totalUmbraCount = 0; - if (!isCasterOpaque) { - // Add the centroid if occluder is translucent. - (*totalVertexCount)++; - *totalIndexCount += 2 * innerVertexCount + 1; - *totalUmbraCount = innerVertexCount; - } -} - -inline bool needsExtraForEdge(float firstAlpha, float secondAlpha) { - return fabsf(firstAlpha - secondAlpha) > ALPHA_THRESHOLD; -} - -/** - * Calculate the shadows as a triangle strips while alpha value as the - * shadow values. - * - * @param isCasterOpaque Whether the caster is opaque. - * @param vertices The shadow caster's polygon, which is represented in a Vector3 - * array. - * @param vertexCount The length of caster's polygon in terms of number of - * vertices. - * @param centroid3d The centroid of the shadow caster. - * @param heightFactor The factor showing the higher the object, the lighter the - * shadow. - * @param geomFactor The factor scaling the geometry expansion along the normal. - * - * @param shadowVertexBuffer Return an floating point array of (x, y, a) - * triangle strips mode. - * - * An simple illustration: - * For now let's mark the outer vertex as Pi, the inner as Vi, the centroid as C. - * - * First project the occluder to the Z=0 surface. - * Then we got all the inner vertices. And we compute the normal for each edge. - * According to the normal, we generate outer vertices. E.g: We generate P1 / P4 - * as extra corner vertices to make the corner looks round and smoother. - * - * Due to the fact that the alpha is not linear interpolated along the inner - * edge, when the alpha is different, we may add extra vertices such as P2.1, P2.2, - * V0.1, V0.2 to avoid the visual artifacts. - * - * (P3) - * (P2) (P2.1) (P2.2) | ' (P4) - * (P1)' | | | | ' - * ' | | | | ' - * (P0) ------------------------------------------------(P5) - * | (V0) (V0.1) (V0.2) |(V1) - * | | - * | | - * | (C) | - * | | - * | | - * | | - * | | - * (V3)-----------------------------------(V2) - */ -void AmbientShadow::createAmbientShadow(bool isCasterOpaque, const Vector3* casterVertices, - int casterVertexCount, const Vector3& centroid3d, - float heightFactor, float geomFactor, - VertexBuffer& shadowVertexBuffer) { - shadowVertexBuffer.setMeshFeatureFlags(VertexBuffer::kAlpha | VertexBuffer::kIndices); - - // In order to computer the outer vertices in one loop, we need pre-compute - // the normal by the vertex (n - 1) to vertex 0, and the spike and alpha value - // for vertex 0. - Vector2 previousNormal = getNormalFromVertices(casterVertices, casterVertexCount - 1, 0); - Vector2 currentSpike = {casterVertices[0].x - centroid3d.x, casterVertices[0].y - centroid3d.y}; - currentSpike.normalize(); - float currentAlpha = getAlphaFromFactoredZ(casterVertices[0].z * heightFactor); - - // Preparing all the output data. - int totalVertexCount, totalIndexCount, totalUmbraCount; - computeBufferSize(&totalVertexCount, &totalIndexCount, &totalUmbraCount, casterVertexCount, - isCasterOpaque); - AlphaVertex* shadowVertices = shadowVertexBuffer.alloc<AlphaVertex>(totalVertexCount); - int vertexBufferIndex = 0; - uint16_t* indexBuffer = shadowVertexBuffer.allocIndices<uint16_t>(totalIndexCount); - int indexBufferIndex = 0; - uint16_t umbraVertices[totalUmbraCount]; - int umbraIndex = 0; - - for (int i = 0; i < casterVertexCount; i++) { - // Corner: first figure out the extra vertices we need for the corner. - const Vector3& innerVertex = casterVertices[i]; - Vector2 currentNormal = - getNormalFromVertices(casterVertices, i, (i + 1) % casterVertexCount); - - int extraVerticesNumber = ShadowTessellator::getExtraVertexNumber( - currentNormal, previousNormal, CORNER_RADIANS_DIVISOR); - - float expansionDist = innerVertex.z * heightFactor * geomFactor; - const int cornerSlicesNumber = extraVerticesNumber + 1; // Minimal as 1. -#if DEBUG_SHADOW - ALOGD("cornerSlicesNumber is %d", cornerSlicesNumber); -#endif - - // Corner: fill the corner Vertex Buffer(VB) and Index Buffer(IB). - // We fill the inner vertex first, such that we can fill the index buffer - // inside the loop. - int currentInnerVertexIndex = vertexBufferIndex; - if (!isCasterOpaque) { - umbraVertices[umbraIndex++] = vertexBufferIndex; - } - AlphaVertex::set(&shadowVertices[vertexBufferIndex++], casterVertices[i].x, - casterVertices[i].y, currentAlpha); - - const Vector3& innerStart = casterVertices[i]; - - // outerStart is the first outer vertex for this inner vertex. - // outerLast is the last outer vertex for this inner vertex. - Vector2 outerStart = {0, 0}; - Vector2 outerLast = {0, 0}; - // This will create vertices from [0, cornerSlicesNumber] inclusively, - // which means minimally 2 vertices even without the extra ones. - for (int j = 0; j <= cornerSlicesNumber; j++) { - Vector2 averageNormal = previousNormal * (cornerSlicesNumber - j) + currentNormal * j; - averageNormal /= cornerSlicesNumber; - averageNormal.normalize(); - Vector2 outerVertex; - outerVertex.x = innerVertex.x + averageNormal.x * expansionDist; - outerVertex.y = innerVertex.y + averageNormal.y * expansionDist; - - indexBuffer[indexBufferIndex++] = vertexBufferIndex; - indexBuffer[indexBufferIndex++] = currentInnerVertexIndex; - AlphaVertex::set(&shadowVertices[vertexBufferIndex++], outerVertex.x, outerVertex.y, - OUTER_ALPHA); - - if (j == 0) { - outerStart = outerVertex; - } else if (j == cornerSlicesNumber) { - outerLast = outerVertex; - } - } - previousNormal = currentNormal; - - // Edge: first figure out the extra vertices needed for the edge. - const Vector3& innerNext = casterVertices[(i + 1) % casterVertexCount]; - float nextAlpha = getAlphaFromFactoredZ(innerNext.z * heightFactor); - if (needsExtraForEdge(currentAlpha, nextAlpha)) { - // TODO: See if we can / should cache this outer vertex across the loop. - Vector2 outerNext; - float expansionDist = innerNext.z * heightFactor * geomFactor; - outerNext.x = innerNext.x + currentNormal.x * expansionDist; - outerNext.y = innerNext.y + currentNormal.y * expansionDist; - - // Compute the angle and see how many extra points we need. - int extraVerticesNumber = - getEdgeExtraAndUpdateSpike(¤tSpike, innerNext, centroid3d); -#if DEBUG_SHADOW - ALOGD("extraVerticesNumber %d for edge %d", extraVerticesNumber, i); -#endif - // Edge: fill the edge's VB and IB. - // This will create vertices pair from [1, extraVerticesNumber - 1]. - // If there is no extra vertices created here, the edge will be drawn - // as just 2 triangles. - for (int k = 1; k < extraVerticesNumber; k++) { - int startWeight = extraVerticesNumber - k; - Vector2 currentOuter = - (outerLast * startWeight + outerNext * k) / extraVerticesNumber; - indexBuffer[indexBufferIndex++] = vertexBufferIndex; - AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentOuter.x, - currentOuter.y, OUTER_ALPHA); - - if (!isCasterOpaque) { - umbraVertices[umbraIndex++] = vertexBufferIndex; - } - Vector3 currentInner = - (innerStart * startWeight + innerNext * k) / extraVerticesNumber; - indexBuffer[indexBufferIndex++] = vertexBufferIndex; - AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentInner.x, - currentInner.y, - getAlphaFromFactoredZ(currentInner.z * heightFactor)); - } - } - currentAlpha = nextAlpha; - } - - indexBuffer[indexBufferIndex++] = 1; - indexBuffer[indexBufferIndex++] = 0; - - if (!isCasterOpaque) { - // Add the centroid as the last one in the vertex buffer. - float centroidOpacity = getAlphaFromFactoredZ(centroid3d.z * heightFactor); - int centroidIndex = vertexBufferIndex; - AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid3d.x, centroid3d.y, - centroidOpacity); - - for (int i = 0; i < umbraIndex; i++) { - // Note that umbraVertices[0] is always 0. - // So the start and the end of the umbra are using the "0". - // And penumbra ended with 0, so a degenerated triangle is formed b/t - // the umbra and penumbra. - indexBuffer[indexBufferIndex++] = umbraVertices[i]; - indexBuffer[indexBufferIndex++] = centroidIndex; - } - indexBuffer[indexBufferIndex++] = 0; - } - - // At the end, update the real index and vertex buffer size. - shadowVertexBuffer.updateVertexCount(vertexBufferIndex); - shadowVertexBuffer.updateIndexCount(indexBufferIndex); - shadowVertexBuffer.computeBounds<AlphaVertex>(); - - ShadowTessellator::checkOverflow(vertexBufferIndex, totalVertexCount, "Ambient Vertex Buffer"); - ShadowTessellator::checkOverflow(indexBufferIndex, totalIndexCount, "Ambient Index Buffer"); - ShadowTessellator::checkOverflow(umbraIndex, totalUmbraCount, "Ambient Umbra Buffer"); - -#if DEBUG_SHADOW - for (int i = 0; i < vertexBufferIndex; i++) { - ALOGD("vertexBuffer i %d, (%f, %f %f)", i, shadowVertices[i].x, shadowVertices[i].y, - shadowVertices[i].alpha); - } - for (int i = 0; i < indexBufferIndex; i++) { - ALOGD("indexBuffer i %d, indexBuffer[i] %d", i, indexBuffer[i]); - } -#endif -} - -}; // namespace uirenderer -}; // namespace android |