Use pre-computed index to draw the shadow.
Also draw the umbra part as triangle fans instead of zig zag fashion.
b/12840179
Change-Id: Iaa5d15e77351acdd71f076bd8f9bb2d4d2b92faf
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index 7700ea0..526772b 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -31,18 +31,16 @@
return a > b ? a : b;
}
-void ShadowTessellator::tessellateAmbientShadow(const Vector3* casterPolygon, int casterVertexCount,
+void ShadowTessellator::tessellateAmbientShadow(const Vector3* casterPolygon,
+ int casterVertexCount, const Vector3& centroid3d,
VertexBuffer& shadowVertexBuffer) {
// A bunch of parameters to tweak the shadow.
// TODO: Allow some of these changable by debug settings or APIs.
- const int rays = 128;
- const int layers = 2;
- const float strength = 0.5;
const float heightFactor = 128;
const float geomFactor = 64;
- AmbientShadow::createAmbientShadow(casterPolygon, casterVertexCount, rays, layers, strength,
- heightFactor, geomFactor, shadowVertexBuffer);
+ AmbientShadow::createAmbientShadow(casterPolygon, casterVertexCount,
+ centroid3d, heightFactor, geomFactor, shadowVertexBuffer);
}
@@ -51,9 +49,6 @@
int screenWidth, int screenHeight, VertexBuffer& shadowVertexBuffer) {
// A bunch of parameters to tweak the shadow.
// TODO: Allow some of these changable by debug settings or APIs.
- const int rays = 256;
- const int layers = 2;
- const float strength = 0.5;
int maximal = max(screenWidth, screenHeight);
Vector3 lightCenter(screenWidth * lightPosScale.x, screenHeight * lightPosScale.y,
maximal * lightPosScale.z);
@@ -70,9 +65,77 @@
const float lightSize = maximal / 4;
const int lightVertexCount = 16;
- SpotShadow::createSpotShadow(casterPolygon, casterVertexCount, lightCenter, lightSize,
- lightVertexCount, rays, layers, strength, shadowVertexBuffer);
+ SpotShadow::createSpotShadow(casterPolygon, casterVertexCount, lightCenter,
+ lightSize, lightVertexCount, shadowVertexBuffer);
}
+
+void ShadowTessellator::generateShadowIndices(uint16_t* shadowIndices) {
+ int currentIndex = 0;
+ const int layers = SHADOW_LAYER_COUNT;
+ const int rays = SHADOW_RAY_COUNT;
+ // For the penumbra area.
+ for (int i = 0; i < layers; i++) {
+ for (int j = 0; j < rays; j++) {
+ shadowIndices[currentIndex++] = i * rays + j;
+ shadowIndices[currentIndex++] = (i + 1) * rays + j;
+ }
+ // To close the loop, back to the ray 0.
+ shadowIndices[currentIndex++] = i * rays;
+ shadowIndices[currentIndex++] = (i + 1) * rays;
+ }
+ uint16_t base = layers * rays;
+ uint16_t centroidIndex = (layers + 1) * rays;
+ // For the umbra area, using strips to simulate the fans.
+ for (int k = 0; k < rays; k++) {
+ shadowIndices[currentIndex++] = base + k;
+ shadowIndices[currentIndex++] = centroidIndex;
+ }
+ shadowIndices[currentIndex++] = base;
+
+#if DEBUG_SHADOW
+ if (currentIndex != SHADOW_INDEX_COUNT) {
+ ALOGE("vertex index count is wrong. current %d, expected %d",
+ currentIndex, SHADOW_INDEX_COUNT);
+ }
+ for (int i = 0; i < SHADOW_INDEX_COUNT; i++) {
+ ALOGD("vertex index is (%d, %d)", i, shadowIndices[i]);
+ }
+#endif
+}
+
+/**
+ * Calculate the centroid of a 2d polygon.
+ *
+ * @param poly The polygon, which is represented in a Vector2 array.
+ * @param polyLength The length of the polygon in terms of number of vertices.
+ * @return the centroid of the polygon.
+ */
+Vector2 ShadowTessellator::centroid2d(const Vector2* poly, int polyLength) {
+ double sumx = 0;
+ double sumy = 0;
+ int p1 = polyLength - 1;
+ double area = 0;
+ for (int p2 = 0; p2 < polyLength; p2++) {
+ double x1 = poly[p1].x;
+ double y1 = poly[p1].y;
+ double x2 = poly[p2].x;
+ double y2 = poly[p2].y;
+ double a = (x1 * y2 - x2 * y1);
+ sumx += (x1 + x2) * a;
+ sumy += (y1 + y2) * a;
+ area += a;
+ p1 = p2;
+ }
+
+ Vector2 centroid = poly[0];
+ if (area != 0) {
+ centroid = Vector2(sumx / (3 * area), sumy / (3 * area));
+ } else {
+ ALOGE("Area is 0 while computing centroid!");
+ }
+ return centroid;
+}
+
}; // namespace uirenderer
}; // namespace android