Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 726118b3 authored by Chris Craik's avatar Chris Craik
Browse files

Improve shadow tessellation performance

- Tune and simplify shadow parameters
- Remove additional inner rings
- Improve polygon ray casting algorithm

Change-Id: If0f28b2d66ae0480b675942bb65e8fcd2864425d
parent b08216c0
Loading
Loading
Loading
Loading
+26 −28
Original line number Diff line number Diff line
@@ -47,9 +47,8 @@ void AmbientShadow::createAmbientShadow(const Vector3* vertices, int vertexCount
        const Vector3& centroid3d, float heightFactor, float geomFactor,
        VertexBuffer& shadowVertexBuffer) {
    const int rays = SHADOW_RAY_COUNT;
    const int layers = SHADOW_LAYER_COUNT;
    // Validate the inputs.
    if (vertexCount < 3 || heightFactor <= 0 || layers <= 0 || rays <= 0
    if (vertexCount < 3 || heightFactor <= 0 || rays <= 0
        || geomFactor <= 0) {
#if DEBUG_SHADOW
        ALOGE("Invalid input for createAmbientShadow(), early return!");
@@ -96,33 +95,32 @@ void AmbientShadow::createAmbientShadow(const Vector3* vertices, int vertexCount
    // calculate the normal N, which should be perpendicular to the edge of the
    // polygon (represented by the neighbor intersection points) .
    // Shadow's vertices will be generated as : P + N * scale.
    int currentVertexIndex = 0;
    for (int layerIndex = 0; layerIndex <= layers; layerIndex++) {
    for (int rayIndex = 0; rayIndex < rays; rayIndex++) {

        Vector2 normal(1.0f, 0.0f);
        calculateNormal(rays, rayIndex, dir.array(), rayDist, normal);

            float opacity = 1.0 / (1 + rayHeight[rayIndex] / heightFactor);

        // The vertex should be start from rayDist[i] then scale the
        // normalizeNormal!
        Vector2 intersection = dir[rayIndex] * rayDist[rayIndex] +
                Vector2(centroid3d.x, centroid3d.y);

            float layerRatio = layerIndex / (float)(layers);
            // The higher the intersection is, the further the ambient shadow expanded.
            float expansionDist = rayHeight[rayIndex] / heightFactor *
                    geomFactor * (1 - layerRatio);
            AlphaVertex::set(&shadowVertices[currentVertexIndex++],
        // outer ring of points, expanded based upon height of each ray intersection
        float expansionDist = rayHeight[rayIndex] * heightFactor *
                geomFactor;
        AlphaVertex::set(&shadowVertices[rayIndex],
                intersection.x + normal.x * expansionDist,
                intersection.y + normal.y * expansionDist,
                    layerRatio * opacity);
        }
                0.0f);

        // inner ring of points
        float opacity = 1.0 / (1 + rayHeight[rayIndex] * heightFactor);
        AlphaVertex::set(&shadowVertices[rayIndex + rays],
                intersection.x,
                intersection.y,
                opacity);
    }
    float centroidAlpha = 1.0 / (1 + centroid3d.z / heightFactor);
    AlphaVertex::set(&shadowVertices[currentVertexIndex++],
    float centroidAlpha = 1.0 / (1 + centroid3d.z * heightFactor);
    AlphaVertex::set(&shadowVertices[SHADOW_VERTEX_COUNT - 1],
            centroid3d.x, centroid3d.y, centroidAlpha);

#if DEBUG_SHADOW
+2 −2
Original line number Diff line number Diff line
@@ -705,8 +705,8 @@ void Caches::initTempProperties() {
    propertyDirtyViewport = false;
    propertyEnable3d = false;
    propertyCameraDistance = 1.0f;
    propertyAmbientShadowStrength = 0x3f;
    propertySpotShadowStrength = 0x3f;
    propertyAmbientShadowStrength = 25;
    propertySpotShadowStrength = 25;

    propertyLightPosXScale = 0.5f;
    propertyLightPosYScale = 0.0f;
+1 −1
Original line number Diff line number Diff line
@@ -491,7 +491,7 @@ void DisplayList::replay(ReplayStateStruct& replayStruct, const int level) {
            replayStruct.mDrawGlStatus);
}

#define SHADOW_DELTA 2.0f
#define SHADOW_DELTA 0.1f

template <class T>
void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& renderer,
+13 −16
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ void ShadowTessellator::tessellateAmbientShadow(const Vector3* casterPolygon,

    // A bunch of parameters to tweak the shadow.
    // TODO: Allow some of these changable by debug settings or APIs.
    const float heightFactor = 128;
    const float heightFactor = 1.0f / 128;
    const float geomFactor = 64;

    AmbientShadow::createAmbientShadow(casterPolygon, casterVertexCount,
@@ -69,7 +69,7 @@ void ShadowTessellator::tessellateSpotShadow(const Vector3* casterPolygon, int c
    reverseReceiverTransform.mapPoint3d(lightCenter);

    const float lightSize = maximal / 4;
    const int lightVertexCount = 16;
    const int lightVertexCount = 8;

    SpotShadow::createSpotShadow(casterPolygon, casterVertexCount, lightCenter,
            lightSize, lightVertexCount, shadowVertexBuffer);
@@ -78,26 +78,23 @@ void ShadowTessellator::tessellateSpotShadow(const Vector3* casterPolygon, int c

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;
    for (int i = 0; i < rays; i++) {
        shadowIndices[currentIndex++] = i;
        shadowIndices[currentIndex++] = rays + i;
    }
    // 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;
    shadowIndices[currentIndex++] = 0;
    shadowIndices[currentIndex++] = rays;

    uint16_t centroidIndex = 2 * rays;
    // For the umbra area, using strips to simulate the fans.
    for (int k = 0; k < rays; k++) {
        shadowIndices[currentIndex++] = base + k;
    for (int i = 0; i < rays; i++) {
        shadowIndices[currentIndex++] = rays + i;
        shadowIndices[currentIndex++] = centroidIndex;
    }
    shadowIndices[currentIndex++] = base;
    shadowIndices[currentIndex++] = rays;

#if DEBUG_SHADOW
    if (currentIndex != SHADOW_INDEX_COUNT) {
+3 −7
Original line number Diff line number Diff line
@@ -46,17 +46,13 @@ namespace uirenderer {

// The total number of rays starting from the centroid of shadow area, in order
// to generate the shadow geometry.
#define SHADOW_RAY_COUNT 256

// The total number of layers in the outer shadow area, 1 being the minimum.
#define SHADOW_LAYER_COUNT 2
#define SHADOW_RAY_COUNT 128

// The total number of all the vertices representing the shadow.
#define SHADOW_VERTEX_COUNT ((SHADOW_LAYER_COUNT + 1) * SHADOW_RAY_COUNT + 1)
#define SHADOW_VERTEX_COUNT (2 * SHADOW_RAY_COUNT + 1)

// The total number of indices used for drawing the shadow geometry as triangle strips.
#define SHADOW_INDEX_COUNT (2 * SHADOW_RAY_COUNT + 1 + 2 * (SHADOW_RAY_COUNT + 1) * \
        SHADOW_LAYER_COUNT)
#define SHADOW_INDEX_COUNT (2 * SHADOW_RAY_COUNT + 1 + 2 * (SHADOW_RAY_COUNT + 1))

class ShadowTessellator {
public:
Loading