summaryrefslogtreecommitdiff
path: root/indra/newview/llface.cpp
diff options
context:
space:
mode:
authorMerov Linden <merov@lindenlab.com>2013-06-19 14:06:06 -0700
committerMerov Linden <merov@lindenlab.com>2013-06-19 14:06:06 -0700
commit7da4c651911743707c0cc7cd4bebdcefb52eb379 (patch)
tree6f99d83a2b2bf3de810dd5a1191a47f7cc53ac9d /indra/newview/llface.cpp
parentf1e594feceb8ab284e023e164d5410cd53a656cb (diff)
parent2655c7a17ae38a073dcf8f05b0127b68edc34c95 (diff)
Pull merge from lindenlab/viewer-release
Diffstat (limited to 'indra/newview/llface.cpp')
-rwxr-xr-xindra/newview/llface.cpp751
1 files changed, 312 insertions, 439 deletions
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 281f852b0a..f021f4ed0f 100755
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -51,7 +51,7 @@
#include "llviewerregion.h"
#include "llviewerwindow.h"
#include "llviewershadermgr.h"
-
+#include "llviewertexture.h"
#define LL_MAX_INDICES_COUNT 1000000
@@ -106,41 +106,6 @@ void planarProjection(LLVector2 &tc, const LLVector4a& normal,
tc.mV[0] = 1.0f+((binormal.dot3(vec).getF32())*2 - 0.5f);
}
-void sphericalProjection(LLVector2 &tc, const LLVector4a& normal,
- const LLVector4a &mCenter, const LLVector4a& vec)
-{ //BROKEN
- /*tc.mV[0] = acosf(vd.mNormal * LLVector3(1,0,0))/3.14159f;
-
- tc.mV[1] = acosf(vd.mNormal * LLVector3(0,0,1))/6.284f;
- if (vd.mNormal.mV[1] > 0)
- {
- tc.mV[1] = 1.0f-tc.mV[1];
- }*/
-}
-
-void cylindricalProjection(LLVector2 &tc, const LLVector4a& normal, const LLVector4a &mCenter, const LLVector4a& vec)
-{ //BROKEN
- /*LLVector3 binormal;
- float d = vd.mNormal * LLVector3(1,0,0);
- if (d >= 0.5f || d <= -0.5f)
- {
- binormal = LLVector3(0,1,0);
- }
- else{
- binormal = LLVector3(1,0,0);
- }
- LLVector3 tangent = binormal % vd.mNormal;
-
- tc.mV[1] = -((tangent*vec)*2 - 0.5f);
-
- tc.mV[0] = acosf(vd.mNormal * LLVector3(1,0,0))/6.284f;
-
- if (vd.mNormal.mV[1] < 0)
- {
- tc.mV[0] = 1.0f-tc.mV[0];
- }*/
-}
-
////////////////////
//
// LLFace implementation
@@ -167,8 +132,12 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
//special value to indicate uninitialized position
mIndicesIndex = 0xFFFFFFFF;
- mIndexInTex = 0;
- mTexture = NULL;
+ for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
+ {
+ mIndexInTex[i] = 0;
+ mTexture[i] = NULL;
+ }
+
mTEOffset = -1;
mTextureIndex = 255;
@@ -185,8 +154,6 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
mImportanceToCamera = 0.f ;
mBoundingSphereRadius = 0.0f ;
- mAtlasInfop = NULL ;
- mUsingAtlas = FALSE ;
mHasMedia = FALSE ;
}
@@ -197,9 +164,12 @@ void LLFace::destroy()
gPipeline.checkReferences(this);
}
- if(mTexture.notNull())
+ for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
{
- mTexture->removeFace(this) ;
+ if(mTexture[i].notNull())
+ {
+ mTexture[i]->removeFace(i, this) ;
+ }
}
if (isState(LLFace::PARTICLE))
@@ -239,8 +209,7 @@ void LLFace::destroy()
}
setDrawInfo(NULL);
- removeAtlas();
-
+
mDrawablep = NULL;
mVObjp = NULL;
}
@@ -293,48 +262,76 @@ void LLFace::setPool(LLFacePool* new_pool, LLViewerTexture *texturep)
setTexture(texturep) ;
}
-void LLFace::setTexture(LLViewerTexture* tex)
+void LLFace::setTexture(U32 ch, LLViewerTexture* tex)
{
- if(mTexture == tex)
+ llassert(ch < LLRender::NUM_TEXTURE_CHANNELS);
+
+ if(mTexture[ch] == tex)
{
return ;
}
- if(mTexture.notNull())
+ if(mTexture[ch].notNull())
{
- mTexture->removeFace(this) ;
- removeAtlas() ;
+ mTexture[ch]->removeFace(ch, this) ;
}
if(tex)
{
- tex->addFace(this) ;
+ tex->addFace(ch, this) ;
}
- mTexture = tex ;
+ mTexture[ch] = tex ;
+}
+
+void LLFace::setTexture(LLViewerTexture* tex)
+{
+ setDiffuseMap(tex);
+}
+
+void LLFace::setDiffuseMap(LLViewerTexture* tex)
+{
+ setTexture(LLRender::DIFFUSE_MAP, tex);
+}
+
+void LLFace::setNormalMap(LLViewerTexture* tex)
+{
+ setTexture(LLRender::NORMAL_MAP, tex);
+}
+
+void LLFace::setSpecularMap(LLViewerTexture* tex)
+{
+ setTexture(LLRender::SPECULAR_MAP, tex);
}
void LLFace::dirtyTexture()
{
LLDrawable* drawablep = getDrawable();
- if (mVObjp.notNull() && mVObjp->getVolume() &&
- mTexture.notNull() && mTexture->getComponents() == 4)
- { //dirty texture on an alpha object should be treated as an LoD update
- LLVOVolume* vobj = drawablep->getVOVolume();
- if (vobj)
+ if (mVObjp.notNull() && mVObjp->getVolume())
+ {
+ for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
{
- vobj->mLODChanged = TRUE;
+ if (mTexture[ch].notNull() && mTexture[ch]->getComponents() == 4)
+ { //dirty texture on an alpha object should be treated as an LoD update
+ LLVOVolume* vobj = drawablep->getVOVolume();
+ if (vobj)
+ {
+ vobj->mLODChanged = TRUE;
+ }
+ gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, FALSE);
+ }
}
- gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, FALSE);
- }
+ }
gPipeline.markTextured(drawablep);
}
-void LLFace::switchTexture(LLViewerTexture* new_texture)
+void LLFace::switchTexture(U32 ch, LLViewerTexture* new_texture)
{
- if(mTexture == new_texture)
+ llassert(ch < LLRender::NUM_TEXTURE_CHANNELS);
+
+ if(mTexture[ch] == new_texture)
{
return ;
}
@@ -344,10 +341,17 @@ void LLFace::switchTexture(LLViewerTexture* new_texture)
llerrs << "Can not switch to a null texture." << llendl;
return;
}
- new_texture->addTextureStats(mTexture->getMaxVirtualSize()) ;
- getViewerObject()->changeTEImage(mTEOffset, new_texture) ;
- setTexture(new_texture) ;
+ llassert(mTexture[ch].notNull());
+
+ new_texture->addTextureStats(mTexture[ch]->getMaxVirtualSize()) ;
+
+ if (ch == LLRender::DIFFUSE_MAP)
+ {
+ getViewerObject()->changeTEImage(mTEOffset, new_texture) ;
+ }
+
+ setTexture(ch, new_texture) ;
dirtyTexture();
}
@@ -543,7 +547,9 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
}
else
{
- mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
+ // cheaters sometimes prosper...
+ //
+ mVertexBuffer->setBuffer(mVertexBuffer->getTypeMask());
mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
}
@@ -811,6 +817,12 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
size.mul(scale);
}
+ // Catch potential badness from normalization before it happens
+ //
+ llassert(mat_normal.mMatrix[0].isFinite3() && (mat_normal.mMatrix[0].dot3(mat_normal.mMatrix[0]).getF32() > F_APPROXIMATELY_ZERO));
+ llassert(mat_normal.mMatrix[1].isFinite3() && (mat_normal.mMatrix[1].dot3(mat_normal.mMatrix[1]).getF32() > F_APPROXIMATELY_ZERO));
+ llassert(mat_normal.mMatrix[2].isFinite3() && (mat_normal.mMatrix[2].dot3(mat_normal.mMatrix[2]).getF32() > F_APPROXIMATELY_ZERO));
+
mat_normal.mMatrix[0].normalize3fast();
mat_normal.mMatrix[1].normalize3fast();
mat_normal.mMatrix[2].normalize3fast();
@@ -896,7 +908,7 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
// integrated with getGeometryVolume() for its texture coordinate
// generation - but i'll leave that to someone more familiar
// with the implications.
-LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, LLVector3 position, LLVector3 normal)
+LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, const LLVector4a& position, const LLVector4a& normal)
{
LLVector2 tc = surface_coord;
@@ -916,7 +928,9 @@ LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, LLVector3 position,
LLVector4a& center = *(mDrawablep->getVOVolume()->getVolume()->getVolumeFace(mTEOffset).mCenter);
LLVector4a volume_position;
- volume_position.load3(mDrawablep->getVOVolume()->agentPositionToVolume(position).mV);
+ LLVector3 v_position(position.getF32ptr());
+
+ volume_position.load3(mDrawablep->getVOVolume()->agentPositionToVolume(v_position).mV);
if (!mDrawablep->getVOVolume()->isVolumeGlobal())
{
@@ -926,23 +940,14 @@ LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, LLVector3 position,
}
LLVector4a volume_normal;
- volume_normal.load3(mDrawablep->getVOVolume()->agentDirectionToVolume(normal).mV);
+ LLVector3 v_normal(normal.getF32ptr());
+ volume_normal.load3(mDrawablep->getVOVolume()->agentDirectionToVolume(v_normal).mV);
volume_normal.normalize3fast();
- switch (texgen)
+ if (texgen == LLTextureEntry::TEX_GEN_PLANAR)
{
- case LLTextureEntry::TEX_GEN_PLANAR:
planarProjection(tc, volume_normal, center, volume_position);
- break;
- case LLTextureEntry::TEX_GEN_SPHERICAL:
- sphericalProjection(tc, volume_normal, center, volume_position);
- break;
- case LLTextureEntry::TEX_GEN_CYLINDRICAL:
- cylindricalProjection(tc, volume_normal, center, volume_position);
- break;
- default:
- break;
- }
+ }
}
if (mTextureMatrix) // if we have a texture matrix, use it
@@ -969,7 +974,12 @@ void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_po
const LLMatrix4& vol_mat = getWorldMatrix();
const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset);
const LLVector4a& normal4a = vf.mNormals[0];
- const LLVector4a& binormal4a = vf.mBinormals[0];
+ const LLVector4a& tangent = vf.mTangents[0];
+
+ LLVector4a binormal4a;
+ binormal4a.setCross3(normal4a, tangent);
+ binormal4a.mul(tangent.getF32ptr()[3]);
+
LLVector2 projected_binormal;
planarProjection(projected_binormal, normal4a, *vf.mCenter, binormal4a);
projected_binormal -= LLVector2(0.5f, 0.5f); // this normally happens in xform()
@@ -1059,6 +1069,12 @@ bool LLFace::canRenderAsMask()
return false;
}
+ LLMaterial* mat = te->getMaterialParams();
+ if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)
+ {
+ return false;
+ }
+
if ((te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha
(te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask
getTexture()->getIsAlphaMask()) // texture actually qualifies for masking (lazily recalculated but expensive)
@@ -1091,7 +1107,7 @@ void LLFace::cacheFaceInVRAM(const LLVolumeFace& vf)
{
LLFastTimer t(FTM_FACE_GEOM_VOLUME);
U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 |
- LLVertexBuffer::MAP_BINORMAL | LLVertexBuffer::MAP_NORMAL;
+ LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_NORMAL;
if (vf.mWeights)
{
@@ -1104,11 +1120,11 @@ void LLFace::cacheFaceInVRAM(const LLVolumeFace& vf)
buff->allocateBuffer(vf.mNumVertices, 0, true);
LLStrider<LLVector4a> f_vert;
- LLStrider<LLVector3> f_binorm;
+ LLStrider<LLVector4a> f_tangent;
LLStrider<LLVector3> f_norm;
LLStrider<LLVector2> f_tc;
- buff->getBinormalStrider(f_binorm);
+ buff->getTangentStrider(f_tangent);
buff->getVertexStrider(f_vert);
buff->getNormalStrider(f_norm);
buff->getTexCoord0Strider(f_tc);
@@ -1116,7 +1132,7 @@ void LLFace::cacheFaceInVRAM(const LLVolumeFace& vf)
for (U32 i = 0; i < vf.mNumVertices; ++i)
{
*f_vert++ = vf.mPositions[i];
- (*f_binorm++).set(vf.mBinormals[i].getF32ptr());
+ *f_tangent++ = vf.mTangents[i];
*f_tc++ = vf.mTexCoords[i];
(*f_norm++).set(vf.mNormals[i].getF32ptr());
}
@@ -1158,7 +1174,7 @@ static LLFastTimer::DeclareTimer FTM_FACE_GEOM_TEXTURE("Texture");
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_COLOR("Color");
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_EMISSIVE("Emissive");
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_WEIGHTS("Weights");
-static LLFastTimer::DeclareTimer FTM_FACE_GEOM_BINORMAL("Binormal");
+static LLFastTimer::DeclareTimer FTM_FACE_GEOM_TANGENT("Binormal");
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX("Index");
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX_TAIL("Tail");
static LLFastTimer::DeclareTimer FTM_FACE_POSITION_STORE("Pos");
@@ -1219,11 +1235,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
LLStrider<LLVector3> vert;
- LLStrider<LLVector2> tex_coords;
+ LLStrider<LLVector2> tex_coords0;
+ LLStrider<LLVector2> tex_coords1;
LLStrider<LLVector2> tex_coords2;
LLStrider<LLVector3> norm;
LLStrider<LLColor4U> colors;
- LLStrider<LLVector3> binorm;
+ LLStrider<LLVector3> tangent;
LLStrider<U16> indicesp;
LLStrider<LLVector4> wght;
@@ -1245,33 +1262,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
bool rebuild_emissive = rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE);
bool rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD);
bool rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);
- bool rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL);
+ bool rebuild_tangent = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TANGENT);
bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4);
const LLTextureEntry *tep = mVObjp->getTE(f);
const U8 bump_code = tep ? tep->getBumpmap() : 0;
- F32 tcoord_xoffset = 0.f ;
- F32 tcoord_yoffset = 0.f ;
- F32 tcoord_xscale = 1.f ;
- F32 tcoord_yscale = 1.f ;
- BOOL in_atlas = FALSE ;
-
- if (rebuild_tcoord)
- {
- in_atlas = isAtlasInUse() ;
- if(in_atlas)
- {
- const LLVector2* tmp = getTexCoordOffset() ;
- tcoord_xoffset = tmp->mV[0] ;
- tcoord_yoffset = tmp->mV[1] ;
-
- tmp = getTexCoordScale() ;
- tcoord_xscale = tmp->mV[0] ;
- tcoord_yscale = tmp->mV[1] ;
- }
- }
-
BOOL is_static = mDrawablep->isStatic();
BOOL is_global = is_static;
@@ -1289,19 +1285,41 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
LLColor4U color = tep->getColor();
if (rebuild_color)
- {
- if (tep)
+ { //decide if shiny goes in alpha channel of color
+ if (tep &&
+ getPoolType() != LLDrawPool::POOL_ALPHA) // <--- alpha channel MUST contain transparency, not shiny
{
- GLfloat alpha[4] =
- {
- 0.00f,
- 0.25f,
- 0.5f,
- 0.75f
- };
+ LLMaterial* mat = tep->getMaterialParams().get();
+
+ bool shiny_in_alpha = false;
- if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || (LLPipeline::sRenderBump && tep->getShiny())))
+ if (LLPipeline::sRenderDeferred)
+ { //store shiny in alpha if we don't have a specular map
+ if (!mat || mat->getSpecularID().isNull())
+ {
+ shiny_in_alpha = true;
+ }
+ }
+ else
{
+ if (!mat || mat->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
+ {
+ shiny_in_alpha = true;
+ }
+ }
+
+ if (shiny_in_alpha)
+ {
+
+ GLfloat alpha[4] =
+ {
+ 0.00f,
+ 0.25f,
+ 0.5f,
+ 0.75f
+ };
+
+ llassert(tep->getShiny() <= 3);
color.mV[3] = U8 (alpha[tep->getShiny()] * 255);
}
}
@@ -1392,7 +1410,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
if (vf.mVertexBuffer.isNull() || buff->getNumVerts() != vf.mNumVertices)
{
- mVObjp->getVolume()->genBinormals(f);
+ mVObjp->getVolume()->genTangents(f);
LLFace::cacheFaceInVRAM(vf);
buff = (LLVertexBuffer*) vf.mVertexBuffer.get();
}
@@ -1477,15 +1495,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
glEndTransformFeedback();
}
- if (rebuild_binormal)
+ if (rebuild_tangent)
{
- LLFastTimer t(FTM_FACE_GEOM_BINORMAL);
- gTransformBinormalProgram.bind();
+ LLFastTimer t(FTM_FACE_GEOM_TANGENT);
+ gTransformTangentProgram.bind();
- mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_BINORMAL, mGeomIndex, mGeomCount);
+ mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TANGENT, mGeomIndex, mGeomCount);
glBeginTransformFeedback(GL_POINTS);
- buff->setBuffer(LLVertexBuffer::MAP_BINORMAL);
+ buff->setBuffer(LLVertexBuffer::MAP_TANGENT);
push_for_transform(buff, vf.mNumVertices, mGeomCount);
glEndTransformFeedback();
}
@@ -1547,7 +1565,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
if (bump_code)
{
- mVObjp->getVolume()->genBinormals(f);
+ mVObjp->getVolume()->genTangents(f);
F32 offset_multiple;
switch( bump_code )
{
@@ -1556,11 +1574,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
break;
case BE_BRIGHTNESS:
case BE_DARKNESS:
- if( mTexture.notNull() && mTexture->hasGLTexture())
+ if( mTexture[LLRender::DIFFUSE_MAP].notNull() && mTexture[LLRender::DIFFUSE_MAP]->hasGLTexture())
{
// Offset by approximately one texel
- S32 cur_discard = mTexture->getDiscardLevel();
- S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() );
+ S32 cur_discard = mTexture[LLRender::DIFFUSE_MAP]->getDiscardLevel();
+ S32 max_size = llmax( mTexture[LLRender::DIFFUSE_MAP]->getWidth(), mTexture[LLRender::DIFFUSE_MAP]->getHeight() );
max_size <<= cur_discard;
const F32 ARTIFICIAL_OFFSET = 2.f;
offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size;
@@ -1596,16 +1614,23 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
U8 texgen = getTextureEntry()->getTexGen();
if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT)
{ //planar texgen needs binormals
- mVObjp->getVolume()->genBinormals(f);
+ mVObjp->getVolume()->genTangents(f);
}
U8 tex_mode = 0;
+ bool tex_anim = false;
+
+ LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;
+ tex_mode = vobj->mTexAnimMode;
+
+ if (vobj->mTextureAnimp)
+ { //texture animation is in play, override specular and normal map tex coords with diffuse texcoords
+ tex_anim = true;
+ }
+
if (isState(TEXTURE_ANIM))
{
- LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;
- tex_mode = vobj->mTexAnimMode;
-
if (!tex_mode)
{
clearState(TEXTURE_ANIM);
@@ -1620,7 +1645,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
do_xform = false;
}
-
+
if (getVirtualSize() >= MIN_TEX_ANIM_SIZE)
{ //don't override texture transform during tc bake
tex_mode = 0;
@@ -1630,12 +1655,21 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
LLVector4a scalea;
scalea.load3(scale.mV);
+ LLMaterial* mat = tep->getMaterialParams().get();
+
bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1);
- bool do_tex_mat = tex_mode && mTextureMatrix;
- if (!in_atlas && !do_bump)
- { //not in atlas or not bump mapped, might be able to do a cheap update
- mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount);
+ if (mat && !do_bump)
+ {
+ do_bump = mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)
+ || mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2);
+ }
+
+ bool do_tex_mat = tex_mode && mTextureMatrix;
+
+ if (!do_bump)
+ { //not bump mapped, might be able to do a cheap update
+ mVertexBuffer->getTexCoord0Strider(tex_coords0, mGeomIndex, mGeomCount);
if (texgen != LLTextureEntry::TEX_GEN_PLANAR)
{
@@ -1646,12 +1680,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
{
LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM);
S32 tc_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF;
- LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, tc_size);
+ LLVector4a::memcpyNonAliased16((F32*) tex_coords0.get(), (F32*) vf.mTexCoords, tc_size);
}
else
{
LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM);
- F32* dst = (F32*) tex_coords.get();
+ F32* dst = (F32*) tex_coords0.get();
LLVector4a* src = (LLVector4a*) vf.mTexCoords;
LLVector4a trans;
@@ -1686,7 +1720,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
}
else
- { //do tex mat, no texgen, no atlas, no bump
+ { //do tex mat, no texgen, no bump
for (S32 i = 0; i < num_vertices; i++)
{
LLVector2 tc(vf.mTexCoords[i]);
@@ -1697,12 +1731,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
tmp = tmp * *mTextureMatrix;
tc.mV[0] = tmp.mV[0];
tc.mV[1] = tmp.mV[1];
- *tex_coords++ = tc;
+ *tex_coords0++ = tc;
}
}
}
else
- { //no bump, no atlas, tex gen planar
+ { //no bump, tex gen planar
LLFastTimer t(FTM_FACE_TEX_QUICK_PLANAR);
if (do_tex_mat)
{
@@ -1720,7 +1754,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
tc.mV[0] = tmp.mV[0];
tc.mV[1] = tmp.mV[1];
- *tex_coords++ = tc;
+ *tex_coords0++ = tc;
}
}
else
@@ -1736,7 +1770,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
- *tex_coords++ = tc;
+ *tex_coords0++ = tc;
}
}
}
@@ -1747,145 +1781,104 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
}
else
- { //either bump mapped or in atlas, just do the whole expensive loop
+ { //bump mapped or has material, just do the whole expensive loop
LLFastTimer t(FTM_FACE_TEX_DEFAULT);
- mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range);
-
- std::vector<LLVector2> bump_tc;
-
- for (S32 i = 0; i < num_vertices; i++)
- {
- LLVector2 tc(vf.mTexCoords[i]);
-
- LLVector4a& norm = vf.mNormals[i];
-
- LLVector4a& center = *(vf.mCenter);
-
- if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
- {
- LLVector4a vec = vf.mPositions[i];
- vec.mul(scalea);
+ std::vector<LLVector2> bump_tc;
- switch (texgen)
- {
- case LLTextureEntry::TEX_GEN_PLANAR:
- planarProjection(tc, norm, center, vec);
- break;
- case LLTextureEntry::TEX_GEN_SPHERICAL:
- sphericalProjection(tc, norm, center, vec);
- break;
- case LLTextureEntry::TEX_GEN_CYLINDRICAL:
- cylindricalProjection(tc, norm, center, vec);
- break;
- default:
- break;
- }
- }
+ if (mat && !mat->getNormalID().isNull())
+ { //writing out normal and specular texture coordinates, not bump offsets
+ do_bump = false;
+ }
- if (tex_mode && mTextureMatrix)
- {
- LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
- tmp = tmp * *mTextureMatrix;
- tc.mV[0] = tmp.mV[0];
- tc.mV[1] = tmp.mV[1];
- }
- else
- {
- xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
- }
+ LLStrider<LLVector2> dst;
- if(in_atlas)
+ for (U32 ch = 0; ch < 3; ++ch)
+ {
+ switch (ch)
{
- //
- //manually calculate tex-coord per vertex for varying address modes.
- //should be removed if shader can handle this.
- //
-
- S32 int_part = 0 ;
- switch(mTexture->getAddressMode())
- {
- case LLTexUnit::TAM_CLAMP:
- if(tc.mV[0] < 0.f)
- {
- tc.mV[0] = 0.f ;
- }
- else if(tc.mV[0] > 1.f)
- {
- tc.mV[0] = 1.f;
- }
-
- if(tc.mV[1] < 0.f)
- {
- tc.mV[1] = 0.f ;
- }
- else if(tc.mV[1] > 1.f)
- {
- tc.mV[1] = 1.f;
- }
+ case 0:
+ mVertexBuffer->getTexCoord0Strider(dst, mGeomIndex, mGeomCount, map_range);
break;
- case LLTexUnit::TAM_MIRROR:
- if(tc.mV[0] < 0.f)
- {
- tc.mV[0] = -tc.mV[0] ;
- }
- int_part = (S32)tc.mV[0] ;
- if(int_part & 1) //odd number
- {
- tc.mV[0] = int_part + 1 - tc.mV[0] ;
- }
- else //even number
+ case 1:
+ if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1))
{
- tc.mV[0] -= int_part ;
- }
+ mVertexBuffer->getTexCoord1Strider(dst, mGeomIndex, mGeomCount, map_range);
+ if (mat && !tex_anim)
+ {
+ r = mat->getNormalRotation();
+ mat->getNormalOffset(os, ot);
+ mat->getNormalRepeat(ms, mt);
- if(tc.mV[1] < 0.f)
- {
- tc.mV[1] = -tc.mV[1] ;
- }
- int_part = (S32)tc.mV[1] ;
- if(int_part & 1) //odd number
- {
- tc.mV[1] = int_part + 1 - tc.mV[1] ;
+ cos_ang = cos(r);
+ sin_ang = sin(r);
+
+ }
}
- else //even number
+ else
{
- tc.mV[1] -= int_part ;
+ continue;
}
break;
- case LLTexUnit::TAM_WRAP:
- if(tc.mV[0] > 1.f)
- tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ;
- else if(tc.mV[0] < -1.f)
- tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ;
-
- if(tc.mV[1] > 1.f)
- tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ;
- else if(tc.mV[1] < -1.f)
- tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ;
-
- if(tc.mV[0] < 0.f)
+ case 2:
+ if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2))
{
- tc.mV[0] = 1.0f + tc.mV[0] ;
+ mVertexBuffer->getTexCoord2Strider(dst, mGeomIndex, mGeomCount, map_range);
+ if (mat && !tex_anim)
+ {
+ r = mat->getSpecularRotation();
+ mat->getSpecularOffset(os, ot);
+ mat->getSpecularRepeat(ms, mt);
+
+ cos_ang = cos(r);
+ sin_ang = sin(r);
+ }
}
- if(tc.mV[1] < 0.f)
+ else
{
- tc.mV[1] = 1.0f + tc.mV[1] ;
+ continue;
}
break;
- default:
- break;
- }
-
- tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ;
- tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ;
}
+
+
+ for (S32 i = 0; i < num_vertices; i++)
+ {
+ LLVector2 tc(vf.mTexCoords[i]);
+
+ LLVector4a& norm = vf.mNormals[i];
+
+ LLVector4a& center = *(vf.mCenter);
+
+ if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
+ {
+ LLVector4a vec = vf.mPositions[i];
+ vec.mul(scalea);
- *tex_coords++ = tc;
- if (do_bump)
- {
- bump_tc.push_back(tc);
+ if (texgen == LLTextureEntry::TEX_GEN_PLANAR)
+ {
+ planarProjection(tc, norm, center, vec);
+ }
+ }
+
+ if (tex_mode && mTextureMatrix)
+ {
+ LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
+ tmp = tmp * *mTextureMatrix;
+ tc.mV[0] = tmp.mV[0];
+ tc.mV[1] = tmp.mV[1];
+ }
+ else
+ {
+ xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
+ }
+
+ *dst++ = tc;
+ if (do_bump)
+ {
+ bump_tc.push_back(tc);
+ }
}
}
@@ -1894,17 +1887,20 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
mVertexBuffer->flush();
}
- if (do_bump)
+ if (!mat && do_bump)
{
- mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, map_range);
+ mVertexBuffer->getTexCoord1Strider(tex_coords1, mGeomIndex, mGeomCount, map_range);
for (S32 i = 0; i < num_vertices; i++)
{
- LLVector4a tangent;
- tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]);
+ LLVector4a tangent = vf.mTangents[i];
+ LLVector4a binorm;
+ binorm.setCross3(vf.mNormals[i], tangent);
+ binorm.mul(tangent.getF32ptr()[3]);
+
LLMatrix4a tangent_to_object;
- tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]);
+ tangent_to_object.setRows(tangent, binorm, vf.mNormals[i]);
LLVector4a t;
tangent_to_object.rotate(binormal_dir, t);
LLVector4a binormal;
@@ -1920,10 +1916,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
binormal.normalize3fast();
+
LLVector2 tc = bump_tc[i];
tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() );
- *tex_coords2++ = tc;
+ *tex_coords1++ = tc;
}
if (map_range)
@@ -2006,7 +2003,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
LLFastTimer t(FTM_FACE_GEOM_NORMAL);
mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range);
F32* normals = (F32*) norm.get();
-
for (S32 i = 0; i < num_vertices; i++)
{
LLVector4a normal;
@@ -2022,19 +2018,27 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
}
- if (rebuild_binormal)
+ if (rebuild_tangent)
{
- LLFastTimer t(FTM_FACE_GEOM_BINORMAL);
- mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range);
- F32* binormals = (F32*) binorm.get();
-
+ LLFastTimer t(FTM_FACE_GEOM_TANGENT);
+ mVertexBuffer->getTangentStrider(tangent, mGeomIndex, mGeomCount, map_range);
+ F32* tangents = (F32*) tangent.get();
+
+ mVObjp->getVolume()->genTangents(f);
+
+ LLVector4Logical mask;
+ mask.clear();
+ mask.setElement<3>();
+
for (S32 i = 0; i < num_vertices; i++)
- {
- LLVector4a binormal;
- mat_normal.rotate(vf.mBinormals[i], binormal);
- binormal.normalize3fast();
- binormal.store4a(binormals);
- binormals += 4;
+ {
+ LLVector4a tangent_out;
+ mat_normal.rotate(vf.mTangents[i], tangent_out);
+ tangent_out.normalize3fast();
+ tangent_out.setSelectWithMask(mask, vf.mTangents[i], tangent_out);
+ tangent_out.store4a(tangents);
+
+ tangents += 4;
}
if (map_range)
@@ -2097,11 +2101,10 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
LLVector4a src;
- U32 glow32 = glow |
- (glow << 8) |
- (glow << 16) |
- (glow << 24);
+ LLColor4U glow4u = LLColor4U(0,0,0,glow);
+ U32 glow32 = glow4u.mAll;
+
U32 vec[4];
vec[0] = vec[1] = vec[2] = vec[3] = glow32;
@@ -2153,9 +2156,9 @@ BOOL LLFace::hasMedia() const
{
return TRUE ;
}
- if(mTexture.notNull())
+ if(mTexture[LLRender::DIFFUSE_MAP].notNull())
{
- return mTexture->hasParcelMedia() ; //if has a parcel media
+ return mTexture[LLRender::DIFFUSE_MAP]->hasParcelMedia() ; //if has a parcel media
}
return FALSE ; //no media.
@@ -2207,7 +2210,7 @@ F32 LLFace::getTextureVirtualSize()
face_area = LLFace::adjustPixelArea(mImportanceToCamera, face_area) ;
if(face_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping.
{
- if(mImportanceToCamera > LEAST_IMPORTANCE_FOR_LARGE_IMAGE && mTexture.notNull() && mTexture->isLargeImage())
+ if(mImportanceToCamera > LEAST_IMPORTANCE_FOR_LARGE_IMAGE && mTexture[LLRender::DIFFUSE_MAP].notNull() && mTexture[LLRender::DIFFUSE_MAP]->isLargeImage())
{
face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius );
}
@@ -2246,7 +2249,7 @@ BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
dist *= 16.f;
}
- lookAt.normalize3fast() ;
+ lookAt.normalize3fast();
//get area of circle around node
F32 app_angle = atanf((F32) sqrt(size_squared) / dist);
@@ -2574,159 +2577,13 @@ LLVector3 LLFace::getPositionAgent() const
}
}
-//
-//atlas
-//
-void LLFace::removeAtlas()
-{
- setAtlasInUse(FALSE) ;
- mAtlasInfop = NULL ;
-}
-
-const LLTextureAtlas* LLFace::getAtlas()const
-{
- if(mAtlasInfop)
- {
- return mAtlasInfop->getAtlas() ;
- }
- return NULL ;
-}
-
-const LLVector2* LLFace::getTexCoordOffset()const
-{
- if(isAtlasInUse())
- {
- return mAtlasInfop->getTexCoordOffset() ;
- }
- return NULL ;
-}
-const LLVector2* LLFace::getTexCoordScale() const
-{
- if(isAtlasInUse())
- {
- return mAtlasInfop->getTexCoordScale() ;
- }
- return NULL ;
-}
-
-BOOL LLFace::isAtlasInUse()const
-{
- return mUsingAtlas ;
-}
-
-BOOL LLFace::canUseAtlas()const
+LLViewerTexture* LLFace::getTexture(U32 ch) const
{
- //no drawable or no spatial group, do not use atlas
- if(!mDrawablep || !mDrawablep->getSpatialGroup())
- {
- return FALSE ;
- }
-
- //if bump face, do not use atlas
- if(getTextureEntry() && getTextureEntry()->getBumpmap())
- {
- return FALSE ;
- }
-
- //if animated texture, do not use atlas
- if(isState(TEXTURE_ANIM))
- {
- return FALSE ;
- }
+ llassert(ch < LLRender::NUM_TEXTURE_CHANNELS);
- return TRUE ;
-}
-
-void LLFace::setAtlasInUse(BOOL flag)
-{
- //no valid atlas to use.
- if(flag && (!mAtlasInfop || !mAtlasInfop->isValid()))
- {
- flag = FALSE ;
- }
-
- if(!flag && !mUsingAtlas)
- {
- return ;
- }
-
- //
- //at this stage (flag || mUsingAtlas) is always true.
- //
-
- //rebuild the tex coords
- if(mDrawablep)
- {
- gPipeline.markRebuild(mDrawablep, LLDrawable::REBUILD_TCOORD);
- mUsingAtlas = flag ;
- }
- else
- {
- mUsingAtlas = FALSE ;
- }
+ return mTexture[ch] ;
}
-LLTextureAtlasSlot* LLFace::getAtlasInfo()
-{
- return mAtlasInfop ;
-}
-
-void LLFace::setAtlasInfo(LLTextureAtlasSlot* atlasp)
-{
- if(mAtlasInfop != atlasp)
- {
- if(mAtlasInfop)
- {
- //llerrs << "Atlas slot changed!" << llendl ;
- }
- mAtlasInfop = atlasp ;
- }
-}
-
-LLViewerTexture* LLFace::getTexture() const
-{
- if(isAtlasInUse())
- {
- return (LLViewerTexture*)mAtlasInfop->getAtlas() ;
- }
-
- return mTexture ;
-}
-
-//switch to atlas or switch back to gl texture
-//return TRUE if using atlas.
-BOOL LLFace::switchTexture()
-{
- //no valid atlas or texture
- if(!mAtlasInfop || !mAtlasInfop->isValid() || !mTexture)
- {
- return FALSE ;
- }
-
- if(mTexture->getTexelsInAtlas() >= (U32)mVSize ||
- mTexture->getTexelsInAtlas() >= mTexture->getTexelsInGLTexture())
- {
- //switch to use atlas
- //atlas resolution is qualified, use it.
- if(!mUsingAtlas)
- {
- setAtlasInUse(TRUE) ;
- }
- }
- else //if atlas not qualified.
- {
- //switch back to GL texture
- if(mUsingAtlas && mTexture->isGLTextureCreated() &&
- mTexture->getDiscardLevel() < mTexture->getDiscardLevelInAtlas())
- {
- setAtlasInUse(FALSE) ;
- }
- }
-
- return mUsingAtlas ;
-}
-
-
void LLFace::setVertexBuffer(LLVertexBuffer* buffer)
{
mVertexBuffer = buffer;
@@ -2742,6 +2599,22 @@ void LLFace::clearVertexBuffer()
U32 LLFace::getRiggedDataMask(U32 type)
{
static const U32 rigged_data_mask[] = {
+ LLDrawPoolAvatar::RIGGED_MATERIAL_MASK,
+ LLDrawPoolAvatar::RIGGED_MATERIAL_ALPHA_VMASK,
+ LLDrawPoolAvatar::RIGGED_MATERIAL_ALPHA_MASK_MASK,
+ LLDrawPoolAvatar::RIGGED_MATERIAL_ALPHA_EMISSIVE_MASK,
+ LLDrawPoolAvatar::RIGGED_SPECMAP_VMASK,
+ LLDrawPoolAvatar::RIGGED_SPECMAP_BLEND_MASK,
+ LLDrawPoolAvatar::RIGGED_SPECMAP_MASK_MASK,
+ LLDrawPoolAvatar::RIGGED_SPECMAP_EMISSIVE_MASK,
+ LLDrawPoolAvatar::RIGGED_NORMMAP_VMASK,
+ LLDrawPoolAvatar::RIGGED_NORMMAP_BLEND_MASK,
+ LLDrawPoolAvatar::RIGGED_NORMMAP_MASK_MASK,
+ LLDrawPoolAvatar::RIGGED_NORMMAP_EMISSIVE_MASK,
+ LLDrawPoolAvatar::RIGGED_NORMSPEC_VMASK,
+ LLDrawPoolAvatar::RIGGED_NORMSPEC_BLEND_MASK,
+ LLDrawPoolAvatar::RIGGED_NORMSPEC_MASK_MASK,
+ LLDrawPoolAvatar::RIGGED_NORMSPEC_EMISSIVE_MASK,
LLDrawPoolAvatar::RIGGED_SIMPLE_MASK,
LLDrawPoolAvatar::RIGGED_FULLBRIGHT_MASK,
LLDrawPoolAvatar::RIGGED_SHINY_MASK,