summaryrefslogtreecommitdiff
path: root/indra/newview/llvovolume.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llvovolume.cpp')
-rwxr-xr-xindra/newview/llvovolume.cpp672
1 files changed, 532 insertions, 140 deletions
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 135c2e1eca..2c9a9704ba 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -36,6 +36,7 @@
#include "lldir.h"
#include "llflexibleobject.h"
#include "llfloatertools.h"
+#include "llmaterialid.h"
#include "llmaterialtable.h"
#include "llprimitive.h"
#include "llvolume.h"
@@ -76,6 +77,7 @@
#include "llviewershadermgr.h"
#include "llvoavatar.h"
#include "llvocache.h"
+#include "llmaterialmgr.h"
const S32 MIN_QUIET_FRAMES_COALESCE = 30;
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
@@ -554,37 +556,9 @@ void LLVOVolume::animateTextures()
tex_mat.setIdentity();
LLVector3 trans ;
- if(facep->isAtlasInUse())
- {
- //
- //if use atlas for animated texture
- //apply the following transform to the animation matrix.
- //
-
- F32 tcoord_xoffset = 0.f ;
- F32 tcoord_yoffset = 0.f ;
- F32 tcoord_xscale = 1.f ;
- F32 tcoord_yscale = 1.f ;
- if(facep->isAtlasInUse())
- {
- const LLVector2* tmp = facep->getTexCoordOffset() ;
- tcoord_xoffset = tmp->mV[0] ;
- tcoord_yoffset = tmp->mV[1] ;
-
- tmp = facep->getTexCoordScale() ;
- tcoord_xscale = tmp->mV[0] ;
- tcoord_yscale = tmp->mV[1] ;
- }
- trans.set(LLVector3(tcoord_xoffset + tcoord_xscale * (off_s+0.5f), tcoord_yoffset + tcoord_yscale * (off_t+0.5f), 0.f));
-
- tex_mat.translate(LLVector3(-(tcoord_xoffset + tcoord_xscale * 0.5f), -(tcoord_yoffset + tcoord_yscale * 0.5f), 0.f));
- }
- else //non atlas
- {
- trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f));
- tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f));
- }
-
+ trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f));
+ tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f));
+
LLVector3 scale(scale_s, scale_t, 1.f);
LLQuaternion quat;
quat.setQuat(rot, 0, 0, -1.f);
@@ -918,6 +892,12 @@ LLFace* LLVOVolume::addFace(S32 f)
{
const LLTextureEntry* te = getTE(f);
LLViewerTexture* imagep = getTEImage(f);
+ if (te->getMaterialParams().notNull())
+ {
+ LLViewerTexture* normalp = getTENormalMap(f);
+ LLViewerTexture* specularp = getTESpecularMap(f);
+ return mDrawable->addFace(te, imagep, normalp, specularp);
+ }
return mDrawable->addFace(te, imagep);
}
@@ -1066,7 +1046,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
{ //already cached
break;
}
- volume->genBinormals(i);
+ volume->genTangents(i);
LLFace::cacheFaceInVRAM(face);
}
}
@@ -1415,6 +1395,11 @@ void LLVOVolume::regenFaces()
facep->setTEOffset(i);
facep->setTexture(getTEImage(i));
+ if (facep->getTextureEntry()->getMaterialParams().notNull())
+ {
+ facep->setNormalMap(getTENormalMap(i));
+ facep->setSpecularMap(getTESpecularMap(i));
+ }
facep->setViewerObject(this);
// If the face had media on it, this will have broken the link between the LLViewerMediaTexture and the face.
@@ -1876,7 +1861,7 @@ S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color)
const LLTextureEntry *tep = getTE(te);
if (!tep)
{
- llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
+ LL_WARNS("MaterialTEs") << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL;
}
else if (color != tep->getColor())
{
@@ -1988,6 +1973,62 @@ S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow)
return res;
}
+void LLVOVolume::setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID &pMaterialID, const LLMaterialPtr pMaterialParams, U32 te)
+{
+ LLVOVolume* pVol = (LLVOVolume*)gObjectList.findObject(objectID);
+ if (pVol)
+ {
+ LL_DEBUGS("MaterialTEs") << "materialid " << pMaterialID.asString() << " to TE " << te << LL_ENDL;
+ if (te >= pVol->getNumTEs())
+ return;
+
+ LLTextureEntry* texture_entry = pVol->getTE(te);
+ if (texture_entry && (texture_entry->getMaterialID() == pMaterialID))
+ {
+ pVol->setTEMaterialParams(te, pMaterialParams);
+ }
+ }
+}
+
+S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID)
+{
+ S32 res = LLViewerObject::setTEMaterialID(te, pMaterialID);
+ LL_DEBUGS("MaterialTEs") << "te "<< (S32)te << " materialid " << pMaterialID.asString() << " res " << res
+ << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this), te) ? " selected" : " not selected" )
+ << LL_ENDL;
+
+ LL_DEBUGS("MaterialTEs") << " " << pMaterialID.asString() << LL_ENDL;
+ if (res)
+ {
+ LLMaterialMgr::instance().getTE(getRegion()->getRegionID(), pMaterialID, te, boost::bind(&LLVOVolume::setTEMaterialParamsCallbackTE, getID(), _1, _2, _3));
+
+ setChanged(ALL_CHANGED);
+ if (!mDrawable.isNull())
+ {
+ gPipeline.markTextured(mDrawable);
+ gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL);
+ }
+ mFaceMappingChanged = TRUE;
+ }
+ return res;
+}
+
+S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams)
+{
+ S32 res = LLViewerObject::setTEMaterialParams(te, pMaterialParams);
+ LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterialParams) ? pMaterialParams->asLLSD() : LLSD("null")) << " res " << res
+ << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this), te) ? " selected" : " not selected" )
+ << LL_ENDL;
+ setChanged(ALL_CHANGED);
+ if (!mDrawable.isNull())
+ {
+ gPipeline.markTextured(mDrawable);
+ gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL);
+ }
+ mFaceMappingChanged = TRUE;
+ return TEM_CHANGE_TEXTURE;
+}
+
S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t)
{
S32 res = LLViewerObject::setTEScale(te, s, t);
@@ -3476,7 +3517,12 @@ F32 LLVOVolume::getBinRadius()
}
else if (mDrawable->isStatic())
{
- radius = llmax((S32) mDrawable->getRadius(), 1)*size_factor;
+ F32 szf = size_factor;
+
+ radius = llmax(mDrawable->getRadius(), szf);
+
+ radius = powf(radius, 1.f+szf/radius);
+
radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1];
radius += mDrawable->mDistanceWRTCamera * distance_factor[0];
}
@@ -3573,8 +3619,8 @@ LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const
}
-BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face, BOOL pick_transparent, S32 *face_hitp,
- LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal)
+BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, S32 *face_hitp,
+ LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
{
if (!mbCanSelect
@@ -3606,23 +3652,25 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
if (volume)
{
- LLVector3 v_start, v_end, v_dir;
-
+ LLVector4a local_start = start;
+ LLVector4a local_end = end;
+
if (transform)
{
- v_start = agentPositionToVolume(start);
- v_end = agentPositionToVolume(end);
- }
- else
- {
- v_start = start;
- v_end = end;
- }
+ LLVector3 v_start(start.getF32ptr());
+ LLVector3 v_end(end.getF32ptr());
- LLVector3 p;
- LLVector3 n;
+ v_start = agentPositionToVolume(v_start);
+ v_end = agentPositionToVolume(v_end);
+
+ local_start.load3(v_start.mV);
+ local_end.load3(v_end.mV);
+ }
+
+ LLVector4a p;
+ LLVector4a n;
LLVector2 tc;
- LLVector3 bn;
+ LLVector4a tn;
if (intersection != NULL)
{
@@ -3639,9 +3687,9 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
n = *normal;
}
- if (bi_normal != NULL)
+ if (tangent != NULL)
{
- bn = *bi_normal;
+ tn = *tangent;
}
S32 face_hit = -1;
@@ -3667,8 +3715,8 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
continue;
}
- face_hit = volume->lineSegmentIntersect(v_start, v_end, i,
- &p, &tc, &n, &bn);
+ face_hit = volume->lineSegmentIntersect(local_start, local_end, i,
+ &p, &tc, &n, &tn);
if (face_hit >= 0 && mDrawable->getNumFaces() > face_hit)
{
@@ -3677,7 +3725,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
if (face &&
(pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n))))
{
- v_end = p;
+ local_end = p;
if (face_hitp != NULL)
{
*face_hitp = face_hit;
@@ -3687,7 +3735,9 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
{
if (transform)
{
- *intersection = volumePositionToAgent(p); // must map back to agent space
+ LLVector3 v_p(p.getF32ptr());
+
+ intersection->load3(volumePositionToAgent(v_p).mV); // must map back to agent space
}
else
{
@@ -3699,27 +3749,36 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
{
if (transform)
{
- *normal = volumeDirectionToAgent(n);
+ LLVector3 v_n(n.getF32ptr());
+ normal->load3(volumeDirectionToAgent(v_n).mV);
}
else
{
*normal = n;
}
-
- (*normal).normVec();
+ (*normal).normalize3fast();
}
- if (bi_normal != NULL)
+ if (tangent != NULL)
{
if (transform)
{
- *bi_normal = volumeDirectionToAgent(bn);
+ LLVector3 v_tn(tn.getF32ptr());
+
+ LLVector4a trans_tangent;
+ trans_tangent.load3(volumeDirectionToAgent(v_tn).mV);
+
+ LLVector4Logical mask;
+ mask.clear();
+ mask.setElement<3>();
+
+ tangent->setSelectWithMask(mask, tn, trans_tangent);
}
else
{
- *bi_normal = bn;
+ *tangent = tn;
}
- (*bi_normal).normVec();
+ (*tangent).normalize3fast();
}
if (tex_coord != NULL)
@@ -3976,6 +4035,11 @@ bool can_batch_texture(LLFace* facep)
return false;
}
+ if (facep->getTextureEntry()->getMaterialParams().notNull())
+ { //materials don't work with texture batching yet
+ return false;
+ }
+
if (facep->getTexture() && facep->getTexture()->getPrimaryFormat() == GL_ALPHA)
{ //can't batch invisiprims
return false;
@@ -3994,7 +4058,11 @@ static LLFastTimer::DeclareTimer FTM_REGISTER_FACE("Register Face");
void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type)
{
LLFastTimer t(FTM_REGISTER_FACE);
-
+ if (type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT))
+ {
+ LL_WARNS("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL;
+ }
+
if (facep->getViewerObject()->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects)
{
return;
@@ -4007,7 +4075,9 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) ||
(type == LLRenderPass::PASS_INVISIBLE) ||
- (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT));
+ (type == LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK) ||
+ (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)) ||
+ (facep->getTextureEntry()->getFullbright());
if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_NORMAL))
{
@@ -4041,16 +4111,39 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
//drawable->getVObj()->setDebugText(llformat("%d", drawable->isState(LLDrawable::ANIMATED_CHILD)));
U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0;
-
+ U8 shiny = facep->getTextureEntry()->getShiny();
+
LLViewerTexture* tex = facep->getTexture();
U8 index = facep->getTextureIndex();
+
+ LLMaterial* mat = facep->getTextureEntry()->getMaterialParams().get();
+ LLMaterialID mat_id = facep->getTextureEntry()->getMaterialID();
bool batchable = false;
+ U32 shader_mask = 0xFFFFFFFF; //no shader
+
+ if (mat)
+ {
+ if (type == LLRenderPass::PASS_ALPHA)
+ {
+ shader_mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND);
+ }
+ else
+ {
+ shader_mask = mat->getShaderMask();
+ }
+ }
+
+
if (index < 255 && idx >= 0)
{
- if (index < draw_vec[idx]->mTextureList.size())
+ if (mat || draw_vec[idx]->mMaterial)
+ { //can't batch textures when materials are present (yet)
+ batchable = false;
+ }
+ else if (index < draw_vec[idx]->mTextureList.size())
{
if (draw_vec[idx]->mTextureList[index].isNull())
{
@@ -4076,16 +4169,20 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
#endif
+ draw_vec[idx]->mMaterial == mat &&
+ draw_vec[idx]->mMaterialID == mat_id &&
draw_vec[idx]->mFullbright == fullbright &&
- draw_vec[idx]->mBump == bump &&
+ draw_vec[idx]->mBump == bump &&
+ (!mat || (draw_vec[idx]->mShiny == shiny)) && // need to break batches when a material is shared, but legacy settings are different
draw_vec[idx]->mTextureMatrix == tex_mat &&
- draw_vec[idx]->mModelMatrix == model_mat)
+ draw_vec[idx]->mModelMatrix == model_mat &&
+ draw_vec[idx]->mShaderMask == shader_mask)
{
draw_vec[idx]->mCount += facep->getIndicesCount();
draw_vec[idx]->mEnd += facep->getGeomCount();
draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize());
- if (index >= draw_vec[idx]->mTextureList.size())
+ if (index < 255 && index >= draw_vec[idx]->mTextureList.size())
{
draw_vec[idx]->mTextureList.resize(index+1);
draw_vec[idx]->mTextureList[index] = tex;
@@ -4101,12 +4198,66 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
U32 offset = facep->getIndicesStart();
U32 count = facep->getIndicesCount();
LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset, tex,
- facep->getVertexBuffer(), fullbright, bump);
+ facep->getVertexBuffer(), fullbright, bump);
draw_info->mGroup = group;
draw_info->mVSize = facep->getVirtualSize();
draw_vec.push_back(draw_info);
draw_info->mTextureMatrix = tex_mat;
draw_info->mModelMatrix = model_mat;
+
+ draw_info->mBump = bump;
+ draw_info->mShiny = shiny;
+
+ float alpha[4] =
+ {
+ 0.00f,
+ 0.25f,
+ 0.5f,
+ 0.75f
+ };
+ float spec = alpha[shiny & TEM_SHINY_MASK];
+ LLVector4 specColor(spec, spec, spec, spec);
+ draw_info->mSpecColor = specColor;
+ draw_info->mEnvIntensity = spec;
+ draw_info->mSpecularMap = NULL;
+ draw_info->mMaterial = mat;
+ draw_info->mShaderMask = shader_mask;
+
+ if (mat)
+ {
+ draw_info->mMaterialID = mat_id;
+
+ // We have a material. Update our draw info accordingly.
+
+ if (!mat->getSpecularID().isNull())
+ {
+ LLVector4 specColor;
+ specColor.mV[0] = mat->getSpecularLightColor().mV[0] * (1.f / 255.f);
+ specColor.mV[1] = mat->getSpecularLightColor().mV[1] * (1.f / 255.f);
+ specColor.mV[2] = mat->getSpecularLightColor().mV[2] * (1.f / 255.f);
+ specColor.mV[3] = mat->getSpecularLightExponent() * (1.f / 255.f);
+ draw_info->mSpecColor = specColor;
+ draw_info->mEnvIntensity = mat->getEnvironmentIntensity() * (1.f / 255.f);
+ draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTEOffset());
+ }
+
+ draw_info->mAlphaMaskCutoff = mat->getAlphaMaskCutoff() * (1.f / 255.f);
+ draw_info->mDiffuseAlphaMode = mat->getDiffuseAlphaMode();
+ draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTEOffset());
+
+ }
+ else
+ {
+ if (type == LLRenderPass::PASS_GRASS)
+ {
+ draw_info->mAlphaMaskCutoff = 0.5f;
+ }
+ else
+ {
+ draw_info->mAlphaMaskCutoff = 0.33f;
+ }
+ }
+
if (type == LLRenderPass::PASS_ALPHA)
{ //for alpha sorting
facep->setDrawInfo(draw_info);
@@ -4223,6 +4374,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
std::vector<LLFace*> fullbright_faces;
std::vector<LLFace*> bump_faces;
+ std::vector<LLFace*> norm_faces;
+ std::vector<LLFace*> spec_faces;
+ std::vector<LLFace*> normspec_faces;
std::vector<LLFace*> simple_faces;
std::vector<LLFace*> alpha_faces;
@@ -4267,7 +4421,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
}
if (vobj->isMesh() &&
- (vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled()))
+ ((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled()))
{
continue;
}
@@ -4387,66 +4541,123 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
LLViewerTexture* tex = facep->getTexture();
U32 type = gPipeline.getPoolTypeFromTE(te, tex);
- if (type == LLDrawPool::POOL_ALPHA)
+
+ if (te->getGlow())
{
- if (te->getColor().mV[3] > 0.f)
- {
- if (te->getFullbright())
- {
- pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA);
- }
- else
- {
- pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA);
- }
+ pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW);
+ }
+
+ LLMaterial* mat = te->getMaterialParams().get();
+
+ if (mat && LLPipeline::sRenderDeferred)
+ {
+ U8 alpha_mode = mat->getDiffuseAlphaMode();
+
+ bool is_alpha = type == LLDrawPool::POOL_ALPHA &&
+ (alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND ||
+ te->getColor().mV[3] < 0.999f);
+
+ if (is_alpha)
+ { //this face needs alpha blending, override alpha mode
+ alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND;
+ }
+
+ if (!is_alpha || te->getColor().mV[3] > 0.f) // //only add the face if it will actually be visible
+ {
+ U32 mask = mat->getShaderMask(alpha_mode);
+ pool->addRiggedFace(facep, mask);
}
}
- else if (te->getShiny())
+ else if (mat)
{
- if (te->getFullbright())
+ bool fullbright = te->getFullbright();
+ bool is_alpha = type == LLDrawPool::POOL_ALPHA;
+ U8 mode = mat->getDiffuseAlphaMode();
+ bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE ||
+ mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE;
+
+ if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && te->getColor().mV[3] >= 0.999f)
{
- pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY);
+ pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE);
}
- else
+ else if (is_alpha || (te->getColor().mV[3] < 0.999f))
{
- if (LLPipeline::sRenderDeferred)
- {
- pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE);
- }
- else
+ if (te->getColor().mV[3] > 0.f)
{
- pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY);
+ pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA);
}
}
- }
- else
- {
- if (te->getFullbright())
+ else if (gPipeline.canUseVertexShaders()
+ && LLPipeline::sRenderBump
+ && te->getShiny()
+ && can_be_shiny)
{
- pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT);
+ pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : LLDrawPoolAvatar::RIGGED_SHINY);
}
else
{
- pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE);
+ pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE);
}
}
-
- if (te->getGlow())
- {
- pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW);
- }
-
- if (LLPipeline::sRenderDeferred)
+ else
{
- if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright())
+ if (type == LLDrawPool::POOL_ALPHA)
{
- if (te->getBumpmap())
+ if (te->getColor().mV[3] > 0.f)
{
- pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP);
+ if (te->getFullbright())
+ {
+ pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA);
+ }
+ else
+ {
+ pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA);
+ }
+ }
+ }
+ else if (te->getShiny())
+ {
+ if (te->getFullbright())
+ {
+ pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY);
}
else
{
- pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE);
+ if (LLPipeline::sRenderDeferred)
+ {
+ pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE);
+ }
+ else
+ {
+ pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY);
+ }
+ }
+ }
+ else
+ {
+ if (te->getFullbright())
+ {
+ pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT);
+ }
+ else
+ {
+ pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE);
+ }
+ }
+
+
+ if (LLPipeline::sRenderDeferred)
+ {
+ if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright())
+ {
+ if (te->getBumpmap())
+ {
+ pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP);
+ }
+ else
+ {
+ pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE);
+ }
}
}
}
@@ -4556,8 +4767,31 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
if (gPipeline.canUseWindLightShadersOnObjects()
&& LLPipeline::sRenderBump)
{
- if (te->getBumpmap())
- { //needs normal + binormal
+ if (LLPipeline::sRenderDeferred && te->getMaterialParams().notNull() && !te->getMaterialID().isNull())
+ {
+ LLMaterial* mat = te->getMaterialParams().get();
+ if (mat->getNormalID().notNull())
+ {
+ if (mat->getSpecularID().notNull())
+ { //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
+ normspec_faces.push_back(facep);
+ }
+ else
+ { //has normal map (needs texcoord1 and tangent)
+ norm_faces.push_back(facep);
+ }
+ }
+ else if (mat->getSpecularID().notNull())
+ { //has specular map but no normal map, needs texcoord2
+ spec_faces.push_back(facep);
+ }
+ else
+ { //has neither specular map nor normal map, only needs texcoord0
+ simple_faces.push_back(facep);
+ }
+ }
+ else if (te->getBumpmap())
+ { //needs normal + tangent
bump_faces.push_back(facep);
}
else if (te->getShiny() || !te->getFullbright())
@@ -4573,7 +4807,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
else
{
if (te->getBumpmap() && LLPipeline::sRenderBump)
- { //needs normal + binormal
+ { //needs normal + tangent
bump_faces.push_back(facep);
}
else if ((te->getShiny() && LLPipeline::sRenderBump) ||
@@ -4623,32 +4857,38 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR;
U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR;
+ U32 norm_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TANGENT;
+ U32 normspec_mask = norm_mask | LLVertexBuffer::MAP_TEXCOORD2;
+ U32 spec_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD2;
+
if (emissive)
{ //emissive faces are present, include emissive byte to preserve batching
simple_mask = simple_mask | LLVertexBuffer::MAP_EMISSIVE;
alpha_mask = alpha_mask | LLVertexBuffer::MAP_EMISSIVE;
bump_mask = bump_mask | LLVertexBuffer::MAP_EMISSIVE;
fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_EMISSIVE;
+ norm_mask = norm_mask | LLVertexBuffer::MAP_EMISSIVE;
+ normspec_mask = normspec_mask | LLVertexBuffer::MAP_EMISSIVE;
+ spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE;
}
- bool batch_textures = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1;
+ BOOL batch_textures = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1;
if (batch_textures)
{
- bump_mask |= LLVertexBuffer::MAP_BINORMAL;
- genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, FALSE, TRUE);
- genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, FALSE, TRUE);
- genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, FALSE, TRUE);
- genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, TRUE, TRUE);
+ bump_mask = bump_mask | LLVertexBuffer::MAP_TANGENT;
+ simple_mask = simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX;
+ alpha_mask = alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2;
+ fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX;
}
- else
- {
- genDrawInfo(group, simple_mask, simple_faces);
- genDrawInfo(group, fullbright_mask, fullbright_faces);
- genDrawInfo(group, bump_mask, bump_faces, FALSE, TRUE);
- genDrawInfo(group, alpha_mask, alpha_faces, TRUE);
- }
-
+
+ genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, FALSE, batch_textures, FALSE);
+ genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, FALSE, batch_textures);
+ genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, TRUE, batch_textures);
+ genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, FALSE, FALSE);
+ genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, norm_faces, FALSE, FALSE);
+ genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, spec_faces, FALSE, FALSE);
+ genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, normspec_faces, FALSE, FALSE);
if (!LLPipeline::sDelayVBUpdate)
{
@@ -4800,11 +5040,18 @@ struct CompareBatchBreakerModified
{
return lte->getFullbright() < rte->getFullbright();
}
+ else if (LLPipeline::sRenderDeferred && lte->getMaterialParams() != rte->getMaterialParams())
+ {
+ return lte->getMaterialParams() < rte->getMaterialParams();
+ }
+ else if (LLPipeline::sRenderDeferred && (lte->getMaterialParams() == rte->getMaterialParams()) && (lte->getShiny() != rte->getShiny()))
+ {
+ return lte->getShiny() < rte->getShiny();
+ }
else
{
return lhs->getTexture() < rhs->getTexture();
}
-
}
};
@@ -4818,7 +5065,7 @@ static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB");
-void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort, BOOL batch_textures)
+void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort, BOOL batch_textures, BOOL no_materials)
{
LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO);
@@ -4888,6 +5135,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
//pull off next face
LLFace* facep = *face_iter;
LLViewerTexture* tex = facep->getTexture();
+ LLMaterialPtr mat = facep->getTextureEntry()->getMaterialParams();
if (distance_sort)
{
@@ -4933,6 +5181,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
if (!can_batch_texture(facep))
{ //face is bump mapped or has an animated texture matrix -- can't
//batch more than 1 texture at a time
+ facep->setTextureIndex(0);
break;
}
@@ -4983,13 +5232,20 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
facep->setTextureIndex(cur_tex);
}
}
+ else
+ {
+ facep->setTextureIndex(0);
+ }
tex = texture_list[0];
}
else
{
while (i != faces.end() &&
- (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex)))
+ (LLPipeline::sTextureBindTest ||
+ (distance_sort ||
+ ((*i)->getTexture() == tex &&
+ ((*i)->getTextureEntry()->getMaterialParams() == mat)))))
{
facep = *i;
@@ -5075,8 +5331,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
index_offset += facep->getGeomCount();
indices_index += facep->getIndicesCount();
-
-
+
//append face to appropriate render batch
BOOL force_simple = facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA;
@@ -5096,7 +5351,130 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE;
- if (is_alpha)
+ LLMaterial* mat = te->getMaterialParams().get();
+
+ bool can_be_shiny = true;
+ if (mat)
+ {
+ U8 mode = mat->getDiffuseAlphaMode();
+ can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE ||
+ mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE;
+ }
+
+ bool use_legacy_bump = te->getBumpmap() && (!mat || mat->getNormalID().isNull());
+
+ if (mat && LLPipeline::sRenderDeferred && !hud_group)
+ {
+ bool material_pass = false;
+
+ if (fullbright)
+ {
+ if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
+ {
+ if (te->getColor().mV[3] >= 0.999f)
+ {
+ material_pass = true;
+ }
+ else
+ {
+ registerFace(group, facep, LLRenderPass::PASS_ALPHA);
+ }
+ }
+ else if (is_alpha)
+ {
+ registerFace(group, facep, LLRenderPass::PASS_ALPHA);
+ }
+ else
+ {
+ if (mat->getEnvironmentIntensity() > 0 ||
+ te->getShiny() > 0)
+ {
+ material_pass = true;
+ }
+ else
+ {
+ registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);
+ }
+ }
+ }
+ else if (no_materials)
+ {
+ registerFace(group, facep, LLRenderPass::PASS_SIMPLE);
+ }
+ else if (te->getColor().mV[3] < 0.999f)
+ {
+ registerFace(group, facep, LLRenderPass::PASS_ALPHA);
+ }
+ else if (use_legacy_bump)
+ {
+ // we have a material AND legacy bump settings, but no normal map
+ registerFace(group, facep, LLRenderPass::PASS_BUMP);
+ }
+ else
+ {
+ material_pass = true;
+ }
+
+ if (material_pass)
+ {
+ U32 pass[] =
+ {
+ LLRenderPass::PASS_MATERIAL,
+ LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_MATERIAL_ALPHA,
+ LLRenderPass::PASS_MATERIAL_ALPHA_MASK,
+ LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE,
+ LLRenderPass::PASS_SPECMAP,
+ LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_SPECMAP_BLEND,
+ LLRenderPass::PASS_SPECMAP_MASK,
+ LLRenderPass::PASS_SPECMAP_EMISSIVE,
+ LLRenderPass::PASS_NORMMAP,
+ LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMMAP_BLEND,
+ LLRenderPass::PASS_NORMMAP_MASK,
+ LLRenderPass::PASS_NORMMAP_EMISSIVE,
+ LLRenderPass::PASS_NORMSPEC,
+ LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMSPEC_BLEND,
+ LLRenderPass::PASS_NORMSPEC_MASK,
+ LLRenderPass::PASS_NORMSPEC_EMISSIVE,
+ };
+
+ U32 mask = mat->getShaderMask();
+
+ llassert(mask < sizeof(pass)/sizeof(U32));
+
+ mask = llmin(mask, (U32)(sizeof(pass)/sizeof(U32)-1));
+
+ registerFace(group, facep, pass[mask]);
+ }
+ }
+ else if (mat)
+ {
+ U8 mode = mat->getDiffuseAlphaMode();
+ if (te->getColor().mV[3] < 0.999f)
+ {
+ mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND;
+ }
+
+ if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
+ {
+ registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK : LLRenderPass::PASS_ALPHA_MASK);
+ }
+ else if (is_alpha || (te->getColor().mV[3] < 0.999f))
+ {
+ registerFace(group, facep, LLRenderPass::PASS_ALPHA);
+ }
+ else if (gPipeline.canUseVertexShaders()
+ && LLPipeline::sRenderBump
+ && te->getShiny()
+ && can_be_shiny)
+ {
+ registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_SHINY : LLRenderPass::PASS_SHINY);
+ }
+ else
+ {
+ registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT : LLRenderPass::PASS_SIMPLE);
+ }
+ }
+ else if (is_alpha)
{
// can we safely treat this as an alpha mask?
if (facep->getFaceColor().mV[3] <= 0.f)
@@ -5121,7 +5499,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
}
else if (gPipeline.canUseVertexShaders()
&& LLPipeline::sRenderBump
- && te->getShiny())
+ && te->getShiny()
+ && can_be_shiny)
{ //shiny
if (tex->getPrimaryFormat() == GL_ALPHA)
{ //invisiprim+shiny
@@ -5138,7 +5517,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
registerFace(group, facep, LLRenderPass::PASS_POST_BUMP);
}
}
- else if (te->getBumpmap())
+ else if (use_legacy_bump)
{ //register in deferred bump pass
registerFace(group, facep, LLRenderPass::PASS_BUMP);
}
@@ -5165,22 +5544,36 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
}
else if (fullbright || bake_sunlight)
{ //fullbright
- registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);
- if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && te->getBumpmap())
+ if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
+ {
+ registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK);
+ }
+ else
+ {
+ registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);
+ }
+ if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && use_legacy_bump)
{ //if this is the deferred render and a bump map is present, register in post deferred bump
registerFace(group, facep, LLRenderPass::PASS_POST_BUMP);
}
}
else
{
- if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap())
+ if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && use_legacy_bump)
{ //non-shiny or fullbright deferred bump
registerFace(group, facep, LLRenderPass::PASS_BUMP);
}
else
{ //all around simple
llassert(mask & LLVertexBuffer::MAP_NORMAL);
- registerFace(group, facep, LLRenderPass::PASS_SIMPLE);
+ if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
+ { //material alpha mask can be respected in non-deferred
+ registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK);
+ }
+ else
+ {
+ registerFace(group, facep, LLRenderPass::PASS_SIMPLE);
+ }
}
}
@@ -5200,7 +5593,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright);
facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE);
- if (!force_simple && te->getBumpmap() && LLPipeline::sRenderBump)
+ if (!force_simple && LLPipeline::sRenderBump && use_legacy_bump)
{
registerFace(group, facep, LLRenderPass::PASS_BUMP);
}
@@ -5289,4 +5682,3 @@ void LLHUDPartition::shift(const LLVector4a &offset)
//HUD objects don't shift with region crossing. That would be silly.
}
-