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