summaryrefslogtreecommitdiff
path: root/libs/hwui/AmbientShadow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/AmbientShadow.cpp')
-rw-r--r--libs/hwui/AmbientShadow.cpp329
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(&currentSpike, 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