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 void LLViewerJointMesh::updateGeometryOriginal(LLFace *mFace, LLPolyMesh *mMesh) { 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* __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->setBuffer(0); }
// 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 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()); } } }
// static void LLViewerJointMesh::updateGeometrySSE(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->getVertexBuffer(); buffer->getVertexStrider(o_vertices, mesh->mFaceVertexOffset); buffer->getNormalStrider(o_normals, mesh->mFaceVertexOffset); const F32* weights = mesh->getWeights(); const LLVector3* coords = (const LLVector3*)mesh->getCoords(); const LLVector3* normals = (const LLVector3*)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 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); } }
//-------------------------------------------------------------------- // 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(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 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); } } }
BOOL LLVOWater::updateGeometry(LLDrawable *drawable) { LLFastTimer ftm(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; const S32 size = gSavedSettings.getBOOL("RenderTransparentWater") ? 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->setBuffer(0); mDrawable->movePartition(); LLPipeline::sCompiles++; return TRUE; }
BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) { LLFastTimer ftm(LLFastTimer::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->setBuffer(0); } { 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); 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->setBuffer(0); } } #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->setBuffer(0); #endif updateStarColors(); updateStarGeometry(drawable); LLPipeline::sCompiles++; return TRUE; }
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()); } } }
// static void LLViewerJointMesh::updateGeometryOriginal(LLFace *mFace, LLPolyMesh *mMesh) { 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 = gJointMatUnaligned[joint+1]; o_vertices[bidx] = coords[index] * gBlendMat; gBlendRotMat = gJointRotUnaligned[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 = gJointMatUnaligned[joint+1]; LLMatrix4 &m1 = gJointMatUnaligned[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 = gJointRotUnaligned[joint+1]; LLMatrix3 &n1 = gJointRotUnaligned[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; } buffer->setBuffer(0); }