155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui/* 255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Copyright (C) 2013 The Android Open Source Project 355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * 455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Licensed under the Apache License, Version 2.0 (the "License"); 555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * you may not use this file except in compliance with the License. 655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * You may obtain a copy of the License at 755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * 855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * http://www.apache.org/licenses/LICENSE-2.0 955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * 1055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Unless required by applicable law or agreed to in writing, software 1155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * distributed under the License is distributed on an "AS IS" BASIS, 1255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * See the License for the specific language governing permissions and 1455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * limitations under the License. 1555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui */ 1655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 17d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui/** 18d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Extra vertices for the corner for smoother corner. 19d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Only for outer vertices. 20d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Note that we use such extra memory to avoid an extra loop. 21d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui */ 22d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// For half circle, we could add EXTRA_VERTEX_PER_PI vertices. 23d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// Set to 1 if we don't want to have any. 24d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define EXTRA_CORNER_VERTEX_PER_PI 12 25d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 26d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// For the whole polygon, the sum of all the deltas b/t normals is 2 * M_PI, 27d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// therefore, the maximum number of extra vertices will be twice bigger. 28d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define MAX_EXTRA_CORNER_VERTEX_NUMBER (2 * EXTRA_CORNER_VERTEX_PER_PI) 29d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 30d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// For each RADIANS_DIVISOR, we would allocate one more vertex b/t the normals. 31d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define CORNER_RADIANS_DIVISOR (M_PI / EXTRA_CORNER_VERTEX_PER_PI) 32d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 33d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui/** 34d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Extra vertices for the Edge for interpolation artifacts. 35d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Same value for both inner and outer vertices. 36d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui */ 37d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define EXTRA_EDGE_VERTEX_PER_PI 50 38d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 39d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define MAX_EXTRA_EDGE_VERTEX_NUMBER (2 * EXTRA_EDGE_VERTEX_PER_PI) 40d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 41d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define EDGE_RADIANS_DIVISOR (M_PI / EXTRA_EDGE_VERTEX_PER_PI) 42d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 43d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui/** 44d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Other constants: 45d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui */ 46138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik#define OUTER_ALPHA (0.0f) 47d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 48d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// Once the alpha difference is greater than this threshold, we will allocate extra 49d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// edge vertices. 50d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// If this is set to negative value, then all the edge will be tessellated. 51d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define ALPHA_THRESHOLD (0.1f / 255.0f) 52d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 5355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include "AmbientShadow.h" 549db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik 5563d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui#include "ShadowTessellator.h" 5655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include "Vertex.h" 572dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include "VertexBuffer.h" 589db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik 599db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik#include <algorithm> 609db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik#include <utils/Log.h> 6155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 6255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghuinamespace android { 6355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghuinamespace uirenderer { 6455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 6555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui/** 66d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Local utility functions. 67d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui */ 68d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline Vector2 getNormalFromVertices(const Vector3* vertices, int current, int next) { 69d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Convert from Vector3 to Vector2 first. 70d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 currentVertex = { vertices[current].x, vertices[current].y }; 71d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 nextVertex = { vertices[next].x, vertices[next].y }; 72d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 73d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui return ShadowTessellator::calculateNormal(currentVertex, nextVertex); 74d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui} 75d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 76d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// The input z value will be converted to be non-negative inside. 77d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// The output must be ranged from 0 to 1. 78d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline float getAlphaFromFactoredZ(float factoredZ) { 799db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik return 1.0 / (1 + std::max(factoredZ, 0.0f)); 80d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui} 81d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 82d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline int getEdgeExtraAndUpdateSpike(Vector2* currentSpike, 83d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui const Vector3& secondVertex, const Vector3& centroid) { 84d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 secondSpike = {secondVertex.x - centroid.x, secondVertex.y - centroid.y}; 85d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui secondSpike.normalize(); 86d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 87512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui int result = ShadowTessellator::getExtraVertexNumber(secondSpike, *currentSpike, 88512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui EDGE_RADIANS_DIVISOR); 89d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *currentSpike = secondSpike; 90d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui return result; 91d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui} 92d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 93d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// Given the caster's vertex count, compute all the buffers size depending on 94d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// whether or not the caster is opaque. 95d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline void computeBufferSize(int* totalVertexCount, int* totalIndexCount, 96d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int* totalUmbraCount, int casterVertexCount, bool isCasterOpaque) { 97d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Compute the size of the vertex buffer. 98d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int outerVertexCount = casterVertexCount * 2 + MAX_EXTRA_CORNER_VERTEX_NUMBER + 99d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui MAX_EXTRA_EDGE_VERTEX_NUMBER; 100d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int innerVertexCount = casterVertexCount + MAX_EXTRA_EDGE_VERTEX_NUMBER; 101d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *totalVertexCount = outerVertexCount + innerVertexCount; 102d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 103d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Compute the size of the index buffer. 104d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *totalIndexCount = 2 * outerVertexCount + 2; 105d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 106d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Compute the size of the umber buffer. 107d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // For translucent object, keep track of the umbra(inner) vertex in order to draw 108d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // inside. We only need to store the index information. 109d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *totalUmbraCount = 0; 110d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui if (!isCasterOpaque) { 111d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Add the centroid if occluder is translucent. 112edaecc1db0584fa017822dfc2da0c968b53967e6Andreas Gampe (*totalVertexCount)++; 113d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *totalIndexCount += 2 * innerVertexCount + 1; 114d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *totalUmbraCount = innerVertexCount; 115d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui } 116d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui} 117d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 118d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline bool needsExtraForEdge(float firstAlpha, float secondAlpha) { 119c44958c78632162d2473ce3e86bef97f020ff4d0Bernhard Rosenkränzer return fabsf(firstAlpha - secondAlpha) > ALPHA_THRESHOLD; 120d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui} 121d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 122d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui/** 12355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Calculate the shadows as a triangle strips while alpha value as the 12455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * shadow values. 12555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * 12650ecf849cb7ccc3482517b74d2214b347927791eztenghui * @param isCasterOpaque Whether the caster is opaque. 12755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param vertices The shadow caster's polygon, which is represented in a Vector3 12855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * array. 12955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param vertexCount The length of caster's polygon in terms of number of 13055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * vertices. 13163d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui * @param centroid3d The centroid of the shadow caster. 13255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param heightFactor The factor showing the higher the object, the lighter the 13355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * shadow. 13455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param geomFactor The factor scaling the geometry expansion along the normal. 13555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * 13655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param shadowVertexBuffer Return an floating point array of (x, y, a) 13755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * triangle strips mode. 138d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * 139d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * An simple illustration: 140d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * For now let's mark the outer vertex as Pi, the inner as Vi, the centroid as C. 141d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * 142d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * First project the occluder to the Z=0 surface. 143d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Then we got all the inner vertices. And we compute the normal for each edge. 144d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * According to the normal, we generate outer vertices. E.g: We generate P1 / P4 145d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * as extra corner vertices to make the corner looks round and smoother. 146d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * 147d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Due to the fact that the alpha is not linear interpolated along the inner 148d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * edge, when the alpha is different, we may add extra vertices such as P2.1, P2.2, 149d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * V0.1, V0.2 to avoid the visual artifacts. 150d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * 151d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * (P3) 152d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * (P2) (P2.1) (P2.2) | ' (P4) 153d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * (P1)' | | | | ' 154d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * ' | | | | ' 155d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * (P0) ------------------------------------------------(P5) 156d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | (V0) (V0.1) (V0.2) |(V1) 157d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | | 158d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | | 159d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | (C) | 160d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | | 161d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | | 162d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | | 163d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | | 164d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * (V3)-----------------------------------(V2) 16555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui */ 16605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid AmbientShadow::createAmbientShadow(bool isCasterOpaque, 167d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui const Vector3* casterVertices, int casterVertexCount, const Vector3& centroid3d, 16850ecf849cb7ccc3482517b74d2214b347927791eztenghui float heightFactor, float geomFactor, VertexBuffer& shadowVertexBuffer) { 169117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik shadowVertexBuffer.setMeshFeatureFlags(VertexBuffer::kAlpha | VertexBuffer::kIndices); 17055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 171d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // In order to computer the outer vertices in one loop, we need pre-compute 172d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // the normal by the vertex (n - 1) to vertex 0, and the spike and alpha value 173d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // for vertex 0. 174d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 previousNormal = getNormalFromVertices(casterVertices, 175d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui casterVertexCount - 1 , 0); 176d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 currentSpike = {casterVertices[0].x - centroid3d.x, 177d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui casterVertices[0].y - centroid3d.y}; 178d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui currentSpike.normalize(); 179d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui float currentAlpha = getAlphaFromFactoredZ(casterVertices[0].z * heightFactor); 18055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 181d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Preparing all the output data. 182d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int totalVertexCount, totalIndexCount, totalUmbraCount; 183d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui computeBufferSize(&totalVertexCount, &totalIndexCount, &totalUmbraCount, 184d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui casterVertexCount, isCasterOpaque); 18550ecf849cb7ccc3482517b74d2214b347927791eztenghui AlphaVertex* shadowVertices = 186d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui shadowVertexBuffer.alloc<AlphaVertex>(totalVertexCount); 187d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int vertexBufferIndex = 0; 188d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui uint16_t* indexBuffer = shadowVertexBuffer.allocIndices<uint16_t>(totalIndexCount); 189d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int indexBufferIndex = 0; 190d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui uint16_t umbraVertices[totalUmbraCount]; 191d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int umbraIndex = 0; 19255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 193d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui for (int i = 0; i < casterVertexCount; i++) { 194d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Corner: first figure out the extra vertices we need for the corner. 195d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui const Vector3& innerVertex = casterVertices[i]; 196d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 currentNormal = getNormalFromVertices(casterVertices, i, 197d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui (i + 1) % casterVertexCount); 198d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 199512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui int extraVerticesNumber = ShadowTessellator::getExtraVertexNumber(currentNormal, 200512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui previousNormal, CORNER_RADIANS_DIVISOR); 20150ecf849cb7ccc3482517b74d2214b347927791eztenghui 202d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui float expansionDist = innerVertex.z * heightFactor * geomFactor; 203d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui const int cornerSlicesNumber = extraVerticesNumber + 1; // Minimal as 1. 20450ecf849cb7ccc3482517b74d2214b347927791eztenghui#if DEBUG_SHADOW 205d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui ALOGD("cornerSlicesNumber is %d", cornerSlicesNumber); 20655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#endif 20755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 208d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Corner: fill the corner Vertex Buffer(VB) and Index Buffer(IB). 209d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // We fill the inner vertex first, such that we can fill the index buffer 210d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // inside the loop. 211d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int currentInnerVertexIndex = vertexBufferIndex; 212d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui if (!isCasterOpaque) { 213d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui umbraVertices[umbraIndex++] = vertexBufferIndex; 2147940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui } 215138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik AlphaVertex::set(&shadowVertices[vertexBufferIndex++], 216138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik casterVertices[i].x, casterVertices[i].y, 217138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik currentAlpha); 21855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 219d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui const Vector3& innerStart = casterVertices[i]; 2207940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui 221d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // outerStart is the first outer vertex for this inner vertex. 222d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // outerLast is the last outer vertex for this inner vertex. 223d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 outerStart = {0, 0}; 224d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 outerLast = {0, 0}; 225d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // This will create vertices from [0, cornerSlicesNumber] inclusively, 226d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // which means minimally 2 vertices even without the extra ones. 227d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui for (int j = 0; j <= cornerSlicesNumber; j++) { 228d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 averageNormal = 229d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui previousNormal * (cornerSlicesNumber - j) + currentNormal * j; 230d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui averageNormal /= cornerSlicesNumber; 231d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui averageNormal.normalize(); 232d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 outerVertex; 233d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui outerVertex.x = innerVertex.x + averageNormal.x * expansionDist; 234d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui outerVertex.y = innerVertex.y + averageNormal.y * expansionDist; 235d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 236d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = vertexBufferIndex; 237d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = currentInnerVertexIndex; 238d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui AlphaVertex::set(&shadowVertices[vertexBufferIndex++], outerVertex.x, 239138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik outerVertex.y, OUTER_ALPHA); 240d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 241d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui if (j == 0) { 242d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui outerStart = outerVertex; 243d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui } else if (j == cornerSlicesNumber) { 244d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui outerLast = outerVertex; 2457940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui } 2467940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui } 247d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui previousNormal = currentNormal; 248d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 249d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Edge: first figure out the extra vertices needed for the edge. 250d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui const Vector3& innerNext = casterVertices[(i + 1) % casterVertexCount]; 251d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui float nextAlpha = getAlphaFromFactoredZ(innerNext.z * heightFactor); 252d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui if (needsExtraForEdge(currentAlpha, nextAlpha)) { 253d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // TODO: See if we can / should cache this outer vertex across the loop. 254d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 outerNext; 255d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui float expansionDist = innerNext.z * heightFactor * geomFactor; 256d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui outerNext.x = innerNext.x + currentNormal.x * expansionDist; 257d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui outerNext.y = innerNext.y + currentNormal.y * expansionDist; 2587940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui 259d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Compute the angle and see how many extra points we need. 260d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int extraVerticesNumber = getEdgeExtraAndUpdateSpike(¤tSpike, 261d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui innerNext, centroid3d); 2627940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui#if DEBUG_SHADOW 263d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui ALOGD("extraVerticesNumber %d for edge %d", extraVerticesNumber, i); 2647940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui#endif 265d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Edge: fill the edge's VB and IB. 266d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // This will create vertices pair from [1, extraVerticesNumber - 1]. 267d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // If there is no extra vertices created here, the edge will be drawn 268d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // as just 2 triangles. 269d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui for (int k = 1; k < extraVerticesNumber; k++) { 270d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int startWeight = extraVerticesNumber - k; 271d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 currentOuter = 272d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui (outerLast * startWeight + outerNext * k) / extraVerticesNumber; 273d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = vertexBufferIndex; 274d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentOuter.x, 275138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik currentOuter.y, OUTER_ALPHA); 27655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 277d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui if (!isCasterOpaque) { 278d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui umbraVertices[umbraIndex++] = vertexBufferIndex; 27955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui } 280d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector3 currentInner = 281d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui (innerStart * startWeight + innerNext * k) / extraVerticesNumber; 282d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = vertexBufferIndex; 283d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentInner.x, 284d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui currentInner.y, 285138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik getAlphaFromFactoredZ(currentInner.z * heightFactor)); 28655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui } 28755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui } 288d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui currentAlpha = nextAlpha; 28955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui } 29055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 291d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = 1; 292d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = 0; 293d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 294d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui if (!isCasterOpaque) { 295d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Add the centroid as the last one in the vertex buffer. 296d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui float centroidOpacity = 297138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik getAlphaFromFactoredZ(centroid3d.z * heightFactor); 298d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int centroidIndex = vertexBufferIndex; 299d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid3d.x, 300d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui centroid3d.y, centroidOpacity); 301d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 302d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui for (int i = 0; i < umbraIndex; i++) { 303d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Note that umbraVertices[0] is always 0. 304d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // So the start and the end of the umbra are using the "0". 305d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // And penumbra ended with 0, so a degenerated triangle is formed b/t 306d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // the umbra and penumbra. 307d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = umbraVertices[i]; 308d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = centroidIndex; 309d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui } 310d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = 0; 31155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui } 312d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 313d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // At the end, update the real index and vertex buffer size. 314d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui shadowVertexBuffer.updateVertexCount(vertexBufferIndex); 315d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui shadowVertexBuffer.updateIndexCount(indexBufferIndex); 3164ac36f80beb958c77a92a3e1a235f6ed9daaa510Chris Craik shadowVertexBuffer.computeBounds<AlphaVertex>(); 317d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 318d2dcd6fded3a036f334a88bf9593398833f2919aztenghui ShadowTessellator::checkOverflow(vertexBufferIndex, totalVertexCount, "Ambient Vertex Buffer"); 319d2dcd6fded3a036f334a88bf9593398833f2919aztenghui ShadowTessellator::checkOverflow(indexBufferIndex, totalIndexCount, "Ambient Index Buffer"); 320d2dcd6fded3a036f334a88bf9593398833f2919aztenghui ShadowTessellator::checkOverflow(umbraIndex, totalUmbraCount, "Ambient Umbra Buffer"); 321d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 322d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#if DEBUG_SHADOW 323d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui for (int i = 0; i < vertexBufferIndex; i++) { 324d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui ALOGD("vertexBuffer i %d, (%f, %f %f)", i, shadowVertices[i].x, shadowVertices[i].y, 325d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui shadowVertices[i].alpha); 326d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui } 327d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui for (int i = 0; i < indexBufferIndex; i++) { 328d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui ALOGD("indexBuffer i %d, indexBuffer[i] %d", i, indexBuffer[i]); 329d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui } 330d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#endif 33155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui} 33255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 33355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui}; // namespace uirenderer 33455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui}; // namespace android 335