diff options
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl | 21 | ||||
-rw-r--r-- | indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl | 6 | ||||
-rw-r--r-- | indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl | 6 | ||||
-rw-r--r-- | indra/newview/lldrawable.cpp | 47 | ||||
-rw-r--r-- | indra/newview/lldrawable.h | 2 | ||||
-rw-r--r-- | indra/newview/lldrawpoolbump.cpp | 27 | ||||
-rwxr-xr-x | indra/newview/llface.cpp | 48 | ||||
-rw-r--r-- | indra/newview/llface.h | 6 | ||||
-rw-r--r-- | indra/newview/llselectmgr.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llspatialpartition.cpp | 7 | ||||
-rw-r--r-- | indra/newview/llspatialpartition.h | 13 | ||||
-rw-r--r-- | indra/newview/llviewerobject.cpp | 175 | ||||
-rw-r--r-- | indra/newview/llviewerobject.h | 11 | ||||
-rw-r--r-- | indra/newview/llvovolume.cpp | 97 | ||||
-rw-r--r-- | indra/newview/llvovolume.h | 2 | ||||
-rw-r--r-- | indra/newview/pipeline.cpp | 25 |
16 files changed, 444 insertions, 51 deletions
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 23c4ea2fff..6e5cc69e39 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -31,6 +31,9 @@ out vec4 frag_data[3]; uniform sampler2D diffuseMap; uniform sampler2D bumpMap; +uniform sampler2D specularMap; +uniform float env_intensity; +uniform vec4 specular_color; VARYING vec3 vary_mat0; VARYING vec3 vary_mat1; @@ -42,15 +45,17 @@ VARYING vec2 vary_texcoord0; void main() { vec3 col = vertex_color.rgb * texture2D(diffuseMap, vary_texcoord0.xy).rgb; - vec3 norm = texture2D(bumpMap, vary_texcoord0.xy).rgb * 2.0 - 1.0; + vec4 spec = texture2D(specularMap, vary_texcoord0.xy); + vec4 norm = texture2D(bumpMap, vary_texcoord0.xy); + norm.xyz = norm.xyz * 2 - 1; - vec3 tnorm = vec3(dot(norm,vary_mat0), - dot(norm,vary_mat1), - dot(norm,vary_mat2)); - - frag_data[0] = vec4(col, 0.0); - frag_data[1] = vertex_color.aaaa; // spec + vec3 tnorm = vec3(dot(norm.xyz,vary_mat0), + dot(norm.xyz,vary_mat1), + dot(norm.xyz,vary_mat2)); + + frag_data[0] = vec4(col * (1 - spec.a * env_intensity), 0); + frag_data[1] = vec4(spec.xyz * specular_color.xyz, specular_color.a * norm.a); // spec //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested vec3 nvn = normalize(tnorm); - frag_data[2] = vec4(nvn.xyz * 0.5 + 0.5, 0.0); + frag_data[2] = vec4(nvn.xyz * 0.5 + 0.5, spec.a * env_intensity); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 87cdf1026f..2ec3fe4a52 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -280,8 +280,8 @@ void main() vec2 tc = vary_fragcoord.xy; float depth = texture2DRect(depthMap, tc.xy).r; vec3 pos = getPosition_d(tc, depth).xyz; - vec3 norm = texture2DRect(normalMap, tc).xyz; - norm = (norm.xyz-0.5)*2.0; // unpack norm + vec4 norm = texture2DRect(normalMap, tc); + norm.xyz = (norm.xyz-0.5)*2.0; // unpack norm float da = max(dot(norm.xyz, sun_dir.xyz), 0.0); @@ -315,7 +315,7 @@ void main() //add environmentmap vec3 env_vec = env_mat * refnormpersp; col = mix(col.rgb, samplesRGB(textureCube(environmentMap, env_vec).rgb) * 2.2, - max(spec.a-diffuse.a*2.0, 0.0)); + max(norm.a-diffuse.a*2.0, 0.0)); } col = atmosLighting(col); diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index bf4c476138..e95991a635 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -283,8 +283,8 @@ void main() vec2 tc = vary_fragcoord.xy; float depth = texture2DRect(depthMap, tc.xy).r; vec3 pos = getPosition_d(tc, depth).xyz; - vec3 norm = texture2DRect(normalMap, tc).xyz; - norm = (norm.xyz-0.5)*2.0; // unpack norm + vec4 norm = texture2DRect(normalMap, tc); + norm.xyz = (norm.xyz-0.5)*2.0; // unpack norm float da = max(dot(norm.xyz, sun_dir.xyz), 0.0); @@ -324,7 +324,7 @@ void main() //add environmentmap vec3 env_vec = env_mat * refnormpersp; col = mix(col.rgb, samplesRGB(textureCube(environmentMap, env_vec).rgb) * 2.2, - max(spec.a-diffuse.a*2.0, 0.0)); + max(norm.a-diffuse.a*2.0, 0.0)); } col = atmosLighting(col); diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 4894d63e13..1ca2344c41 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -300,6 +300,53 @@ LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep) } +LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep, LLViewerTexture *normalp) +{ + LLMemType mt(LLMemType::MTYPE_DRAWABLE); + + LLFace *face; + face = new LLFace(this, mVObjp); + + face->setTEOffset(mFaces.size()); + face->setTexture(texturep); + face->setNormalMap(normalp); + face->setPoolType(gPipeline.getPoolTypeFromTE(te, texturep)); + + mFaces.push_back(face); + + if (isState(UNLIT)) + { + face->setState(LLFace::FULLBRIGHT); + } + + return face; + +} + +LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep, LLViewerTexture *normalp, LLViewerTexture *specularp) +{ + LLMemType mt(LLMemType::MTYPE_DRAWABLE); + + LLFace *face; + face = new LLFace(this, mVObjp); + + face->setTEOffset(mFaces.size()); + face->setTexture(texturep); + face->setNormalMap(normalp); + face->setSpecularMap(specularp); + face->setPoolType(gPipeline.getPoolTypeFromTE(te, texturep)); + + mFaces.push_back(face); + + if (isState(UNLIT)) + { + face->setState(LLFace::FULLBRIGHT); + } + + return face; + +} + void LLDrawable::setNumFaces(const S32 newFaces, LLFacePool *poolp, LLViewerTexture *texturep) { if (newFaces == (S32)mFaces.size()) diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index b1e32bdb5b..13089f4f26 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -147,6 +147,8 @@ public: //void removeFace(const S32 i); // SJB: Avoid using this, it's slow LLFace* addFace(LLFacePool *poolp, LLViewerTexture *texturep); LLFace* addFace(const LLTextureEntry *te, LLViewerTexture *texturep); + LLFace* addFace(const LLTextureEntry *te, LLViewerTexture *texturep, LLViewerTexture *normalp); + LLFace* addFace(const LLTextureEntry *te, LLViewerTexture *texturep, LLViewerTexture *normalp, LLViewerTexture *specularp); void deleteFaces(S32 offset, S32 count); void setNumFaces(const S32 numFaces, LLFacePool *poolp, LLViewerTexture *texturep); void setNumFacesFast(const S32 numFaces, LLFacePool *poolp, LLViewerTexture *texturep); diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 718133ba29..07384a136a 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -72,7 +72,7 @@ static LLGLSLShader* shader = NULL; static S32 cube_channel = -1; static S32 diffuse_channel = -1; static S32 bump_channel = -1; - +static S32 spec_channel = -1; // static void LLStandardBumpmap::init() { @@ -632,6 +632,11 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) { U8 bump_code = params.mBump; + if (params.mNormalMap.notNull()) + { + bump_code = 99; + return bindBumpMap(bump_code, params.mNormalMap, params.mVSize, channel); + } return bindBumpMap(bump_code, params.mTexture, params.mVSize, channel); } @@ -670,7 +675,10 @@ BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsi case BE_DARKNESS: bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code ); break; - + case 99: + bump = tex; + bump->addTextureStats(vsize); + break; default: if( bump_code < LLStandardBumpmap::sStandardBumpmapCount ) { @@ -820,6 +828,7 @@ void LLDrawPoolBump::beginDeferredPass(S32 pass) gDeferredBumpProgram.bind(); diffuse_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); bump_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::BUMP_MAP); + spec_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::SPECULAR_MAP); gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(bump_channel)->unbind(LLTexUnit::TT_TEXTURE); } @@ -834,6 +843,7 @@ void LLDrawPoolBump::endDeferredPass(S32 pass) mShiny = FALSE; gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::BUMP_MAP); + gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::SPECULAR_MAP); gDeferredBumpProgram.unbind(); gGL.getTexUnit(0)->activate(); } @@ -855,7 +865,18 @@ void LLDrawPoolBump::renderDeferred(S32 pass) for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) { LLDrawInfo& params = **i; - + + gDeferredBumpProgram.uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]); + gDeferredBumpProgram.uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity); + + if (params.mSpecularMap) + { + params.mSpecularMap->addTextureStats(params.mVSize); + gGL.getTexUnit(spec_channel)->bind(params.mSpecularMap); + } else { + gGL.getTexUnit(spec_channel)->bind(LLViewerFetchedTexture::sWhiteImagep); + } + LLDrawPoolBump::bindBumpMap(params, bump_channel); pushBatch(params, mask, TRUE); } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 605cb81c10..cd84815295 100755 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -316,6 +316,48 @@ void LLFace::setTexture(LLViewerTexture* tex) mTexture = tex ; } +void LLFace::setNormalMap(LLViewerTexture* tex) +{ + if(mNormalMap == tex) + { + return ; + } + + if(mNormalMap.notNull()) + { + mNormalMap->removeFace(this) ; + removeAtlas() ; + } + + if(tex) + { + tex->addFace(this) ; + } + + mNormalMap = tex ; +} + +void LLFace::setSpecularMap(LLViewerTexture* tex) +{ + if(mSpecMap == tex) + { + return ; + } + + if(mSpecMap.notNull()) + { + mSpecMap->removeFace(this) ; + removeAtlas() ; + } + + if(tex) + { + tex->addFace(this) ; + } + + mSpecMap = tex ; +} + void LLFace::dirtyTexture() { LLDrawable* drawablep = getDrawable(); @@ -2035,9 +2077,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLFastTimer t(FTM_FACE_GEOM_BINORMAL); mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range); F32* binormals = (F32*) binorm.get(); - + + mVObjp->getVolume()->genBinormals(f); + for (S32 i = 0; i < num_vertices; i++) - { + { LLVector4a binormal; mat_normal.rotate(vf.mBinormals[i], binormal); binormal.normalize3fast(); diff --git a/indra/newview/llface.h b/indra/newview/llface.h index de4d03351c..cb76c6e8a6 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -111,6 +111,8 @@ public: void setTextureIndex(U8 index); U8 getTextureIndex() const { return mTextureIndex; } void setTexture(LLViewerTexture* tex) ; + void setNormalMap(LLViewerTexture* tex); + void setSpecularMap(LLViewerTexture* tex); void switchTexture(LLViewerTexture* new_texture); void dirtyTexture(); LLXformMatrix* getXform() const { return mXform; } @@ -266,6 +268,8 @@ public: F32 mLastSkinTime; F32 mLastMoveTime; LLMatrix4* mTextureMatrix; + LLMatrix4* mSpecMapMatrix; + LLMatrix4* mNormalMapMatrix; LLDrawInfo* mDrawInfo; private: @@ -285,6 +289,8 @@ private: LLXformMatrix* mXform; LLPointer<LLViewerTexture> mTexture; + LLPointer<LLViewerTexture> mSpecMap; + LLPointer<LLViewerTexture> mNormalMap; LLPointer<LLDrawable> mDrawablep; LLPointer<LLViewerObject> mVObjp; S32 mTEOffset; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 9f9e39527f..b5dc1dae90 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1928,7 +1928,7 @@ void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data) llassert(mMediaData.isMap()); const LLTextureEntry *texture_entry = object->getTE(te); if (!mMediaData.isMap() || - (NULL != texture_entry) && !texture_entry->hasMedia() && !mMediaData.has(LLMediaEntry::HOME_URL_KEY)) + ((NULL != texture_entry) && !texture_entry->hasMedia() && !mMediaData.has(LLMediaEntry::HOME_URL_KEY))) { // skip adding/updating media } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 2083afdcf5..8a62f22985 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -4672,7 +4672,12 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, mGroup(NULL), mFace(NULL), mDistance(0.f), - mDrawMode(LLRender::TRIANGLES) + mDrawMode(LLRender::TRIANGLES), + mSpecColor(1.0f, 1.0f, 1.0f, 0.5f), + mEnvIntensity(0.0f), + mAlphaMaskCutoff(0.5f), + mDiffuseAlphaMode(0), + mMaterialID(NULL) { mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index b1706d9d35..a71ca60d85 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -119,6 +119,17 @@ public: LL_ALIGN_16(LLFace* mFace); //associated face F32 mDistance; U32 mDrawMode; + + const LLMaterialID *mMaterialID; // If this is false, the following parameters are unused. + LLPointer<LLViewerTexture> mSpecularMap; + const LLMatrix4* mSpecularMapMatrix; + LLPointer<LLViewerTexture> mNormalMap; + const LLMatrix4* mNormalMapMatrix; + LLVector4 mSpecColor; // XYZ = Specular RGB, W = Specular Exponent + F32 mEnvIntensity; + F32 mAlphaMaskCutoff; + U8 mDiffuseAlphaMode; + struct CompareTexture { @@ -169,7 +180,7 @@ public: } }; - + struct CompareBump { bool operator()(const LLPointer<LLDrawInfo>& lhs, const LLPointer<LLDrawInfo>& rhs) diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 347d82d492..b8de345a9a 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -202,6 +202,8 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mTotalCRC(0), mListIndex(-1), mTEImages(NULL), + mTENormalMaps(NULL), + mTESpecularMaps(NULL), mGLName(0), mbCanSelect(TRUE), mFlags(0), @@ -322,6 +324,18 @@ void LLViewerObject::deleteTEImages() { delete[] mTEImages; mTEImages = NULL; + + if (mTENormalMaps != NULL) + { + delete[] mTENormalMaps; + mTENormalMaps = NULL; + } + + if (mTESpecularMaps != NULL) + { + delete[] mTESpecularMaps; + mTESpecularMaps = NULL; + } } void LLViewerObject::markDead() @@ -3935,25 +3949,39 @@ void LLViewerObject::setNumTEs(const U8 num_tes) { LLPointer<LLViewerTexture> *new_images; new_images = new LLPointer<LLViewerTexture>[num_tes]; + + LLPointer<LLViewerTexture> *new_normmaps; + new_normmaps = new LLPointer<LLViewerTexture>[num_tes]; + + LLPointer<LLViewerTexture> *new_specmaps; + new_specmaps = new LLPointer<LLViewerTexture>[num_tes]; for (i = 0; i < num_tes; i++) { if (i < getNumTEs()) { new_images[i] = mTEImages[i]; + new_normmaps[i] = mTENormalMaps[i]; + new_specmaps[i] = mTESpecularMaps[i]; } else if (getNumTEs()) { new_images[i] = mTEImages[getNumTEs()-1]; + new_normmaps[i] = mTENormalMaps[i]; + new_specmaps[i] = mTESpecularMaps[i]; } else { new_images[i] = NULL; + new_normmaps[i] = NULL; + new_specmaps[i] = NULL; } } deleteTEImages(); mTEImages = new_images; + mTENormalMaps = new_normmaps; + mTESpecularMaps = new_specmaps; } else { @@ -4032,12 +4060,18 @@ void LLViewerObject::sendTEUpdate() const void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry) { LLPrimitive::setTE(te, texture_entry); -// This doesn't work, don't get any textures. -// if (mDrawable.notNull() && mDrawable->isVisible()) -// { - const LLUUID& image_id = getTE(te)->getID(); - mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); -// } + + const LLUUID& image_id = getTE(te)->getID(); + mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + + if (getTE(te)->getMaterialParams() != NULL) + { + const LLUUID& norm_id = getTE(te)->getMaterialParams()->getNormalID(); + mTENormalMaps[te] = LLViewerTextureManager::getFetchedTexture(norm_id, TRUE, LLViewerTexture::BOOST_BUMP, LLViewerTexture::LOD_TEXTURE); + + const LLUUID& spec_id = getTE(te)->getMaterialParams()->getSpecularID(); + mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } } void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep) @@ -4072,6 +4106,42 @@ S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost hos return retval; } +S32 LLViewerObject::setTENormalMapCore(const U8 te, const LLUUID& uuid, LLHost host) +{ + S32 retval = 0; + //if (uuid != getTE(te)->getMaterialParams()->getNormalID() || + // uuid == LLUUID::null) + { + retval = TEM_CHANGE_TEXTURE; + getTE(te)->getMaterialParams()->setNormalID(uuid); + mTENormalMaps[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, LLViewerTexture::BOOST_BUMP, LLViewerTexture::LOD_TEXTURE, 0, 0, host); + setChanged(TEXTURE); + if (mDrawable.notNull()) + { + gPipeline.markTextured(mDrawable); + } + } + return retval; +} + +S32 LLViewerObject::setTESpecularMapCore(const U8 te, const LLUUID& uuid, LLHost host) +{ + S32 retval = 0; + //if (uuid != getTE(te)->getMaterialParams()->getSpecularID() || + // uuid == LLUUID::null) + { + retval = TEM_CHANGE_TEXTURE; + getTE(te)->getMaterialParams()->setSpecularID(uuid); + mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); + setChanged(TEXTURE); + if (mDrawable.notNull()) + { + gPipeline.markTextured(mDrawable); + } + } + return retval; +} + //virtual void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image) { @@ -4082,12 +4152,39 @@ void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image) mTEImages[index] = new_image ; } +void LLViewerObject::changeTENormalMap(S32 index, LLViewerTexture* new_image) +{ + if(index < 0 || index >= getNumTEs()) + { + return ; + } + mTENormalMaps[index] = new_image ; +} + +void LLViewerObject::changeTESpecularMap(S32 index, LLViewerTexture* new_image) +{ + if(index < 0 || index >= getNumTEs()) + { + return ; + } + mTESpecularMaps[index] = new_image ; +} + S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid) { // Invalid host == get from the agent's sim return setTETextureCore(te, uuid, LLHost::invalid); } +S32 LLViewerObject::setTENormalMap(const U8 te, const LLUUID& uuid) +{ + return setTENormalMapCore(te, uuid, LLHost::invalid); +} + +S32 LLViewerObject::setTESpecularMap(const U8 te, const LLUUID& uuid) +{ + return setTESpecularMapCore(te, uuid, LLHost::invalid); +} S32 LLViewerObject::setTEColor(const U8 te, const LLColor3& color) { @@ -4268,6 +4365,28 @@ S32 LLViewerObject::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID return retval; } +S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) +{ + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; + } + else if (pMaterialParams != tep->getMaterialParams()) + { + retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams); + setTENormalMap(te, tep->getMaterialParams()->getNormalID()); + setTESpecularMap(te, tep->getMaterialParams()->getSpecularID()); + setChanged(TEXTURE); + if (mDrawable.notNull() && retval) + { + gPipeline.markTextured(mDrawable); + } + } + return retval; +} + S32 LLViewerObject::setTEScale(const U8 te, const F32 s, const F32 t) { @@ -4369,6 +4488,50 @@ LLViewerTexture *LLViewerObject::getTEImage(const U8 face) const } +LLViewerTexture *LLViewerObject::getTENormalMap(const U8 face) const +{ + // llassert(mTEImages); + + if (face < getNumTEs()) + { + LLViewerTexture* image = mTENormalMaps[face]; + if (image) + { + return image; + } + else + { + return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep); + } + } + + llerrs << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << llendl; + + return NULL; +} + +LLViewerTexture *LLViewerObject::getTESpecularMap(const U8 face) const +{ + // llassert(mTEImages); + + if (face < getNumTEs()) + { + LLViewerTexture* image = mTESpecularMaps[face]; + if (image) + { + return image; + } + else + { + return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep); + } + } + + llerrs << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << llendl; + + return NULL; +} + void LLViewerObject::fitFaceTexture(const U8 face) { llinfos << "fitFaceTexture not implemented" << llendl; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 255d0cd080..26160d14b3 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -292,7 +292,11 @@ public: /*virtual*/ void setNumTEs(const U8 num_tes); /*virtual*/ void setTE(const U8 te, const LLTextureEntry &texture_entry); /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid); + /*virtual*/ S32 setTENormalMap(const U8 te, const LLUUID &uuid); + /*virtual*/ S32 setTESpecularMap(const U8 te, const LLUUID &uuid); S32 setTETextureCore(const U8 te, const LLUUID& uuid, LLHost host); + S32 setTENormalMapCore(const U8 te, const LLUUID& uuid, LLHost host); + S32 setTESpecularMapCore(const U8 te, const LLUUID& uuid, LLHost host); /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color); /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color); /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t); @@ -310,10 +314,15 @@ public: /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags ); /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); + /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams); /*virtual*/ BOOL setMaterial(const U8 material); virtual void setTEImage(const U8 te, LLViewerTexture *imagep); // Not derived from LLPrimitive virtual void changeTEImage(S32 index, LLViewerTexture* new_image) ; + virtual void changeTENormalMap(S32 index, LLViewerTexture* new_image) ; + virtual void changeTESpecularMap(S32 index, LLViewerTexture* new_image) ; LLViewerTexture *getTEImage(const U8 te) const; + LLViewerTexture *getTENormalMap(const U8 te) const; + LLViewerTexture *getTESpecularMap(const U8 te) const; void fitFaceTexture(const U8 face); void sendTEUpdate() const; // Sends packed representation of all texture entry information @@ -588,6 +597,8 @@ public: S32 mListIndex; LLPointer<LLViewerTexture> *mTEImages; + LLPointer<LLViewerTexture> *mTENormalMaps; + LLPointer<LLViewerTexture> *mTESpecularMaps; // Selection, picking and rendering variables U32 mGLName; // GL "name" used by selection code diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index a37dea4a60..6c073a8e20 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -77,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; @@ -919,6 +920,12 @@ LLFace* LLVOVolume::addFace(S32 f) { const LLTextureEntry* te = getTE(f); LLViewerTexture* imagep = getTEImage(f); + if (te->getMaterialParams() != NULL) + { + LLViewerTexture* normalp = getTENormalMap(f); + LLViewerTexture* specularp = getTESpecularMap(f); + return mDrawable->addFace(te, imagep, normalp, specularp); + } return mDrawable->addFace(te, imagep); } @@ -1404,6 +1411,11 @@ void LLVOVolume::regenFaces() facep->setTEOffset(i); facep->setTexture(getTEImage(i)); + if (facep->getTextureEntry()->getMaterialParams() != NULL) + { + 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. @@ -1977,15 +1989,47 @@ S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow) return res; } +void LLVOVolume::setTEMaterialParamsCallback(const LLMaterialID &pMaterialID, const LLMaterialPtr pMaterialParams) +{ + for (U8 i = 0; i < getNumTEs(); i++) + { + if (getTE(i)->getMaterialID() == pMaterialID) + { + LL_INFOS("Materials") << "Material params callback triggered!" << LL_ENDL; + setTEMaterialParams(i, pMaterialParams); + } + } +} + S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) { - S32 res = LLViewerObject::setTEMaterialID(te, pMaterialID); + if (!pMaterialID.isNull()) + { + LL_INFOS("Materials") << "Oh god it's a material! " << pMaterialID.asString() << LL_ENDL; + S32 res = LLViewerObject::setTEMaterialID(te, pMaterialID); + if (res) + { + LL_INFOS("Materials") << "We have a material!" << LL_ENDL; + LLMaterialMgr::instance().get(getRegion()->getRegionID(), pMaterialID, boost::bind(&LLVOVolume::setTEMaterialParamsCallback, this, _1, _2)); + //setTEMaterialParams(te, pMatParam); + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; + } + return 0; +} + +S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) +{ + S32 res = LLViewerObject::setTEMaterialParams(te, pMaterialParams); if (res) { gPipeline.markTextured(mDrawable); mFaceMappingChanged = TRUE; } - return res; + + return res; } S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t) @@ -4050,6 +4094,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, LLViewerTexture* tex = facep->getTexture(); U8 index = facep->getTextureIndex(); + + const LLMaterialID* matid = &facep->getTextureEntry()->getMaterialID(); bool batchable = false; @@ -4084,7 +4130,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_vec[idx]->mFullbright == fullbright && draw_vec[idx]->mBump == bump && draw_vec[idx]->mTextureMatrix == tex_mat && - draw_vec[idx]->mModelMatrix == model_mat) + draw_vec[idx]->mModelMatrix == model_mat && + draw_vec[idx]->mMaterialID == matid) { draw_vec[idx]->mCount += facep->getIndicesCount(); draw_vec[idx]->mEnd += facep->getGeomCount(); @@ -4106,12 +4153,46 @@ 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; + if (!facep->getTextureEntry()->getMaterialID().isNull()) + { + + if (facep->getTextureEntry()->getMaterialParams() != NULL) + { + // We have a material. Update our draw info accordingly. + draw_info->mMaterialID = &facep->getTextureEntry()->getMaterialID(); + LLVector4 specColor; + specColor.mV[0] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightColor().mV[0] * (1.0 / 255); + specColor.mV[1] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightColor().mV[1] * (1.0 / 255); + specColor.mV[2] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightColor().mV[2] * (1.0 / 255); + specColor.mV[3] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightExponent() * (1.0 / 255); + draw_info->mSpecColor = specColor; + draw_info->mEnvIntensity = facep->getTextureEntry()->getMaterialParams()->getEnvironmentIntensity() * (1.0 / 255); + draw_info->mAlphaMaskCutoff = facep->getTextureEntry()->getMaterialParams()->getAlphaMaskCutoff() * (1.0 / 255); + draw_info->mDiffuseAlphaMode = facep->getTextureEntry()->getMaterialParams()->getDiffuseAlphaMode(); + draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTextureIndex()); + draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTextureIndex()); + } + } else { + U8 shiny = facep->getTextureEntry()->getShiny(); + float alpha[4] = + { + 0.00f, + 0.25f, + 0.5f, + 0.75f + }; + float spec = alpha[shiny]; + LLVector4 specColor(spec, spec, spec, spec); + draw_info->mSpecColor = specColor; + draw_info->mEnvIntensity = spec; + } + if (type == LLRenderPass::PASS_ALPHA) { //for alpha sorting facep->setDrawInfo(draw_info); @@ -4267,7 +4348,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } if (vobj->isMesh() && - (vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled())) + ((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) { continue; } @@ -4563,7 +4644,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (gPipeline.canUseWindLightShadersOnObjects() && LLPipeline::sRenderBump) { - if (te->getBumpmap()) + if (te->getBumpmap() || te->getMaterialParams() != NULL) { //needs normal + binormal bump_faces.push_back(facep); } @@ -5134,7 +5215,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); } } - else if (te->getBumpmap()) + else if (te->getBumpmap() || te->getMaterialParams() != NULL) { //register in deferred bump pass registerFace(group, facep, LLRenderPass::PASS_BUMP); } @@ -5169,7 +5250,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } else { - if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) + if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && (te->getBumpmap() || te->getMaterialParams())) { //non-shiny or fullbright deferred bump registerFace(group, facep, LLRenderPass::PASS_BUMP); } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index ff6dca9737..d1bfefdc70 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -187,6 +187,8 @@ public: /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags); /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); + void setTEMaterialParamsCallback(const LLMaterialID& pMaterialID, const LLMaterialPtr pMaterialParams); + /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams); /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t); /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s); /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 07246391e3..ea7de6f399 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1262,31 +1262,26 @@ void LLPipeline::createLUTBuffers() U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); F32* ls = new F32[lightResX*lightResY]; //F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); // Note: only use this when creating new specular lighting functions. - // Calculate the (normalized) Gaussian specular lookup texture. (with a few tweaks) + // Calculate the (normalized) blinn-phong specular lookup texture. (with a few tweaks) for (U32 y = 0; y < lightResY; ++y) { for (U32 x = 0; x < lightResX; ++x) { ls[y*lightResX+x] = 0; F32 sa = (F32) x/(lightResX-1); - F32 spec = (F32) y/(lightResY); - F32 n = spec; + F32 spec = (F32) y/(lightResY-1); + F32 n = spec * spec * 368; - float angleNormalHalf = acosf(sa); - float exponent = angleNormalHalf / ((1 - n)); - exponent = -(exponent * exponent); - spec = expf(exponent); + // Nothing special here. Just your typical blinn-phong term. + spec = powf(sa, n); // Apply our normalization function. - // This is based around the phong normalization function, trading n+2 for n+1 instead. - // Since we're using a gaussian model here, we actually don't really need as large of an exponent as blinn-phong shading. - // Instead, we assume that the correct exponent is 8 here. - // This was achieved through much tweaking to find a decent "middleground" with our specular highlights with the gaussian term. - // Bigger highlights don't look too soft, smaller highlights don't look too bright, and everything in the middle seems to have a well maintained highlight curvature. - // There isn't really much theory behind this one. This was done purely to produce a nice and mostly customizable BRDF. - - spec = lerpf(spec, spec * (n * 8 + 1) / 4.5, n); + // Note: This is the full equation that applies the full normalization curve, not an approximation. + // This is fine, given we only need to create our LUT once per buffer initialization. + spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n))); + // Since we use R16F, we no longer have a dynamic range issue we need to work around here. + // Though some older drivers may not like this, newer drivers shouldn't have this problem. ls[y*lightResX+x] = spec; } } |