AmbientShadow.cpp revision 4ac36f80beb958c77a92a3e1a235f6ed9daaa510
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 1755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#define LOG_TAG "OpenGLRenderer" 1855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 19d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui/** 20d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Extra vertices for the corner for smoother corner. 21d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Only for outer vertices. 22d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Note that we use such extra memory to avoid an extra loop. 23d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui */ 24d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// For half circle, we could add EXTRA_VERTEX_PER_PI vertices. 25d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// Set to 1 if we don't want to have any. 26d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define EXTRA_CORNER_VERTEX_PER_PI 12 27d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 28d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// For the whole polygon, the sum of all the deltas b/t normals is 2 * M_PI, 29d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// therefore, the maximum number of extra vertices will be twice bigger. 30d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define MAX_EXTRA_CORNER_VERTEX_NUMBER (2 * EXTRA_CORNER_VERTEX_PER_PI) 31d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 32d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// For each RADIANS_DIVISOR, we would allocate one more vertex b/t the normals. 33d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define CORNER_RADIANS_DIVISOR (M_PI / EXTRA_CORNER_VERTEX_PER_PI) 34d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 35d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui/** 36d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Extra vertices for the Edge for interpolation artifacts. 37d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Same value for both inner and outer vertices. 38d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui */ 39d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define EXTRA_EDGE_VERTEX_PER_PI 50 40d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 41d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define MAX_EXTRA_EDGE_VERTEX_NUMBER (2 * EXTRA_EDGE_VERTEX_PER_PI) 42d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 43d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define EDGE_RADIANS_DIVISOR (M_PI / EXTRA_EDGE_VERTEX_PER_PI) 44d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 45d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui/** 46d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Other constants: 47d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui */ 48d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// For the edge of the penumbra, the opacity is 0. 49d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define OUTER_OPACITY (0.0f) 50d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 51d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// Once the alpha difference is greater than this threshold, we will allocate extra 52d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// edge vertices. 53d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// If this is set to negative value, then all the edge will be tessellated. 54d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#define ALPHA_THRESHOLD (0.1f / 255.0f) 55d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 5655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include <math.h> 5755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include <utils/Log.h> 58564acf7c9bff822f608cda0d5df0a64a9f9aaefdChris Craik#include <utils/Vector.h> 5955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 6055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include "AmbientShadow.h" 6163d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui#include "ShadowTessellator.h" 6255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include "Vertex.h" 63d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#include "utils/MathUtils.h" 6455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 6555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghuinamespace android { 6655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghuinamespace uirenderer { 6755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 6855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui/** 69d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Local utility functions. 70d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui */ 71d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline Vector2 getNormalFromVertices(const Vector3* vertices, int current, int next) { 72d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Convert from Vector3 to Vector2 first. 73d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 currentVertex = { vertices[current].x, vertices[current].y }; 74d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 nextVertex = { vertices[next].x, vertices[next].y }; 75d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 76d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui return ShadowTessellator::calculateNormal(currentVertex, nextVertex); 77d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui} 78d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 79d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// The input z value will be converted to be non-negative inside. 80d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// The output must be ranged from 0 to 1. 81d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline float getAlphaFromFactoredZ(float factoredZ) { 82d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui return 1.0 / (1 + MathUtils::max(factoredZ, 0.0f)); 83d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui} 84d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 85d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline float getTransformedAlphaFromAlpha(float alpha) { 86d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui return acosf(1.0f - 2.0f * alpha); 87d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui} 88d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 89d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// The output is ranged from 0 to M_PI. 90d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline float getTransformedAlphaFromFactoredZ(float factoredZ) { 91d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui return getTransformedAlphaFromAlpha(getAlphaFromFactoredZ(factoredZ)); 92d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui} 93d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 94d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline int getEdgeExtraAndUpdateSpike(Vector2* currentSpike, 95d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui const Vector3& secondVertex, const Vector3& centroid) { 96d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 secondSpike = {secondVertex.x - centroid.x, secondVertex.y - centroid.y}; 97d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui secondSpike.normalize(); 98d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 99512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui int result = ShadowTessellator::getExtraVertexNumber(secondSpike, *currentSpike, 100512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui EDGE_RADIANS_DIVISOR); 101d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *currentSpike = secondSpike; 102d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui return result; 103d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui} 104d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 105d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// Given the caster's vertex count, compute all the buffers size depending on 106d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui// whether or not the caster is opaque. 107d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline void computeBufferSize(int* totalVertexCount, int* totalIndexCount, 108d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int* totalUmbraCount, int casterVertexCount, bool isCasterOpaque) { 109d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Compute the size of the vertex buffer. 110d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int outerVertexCount = casterVertexCount * 2 + MAX_EXTRA_CORNER_VERTEX_NUMBER + 111d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui MAX_EXTRA_EDGE_VERTEX_NUMBER; 112d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int innerVertexCount = casterVertexCount + MAX_EXTRA_EDGE_VERTEX_NUMBER; 113d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *totalVertexCount = outerVertexCount + innerVertexCount; 114d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 115d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Compute the size of the index buffer. 116d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *totalIndexCount = 2 * outerVertexCount + 2; 117d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 118d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Compute the size of the umber buffer. 119d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // For translucent object, keep track of the umbra(inner) vertex in order to draw 120d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // inside. We only need to store the index information. 121d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *totalUmbraCount = 0; 122d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui if (!isCasterOpaque) { 123d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Add the centroid if occluder is translucent. 124d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *totalVertexCount++; 125d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *totalIndexCount += 2 * innerVertexCount + 1; 126d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui *totalUmbraCount = innerVertexCount; 127d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui } 128d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui} 129d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 130d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghuiinline bool needsExtraForEdge(float firstAlpha, float secondAlpha) { 131d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui return abs(firstAlpha - secondAlpha) > ALPHA_THRESHOLD; 132d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui} 133d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 134d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui/** 13555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Calculate the shadows as a triangle strips while alpha value as the 13655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * shadow values. 13755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * 13850ecf849cb7ccc3482517b74d2214b347927791eztenghui * @param isCasterOpaque Whether the caster is opaque. 13955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param vertices The shadow caster's polygon, which is represented in a Vector3 14055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * array. 14155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param vertexCount The length of caster's polygon in terms of number of 14255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * vertices. 14363d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui * @param centroid3d The centroid of the shadow caster. 14455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param heightFactor The factor showing the higher the object, the lighter the 14555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * shadow. 14655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param geomFactor The factor scaling the geometry expansion along the normal. 14755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * 14855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * @param shadowVertexBuffer Return an floating point array of (x, y, a) 14955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * triangle strips mode. 150d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * 151d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * An simple illustration: 152d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * For now let's mark the outer vertex as Pi, the inner as Vi, the centroid as C. 153d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * 154d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * First project the occluder to the Z=0 surface. 155d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Then we got all the inner vertices. And we compute the normal for each edge. 156d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * According to the normal, we generate outer vertices. E.g: We generate P1 / P4 157d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * as extra corner vertices to make the corner looks round and smoother. 158d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * 159d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * Due to the fact that the alpha is not linear interpolated along the inner 160d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * edge, when the alpha is different, we may add extra vertices such as P2.1, P2.2, 161d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * V0.1, V0.2 to avoid the visual artifacts. 162d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * 163d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * (P3) 164d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * (P2) (P2.1) (P2.2) | ' (P4) 165d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * (P1)' | | | | ' 166d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * ' | | | | ' 167d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * (P0) ------------------------------------------------(P5) 168d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | (V0) (V0.1) (V0.2) |(V1) 169d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | | 170d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | | 171d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | (C) | 172d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | | 173d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | | 174d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | | 175d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * | | 176d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui * (V3)-----------------------------------(V2) 17755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui */ 17805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craikvoid AmbientShadow::createAmbientShadow(bool isCasterOpaque, 179d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui const Vector3* casterVertices, int casterVertexCount, const Vector3& centroid3d, 18050ecf849cb7ccc3482517b74d2214b347927791eztenghui float heightFactor, float geomFactor, VertexBuffer& shadowVertexBuffer) { 181d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui shadowVertexBuffer.setMode(VertexBuffer::kIndices); 18255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 183d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // In order to computer the outer vertices in one loop, we need pre-compute 184d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // the normal by the vertex (n - 1) to vertex 0, and the spike and alpha value 185d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // for vertex 0. 186d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 previousNormal = getNormalFromVertices(casterVertices, 187d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui casterVertexCount - 1 , 0); 188d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 currentSpike = {casterVertices[0].x - centroid3d.x, 189d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui casterVertices[0].y - centroid3d.y}; 190d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui currentSpike.normalize(); 191d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui float currentAlpha = getAlphaFromFactoredZ(casterVertices[0].z * heightFactor); 19255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 193d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Preparing all the output data. 194d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int totalVertexCount, totalIndexCount, totalUmbraCount; 195d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui computeBufferSize(&totalVertexCount, &totalIndexCount, &totalUmbraCount, 196d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui casterVertexCount, isCasterOpaque); 19750ecf849cb7ccc3482517b74d2214b347927791eztenghui AlphaVertex* shadowVertices = 198d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui shadowVertexBuffer.alloc<AlphaVertex>(totalVertexCount); 199d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int vertexBufferIndex = 0; 200d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui uint16_t* indexBuffer = shadowVertexBuffer.allocIndices<uint16_t>(totalIndexCount); 201d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int indexBufferIndex = 0; 202d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui uint16_t umbraVertices[totalUmbraCount]; 203d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int umbraIndex = 0; 20455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 205d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui for (int i = 0; i < casterVertexCount; i++) { 206d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Corner: first figure out the extra vertices we need for the corner. 207d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui const Vector3& innerVertex = casterVertices[i]; 208d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 currentNormal = getNormalFromVertices(casterVertices, i, 209d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui (i + 1) % casterVertexCount); 210d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 211512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui int extraVerticesNumber = ShadowTessellator::getExtraVertexNumber(currentNormal, 212512e643ce83b1d48ad9630a3622276f795cf4fb2ztenghui previousNormal, CORNER_RADIANS_DIVISOR); 21350ecf849cb7ccc3482517b74d2214b347927791eztenghui 214d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui float expansionDist = innerVertex.z * heightFactor * geomFactor; 215d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui const int cornerSlicesNumber = extraVerticesNumber + 1; // Minimal as 1. 21650ecf849cb7ccc3482517b74d2214b347927791eztenghui#if DEBUG_SHADOW 217d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui ALOGD("cornerSlicesNumber is %d", cornerSlicesNumber); 21855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#endif 21955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 220d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Corner: fill the corner Vertex Buffer(VB) and Index Buffer(IB). 221d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // We fill the inner vertex first, such that we can fill the index buffer 222d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // inside the loop. 223d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int currentInnerVertexIndex = vertexBufferIndex; 224d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui if (!isCasterOpaque) { 225d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui umbraVertices[umbraIndex++] = vertexBufferIndex; 2267940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui } 227d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui AlphaVertex::set(&shadowVertices[vertexBufferIndex++], casterVertices[i].x, 228d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui casterVertices[i].y, 229d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui getTransformedAlphaFromAlpha(currentAlpha)); 23055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 231d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui const Vector3& innerStart = casterVertices[i]; 2327940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui 233d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // outerStart is the first outer vertex for this inner vertex. 234d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // outerLast is the last outer vertex for this inner vertex. 235d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 outerStart = {0, 0}; 236d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 outerLast = {0, 0}; 237d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // This will create vertices from [0, cornerSlicesNumber] inclusively, 238d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // which means minimally 2 vertices even without the extra ones. 239d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui for (int j = 0; j <= cornerSlicesNumber; j++) { 240d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 averageNormal = 241d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui previousNormal * (cornerSlicesNumber - j) + currentNormal * j; 242d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui averageNormal /= cornerSlicesNumber; 243d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui averageNormal.normalize(); 244d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 outerVertex; 245d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui outerVertex.x = innerVertex.x + averageNormal.x * expansionDist; 246d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui outerVertex.y = innerVertex.y + averageNormal.y * expansionDist; 247d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 248d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = vertexBufferIndex; 249d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = currentInnerVertexIndex; 250d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui AlphaVertex::set(&shadowVertices[vertexBufferIndex++], outerVertex.x, 251d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui outerVertex.y, OUTER_OPACITY); 252d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 253d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui if (j == 0) { 254d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui outerStart = outerVertex; 255d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui } else if (j == cornerSlicesNumber) { 256d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui outerLast = outerVertex; 2577940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui } 2587940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui } 259d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui previousNormal = currentNormal; 260d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 261d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Edge: first figure out the extra vertices needed for the edge. 262d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui const Vector3& innerNext = casterVertices[(i + 1) % casterVertexCount]; 263d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui float nextAlpha = getAlphaFromFactoredZ(innerNext.z * heightFactor); 264d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui if (needsExtraForEdge(currentAlpha, nextAlpha)) { 265d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // TODO: See if we can / should cache this outer vertex across the loop. 266d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 outerNext; 267d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui float expansionDist = innerNext.z * heightFactor * geomFactor; 268d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui outerNext.x = innerNext.x + currentNormal.x * expansionDist; 269d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui outerNext.y = innerNext.y + currentNormal.y * expansionDist; 2707940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui 271d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Compute the angle and see how many extra points we need. 272d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int extraVerticesNumber = getEdgeExtraAndUpdateSpike(¤tSpike, 273d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui innerNext, centroid3d); 2747940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui#if DEBUG_SHADOW 275d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui ALOGD("extraVerticesNumber %d for edge %d", extraVerticesNumber, i); 2767940dc57e3ffcf9c4a33375215f3a42250fa896cztenghui#endif 277d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Edge: fill the edge's VB and IB. 278d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // This will create vertices pair from [1, extraVerticesNumber - 1]. 279d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // If there is no extra vertices created here, the edge will be drawn 280d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // as just 2 triangles. 281d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui for (int k = 1; k < extraVerticesNumber; k++) { 282d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int startWeight = extraVerticesNumber - k; 283d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector2 currentOuter = 284d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui (outerLast * startWeight + outerNext * k) / extraVerticesNumber; 285d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = vertexBufferIndex; 286d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentOuter.x, 287d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui currentOuter.y, OUTER_OPACITY); 28855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 289d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui if (!isCasterOpaque) { 290d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui umbraVertices[umbraIndex++] = vertexBufferIndex; 29155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui } 292d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui Vector3 currentInner = 293d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui (innerStart * startWeight + innerNext * k) / extraVerticesNumber; 294d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = vertexBufferIndex; 295d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentInner.x, 296d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui currentInner.y, 297d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui getTransformedAlphaFromFactoredZ(currentInner.z * heightFactor)); 29855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui } 29955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui } 300d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui currentAlpha = nextAlpha; 30155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui } 30255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 303d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = 1; 304d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = 0; 305d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 306d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui if (!isCasterOpaque) { 307d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Add the centroid as the last one in the vertex buffer. 308d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui float centroidOpacity = 309d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui getTransformedAlphaFromFactoredZ(centroid3d.z * heightFactor); 310d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui int centroidIndex = vertexBufferIndex; 311d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid3d.x, 312d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui centroid3d.y, centroidOpacity); 313d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 314d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui for (int i = 0; i < umbraIndex; i++) { 315d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // Note that umbraVertices[0] is always 0. 316d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // So the start and the end of the umbra are using the "0". 317d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // And penumbra ended with 0, so a degenerated triangle is formed b/t 318d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // the umbra and penumbra. 319d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = umbraVertices[i]; 320d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = centroidIndex; 321d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui } 322d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui indexBuffer[indexBufferIndex++] = 0; 32355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui } 324d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 325d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui // At the end, update the real index and vertex buffer size. 326d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui shadowVertexBuffer.updateVertexCount(vertexBufferIndex); 327d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui shadowVertexBuffer.updateIndexCount(indexBufferIndex); 3284ac36f80beb958c77a92a3e1a235f6ed9daaa510Chris Craik shadowVertexBuffer.computeBounds<AlphaVertex>(); 329d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 330d2dcd6fded3a036f334a88bf9593398833f2919aztenghui ShadowTessellator::checkOverflow(vertexBufferIndex, totalVertexCount, "Ambient Vertex Buffer"); 331d2dcd6fded3a036f334a88bf9593398833f2919aztenghui ShadowTessellator::checkOverflow(indexBufferIndex, totalIndexCount, "Ambient Index Buffer"); 332d2dcd6fded3a036f334a88bf9593398833f2919aztenghui ShadowTessellator::checkOverflow(umbraIndex, totalUmbraCount, "Ambient Umbra Buffer"); 333d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui 334d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#if DEBUG_SHADOW 335d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui for (int i = 0; i < vertexBufferIndex; i++) { 336d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui ALOGD("vertexBuffer i %d, (%f, %f %f)", i, shadowVertices[i].x, shadowVertices[i].y, 337d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui shadowVertices[i].alpha); 338d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui } 339d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui for (int i = 0; i < indexBufferIndex; i++) { 340d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui ALOGD("indexBuffer i %d, indexBuffer[i] %d", i, indexBuffer[i]); 341d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui } 342d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui#endif 34355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui} 34455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 34555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui}; // namespace uirenderer 34655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui}; // namespace android 347