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; } }
//-------------------------------------------------------------------- // LLViewerJointMesh::drawShape() //-------------------------------------------------------------------- U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass) { if (!mValid || !mMesh || !mFace || !mVisible || mFace->mVertexBuffer.isNull() || mMesh->getNumFaces() == 0) { return 0; } U32 triangle_count = 0; stop_glerror(); //---------------------------------------------------------------- // setup current color //---------------------------------------------------------------- if (!gRenderForSelect) { if ((mFace->getPool()->getVertexShaderLevel() > 0)) { glColor4f(0,0,0,1); if (gMaterialIndex > 0) { glVertexAttrib4fvARB(gMaterialIndex, mColor.mV); } if (mShiny && gSpecularIndex > 0) { glVertexAttrib4fARB(gSpecularIndex, 1,1,1,1); } } else { glColor4fv(mColor.mV); } } stop_glerror(); LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), gRenderForSelect ? 0.0f : mShiny && !(mFace->getPool()->getVertexShaderLevel() > 0)); LLGLEnable texture_2d((gRenderForSelect && isTransparent()) ? GL_TEXTURE_2D : 0); //---------------------------------------------------------------- // setup current texture //---------------------------------------------------------------- llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive if (mTestImageName) { LLImageGL::bindExternalTexture( mTestImageName, 0, GL_TEXTURE_2D ); if (mIsTransparent) { glColor4f(1.f, 1.f, 1.f, 1.f); } else { glColor4f(0.7f, 0.6f, 0.3f, 1.f); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA); } } else if( mLayerSet ) { if( mLayerSet->hasComposite() ) { mLayerSet->getComposite()->bindTexture(); } else { llwarns << "Layerset without composite" << llendl; gImageList.getImage(IMG_DEFAULT)->bind(); } } else if ( mTexture.notNull() ) { mTexture->bind(); if (!mTexture->getClampS()) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); } if (!mTexture->getClampT()) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } } else { gImageList.getImage(IMG_DEFAULT_AVATAR)->bind(); } LLGLDisable tex(gRenderForSelect && !isTransparent() ? GL_TEXTURE_2D : 0); if (gRenderForSelect) { if (isTransparent()) { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); // GL_TEXTURE_ENV_COLOR is set in renderPass1 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); } } else { //---------------------------------------------------------------- // by default, backface culling is enabled //---------------------------------------------------------------- /*if (sRenderPass == AVATAR_RENDER_PASS_CLOTHING_INNER) { LLImageGL::bindExternalTexture( sClothingMaskImageName, 1, GL_TEXTURE_2D ); glClientActiveTextureARB(GL_TEXTURE0_ARB); glActiveTextureARB(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); glClientActiveTextureARB(GL_TEXTURE1_ARB); glEnable(GL_TEXTURE_2D); // Texture unit 1 glActiveTextureARB(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, sClothingInnerColor.mV); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_CONSTANT_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA); } else if (sRenderPass == AVATAR_RENDER_PASS_CLOTHING_OUTER) { glAlphaFunc(GL_GREATER, 0.1f); LLImageGL::bindExternalTexture( sClothingMaskImageName, 1, GL_TEXTURE_2D ); glClientActiveTextureARB(GL_TEXTURE0_ARB); glActiveTextureARB(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); glClientActiveTextureARB(GL_TEXTURE1_ARB); glEnable(GL_TEXTURE_2D); // Texture unit 1 glActiveTextureARB(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); }*/ } mFace->mVertexBuffer->setBuffer(sRenderMask); U32 start = mMesh->mFaceVertexOffset; U32 end = start + mMesh->mFaceVertexCount - 1; U32 count = mMesh->mFaceIndexCount; U32* indicesp = ((U32*) mFace->mVertexBuffer->getIndicesPointer()) + mMesh->mFaceIndexOffset; if (mMesh->hasWeights()) { if ((mFace->getPool()->getVertexShaderLevel() > 0)) { if (first_pass) { uploadJointMatrices(); } llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_INT, indicesp); } else { llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_INT, indicesp); } } else { glPushMatrix(); LLMatrix4 jointToWorld = getWorldMatrix(); glMultMatrixf((GLfloat*)jointToWorld.mMatrix); llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_INT, indicesp); glPopMatrix(); } triangle_count += mMesh->mFaceIndexCount; if (mTestImageName) { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } /*if (sRenderPass != AVATAR_RENDER_PASS_SINGLE) { LLImageGL::unbindTexture(1, GL_TEXTURE_2D); glActiveTextureARB(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); // Return to the default texture. LLImageGL::unbindTexture(0, GL_TEXTURE_2D); glClientActiveTextureARB(GL_TEXTURE0_ARB); glActiveTextureARB(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glAlphaFunc(GL_GREATER, 0.01f); }*/ if (mTexture.notNull()) { if (!mTexture->getClampS()) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); } if (!mTexture->getClampT()) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } } return triangle_count; }
void LLViewerJointMesh::updateJointGeometry() { if (!(mValid && mMesh && mFace && mMesh->hasWeights() && mFace->mVertexBuffer.notNull() && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) == 0)) { return; } if (!sVectorizePerfTest) { // Once we've measured performance, just run the specified // code version. if(sUpdateGeometryFunc == updateGeometryOriginal) uploadJointMatrices(); sUpdateGeometryFunc(mFace, mMesh); } else { // At startup, measure the amount of time in skinning and choose // the fastest one. LLTimer ug_timer ; if (sUpdateGeometryCallPointer) { if(sUpdateGeometryFunc == updateGeometryOriginal) uploadJointMatrices(); // call accelerated version for this processor sUpdateGeometryFunc(mFace, mMesh); } else { uploadJointMatrices(); updateGeometryOriginal(mFace, mMesh); } sUpdateGeometryElapsedTime += ug_timer.getElapsedTimeF64(); ++sUpdateGeometryCalls; if(0 != (sUpdateGeometryCalls & UPDATE_GEOMETRY_CALL_OVERFLOW)) { F64 time_since_app_start = ug_timer.getElapsedSeconds(); if(sUpdateGeometryGlobalTime == 0.0 || sUpdateGeometryLastProcessor != sVectorizeProcessor) { sUpdateGeometryGlobalTime = time_since_app_start; sUpdateGeometryElapsedTime = 0; sUpdateGeometryCalls = 0; sUpdateGeometryRunCount = 0; sUpdateGeometryLastProcessor = sVectorizeProcessor; sUpdateGeometryCallPointer = false; return; } F64 percent_time_in_function = ( sUpdateGeometryElapsedTime * 100.0 ) / ( time_since_app_start - sUpdateGeometryGlobalTime ) ; sUpdateGeometryGlobalTime = time_since_app_start; if (!sUpdateGeometryCallPointer) { // First set of run data is with vectorization off. sUpdateGeometryCallPointer = true; llinfos << "profile (avg of " << sUpdateGeometryCalls << " samples) = " << "vectorize off " << percent_time_in_function << "% of time with " << (sUpdateGeometryElapsedTime / (F64)sUpdateGeometryCalls) << " seconds per call " << llendl; sUpdateGeometryRunAvgOff[sUpdateGeometryRunCount] = percent_time_in_function; sUpdateGeometryElapsedTimeOff += sUpdateGeometryElapsedTime; sUpdateGeometryCalls = 0; } else { // Second set of run data is with vectorization on. sUpdateGeometryCallPointer = false; llinfos << "profile (avg of " << sUpdateGeometryCalls << " samples) = " << "VEC on " << percent_time_in_function << "% of time with " << (sUpdateGeometryElapsedTime / (F64)sUpdateGeometryCalls) << " seconds per call " << llendl; sUpdateGeometryRunAvgOn[sUpdateGeometryRunCount] = percent_time_in_function ; sUpdateGeometryElapsedTimeOn += sUpdateGeometryElapsedTime; sUpdateGeometryCalls = 0; sUpdateGeometryRunCount++; F64 a = 0.0, b = 0.0; for(U32 i = 0; i<sUpdateGeometryRunCount; i++) { a += sUpdateGeometryRunAvgOff[i]; b += sUpdateGeometryRunAvgOn[i]; } a /= sUpdateGeometryRunCount; b /= sUpdateGeometryRunCount; F64 perf_boost = ( sUpdateGeometryElapsedTimeOff - sUpdateGeometryElapsedTimeOn ) / sUpdateGeometryElapsedTimeOn; llinfos << "run averages (" << (F64)sUpdateGeometryRunCount << "/10) vectorize off " << a << "% : vectorize type " << sVectorizeProcessor << " " << b << "% : performance boost " << perf_boost * 100.0 << "%" << llendl ; if(sUpdateGeometryRunCount == 10) { // In case user runs test again, force reset of data on // next run. sUpdateGeometryGlobalTime = 0.0; // We have data now on which version is faster. Switch to that // code and save the data for next run. gSavedSettings.setBOOL("VectorizePerfTest", FALSE); if (perf_boost > 0.0) { llinfos << "Vectorization improves avatar skinning performance, " << "keeping on for future runs." << llendl; gSavedSettings.setBOOL("VectorizeSkin", TRUE); } else { // SIMD decreases performance, fall back to original code llinfos << "Vectorization decreases avatar skinning performance, " << "switching back to original code." << llendl; gSavedSettings.setBOOL("VectorizeSkin", FALSE); } } } sUpdateGeometryElapsedTime = 0.0f; } } }
//-------------------------------------------------------------------- // LLViewerJointMesh::drawShape() //-------------------------------------------------------------------- U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) { if (!mValid || !mMesh || !mFace || !mVisible || mFace->mVertexBuffer.isNull() || mMesh->getNumFaces() == 0) { return 0; } U32 triangle_count = 0; stop_glerror(); //---------------------------------------------------------------- // setup current color //---------------------------------------------------------------- if (!gRenderForSelect) { if (is_dummy) glColor4fv(LLVOAvatar::getDummyColor().mV); else glColor4fv(mColor.mV); } stop_glerror(); LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), gRenderForSelect ? 0.0f : mShiny && !(mFace->getPool()->getVertexShaderLevel() > 0)); //---------------------------------------------------------------- // setup current texture //---------------------------------------------------------------- llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive LLTexUnit::eTextureAddressMode old_mode = LLTexUnit::TAM_WRAP; if (mTestImageName) { gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName); if (mIsTransparent) { glColor4f(1.f, 1.f, 1.f, 1.f); } else { glColor4f(0.7f, 0.6f, 0.3f, 1.f); gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); } } else if( !is_dummy && mLayerSet ) { if( mLayerSet->hasComposite() ) { gGL.getTexUnit(0)->bind(mLayerSet->getComposite()); } else { // This warning will always trigger if you've hacked the avatar to show as incomplete. // Ignore the warning if that's the case. if (!gSavedSettings.getBOOL("RenderUnloadedAvatar")) { //llwarns << "Layerset without composite" << llendl; } gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); } } else if ( !is_dummy && mTexture.notNull() ) { if(mTexture->hasGLTexture()) { old_mode = mTexture->getAddressMode(); } gGL.getTexUnit(0)->bind(mTexture.get()); gGL.getTexUnit(0)->bind(mTexture); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } else { gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); } if (gRenderForSelect) { if (isTransparent()) { gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_CONST_ALPHA); } else { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } } mFace->mVertexBuffer->setBuffer(sRenderMask); U32 start = mMesh->mFaceVertexOffset; U32 end = start + mMesh->mFaceVertexCount - 1; U32 count = mMesh->mFaceIndexCount; U32 offset = mMesh->mFaceIndexOffset; if (mMesh->hasWeights()) { if ((mFace->getPool()->getVertexShaderLevel() > 0)) { if (first_pass) { uploadJointMatrices(); } } mFace->mVertexBuffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); } else { glPushMatrix(); LLMatrix4 jointToWorld = getWorldMatrix(); glMultMatrixf((GLfloat*)jointToWorld.mMatrix); mFace->mVertexBuffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); glPopMatrix(); } gPipeline.addTrianglesDrawn(count); triangle_count += count; if (mTestImageName) { gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } if (mTexture.notNull() && !is_dummy) { gGL.getTexUnit(0)->bind(mTexture); gGL.getTexUnit(0)->setTextureAddressMode(old_mode); } return triangle_count; }
//-------------------------------------------------------------------- // LLViewerJointMesh::drawShape() //-------------------------------------------------------------------- U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass) { if (!mValid || !mMesh || !mFace || !mVisible || mFace->mVertexBuffer.isNull() || mMesh->getNumFaces() == 0) { return 0; } U32 triangle_count = 0; stop_glerror(); //---------------------------------------------------------------- // setup current color //---------------------------------------------------------------- if (!gRenderForSelect) { glColor4fv(mColor.mV); } stop_glerror(); LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), gRenderForSelect ? 0.0f : mShiny && !(mFace->getPool()->getVertexShaderLevel() > 0)); //---------------------------------------------------------------- // setup current texture //---------------------------------------------------------------- llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive if (mTestImageName) { LLImageGL::bindExternalTexture( mTestImageName, 0, GL_TEXTURE_2D ); if (mIsTransparent) { glColor4f(1.f, 1.f, 1.f, 1.f); } else { glColor4f(0.7f, 0.6f, 0.3f, 1.f); gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); } } else if( mLayerSet ) { if( mLayerSet->hasComposite() ) { mLayerSet->getComposite()->bindTexture(); } else { llwarns << "Layerset without composite" << llendl; gImageList.getImage(IMG_DEFAULT)->bind(); } } else if ( mTexture.notNull() ) { if (!mTexture->getClampS() || !mTexture->getClampT()) { mTexture->bind(); mTexture->overrideClamp (TRUE, TRUE); } } else { gImageList.getImage(IMG_DEFAULT_AVATAR)->bind(); } if (gRenderForSelect) { if (isTransparent()) { gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_CONST_ALPHA); } else { LLImageGL::unbindTexture(0); } } mFace->mVertexBuffer->setBuffer(sRenderMask); U32 start = mMesh->mFaceVertexOffset; U32 end = start + mMesh->mFaceVertexCount - 1; U32 count = mMesh->mFaceIndexCount; U32 offset = mMesh->mFaceIndexOffset; if (mMesh->hasWeights()) { if ((mFace->getPool()->getVertexShaderLevel() > 0)) { if (first_pass) { uploadJointMatrices(); } } mFace->mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, start, end, count, offset); } else { glPushMatrix(); LLMatrix4 jointToWorld = getWorldMatrix(); glMultMatrixf((GLfloat*)jointToWorld.mMatrix); mFace->mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, start, end, count, offset); glPopMatrix(); } gPipeline.addTrianglesDrawn(count/3); triangle_count += count; if (mTestImageName) { gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } if (mTexture.notNull()) { mTexture->bind(); mTexture->restoreClamp(); } return triangle_count; }
//-------------------------------------------------------------------- // 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; 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 && mLayerSet ) { if( mLayerSet->hasComposite() ) { gGL.getTexUnit(diffuse_channel)->bind(mLayerSet->getComposite()); } else { 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.get()); 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; }