//create a vertex buffer for efficiently rendering cubes LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage) { LLVertexBuffer* ret = new LLVertexBuffer(type_mask, usage); ret->allocateBuffer(8, 64, true); LLStrider<LLVector3> pos; LLStrider<U16> idx; ret->getVertexStrider(pos); ret->getIndexStrider(idx); pos[0] = LLVector3(-1,-1,-1); pos[1] = LLVector3(-1,-1, 1); pos[2] = LLVector3(-1, 1,-1); pos[3] = LLVector3(-1, 1, 1); pos[4] = LLVector3( 1,-1,-1); pos[5] = LLVector3( 1,-1, 1); pos[6] = LLVector3( 1, 1,-1); pos[7] = LLVector3( 1, 1, 1); for (U32 i = 0; i < 64; i++) { idx[i] = sOcclusionIndices[i]; } ret->flush(); return ret; }
Wavefront::Wavefront(LLFace* face, LLPolyMesh* mesh, const LLXform* transform, const LLXform* transform_normals) : name("") { LLVertexBuffer* vb = face->getVertexBuffer(); if (!vb) return; LLStrider<LLVector3> getVerts; LLStrider<LLVector3> getNorms; LLStrider<LLVector2> getCoord; LLStrider<U16> getIndices; face->getGeometry(getVerts, getNorms, getCoord, getIndices); const U16 start = face->getGeomStart(); const U32 end = start + (mesh ? mesh->getNumVertices() : vb->getNumVerts()) - 1; //vertices for (U32 i = start; i <= end; ++i) vertices.push_back(std::make_pair(getVerts[i], getCoord[i])); if (transform) Transform(vertices, transform); for (U32 i = start; i <= end; ++i) normals.push_back(getNorms[i]); if (transform_normals) Transform(normals, transform_normals); const U32 pcount = mesh ? mesh->getNumFaces() : (vb->getNumIndices()/3); //indices const U16 offset = face->getIndicesStart(); //indices for (U32 i = 0; i < pcount; ++i) { triangles.push_back(tri(getIndices[i * 3 + offset] + start, getIndices[i * 3 + 1 + offset] + start, getIndices[i * 3 + 2 + offset] + start)); } }
// static void LLViewerJointMesh::updateGeometry(LLFace *mFace, LLPolyMesh *mMesh) { LLStrider<LLVector3> o_vertices; LLStrider<LLVector3> o_normals; //get vertex and normal striders LLVertexBuffer* buffer = mFace->getVertexBuffer(); buffer->getVertexStrider(o_vertices, 0); buffer->getNormalStrider(o_normals, 0); F32* __restrict vert = o_vertices[0].mV; F32* __restrict norm = o_normals[0].mV; const F32* __restrict weights = mMesh->getWeights(); const LLVector4a* __restrict coords = (LLVector4a*) mMesh->getCoords(); const LLVector4a* __restrict normals = (LLVector4a*) mMesh->getNormals(); U32 offset = mMesh->mFaceVertexOffset*4; vert += offset; norm += offset; for (U32 index = 0; index < mMesh->getNumVertices(); index++) { // equivalent to joint = floorf(weights[index]); S32 joint = _mm_cvtt_ss2si(_mm_load_ss(weights+index)); F32 w = weights[index] - joint; LLMatrix4a gBlendMat; if (w != 0.f) { // blend between matrices and apply gBlendMat.setLerp(gJointMatAligned[joint+0], gJointMatAligned[joint+1], w); LLVector4a res; gBlendMat.affineTransform(coords[index], res); res.store4a(vert+index*4); gBlendMat.rotate(normals[index], res); res.store4a(norm+index*4); } else { // No lerp required in this case. LLVector4a res; gJointMatAligned[joint].affineTransform(coords[index], res); res.store4a(vert+index*4); gJointMatAligned[joint].rotate(normals[index], res); res.store4a(norm+index*4); } } buffer->flush(); }
//split every triangle in LLVertexBuffer into even fourths (assumes index triangle lists) void subdivide(LLVertexBuffer& in, LLVertexBuffer* ret) { S32 tri_in = in.getNumIndices()/3; ret->allocateBuffer(tri_in*4*3, tri_in*4*3, TRUE); LLStrider<LLVector3> vin, vout; LLStrider<U16> indin, indout; ret->getVertexStrider(vout); in.getVertexStrider(vin); ret->getIndexStrider(indout); in.getIndexStrider(indin); for (S32 i = 0; i < tri_in; i++) { LLVector3 v0 = vin[*indin++]; LLVector3 v1 = vin[*indin++]; LLVector3 v2 = vin[*indin++]; LLVector3 v3 = (v0 + v1) * 0.5f; LLVector3 v4 = (v1 + v2) * 0.5f; LLVector3 v5 = (v2 + v0) * 0.5f; *vout++ = v0; *vout++ = v3; *vout++ = v5; *vout++ = v3; *vout++ = v4; *vout++ = v5; *vout++ = v3; *vout++ = v1; *vout++ = v4; *vout++ = v5; *vout++ = v4; *vout++ = v2; } for (S32 i = 0; i < ret->getNumIndices(); i++) { *indout++ = i; } }
// static void LLViewerJointMesh::updateGeometryVectorized(LLFace *face, LLPolyMesh *mesh) { static LLV4Matrix4 sJointMat[32]; LLDynamicArray<LLJointRenderData*>& joint_data = mesh->getReferenceMesh()->mJointRenderData; S32 j, joint_num, joint_end = joint_data.count(); LLV4Vector3 pivot; //upload joint pivots/matrices for(j = joint_num = 0; joint_num < joint_end ; ++joint_num ) { LLSkinJoint *sj; const LLMatrix4 * wm = joint_data[joint_num]->mWorldMatrix; if (NULL == (sj = joint_data[joint_num]->mSkinJoint)) { sj = joint_data[++joint_num]->mSkinJoint; ((LLV4Matrix3)(sJointMat[j] = *wm)).multiply(sj->mRootToParentJointSkinOffset, pivot); sJointMat[j++].translate(pivot); wm = joint_data[joint_num]->mWorldMatrix; } ((LLV4Matrix3)(sJointMat[j] = *wm)).multiply(sj->mRootToJointSkinOffset, pivot); sJointMat[j++].translate(pivot); } F32 weight = F32_MAX; LLV4Matrix4 blend_mat; LLStrider<LLVector3> o_vertices; LLStrider<LLVector3> o_normals; LLVertexBuffer *buffer = face->mVertexBuffer; buffer->getVertexStrider(o_vertices, mesh->mFaceVertexOffset); buffer->getNormalStrider(o_normals, mesh->mFaceVertexOffset); const F32* weights = mesh->getWeights(); const LLVector3* coords = mesh->getCoords(); const LLVector3* normals = mesh->getNormals(); for (U32 index = 0, index_end = mesh->getNumVertices(); index < index_end; ++index) { if( weight != weights[index]) { S32 joint = llfloor(weight = weights[index]); blend_mat.lerp(sJointMat[joint], sJointMat[joint+1], weight - joint); } blend_mat.multiply(coords[index], o_vertices[index]); ((LLV4Matrix3)blend_mat).multiply(normals[index], o_normals[index]); } buffer->setBuffer(0); }
void chop(LLVertexBuffer& in, LLVertexBuffer* out) { //chop off all triangles below horizon F32 d = LLWLParamManager::sParamMgr->getDomeOffset() * LLWLParamManager::sParamMgr->getDomeRadius(); std::vector<LLVector3> vert; LLStrider<LLVector3> vin; LLStrider<U16> index; in.getVertexStrider(vin); in.getIndexStrider(index); U32 tri_count = in.getNumIndices()/3; for (U32 i = 0; i < tri_count; i++) { LLVector3 &v1 = vin[index[i*3+0]]; LLVector3 &v2 = vin[index[i*3+1]]; LLVector3 &v3 = vin[index[i*3+2]]; if (v1.mV[1] > d || v2.mV[1] > d || v3.mV[1] > d) { v1.mV[1] = llmax(v1.mV[1], d); v2.mV[1] = llmax(v1.mV[1], d); v3.mV[1] = llmax(v1.mV[1], d); vert.push_back(v1); vert.push_back(v2); vert.push_back(v3); } } out->allocateBuffer(vert.size(), vert.size(), TRUE); LLStrider<LLVector3> vout; out->getVertexStrider(vout); out->getIndexStrider(index); for (U32 i = 0; i < vert.size(); i++) { *vout++ = vert[i]; *index++ = i; } }
static bool get(LLVertexBuffer& vbo, strider_t& strider, S32 index) { if (type == LLVertexBuffer::TYPE_INDEX) { volatile U8* ptr = vbo.mapIndexBuffer(index); if (ptr == NULL) { llwarns << "mapIndexBuffer failed!" << llendl; return FALSE; } strider = (T*)ptr; strider.setStride(0); strider.setTypeSize(0); return TRUE; } else if (vbo.hasDataType(type)) { S32 stride = vbo.getStride(type); volatile U8* ptr = vbo.mapVertexBuffer(type,index); if (ptr == NULL) { llwarns << "mapVertexBuffer failed!" << llendl; return FALSE; } strider = (T*)ptr; strider.setStride(stride); strider.setTypeSize(LLVertexBuffer::sTypeSize[type]); return TRUE; } else { llerrs << "VertexBufferStrider could not find valid vertex data." << llendl; } return FALSE; }
// static void LLViewerJointMesh::updateGeometrySSE2(LLFace *face, LLPolyMesh *mesh) { // This cannot be a file-level static because it will be initialized // before main() using SSE code, which will crash on non-SSE processors. static LLV4Matrix4 sJointMat[32]; LLDynamicArray<LLJointRenderData*>& joint_data = mesh->getReferenceMesh()->mJointRenderData; //upload joint pivots/matrices for(S32 j = 0, jend = joint_data.count(); j < jend ; ++j ) { matrix_translate(sJointMat[j], joint_data[j]->mWorldMatrix, joint_data[j]->mSkinJoint ? joint_data[j]->mSkinJoint->mRootToJointSkinOffset : joint_data[j+1]->mSkinJoint->mRootToParentJointSkinOffset); } F32 weight = F32_MAX; LLV4Matrix4 blend_mat; LLStrider<LLVector3> o_vertices; LLStrider<LLVector3> o_normals; LLVertexBuffer *buffer = face->mVertexBuffer; buffer->getVertexStrider(o_vertices, mesh->mFaceVertexOffset); buffer->getNormalStrider(o_normals, mesh->mFaceVertexOffset); const F32* weights = mesh->getWeights(); const LLVector3* coords = mesh->getCoords(); const LLVector3* normals = mesh->getNormals(); for (U32 index = 0, index_end = mesh->getNumVertices(); index < index_end; ++index) { if( weight != weights[index]) { S32 joint = llfloor(weight = weights[index]); blend_mat.lerp(sJointMat[joint], sJointMat[joint+1], weight - joint); } blend_mat.multiply(coords[index], o_vertices[index]); ((LLV4Matrix3)blend_mat).multiply(normals[index], o_normals[index]); } //setBuffer(0) called in LLVOAvatar::renderSkinned }
void LLVertexBuffer::clientCopy(F64 max_time) { if (!sDeleteList.empty()) { size_t num = sDeleteList.size(); glDeleteBuffersARB(sDeleteList.size(), (GLuint*) &(sDeleteList[0])); sDeleteList.clear(); sGLCount -= num; } if (sEnableVBOs) { LLTimer timer; BOOL reset = TRUE; buffer_list_t::iterator iter = sLockedList.begin(); while(iter != sLockedList.end()) { LLVertexBuffer* buffer = *iter; if (buffer->isLocked() && buffer->useVBOs()) { buffer->setBuffer(0); } ++iter; if (reset) { reset = FALSE; timer.reset(); //skip first copy (don't count pipeline stall) } else { if (timer.getElapsedTimeF64() > max_time) { break; } } } sLockedList.erase(sLockedList.begin(), iter); } }
void LLDrawPoolTree::render(S32 pass) { LLFastTimer t(LLPipeline::sShadowRender ? FTM_SHADOW_TREE : FTM_RENDER_TREES); if (mDrawFace.empty()) { return; } LLGLEnable test(GL_ALPHA_TEST); LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f); if (gSavedSettings.getBOOL("RenderAnimateTrees")) { renderTree(); } else { gGL.getTexUnit(sDiffTex)->bind(mTexturep); for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { LLFace *face = *iter; LLVertexBuffer* buff = face->getVertexBuffer(); if(buff) { buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); buff->drawRange(LLRender::TRIANGLES, 0, buff->getRequestedVerts()-1, buff->getRequestedIndices(), 0); gPipeline.addTrianglesDrawn(buff->getRequestedIndices()); } } } }
void LLDrawPoolTree::render(S32 pass) { LLFastTimer t(LLPipeline::sShadowRender ? FTM_SHADOW_TREE : FTM_RENDER_TREES); if (mDrawFace.empty()) { return; } LLGLState test(GL_ALPHA_TEST, LLGLSLShader::sNoFixedFunction ? 0 : 1); LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f); gGL.getTexUnit(sDiffTex)->bind(mTexturep); for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { LLFace *face = *iter; LLVertexBuffer* buff = face->getVertexBuffer(); if(buff) { buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0); gPipeline.addTrianglesDrawn(buff->getNumIndices()); } } }
static bool get(LLVertexBuffer& vbo, strider_t& strider, S32 index) { vbo.mapBuffer(); if (type == LLVertexBuffer::TYPE_INDEX) { S32 stride = sizeof(T); strider = (T*)(vbo.getMappedIndices() + index*stride); strider.setStride(0); return TRUE; } else if (vbo.hasDataType(type)) { S32 stride = vbo.getStride(); strider = (T*)(vbo.getMappedData() + vbo.getOffset(type) + index*stride); strider.setStride(stride); return TRUE; } else { llerrs << "VertexBufferStrider could not find valid vertex data." << llendl; } return FALSE; }
void create_vertex_buffers_from_model(LLModel* model, std::vector<LLPointer <LLVertexBuffer> >& vertex_buffers) { #if 0 //VECTORIZE THIS ? vertex_buffers.clear(); for (S32 i = 0; i < model->getNumVolumeFaces(); ++i) { const LLVolumeFace &vf = model->getVolumeFace(i); U32 num_vertices = vf.mNumVertices; U32 num_indices = vf.mNumIndices; if (!num_vertices || ! num_indices) { continue; } LLVertexBuffer* vb = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0, 0); vb->allocateBuffer(num_vertices, num_indices, TRUE); LLStrider<LLVector3> vertex_strider; LLStrider<LLVector3> normal_strider; LLStrider<LLVector2> tc_strider; LLStrider<U16> index_strider; vb->getVertexStrider(vertex_strider); vb->getNormalStrider(normal_strider); vb->getTexCoord0Strider(tc_strider); vb->getIndexStrider(index_strider); // build vertices and normals for (U32 i = 0; (S32)i < num_vertices; i++) { *(vertex_strider++) = vf.mVertices[i].mPosition; *(tc_strider++) = vf.mVertices[i].mTexCoord; LLVector3 normal = vf.mVertices[i].mNormal; normal.normalize(); *(normal_strider++) = normal; } // build indices for (U32 i = 0; i < num_indices; i++) { *(index_strider++) = vf.mIndices[i]; } vertex_buffers.push_back(vb); } #endif }
void LLDrawPoolTree::render(S32 pass) { LLFastTimer t(LLPipeline::sShadowRender ? FTM_SHADOW_TREE : FTM_RENDER_TREES); if (mDrawFace.empty()) { return; } LLGLState test(GL_ALPHA_TEST, LLGLSLShader::sNoFixedFunction ? 0 : 1); LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f); static LLCachedControl<bool> sRenderAnimateTrees("RenderAnimateTrees", false); if (sRenderAnimateTrees) { renderTree(); } else gGL.getTexUnit(sDiffTex)->bind(mTexturep); for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { LLFace *face = *iter; LLVertexBuffer* buff = face->getVertexBuffer(); if(buff) { LLMatrix4* model_matrix = &(face->getDrawable()->getRegion()->mRenderMatrix); if (model_matrix != gGLLastMatrix) { gGLLastMatrix = model_matrix; gGL.loadMatrix(gGLModelView); if (model_matrix) { llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); gGL.multMatrix((GLfloat*) model_matrix->mMatrix); } gPipeline.mMatrixOpCount++; } buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0); gPipeline.addTrianglesDrawn(buff->getNumIndices()); } } }
void LLTerrainPartition::getGeometry(LLSpatialGroup* group) { LLFastTimer ftm(FTM_REBUILD_TERRAIN_VB); LLVertexBuffer* buffer = group->mVertexBuffer; //get vertex buffer striders LLStrider<LLVector3> vertices; LLStrider<LLVector3> normals; LLStrider<LLVector2> texcoords2; LLStrider<LLVector2> texcoords; LLStrider<U16> indices; llassert_always(buffer->getVertexStrider(vertices)); llassert_always(buffer->getNormalStrider(normals)); llassert_always(buffer->getTexCoord0Strider(texcoords)); llassert_always(buffer->getTexCoord1Strider(texcoords2)); llassert_always(buffer->getIndexStrider(indices)); U32 indices_index = 0; U32 index_offset = 0; for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) { LLFace* facep = *i; facep->setIndicesIndex(indices_index); facep->setGeomIndex(index_offset); facep->setVertexBuffer(buffer); LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject(); patchp->getGeometry(vertices, normals, texcoords, texcoords2, indices); indices_index += facep->getIndicesCount(); index_offset += facep->getGeomCount(); } buffer->flush(); mFaceList.clear(); }
void LLViewerJointMesh::updateGeometry() { if (!(mValid && mMesh && mFace && mMesh->hasWeights() && mFace->mVertexBuffer.notNull() && LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR) == 0)) { return; } uploadJointMatrices(); LLStrider<LLVector3> o_vertices; LLStrider<LLVector3> o_normals; //get vertex and normal striders LLVertexBuffer *buffer = mFace->mVertexBuffer; buffer->getVertexStrider(o_vertices, 0); buffer->getNormalStrider(o_normals, 0); F32 last_weight = F32_MAX; LLMatrix4 gBlendMat; LLMatrix3 gBlendRotMat; const F32* weights = mMesh->getWeights(); const LLVector3* coords = mMesh->getCoords(); const LLVector3* normals = mMesh->getNormals(); for (U32 index = 0; index < mMesh->getNumVertices(); index++) { U32 bidx = index + mMesh->mFaceVertexOffset; // blend by first matrix F32 w = weights[index]; // Maybe we don't have to change gBlendMat. // Profiles of a single-avatar scene on a Mac show this to be a very // common case. JC if (w == last_weight) { o_vertices[bidx] = coords[index] * gBlendMat; o_normals[bidx] = normals[index] * gBlendRotMat; continue; } last_weight = w; S32 joint = llfloor(w); w -= joint; // No lerp required in this case. if (w == 1.0f) { gBlendMat = gJointMat[joint+1]; o_vertices[bidx] = coords[index] * gBlendMat; gBlendRotMat = gJointRot[joint+1]; o_normals[bidx] = normals[index] * gBlendRotMat; continue; } // Try to keep all the accesses to the matrix data as close // together as possible. This function is a hot spot on the // Mac. JC LLMatrix4 &m0 = gJointMat[joint+1]; LLMatrix4 &m1 = gJointMat[joint+0]; gBlendMat.mMatrix[VX][VX] = lerp(m1.mMatrix[VX][VX], m0.mMatrix[VX][VX], w); gBlendMat.mMatrix[VX][VY] = lerp(m1.mMatrix[VX][VY], m0.mMatrix[VX][VY], w); gBlendMat.mMatrix[VX][VZ] = lerp(m1.mMatrix[VX][VZ], m0.mMatrix[VX][VZ], w); gBlendMat.mMatrix[VY][VX] = lerp(m1.mMatrix[VY][VX], m0.mMatrix[VY][VX], w); gBlendMat.mMatrix[VY][VY] = lerp(m1.mMatrix[VY][VY], m0.mMatrix[VY][VY], w); gBlendMat.mMatrix[VY][VZ] = lerp(m1.mMatrix[VY][VZ], m0.mMatrix[VY][VZ], w); gBlendMat.mMatrix[VZ][VX] = lerp(m1.mMatrix[VZ][VX], m0.mMatrix[VZ][VX], w); gBlendMat.mMatrix[VZ][VY] = lerp(m1.mMatrix[VZ][VY], m0.mMatrix[VZ][VY], w); gBlendMat.mMatrix[VZ][VZ] = lerp(m1.mMatrix[VZ][VZ], m0.mMatrix[VZ][VZ], w); gBlendMat.mMatrix[VW][VX] = lerp(m1.mMatrix[VW][VX], m0.mMatrix[VW][VX], w); gBlendMat.mMatrix[VW][VY] = lerp(m1.mMatrix[VW][VY], m0.mMatrix[VW][VY], w); gBlendMat.mMatrix[VW][VZ] = lerp(m1.mMatrix[VW][VZ], m0.mMatrix[VW][VZ], w); o_vertices[bidx] = coords[index] * gBlendMat; LLMatrix3 &n0 = gJointRot[joint+1]; LLMatrix3 &n1 = gJointRot[joint+0]; gBlendRotMat.mMatrix[VX][VX] = lerp(n1.mMatrix[VX][VX], n0.mMatrix[VX][VX], w); gBlendRotMat.mMatrix[VX][VY] = lerp(n1.mMatrix[VX][VY], n0.mMatrix[VX][VY], w); gBlendRotMat.mMatrix[VX][VZ] = lerp(n1.mMatrix[VX][VZ], n0.mMatrix[VX][VZ], w); gBlendRotMat.mMatrix[VY][VX] = lerp(n1.mMatrix[VY][VX], n0.mMatrix[VY][VX], w); gBlendRotMat.mMatrix[VY][VY] = lerp(n1.mMatrix[VY][VY], n0.mMatrix[VY][VY], w); gBlendRotMat.mMatrix[VY][VZ] = lerp(n1.mMatrix[VY][VZ], n0.mMatrix[VY][VZ], w); gBlendRotMat.mMatrix[VZ][VX] = lerp(n1.mMatrix[VZ][VX], n0.mMatrix[VZ][VX], w); gBlendRotMat.mMatrix[VZ][VY] = lerp(n1.mMatrix[VZ][VY], n0.mMatrix[VZ][VY], w); gBlendRotMat.mMatrix[VZ][VZ] = lerp(n1.mMatrix[VZ][VZ], n0.mMatrix[VZ][VZ], w); o_normals[bidx] = normals[index] * gBlendRotMat; } }
void LLParticlePartition::getGeometry(LLSpatialGroup* group) { LLFastTimer ftm(FTM_REBUILD_PARTICLE_GEOM); std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); U32 index_count = 0; U32 vertex_count = 0; group->clearDrawMap(); LLVertexBuffer* buffer = group->mVertexBuffer; LLStrider<U16> indicesp; LLStrider<LLVector4a> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> texcoordsp; LLStrider<LLColor4U> colorsp; LLStrider<LLColor4U> emissivep; buffer->getVertexStrider(verticesp); buffer->getNormalStrider(normalsp); buffer->getColorStrider(colorsp); buffer->getEmissiveStrider(emissivep); LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) { LLFace* facep = *i; LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); if (!facep->isState(LLFace::PARTICLE)) { //set the indices of this face S32 idx = LLVOPartGroup::findAvailableVBSlot(); if (idx >= 0) { facep->setGeomIndex(idx*4); facep->setIndicesIndex(idx*6); facep->setVertexBuffer(LLVOPartGroup::sVB); facep->setPoolType(LLDrawPool::POOL_ALPHA); facep->setState(LLFace::PARTICLE); } else { continue; //out of space in particle buffer } } S32 geom_idx = (S32) facep->getGeomIndex(); LLStrider<U16> cur_idx = indicesp + facep->getIndicesStart(); LLStrider<LLVector4a> cur_vert = verticesp + geom_idx; LLStrider<LLVector3> cur_norm = normalsp + geom_idx; LLStrider<LLVector2> cur_tc = texcoordsp + geom_idx; LLStrider<LLColor4U> cur_col = colorsp + geom_idx; LLStrider<LLColor4U> cur_glow = emissivep + geom_idx; LLColor4U* start_glow = cur_glow.get(); object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_glow, cur_idx); BOOL has_glow = FALSE; if (cur_glow.get() != start_glow) { has_glow = TRUE; } llassert(facep->getGeomCount() == 4); llassert(facep->getIndicesCount() == 6); vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); S32 idx = draw_vec.size()-1; BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); F32 vsize = facep->getVirtualSize(); bool batched = false; U32 bf_src = LLRender::BF_SOURCE_ALPHA; U32 bf_dst = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; object->getBlendFunc(facep->getTEOffset(), bf_src, bf_dst); if (idx >= 0) { LLDrawInfo* info = draw_vec[idx]; if (info->mTexture == facep->getTexture() && info->mHasGlow == has_glow && info->mFullbright == fullbright && info->mBlendFuncDst == bf_dst && info->mBlendFuncSrc == bf_src) { if (draw_vec[idx]->mEnd == facep->getGeomIndex()-1) { batched = true; info->mCount += facep->getIndicesCount(); info->mEnd += facep->getGeomCount(); info->mVSize = llmax(draw_vec[idx]->mVSize, vsize); } else if (draw_vec[idx]->mStart == facep->getGeomIndex()+facep->getGeomCount()+1) { batched = true; info->mCount += facep->getIndicesCount(); info->mStart -= facep->getGeomCount(); info->mOffset = facep->getIndicesStart(); info->mVSize = llmax(draw_vec[idx]->mVSize, vsize); } } } if (!batched) { U32 start = facep->getGeomIndex(); U32 end = start + facep->getGeomCount()-1; U32 offset = facep->getIndicesStart(); U32 count = facep->getIndicesCount(); LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), //facep->getTexture(), buffer, fullbright); const LLVector4a* bounds = group->getBounds(); info->mExtents[0] = bounds[0]; info->mExtents[1] = bounds[1]; info->mVSize = vsize; info->mBlendFuncDst = bf_dst; info->mBlendFuncSrc = bf_src; info->mHasGlow = has_glow; info->mParticle = TRUE; draw_vec.push_back(info); //for alpha sorting facep->setDrawInfo(info); } if(facep->getGeomCount() > 0) { buffer->validateRange(facep->getGeomIndex(), facep->getGeomIndex() + facep->getGeomCount() - 1, facep->getIndicesCount(), facep->getIndicesStart()); } } mFaceList.clear(); }
void LLParticlePartition::getGeometry(LLSpatialGroup* group) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); LLFastTimer ftm(mDrawableType == LLPipeline::RENDER_TYPE_GRASS ? LLFastTimer::FTM_REBUILD_GRASS_VB : LLFastTimer::FTM_REBUILD_PARTICLE_VB); std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); U32 index_count = 0; U32 vertex_count = 0; group->clearDrawMap(); LLVertexBuffer* buffer = group->mVertexBuffer; LLStrider<U16> indicesp; LLStrider<LLVector3> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> texcoordsp; LLStrider<LLColor4U> colorsp; buffer->getVertexStrider(verticesp); buffer->getNormalStrider(normalsp); buffer->getColorStrider(colorsp); buffer->getTexCoord0Strider(texcoordsp); buffer->getIndexStrider(indicesp); LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) { LLFace* facep = *i; LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); facep->setGeomIndex(vertex_count); facep->setIndicesIndex(index_count); facep->mVertexBuffer = buffer; facep->setPoolType(LLDrawPool::POOL_ALPHA); object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); S32 idx = draw_vec.size()-1; BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); F32 vsize = facep->getVirtualSize(); if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && draw_vec[idx]->mTexture == facep->getTexture() && (U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange && //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 && draw_vec[idx]->mFullbright == fullbright) { draw_vec[idx]->mCount += facep->getIndicesCount(); draw_vec[idx]->mEnd += facep->getGeomCount(); draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); } else { U32 start = facep->getGeomIndex(); U32 end = start + facep->getGeomCount()-1; U32 offset = facep->getIndicesStart(); U32 count = facep->getIndicesCount(); LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), buffer, fullbright); info->mExtents[0] = group->mObjectExtents[0]; info->mExtents[1] = group->mObjectExtents[1]; info->mVSize = vsize; draw_vec.push_back(info); //for alpha sorting facep->setDrawInfo(info); } } buffer->setBuffer(0); mFaceList.clear(); }
void LLDrawPoolTree::render(S32 pass) { LLFastTimer t(LLPipeline::sShadowRender ? FTM_SHADOW_TREE : FTM_RENDER_TREES); if (mDrawFace.empty()) { return; } LLGLState test(GL_ALPHA_TEST, LLGLSLShader::sNoFixedFunction ? 0 : 1); LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f); gGL.getTexUnit(sDiffTex)->bind(mTexturep); for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { LLFace *face = *iter; if(face->getViewerObject()) { LLVOTree* pTree = dynamic_cast<LLVOTree*>(face->getViewerObject()); if(pTree && !pTree->mDrawList.empty() ) { LLMatrix4a* model_matrix = &(face->getDrawable()->getRegion()->mRenderMatrix); gGL.loadMatrix(gGLModelView); gGL.multMatrix(*model_matrix); gPipeline.mMatrixOpCount++; for(std::vector<LLPointer<LLDrawInfo> >::iterator iter2 = pTree->mDrawList.begin(); iter2 != pTree->mDrawList.end(); iter2++) { LLDrawInfo& params = *iter2->get(); gGL.pushMatrix(); gGL.multMatrix(*params.mModelMatrix); gPipeline.mMatrixOpCount++; params.mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); gGL.popMatrix(); } continue; } } LLVertexBuffer* buff = face->getVertexBuffer(); if(buff) { LLMatrix4a* model_matrix = &(face->getDrawable()->getRegion()->mRenderMatrix); if(model_matrix && model_matrix->isIdentity()) { model_matrix = NULL; } if (model_matrix != gGLLastMatrix) { gGLLastMatrix = model_matrix; gGL.loadMatrix(gGLModelView); if (model_matrix) { llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); gGL.multMatrix(*model_matrix); } gPipeline.mMatrixOpCount++; } buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0); gPipeline.addTrianglesDrawn(buff->getNumIndices()); } } }
void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { if (avatar->isSelf() && !gAgent.needsRenderAvatar() || !gMeshRepo.meshRezEnabled()) { return; } stop_glerror(); for (U32 i = 0; i < mRiggedFace[type].size(); ++i) { LLFace* face = mRiggedFace[type][i]; LLDrawable* drawable = face->getDrawable(); if (!drawable) { continue; } LLVOVolume* vobj = drawable->getVOVolume(); if (!vobj) { continue; } LLVolume* volume = vobj->getVolume(); S32 te = face->getTEOffset(); if (!volume || volume->getNumVolumeFaces() <= te || !volume->isMeshAssetLoaded()) { continue; } LLUUID mesh_id = volume->getParams().getSculptID(); if (mesh_id.isNull()) { continue; } const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id, vobj); if (!skin) { continue; } stop_glerror(); const LLVolumeFace& vol_face = volume->getVolumeFace(te); updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face, vobj); stop_glerror(); U32 data_mask = LLFace::getRiggedDataMask(type); LLVertexBuffer* buff = face->getVertexBuffer(); if (buff) { if (sShaderLevel > 0) { //upload matrix palette to shader LLMatrix4 mat[64]; for (U32 i = 0; i < skin->mJointNames.size(); ++i) { LLJoint* joint = avatar->getJoint(skin->mJointNames[i]); if (joint) { mat[i] = skin->mInvBindMatrix[i]; mat[i] *= joint->getWorldMatrix(); } } stop_glerror(); LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette", skin->mJointNames.size(), FALSE, (GLfloat*) mat[0].mMatrix); stop_glerror(); } else { data_mask &= ~LLVertexBuffer::MAP_WEIGHT4; } buff->setBuffer(data_mask); U16 start = face->getGeomStart(); U16 end = start + face->getGeomCount()-1; S32 offset = face->getIndicesStart(); U32 count = face->getIndicesCount(); if (glow) { glColor4f(0,0,0,face->getTextureEntry()->getGlow()); } gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture()); if (normal_channel > -1) { LLDrawPoolBump::bindBumpMap(face, normal_channel); } if (face->mTextureMatrix) { glMatrixMode(GL_TEXTURE); glLoadMatrixf((F32*) face->mTextureMatrix->mMatrix); buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); } else { buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); } } } }
void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { if ((avatar->isSelf() && !gAgent.needsRenderAvatar()) || !gMeshRepo.meshRezEnabled()) { return; } stop_glerror(); for (U32 i = 0; i < mRiggedFace[type].size(); ++i) { LLFace* face = mRiggedFace[type][i]; LLDrawable* drawable = face->getDrawable(); if (!drawable) { continue; } LLVOVolume* vobj = drawable->getVOVolume(); if (!vobj) { continue; } LLVolume* volume = vobj->getVolume(); S32 te = face->getTEOffset(); if (!volume || volume->getNumVolumeFaces() <= te || !volume->isMeshAssetLoaded()) { continue; } LLUUID mesh_id = volume->getParams().getSculptID(); if (mesh_id.isNull()) { continue; } const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id, vobj); if (!skin) { continue; } //stop_glerror(); //const LLVolumeFace& vol_face = volume->getVolumeFace(te); //updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face); //stop_glerror(); U32 data_mask = LLFace::getRiggedDataMask(type); LLVertexBuffer* buff = face->getVertexBuffer(); if (buff) { if (sShaderLevel > 0) { //upload matrix palette to shader LLMatrix4 mat[JOINT_COUNT]; U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT); for (U32 i = 0; i < count; ++i) { LLJoint* joint = avatar->getJoint(skin->mJointNames[i]); if(!joint) { joint = avatar->getJoint("mRoot"); } if (joint) { LLMatrix4a tmp; tmp.loadu((F32*)skin->mInvBindMatrix[i].mMatrix); tmp.setMul(joint->getWorldMatrix(),tmp); mat[i] = LLMatrix4(tmp.getF32ptr()); } } stop_glerror(); F32 mp[JOINT_COUNT*12]; for (U32 i = 0; i < count; ++i) { F32* m = (F32*) mat[i].mMatrix; U32 idx = i*12; mp[idx+0] = m[0]; mp[idx+1] = m[1]; mp[idx+2] = m[2]; mp[idx+3] = m[12]; mp[idx+4] = m[4]; mp[idx+5] = m[5]; mp[idx+6] = m[6]; mp[idx+7] = m[13]; mp[idx+8] = m[8]; mp[idx+9] = m[9]; mp[idx+10] = m[10]; mp[idx+11] = m[14]; } LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, count, FALSE, (GLfloat*) mp); LLDrawPoolAvatar::sVertexProgram->uniform1f(LLShaderMgr::AVATAR_MAX_WEIGHT, F32(count-1)); stop_glerror(); } else { data_mask &= ~LLVertexBuffer::MAP_WEIGHT4; } U16 start = face->getGeomStart(); U16 end = start + face->getGeomCount()-1; S32 offset = face->getIndicesStart(); U32 count = face->getIndicesCount(); /*if (glow) { gGL.diffuseColor4f(0,0,0,face->getTextureEntry()->getGlow()); }*/ const LLTextureEntry* te = face->getTextureEntry(); LLMaterial* mat = te->getMaterialParams().get(); if (mat && is_deferred_render) { gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture(LLRender::DIFFUSE_MAP)); gGL.getTexUnit(normal_channel)->bind(face->getTexture(LLRender::NORMAL_MAP)); gGL.getTexUnit(specular_channel)->bind(face->getTexture(LLRender::SPECULAR_MAP)); LLColor4 col = mat->getSpecularLightColor(); F32 spec = llmax(0.0001f, mat->getSpecularLightExponent() / 255.f); F32 env = mat->getEnvironmentIntensity()/255.f; if (mat->getSpecularID().isNull()) { env = te->getShiny()*0.25f; col.set(env,env,env,0); spec = env; } BOOL fullbright = te->getFullbright(); sVertexProgram->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, fullbright ? 1.f : 0.f); sVertexProgram->uniform4f(LLShaderMgr::SPECULAR_COLOR, col.mV[0], col.mV[1], col.mV[2], spec); sVertexProgram->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env); if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) { sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff()/255.f); } else { sVertexProgram->setMinimumAlpha(0.004f); } for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) { LLViewerTexture* tex = face->getTexture(i); if (tex) { tex->addTextureStats(avatar->getPixelArea()); } } } else { gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture()); if(sVertexProgram) { if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) { sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff()/255.f); } else { sVertexProgram->setMinimumAlpha(0.004f); } } if (normal_channel > -1) { LLDrawPoolBump::bindBumpMap(face, normal_channel); } } if (face->mTextureMatrix && vobj->mTexAnimMode) { gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadMatrix(*face->mTextureMatrix); buff->setBuffer(data_mask); buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); gGL.loadIdentity(); gGL.matrixMode(LLRender::MM_MODELVIEW); } else { buff->setBuffer(data_mask); buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); } gPipeline.addTrianglesDrawn(count, LLRender::TRIANGLES); } } }
void LLVOTree::updateMesh() { LLMatrix4 matrix; // Translate to tree base HACK - adjustment in Z plants tree underground const LLVector3 &pos_agent = getPositionAgent(); //gGL.translatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); LLMatrix4 trans_mat; trans_mat.setTranslation(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); trans_mat *= matrix; // Rotate to tree position and bend for current trunk/wind // Note that trunk stiffness controls the amount of bend at the trunk as // opposed to the crown of the tree // const F32 TRUNK_STIFF = 22.f; LLQuaternion rot = LLQuaternion(mTrunkBend.magVec()*TRUNK_STIFF*DEG_TO_RAD, LLVector4(mTrunkBend.mV[VX], mTrunkBend.mV[VY], 0)) * LLQuaternion(90.f*DEG_TO_RAD, LLVector4(0,0,1)) * getRotation(); LLMatrix4 rot_mat(rot); rot_mat *= trans_mat; F32 radius = getScale().magVec()*0.05f; LLMatrix4 scale_mat; scale_mat.mMatrix[0][0] = scale_mat.mMatrix[1][1] = scale_mat.mMatrix[2][2] = radius; scale_mat *= rot_mat; // const F32 THRESH_ANGLE_FOR_BILLBOARD = 15.f; // const F32 BLEND_RANGE_FOR_BILLBOARD = 3.f; F32 droop = mDroop + 25.f*(1.f - mTrunkBend.magVec()); S32 stop_depth = 0; F32 alpha = 1.0; U32 vert_count = 0; U32 index_count = 0; calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches); LLFace* facep = mDrawable->getFace(0); LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); buff->allocateBuffer(vert_count, index_count, TRUE); facep->setVertexBuffer(buff); LLStrider<LLVector3> vertices; LLStrider<LLVector3> normals; LLStrider<LLVector2> tex_coords; LLStrider<U16> indices; U16 idx_offset = 0; buff->getVertexStrider(vertices); buff->getNormalStrider(normals); buff->getTexCoord0Strider(tex_coords); buff->getIndexStrider(indices); genBranchPipeline(vertices, normals, tex_coords, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha); mReferenceBuffer->flush(); buff->flush(); }
//-------------------------------------------------------------------- // LLViewerJointMesh::drawShape() //-------------------------------------------------------------------- U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) { if (!mValid || !mMesh || !mFace || !mVisible || !mFace->getVertexBuffer() || mMesh->getNumFaces() == 0 || (LLGLSLShader::sNoFixedFunction && LLGLSLShader::sCurBoundShaderPtr == NULL)) { return 0; } U32 triangle_count = 0; S32 diffuse_channel = LLDrawPoolAvatar::sDiffuseChannel; stop_glerror(); //---------------------------------------------------------------- // setup current color //---------------------------------------------------------------- if (is_dummy) gGL.diffuseColor4fv(LLVOAvatar::getDummyColor().mV); else gGL.diffuseColor4fv(mColor.mV); stop_glerror(); LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), (mFace->getPool()->getVertexShaderLevel() > 0 || LLGLSLShader::sNoFixedFunction) ? 0.f : mShiny); //---------------------------------------------------------------- // setup current texture //---------------------------------------------------------------- llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive LLTexUnit::eTextureAddressMode old_mode = LLTexUnit::TAM_WRAP; LLViewerTexLayerSet *layerset = dynamic_cast<LLViewerTexLayerSet*>(mLayerSet); if (mTestImageName) { gGL.getTexUnit(diffuse_channel)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName); if (mIsTransparent) { gGL.diffuseColor4f(1.f, 1.f, 1.f, 1.f); } else { gGL.diffuseColor4f(0.7f, 0.6f, 0.3f, 1.f); gGL.getTexUnit(diffuse_channel)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); } } else if( !is_dummy && layerset ) { if( layerset->hasComposite() ) { gGL.getTexUnit(diffuse_channel)->bind(layerset->getViewerComposite()); } else { // This warning will always trigger if you've hacked the avatar to show as incomplete. // Ignore the warning if that's the case. static const LLCachedControl<bool> render_unloaded_avatar("RenderUnloadedAvatar", false); if (!render_unloaded_avatar) { llwarns << "Layerset without composite" << llendl; } gGL.getTexUnit(diffuse_channel)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); } } else if ( !is_dummy && mTexture.notNull() ) { if(mTexture->hasGLTexture()) { old_mode = mTexture->getAddressMode(); } gGL.getTexUnit(diffuse_channel)->bind(mTexture); gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } else { gGL.getTexUnit(diffuse_channel)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); } U32 mask = sRenderMask; U32 start = mMesh->mFaceVertexOffset; U32 end = start + mMesh->mFaceVertexCount - 1; U32 count = mMesh->mFaceIndexCount; U32 offset = mMesh->mFaceIndexOffset; LLVertexBuffer* buff = mFace->getVertexBuffer(); if (mMesh->hasWeights()) { if ((mFace->getPool()->getVertexShaderLevel() > 0)) { if (first_pass) { uploadJointMatrices(); } mask = mask | LLVertexBuffer::MAP_WEIGHT; if (mFace->getPool()->getVertexShaderLevel() > 1) { mask = mask | LLVertexBuffer::MAP_CLOTHWEIGHT; } } buff->setBuffer(mask); buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); } else { gGL.pushMatrix(); LLMatrix4 jointToWorld = getWorldMatrix(); gGL.multMatrix((GLfloat*)jointToWorld.mMatrix); buff->setBuffer(mask); buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); gGL.popMatrix(); } gPipeline.addTrianglesDrawn(count); triangle_count += count; if (mTestImageName) { gGL.getTexUnit(diffuse_channel)->setTextureBlendType(LLTexUnit::TB_MULT); } if (mTexture.notNull() && !is_dummy) { gGL.getTexUnit(diffuse_channel)->bind(mTexture); gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(old_mode); } return triangle_count; }
void LLParticlePartition::getGeometry(LLSpatialGroup* group) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); LLFastTimer ftm(FTM_REBUILD_PARTICLE_GEOM); std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); U32 index_count = 0; U32 vertex_count = 0; group->clearDrawMap(); LLVertexBuffer* buffer = group->mVertexBuffer; LLStrider<U16> indicesp; LLStrider<LLVector4a> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> texcoordsp; LLStrider<LLColor4U> colorsp; buffer->getVertexStrider(verticesp); buffer->getNormalStrider(normalsp); buffer->getColorStrider(colorsp); LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) { LLFace* facep = *i; LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); if (!facep->isState(LLFace::PARTICLE)) { //set the indices of this face S32 idx = LLVOPartGroup::findAvailableVBSlot(); if (idx >= 0) { facep->setGeomIndex(idx*4); facep->setIndicesIndex(idx*6); facep->setVertexBuffer(LLVOPartGroup::sVB); facep->setPoolType(LLDrawPool::POOL_ALPHA); facep->setState(LLFace::PARTICLE); } else { continue; //out of space in particle buffer } } S32 geom_idx = (S32) facep->getGeomIndex(); LLStrider<U16> cur_idx = indicesp + facep->getIndicesStart(); LLStrider<LLVector4a> cur_vert = verticesp + geom_idx; LLStrider<LLVector3> cur_norm = normalsp + geom_idx; LLStrider<LLVector2> cur_tc = texcoordsp + geom_idx; LLStrider<LLColor4U> cur_col = colorsp + geom_idx; object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_idx); llassert(facep->getGeomCount() == 4); llassert(facep->getIndicesCount() == 6); vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); S32 idx = draw_vec.size()-1; BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); F32 vsize = facep->getVirtualSize(); bool batched = false; if (idx >= 0 && draw_vec[idx]->mTexture == facep->getTexture() && draw_vec[idx]->mFullbright == fullbright) { if (draw_vec[idx]->mEnd == facep->getGeomIndex()-1) { batched = true; draw_vec[idx]->mCount += facep->getIndicesCount(); draw_vec[idx]->mEnd += facep->getGeomCount(); draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); } else if (draw_vec[idx]->mStart == facep->getGeomIndex()+facep->getGeomCount()+1) { batched = true; draw_vec[idx]->mCount += facep->getIndicesCount(); draw_vec[idx]->mStart -= facep->getGeomCount(); draw_vec[idx]->mOffset = facep->getIndicesStart(); draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); } } if (!batched) { U32 start = facep->getGeomIndex(); U32 end = start + facep->getGeomCount()-1; U32 offset = facep->getIndicesStart(); U32 count = facep->getIndicesCount(); LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), //facep->getTexture(), buffer, fullbright); info->mExtents[0] = group->mObjectExtents[0]; info->mExtents[1] = group->mObjectExtents[1]; info->mVSize = vsize; draw_vec.push_back(info); //for alpha sorting facep->setDrawInfo(info); } } mFaceList.clear(); }
BOOL LLVOWater::updateGeometry(LLDrawable *drawable) { LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WATER); LLFace *face; if (drawable->getNumFaces() < 1) { LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER); drawable->addFace(poolp, NULL); } face = drawable->getFace(0); // LLVector2 uvs[4]; // LLVector3 vtx[4]; LLStrider<LLVector3> verticesp, normalsp; LLStrider<LLVector2> texCoordsp; LLStrider<U16> indicesp; U16 index_offset; // A quad is 4 vertices and 6 indices (making 2 triangles) static const unsigned int vertices_per_quad = 4; static const unsigned int indices_per_quad = 6; static const LLCachedControl<bool> render_transparent_water("RenderTransparentWater",false); const S32 size = (render_transparent_water && !LLGLSLShader::sNoFixedFunction) ? 16 : 1; const S32 num_quads = size * size; face->setSize(vertices_per_quad * num_quads, indices_per_quad * num_quads); LLVertexBuffer* buff = face->getVertexBuffer(); if (!buff) { buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB); buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); face->setIndicesIndex(0); face->setGeomIndex(0); face->setVertexBuffer(buff); } else { buff->resizeBuffer(face->getGeomCount(), face->getIndicesCount()); } index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); LLVector3 position_agent; position_agent = getPositionAgent(); face->mCenterAgent = position_agent; face->mCenterLocal = position_agent; S32 x, y; F32 step_x = getScale().mV[0] / size; F32 step_y = getScale().mV[1] / size; const LLVector3 up(0.f, step_y * 0.5f, 0.f); const LLVector3 right(step_x * 0.5f, 0.f, 0.f); const LLVector3 normal(0.f, 0.f, 1.f); F32 size_inv = 1.f / size; for (y = 0; y < size; y++) { for (x = 0; x < size; x++) { S32 toffset = index_offset + 4*(y*size + x); position_agent = getPositionAgent() - getScale() * 0.5f; position_agent.mV[VX] += (x + 0.5f) * step_x; position_agent.mV[VY] += (y + 0.5f) * step_y; *verticesp++ = position_agent - right + up; *verticesp++ = position_agent - right - up; *verticesp++ = position_agent + right + up; *verticesp++ = position_agent + right - up; *texCoordsp++ = LLVector2(x*size_inv, (y+1)*size_inv); *texCoordsp++ = LLVector2(x*size_inv, y*size_inv); *texCoordsp++ = LLVector2((x+1)*size_inv, (y+1)*size_inv); *texCoordsp++ = LLVector2((x+1)*size_inv, y*size_inv); *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; *indicesp++ = toffset + 0; *indicesp++ = toffset + 1; *indicesp++ = toffset + 2; *indicesp++ = toffset + 1; *indicesp++ = toffset + 3; *indicesp++ = toffset + 2; } } buff->flush(); mDrawable->movePartition(); LLPipeline::sCompiles++; return TRUE; }
void LLSprite::updateFace(LLFace &face) { LLViewerCamera &camera = *LLViewerCamera::getInstance(); // First, figure out how many vertices/indices we need. U32 num_vertices, num_indices; U32 vertex_count = 0; // Get the total number of vertices and indices if (mFollow) { num_vertices = 4; num_indices = 6; } else { num_vertices = 4; num_indices = 12; } face.setSize(num_vertices, num_indices); if (mFollow) { sCameraUp = camera.getUpAxis(); sCameraRight = -camera.getLeftAxis(); sCameraPosition = camera.getOrigin(); sNormal = -camera.getAtAxis(); if (mUseCameraUp) { // these need to live here because the height/width may change between render calls mScaledUp = sCameraUp; mScaledRight = sCameraRight; mScaledUp *= mHeightDiv2; mScaledRight *= mWidthDiv2; mA = mPosition + mScaledRight + mScaledUp; mB = mPosition - mScaledRight + mScaledUp; mC = mPosition - mScaledRight - mScaledUp; mD = mPosition + mScaledRight - mScaledUp; } else { // The up vector is perpendicular to the camera vector... LLVector3 camera_vec = mPosition - sCameraPosition; mScaledRight = camera_vec % LLVector3(0.f, 0.f, 1.f); mScaledUp = -(camera_vec % mScaledRight); mScaledUp.normalize(); mScaledRight.normalize(); mScaledUp *= mHeightDiv2; mScaledRight *= mWidthDiv2; mA = mPosition + mScaledRight + mScaledUp; mB = mPosition - mScaledRight + mScaledUp; mC = mPosition - mScaledRight - mScaledUp; mD = mPosition + mScaledRight - mScaledUp; } } else { // this is equivalent to how it was done before. . . // we need to establish a way to // identify the orientation of a particular sprite rather than // just banging it in on the x,z plane if it's not following the camera. LLVector3 x_axis; LLVector3 y_axis; F32 dot = sNormal * LLVector3(0.f, 1.f, 0.f); if (dot == 1.f || dot == -1.f) { x_axis.setVec(1.f, 0.f, 0.f); y_axis.setVec(0.f, 1.f, 0.f); } else { x_axis = sNormal % LLVector3(0.f, -1.f, 0.f); x_axis.normalize(); y_axis = sNormal % x_axis; } LLQuaternion yaw_rot(mYaw, sNormal); // rotate axes by specified yaw x_axis = x_axis * yaw_rot; y_axis = y_axis * yaw_rot; // rescale axes by width and height of sprite x_axis = x_axis * mWidthDiv2; y_axis = y_axis * mHeightDiv2; mA = -x_axis + y_axis; mB = x_axis + y_axis; mC = x_axis - y_axis; mD = -x_axis - y_axis; mA += mPosition; mB += mPosition; mC += mPosition; mD += mPosition; } face.setFaceColor(mColor); LLStrider<LLVector3> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> tex_coordsp; LLStrider<U16> indicesp; U16 index_offset; // Setup face if (!face.getVertexBuffer()) { LLVertexBuffer* buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, GL_STREAM_DRAW_ARB); buff->allocateBuffer(4, 12, TRUE); face.setGeomIndex(0); face.setIndicesIndex(0); face.setVertexBuffer(buff); } index_offset = face.getGeometry(verticesp,normalsp,tex_coordsp, indicesp); *tex_coordsp = LLVector2(0.f, 0.f); *verticesp = mC; tex_coordsp++; verticesp++; vertex_count++; *tex_coordsp = LLVector2(0.f, 1.f); *verticesp = mB; tex_coordsp++; verticesp++; vertex_count++; *tex_coordsp = LLVector2(1.f, 1.f); *verticesp = mA; tex_coordsp++; verticesp++; vertex_count++; *tex_coordsp = LLVector2(1.f, 0.0f); *verticesp = mD; tex_coordsp++; verticesp++; vertex_count++; // Generate indices, since they're easy. // Just a series of quads. *indicesp++ = index_offset; *indicesp++ = 2 + index_offset; *indicesp++ = 1 + index_offset; *indicesp++ = index_offset; *indicesp++ = 3 + index_offset; *indicesp++ = 2 + index_offset; if (!mFollow) { *indicesp++ = 0 + index_offset; *indicesp++ = 1 + index_offset; *indicesp++ = 2 + index_offset; *indicesp++ = 0 + index_offset; *indicesp++ = 2 + index_offset; *indicesp++ = 3 + index_offset; } face.getVertexBuffer()->setBuffer(0); face.mCenterAgent = mPosition; }
BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) { LLFastTimer ftm(FTM_GEO_SKY); LLStrider<LLVector3> vertices; LLStrider<LLVector2> texCoords; LLStrider<U16> indices; #if DOME_SLICES { mFanVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); mFanVerts->allocateBuffer(getFanNumVerts(), getFanNumIndices(), TRUE); BOOL success = mFanVerts->getVertexStrider(vertices) && mFanVerts->getTexCoord0Strider(texCoords) && mFanVerts->getIndexStrider(indices); if(!success) { llerrs << "Failed updating WindLight sky geometry." << llendl; } buildFanBuffer(vertices, texCoords, indices); mFanVerts->flush(); } { const U32 max_buffer_bytes = gSavedSettings.getS32("RenderMaxVBOSize")*1024; const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK; const U32 max_verts = max_buffer_bytes / LLVertexBuffer::calcVertexSize(data_mask); const U32 total_stacks = getNumStacks(); const U32 verts_per_stack = getNumSlices(); // each seg has to have one more row of verts than it has stacks // then round down const U32 stacks_per_seg = (max_verts - verts_per_stack) / verts_per_stack; // round up to a whole number of segments const U32 strips_segments = (total_stacks+stacks_per_seg-1) / stacks_per_seg; llinfos << "WL Skydome strips in " << strips_segments << " batches." << llendl; mStripsVerts.resize(strips_segments, NULL); LLTimer timer; timer.start(); for (U32 i = 0; i < strips_segments ;++i) { LLVertexBuffer * segment = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); mStripsVerts[i] = segment; U32 num_stacks_this_seg = stacks_per_seg; if ((i == strips_segments - 1) && (total_stacks % stacks_per_seg) != 0) { // for the last buffer only allocate what we'll use num_stacks_this_seg = total_stacks % stacks_per_seg; } // figure out what range of the sky we're filling const U32 begin_stack = i * stacks_per_seg; const U32 end_stack = begin_stack + num_stacks_this_seg; llassert(end_stack <= total_stacks); const U32 num_verts_this_seg = verts_per_stack * (num_stacks_this_seg+1); llassert(num_verts_this_seg <= max_verts); const U32 num_indices_this_seg = 1+num_stacks_this_seg*(2+2*verts_per_stack); llassert(num_indices_this_seg * sizeof(U16) <= max_buffer_bytes); segment->allocateBuffer(num_verts_this_seg, num_indices_this_seg, TRUE); // lock the buffer BOOL success = segment->getVertexStrider(vertices) && segment->getTexCoord0Strider(texCoords) && segment->getIndexStrider(indices); if(!success) { llerrs << "Failed updating WindLight sky geometry." << llendl; } // fill it buildStripsBuffer(begin_stack, end_stack, vertices, texCoords, indices); // and unlock the buffer segment->flush(); } llinfos << "completed in " << llformat("%.2f", timer.getElapsedTimeF32()) << "seconds" << llendl; } #else mStripsVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); const F32 RADIUS = LLWLParamManager::sParamMgr->getDomeRadius(); LLPointer<LLVertexBuffer> temp = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0); temp->allocateBuffer(12, 60, TRUE); BOOL success = temp->getVertexStrider(vertices) && temp->getIndexStrider(indices); if (success) { for (U32 i = 0; i < 12; i++) { *vertices++ = icosahedron_vert[i]; } for (U32 i = 0; i < 60; i++) { *indices++ = icosahedron_ind[i]; } } LLPointer<LLVertexBuffer> temp2; for (U32 i = 0; i < 8; i++) { temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0); subdivide(*temp, temp2); temp = temp2; } temp->getVertexStrider(vertices); for (S32 i = 0; i < temp->getNumVerts(); i++) { LLVector3 v = vertices[i]; v.normVec(); vertices[i] = v*RADIUS; } temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0); chop(*temp, temp2); mStripsVerts->allocateBuffer(temp2->getNumVerts(), temp2->getNumIndices(), TRUE); success = mStripsVerts->getVertexStrider(vertices) && mStripsVerts->getTexCoordStrider(texCoords) && mStripsVerts->getIndexStrider(indices); LLStrider<LLVector3> v; temp2->getVertexStrider(v); LLStrider<U16> ind; temp2->getIndexStrider(ind); if (success) { for (S32 i = 0; i < temp2->getNumVerts(); ++i) { LLVector3 vert = *v++; vert.normVec(); F32 z0 = vert.mV[2]; F32 x0 = vert.mV[0]; vert *= RADIUS; *vertices++ = vert; *texCoords++ = LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f); } for (S32 i = 0; i < temp2->getNumIndices(); ++i) { *indices++ = *ind++; } } mStripsVerts->flush(); #endif updateStarColors(); updateStarGeometry(drawable); LLPipeline::sCompiles++; return TRUE; }
BOOL LLVOGround::updateGeometry(LLDrawable *drawable) { LLStrider<LLVector3> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> texCoordsp; LLStrider<U16> indicesp; S32 index_offset; LLFace *face; LLDrawPoolGround *poolp = (LLDrawPoolGround*) gPipeline.getPool(LLDrawPool::POOL_GROUND); if (drawable->getNumFaces() < 1) drawable->addFace(poolp, NULL); face = drawable->getFace(0); if (!face->getVertexBuffer()) { face->setSize(5, 12); LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolGround::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); face->setGeomIndex(0); face->setIndicesIndex(0); face->setVertexBuffer(buff); } index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); if (-1 == index_offset) { return TRUE; } /////////////////////////////////////// // // // LLVector3 at_dir = LLViewerCamera::getInstance()->getAtAxis(); at_dir.mV[VZ] = 0.f; if (at_dir.normVec() < 0.01) { // We really don't care, as we're not looking anywhere near the horizon. } LLVector3 left_dir = LLViewerCamera::getInstance()->getLeftAxis(); left_dir.mV[VZ] = 0.f; left_dir.normVec(); // Our center top point LLColor4 ground_color = gSky.getFogColor(); ground_color.mV[3] = 1.f; face->setFaceColor(ground_color); *(verticesp++) = LLVector3(64, 64, 0); *(verticesp++) = LLVector3(-64, 64, 0); *(verticesp++) = LLVector3(-64, -64, 0); *(verticesp++) = LLVector3(64, -64, 0); *(verticesp++) = LLVector3(0, 0, -1024); // Triangles for each side *indicesp++ = index_offset + 0; *indicesp++ = index_offset + 1; *indicesp++ = index_offset + 4; *indicesp++ = index_offset + 1; *indicesp++ = index_offset + 2; *indicesp++ = index_offset + 4; *indicesp++ = index_offset + 2; *indicesp++ = index_offset + 3; *indicesp++ = index_offset + 4; *indicesp++ = index_offset + 3; *indicesp++ = index_offset + 0; *indicesp++ = index_offset + 4; *(texCoordsp++) = LLVector2(0.f, 0.f); *(texCoordsp++) = LLVector2(1.f, 0.f); *(texCoordsp++) = LLVector2(1.f, 1.f); *(texCoordsp++) = LLVector2(0.f, 1.f); *(texCoordsp++) = LLVector2(0.5f, 0.5f); face->getVertexBuffer()->flush(); LLPipeline::sCompiles++; return TRUE; }