ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 1 | /* |
| 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 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 17 | /** |
| 18 | * Extra vertices for the corner for smoother corner. |
| 19 | * Only for outer vertices. |
| 20 | * Note that we use such extra memory to avoid an extra loop. |
| 21 | */ |
| 22 | // For half circle, we could add EXTRA_VERTEX_PER_PI vertices. |
| 23 | // Set to 1 if we don't want to have any. |
| 24 | #define EXTRA_CORNER_VERTEX_PER_PI 12 |
| 25 | |
| 26 | // For the whole polygon, the sum of all the deltas b/t normals is 2 * M_PI, |
| 27 | // therefore, the maximum number of extra vertices will be twice bigger. |
| 28 | #define MAX_EXTRA_CORNER_VERTEX_NUMBER (2 * EXTRA_CORNER_VERTEX_PER_PI) |
| 29 | |
| 30 | // For each RADIANS_DIVISOR, we would allocate one more vertex b/t the normals. |
| 31 | #define CORNER_RADIANS_DIVISOR (M_PI / EXTRA_CORNER_VERTEX_PER_PI) |
| 32 | |
| 33 | /** |
| 34 | * Extra vertices for the Edge for interpolation artifacts. |
| 35 | * Same value for both inner and outer vertices. |
| 36 | */ |
| 37 | #define EXTRA_EDGE_VERTEX_PER_PI 50 |
| 38 | |
| 39 | #define MAX_EXTRA_EDGE_VERTEX_NUMBER (2 * EXTRA_EDGE_VERTEX_PER_PI) |
| 40 | |
| 41 | #define EDGE_RADIANS_DIVISOR (M_PI / EXTRA_EDGE_VERTEX_PER_PI) |
| 42 | |
| 43 | /** |
| 44 | * Other constants: |
| 45 | */ |
ztenghui | ecf091e | 2015-02-17 13:26:10 -0800 | [diff] [blame] | 46 | // For the edge of the penumbra, the opacity is 0. After transform (1 - alpha), |
| 47 | // it is 1. |
| 48 | #define TRANSFORMED_OUTER_OPACITY (1.0f) |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 49 | |
| 50 | // Once the alpha difference is greater than this threshold, we will allocate extra |
| 51 | // edge vertices. |
| 52 | // If this is set to negative value, then all the edge will be tessellated. |
| 53 | #define ALPHA_THRESHOLD (0.1f / 255.0f) |
| 54 | |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 55 | #include "AmbientShadow.h" |
Chris Craik | 9db58c0 | 2015-08-19 15:19:18 -0700 | [diff] [blame] | 56 | |
ztenghui | 63d41ab | 2014-02-14 13:13:41 -0800 | [diff] [blame] | 57 | #include "ShadowTessellator.h" |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 58 | #include "Vertex.h" |
Tom Hudson | 2dc236b | 2014-10-15 15:46:42 -0400 | [diff] [blame] | 59 | #include "VertexBuffer.h" |
Chris Craik | 9db58c0 | 2015-08-19 15:19:18 -0700 | [diff] [blame] | 60 | |
| 61 | #include <algorithm> |
| 62 | #include <utils/Log.h> |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 63 | |
| 64 | namespace android { |
| 65 | namespace uirenderer { |
| 66 | |
| 67 | /** |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 68 | * Local utility functions. |
| 69 | */ |
| 70 | inline Vector2 getNormalFromVertices(const Vector3* vertices, int current, int next) { |
| 71 | // Convert from Vector3 to Vector2 first. |
| 72 | Vector2 currentVertex = { vertices[current].x, vertices[current].y }; |
| 73 | Vector2 nextVertex = { vertices[next].x, vertices[next].y }; |
| 74 | |
| 75 | return ShadowTessellator::calculateNormal(currentVertex, nextVertex); |
| 76 | } |
| 77 | |
| 78 | // The input z value will be converted to be non-negative inside. |
| 79 | // The output must be ranged from 0 to 1. |
| 80 | inline float getAlphaFromFactoredZ(float factoredZ) { |
Chris Craik | 9db58c0 | 2015-08-19 15:19:18 -0700 | [diff] [blame] | 81 | return 1.0 / (1 + std::max(factoredZ, 0.0f)); |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 82 | } |
| 83 | |
ztenghui | ecf091e | 2015-02-17 13:26:10 -0800 | [diff] [blame] | 84 | // The shader is using gaussian function e^-(1-x)*(1-x)*4, therefore, we transform |
| 85 | // the alpha value to (1 - alpha) |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 86 | inline float getTransformedAlphaFromAlpha(float alpha) { |
ztenghui | ecf091e | 2015-02-17 13:26:10 -0800 | [diff] [blame] | 87 | return 1.0f - alpha; |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 88 | } |
| 89 | |
ztenghui | ecf091e | 2015-02-17 13:26:10 -0800 | [diff] [blame] | 90 | // The output is ranged from 0 to 1. |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 91 | inline float getTransformedAlphaFromFactoredZ(float factoredZ) { |
| 92 | return getTransformedAlphaFromAlpha(getAlphaFromFactoredZ(factoredZ)); |
| 93 | } |
| 94 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 95 | inline int getEdgeExtraAndUpdateSpike(Vector2* currentSpike, |
| 96 | const Vector3& secondVertex, const Vector3& centroid) { |
| 97 | Vector2 secondSpike = {secondVertex.x - centroid.x, secondVertex.y - centroid.y}; |
| 98 | secondSpike.normalize(); |
| 99 | |
ztenghui | 512e643 | 2014-09-10 13:08:20 -0700 | [diff] [blame] | 100 | int result = ShadowTessellator::getExtraVertexNumber(secondSpike, *currentSpike, |
| 101 | EDGE_RADIANS_DIVISOR); |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 102 | *currentSpike = secondSpike; |
| 103 | return result; |
| 104 | } |
| 105 | |
| 106 | // Given the caster's vertex count, compute all the buffers size depending on |
| 107 | // whether or not the caster is opaque. |
| 108 | inline void computeBufferSize(int* totalVertexCount, int* totalIndexCount, |
| 109 | int* totalUmbraCount, int casterVertexCount, bool isCasterOpaque) { |
| 110 | // Compute the size of the vertex buffer. |
| 111 | int outerVertexCount = casterVertexCount * 2 + MAX_EXTRA_CORNER_VERTEX_NUMBER + |
| 112 | MAX_EXTRA_EDGE_VERTEX_NUMBER; |
| 113 | int innerVertexCount = casterVertexCount + MAX_EXTRA_EDGE_VERTEX_NUMBER; |
| 114 | *totalVertexCount = outerVertexCount + innerVertexCount; |
| 115 | |
| 116 | // Compute the size of the index buffer. |
| 117 | *totalIndexCount = 2 * outerVertexCount + 2; |
| 118 | |
| 119 | // Compute the size of the umber buffer. |
| 120 | // For translucent object, keep track of the umbra(inner) vertex in order to draw |
| 121 | // inside. We only need to store the index information. |
| 122 | *totalUmbraCount = 0; |
| 123 | if (!isCasterOpaque) { |
| 124 | // Add the centroid if occluder is translucent. |
Andreas Gampe | edaecc1 | 2014-11-10 20:54:07 -0800 | [diff] [blame] | 125 | (*totalVertexCount)++; |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 126 | *totalIndexCount += 2 * innerVertexCount + 1; |
| 127 | *totalUmbraCount = innerVertexCount; |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | inline bool needsExtraForEdge(float firstAlpha, float secondAlpha) { |
Bernhard Rosenkränzer | c44958c7 | 2014-11-17 21:48:46 +0100 | [diff] [blame] | 132 | return fabsf(firstAlpha - secondAlpha) > ALPHA_THRESHOLD; |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 133 | } |
| 134 | |
| 135 | /** |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 136 | * Calculate the shadows as a triangle strips while alpha value as the |
| 137 | * shadow values. |
| 138 | * |
ztenghui | 50ecf84 | 2014-03-11 16:52:30 -0700 | [diff] [blame] | 139 | * @param isCasterOpaque Whether the caster is opaque. |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 140 | * @param vertices The shadow caster's polygon, which is represented in a Vector3 |
| 141 | * array. |
| 142 | * @param vertexCount The length of caster's polygon in terms of number of |
| 143 | * vertices. |
ztenghui | 63d41ab | 2014-02-14 13:13:41 -0800 | [diff] [blame] | 144 | * @param centroid3d The centroid of the shadow caster. |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 145 | * @param heightFactor The factor showing the higher the object, the lighter the |
| 146 | * shadow. |
| 147 | * @param geomFactor The factor scaling the geometry expansion along the normal. |
| 148 | * |
| 149 | * @param shadowVertexBuffer Return an floating point array of (x, y, a) |
| 150 | * triangle strips mode. |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 151 | * |
| 152 | * An simple illustration: |
| 153 | * For now let's mark the outer vertex as Pi, the inner as Vi, the centroid as C. |
| 154 | * |
| 155 | * First project the occluder to the Z=0 surface. |
| 156 | * Then we got all the inner vertices. And we compute the normal for each edge. |
| 157 | * According to the normal, we generate outer vertices. E.g: We generate P1 / P4 |
| 158 | * as extra corner vertices to make the corner looks round and smoother. |
| 159 | * |
| 160 | * Due to the fact that the alpha is not linear interpolated along the inner |
| 161 | * edge, when the alpha is different, we may add extra vertices such as P2.1, P2.2, |
| 162 | * V0.1, V0.2 to avoid the visual artifacts. |
| 163 | * |
| 164 | * (P3) |
| 165 | * (P2) (P2.1) (P2.2) | ' (P4) |
| 166 | * (P1)' | | | | ' |
| 167 | * ' | | | | ' |
| 168 | * (P0) ------------------------------------------------(P5) |
| 169 | * | (V0) (V0.1) (V0.2) |(V1) |
| 170 | * | | |
| 171 | * | | |
| 172 | * | (C) | |
| 173 | * | | |
| 174 | * | | |
| 175 | * | | |
| 176 | * | | |
| 177 | * (V3)-----------------------------------(V2) |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 178 | */ |
Chris Craik | 05f3d6e | 2014-06-02 16:27:04 -0700 | [diff] [blame] | 179 | void AmbientShadow::createAmbientShadow(bool isCasterOpaque, |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 180 | const Vector3* casterVertices, int casterVertexCount, const Vector3& centroid3d, |
ztenghui | 50ecf84 | 2014-03-11 16:52:30 -0700 | [diff] [blame] | 181 | float heightFactor, float geomFactor, VertexBuffer& shadowVertexBuffer) { |
Chris Craik | 117bdbc | 2015-02-05 10:12:38 -0800 | [diff] [blame] | 182 | shadowVertexBuffer.setMeshFeatureFlags(VertexBuffer::kAlpha | VertexBuffer::kIndices); |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 183 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 184 | // In order to computer the outer vertices in one loop, we need pre-compute |
| 185 | // the normal by the vertex (n - 1) to vertex 0, and the spike and alpha value |
| 186 | // for vertex 0. |
| 187 | Vector2 previousNormal = getNormalFromVertices(casterVertices, |
| 188 | casterVertexCount - 1 , 0); |
| 189 | Vector2 currentSpike = {casterVertices[0].x - centroid3d.x, |
| 190 | casterVertices[0].y - centroid3d.y}; |
| 191 | currentSpike.normalize(); |
| 192 | float currentAlpha = getAlphaFromFactoredZ(casterVertices[0].z * heightFactor); |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 193 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 194 | // Preparing all the output data. |
| 195 | int totalVertexCount, totalIndexCount, totalUmbraCount; |
| 196 | computeBufferSize(&totalVertexCount, &totalIndexCount, &totalUmbraCount, |
| 197 | casterVertexCount, isCasterOpaque); |
ztenghui | 50ecf84 | 2014-03-11 16:52:30 -0700 | [diff] [blame] | 198 | AlphaVertex* shadowVertices = |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 199 | shadowVertexBuffer.alloc<AlphaVertex>(totalVertexCount); |
| 200 | int vertexBufferIndex = 0; |
| 201 | uint16_t* indexBuffer = shadowVertexBuffer.allocIndices<uint16_t>(totalIndexCount); |
| 202 | int indexBufferIndex = 0; |
| 203 | uint16_t umbraVertices[totalUmbraCount]; |
| 204 | int umbraIndex = 0; |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 205 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 206 | for (int i = 0; i < casterVertexCount; i++) { |
| 207 | // Corner: first figure out the extra vertices we need for the corner. |
| 208 | const Vector3& innerVertex = casterVertices[i]; |
| 209 | Vector2 currentNormal = getNormalFromVertices(casterVertices, i, |
| 210 | (i + 1) % casterVertexCount); |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 211 | |
ztenghui | 512e643 | 2014-09-10 13:08:20 -0700 | [diff] [blame] | 212 | int extraVerticesNumber = ShadowTessellator::getExtraVertexNumber(currentNormal, |
| 213 | previousNormal, CORNER_RADIANS_DIVISOR); |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 214 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 215 | float expansionDist = innerVertex.z * heightFactor * geomFactor; |
| 216 | const int cornerSlicesNumber = extraVerticesNumber + 1; // Minimal as 1. |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 217 | #if DEBUG_SHADOW |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 218 | ALOGD("cornerSlicesNumber is %d", cornerSlicesNumber); |
ztenghui | 63d41ab | 2014-02-14 13:13:41 -0800 | [diff] [blame] | 219 | #endif |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 220 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 221 | // Corner: fill the corner Vertex Buffer(VB) and Index Buffer(IB). |
| 222 | // We fill the inner vertex first, such that we can fill the index buffer |
| 223 | // inside the loop. |
| 224 | int currentInnerVertexIndex = vertexBufferIndex; |
| 225 | if (!isCasterOpaque) { |
| 226 | umbraVertices[umbraIndex++] = vertexBufferIndex; |
ztenghui | 7940dc5 | 2014-04-22 11:21:49 -0700 | [diff] [blame] | 227 | } |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 228 | AlphaVertex::set(&shadowVertices[vertexBufferIndex++], casterVertices[i].x, |
| 229 | casterVertices[i].y, |
| 230 | getTransformedAlphaFromAlpha(currentAlpha)); |
ztenghui | 7940dc5 | 2014-04-22 11:21:49 -0700 | [diff] [blame] | 231 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 232 | const Vector3& innerStart = casterVertices[i]; |
ztenghui | 7940dc5 | 2014-04-22 11:21:49 -0700 | [diff] [blame] | 233 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 234 | // outerStart is the first outer vertex for this inner vertex. |
| 235 | // outerLast is the last outer vertex for this inner vertex. |
| 236 | Vector2 outerStart = {0, 0}; |
| 237 | Vector2 outerLast = {0, 0}; |
| 238 | // This will create vertices from [0, cornerSlicesNumber] inclusively, |
| 239 | // which means minimally 2 vertices even without the extra ones. |
| 240 | for (int j = 0; j <= cornerSlicesNumber; j++) { |
| 241 | Vector2 averageNormal = |
| 242 | previousNormal * (cornerSlicesNumber - j) + currentNormal * j; |
| 243 | averageNormal /= cornerSlicesNumber; |
| 244 | averageNormal.normalize(); |
| 245 | Vector2 outerVertex; |
| 246 | outerVertex.x = innerVertex.x + averageNormal.x * expansionDist; |
| 247 | outerVertex.y = innerVertex.y + averageNormal.y * expansionDist; |
ztenghui | 7940dc5 | 2014-04-22 11:21:49 -0700 | [diff] [blame] | 248 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 249 | indexBuffer[indexBufferIndex++] = vertexBufferIndex; |
| 250 | indexBuffer[indexBufferIndex++] = currentInnerVertexIndex; |
| 251 | AlphaVertex::set(&shadowVertices[vertexBufferIndex++], outerVertex.x, |
ztenghui | ecf091e | 2015-02-17 13:26:10 -0800 | [diff] [blame] | 252 | outerVertex.y, TRANSFORMED_OUTER_OPACITY); |
ztenghui | 7940dc5 | 2014-04-22 11:21:49 -0700 | [diff] [blame] | 253 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 254 | if (j == 0) { |
| 255 | outerStart = outerVertex; |
| 256 | } else if (j == cornerSlicesNumber) { |
| 257 | outerLast = outerVertex; |
ztenghui | 7940dc5 | 2014-04-22 11:21:49 -0700 | [diff] [blame] | 258 | } |
| 259 | } |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 260 | previousNormal = currentNormal; |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 261 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 262 | // Edge: first figure out the extra vertices needed for the edge. |
| 263 | const Vector3& innerNext = casterVertices[(i + 1) % casterVertexCount]; |
| 264 | float nextAlpha = getAlphaFromFactoredZ(innerNext.z * heightFactor); |
| 265 | if (needsExtraForEdge(currentAlpha, nextAlpha)) { |
| 266 | // TODO: See if we can / should cache this outer vertex across the loop. |
| 267 | Vector2 outerNext; |
| 268 | float expansionDist = innerNext.z * heightFactor * geomFactor; |
| 269 | outerNext.x = innerNext.x + currentNormal.x * expansionDist; |
| 270 | outerNext.y = innerNext.y + currentNormal.y * expansionDist; |
| 271 | |
| 272 | // Compute the angle and see how many extra points we need. |
| 273 | int extraVerticesNumber = getEdgeExtraAndUpdateSpike(¤tSpike, |
| 274 | innerNext, centroid3d); |
ztenghui | 7940dc5 | 2014-04-22 11:21:49 -0700 | [diff] [blame] | 275 | #if DEBUG_SHADOW |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 276 | ALOGD("extraVerticesNumber %d for edge %d", extraVerticesNumber, i); |
ztenghui | 7940dc5 | 2014-04-22 11:21:49 -0700 | [diff] [blame] | 277 | #endif |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 278 | // Edge: fill the edge's VB and IB. |
| 279 | // This will create vertices pair from [1, extraVerticesNumber - 1]. |
| 280 | // If there is no extra vertices created here, the edge will be drawn |
| 281 | // as just 2 triangles. |
| 282 | for (int k = 1; k < extraVerticesNumber; k++) { |
| 283 | int startWeight = extraVerticesNumber - k; |
| 284 | Vector2 currentOuter = |
| 285 | (outerLast * startWeight + outerNext * k) / extraVerticesNumber; |
| 286 | indexBuffer[indexBufferIndex++] = vertexBufferIndex; |
| 287 | AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentOuter.x, |
ztenghui | ecf091e | 2015-02-17 13:26:10 -0800 | [diff] [blame] | 288 | currentOuter.y, TRANSFORMED_OUTER_OPACITY); |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 289 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 290 | if (!isCasterOpaque) { |
| 291 | umbraVertices[umbraIndex++] = vertexBufferIndex; |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 292 | } |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 293 | Vector3 currentInner = |
| 294 | (innerStart * startWeight + innerNext * k) / extraVerticesNumber; |
| 295 | indexBuffer[indexBufferIndex++] = vertexBufferIndex; |
| 296 | AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentInner.x, |
| 297 | currentInner.y, |
| 298 | getTransformedAlphaFromFactoredZ(currentInner.z * heightFactor)); |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 299 | } |
| 300 | } |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 301 | currentAlpha = nextAlpha; |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 302 | } |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 303 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 304 | indexBuffer[indexBufferIndex++] = 1; |
| 305 | indexBuffer[indexBufferIndex++] = 0; |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 306 | |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 307 | if (!isCasterOpaque) { |
| 308 | // Add the centroid as the last one in the vertex buffer. |
| 309 | float centroidOpacity = |
| 310 | getTransformedAlphaFromFactoredZ(centroid3d.z * heightFactor); |
| 311 | int centroidIndex = vertexBufferIndex; |
| 312 | AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid3d.x, |
| 313 | centroid3d.y, centroidOpacity); |
| 314 | |
| 315 | for (int i = 0; i < umbraIndex; i++) { |
| 316 | // Note that umbraVertices[0] is always 0. |
| 317 | // So the start and the end of the umbra are using the "0". |
| 318 | // And penumbra ended with 0, so a degenerated triangle is formed b/t |
| 319 | // the umbra and penumbra. |
| 320 | indexBuffer[indexBufferIndex++] = umbraVertices[i]; |
| 321 | indexBuffer[indexBufferIndex++] = centroidIndex; |
| 322 | } |
| 323 | indexBuffer[indexBufferIndex++] = 0; |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 324 | } |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 325 | |
| 326 | // At the end, update the real index and vertex buffer size. |
| 327 | shadowVertexBuffer.updateVertexCount(vertexBufferIndex); |
| 328 | shadowVertexBuffer.updateIndexCount(indexBufferIndex); |
Chris Craik | 4ac36f8 | 2014-12-09 16:54:03 -0800 | [diff] [blame] | 329 | shadowVertexBuffer.computeBounds<AlphaVertex>(); |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 330 | |
ztenghui | d2dcd6f | 2014-10-29 16:04:29 -0700 | [diff] [blame] | 331 | ShadowTessellator::checkOverflow(vertexBufferIndex, totalVertexCount, "Ambient Vertex Buffer"); |
| 332 | ShadowTessellator::checkOverflow(indexBufferIndex, totalIndexCount, "Ambient Index Buffer"); |
| 333 | ShadowTessellator::checkOverflow(umbraIndex, totalUmbraCount, "Ambient Umbra Buffer"); |
ztenghui | d5e8ade | 2014-08-13 15:48:02 -0700 | [diff] [blame] | 334 | |
| 335 | #if DEBUG_SHADOW |
| 336 | for (int i = 0; i < vertexBufferIndex; i++) { |
| 337 | ALOGD("vertexBuffer i %d, (%f, %f %f)", i, shadowVertices[i].x, shadowVertices[i].y, |
| 338 | shadowVertices[i].alpha); |
| 339 | } |
| 340 | for (int i = 0; i < indexBufferIndex; i++) { |
| 341 | ALOGD("indexBuffer i %d, indexBuffer[i] %d", i, indexBuffer[i]); |
| 342 | } |
| 343 | #endif |
ztenghui | 55bfb4e | 2013-12-03 10:38:55 -0800 | [diff] [blame] | 344 | } |
| 345 | |
| 346 | }; // namespace uirenderer |
| 347 | }; // namespace android |