diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 26767841a..0df12e38d 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -166,7 +166,8 @@ void calc_tangent_from_triangle( F32 rd = s1*t2-s2*t1; - float r = ((rd*rd) > FLT_EPSILON) ? 1.0F / rd : 1024.f; //some made up large ratio for division by zero + float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) + : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero llassert(llfinite(r)); llassert(!llisnan(r)); @@ -6801,7 +6802,8 @@ void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVe F32 rd = s1*t2-s2*t1; - float r = ((rd*rd) > FLT_EPSILON) ? 1.0F / rd : 1024.f; //some made up large ratio for division by zero + float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) + : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero llassert(llfinite(r)); llassert(!llisnan(r)); diff --git a/indra/llmessage/llpartdata.cpp b/indra/llmessage/llpartdata.cpp index de369dc3c..41a0310ce 100644 --- a/indra/llmessage/llpartdata.cpp +++ b/indra/llmessage/llpartdata.cpp @@ -37,53 +37,46 @@ -const S32 PS_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; // 18 -const S32 PS_DATA_BLOCK_SIZE = 68 + PS_PART_DATA_BLOCK_SIZE; // 68 + 18 = 86 +const S32 PS_PART_DATA_GLOW_SIZE = 2; +const S32 PS_PART_DATA_BLEND_SIZE = 2; +const S32 PS_LEGACY_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; //18 +const S32 PS_SYS_DATA_BLOCK_SIZE = 68; +const S32 PS_MAX_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE+ + PS_LEGACY_PART_DATA_BLOCK_SIZE + + PS_PART_DATA_BLEND_SIZE + + PS_PART_DATA_GLOW_SIZE+ + 8; //two S32 size fields + +const S32 PS_LEGACY_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE + PS_LEGACY_PART_DATA_BLOCK_SIZE; + + +const U32 PART_DATA_MASK = LLPartData::LL_PART_DATA_GLOW | LLPartData::LL_PART_DATA_BLEND; + const F32 MAX_PART_SCALE = 4.f; -BOOL LLPartData::pack(LLDataPacker &dp) +bool LLPartData::hasGlow() const { - LLColor4U coloru; - dp.packU32(mFlags, "pdflags"); - dp.packFixed(mMaxAge, "pdmaxage", FALSE, 8, 8); - coloru.setVec(mStartColor); - dp.packColor4U(coloru, "pdstartcolor"); - coloru.setVec(mEndColor); - dp.packColor4U(coloru, "pdendcolor"); - dp.packFixed(mStartScale.mV[0], "pdstartscalex", FALSE, 3, 5); - dp.packFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5); - dp.packFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5); - dp.packFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5); - return TRUE; + return mStartGlow > 0.f || mEndGlow > 0.f; } -LLSD LLPartData::asLLSD() const +bool LLPartData::hasBlendFunc() const { - LLSD sd = LLSD(); - sd["pdflags"] = ll_sd_from_U32(mFlags); - sd["pdmaxage"] = mMaxAge; - sd["pdstartcolor"] = ll_sd_from_color4(mStartColor); - sd["pdendcolor"] = ll_sd_from_color4(mEndColor); - sd["pdstartscale"] = ll_sd_from_vector2(mStartScale); - sd["pdendscale"] = ll_sd_from_vector2(mEndScale); - return sd; + return mBlendFuncSource != LLPartData::LL_PART_BF_SOURCE_ALPHA || mBlendFuncDest != LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; } -bool LLPartData::fromLLSD(LLSD& sd) +S32 LLPartData::getSize() const { - mFlags = ll_U32_from_sd(sd["pdflags"]); - mMaxAge = (F32)sd["pdmaxage"].asReal(); - mStartColor = ll_color4_from_sd(sd["pdstartcolor"]); - mEndColor = ll_color4_from_sd(sd["pdendcolor"]); - mStartScale = ll_vector2_from_sd(sd["pdstartscale"]); - mEndScale = ll_vector2_from_sd(sd["pdendscale"]); - return true; + S32 size = PS_LEGACY_PART_DATA_BLOCK_SIZE; + if (hasGlow()) size += PS_PART_DATA_GLOW_SIZE; + if (hasBlendFunc()) size += PS_PART_DATA_BLEND_SIZE; + + return size; } -BOOL LLPartData::unpack(LLDataPacker &dp) +BOOL LLPartData::unpackLegacy(LLDataPacker &dp) { LLColor4U coloru; @@ -98,9 +91,70 @@ BOOL LLPartData::unpack(LLDataPacker &dp) dp.unpackFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5); dp.unpackFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5); dp.unpackFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5); + + mStartGlow = 0.f; + mEndGlow = 0.f; + mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA; + mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; + return TRUE; } +BOOL LLPartData::unpack(LLDataPacker &dp) +{ + S32 size = 0; + dp.unpackS32(size, "partsize"); + + unpackLegacy(dp); + size -= PS_LEGACY_PART_DATA_BLOCK_SIZE; + + if (mFlags & LL_PART_DATA_GLOW) + { + if (size < PS_PART_DATA_GLOW_SIZE) return FALSE; + + U8 tmp_glow = 0; + dp.unpackU8(tmp_glow,"pdstartglow"); + mStartGlow = tmp_glow / 255.f; + dp.unpackU8(tmp_glow,"pdendglow"); + mEndGlow = tmp_glow / 255.f; + + size -= PS_PART_DATA_GLOW_SIZE; + } + else + { + mStartGlow = 0.f; + mEndGlow = 0.f; + } + + if (mFlags & LL_PART_DATA_BLEND) + { + if (size < PS_PART_DATA_BLEND_SIZE) return FALSE; + dp.unpackU8(mBlendFuncSource,"pdblendsource"); + dp.unpackU8(mBlendFuncDest,"pdblenddest"); + size -= PS_PART_DATA_BLEND_SIZE; + } + else + { + mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA; + mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; + } + + if (size > 0) + { //leftover bytes, unrecognized parameters + U8 feh = 0; + while (size > 0) + { //read remaining bytes in block + dp.unpackU8(feh, "whippang"); + size--; + } + + //this particle system won't display properly, better to not show anything + return FALSE; + } + + + return TRUE; +} void LLPartData::setFlags(const U32 flags) { @@ -148,6 +202,18 @@ void LLPartData::setEndAlpha(const F32 alpha) mEndColor.mV[3] = alpha; } +// static +bool LLPartData::validBlendFunc(S32 func) +{ + if (func >= 0 + && func < LL_PART_BF_COUNT + && func != UNSUPPORTED_DEST_ALPHA + && func != UNSUPPORTED_ONE_MINUS_DEST_ALPHA) + { + return true; + } + return false; +} LLPartSysData::LLPartSysData() { @@ -160,6 +226,10 @@ LLPartSysData::LLPartSysData() mPartData.mStartScale = LLVector2(1.f, 1.f); mPartData.mEndScale = LLVector2(1.f, 1.f); mPartData.mMaxAge = 10.0; + mPartData.mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA; + mPartData.mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; + mPartData.mStartGlow = 0.f; + mPartData.mEndGlow = 0.f; mMaxAge = 0.0; mStartAge = 0.0; @@ -175,38 +245,7 @@ LLPartSysData::LLPartSysData() mNumParticles = 0; } - -BOOL LLPartSysData::pack(LLDataPacker &dp) -{ - dp.packU32(mCRC, "pscrc"); - dp.packU32(mFlags, "psflags"); - dp.packU8(mPattern, "pspattern"); - dp.packFixed(mMaxAge, "psmaxage", FALSE, 8, 8); - dp.packFixed(mStartAge, "psstartage", FALSE, 8, 8); - dp.packFixed(mInnerAngle, "psinnerangle", FALSE, 3, 5); - dp.packFixed(mOuterAngle, "psouterangle", FALSE, 3, 5); - dp.packFixed(mBurstRate, "psburstrate", FALSE, 8, 8); - dp.packFixed(mBurstRadius, "psburstradius", FALSE, 8, 8); - dp.packFixed(mBurstSpeedMin, "psburstspeedmin", FALSE, 8, 8); - dp.packFixed(mBurstSpeedMax, "psburstspeedmax", FALSE, 8, 8); - dp.packU8(mBurstPartCount, "psburstpartcount"); - - dp.packFixed(mAngularVelocity.mV[0], "psangvelx", TRUE, 8, 7); - dp.packFixed(mAngularVelocity.mV[1], "psangvely", TRUE, 8, 7); - dp.packFixed(mAngularVelocity.mV[2], "psangvelz", TRUE, 8, 7); - - dp.packFixed(mPartAccel.mV[0], "psaccelx", TRUE, 8, 7); - dp.packFixed(mPartAccel.mV[1], "psaccely", TRUE, 8, 7); - dp.packFixed(mPartAccel.mV[2], "psaccelz", TRUE, 8, 7); - - dp.packUUID(mPartImageID, "psuuid"); - dp.packUUID(mTargetUUID, "pstargetuuid"); - mPartData.pack(dp); - return TRUE; -} - - -BOOL LLPartSysData::unpack(LLDataPacker &dp) +BOOL LLPartSysData::unpackSystem(LLDataPacker &dp) { dp.unpackU32(mCRC, "pscrc"); dp.unpackU32(mFlags, "psflags"); @@ -232,20 +271,58 @@ BOOL LLPartSysData::unpack(LLDataPacker &dp) dp.unpackUUID(mPartImageID, "psuuid"); dp.unpackUUID(mTargetUUID, "pstargetuuid"); - mPartData.unpack(dp); return TRUE; } +BOOL LLPartSysData::unpackLegacy(LLDataPacker &dp) +{ + unpackSystem(dp); + mPartData.unpackLegacy(dp); + + return TRUE; +} + +BOOL LLPartSysData::unpack(LLDataPacker &dp) +{ + // syssize is currently unused. Adding now when modifying the 'version to make extensible in the future + S32 size = 0; + dp.unpackS32(size, "syssize"); + + if (size != PS_SYS_DATA_BLOCK_SIZE) + { //unexpected size, this viewer doesn't know how to parse this particle system + + //skip to LLPartData block + U8 feh = 0; + + for (U32 i = 0; i < size; ++i) + { + dp.unpackU8(feh, "whippang"); + } + + dp.unpackS32(size, "partsize"); + //skip LLPartData block + for (U32 i = 0; i < size; ++i) + { + dp.unpackU8(feh, "whippang"); + } + return FALSE; + } + + unpackSystem(dp); + + return mPartData.unpack(dp); +} + std::ostream& operator<<(std::ostream& s, const LLPartSysData &data) { - s << "Flags: " << std::hex << data.mFlags << std::dec; - s << " Pattern: " << std::hex << (U32) data.mPattern << std::dec << "\n"; + s << "Flags: " << std::hex << data.mFlags; + s << " Pattern: " << std::hex << (U32) data.mPattern << "\n"; s << "Age: [" << data.mStartAge << ", " << data.mMaxAge << "]\n"; s << "Angle: [" << data.mInnerAngle << ", " << data.mOuterAngle << "]\n"; s << "Burst Rate: " << data.mBurstRate << "\n"; s << "Burst Radius: " << data.mBurstRadius << "\n"; s << "Burst Speed: [" << data.mBurstSpeedMin << ", " << data.mBurstSpeedMax << "]\n"; - s << "Burst Part Count: " << std::hex << (U32) data.mBurstPartCount << std::dec << "\n"; + s << "Burst Part Count: " << std::hex << (U32) data.mBurstPartCount << "\n"; s << "Angular Velocity: " << data.mAngularVelocity << "\n"; s << "Accel: " << data.mPartAccel; return s; @@ -253,7 +330,7 @@ std::ostream& operator<<(std::ostream& s, const LLPartSysData &data) BOOL LLPartSysData::isNullPS(const S32 block_num) { - U8 ps_data_block[PS_DATA_BLOCK_SIZE]; + U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE]; U32 crc; S32 size; @@ -264,14 +341,28 @@ BOOL LLPartSysData::isNullPS(const S32 block_num) { return TRUE; } - else if (size != PS_DATA_BLOCK_SIZE) + + if (size > PS_MAX_DATA_BLOCK_SIZE) { - llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl; + //size is too big, newer particle version unsupported return TRUE; } - gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE); - LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE); + gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE); + + LLDataPackerBinaryBuffer dp(ps_data_block, size); + if (size > PS_LEGACY_DATA_BLOCK_SIZE) + { + // non legacy systems pack a size before the CRC + S32 tmp = 0; + dp.unpackS32(tmp, "syssize"); + + if (tmp > PS_SYS_DATA_BLOCK_SIZE) + { //unknown system data block size, don't know how to parse it, treat as NULL + return TRUE; + } + } + dp.unpackU32(crc, "crc"); if (crc == 0) @@ -281,50 +372,37 @@ BOOL LLPartSysData::isNullPS(const S32 block_num) return FALSE; } - -//static -BOOL LLPartSysData::packNull() -{ - U8 ps_data_block[PS_DATA_BLOCK_SIZE]; - gMessageSystem->addBinaryData("PSBlock", ps_data_block, 0); - return TRUE; -} - - -BOOL LLPartSysData::packBlock() -{ - U8 ps_data_block[PS_DATA_BLOCK_SIZE]; - - LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE); - pack(dp); - - // Add to message - gMessageSystem->addBinaryData("PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE); - - return TRUE; -} - - BOOL LLPartSysData::unpackBlock(const S32 block_num) { - U8 ps_data_block[PS_DATA_BLOCK_SIZE]; + U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE]; // Check size of block S32 size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock"); - if (size != PS_DATA_BLOCK_SIZE) + if (size > PS_MAX_DATA_BLOCK_SIZE) { - llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl; + // Larger packets are newer and unsupported return FALSE; } // Get from message - gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE); + gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE); - LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE); - unpack(dp); + LLDataPackerBinaryBuffer dp(ps_data_block, size); - return TRUE; + if (size == PS_LEGACY_DATA_BLOCK_SIZE) + { + return unpackLegacy(dp); + } + else + { + return unpack(dp); + } +} + +bool LLPartSysData::isLegacyCompatible() const +{ + return !mPartData.hasGlow() && !mPartData.hasBlendFunc(); } void LLPartSysData::clampSourceParticleRate() diff --git a/indra/llmessage/llpartdata.h b/indra/llmessage/llpartdata.h index a4ef058b3..ed5c1a6ac 100644 --- a/indra/llmessage/llpartdata.h +++ b/indra/llmessage/llpartdata.h @@ -70,7 +70,12 @@ enum LLPSScriptFlags LLPS_SRC_TARGET_UUID, LLPS_SRC_OMEGA, LLPS_SRC_ANGLE_BEGIN, - LLPS_SRC_ANGLE_END + LLPS_SRC_ANGLE_END, + + LLPS_PART_BLEND_FUNC_SOURCE, + LLPS_PART_BLEND_FUNC_DEST, + LLPS_PART_START_GLOW, + LLPS_PART_END_GLOW }; @@ -83,11 +88,13 @@ public: mParameter(0.f) { } + BOOL unpackLegacy(LLDataPacker &dp); BOOL unpack(LLDataPacker &dp); + BOOL pack(LLDataPacker &dp); - LLSD asLLSD() const; - operator LLSD() const {return asLLSD(); } - bool fromLLSD(LLSD& sd); + + bool hasGlow() const; + bool hasBlendFunc() const; // Masks for the different particle flags enum @@ -102,17 +109,39 @@ public: LL_PART_TARGET_LINEAR_MASK = 0x80, // Particle uses a direct linear interpolation LL_PART_EMISSIVE_MASK = 0x100, // Particle is "emissive", instead of being lit LL_PART_BEAM_MASK = 0x200, // Particle is a "beam" connecting source and target + LL_PART_RIBBON_MASK = 0x400, // Particles are joined together into one continuous triangle strip // Not implemented yet! //LL_PART_RANDOM_ACCEL_MASK = 0x100, // Particles have random acceleration //LL_PART_RANDOM_VEL_MASK = 0x200, // Particles have random velocity shifts" //LL_PART_TRAIL_MASK = 0x400, // Particles have historical "trails" + //sYSTEM SET FLAGS + LL_PART_DATA_GLOW = 0x10000, + LL_PART_DATA_BLEND = 0x20000, + // Viewer side use only! LL_PART_HUD = 0x40000000, LL_PART_DEAD_MASK = 0x80000000, }; + enum + { + LL_PART_BF_ONE = 0, + LL_PART_BF_ZERO = 1, + LL_PART_BF_DEST_COLOR = 2, + LL_PART_BF_SOURCE_COLOR = 3, + LL_PART_BF_ONE_MINUS_DEST_COLOR = 4, + LL_PART_BF_ONE_MINUS_SOURCE_COLOR = 5, + UNSUPPORTED_DEST_ALPHA = 6, + LL_PART_BF_SOURCE_ALPHA = 7, + UNSUPPORTED_ONE_MINUS_DEST_ALPHA = 8, + LL_PART_BF_ONE_MINUS_SOURCE_ALPHA = 9, + LL_PART_BF_COUNT = 10 + }; + + static bool validBlendFunc(S32 func); + void setFlags(const U32 flags); void setMaxAge(const F32 max_age); void setStartScale(const F32 xs, F32 ys); @@ -126,6 +155,9 @@ public: friend class LLPartSysData; friend class LLViewerPartSourceScript; +private: + S32 getSize() const; + // These are public because I'm really lazy... public: U32 mFlags; // Particle state/interpolators in effect @@ -137,6 +169,12 @@ public: LLVector3 mPosOffset; // Offset from source if using FOLLOW_SOURCE F32 mParameter; // A single floating point parameter + + F32 mStartGlow; + F32 mEndGlow; + + U8 mBlendFuncSource; + U8 mBlendFuncDest; }; @@ -146,15 +184,13 @@ public: LLPartSysData(); BOOL unpack(LLDataPacker &dp); - BOOL pack(LLDataPacker &dp); - - + BOOL unpackLegacy(LLDataPacker &dp); BOOL unpackBlock(const S32 block_num); - BOOL packBlock(); - - static BOOL packNull(); + static BOOL isNullPS(const S32 block_num); // Returns FALSE if this is a "NULL" particle system (i.e. no system) + bool isLegacyCompatible() const; + // Different masks for effects on the source enum { @@ -187,7 +223,12 @@ public: void clampSourceParticleRate(); friend std::ostream& operator<<(std::ostream& s, const LLPartSysData &data); // Stream a + + S32 getdataBlockSize() const; +private: + BOOL unpackSystem(LLDataPacker &dp); + public: // Public because I'm lazy.... diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 36969d27c..bdf15cb94 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -38,6 +38,8 @@ #include "lldatapacker.h" #include "llsdutil_math.h" #include "llprimtexturelist.h" +#include "imageids.h" +#include "llmaterialid.h" /** * exported constants @@ -1062,7 +1064,7 @@ S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 dat while ((cur_ptr < buffer_end) && (*cur_ptr != 0)) { -// llinfos << "TE exception" << llendl; + LL_DEBUGS("TEFieldDecode") << "TE exception" << LL_ENDL; i = 0; while (*cur_ptr & 0x80) { @@ -1077,14 +1079,16 @@ S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 dat if (i & 0x01) { htonmemcpy(data_ptr+(j*data_size),cur_ptr,type,data_size); -// char foo[64]; -// sprintf(foo,"%x %x",*(data_ptr+(j*data_size)), *(data_ptr+(j*data_size)+1)); -// llinfos << "Assigning " << foo << " to face " << j << llendl; + LL_DEBUGS("TEFieldDecode") << "Assigning " ; + char foo[64]; + sprintf(foo,"%x %x",*(data_ptr+(j*data_size)), *(data_ptr+(j*data_size)+1)); + LL_CONT << foo << " to face " << j << LL_ENDL; } i = i >> 1; } cur_ptr += data_size; } + llassert(cur_ptr <= buffer_end); // buffer underrun return (S32)(cur_ptr - start_loc); } diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 7dcce3e76..974bbb3b5 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -159,6 +159,11 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, // Create program mProgramObject = glCreateProgramObjectARB(); +#if LL_DARWIN + // work-around missing mix(vec3,vec3,bvec3) + mDefines["OLD_SELECT"] = "1"; +#endif + //compile new source vector< pair >::iterator fileIter = mShaderFiles.begin(); for ( ; fileIter != mShaderFiles.end(); fileIter++ ) diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 782562886..85c5a0cb5 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1075,6 +1075,15 @@ LLRender::~LLRender() void LLRender::init() { + if (sGLCoreProfile && !LLVertexBuffer::sUseVAO) + { //bind a dummy vertex array object so we're core profile compliant +#ifdef GL_ARB_vertex_array_object + U32 ret; + glGenVertexArrays(1, &ret); + glBindVertexArray(ret); +#endif + } + llassert_always(mBuffer.isNull()) ; stop_glerror(); mBuffer = new LLVertexBuffer(immediate_mask, 0); @@ -2295,6 +2304,22 @@ void LLRender::diffuseColor4ubv(const U8* c) } } +void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a) +{ + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + + if (shader) + { + shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f); + } + else + { + glColor4ub(r,g,b,a); + } +} + + void LLRender::debugTexUnits(void) { LL_INFOS("TextureUnit") << "Active TexUnit: " << mCurrTextureUnitIndex << LL_ENDL; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 2ca28c669..66786d6ee 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -262,6 +262,14 @@ class LLRender friend class LLTexUnit; public: + enum eTexIndex + { + DIFFUSE_MAP = 0, + NORMAL_MAP, + SPECULAR_MAP, + NUM_TEXTURE_CHANNELS, + }; + typedef enum { TRIANGLES = 0, TRIANGLE_STRIP, @@ -390,6 +398,7 @@ public: void diffuseColor4f(F32 r, F32 g, F32 b, F32 a); void diffuseColor4fv(const F32* c); void diffuseColor4ubv(const U8* c); + void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a); void vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count); void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count); diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index c4223da93..87d1cfd40 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -534,8 +534,11 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade range = mShaderObjects.equal_range(filename); for (std::multimap::iterator it = range.first; it != range.second;++it) { - if((*it).second.mLevel == shader_level && (*it).second.mType == type) + if((*it).second.mLevel == shader_level && (*it).second.mType == type && (*it).second.mDefinitions == (defines ? *defines : std::map())) + { + llinfos << "Loading cached shader for " << filename << llendl; return (*it).second.mHandle; + } } GLenum error = GL_NO_ERROR; @@ -713,6 +716,8 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } */ + text[count++] = strdup("#define HAS_DIFFUSE_LOOKUP 1\n"); + //uniform declartion for (S32 i = 0; i < texture_index_channels; ++i) { @@ -770,6 +775,10 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade llerrs << "Indexed texture rendering requires GLSL 1.30 or later." << llendl; } } + else + { + text[count++] = strdup("#define HAS_DIFFUSE_LOOKUP 0\n"); + } //copy file into memory while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(text) ) @@ -918,7 +927,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (ret) { // Add shader file to map - mShaderObjects.insert(make_pair(filename,CachedObjectInfo(ret,try_gpu_class,type))); + mShaderObjects.insert(make_pair(filename,CachedObjectInfo(ret,try_gpu_class,type,defines))); shader_level = try_gpu_class; } else @@ -1129,6 +1138,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("minimum_alpha"); + mReservedUniforms.push_back("emissive_brightness"); mReservedUniforms.push_back("shadow_matrix"); mReservedUniforms.push_back("env_mat"); @@ -1191,6 +1201,12 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("projectionMap"); mReservedUniforms.push_back("norm_mat"); + mReservedUniforms.push_back("global_gamma"); + mReservedUniforms.push_back("texture_gamma"); + + mReservedUniforms.push_back("specular_color"); + mReservedUniforms.push_back("env_intensity"); + mReservedUniforms.push_back("matrixPalette"); mReservedUniforms.push_back("screenTex"); @@ -1230,6 +1246,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("alpha_ramp"); mReservedUniforms.push_back("origin"); + mReservedUniforms.push_back("display_gamma"); llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); std::set dupe_check; diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 6d4582ec3..c13485b71 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -111,6 +111,7 @@ public: GLOW_DELTA, MINIMUM_ALPHA, + EMISSIVE_BRIGHTNESS, DEFERRED_SHADOW_MATRIX, DEFERRED_ENV_MAT, @@ -168,7 +169,14 @@ public: DEFERRED_PROJECTION, DEFERRED_NORM_MATRIX, + GLOBAL_GAMMA, + TEXTURE_GAMMA, + + SPECULAR_COLOR, + ENVIRONMENT_INTENSITY, + AVATAR_MATRIX, + WATER_SCREENTEX, WATER_SCREENDEPTH, WATER_REFTEX, @@ -204,7 +212,9 @@ public: TERRAIN_DETAIL2, TERRAIN_DETAIL3, TERRAIN_ALPHARAMP, + SHINY_ORIGIN, +DISPLAY_GAMMA, END_RESERVED_UNIFORMS } eGLSLReservedUniforms; @@ -228,11 +238,12 @@ public: public: struct CachedObjectInfo { - CachedObjectInfo(GLhandleARB handle, U32 level, GLenum type) : - mHandle(handle), mLevel(level), mType(type) {} + CachedObjectInfo(GLhandleARB handle, U32 level, GLenum type, std::map *definitions) : + mHandle(handle), mLevel(level), mType(type), mDefinitions(definitions ? *definitions : std::map()){} GLhandleARB mHandle; //Actual handle of the opengl shader object. U32 mLevel; //Level /might/ not be needed, but it's stored to ensure there's no change in behavior. GLenum mType; //GL_VERTEX_SHADER_ARB or GL_FRAGMENT_SHADER_ARB. Tracked because some utility shaders can be loaded as both types (carefully). + std::map mDefinitions; }; // Map of shader names to compiled std::multimap mShaderObjects; //Singu Note: Packing more info here. Doing such provides capability to skip unneeded duplicate loading.. diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index f5d8bef9c..0c59d99c0 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -2035,7 +2035,10 @@ bool LLVertexBuffer::getTexCoord1Strider(LLStrider& strider, S32 inde { return VertexBufferStrider::get(*this, strider, index, count, map_range); } - +bool LLVertexBuffer::getTexCoord2Strider(LLStrider& strider, S32 index, S32 count, bool map_range) +{ + return VertexBufferStrider::get(*this, strider, index, count, map_range); +} bool LLVertexBuffer::getNormalStrider(LLStrider& strider, S32 index, S32 count, bool map_range) { return VertexBufferStrider::get(*this, strider, index, count, map_range); @@ -2371,7 +2374,8 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) if (data_mask & MAP_COLOR) { S32 loc = TYPE_COLOR; - void* ptr = (void*)(base + mOffsets[TYPE_COLOR]); + //bind emissive instead of color pointer if emissive is present + void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]); glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr); } if (data_mask & MAP_EMISSIVE) @@ -2379,6 +2383,12 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) S32 loc = TYPE_EMISSIVE; void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]); glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + + if (!(data_mask & MAP_COLOR)) + { //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps + loc = TYPE_COLOR; + glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + } } if (data_mask & MAP_WEIGHT) { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 0025937ba..ea5aca583 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -246,6 +246,7 @@ public: bool getIndexStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getTexCoord0Strider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getTexCoord1Strider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getTexCoord2Strider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getNormalStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getTangentStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getTangentStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index d7dbce179..edb6c8c9d 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -153,6 +153,7 @@ set(viewer_SOURCE_FILES lldrawpoolavatar.cpp lldrawpoolbump.cpp lldrawpoolground.cpp + lldrawpoolmaterials.cpp lldrawpoolsimple.cpp lldrawpoolsky.cpp lldrawpoolterrain.cpp @@ -669,6 +670,7 @@ set(viewer_HEADER_FILES lldrawpoolalpha.h lldrawpoolavatar.h lldrawpoolbump.h + lldrawpoolmaterials.h lldrawpoolground.h lldrawpoolsimple.h lldrawpoolsky.h diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index dd87ddb33..1aa3261fe 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -25,31 +25,429 @@ #extension GL_ARB_texture_rectangle : enable +#define INDEXED 1 +#define NON_INDEXED 2 +#define NON_INDEXED_NO_COLOR 3 + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; #else #define frag_color gl_FragColor #endif -uniform sampler2DRect depthMap; +//uniform float display_gamma; +uniform vec4 gamma; +uniform vec4 lightnorm; +uniform vec4 sunlight_color; +uniform vec4 ambient; +uniform vec4 blue_horizon; +uniform vec4 blue_density; +uniform float haze_horizon; +uniform float haze_density; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float distance_multiplier; +uniform float max_y; +uniform vec4 glow; +uniform float scene_light_strength; +uniform mat3 env_mat; +uniform mat3 ssao_effect_mat; -vec4 diffuseLookup(vec2 texcoord); +uniform vec3 sun_dir; -uniform vec2 screen_res; +#if HAS_SHADOW +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; -vec3 atmosLighting(vec3 light); -vec3 scaleSoftClip(vec3 light); +uniform vec2 shadow_res; + +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform float shadow_bias; + +#endif + +#ifdef USE_DIFFUSE_TEX +uniform sampler2D diffuseMap; +#endif -VARYING vec3 vary_ambient; -VARYING vec3 vary_directional; VARYING vec3 vary_fragcoord; VARYING vec3 vary_position; -VARYING vec3 vary_pointlight_col; - -VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +VARYING vec3 vary_norm; + +#ifdef USE_VERTEX_COLOR +VARYING vec4 vertex_color; +#endif + +vec3 vary_PositionEye; +vec3 vary_SunlitColor; +vec3 vary_AmblitColor; +vec3 vary_AdditiveColor; +vec3 vary_AtmosAttenuation; uniform mat4 inv_proj; +uniform vec2 screen_res; + +uniform vec4 light_position[8]; +uniform vec3 light_direction[8]; +uniform vec3 light_attenuation[8]; +uniform vec3 light_diffuse[8]; + +vec3 srgb_to_linear(vec3 cs) +{ + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lte); +#endif + +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} + +vec3 calcDirectionalLight(vec3 n, vec3 l) +{ + float a = max(dot(n,l),0.0); + a = pow(a, 1.0/1.3); + return vec3(a,a,a); +} + +vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + float da = 1.0; + + vec3 col = vec3(0); + + if (d > 0.0 && la > 0.0 && fa > 0.0) + { + //normalize light vector + lv = normalize(lv); + + //distance attenuation + float dist = d/la; + float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); + dist_atten *= dist_atten; + dist_atten *= 2.0; + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= max(dot(n, lv), 0.0); + + float lit = max(da * dist_atten,0.0); + + col = light_col * lit * diffuse; + + // no spec for alpha shader... + } + + return max(col, vec3(0.0,0.0,0.0)); +} + +#if HAS_SHADOW +float pcfShadow(sampler2DShadow shadowMap, vec4 stc) +{ + stc.xyz /= stc.w; + stc.z += shadow_bias; + + stc.x = floor(stc.x*shadow_res.x + fract(stc.y*shadow_res.y*12345))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here + + float cs = shadow2D(shadowMap, stc.xyz).x; + float shadow = cs; + + shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; + + return shadow*0.2; +} +#endif + +#ifdef WATER_FOG +uniform vec4 waterPlane; +uniform vec4 waterFogColor; +uniform float waterFogDensity; +uniform float waterFogKS; + +vec4 applyWaterFogDeferred(vec3 pos, vec4 color) +{ + //normalize view vector + vec3 view = normalize(pos); + float es = -(dot(view, waterPlane.xyz)); + + //find intersection point with water plane and eye vector + + //get eye depth + float e0 = max(-waterPlane.w, 0.0); + + vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0); + + //get object depth + float depth = length(pos - int_v); + + //get "thickness" of water + float l = max(depth, 0.1); + + float kd = waterFogDensity; + float ks = waterFogKS; + vec4 kc = waterFogColor; + + float F = 0.98; + + float t1 = -kd * pow(F, ks * e0); + float t2 = kd + ks * es; + float t3 = pow(F, t2*l) - 1.0; + + float L = min(t1/t2*t3, 1.0); + + float D = pow(0.98, l*kd); + + color.rgb = color.rgb * D + kc.rgb * L; + color.a = kc.a + color.a; + + return color; +} +#endif + +vec3 getSunlitColor() +{ + return vary_SunlitColor; +} +vec3 getAmblitColor() +{ + return vary_AmblitColor; +} +vec3 getAdditiveColor() +{ + return vary_AdditiveColor; +} +vec3 getAtmosAttenuation() +{ + return vary_AtmosAttenuation; +} + +void setPositionEye(vec3 v) +{ + vary_PositionEye = v; +} + +void setSunlitColor(vec3 v) +{ + vary_SunlitColor = v; +} + +void setAmblitColor(vec3 v) +{ + vary_AmblitColor = v; +} + +void setAdditiveColor(vec3 v) +{ + vary_AdditiveColor = v; +} + +void setAtmosAttenuation(vec3 v) +{ + vary_AtmosAttenuation = v; +} + +void calcAtmospherics(vec3 inPositionEye, float ambFactor) { + + vec3 P = inPositionEye; + setPositionEye(P); + + vec3 tmpLightnorm = lightnorm.xyz; + + vec3 Pn = normalize(P); + float Plen = length(P); + + vec4 temp1 = vec4(0); + vec3 temp2 = vec3(0); + vec4 blue_weight; + vec4 haze_weight; + vec4 sunlight = sunlight_color; + vec4 light_atten; + + //sunlight attenuation effect (hue and brightness) due to atmosphere + //this is used later for sunlight modulation at various altitudes + light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); + //I had thought blue_density and haze_density should have equal weighting, + //but attenuation due to haze_density tends to seem too strong + + temp1 = blue_density + vec4(haze_density); + blue_weight = blue_density / temp1; + haze_weight = vec4(haze_density) / temp1; + + //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain) + temp2.y = max(0.0, tmpLightnorm.y); + temp2.y = 1. / temp2.y; + sunlight *= exp( - light_atten * temp2.y); + + // main atmospheric scattering line integral + temp2.z = Plen * density_multiplier; + + // Transparency (-> temp1) + // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati + // compiler gets confused. + temp1 = exp(-temp1 * temp2.z * distance_multiplier); + + //final atmosphere attenuation factor + setAtmosAttenuation(temp1.rgb); + + //compute haze glow + //(can use temp2.x as temp because we haven't used it yet) + temp2.x = dot(Pn, tmpLightnorm.xyz); + temp2.x = 1. - temp2.x; + //temp2.x is 0 at the sun and increases away from sun + temp2.x = max(temp2.x, .03); //was glow.y + //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) + temp2.x *= glow.x; + //higher glow.x gives dimmer glow (because next step is 1 / "angle") + temp2.x = pow(temp2.x, glow.z); + //glow.z should be negative, so we're doing a sort of (1 / "angle") function + + //add "minimum anti-solar illumination" + temp2.x += .25; + + //increase ambient when there are more clouds + vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5; + + /* decrease value and saturation (that in HSV, not HSL) for occluded areas + * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html + * // The following line of code performs the equivalent of: + * float ambAlpha = tmpAmbient.a; + * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis + * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); + * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); + */ + tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); + + //haze color + setAdditiveColor( + vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient) + + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x + + tmpAmbient))); + + //brightness of surface both sunlight and ambient + setSunlitColor(vec3(sunlight * .5)); + setAmblitColor(vec3(tmpAmbient * .25)); + setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1)); +} + +vec3 atmosLighting(vec3 light) +{ + light *= getAtmosAttenuation().r; + light += getAdditiveColor(); + return (2.0 * light); +} + +vec3 atmosTransport(vec3 light) { + light *= getAtmosAttenuation().r; + light += getAdditiveColor() * 2.0; + return light; +} +vec3 atmosGetDiffuseSunlightColor() +{ + return getSunlitColor(); +} + +vec3 scaleDownLight(vec3 light) +{ + return (light / vec3(scene_light_strength, scene_light_strength, scene_light_strength)); +} + +vec3 scaleUpLight(vec3 light) +{ + return (light * vec3(scene_light_strength, scene_light_strength, scene_light_strength)); +} + +vec3 atmosAmbient(vec3 light) +{ + return getAmblitColor() + (light * vec3(0.5f, 0.5f, 0.5f)); +} + +vec3 atmosAffectDirectionalLight(float lightIntensity) +{ + return getSunlitColor() * vec3(lightIntensity, lightIntensity, lightIntensity); +} + +vec3 scaleSoftClip(vec3 light) +{ + //soft clip effect: + vec3 zeroes = vec3(0.0f, 0.0f, 0.0f); + vec3 ones = vec3(1.0f, 1.0f, 1.0f); + + light = ones - clamp(light, zeroes, ones); + light = ones - pow(light, gamma.xxx); + + return light; +} + +vec3 fullbrightAtmosTransport(vec3 light) { + float brightness = dot(light.rgb, vec3(0.33333)); + + return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness); +} + +vec3 fullbrightScaleSoftClip(vec3 light) +{ + //soft clip effect: + return light; +} void main() { @@ -58,16 +456,172 @@ void main() vec4 pos = vec4(vary_position, 1.0); - vec4 diff= diffuseLookup(vary_texcoord0.xy); + float shadow = 1.0; - vec4 col = vec4(vary_ambient + vary_directional.rgb, vertex_color.a); - vec4 color = diff * col; +#if HAS_SHADOW + vec4 spos = pos; + + if (spos.z > -shadow_clip.w) + { + shadow = 0.0; + + vec4 lpos; + + vec4 near_split = shadow_clip*-0.75; + vec4 far_split = shadow_clip*-1.25; + vec4 transition_domain = near_split-far_split; + float weight = 0.0; + + if (spos.z < near_split.z) + { + lpos = shadow_matrix[3]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap3, lpos)*w; + weight += w; + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + + if (spos.z < near_split.y && spos.z > far_split.z) + { + lpos = shadow_matrix[2]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; + w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap2, lpos)*w; + weight += w; + } + + if (spos.z < near_split.x && spos.z > far_split.y) + { + lpos = shadow_matrix[1]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; + w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; + shadow += pcfShadow(shadowMap1, lpos)*w; + weight += w; + } + + if (spos.z > far_split.x) + { + lpos = shadow_matrix[0]*spos; + + float w = 1.0; + w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; + + shadow += pcfShadow(shadowMap0, lpos)*w; + weight += w; + } + + + shadow /= weight; + } + else + { + shadow = 1.0; + } +#endif + +#ifdef USE_INDEXED_TEX + vec4 diff = diffuseLookup(vary_texcoord0.xy); +#else + vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy); +#endif + +#ifdef FOR_IMPOSTOR + vec4 color; + color.rgb = diff.rgb; + +#ifdef USE_VERTEX_COLOR + float final_alpha = diff.a * vertex_color.a; + diff.rgb *= vertex_color.rgb; +#else + float final_alpha = diff.a; +#endif + + // Insure we don't pollute depth with invis pixels in impostor rendering + // + if (final_alpha < 0.01) + { + discard; + } +#else + +#ifdef USE_VERTEX_COLOR + float final_alpha = diff.a * vertex_color.a; + diff.rgb *= vertex_color.rgb; +#else + float final_alpha = diff.a; +#endif + + + vec4 gamma_diff = diff; + diff.rgb = srgb_to_linear(diff.rgb); + + vec3 norm = vary_norm; + + calcAtmospherics(pos.xyz, 1.0); + + vec2 abnormal = encode_normal(norm.xyz); + norm.xyz = decode_normal(abnormal.xy); + + float da = dot(norm.xyz, sun_dir.xyz); + + float final_da = da; + final_da = min(final_da, shadow); + final_da = max(final_da, 0.0f); + final_da = min(final_da, 1.0f); + final_da = pow(final_da, 1.0/1.3); + + vec4 color = vec4(0,0,0,0); + + color.rgb = atmosAmbient(color.rgb); + color.a = final_alpha; + + float ambient = abs(da); + ambient *= 0.5; + ambient *= ambient; + ambient = (1.0-ambient); + + color.rgb *= ambient; + color.rgb += atmosAffectDirectionalLight(final_da); + color.rgb *= gamma_diff.rgb; + + //color.rgb = mix(diff.rgb, color.rgb, final_alpha); color.rgb = atmosLighting(color.rgb); - color.rgb = scaleSoftClip(color.rgb); - color.rgb += diff.rgb * vary_pointlight_col.rgb; + vec4 light = vec4(0,0,0,0); + + color.rgb = srgb_to_linear(color.rgb); + + #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, diff.rgb, pos.xyz, norm, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z); + + LIGHT_LOOP(1) + LIGHT_LOOP(2) + LIGHT_LOOP(3) + LIGHT_LOOP(4) + LIGHT_LOOP(5) + LIGHT_LOOP(6) + LIGHT_LOOP(7) + + // keep it linear + // + color.rgb += light.rgb; + + // straight to display gamma, we're post-deferred + // + color.rgb = linear_to_srgb(color.rgb); + +#ifdef WATER_FOG + color = applyWaterFogDeferred(pos.xyz, color); +#endif + +#endif frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl deleted file mode 100644 index 1113a9845..000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @file alphaNonIndexedNoColorF.glsl - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2005, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#extension GL_ARB_texture_rectangle : enable - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -uniform float minimum_alpha; - -uniform sampler2DRect depthMap; -uniform sampler2D diffuseMap; - -uniform vec2 screen_res; - -vec3 atmosLighting(vec3 light); -vec3 scaleSoftClip(vec3 light); - -VARYING vec3 vary_ambient; -VARYING vec3 vary_directional; -VARYING vec3 vary_fragcoord; -VARYING vec3 vary_position; -VARYING vec3 vary_pointlight_col; -VARYING vec2 vary_texcoord0; - -uniform mat4 inv_proj; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -void main() -{ - vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - frag *= screen_res; - - vec4 pos = vec4(vary_position, 1.0); - - vec4 diff= texture2D(diffuseMap,vary_texcoord0.xy); - - if (diff.a < minimum_alpha) - { - discard; - } - - vec4 col = vec4(vary_ambient + vary_directional.rgb, 1.0); - vec4 color = diff * col; - - - color.rgb = atmosLighting(color.rgb); - - color.rgb = scaleSoftClip(color.rgb); - - color.rgb += diff.rgb * vary_pointlight_col.rgb; - - frag_color = color; -} - diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl deleted file mode 100644 index 5a0e8ff68..000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl +++ /dev/null @@ -1,144 +0,0 @@ -/** - * @file alphaSkinnedV.glsl - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 projection_matrix; -uniform mat4 modelview_matrix; - -ATTRIBUTE vec3 position; -ATTRIBUTE vec3 normal; -ATTRIBUTE vec4 diffuse_color; -ATTRIBUTE vec2 texcoord0; - -mat4 getObjectSkinnedTransform(); -void calcAtmospherics(vec3 inPositionEye); - -float calcDirectionalLight(vec3 n, vec3 l); - -vec3 atmosAmbient(vec3 light); -vec3 atmosAffectDirectionalLight(float lightIntensity); - -VARYING vec3 vary_position; -VARYING vec3 vary_ambient; -VARYING vec3 vary_directional; -VARYING vec3 vary_fragcoord; -VARYING vec3 vary_pointlight_col; -VARYING vec4 vertex_color; -VARYING vec2 vary_texcoord0; - - -uniform float near_clip; - -uniform vec4 light_position[8]; -uniform vec3 light_direction[8]; -uniform vec3 light_attenuation[8]; -uniform vec3 light_diffuse[8]; - -float calcDirectionalLight(vec3 n, vec3 l) -{ - float a = max(dot(n,l),0.0); - return a; -} - -float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) -{ - //get light vector - vec3 lv = lp.xyz-v; - - //get distance - float d = dot(lv,lv); - - float da = 0.0; - - if (d > 0.0 && la > 0.0 && fa > 0.0) - { - //normalize light vector - lv = normalize(lv); - - //distance attenuation - float dist2 = d/la; - da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 - - //angular attenuation - da *= max(dot(n, lv), 0.0); - } - - return da; -} - -void main() -{ - vary_texcoord0 = texcoord0; - - vec4 pos; - vec3 norm; - - mat4 trans = getObjectSkinnedTransform(); - trans = modelview_matrix * trans; - - pos = trans * vec4(position.xyz, 1.0); - - norm = position.xyz + normal.xyz; - norm = normalize(( trans*vec4(norm, 1.0) ).xyz-pos.xyz); - - vec4 frag_pos = projection_matrix * pos; - gl_Position = frag_pos; - - vary_position = pos.xyz; - - calcAtmospherics(pos.xyz); - - vec4 col = vec4(0.0, 0.0, 0.0, diffuse_color.a); - - // Collect normal lights - col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].y, light_attenuation[2].z); - col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].y, light_attenuation[3].z); - col.rgb += light_diffuse[4].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[4], light_direction[4], light_attenuation[4].x, light_attenuation[4].y, light_attenuation[4].z); - col.rgb += light_diffuse[5].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[5], light_direction[5], light_attenuation[5].x, light_attenuation[5].y, light_attenuation[5].z); - col.rgb += light_diffuse[6].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[6], light_direction[6], light_attenuation[6].x, light_attenuation[6].y, light_attenuation[6].z); - col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].y, light_attenuation[7].z); - - vary_pointlight_col = col.rgb*diffuse_color.rgb; - - col.rgb = vec3(0,0,0); - - // Add windlight lights - col.rgb = atmosAmbient(vec3(0.)); - - vary_ambient = col.rgb*diffuse_color.rgb; - vary_directional = diffuse_color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, light_position[0].xyz), (1.0-diffuse_color.a)*(1.0-diffuse_color.a))); - - col.rgb = min(col.rgb*diffuse_color.rgb, 1.0); - - vertex_color = col; - - - - vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip); -} - - diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index cf38a2f4f..b40785bbd 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -23,126 +23,118 @@ * $/LicenseInfo$ */ +#define INDEXED 1 +#define NON_INDEXED 2 +#define NON_INDEXED_NO_COLOR 3 + uniform mat3 normal_matrix; uniform mat4 texture_matrix0; +uniform mat4 projection_matrix; uniform mat4 modelview_matrix; uniform mat4 modelview_projection_matrix; ATTRIBUTE vec3 position; + +#ifdef USE_INDEXED_TEX void passTextureIndex(); +#endif + ATTRIBUTE vec3 normal; + +#ifdef USE_VERTEX_COLOR ATTRIBUTE vec4 diffuse_color; +#endif + ATTRIBUTE vec2 texcoord0; -vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); -void calcAtmospherics(vec3 inPositionEye); +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +#else +#ifdef IS_AVATAR_SKIN +mat4 getSkinnedTransform(); +#endif +#endif -float calcDirectionalLight(vec3 n, vec3 l); - -vec3 atmosAmbient(vec3 light); -vec3 atmosAffectDirectionalLight(float lightIntensity); -vec3 scaleDownLight(vec3 light); -vec3 scaleUpLight(vec3 light); - -VARYING vec3 vary_ambient; -VARYING vec3 vary_directional; VARYING vec3 vary_fragcoord; VARYING vec3 vary_position; -VARYING vec3 vary_pointlight_col; +#ifdef USE_VERTEX_COLOR VARYING vec4 vertex_color; -VARYING vec2 vary_texcoord0; +#endif +VARYING vec2 vary_texcoord0; +VARYING vec3 vary_norm; uniform float near_clip; -uniform float shadow_offset; -uniform float shadow_bias; - -uniform vec4 light_position[8]; -uniform vec3 light_direction[8]; -uniform vec3 light_attenuation[8]; -uniform vec3 light_diffuse[8]; - -float calcDirectionalLight(vec3 n, vec3 l) -{ - float a = max(dot(n,l),0.0); - return a; -} - -float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) -{ - //get light vector - vec3 lv = lp.xyz-v; - - //get distance - float d = dot(lv,lv); - - float da = 0.0; - - if (d > 0.0 && la > 0.0 && fa > 0.0) - { - //normalize light vector - lv = normalize(lv); - - //distance attenuation - float dist2 = d/la; - da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 - - //angular attenuation - da *= max(dot(n, lv), 0.0); - } - - return da; -} void main() { + vec4 pos; + vec3 norm; + //transform vertex +#ifdef HAS_SKIN + mat4 trans = getObjectSkinnedTransform(); + trans = modelview_matrix * trans; + + pos = trans * vec4(position.xyz, 1.0); + + norm = position.xyz + normal.xyz; + norm = normalize((trans * vec4(norm, 1.0)).xyz - pos.xyz); + vec4 frag_pos = projection_matrix * pos; + gl_Position = frag_pos; +#else + +#ifdef IS_AVATAR_SKIN + mat4 trans = getSkinnedTransform(); + vec4 pos_in = vec4(position.xyz, 1.0); + pos.x = dot(trans[0], pos_in); + pos.y = dot(trans[1], pos_in); + pos.z = dot(trans[2], pos_in); + pos.w = 1.0; + + norm.x = dot(trans[0].xyz, normal); + norm.y = dot(trans[1].xyz, normal); + norm.z = dot(trans[2].xyz, normal); + norm = normalize(norm); + + vec4 frag_pos = projection_matrix * pos; + gl_Position = frag_pos; +#else + norm = normalize(normal_matrix * normal); vec4 vert = vec4(position.xyz, 1.0); - passTextureIndex(); - vec4 pos = (modelview_matrix * vert); + pos = (modelview_matrix * vert); gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); +#endif +#endif + +#ifdef USE_INDEXED_TEX + passTextureIndex(); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; +#else + vary_texcoord0 = texcoord0; +#endif - vec3 norm = normalize(normal_matrix * normal); - - float dp_directional_light = max(0.0, dot(norm, light_position[0].xyz)); - vary_position = pos.xyz + light_position[0].xyz * (1.0-dp_directional_light)*shadow_offset; - - calcAtmospherics(pos.xyz); + vary_norm = norm; + vary_position = pos.xyz; - //vec4 color = calcLighting(pos.xyz, norm, diffuse_color, vec4(0.)); - vec4 col = vec4(0.0, 0.0, 0.0, diffuse_color.a); +#ifdef USE_VERTEX_COLOR + vertex_color = diffuse_color; +#endif + +#ifdef HAS_SKIN + vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip); +#else - // Collect normal lights - col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].y, light_attenuation[2].z); - col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].y, light_attenuation[3].z); - col.rgb += light_diffuse[4].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[4], light_direction[4], light_attenuation[4].x, light_attenuation[4].y, light_attenuation[4].z); - col.rgb += light_diffuse[5].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[5], light_direction[5], light_attenuation[5].x, light_attenuation[5].y, light_attenuation[5].z); - col.rgb += light_diffuse[6].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[6], light_direction[6], light_attenuation[6].x, light_attenuation[6].y, light_attenuation[6].z); - col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].y, light_attenuation[7].z); - - vary_pointlight_col = col.rgb*diffuse_color.rgb; - col.rgb = vec3(0,0,0); - - // Add windlight lights - col.rgb = atmosAmbient(vec3(0.)); - - vary_ambient = col.rgb*diffuse_color.rgb; - vary_directional.rgb = diffuse_color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, light_position[0].xyz), (1.0-diffuse_color.a)*(1.0-diffuse_color.a))); - - col.rgb = col.rgb*diffuse_color.rgb; - - vertex_color = col; - - - +#ifdef IS_AVATAR_SKIN + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); +#else pos = modelview_projection_matrix * vert; vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); +#endif +#endif + } + diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl index 81961d774..3f90600ac 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl @@ -39,7 +39,12 @@ void main() mat = modelview_matrix * mat; vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; + vec4 p = projection_matrix * vec4(pos, 1.0); +#if !DEPTH_CLAMP p.z = max(p.z, -p.w+0.01); gl_Position = p; +#else + gl_Position = p; +#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl index 5f395801e..c8ddefac2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl @@ -47,6 +47,7 @@ VARYING vec3 vary_directional; VARYING vec3 vary_fragcoord; VARYING vec3 vary_pointlight_col; VARYING vec2 vary_texcoord0; +VARYING vec3 vary_norm; uniform float near_clip; @@ -112,6 +113,7 @@ void main() norm.y = dot(trans[1].xyz, normal); norm.z = dot(trans[2].xyz, normal); norm = normalize(norm); + vary_norm = norm; vec4 frag_pos = projection_matrix * pos; gl_Position = frag_pos; diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl deleted file mode 100644 index d6149fcc3..000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ /dev/null @@ -1,153 +0,0 @@ -/** - * @file avatarAlphaV.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 projection_matrix; - -ATTRIBUTE vec3 position; -ATTRIBUTE vec3 normal; -ATTRIBUTE vec2 texcoord0; - -vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); -mat4 getSkinnedTransform(); -void calcAtmospherics(vec3 inPositionEye); - -float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); - -vec3 atmosAmbient(vec3 light); -vec3 atmosAffectDirectionalLight(float lightIntensity); -vec3 scaleDownLight(vec3 light); -vec3 scaleUpLight(vec3 light); - -VARYING vec3 vary_position; -VARYING vec3 vary_ambient; -VARYING vec3 vary_directional; -VARYING vec3 vary_fragcoord; -VARYING vec3 vary_pointlight_col; -VARYING vec4 vertex_color; -VARYING vec2 vary_texcoord0; - - -uniform float near_clip; - -uniform vec4 color; - -uniform vec4 light_position[8]; -uniform vec3 light_direction[8]; -uniform vec3 light_attenuation[8]; -uniform vec3 light_diffuse[8]; - -float calcDirectionalLight(vec3 n, vec3 l) -{ - float a = max(dot(n,l),0.0); - return a; -} - -float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) -{ - //get light vector - vec3 lv = lp.xyz-v; - - //get distance - float d = dot(lv,lv); - - float da = 0.0; - - if (d > 0.0 && la > 0.0 && fa > 0.0) - { - //normalize light vector - lv = normalize(lv); - - //distance attenuation - float dist2 = d/la; - da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 - - //angular attenuation - da *= max(dot(n, lv), 0.0); - } - - return da; -} - -void main() -{ - vary_texcoord0 = texcoord0; - - vec4 pos; - vec3 norm; - - mat4 trans = getSkinnedTransform(); - vec4 pos_in = vec4(position.xyz, 1.0); - pos.x = dot(trans[0], pos_in); - pos.y = dot(trans[1], pos_in); - pos.z = dot(trans[2], pos_in); - pos.w = 1.0; - - norm.x = dot(trans[0].xyz, normal); - norm.y = dot(trans[1].xyz, normal); - norm.z = dot(trans[2].xyz, normal); - norm = normalize(norm); - - vec4 frag_pos = projection_matrix * pos; - gl_Position = frag_pos; - - vary_position = pos.xyz; - - calcAtmospherics(pos.xyz); - - vec4 col = vec4(0.0, 0.0, 0.0, 1.0); - - // Collect normal lights - col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].y, light_attenuation[2].z); - col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].y, light_attenuation[3].z); - col.rgb += light_diffuse[4].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[4], light_direction[4], light_attenuation[4].x, light_attenuation[4].y, light_attenuation[4].z); - col.rgb += light_diffuse[5].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[5], light_direction[5], light_attenuation[5].x, light_attenuation[5].y, light_attenuation[5].z); - col.rgb += light_diffuse[6].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[6], light_direction[6], light_attenuation[6].x, light_attenuation[6].y, light_attenuation[6].z); - col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].y, light_attenuation[7].z); - - vary_pointlight_col = col.rgb*color.rgb; - - col.rgb = vec3(0,0,0); - - // Add windlight lights - col.rgb = atmosAmbient(vec3(0.)); - - vary_ambient = col.rgb*color.rgb; - vary_directional = color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, light_position[0].xyz), 0.0)); - - col.rgb = col.rgb * color.rgb; - - vertex_color = col; - - - - vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip); -} - - diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index cf57a33d9..662c762bc 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -31,25 +31,22 @@ out vec4 frag_data[3]; uniform sampler2D diffuseMap; +uniform float minimum_alpha; + VARYING vec3 vary_normal; VARYING vec2 vary_texcoord0; -vec3 pack(vec3 norm) +vec2 encode_normal(vec3 n) { -//#define PACK_NORMALS -#ifdef PACK_NORMALS - float p = sqrt(8.0*norm.z+8.0); - return vec3(norm.xy/p + 0.5, 0.0); -#else - return norm.xyz*0.5+0.5; -#endif + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; } void main() { vec4 diff = texture2D(diffuseMap, vary_texcoord0.xy); - if (diff.a < 0.2) + if (diff.a < minimum_alpha) { discard; } @@ -57,6 +54,6 @@ void main() frag_data[0] = vec4(diff.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(pack(nvn), 0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index 9a9b889da..3e836e794 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -64,24 +64,28 @@ vec4 getPosition(vec2 pos_screen) return pos; } -vec3 unpack(vec2 tc) +vec2 encode_normal(vec3 n) { -//#define PACK_NORMALS -#ifdef PACK_NORMALS - vec2 enc = texture2DRect(normalMap, tc).xy; - enc = enc*4.0-2.0; - float prod = dot(enc,enc); - return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); -#else - vec3 norm = texture2DRect(normalMap, tc).xyz; - return norm*2.0-1.0; -#endif + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; } void main() { vec2 tc = vary_fragcoord.xy; - vec3 norm = unpack(tc); // unpack norm + vec3 norm = texture2DRect(normalMap, tc).xyz; + norm = decode_normal(norm.xy); // unpack norm vec3 pos = getPosition(tc).xyz; vec4 ccol = texture2DRect(lightMap, tc).rgba; @@ -93,11 +97,12 @@ void main() vec4 col = defined_weight.xyxx * ccol; // relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances - float pointplanedist_tolerance_pow2 = pos.z*-0.001; + float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005; // perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large - vec2 tc_v = fract(0.5 * tc.xy); // we now have floor(mod(tc,2.0))*0.5 - float tc_mod = 2.0 * abs(tc_v.x - tc_v.y); // diff of x,y makes checkerboard + float tc_mod = 0.5*(tc.x + tc.y); // mod(tc.x+tc.y,2) + tc_mod -= floor(tc_mod); + tc_mod *= 2.0; tc += ( (tc_mod - 0.5) * getKern(1).z * dlt * 0.5 ); for (int i = 1; i < 4; i++) diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index db80a8e87..595c11fae 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -39,15 +39,10 @@ VARYING vec3 vary_mat2; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -vec3 pack(vec3 norm) +vec2 encode_normal(vec3 n) { -//#define PACK_NORMALS -#ifdef PACK_NORMALS - float p = sqrt(8.0*norm.z+8.0); - return vec3(norm.xy/p + 0.5, 0.0); -#else - return norm.xyz*0.5+0.5; -#endif + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; } void main() @@ -63,5 +58,5 @@ void main() frag_data[1] = vertex_color.aaaa; // 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(pack(nvn), 0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl index 9f6b1ea1f..bb1093082 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl @@ -102,11 +102,6 @@ void main() /// Gamma correct for WL (soft clip effect). frag_data[0] = vec4(scaleSoftClip(color.rgb), alpha1); frag_data[1] = vec4(0.0,0.0,0.0,0.0); -//#define PACK_NORMALS -#ifdef PACK_NORMALS frag_data[2] = vec4(0.5,0.5,0.0,0.0); -#else - frag_data[2] = vec4(0.0,0.0,1.0,0.0); -#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl index d31cbfa28..7930b5d18 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl @@ -37,15 +37,10 @@ VARYING vec3 vary_normal; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -vec3 pack(vec3 norm) +vec2 encode_normal(vec3 n) { -//#define PACK_NORMALS -#ifdef PACK_NORMALS - float p = sqrt(8.0*norm.z+8.0); - return vec3(norm.xy/p + 0.5, 0.0); -#else - return norm.xyz*0.5+0.5; -#endif + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; } void main() @@ -60,6 +55,6 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(pack(nvn),0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl index c65539d43..8525e1333 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl @@ -36,15 +36,10 @@ uniform float minimum_alpha; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -vec3 pack(vec3 norm) +vec2 encode_normal(vec3 n) { -//#define PACK_NORMALS -#ifdef PACK_NORMALS - float p = sqrt(8.0*norm.z+8.0); - return vec3(norm.xy/p + 0.5, 0.0); -#else - return norm.xyz*0.5+0.5; -#endif + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; } void main() @@ -55,9 +50,9 @@ void main() { discard; } - + frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(pack(nvn), 0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl index 252975aad..37d70a241 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl @@ -37,15 +37,10 @@ uniform sampler2D diffuseMap; VARYING vec3 vary_normal; VARYING vec2 vary_texcoord0; -vec3 pack(vec3 norm) +vec2 encode_normal(vec3 n) { -//#define PACK_NORMALS -#ifdef PACK_NORMALS - float p = sqrt(8.0*norm.z+8.0); - return vec3(norm.xy/p + 0.5, 0.0); -#else - return norm.xyz*0.5+0.5; -#endif + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; } void main() @@ -60,6 +55,6 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(pack(nvn),0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index ac33fd261..6befb1bd8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -35,15 +35,10 @@ VARYING vec3 vary_normal; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -vec3 pack(vec3 norm) +vec2 encode_normal(vec3 n) { -//#define PACK_NORMALS -#ifdef PACK_NORMALS - float p = sqrt(8.0*norm.z+8.0); - return vec3(norm.xy/p + 0.5, 0.0); -#else - return norm.xyz*0.5+0.5; -#endif + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; } void main() @@ -53,6 +48,6 @@ void main() frag_data[1] = vertex_color.aaaa; // 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(vary_normal); - frag_data[2] = vec4(pack(nvn),0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl index b97cd060d..adc361d7a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl @@ -33,24 +33,22 @@ VARYING vec3 vary_normal; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -vec3 pack(vec3 norm) +vec2 encode_normal(vec3 n) { -//#define PACK_NORMALS -#ifdef PACK_NORMALS - float p = sqrt(8.0*norm.z+8.0); - return vec3(norm.xy/p + 0.5, 0.0); -#else - return norm.xyz*0.5+0.5; -#endif + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; } + void main() { vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb; + + vec3 spec; + spec.rgb = vec3(vertex_color.a); frag_data[0] = vec4(col, 0.0); - frag_data[1] = vertex_color.aaaa; // 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 + frag_data[1] = vec4(spec, vertex_color.a); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(pack(nvn),0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl b/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl index 6aa4d7b4e..ed02c4a48 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl @@ -42,7 +42,7 @@ void main() float shadow = 1.0; vec4 color = diffuseLookup(vary_texcoord0.xy)*vertex_color; - + color.rgb = pow(color.rgb, vec3(2.2)); color.rgb = fullbrightAtmosTransport(color.rgb); color.rgb = fullbrightScaleSoftClip(color.rgb); diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl index 764afa7a7..41cee1db0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -31,22 +31,145 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif +#if !HAS_DIFFUSE_LOOKUP +uniform sampler2D diffuseMap; +#endif + +VARYING vec3 vary_position; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -vec3 fullbrightAtmosTransport(vec3 light); -vec3 fullbrightScaleSoftClip(vec3 light); +vec3 srgb_to_linear(vec3 cs) +{ + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lte); +#endif + +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + +vec3 fullbrightAtmosTransportDeferred(vec3 light) +{ + return light; +} + +vec3 fullbrightScaleSoftClipDeferred(vec3 light) +{ + //soft clip effect: + return light; +} + +#ifdef HAS_ALPHA_MASK +uniform float minimum_alpha; +#endif + +#ifdef WATER_FOG +uniform vec4 waterPlane; +uniform vec4 waterFogColor; +uniform float waterFogDensity; +uniform float waterFogKS; + +vec4 applyWaterFogDeferred(vec3 pos, vec4 color) +{ + //normalize view vector + vec3 view = normalize(pos); + float es = -(dot(view, waterPlane.xyz)); + + //find intersection point with water plane and eye vector + + //get eye depth + float e0 = max(-waterPlane.w, 0.0); + + vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0); + + //get object depth + float depth = length(pos - int_v); + + //get "thickness" of water + float l = max(depth, 0.1); + + float kd = waterFogDensity; + float ks = waterFogKS; + vec4 kc = waterFogColor; + + float F = 0.98; + + float t1 = -kd * pow(F, ks * e0); + float t2 = kd + ks * es; + float t3 = pow(F, t2*l) - 1.0; + + float L = min(t1/t2*t3, 1.0); + + float D = pow(0.98, l*kd); + + color.rgb = color.rgb * D + kc.rgb * L; + color.a = kc.a + color.a; + + return color; +} +#endif void main() { - float shadow = 1.0; +#if HAS_DIFFUSE_LOOKUP + vec4 color = diffuseLookup(vary_texcoord0.xy); +#else + vec4 color = texture2D(diffuseMap, vary_texcoord0.xy); +#endif - vec4 color = diffuseLookup(vary_texcoord0.xy)*vertex_color; + float final_alpha = color.a * vertex_color.a; + +#ifdef HAS_ALPHA_MASK + if (color.a < minimum_alpha) + { + discard; + } +#endif + + color.rgb *= vertex_color.rgb; + color.rgb = srgb_to_linear(color.rgb); + color.rgb = fullbrightAtmosTransportDeferred(color.rgb); + color.rgb = fullbrightScaleSoftClipDeferred(color.rgb); - color.rgb = fullbrightAtmosTransport(color.rgb); + color.rgb = linear_to_srgb(color.rgb); - color.rgb = fullbrightScaleSoftClip(color.rgb); +#ifdef WATER_FOG + vec3 pos = vary_position; + vec4 fogged = applyWaterFogDeferred(pos, vec4(color.rgb, final_alpha)); + color.rgb = fogged.rgb; + //color.a = fogged.a; +#else + //color.a = final_alpha; +#endif color.a = .0; frag_color = color; diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl similarity index 51% rename from indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl rename to indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl index beb329018..edc6ff049 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl @@ -1,5 +1,5 @@ /** - * @file alphaF.glsl + * @file fullbrightShinyF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code @@ -23,7 +23,7 @@ * $/LicenseInfo$ */ -#extension GL_ARB_texture_rectangle : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -31,59 +31,42 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRect depthMap; +#ifndef diffuseLookup uniform sampler2D diffuseMap; +#endif - -uniform vec2 screen_res; - -vec3 atmosLighting(vec3 light); -vec3 scaleSoftClip(vec3 light); - -VARYING vec3 vary_ambient; -VARYING vec3 vary_directional; -VARYING vec3 vary_fragcoord; -VARYING vec3 vary_position; -VARYING vec3 vary_pointlight_col; -VARYING vec2 vary_texcoord0; VARYING vec4 vertex_color; +VARYING vec2 vary_texcoord0; +VARYING vec3 vary_texcoord1; -uniform mat4 inv_proj; +uniform samplerCube environmentMap; -vec4 getPosition(vec2 pos_screen) +vec3 fullbrightShinyAtmosTransport(vec3 light); +vec3 fullbrightScaleSoftClip(vec3 light); + +void main() { - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +#if HAS_DIFFUSE_LOOKUP + vec4 color = diffuseLookup(vary_texcoord0.xy); +#else + vec4 color = texture2D(diffuseMap, vary_texcoord0.xy); +#endif -void main() -{ - vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - frag *= screen_res; - vec4 pos = vec4(vary_position, 1.0); + color.rgb *= vertex_color.rgb; - vec4 diff= texture2D(diffuseMap,vary_texcoord0.xy); + vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb; + color.rgb = mix(color.rgb, envColor.rgb, vertex_color.a); - vec4 col = vec4(vary_ambient + vary_directional.rgb, vertex_color.a); - vec4 color = diff * col; + color.rgb = pow(color.rgb,vec3(2.2f,2.2f,2.2f)); - color.rgb = atmosLighting(color.rgb); + color.rgb = fullbrightShinyAtmosTransport(color.rgb); + color.rgb = fullbrightScaleSoftClip(color.rgb); - color.rgb = scaleSoftClip(color.rgb); + color.a = 0.0; - color.rgb += diff.rgb * vary_pointlight_col.rgb; + color.rgb = pow(color.rgb, vec3(1.0/2.2)); frag_color = color; - //frag_color = vec4(1,0,1,1); - //frag_color = vec4(1,0,1,1)*shadow; - } diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl new file mode 100644 index 000000000..34bd8d445 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl @@ -0,0 +1,67 @@ +/** + * @file fullbrightShinyV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform mat3 normal_matrix; +uniform mat4 texture_matrix0; +uniform mat4 texture_matrix1; +uniform mat4 modelview_matrix; +uniform mat4 modelview_projection_matrix; + + +void calcAtmospherics(vec3 inPositionEye); + +uniform vec4 origin; + + + +ATTRIBUTE vec3 position; +void passTextureIndex(); +ATTRIBUTE vec3 normal; +ATTRIBUTE vec4 diffuse_color; +ATTRIBUTE vec2 texcoord0; + +VARYING vec4 vertex_color; +VARYING vec2 vary_texcoord0; +VARYING vec3 vary_texcoord1; + + +void main() +{ + //transform vertex + vec4 vert = vec4(position.xyz,1.0); + passTextureIndex(); + vec4 pos = (modelview_matrix * vert); + gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); + + vec3 norm = normalize(normal_matrix * normal); + vec3 ref = reflect(pos.xyz, -norm); + + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + vary_texcoord1 = (texture_matrix1*vec4(ref,1.0)).xyz; + + calcAtmospherics(pos.xyz); + + vertex_color = diffuse_color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl index 2e6982d10..0e623aa4f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl @@ -40,6 +40,9 @@ vec3 atmosAffectDirectionalLight(float lightIntensity); vec3 scaleDownLight(vec3 light); vec3 scaleUpLight(vec3 light); +#ifdef WATER_FOG +VARYING vec3 vary_position; +#endif VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; @@ -53,11 +56,15 @@ void main() passTextureIndex(); gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); - + +#ifdef WATER_FOG + vary_position = pos.xyz; +#endif + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; calcAtmospherics(pos.xyz); - + vertex_color = diffuse_color; diff --git a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl index 2cef8f2a5..a2b4b3b8c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl @@ -24,6 +24,7 @@ */ #extension GL_ARB_texture_rectangle : enable +#extension GL_ARB_shader_texture_lod : enable #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; diff --git a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl deleted file mode 100644 index da1b23424..000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl +++ /dev/null @@ -1,190 +0,0 @@ -/** - * @file giF.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#extension GL_ARB_texture_rectangle : enable - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform sampler2D noiseMap; - -uniform sampler2D diffuseGIMap; -uniform sampler2D normalGIMap; -uniform sampler2D depthGIMap; - -uniform sampler2D lightFunc; - -// Inputs -VARYING vec2 vary_fragcoord; - -uniform vec2 screen_res; - -uniform mat4 inv_proj; -uniform mat4 gi_mat; //gPipeline.mGIMatrix - eye space to sun space -uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space -uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix -uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space -uniform float gi_radius; -uniform float gi_intensity; -uniform int gi_samples; -uniform vec2 gi_kern[25]; -uniform vec2 gi_scale; -uniform vec3 gi_quad; -uniform vec3 gi_spec; -uniform float gi_direction_weight; -uniform float gi_light_offset; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -vec4 getGIPosition(vec2 gi_tc) -{ - float depth = texture2D(depthGIMap, gi_tc).a; - vec2 sc = gi_tc*2.0; - sc -= vec2(1.0, 1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = gi_inv_proj*ndc; - pos.xyz /= pos.w; - pos.w = 1.0; - return pos; -} - -vec3 giAmbient(vec3 pos, vec3 norm) -{ - vec4 gi_c = gi_mat_proj * vec4(pos, 1.0); - gi_c.xyz /= gi_c.w; - - vec4 gi_pos = gi_mat*vec4(pos,1.0); - vec3 gi_norm = (gi_norm_mat*vec4(norm,1.0)).xyz; - gi_norm = normalize(gi_norm); - - vec2 tcx = gi_norm.xy; - vec2 tcy = gi_norm.yx; - - vec4 eye_pos = gi_mat*vec4(0,0,0,1.0); - - vec3 eye_dir = normalize(gi_pos.xyz-eye_pos.xyz/eye_pos.w); - - //vec3 eye_dir = vec3(0,0,-1); - //eye_dir = (gi_norm_mat*vec4(eye_dir, 1.0)).xyz; - //eye_dir = normalize(eye_dir); - - //float round_x = gi_scale.x; - //float round_y = gi_scale.y; - - vec3 debug = texture2D(normalGIMap, gi_c.xy).rgb*0.5+0.5; - debug.xz = vec2(0.0,0.0); - //debug = fract(debug); - - float round_x = 1.0/64.0; - float round_y = 1.0/64.0; - - //gi_c.x = floor(gi_c.x/round_x+0.5)*round_x; - //gi_c.y = floor(gi_c.y/round_y+0.5)*round_y; - - float fda = 0.0; - vec3 fdiff = vec3(0,0,0); - - vec3 rcol = vec3(0,0,0); - - float fsa = 0.0; - - for (int i = -1; i < 2; i+=2 ) - { - for (int j = -1; j < 2; j+=2) - { - vec2 tc = vec2(i, j)*0.75; - vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0+tc*0.5).xyz; - //tc += gi_norm.xy*nz.z; - tc += nz.xy*2.0; - tc /= gi_samples; - tc += gi_c.xy; - - vec3 lnorm = -normalize(texture2D(normalGIMap, tc.xy).xyz*2.0-1.0); - vec3 lpos = getGIPosition(tc.xy).xyz; - - vec3 at = lpos-gi_pos.xyz; - float dist = dot(at,at); - float da = clamp(1.0/(gi_spec.x*dist), 0.0, 1.0); - - if (da > 0.0) - { - //add angular attenuation - vec3 ldir = at; - float ang_atten = clamp(dot(ldir, gi_norm), 0.0, 1.0); - - float ld = -dot(ldir, lnorm); - - if (ang_atten > 0.0 && ld < 0.0) - { - vec3 diff = texture2D(diffuseGIMap, tc.xy).xyz; - da = da*ang_atten; - fda += da; - fdiff += diff*da; - } - } - } - } - - fdiff /= max(gi_spec.y*fda, gi_quad.z); - fdiff = clamp(fdiff, vec3(0), vec3(1)); - - vec3 ret = fda*fdiff; - //ret = ret*ret*gi_quad.x+ret*gi_quad.y+gi_quad.z; - - //fda *= nz.z; - - //rcol.rgb *= gi_intensity; - //return rcol.rgb+vary_AmblitColor.rgb*0.25; - //return vec4(debug, 0.0); - //return vec4(fda*fdiff, 0.0); - return clamp(ret,vec3(0.0), vec3(1.0)); - //return debug.xyz; -} - -void main() -{ - vec2 pos_screen = vary_fragcoord.xy; - vec4 pos = getPosition(pos_screen); - vec3 norm = texture2DRect(normalMap, pos_screen).xyz; - norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm - - frag_color.xyz = giAmbient(pos, norm); -} diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index bc0719cb8..f8fdde43f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -38,6 +38,42 @@ uniform sampler2D specularMap; VARYING vec2 vary_texcoord0; +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} + +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + void main() { vec4 col = texture2D(diffuseMap, vary_texcoord0.xy); @@ -47,7 +83,12 @@ void main() discard; } - frag_data[0] = vec4(col.rgb, col.a * 0.005); - frag_data[1] = texture2D(specularMap, vary_texcoord0.xy); - frag_data[2] = vec4(texture2D(normalMap, vary_texcoord0.xy).xyz, 0.0); + vec4 norm = texture2D(normalMap, vary_texcoord0.xy); + vec4 spec = texture2D(specularMap, vary_texcoord0.xy); + + col.rgb = linear_to_srgb(col.rgb); + + frag_data[0] = vec4(col.rgb, 0.0); + frag_data[1] = spec; + frag_data[2] = vec4(norm.xy,0,0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl new file mode 100644 index 000000000..04f17e853 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl @@ -0,0 +1,788 @@ +/** + * @file materialF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#define DIFFUSE_ALPHA_MODE_IGNORE 0 +#define DIFFUSE_ALPHA_MODE_BLEND 1 +#define DIFFUSE_ALPHA_MODE_MASK 2 +#define DIFFUSE_ALPHA_MODE_EMISSIVE 3 + +uniform float emissive_brightness; +//uniform float display_gamma; + +vec3 srgb_to_linear(vec3 cs) +{ + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lte); +#endif + +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +#if HAS_SUN_SHADOW + +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; + +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform vec2 shadow_res; +uniform float shadow_bias; + +float pcfShadow(sampler2DShadow shadowMap, vec4 stc) +{ + stc.xyz /= stc.w; + stc.z += shadow_bias; + + stc.x = floor(stc.x*shadow_res.x + fract(stc.y*shadow_res.y*12345))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here + + float cs = shadow2D(shadowMap, stc.xyz).x; + float shadow = cs; + + shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; + + return shadow*0.2; +} + +#endif + +uniform samplerCube environmentMap; +uniform sampler2D lightFunc; + +// Inputs +uniform vec4 morphFactor; +uniform vec3 camPosLocal; +//uniform vec4 camPosWorld; +uniform vec4 gamma; +uniform vec4 lightnorm; +uniform vec4 sunlight_color; +uniform vec4 ambient; +uniform vec4 blue_horizon; +uniform vec4 blue_density; +uniform float haze_horizon; +uniform float haze_density; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float distance_multiplier; +uniform float max_y; +uniform vec4 glow; +uniform float scene_light_strength; +uniform mat3 env_mat; +uniform mat3 ssao_effect_mat; + +uniform vec3 sun_dir; +VARYING vec2 vary_fragcoord; + +VARYING vec3 vary_position; + +vec3 vary_PositionEye; + +vec3 vary_SunlitColor; +vec3 vary_AmblitColor; +vec3 vary_AdditiveColor; +vec3 vary_AtmosAttenuation; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +uniform vec4 light_position[8]; +uniform vec3 light_direction[8]; +uniform vec3 light_attenuation[8]; +uniform vec3 light_diffuse[8]; + +#ifdef WATER_FOG +uniform vec4 waterPlane; +uniform vec4 waterFogColor; +uniform float waterFogDensity; +uniform float waterFogKS; + +vec4 applyWaterFogDeferred(vec3 pos, vec4 color) +{ + //normalize view vector + vec3 view = normalize(pos); + float es = -(dot(view, waterPlane.xyz)); + + //find intersection point with water plane and eye vector + + //get eye depth + float e0 = max(-waterPlane.w, 0.0); + + vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0); + + //get object depth + float depth = length(pos - int_v); + + //get "thickness" of water + float l = max(depth, 0.1); + + float kd = waterFogDensity; + float ks = waterFogKS; + vec4 kc = waterFogColor; + + float F = 0.98; + + float t1 = -kd * pow(F, ks * e0); + float t2 = kd + ks * es; + float t3 = pow(F, t2*l) - 1.0; + + float L = min(t1/t2*t3, 1.0); + + float D = pow(0.98, l*kd); + + color.rgb = color.rgb * D + kc.rgb * L; + color.a = kc.a + color.a; + + return color; +} +#endif + +vec3 calcDirectionalLight(vec3 n, vec3 l) +{ + float a = max(dot(n,l),0.0); + return vec3(a,a,a); +} + + +vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + float da = 1.0; + + vec3 col = vec3(0,0,0); + + if (d > 0.0 && la > 0.0 && fa > 0.0) + { + //normalize light vector + lv = normalize(lv); + + //distance attenuation + float dist = d/la; + float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); + dist_atten *= dist_atten; + dist_atten *= 2.0; + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= max(dot(n, lv), 0.0); + + float lit = max(da * dist_atten, 0.0); + + col = light_col*lit*diffuse; + + if (spec.a > 0.0) + { + //vec3 ref = dot(pos+lv, norm); + vec3 h = normalize(lv+npos); + float nh = dot(n, h); + float nv = dot(n, npos); + float vh = dot(npos, h); + float sa = nh; + float fres = pow(1 - dot(h, npos), 5)*0.4+0.5; + + float gtdenom = 2 * nh; + float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); + + if (nh > 0.0) + { + float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); + vec3 speccol = lit*scol*light_col.rgb*spec.rgb; + col += speccol; + + float cur_glare = max(speccol.r, speccol.g); + cur_glare = max(cur_glare, speccol.b); + glare = max(glare, speccol.r); + glare += max(cur_glare, 0.0); + //col += spec.rgb; + } + } + } + + return max(col, vec3(0.0,0.0,0.0)); + +} + +vec4 getPosition_d(vec2 pos_screen, float depth) +{ + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +#ifndef WATER_FOG +vec3 getPositionEye() +{ + return vary_PositionEye; +} +#endif + +vec3 getSunlitColor() +{ + return vary_SunlitColor; +} +vec3 getAmblitColor() +{ + return vary_AmblitColor; +} +vec3 getAdditiveColor() +{ + return vary_AdditiveColor; +} +vec3 getAtmosAttenuation() +{ + return vary_AtmosAttenuation; +} + +void setPositionEye(vec3 v) +{ + vary_PositionEye = v; +} + +void setSunlitColor(vec3 v) +{ + vary_SunlitColor = v; +} + +void setAmblitColor(vec3 v) +{ + vary_AmblitColor = v; +} + +void setAdditiveColor(vec3 v) +{ + vary_AdditiveColor = v; +} + +void setAtmosAttenuation(vec3 v) +{ + vary_AtmosAttenuation = v; +} + +void calcAtmospherics(vec3 inPositionEye, float ambFactor) { + + vec3 P = inPositionEye; + setPositionEye(P); + + vec3 tmpLightnorm = lightnorm.xyz; + + vec3 Pn = normalize(P); + float Plen = length(P); + + vec4 temp1 = vec4(0); + vec3 temp2 = vec3(0); + vec4 blue_weight; + vec4 haze_weight; + vec4 sunlight = sunlight_color; + vec4 light_atten; + + //sunlight attenuation effect (hue and brightness) due to atmosphere + //this is used later for sunlight modulation at various altitudes + light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); + //I had thought blue_density and haze_density should have equal weighting, + //but attenuation due to haze_density tends to seem too strong + + temp1 = blue_density + vec4(haze_density); + blue_weight = blue_density / temp1; + haze_weight = vec4(haze_density) / temp1; + + //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain) + temp2.y = max(0.0, tmpLightnorm.y); + temp2.y = 1. / temp2.y; + sunlight *= exp( - light_atten * temp2.y); + + // main atmospheric scattering line integral + temp2.z = Plen * density_multiplier; + + // Transparency (-> temp1) + // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati + // compiler gets confused. + temp1 = exp(-temp1 * temp2.z * distance_multiplier); + + //final atmosphere attenuation factor + setAtmosAttenuation(temp1.rgb); + + //compute haze glow + //(can use temp2.x as temp because we haven't used it yet) + temp2.x = dot(Pn, tmpLightnorm.xyz); + temp2.x = 1. - temp2.x; + //temp2.x is 0 at the sun and increases away from sun + temp2.x = max(temp2.x, .03); //was glow.y + //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) + temp2.x *= glow.x; + //higher glow.x gives dimmer glow (because next step is 1 / "angle") + temp2.x = pow(temp2.x, glow.z); + //glow.z should be negative, so we're doing a sort of (1 / "angle") function + + //add "minimum anti-solar illumination" + temp2.x += .25; + + //increase ambient when there are more clouds + vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5; + + /* decrease value and saturation (that in HSV, not HSL) for occluded areas + * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html + * // The following line of code performs the equivalent of: + * float ambAlpha = tmpAmbient.a; + * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis + * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); + * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); + */ + tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); + + //haze color + setAdditiveColor( + vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient) + + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x + + tmpAmbient))); + + //brightness of surface both sunlight and ambient + setSunlitColor(vec3(sunlight * .5)); + setAmblitColor(vec3(tmpAmbient * .25)); + setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1)); +} + +vec3 atmosLighting(vec3 light) +{ + light *= getAtmosAttenuation().r; + light += getAdditiveColor(); + return (2.0 * light); +} + +vec3 atmosTransport(vec3 light) { + light *= getAtmosAttenuation().r; + light += getAdditiveColor() * 2.0; + return light; +} +vec3 atmosGetDiffuseSunlightColor() +{ + return getSunlitColor(); +} + +vec3 scaleDownLight(vec3 light) +{ + return (light / vec3(scene_light_strength, scene_light_strength, scene_light_strength)); +} + +vec3 scaleUpLight(vec3 light) +{ + return (light * vec3(scene_light_strength, scene_light_strength, scene_light_strength)); +} + +vec3 atmosAmbient(vec3 light) +{ + return getAmblitColor() + (light * vec3(0.5f, 0.5f, 0.5f)); +} + +vec3 atmosAffectDirectionalLight(float lightIntensity) +{ + return getSunlitColor() * vec3(lightIntensity, lightIntensity, lightIntensity); +} + +vec3 scaleSoftClip(vec3 light) +{ + //soft clip effect: + vec3 zeroes = vec3(0.0f, 0.0f, 0.0f); + vec3 ones = vec3(1.0f, 1.0f, 1.0f); + + light = ones - clamp(light, zeroes, ones); + light = ones - pow(light, gamma.xxx); + + return light; +} + +vec3 fullbrightAtmosTransport(vec3 light) { + float brightness = dot(light.rgb, vec3(0.33333)); + + return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness); +} + +vec3 fullbrightScaleSoftClip(vec3 light) +{ + //soft clip effect: + return light; +} + +#else +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData +#endif +#endif + +uniform sampler2D diffuseMap; + +#if HAS_NORMAL_MAP +uniform sampler2D bumpMap; +#endif + +#if HAS_SPECULAR_MAP +uniform sampler2D specularMap; + +VARYING vec2 vary_texcoord2; +#endif + +uniform float env_intensity; +uniform vec4 specular_color; // specular color RGB and specular exponent (glossiness) in alpha + +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK) +uniform float minimum_alpha; +#endif + +#if HAS_NORMAL_MAP +VARYING vec3 vary_mat0; +VARYING vec3 vary_mat1; +VARYING vec3 vary_mat2; +VARYING vec2 vary_texcoord1; +#else +VARYING vec3 vary_normal; +#endif + +VARYING vec4 vertex_color; +VARYING vec2 vary_texcoord0; + +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} + +void main() +{ + vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy); + diffcol.rgb *= vertex_color.rgb; + +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK) + if (diffcol.a < minimum_alpha) + { + discard; + } +#endif + +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) + vec3 gamma_diff = diffcol.rgb; + diffcol.rgb = srgb_to_linear(diffcol.rgb); +#endif + +#if HAS_SPECULAR_MAP + vec4 spec = texture2D(specularMap, vary_texcoord2.xy); + spec.rgb *= specular_color.rgb; +#else + vec4 spec = vec4(specular_color.rgb, 1.0); +#endif + +#if HAS_NORMAL_MAP + vec4 norm = texture2D(bumpMap, vary_texcoord1.xy); + + norm.xyz = norm.xyz * 2 - 1; + + vec3 tnorm = vec3(dot(norm.xyz,vary_mat0), + dot(norm.xyz,vary_mat1), + dot(norm.xyz,vary_mat2)); +#else + vec4 norm = vec4(0,0,0,1.0); + vec3 tnorm = vary_normal; +#endif + + norm.xyz = tnorm; + norm.xyz = normalize(norm.xyz); + + vec2 abnormal = encode_normal(norm.xyz); + norm.xyz = decode_normal(abnormal.xy); + + vec4 final_color = diffcol; + +#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE) + final_color.a = emissive_brightness; +#else + final_color.a = max(final_color.a, emissive_brightness); +#endif + + vec4 final_specular = spec; +#if HAS_SPECULAR_MAP + vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0); + final_specular.a = specular_color.a * norm.a; +#else + vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0); + final_specular.a = specular_color.a; +#endif + + +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) + //forward rendering, output just lit RGBA + vec3 pos = vary_position; + +#if HAS_SUN_SHADOW + float shadow = 0.0; + + vec4 spos = vec4(pos,1.0); + + if (spos.z > -shadow_clip.w) + { + vec4 lpos; + + vec4 near_split = shadow_clip*-0.75; + vec4 far_split = shadow_clip*-1.25; + vec4 transition_domain = near_split-far_split; + float weight = 0.0; + + if (spos.z < near_split.z) + { + lpos = shadow_matrix[3]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap3, lpos)*w; + weight += w; + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + + if (spos.z < near_split.y && spos.z > far_split.z) + { + lpos = shadow_matrix[2]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; + w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap2, lpos)*w; + weight += w; + } + + if (spos.z < near_split.x && spos.z > far_split.y) + { + lpos = shadow_matrix[1]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; + w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; + shadow += pcfShadow(shadowMap1, lpos)*w; + weight += w; + } + + if (spos.z > far_split.x) + { + lpos = shadow_matrix[0]*spos; + + float w = 1.0; + w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; + + shadow += pcfShadow(shadowMap0, lpos)*w; + weight += w; + } + + + shadow /= weight; + } + else + { + shadow = 1.0; + } +#else + float shadow = 1.0; +#endif + + spec = final_specular; + vec4 diffuse = final_color; + float envIntensity = final_normal.z; + + vec3 col = vec3(0.0f,0.0f,0.0f); + + float bloom = 0.0; + calcAtmospherics(pos.xyz, 1.0); + + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + + float da =dot(norm.xyz, sun_dir.xyz); + + float final_da = da; + final_da = min(final_da, shadow); + //final_da = max(final_da, diffuse.a); + final_da = max(final_da, 0.0f); + final_da = min(final_da, 1.0f); + final_da = pow(final_da, 1.0/1.3); + + col.rgb = atmosAmbient(col); + + float ambient = min(abs(da), 1.0); + ambient *= 0.5; + ambient *= ambient; + ambient = (1.0-ambient); + + col.rgb *= ambient; + + col.rgb = col.rgb + atmosAffectDirectionalLight(final_da); + + col.rgb *= gamma_diff.rgb; + + + float glare = 0.0; + + if (spec.a > 0.0) // specular reflection + { + // the old infinite-sky shiny reflection + // + + float sa = dot(refnormpersp, sun_dir.xyz); + vec3 dumbshiny = vary_SunlitColor*shadow*(texture2D(lightFunc, vec2(sa, spec.a)).r); + + // add the two types of shiny together + vec3 spec_contrib = dumbshiny * spec.rgb; + bloom = dot(spec_contrib, spec_contrib) / 6; + + glare = max(spec_contrib.r, spec_contrib.g); + glare = max(glare, spec_contrib.b); + + col += spec_contrib; + } + + + col = mix(col.rgb, diffcol.rgb, diffuse.a); + + if (envIntensity > 0.0) + { + //add environmentmap + vec3 env_vec = env_mat * refnormpersp; + + vec3 refcol = textureCube(environmentMap, env_vec).rgb; + + col = mix(col.rgb, refcol, + envIntensity); + + float cur_glare = max(refcol.r, refcol.g); + cur_glare = max(cur_glare, refcol.b); + cur_glare *= envIntensity*4.0; + glare += cur_glare; + } + + //col = mix(atmosLighting(col), fullbrightAtmosTransport(col), diffuse.a); + //col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col), diffuse.a); + + col = atmosLighting(col); + col = scaleSoftClip(col); + + //convert to linear space before adding local lights + col = srgb_to_linear(col); + + vec3 npos = normalize(-pos.xyz); + + vec3 light = vec3(0,0,0); + + #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare); + + LIGHT_LOOP(1) + LIGHT_LOOP(2) + LIGHT_LOOP(3) + LIGHT_LOOP(4) + LIGHT_LOOP(5) + LIGHT_LOOP(6) + LIGHT_LOOP(7) + + col.rgb += light.rgb; + + glare = min(glare, 1.0); + float al = max(diffcol.a,glare)*vertex_color.a; + + //convert to gamma space for display on screen + col.rgb = linear_to_srgb(col.rgb); + +#ifdef WATER_FOG + vec4 temp = applyWaterFogDeferred(pos, vec4(col.rgb, al)); + col.rgb = temp.rgb; + al = temp.a; +#endif + + frag_color.rgb = col.rgb; + frag_color.a = al; + +#else + frag_data[0] = final_color; + frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent. + frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity. +#endif +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl new file mode 100644 index 000000000..393d1e69d --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl @@ -0,0 +1,145 @@ +/** + * @file bumpV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#define DIFFUSE_ALPHA_MODE_IGNORE 0 +#define DIFFUSE_ALPHA_MODE_BLEND 1 +#define DIFFUSE_ALPHA_MODE_MASK 2 +#define DIFFUSE_ALPHA_MODE_EMISSIVE 3 + +#if HAS_SKIN +uniform mat4 modelview_matrix; +uniform mat4 projection_matrix; +mat4 getObjectSkinnedTransform(); +#else +uniform mat3 normal_matrix; +uniform mat4 modelview_projection_matrix; +#endif + +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) + +#if !HAS_SKIN +uniform mat4 modelview_matrix; +#endif + +VARYING vec3 vary_position; + +#endif + +uniform mat4 texture_matrix0; + +ATTRIBUTE vec3 position; +ATTRIBUTE vec4 diffuse_color; +ATTRIBUTE vec3 normal; +ATTRIBUTE vec2 texcoord0; + + +#if HAS_NORMAL_MAP +ATTRIBUTE vec4 tangent; +ATTRIBUTE vec2 texcoord1; + +VARYING vec3 vary_mat0; +VARYING vec3 vary_mat1; +VARYING vec3 vary_mat2; + +VARYING vec2 vary_texcoord1; +#else +VARYING vec3 vary_normal; +#endif + +#if HAS_SPECULAR_MAP +ATTRIBUTE vec2 texcoord2; +VARYING vec2 vary_texcoord2; +#endif + +VARYING vec4 vertex_color; +VARYING vec2 vary_texcoord0; + +void main() +{ +#if HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + + mat = modelview_matrix * mat; + + vec3 pos = (mat*vec4(position.xyz,1.0)).xyz; + +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) + vary_position = pos; +#endif + + gl_Position = projection_matrix*vec4(pos,1.0); + +#else + //transform vertex + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + +#endif + + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + +#if HAS_NORMAL_MAP + vary_texcoord1 = (texture_matrix0 * vec4(texcoord1,0,1)).xy; +#endif + +#if HAS_SPECULAR_MAP + vary_texcoord2 = (texture_matrix0 * vec4(texcoord2,0,1)).xy; +#endif + +#if HAS_SKIN + vec3 n = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz); +#if HAS_NORMAL_MAP + vec3 t = normalize((mat*vec4(tangent.xyz+position.xyz,1.0)).xyz-pos.xyz); + vec3 b = cross(n, t)*tangent.w; + + vary_mat0 = vec3(t.x, b.x, n.x); + vary_mat1 = vec3(t.y, b.y, n.y); + vary_mat2 = vec3(t.z, b.z, n.z); +#else //HAS_NORMAL_MAP +vary_normal = n; +#endif //HAS_NORMAL_MAP +#else //HAS_SKIN + vec3 n = normalize(normal_matrix * normal); +#if HAS_NORMAL_MAP + vec3 t = normalize(normal_matrix * tangent.xyz); + vec3 b = cross(n,t)*tangent.w; + //vec3 t = cross(b,n) * binormal.w; + + vary_mat0 = vec3(t.x, b.x, n.x); + vary_mat1 = vec3(t.y, b.y, n.y); + vary_mat2 = vec3(t.z, b.z, n.z); +#else //HAS_NORMAL_MAP + vary_normal = n; +#endif //HAS_NORMAL_MAP +#endif //HAS_SKIN + + vertex_color = diffuse_color; + +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) +#if !HAS_SKIN + vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; +#endif +#endif +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index 8a39a875c..236567219 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -45,9 +45,8 @@ uniform float sun_wash; uniform int light_count; -#define MAX_LIGHT_COUNT 16 -uniform vec4 light[MAX_LIGHT_COUNT]; -uniform vec4 light_col[MAX_LIGHT_COUNT]; +uniform vec4 light[LIGHT_COUNT]; +uniform vec4 light_col[LIGHT_COUNT]; VARYING vec4 vary_fragcoord; uniform vec2 screen_res; @@ -56,6 +55,23 @@ uniform float far_z; uniform mat4 inv_proj; +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} + vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).r; @@ -69,20 +85,6 @@ vec4 getPosition(vec2 pos_screen) return pos; } -vec3 unpack(vec2 tc) -{ -//#define PACK_NORMALS -#ifdef PACK_NORMALS - vec2 enc = texture2DRect(normalMap, tc).xy; - enc = enc*4.0-2.0; - float prod = dot(enc,enc); - return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); -#else - vec3 norm = texture2DRect(normalMap, tc).xyz; - return norm*2.0-1.0; -#endif -} - void main() { vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res; @@ -92,70 +94,71 @@ void main() discard; } - vec3 norm = unpack(frag.xy); // unpack norm - //norm = normalize(norm); // may be superfluous + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = decode_normal(norm.xy); // unpack norm + norm = normalize(norm); vec4 spec = texture2DRect(specularRect, frag.xy); vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb; + float noise = texture2D(noiseMap, frag.xy/128.0).b; vec3 out_col = vec3(0,0,0); vec3 npos = normalize(-pos); // As of OSX 10.6.7 ATI Apple's crash when using a variable size loop - for (int i = 0; i < MAX_LIGHT_COUNT; ++i) + for (int i = 0; i < LIGHT_COUNT; ++i) { - bool light_contrib = (i < light_count); - vec3 lv = light[i].xyz-pos; - float dist2 = dot(lv,lv); - dist2 /= light[i].w; - if (dist2 > 1.0) + float dist = length(lv); + dist /= light[i].w; + if (dist <= 1.0) { - light_contrib = false; - } - float da = dot(norm, lv); - if (da < 0.0) - { - light_contrib = false; - } - - if (light_contrib) + if (da > 0.0) { lv = normalize(lv); da = dot(norm, lv); - + float fa = light_col[i].a+1.0; - float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); + dist_atten *= dist_atten; + dist_atten *= 2.0; + dist_atten *= noise; float lit = da * dist_atten; - + vec3 col = light_col[i].rgb*lit*diff; + //vec3 col = vec3(dist2, light_col[i].a, lit); if (spec.a > 0.0) { + lit = min(da*6.0, 1.0) * dist_atten; //vec3 ref = dot(pos+lv, norm); - - float sa = dot(normalize(lv+npos),norm); - - if (sa > 0.0) + vec3 h = normalize(lv+npos); + float nh = dot(norm, h); + float nv = dot(norm, npos); + float vh = dot(npos, h); + float sa = nh; + float fres = pow(1 - dot(h, npos), 5)*0.4+0.5; + + float gtdenom = 2 * nh; + float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); + + if (nh > 0.0) { - sa = texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*light_col[i].rgb*spec.rgb; + float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); + col += lit*scol*light_col[i].rgb*spec.rgb; + //col += spec.rgb; } } out_col += col; } } - - if (dot(out_col, out_col) <= 0.0) - { - discard; } + frag_color.rgb = out_col; frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index a82ba899a..0e6ab80d4 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -32,6 +32,7 @@ out vec4 frag_color; //class 1 -- no shadows #extension GL_ARB_texture_rectangle : enable +#extension GL_ARB_shader_texture_lod : enable uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; @@ -40,6 +41,7 @@ uniform sampler2DRect normalMap; uniform samplerCube environmentMap; uniform sampler2D noiseMap; uniform sampler2D projectionMap; +uniform sampler2D lightFunc; uniform mat4 proj_mat; //screen space to light space uniform float proj_near; //near clip for projection @@ -66,9 +68,64 @@ uniform vec2 screen_res; uniform mat4 inv_proj; +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} +vec3 srgb_to_linear(vec3 cs) +{ + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lte); +#endif + +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + + vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); + ret.rgb = srgb_to_linear(ret.rgb); vec2 dist = tc-vec2(0.5); @@ -84,6 +141,7 @@ vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); + ret.rgb = srgb_to_linear(ret.rgb); vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); @@ -101,6 +159,7 @@ vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); + ret.rgb = srgb_to_linear(ret.rgb); vec2 dist = tc-vec2(0.5); @@ -125,20 +184,6 @@ vec4 getPosition(vec2 pos_screen) return pos; } -vec3 unpack(vec2 tc) -{ -//#define PACK_NORMALS -#ifdef PACK_NORMALS - vec2 enc = texture2DRect(normalMap, tc).xy; - enc = enc*4.0-2.0; - float prod = dot(enc,enc); - return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); -#else - vec3 norm = texture2DRect(normalMap, tc).xyz; - return norm*2.0-1.0; -#endif -} - void main() { vec4 frag = vary_fragcoord; @@ -148,16 +193,19 @@ void main() vec3 pos = getPosition(frag.xy).xyz; vec3 lv = center.xyz-pos.xyz; - float dist2 = dot(lv,lv); - dist2 /= size; - if (dist2 > 1.0) + float dist = length(lv); + dist /= size; + if (dist > 1.0) { discard; } - vec3 norm = unpack(frag.xy); // unpack norm + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + float envIntensity = norm.z; + + norm = decode_normal(norm.xy); - //norm = normalize(norm); // may be superfluous + norm = normalize(norm); float l_dist = -dot(lv, proj_n); vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); @@ -169,7 +217,10 @@ void main() proj_tc.xyz /= proj_tc.w; float fa = falloff+1.0; - float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); + float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0); + dist_atten *= dist_atten; + dist_atten *= 2.0; + if (dist_atten <= 0.0) { discard; @@ -182,7 +233,8 @@ void main() vec3 col = vec3(0,0,0); vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; - + vec3 dlit = vec3(0, 0, 0); + float noise = texture2D(noiseMap, frag.xy/128.0).b; if (proj_tc.z > 0.0 && proj_tc.x < 1.0 && @@ -200,14 +252,13 @@ void main() vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); - vec3 lcol = color.rgb * plcol.rgb * plcol.a; + dlit = color.rgb * plcol.rgb * plcol.a; lit = da * dist_atten * noise; - col = lcol*lit*diff_tex; + col = dlit*lit*diff_tex; amb_da += (da*0.5)*proj_ambiance; } - //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); @@ -216,13 +267,38 @@ void main() amb_da *= dist_atten * noise; amb_da = min(amb_da, 1.0-lit); - - col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + col += amb_da*color.rgb*diff_tex*amb_plcol.rgb*amb_plcol.a; } vec4 spec = texture2DRect(specularRect, frag.xy); + if (spec.a > 0.0) + { + dlit *= min(da*6.0, 1.0) * dist_atten; + + vec3 npos = -normalize(pos); + + //vec3 ref = dot(pos+lv, norm); + vec3 h = normalize(lv+npos); + float nh = dot(norm, h); + float nv = dot(norm, npos); + float vh = dot(npos, h); + float sa = nh; + float fres = pow(1 - dot(h, npos), 5)*0.4+0.5; + + float gtdenom = 2 * nh; + float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); + + if (nh > 0.0) + { + float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); + col += dlit*scol*spec.rgb; + //col += spec.rgb; + } + } + + if (envIntensity > 0.0) { vec3 ref = reflect(normalize(pos), norm); @@ -235,12 +311,10 @@ void main() vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); - + stc /= stc.w; if (stc.z > 0.0) { - stc.xy /= stc.w; - - float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); + float fatten = clamp(envIntensity*envIntensity+envIntensity*0.25, 0.25, 1.0); stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); @@ -249,8 +323,7 @@ void main() stc.x > 0.0 && stc.y > 0.0) { - vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); - col += dist_atten*scol.rgb*color.rgb*scol.a*spec.rgb; + col += color.rgb*texture2DLodSpecular(projectionMap, stc.xy, proj_lod).rgb*spec.rgb; } } } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 107fd04f5..106d48bd7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -54,6 +54,23 @@ uniform vec2 screen_res; uniform mat4 inv_proj; uniform vec4 viewport; +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} + vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).r; @@ -67,20 +84,6 @@ vec4 getPosition(vec2 pos_screen) return pos; } -vec3 unpack(vec2 tc) -{ -//#define PACK_NORMALS -#ifdef PACK_NORMALS - vec2 enc = texture2DRect(normalMap, tc).xy; - enc = enc*4.0-2.0; - float prod = dot(enc,enc); - return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); -#else - vec3 norm = texture2DRect(normalMap, tc).xyz; - return norm*2.0-1.0; -#endif -} - void main() { vec4 frag = vary_fragcoord; @@ -90,21 +93,22 @@ void main() vec3 pos = getPosition(frag.xy).xyz; vec3 lv = trans_center.xyz-pos; - float dist2 = dot(lv,lv); - dist2 /= size; - if (dist2 > 1.0) + float dist = length(lv); + dist /= size; + if (dist > 1.0) { discard; } - vec3 norm = unpack(frag.xy); // unpack norm + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = decode_normal(norm.xy); // unpack norm float da = dot(norm, lv); if (da < 0.0) { discard; } - //norm = normalize(norm); // may be superfluous + norm = normalize(norm); lv = normalize(lv); da = dot(norm, lv); @@ -112,20 +116,33 @@ void main() vec3 col = texture2DRect(diffuseRect, frag.xy).rgb; float fa = falloff+1.0; - float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - float lit = da * dist_atten * noise; + float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); + dist_atten *= dist_atten; + dist_atten *= 2.0; + float lit = da * dist_atten * noise; + col = color.rgb*lit*col; vec4 spec = texture2DRect(specularRect, frag.xy); if (spec.a > 0.0) { - float sa = dot(normalize(lv-normalize(pos)),norm); - if (sa > 0.0) + lit = min(da*6.0, 1.0) * dist_atten; + + vec3 npos = -normalize(pos); + vec3 h = normalize(lv+npos); + float nh = dot(norm, h); + float nv = dot(norm, npos); + float vh = dot(npos, h); + float sa = nh; + float fres = pow(1 - dot(h, npos), 5) * 0.4+0.5; + float gtdenom = 2 * nh; + float gt = max(0,(min(gtdenom * nv / vh, gtdenom * da / vh))); + + if (nh > 0.0) { - sa = texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*color.rgb*spec.rgb; + float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); + col += lit*scol*color.rgb*spec.rgb; } } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl index 949142123..a5625fbc1 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl @@ -37,7 +37,7 @@ VARYING vec3 trans_center; void main() { //transform vertex - vec3 p = position*sqrt(size)+center; + vec3 p = position*size+center; vec4 pos = modelview_projection_matrix * vec4(p.xyz, 1.0); vary_fragcoord = pos; trans_center = (modelview_matrix*vec4(center.xyz, 1.0)).xyz; diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl new file mode 100644 index 000000000..126f17fab --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl @@ -0,0 +1,67 @@ +/** + * @file postDeferredGammaCorrect.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#extension GL_ARB_texture_rectangle : enable + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform sampler2DRect diffuseRect; + +uniform vec2 screen_res; +VARYING vec2 vary_fragcoord; + +//uniform float display_gamma; + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + + +void main() +{ + vec4 diff = texture2DRect(diffuseRect, vary_fragcoord); + diff.rgb = linear_to_srgb(diff.rgb); + frag_color = diff; +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl index 4eefdd8b6..3e861a043 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl @@ -61,11 +61,7 @@ void main() /// Gamma correct for WL (soft clip effect). frag_data[0] = vec4(scaleSoftClip(color.rgb), 1.0); frag_data[1] = vec4(vary_HazeColor.a,0.0,0.0,0.0); -//#define PACK_NORMALS -#ifdef PACK_NORMALS - frag_data[2] = vec4(0.5,0.5,0.0,0.0); -#else - frag_data[2] = vec4(0.0,0.0,1.0,0.0); -#endif + frag_data[2] = vec4(0.5,0.5,0.0,1.0); + } diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 302f31d28..edab4d4e8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -24,6 +24,7 @@ */ #extension GL_ARB_texture_rectangle : enable +#extension GL_ARB_shader_texture_lod : enable #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -60,6 +61,7 @@ uniform float density_multiplier; uniform float distance_multiplier; uniform float max_y; uniform vec4 glow; +uniform float global_gamma; uniform float scene_light_strength; uniform mat3 env_mat; uniform float ssao_effect; @@ -77,6 +79,54 @@ vec3 vary_AtmosAttenuation; uniform mat4 inv_proj; uniform vec2 screen_res; +vec3 srgb_to_linear(vec3 cs) +{ + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lte); +#endif + +} + +vec3 linear_to_srgb(vec3 cl) +{ + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} + vec4 getPosition_d(vec2 pos_screen, float depth) { vec2 sc = pos_screen.xy*2.0; @@ -142,6 +192,52 @@ void setAtmosAttenuation(vec3 v) vary_AtmosAttenuation = v; } +#ifdef WATER_FOG +uniform vec4 waterPlane; +uniform vec4 waterFogColor; +uniform float waterFogDensity; +uniform float waterFogKS; + +vec4 applyWaterFogDeferred(vec3 pos, vec4 color) +{ + //normalize view vector + vec3 view = normalize(pos); + float es = -(dot(view, waterPlane.xyz)); + + //find intersection point with water plane and eye vector + + //get eye depth + float e0 = max(-waterPlane.w, 0.0); + + vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0); + + //get object depth + float depth = length(pos - int_v); + + //get "thickness" of water + float l = max(depth, 0.1); + + float kd = waterFogDensity; + float ks = waterFogKS; + vec4 kc = waterFogColor; + + float F = 0.98; + + float t1 = -kd * pow(F, ks * e0); + float t2 = kd + ks * es; + float t3 = pow(F, t2*l) - 1.0; + + float L = min(t1/t2*t3, 1.0); + + float D = pow(0.98, l*kd); + + color.rgb = color.rgb * D + kc.rgb * L; + color.a = kc.a + color.a; + + return color; +} +#endif + void calcAtmospherics(vec3 inPositionEye, float ambFactor) { vec3 P = inPositionEye; @@ -230,6 +326,15 @@ vec3 atmosTransport(vec3 light) { light += getAdditiveColor() * 2.0; return light; } + +vec3 fullbrightAtmosTransport(vec3 light) { + float brightness = dot(light.rgb, vec3(0.33333)); + + return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness); +} + + + vec3 atmosGetDiffuseSunlightColor() { return getSunlitColor(); @@ -264,18 +369,10 @@ vec3 scaleSoftClip(vec3 light) return light; } -vec3 unpack(vec2 tc) +vec3 fullbrightScaleSoftClip(vec3 light) { -//#define PACK_NORMALS -#ifdef PACK_NORMALS - vec2 enc = texture2DRect(normalMap, tc).xy; - enc = enc*4.0-2.0; - float prod = dot(enc,enc); - return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); -#else - vec3 norm = texture2DRect(normalMap, tc).xyz; - return norm*2.0-1.0; -#endif + //soft clip effect: + return light; } float luminance(vec3 color) @@ -290,57 +387,95 @@ void main() vec2 tc = vary_fragcoord.xy; float depth = texture2DRect(depthMap, tc.xy).r; vec3 pos = getPosition_d(tc, depth).xyz; - vec3 norm = unpack(tc); // unpack norm + vec4 norm = texture2DRect(normalMap, tc); + float envIntensity = norm.z; + norm.xyz = decode_normal(norm.xy); // unpack norm - float da = max(dot(norm.xyz, sun_dir.xyz), 0.0); - + float da = dot(norm.xyz, sun_dir.xyz); + + float final_da = max(0.0,da); + final_da = min(final_da, 1.0f); + final_da = pow(final_da, 1.0/1.3); + vec4 diffuse = texture2DRect(diffuseRect, tc); + + //convert to gamma space + diffuse.rgb = linear_to_srgb(diffuse.rgb); + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); - vec3 col; float bloom = 0.0; - if (diffuse.a < 0.9) { + bloom = spec.r*norm.w; + if (norm.w < 0.5) + { calcAtmospherics(pos.xyz, 1.0); col = atmosAmbient(vec3(0)); - col += atmosAffectDirectionalLight(max(min(da, 1.0), diffuse.a)); + float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0); + ambient *= 0.5; + ambient *= ambient; + ambient = (1.0-ambient); + + col.rgb *= ambient; + + col += atmosAffectDirectionalLight(final_da); col *= diffuse.rgb; + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + if (spec.a > 0.0) // specular reflection { // the old infinite-sky shiny reflection // - vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnormpersp, sun_dir.xyz); vec3 dumbshiny = vary_SunlitColor*(texture2D(lightFunc, vec2(sa, spec.a)).r); // add the two types of shiny together vec3 spec_contrib = dumbshiny * spec.rgb; - bloom = dot(spec_contrib, spec_contrib) / 4; + bloom = dot(spec_contrib, spec_contrib) / 6; col += spec_contrib; - - //add environmentmap - vec3 env_vec = env_mat * refnormpersp; - vec3 env = textureCube(environmentMap, env_vec).rgb; - bloom = (luminance(env) - .45)*.25; - col = mix(col.rgb, env, - max(spec.a-diffuse.a*2.0, 0.0)); } - - col = atmosLighting(col); - col = scaleSoftClip(col); + + + col = mix(col.rgb, diffuse.rgb, diffuse.a); + + if (envIntensity > 0.0) + { //add environmentmap + vec3 env_vec = env_mat * refnormpersp; + vec3 refcol = textureCube(environmentMap, env_vec).rgb; + bloom = (luminance(refcol) - .45)*.25; + col = mix(col.rgb, refcol, + envIntensity); + } + + //if (norm.w < 0.5) + { + col = mix(atmosLighting(col), fullbrightAtmosTransport(col), diffuse.a); + col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col), diffuse.a); + //bloom += (luminance(col))*.075; //This looks nice, but requires a larger glow rendertarget. + } - col = mix(col, diffuse.rgb, diffuse.a); - } - else - { - bloom = spec.r; - col = diffuse.rgb; + #ifdef WATER_FOG + vec4 fogged = applyWaterFogDeferred(pos,vec4(col, bloom)); + col = fogged.rgb; + bloom = fogged.a; + #endif + } + else + { + col = diffuse.rgb; + } + + col = srgb_to_linear(col); + + //col = vec3(1,0,1); + //col.g = envIntensity; } - frag_color.rgb = col; + frag_color.rgb = col.rgb; frag_color.a = bloom; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index ae64d8937..8d8a6c9dd 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -23,7 +23,9 @@ * $/LicenseInfo$ */ - +#extension GL_ARB_texture_rectangle : enable +#extension GL_ARB_shader_texture_lod : enable + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; #else @@ -32,8 +34,6 @@ out vec4 frag_color; //class 1 -- no shadows -#extension GL_ARB_texture_rectangle : enable - uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; uniform sampler2DRect depthMap; @@ -41,6 +41,7 @@ uniform sampler2DRect normalMap; uniform samplerCube environmentMap; uniform sampler2D noiseMap; uniform sampler2D projectionMap; +uniform sampler2D lightFunc; uniform mat4 proj_mat; //screen space to light space uniform float proj_near; //near clip for projection @@ -57,20 +58,79 @@ uniform float far_clip; uniform vec3 proj_origin; //origin of projection to be used for angular attenuation uniform float sun_wash; +uniform float size; uniform vec3 color; uniform float falloff; -uniform float size; -VARYING vec4 vary_fragcoord; VARYING vec3 trans_center; - +VARYING vec4 vary_fragcoord; uniform vec2 screen_res; uniform mat4 inv_proj; +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} + +vec3 srgb_to_linear(vec3 cs) +{ + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lte); +#endif + +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + +vec4 correctWithGamma(vec4 col) +{ + return vec4(srgb_to_linear(col.rgb), col.a); +} + vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); + ret = correctWithGamma(ret); vec2 dist = tc-vec2(0.5); @@ -86,6 +146,7 @@ vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); + ret = correctWithGamma(ret); vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); @@ -103,6 +164,7 @@ vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); + ret = correctWithGamma(ret); vec2 dist = tc-vec2(0.5); @@ -127,20 +189,6 @@ vec4 getPosition(vec2 pos_screen) return pos; } -vec3 unpack(vec2 tc) -{ -//#define PACK_NORMALS -#ifdef PACK_NORMALS - vec2 enc = texture2DRect(normalMap, tc).xy; - enc = enc*4.0-2.0; - float prod = dot(enc,enc); - return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); -#else - vec3 norm = texture2DRect(normalMap, tc).xyz; - return norm*2.0-1.0; -#endif -} - void main() { vec4 frag = vary_fragcoord; @@ -150,16 +198,19 @@ void main() vec3 pos = getPosition(frag.xy).xyz; vec3 lv = trans_center.xyz-pos.xyz; - float dist2 = dot(lv,lv); - dist2 /= size; - if (dist2 > 1.0) + float dist = length(lv); + dist /= size; + if (dist > 1.0) { discard; } - - vec3 norm = unpack(frag.xy); // unpack norm - //norm = normalize(norm); // may be superfluous + + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + float envIntensity = norm.z; + norm = decode_normal(norm.xy); + + norm = normalize(norm); float l_dist = -dot(lv, proj_n); vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); @@ -171,7 +222,10 @@ void main() proj_tc.xyz /= proj_tc.w; float fa = falloff+1.0; - float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); + float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0); + dist_atten *= dist_atten; + dist_atten *= 2.0; + if (dist_atten <= 0.0) { discard; @@ -185,31 +239,35 @@ void main() vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; + vec4 spec = texture2DRect(specularRect, frag.xy); + + + float noise = texture2D(noiseMap, frag.xy/128.0).b; + vec3 dlit = vec3(0, 0, 0); + if (proj_tc.z > 0.0 && proj_tc.x < 1.0 && proj_tc.y < 1.0 && proj_tc.x > 0.0 && proj_tc.y > 0.0) { - float lit = 0.0; float amb_da = proj_ambiance; + float lit = 0.0; if (da > 0.0) { + lit = da * dist_atten * noise; + float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); - - vec3 lcol = color.rgb * plcol.rgb * plcol.a; + dlit = color.rgb * plcol.rgb * plcol.a; - lit = da * dist_atten * noise; - - col = lcol*lit*diff_tex; - amb_da += (da*0.5)*proj_ambiance; + col = dlit*lit*diff_tex; + //amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; } - //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); @@ -218,13 +276,37 @@ void main() amb_da *= dist_atten * noise; amb_da = min(amb_da, 1.0-lit); - - col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a*diff_tex.rgb; } - - vec4 spec = texture2DRect(specularRect, frag.xy); + if (spec.a > 0.0) + { + dlit *= min(da*6.0, 1.0) * dist_atten; + vec3 npos = -normalize(pos); + + //vec3 ref = dot(pos+lv, norm); + vec3 h = normalize(lv+npos); + float nh = dot(norm, h); + float nv = dot(norm, npos); + float vh = dot(npos, h); + float sa = nh; + float fres = pow(1 - dot(h, npos), 5)*0.4+0.5; + + float gtdenom = 2 * nh; + float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); + + if (nh > 0.0) + { + + float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); + col += dlit*scol*spec.rgb; + //col += spec.rgb; + } + } + + + if (envIntensity > 0.0) { vec3 ref = reflect(normalize(pos), norm); @@ -242,8 +324,9 @@ void main() { stc.xy /= stc.w; - float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); + float fatten = clamp(envIntensity*envIntensity+envIntensity*0.5, 0.25, 1.0); + //stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); if (stc.x < 1.0 && @@ -251,8 +334,7 @@ void main() stc.x > 0.0 && stc.y > 0.0) { - vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); - col += dist_atten*scol.rgb*color.rgb*scol.a*spec.rgb; + col += color.rgb*texture2DLodSpecular(projectionMap, stc.xy, proj_lod-envIntensity*proj_lod).rgb*spec.rgb; } } } diff --git a/indra/newview/app_settings/shaders/class1/deferred/srgb.glsl b/indra/newview/app_settings/shaders/class1/deferred/srgb.glsl new file mode 100644 index 000000000..587f3d5a9 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/srgb.glsl @@ -0,0 +1,46 @@ +/** + * @file srgb.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +vec3 srgb_to_linear(vec3 cs) +{ + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + return mix(high_range, low_range, lte); + +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + + bvec3 lt = lessThan(cl,vec3(0.0031308)); + return mix(high_range, low_range, lt); + +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/srgb_mac.glsl b/indra/newview/app_settings/shaders/class1/deferred/srgb_mac.glsl new file mode 100644 index 000000000..6cc1e6e79 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/srgb_mac.glsl @@ -0,0 +1,54 @@ +/** + * @file srgb.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +vec3 srgb_to_linear(vec3 cs) +{ + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + + vec3 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + return result; +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + + bvec3 lt = lessThan(cl,vec3(0.0031308)); + + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl index 2e4b416c4..99e371cf8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl @@ -42,10 +42,5 @@ void main() frag_data[0] = vec4(col.rgb,col.a*custom_alpha); frag_data[1] = vec4(0,0,0,0); -//#define PACK_NORMALS -#ifdef PACK_NORMALS - frag_data[2] = vec4(0.5,0.5,0.0,0.0); -#else - frag_data[2] = vec4(0.0,0.0,1.0,0.0); -#endif + frag_data[2] = vec4(0.5,0.5,0.0,1.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl index 24a827e91..730f01117 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl @@ -49,6 +49,23 @@ VARYING vec2 vary_fragcoord; uniform mat4 inv_proj; uniform vec2 screen_res; +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} + vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).r; @@ -115,19 +132,6 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) return (rtn * rtn); } -vec3 unpack(vec2 tc) -{ -//#define PACK_NORMALS -#ifdef PACK_NORMALS - vec2 enc = texture2DRect(normalMap, tc).xy; - enc = enc*4.0-2.0; - float prod = dot(enc,enc); - return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); -#else - vec3 norm = texture2DRect(normalMap, tc).xyz; - return norm*2.0-1.0; -#endif -} void main() { vec2 pos_screen = vary_fragcoord.xy; @@ -136,7 +140,8 @@ void main() vec4 pos = getPosition(pos_screen); - vec3 norm = unpack(pos_screen); // unpack norm + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + norm = decode_normal(norm.xy); frag_color[0] = 1.0; frag_color[1] = calcAmbientOcclusion(pos, norm); diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index 3e4c5fc9c..52a429465 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -39,15 +39,10 @@ VARYING vec3 vary_normal; VARYING vec4 vary_texcoord0; VARYING vec4 vary_texcoord1; -vec3 pack(vec3 norm) +vec2 encode_normal(vec3 n) { -//#define PACK_NORMALS -#ifdef PACK_NORMALS - float p = sqrt(8.0*norm.z+8.0); - return vec3(norm.xy/p + 0.5, 0.0); -#else - return norm.xyz*0.5+0.5; -#endif + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; } void main() @@ -67,6 +62,6 @@ void main() frag_data[0] = vec4(outColor.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(pack(nvn),0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index 6cd309fdb..808750496 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -37,15 +37,10 @@ VARYING vec2 vary_texcoord0; uniform float minimum_alpha; -vec3 pack(vec3 norm) +vec2 encode_normal(vec3 n) { -//#define PACK_NORMALS -#ifdef PACK_NORMALS - float p = sqrt(8.0*norm.z+8.0); - return vec3(norm.xy/p + 0.5, 0.0); -#else - return norm.xyz*0.5+0.5; -#endif + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; } void main() @@ -59,5 +54,5 @@ void main() frag_data[0] = vec4(vertex_color.rgb*col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(pack(nvn),0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl new file mode 100644 index 000000000..78f841c73 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl @@ -0,0 +1,157 @@ +/** + * @file underWaterF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData +#endif + +uniform sampler2D diffuseMap; +uniform sampler2D bumpMap; +uniform sampler2D screenTex; +uniform sampler2D refTex; +uniform sampler2D screenDepth; + +uniform vec4 fogCol; +uniform vec3 lightDir; +uniform vec3 specular; +uniform float lightExp; +uniform vec2 fbScale; +uniform float refScale; +uniform float znear; +uniform float zfar; +uniform float kd; +uniform vec4 waterPlane; +uniform vec3 eyeVec; +uniform vec4 waterFogColor; +uniform float waterFogDensity; +uniform float waterFogKS; +uniform vec2 screenRes; + +//bigWave is (refCoord.w, view.w); +VARYING vec4 refCoord; +VARYING vec4 littleWave; +VARYING vec4 view; + +vec3 srgb_to_linear(vec3 cs) +{ + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lte); +#endif + +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec4 applyWaterFog(vec4 color, vec3 viewVec) +{ + //normalize view vector + vec3 view = normalize(viewVec); + float es = -view.z; + + //find intersection point with water plane and eye vector + + //get eye depth + float e0 = max(-waterPlane.w, 0.0); + + //get object depth + float depth = length(viewVec); + + //get "thickness" of water + float l = max(depth, 0.1); + + float kd = waterFogDensity; + float ks = waterFogKS; + vec4 kc = waterFogColor; + + float F = 0.98; + + float t1 = -kd * pow(F, ks * e0); + float t2 = kd + ks * es; + float t3 = pow(F, t2*l) - 1.0; + + float L = min(t1/t2*t3, 1.0); + + float D = pow(0.98, l*kd); + //return vec4(1.0, 0.0, 1.0, 1.0); + return color * D + kc * L; + //depth /= 10.0; + //return vec4(depth,depth,depth,0.0); +} + +void main() +{ + vec4 color; + + //get detail normals + vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0; + vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0; + vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0; + vec3 wavef = normalize(wave1+wave2+wave3); + + //figure out distortion vector (ripply) + vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; + distort = distort+wavef.xy*refScale; + + vec4 fb = texture2D(screenTex, distort); + + frag_data[0] = vec4(linear_to_srgb(fb.rgb), 1.0); // diffuse + frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec + frag_data[2] = vec4(encode_normal(wavef), 0.0, 0.0); // normalxyz, displace +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index b27822814..4b758772a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -67,15 +67,47 @@ VARYING vec4 littleWave; VARYING vec4 view; VARYING vec4 vary_position; -vec3 pack(vec3 norm) +vec3 srgb_to_linear(vec3 cs) { -//#define PACK_NORMALS -#ifdef PACK_NORMALS - float p = sqrt(8.0*norm.z+8.0); - return vec3(norm.xy/p + 0.5, 0.0); + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + return result; #else - return norm.xyz*0.5+0.5; + return mix(high_range, low_range, lte); #endif + +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; } void main() @@ -126,7 +158,7 @@ void main() refcol *= df1 * 0.333; vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5; - //wavef.z *= max(-viewVec.z, 0.1); + wavef.z *= max(-viewVec.z, 0.1); wavef = normalize(wavef); float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset; @@ -136,13 +168,14 @@ void main() vec2 refvec4 = distort+refdistort4/dmod; float dweight = min(dist2*blurMultiplier, 1.0); vec4 baseCol = texture2D(refTex, refvec4); + refcol = mix(baseCol*df2, refcol, dweight); //get specular component - //float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0); + float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0); //harden specular - //spec = pow(spec, 128.0); + spec = pow(spec, 128.0); //figure out distortion vector (ripply) vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0); @@ -153,25 +186,17 @@ void main() // Note we actually want to use just df1, but multiplying by 0.999999 gets around an nvidia compiler bug color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999); - float shadow = 1.0; vec4 pos = vary_position; - //vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; - vec4 spos = pos; - - //spec *= shadow; - //color.rgb += spec * specular; + color.rgb += spec * specular; color.rgb = atmosTransport(color.rgb); color.rgb = scaleSoftClip(color.rgb); + color.a = spec * sunAngle2; - //color.a = spec * sunAngle2; - - //wavef.z *= 0.1f; - //wavef = normalize(wavef); - vec3 screenspacewavef = (norm_mat*vec4(wavef, 1.0)).xyz; + vec3 screenspacewavef = normalize((norm_mat*vec4(wavef, 1.0)).xyz); - frag_data[0] = vec4(color.rgb, 0.5); // diffuse - frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec - frag_data[2] = vec4(pack(screenspacewavef), 0.5); + frag_data[0] = vec4(color.rgb, color.a); // diffuse + frag_data[1] = vec4(0); // speccolor, spec + frag_data[2] = vec4(encode_normal(screenspacewavef.xyz*0.5+0.5), 0.05, 0);// normalxy, 0, 0 } diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl index ece34dcc4..9734acf00 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl @@ -85,7 +85,7 @@ void main() pos.w = 1.0; pos = modelview_matrix*pos; - calcAtmospherics(view.xyz); + calcAtmospherics(pos.xyz); //pass wave parameters to pixel shader vec2 bigWave = (v.xy) * vec2(0.04,0.04) + d1 * time * 0.055; diff --git a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl index f77edde70..df65cb953 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl @@ -48,40 +48,40 @@ float wave(vec2 v, float t, float f, vec2 d, float s) void main() { //transform vertex + vec4 pos = vec4(position.xyz, 1.0); mat4 modelViewProj = modelview_projection_matrix; vec4 oPosition; //get view vector vec3 oEyeVec; - oEyeVec.xyz = position.xyz-eyeVec; + oEyeVec.xyz = pos.xyz-eyeVec; float d = length(oEyeVec.xy); float ld = min(d, 2560.0); - vec3 lpos = position; - lpos.xy = eyeVec.xy + oEyeVec.xy/d*ld; + pos.xy = eyeVec.xy + oEyeVec.xy/d*ld; view.xyz = oEyeVec; d = clamp(ld/1536.0-0.5, 0.0, 1.0); d *= d; - oPosition = vec4(lpos, 1.0); + oPosition = vec4(position, 1.0); oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d); oPosition = modelViewProj * oPosition; + refCoord.xyz = oPosition.xyz + vec3(0,0,0.2); //get wave position parameter (create sweeping horizontal waves) - vec3 v = lpos; + vec3 v = pos.xyz; v.x += (cos(v.x*0.08/*+time*0.01*/)+sin(v.y*0.02))*6.0; //push position for further horizon effect. - vec4 pos; pos.xyz = oEyeVec.xyz*(waterHeight/oEyeVec.z); pos.w = 1.0; pos = modelview_matrix*pos; - calcAtmospherics(view.xyz); + calcAtmospherics(pos.xyz); //pass wave parameters to pixel shader diff --git a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthF.glsl b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthF.glsl index 6523a06d2..f8efd7cb4 100644 --- a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthF.glsl @@ -31,8 +31,6 @@ out vec4 frag_color; uniform sampler2D depthMap; -uniform float delta; - VARYING vec2 tc0; VARYING vec2 tc1; VARYING vec2 tc2; diff --git a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl index 0e5dc0818..942c5888e 100644 --- a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl @@ -33,8 +33,6 @@ out vec4 frag_color; uniform sampler2DRect depthMap; -uniform float delta; - VARYING vec2 tc0; VARYING vec2 tc1; VARYING vec2 tc2; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl index 4070d41f4..b9ddbc8e1 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl @@ -41,13 +41,15 @@ VARYING vec2 vary_texcoord0; void default_lighting() { - vec4 color = texture2D(diffuseMap,vary_texcoord0.xy) * vertex_color; + vec4 color = texture2D(diffuseMap,vary_texcoord0.xy); if (color.a < minimum_alpha) { discard; } + color.rgb *= vertex_color.rgb; + color.rgb = atmosLighting(color.rgb); color.rgb = scaleSoftClip(color.rgb); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl index 6c34643aa..5740987ab 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl @@ -30,6 +30,7 @@ out vec4 frag_color; #endif uniform float minimum_alpha; +uniform float texture_gamma; vec3 fullbrightAtmosTransport(vec3 light); vec3 fullbrightScaleSoftClip(vec3 light); @@ -39,13 +40,16 @@ VARYING vec2 vary_texcoord0; void fullbright_lighting() { - vec4 color = diffuseLookup(vary_texcoord0.xy) * vertex_color; + vec4 color = diffuseLookup(vary_texcoord0.xy); if (color.a < minimum_alpha) { discard; } + color.rgb *= vertex_color.rgb; + + color.rgb = pow(color.rgb, vec3(texture_gamma)); color.rgb = fullbrightAtmosTransport(color.rgb); color.rgb = fullbrightScaleSoftClip(color.rgb); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl index 2ff7f795b..c8771a3f1 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl @@ -32,6 +32,8 @@ out vec4 frag_color; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +uniform float texture_gamma; + vec3 fullbrightAtmosTransport(vec3 light); vec3 fullbrightScaleSoftClip(vec3 light); @@ -39,10 +41,14 @@ void fullbright_lighting() { vec4 color = diffuseLookup(vary_texcoord0.xy) * vertex_color; + color.rgb = pow(color.rgb, vec3(texture_gamma)); + color.rgb = fullbrightAtmosTransport(color.rgb); color.rgb = fullbrightScaleSoftClip(color.rgb); + color.rgb = pow(color.rgb, vec3(1.0/texture_gamma)); + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl index f4477bd29..f72f20b03 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl @@ -30,6 +30,7 @@ out vec4 frag_color; #endif uniform float minimum_alpha; +uniform float texture_gamma; vec3 fullbrightAtmosTransport(vec3 light); vec3 fullbrightScaleSoftClip(vec3 light); @@ -41,17 +42,22 @@ VARYING vec2 vary_texcoord0; void fullbright_lighting() { - vec4 color = texture2D(diffuseMap,vary_texcoord0.xy) * vertex_color; + vec4 color = texture2D(diffuseMap,vary_texcoord0.xy); if (color.a < minimum_alpha) { discard; } + + color.rgb *= vertex_color.rgb; + color.rgb = pow(color.rgb, vec3(texture_gamma)); color.rgb = fullbrightAtmosTransport(color.rgb); color.rgb = fullbrightScaleSoftClip(color.rgb); + color.rgb = pow(color.rgb, vec3(1.0/texture_gamma)); + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl index 99a6fe85f..9c82056fd 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl @@ -31,7 +31,7 @@ out vec4 frag_color; uniform float minimum_alpha; -vec4 diffuseLookup(vec2 texcoord); +/* vec4 diffuseLookup(vec2 texcoord); */ vec3 fullbrightAtmosTransport(vec3 light); vec4 applyWaterFog(vec4 color); diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl deleted file mode 100644 index 8db4cb58c..000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ /dev/null @@ -1,168 +0,0 @@ -/** - * @file alphaF.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#extension GL_ARB_texture_rectangle : enable - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -VARYING vec4 vertex_color; -VARYING vec2 vary_texcoord0; - -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; -uniform sampler2DRect depthMap; - -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; -uniform vec2 screen_res; -uniform vec2 shadow_res; - -vec3 atmosLighting(vec3 light); -vec3 scaleSoftClip(vec3 light); - -VARYING vec3 vary_ambient; -VARYING vec3 vary_directional; -VARYING vec3 vary_fragcoord; -VARYING vec3 vary_position; -VARYING vec3 vary_pointlight_col; - -uniform float shadow_bias; - -uniform mat4 inv_proj; - -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc) -{ - stc.xyz /= stc.w; - stc.z += shadow_bias; - - stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here - - float cs = shadow2DRect(shadowMap, stc.xyz).x; - float shadow = cs; - - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; - - return shadow*0.2; -} - - -void main() -{ - vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - frag *= screen_res; - - float shadow = 0.0; - vec4 pos = vec4(vary_position, 1.0); - - vec4 spos = pos; - - if (spos.z > -shadow_clip.w) - { - vec4 lpos; - - vec4 near_split = shadow_clip*-0.75; - vec4 far_split = shadow_clip*-1.25; - vec4 transition_domain = near_split-far_split; - float weight = 0.0; - - if (spos.z < near_split.z) - { - lpos = shadow_matrix[3]*spos; - lpos.xy *= shadow_res; - - float w = 1.0; - w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap3, lpos)*w; - weight += w; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - - if (spos.z < near_split.y && spos.z > far_split.z) - { - lpos = shadow_matrix[2]*spos; - lpos.xy *= shadow_res; - - float w = 1.0; - w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; - w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap2, lpos)*w; - weight += w; - } - - if (spos.z < near_split.x && spos.z > far_split.y) - { - lpos = shadow_matrix[1]*spos; - lpos.xy *= shadow_res; - - float w = 1.0; - w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; - w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; - shadow += pcfShadow(shadowMap1, lpos)*w; - weight += w; - } - - if (spos.z > far_split.x) - { - lpos = shadow_matrix[0]*spos; - lpos.xy *= shadow_res; - - float w = 1.0; - w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; - - shadow += pcfShadow(shadowMap0, lpos)*w; - weight += w; - } - - - shadow /= weight; - } - else - { - shadow = 1.0; - } - - vec4 diff = diffuseLookup(vary_texcoord0.xy); - - vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, vertex_color.a); - vec4 color = diff * col; - - color.rgb = atmosLighting(color.rgb); - - color.rgb = scaleSoftClip(color.rgb); - - color.rgb += diff.rgb * vary_pointlight_col.rgb; - - frag_color = color; -} - diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl deleted file mode 100644 index 33958a501..000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl +++ /dev/null @@ -1,182 +0,0 @@ -/** - * @file alphaF.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#extension GL_ARB_texture_rectangle : enable - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; -uniform sampler2DRect depthMap; -uniform sampler2D diffuseMap; - -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; -uniform vec2 screen_res; -uniform vec2 shadow_res; - -vec3 atmosLighting(vec3 light); -vec3 scaleSoftClip(vec3 light); - -VARYING vec3 vary_ambient; -VARYING vec3 vary_directional; -VARYING vec3 vary_fragcoord; -VARYING vec3 vary_position; -VARYING vec3 vary_pointlight_col; -VARYING vec2 vary_texcoord0; -VARYING vec4 vertex_color; - -uniform float shadow_bias; - -uniform mat4 inv_proj; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos.xyz /= pos.w; - pos.w = 1.0; - return pos; -} - -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc) -{ - stc.xyz /= stc.w; - stc.z += shadow_bias; - - stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here - - float cs = shadow2DRect(shadowMap, stc.xyz).x; - float shadow = cs; - - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; - - return shadow*0.2; -} - - -void main() -{ - vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - frag *= screen_res; - - float shadow = 0.0; - vec4 pos = vec4(vary_position, 1.0); - - vec4 spos = pos; - - if (spos.z > -shadow_clip.w) - { - vec4 lpos; - - vec4 near_split = shadow_clip*-0.75; - vec4 far_split = shadow_clip*-1.25; - vec4 transition_domain = near_split-far_split; - float weight = 0.0; - - if (spos.z < near_split.z) - { - lpos = shadow_matrix[3]*spos; - lpos.xy *= shadow_res; - - float w = 1.0; - w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap3, lpos)*w; - weight += w; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - - if (spos.z < near_split.y && spos.z > far_split.z) - { - lpos = shadow_matrix[2]*spos; - lpos.xy *= shadow_res; - - float w = 1.0; - w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; - w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap2, lpos)*w; - weight += w; - } - - if (spos.z < near_split.x && spos.z > far_split.y) - { - lpos = shadow_matrix[1]*spos; - lpos.xy *= shadow_res; - - float w = 1.0; - w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; - w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; - shadow += pcfShadow(shadowMap1, lpos)*w; - weight += w; - } - - if (spos.z > far_split.x) - { - lpos = shadow_matrix[0]*spos; - lpos.xy *= shadow_res; - - float w = 1.0; - w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; - - shadow += pcfShadow(shadowMap0, lpos)*w; - weight += w; - } - - - shadow /= weight; - - } - else - { - shadow = 1.0; - } - - vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy); - - vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, vertex_color.a); - vec4 color = diff * col; - - color.rgb = atmosLighting(color.rgb); - - color.rgb = scaleSoftClip(color.rgb); - - color.rgb += diff.rgb * vary_pointlight_col.rgb; - - frag_color = color; -} - diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl deleted file mode 100644 index 2093fc37d..000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl +++ /dev/null @@ -1,187 +0,0 @@ -/** - * @file alphaNonIndexedNoColorF.glsl - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2005, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#extension GL_ARB_texture_rectangle : enable - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -uniform float minimum_alpha; - -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; -uniform sampler2DRect depthMap; -uniform sampler2D diffuseMap; - -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; -uniform vec2 screen_res; -uniform vec2 shadow_res; - -vec3 atmosLighting(vec3 light); -vec3 scaleSoftClip(vec3 light); - -VARYING vec3 vary_ambient; -VARYING vec3 vary_directional; -VARYING vec3 vary_fragcoord; -VARYING vec3 vary_position; -VARYING vec3 vary_pointlight_col; -VARYING vec2 vary_texcoord0; - -uniform float shadow_bias; - -uniform mat4 inv_proj; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos.xyz /= pos.w; - pos.w = 1.0; - return pos; -} - -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc) -{ - stc.xyz /= stc.w; - stc.z += shadow_bias; - - stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here - - float cs = shadow2DRect(shadowMap, stc.xyz).x; - float shadow = cs; - - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; - - return shadow*0.2; -} - - -void main() -{ - vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - frag *= screen_res; - - float shadow = 0.0; - vec4 pos = vec4(vary_position, 1.0); - - vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy); - - if (diff.a < minimum_alpha) - { - discard; - } - - vec4 spos = pos; - - if (spos.z > -shadow_clip.w) - { - vec4 lpos; - - vec4 near_split = shadow_clip*-0.75; - vec4 far_split = shadow_clip*-1.25; - vec4 transition_domain = near_split-far_split; - float weight = 0.0; - - if (spos.z < near_split.z) - { - lpos = shadow_matrix[3]*spos; - lpos.xy *= shadow_res; - - float w = 1.0; - w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap3, lpos)*w; - weight += w; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - - if (spos.z < near_split.y && spos.z > far_split.z) - { - lpos = shadow_matrix[2]*spos; - lpos.xy *= shadow_res; - - float w = 1.0; - w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; - w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap2, lpos)*w; - weight += w; - } - - if (spos.z < near_split.x && spos.z > far_split.y) - { - lpos = shadow_matrix[1]*spos; - lpos.xy *= shadow_res; - - float w = 1.0; - w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; - w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; - shadow += pcfShadow(shadowMap1, lpos)*w; - weight += w; - } - - if (spos.z > far_split.x) - { - lpos = shadow_matrix[0]*spos; - lpos.xy *= shadow_res; - - float w = 1.0; - w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; - - shadow += pcfShadow(shadowMap0, lpos)*w; - weight += w; - } - - - shadow /= weight; - } - else - { - shadow = 1.0; - } - - vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, 1.0); - vec4 color = diff * col; - - color.rgb = atmosLighting(color.rgb); - - color.rgb = scaleSoftClip(color.rgb); - - color.rgb += diff.rgb * vary_pointlight_col.rgb; - - frag_color = color; -} - diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl deleted file mode 100644 index 9629cfe82..000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl +++ /dev/null @@ -1,155 +0,0 @@ -/** - * @file alphaSkinnedV.glsl - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 projection_matrix; -uniform mat4 texture_matrix0; -uniform mat4 modelview_matrix; -uniform mat4 modelview_projection_matrix; - -ATTRIBUTE vec3 position; -ATTRIBUTE vec3 normal; -ATTRIBUTE vec4 diffuse_color; -ATTRIBUTE vec2 texcoord0; - -vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); -void calcAtmospherics(vec3 inPositionEye); - -float calcDirectionalLight(vec3 n, vec3 l); -mat4 getObjectSkinnedTransform(); -vec3 atmosAmbient(vec3 light); -vec3 atmosAffectDirectionalLight(float lightIntensity); -vec3 scaleDownLight(vec3 light); -vec3 scaleUpLight(vec3 light); - -VARYING vec3 vary_ambient; -VARYING vec3 vary_directional; -VARYING vec3 vary_fragcoord; -VARYING vec3 vary_position; -VARYING vec3 vary_pointlight_col; - -VARYING vec4 vertex_color; -VARYING vec2 vary_texcoord0; - - -uniform float near_clip; -uniform float shadow_offset; -uniform float shadow_bias; - -uniform vec4 light_position[8]; -uniform vec3 light_direction[8]; -uniform vec3 light_attenuation[8]; -uniform vec3 light_diffuse[8]; - -float calcDirectionalLight(vec3 n, vec3 l) -{ - float a = max(dot(n,l),0.0); - return a; -} - -float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) -{ -//get light vector - vec3 lv = lp.xyz-v; - - //get distance - float d = dot(lv,lv); - - float da = 0.0; - - if (d > 0.0 && la > 0.0 && fa > 0.0) - { - //normalize light vector - lv = normalize(lv); - - //distance attenuation - float dist2 = d/la; - da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 - - //angular attenuation - da *= max(dot(n, lv), 0.0); - } - - return da; -} - -void main() -{ - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - - mat4 mat = getObjectSkinnedTransform(); - - mat = modelview_matrix * mat; - - vec3 pos = (mat*vec4(position, 1.0)).xyz; - - gl_Position = projection_matrix * vec4(pos, 1.0); - - vec4 n = vec4(position, 1.0); - n.xyz += normal.xyz; - n.xyz = (mat*n).xyz; - n.xyz = normalize(n.xyz-pos.xyz); - - vec3 norm = n.xyz; - - float dp_directional_light = max(0.0, dot(norm, light_position[0].xyz)); - vary_position = pos.xyz + light_position[0].xyz * (1.0-dp_directional_light)*shadow_offset; - - calcAtmospherics(pos.xyz); - - //vec4 color = calcLighting(pos.xyz, norm, diffuse_color, vec4(0.)); - vec4 col = vec4(0.0, 0.0, 0.0, diffuse_color.a); - - // Collect normal lights - col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].y, light_attenuation[2].z); - col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].y, light_attenuation[3].z); - col.rgb += light_diffuse[4].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[4], light_direction[4], light_attenuation[4].x, light_attenuation[4].y, light_attenuation[4].z); - col.rgb += light_diffuse[5].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[5], light_direction[5], light_attenuation[5].x, light_attenuation[5].y, light_attenuation[5].z); - col.rgb += light_diffuse[6].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[6], light_direction[6], light_attenuation[6].x, light_attenuation[6].y, light_attenuation[6].z); - col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].y, light_attenuation[7].z); - - vary_pointlight_col = col.rgb*diffuse_color.rgb; - - col.rgb = vec3(0,0,0); - - // Add windlight lights - col.rgb = atmosAmbient(vec3(0.)); - - vary_ambient = col.rgb*diffuse_color.rgb; - vary_directional.rgb = diffuse_color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, light_position[0].xyz), (1.0-diffuse_color.a)*(1.0-diffuse_color.a))); - - col.rgb = min(col.rgb*diffuse_color.rgb, 1.0); - - vertex_color = col; - - - - pos.xyz = (modelview_projection_matrix * vec4(position.xyz, 1.0)).xyz; - vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); - -} - diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl deleted file mode 100644 index 1586aab0f..000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl +++ /dev/null @@ -1,150 +0,0 @@ -/** - * @file alphaV.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat3 normal_matrix; -uniform mat4 texture_matrix0; -uniform mat4 modelview_matrix; -uniform mat4 modelview_projection_matrix; - -ATTRIBUTE vec3 position; -void passTextureIndex(); -ATTRIBUTE vec3 normal; -ATTRIBUTE vec4 diffuse_color; -ATTRIBUTE vec2 texcoord0; - -vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); -void calcAtmospherics(vec3 inPositionEye); - -float calcDirectionalLight(vec3 n, vec3 l); - -vec3 atmosAmbient(vec3 light); -vec3 atmosAffectDirectionalLight(float lightIntensity); -vec3 scaleDownLight(vec3 light); -vec3 scaleUpLight(vec3 light); - -VARYING vec3 vary_ambient; -VARYING vec3 vary_directional; -VARYING vec3 vary_fragcoord; -VARYING vec3 vary_position; -VARYING vec3 vary_pointlight_col; - -VARYING vec4 vertex_color; -VARYING vec2 vary_texcoord0; - - -uniform float near_clip; -uniform float shadow_offset; -uniform float shadow_bias; - -uniform vec4 light_position[8]; -uniform vec3 light_direction[8]; -uniform vec3 light_attenuation[8]; -uniform vec3 light_diffuse[8]; - -float calcDirectionalLight(vec3 n, vec3 l) -{ - float a = max(dot(n,l),0.0); - return a; -} - -float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) -{ - //get light vector - vec3 lv = lp.xyz-v; - - //get distance - float d = dot(lv,lv); - - float da = 0.0; - - if (d > 0.0 && la > 0.0 && fa > 0.0) - { - //normalize light vector - lv = normalize(lv); - - //distance attenuation - float dist2 = d/la; - da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 - - //angular attenuation - da *= max(dot(n, lv), 0.0); - } - - return da; -} - -void main() -{ - //transform vertex - vec4 vert = vec4(position.xyz, 1.0); - passTextureIndex(); - vec4 pos = (modelview_matrix * vert); - gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); - - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - - vec3 norm = normalize(normal_matrix * normal); - - float dp_directional_light = max(0.0, dot(norm, light_position[0].xyz)); - vary_position = pos.xyz + light_position[0].xyz * (1.0-dp_directional_light)*shadow_offset; - - calcAtmospherics(pos.xyz); - - //vec4 color = calcLighting(pos.xyz, norm, diffuse_color, vec4(0.)); - vec4 col = vec4(0.0, 0.0, 0.0, diffuse_color.a); - - - // Collect normal lights - col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].y, light_attenuation[2].z); - col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].y, light_attenuation[3].z); - col.rgb += light_diffuse[4].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[4], light_direction[4], light_attenuation[4].x, light_attenuation[4].y, light_attenuation[4].z); - col.rgb += light_diffuse[5].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[5], light_direction[5], light_attenuation[5].x, light_attenuation[5].y, light_attenuation[5].z); - col.rgb += light_diffuse[6].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[6], light_direction[6], light_attenuation[6].x, light_attenuation[6].y, light_attenuation[6].z); - col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].y, light_attenuation[7].z); - - vary_pointlight_col = col.rgb*diffuse_color.rgb; - - col.rgb = vec3(0,0,0); - - // Add windlight lights - col.rgb = atmosAmbient(vec3(0.)); - - vary_ambient = col.rgb*diffuse_color.rgb; - vary_directional.rgb = diffuse_color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, light_position[0].xyz), (1.0-diffuse_color.a)*(1.0-diffuse_color.a))); - - col.rgb = col.rgb*diffuse_color.rgb; - - vertex_color = col; - - - - pos = modelview_projection_matrix * vert; - vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); - -} diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl deleted file mode 100644 index 44aaa98b9..000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ /dev/null @@ -1,153 +0,0 @@ -/** - * @file avatarAlphaV.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 projection_matrix; - -ATTRIBUTE vec3 position; -ATTRIBUTE vec3 normal; -ATTRIBUTE vec2 texcoord0; - -vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); -mat4 getSkinnedTransform(); -void calcAtmospherics(vec3 inPositionEye); - -float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); - -vec3 atmosAmbient(vec3 light); -vec3 atmosAffectDirectionalLight(float lightIntensity); -vec3 scaleDownLight(vec3 light); -vec3 scaleUpLight(vec3 light); - -VARYING vec3 vary_position; -VARYING vec3 vary_ambient; -VARYING vec3 vary_directional; -VARYING vec3 vary_fragcoord; -VARYING vec3 vary_pointlight_col; -VARYING vec4 vertex_color; -VARYING vec2 vary_texcoord0; - -uniform vec4 color; - -uniform float near_clip; -uniform float shadow_offset; -uniform float shadow_bias; - -uniform vec4 light_position[8]; -uniform vec3 light_direction[8]; -uniform vec3 light_attenuation[8]; -uniform vec3 light_diffuse[8]; - -float calcDirectionalLight(vec3 n, vec3 l) -{ - float a = max(dot(n,l),0.0); - return a; -} - -float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) -{ - //get light vector - vec3 lv = lp.xyz-v; - - //get distance - float d = dot(lv,lv); - - float da = 0.0; - - if (d > 0.0 && la > 0.0 && fa > 0.0) - { - //normalize light vector - lv = normalize(lv); - - //distance attenuation - float dist2 = d/la; - da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 - - //angular attenuation - da *= max(dot(n, lv), 0.0); - } - - return da; -} - -void main() -{ - vary_texcoord0 = texcoord0; - - vec4 pos; - vec3 norm; - - mat4 trans = getSkinnedTransform(); - vec4 pos_in = vec4(position.xyz, 1.0); - pos.x = dot(trans[0], pos_in); - pos.y = dot(trans[1], pos_in); - pos.z = dot(trans[2], pos_in); - pos.w = 1.0; - - norm.x = dot(trans[0].xyz, normal); - norm.y = dot(trans[1].xyz, normal); - norm.z = dot(trans[2].xyz, normal); - norm = normalize(norm); - - gl_Position = projection_matrix * pos; - - float dp_directional_light = max(0.0, dot(norm, light_position[0].xyz)); - vary_position = pos.xyz + light_position[0].xyz * (1.0-dp_directional_light)*shadow_offset; - - calcAtmospherics(pos.xyz); - - vec4 col = vec4(0.0, 0.0, 0.0, 1.0); - - // Collect normal lights - col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].y, light_attenuation[2].z); - col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].y, light_attenuation[3].z); - col.rgb += light_diffuse[4].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[4], light_direction[4], light_attenuation[4].x, light_attenuation[4].y, light_attenuation[4].z); - col.rgb += light_diffuse[5].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[5], light_direction[5], light_attenuation[5].x, light_attenuation[5].y, light_attenuation[5].z); - col.rgb += light_diffuse[6].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[6], light_direction[6], light_attenuation[6].x, light_attenuation[6].y, light_attenuation[6].z); - col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].y, light_attenuation[7].z); - - vary_pointlight_col = col.rgb*color.rgb; - - col.rgb = vec3(0,0,0); - - // Add windlight lights - col.rgb = atmosAmbient(vec3(0.)); - - vary_ambient = col.rgb*color.rgb; - vary_directional = atmosAffectDirectionalLight(max(calcDirectionalLight(norm, light_position[0].xyz), 0.0)); - - col.rgb = col.rgb*color.rgb; - - vertex_color = col; - - - vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); -} - - diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index 7f6a31ef7..ac5b7d676 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -24,6 +24,7 @@ */ #extension GL_ARB_texture_rectangle : enable +#extension GL_ARB_shader_texture_lod : enable #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -39,6 +40,7 @@ uniform samplerCube environmentMap; uniform sampler2DRect lightMap; uniform sampler2D noiseMap; uniform sampler2D projectionMap; +uniform sampler2D lightFunc; uniform mat4 proj_mat; //screen space to light space uniform float proj_near; //near clip for projection @@ -67,10 +69,70 @@ uniform vec2 screen_res; uniform mat4 inv_proj; +vec3 srgb_to_linear(vec3 cs) +{ + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lte); +#endif + +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} + +vec4 correctWithGamma(vec4 col) +{ + return vec4(srgb_to_linear(col.rgb), col.a); +} + vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - + ret = correctWithGamma(ret); + vec2 dist = tc-vec2(0.5); float det = max(1.0-lod/(proj_lod*0.5), 0.0); @@ -85,7 +147,8 @@ vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - + ret = correctWithGamma(ret); + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); float det = min(lod/(proj_lod*0.5), 1.0); @@ -102,6 +165,7 @@ vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); + ret = correctWithGamma(ret); vec2 dist = tc-vec2(0.5); @@ -126,20 +190,6 @@ vec4 getPosition(vec2 pos_screen) return pos; } -vec3 unpack(vec2 tc) -{ -//#define PACK_NORMALS -#ifdef PACK_NORMALS - vec2 enc = texture2DRect(normalMap, tc).xy; - enc = enc*4.0-2.0; - float prod = dot(enc,enc); - return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); -#else - vec3 norm = texture2DRect(normalMap, tc).xyz; - return norm*2.0-1.0; -#endif -} - void main() { vec4 frag = vary_fragcoord; @@ -149,9 +199,9 @@ void main() vec3 pos = getPosition(frag.xy).xyz; vec3 lv = center.xyz-pos.xyz; - float dist2 = dot(lv,lv); - dist2 /= size; - if (dist2 > 1.0) + float dist = length(lv); + dist /= size; + if (dist > 1.0) { discard; } @@ -167,9 +217,13 @@ void main() shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); } - vec3 norm = unpack(frag.xy); // unpack norm + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; - //norm = normalize(norm); // may be superfluous + float envIntensity = norm.z; + + norm = decode_normal(norm.xy); + + norm = normalize(norm); float l_dist = -dot(lv, proj_n); vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); @@ -181,7 +235,9 @@ void main() proj_tc.xyz /= proj_tc.w; float fa = falloff+1.0; - float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); + float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0); + dist_atten *= dist_atten; + dist_atten *= 2.0; if (dist_atten <= 0.0) { discard; @@ -190,11 +246,15 @@ void main() lv = proj_origin-pos.xyz; lv = normalize(lv); float da = dot(norm, lv); - + vec3 col = vec3(0,0,0); vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; - + + vec4 spec = texture2DRect(specularRect, frag.xy); + + vec3 dlit = vec3(0, 0, 0); + float noise = texture2D(noiseMap, frag.xy/128.0).b; if (proj_tc.z > 0.0 && proj_tc.x < 1.0 && @@ -202,21 +262,21 @@ void main() proj_tc.x > 0.0 && proj_tc.y > 0.0) { - float lit = 0.0; float amb_da = proj_ambiance; - + float lit = 0.0; + if (da > 0.0) { + lit = da * dist_atten * noise; + float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); - vec3 lcol = color.rgb * plcol.rgb * plcol.a; + dlit = color.rgb * plcol.rgb * plcol.a; - lit = da * dist_atten * noise; - - col = lcol*lit*diff_tex*shadow; + col = dlit*lit*diff_tex*shadow; amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; } @@ -232,9 +292,36 @@ void main() col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; } - - vec4 spec = texture2DRect(specularRect, frag.xy); + if (spec.a > 0.0) + { + vec3 npos = -normalize(pos); + dlit *= min(da*6.0, 1.0) * dist_atten; + + //vec3 ref = dot(pos+lv, norm); + vec3 h = normalize(lv+npos); + float nh = dot(norm, h); + float nv = dot(norm, npos); + float vh = dot(npos, h); + float sa = nh; + float fres = pow(1 - dot(h, npos), 5)*0.4+0.5; + + float gtdenom = 2 * nh; + float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); + + if (nh > 0.0) + { + float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); + col += dlit*scol*spec.rgb*shadow; + //col += spec.rgb; + } + } + + + + + + if (envIntensity > 0.0) { vec3 ref = reflect(normalize(pos), norm); @@ -247,13 +334,12 @@ void main() vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); + stc /= stc.w; if (stc.z > 0.0) { - stc.xy /= stc.w; + float fatten = clamp(envIntensity*envIntensity+envIntensity*0.25, 0.25, 1.0); - float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); - stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); if (stc.x < 1.0 && @@ -261,13 +347,16 @@ void main() stc.x > 0.0 && stc.y > 0.0) { - vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); - col += dist_atten*scol.rgb*color.rgb*scol.a*spec.rgb*shadow; + col += color.rgb*texture2DLodSpecular(projectionMap, stc.xy, proj_lod).rgb*shadow*spec.rgb; } } } } + + //not sure why, but this line prevents MATBUG-194 + col = max(col, vec3(0.0)); + frag_color.rgb = col; frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index d490b5d46..64ac5ebb2 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -38,7 +38,6 @@ uniform sampler2DRect lightMap; uniform sampler2DRect depthMap; uniform samplerCube environmentMap; uniform sampler2D lightFunc; -uniform vec3 gi_quad; uniform float blur_size; uniform float blur_fidelity; @@ -60,16 +59,13 @@ uniform float density_multiplier; uniform float distance_multiplier; uniform float max_y; uniform vec4 glow; +uniform float global_gamma; uniform float scene_light_strength; uniform mat3 env_mat; uniform vec4 shadow_clip; -uniform float ssao_effect; - -uniform mat4 inv_proj; -uniform vec2 screen_res; +uniform mat3 ssao_effect_mat; uniform vec3 sun_dir; - VARYING vec2 vary_fragcoord; vec3 vary_PositionEye; @@ -79,11 +75,61 @@ vec3 vary_AmblitColor; vec3 vary_AdditiveColor; vec3 vary_AtmosAttenuation; -float luminance(vec3 color) +uniform mat4 inv_proj; +uniform vec2 screen_res; + +vec3 srgb_to_linear(vec3 cs) { - /// CALCULATING LUMINANCE (Using NTSC lum weights) - /// http://en.wikipedia.org/wiki/Luma_%28video%29 - return dot(color, vec3(0.299, 0.587, 0.114)); + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lte); +#endif + +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; } vec4 getPosition_d(vec2 pos_screen, float depth) @@ -125,7 +171,6 @@ vec3 getAtmosAttenuation() return vary_AtmosAttenuation; } - void setPositionEye(vec3 v) { vary_PositionEye = v; @@ -212,21 +257,78 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { //increase ambient when there are more clouds vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5; + /* decrease value and saturation (that in HSV, not HSL) for occluded areas + * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html + * // The following line of code performs the equivalent of: + * float ambAlpha = tmpAmbient.a; + * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis + * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); + * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); + */ + tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); + //haze color setAdditiveColor( vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x + tmpAmbient))); - // decrease ambient value for occluded areas - tmpAmbient *= mix(ssao_effect, 1.0, ambFactor); - //brightness of surface both sunlight and ambient + /*setSunlitColor(pow(vec3(sunlight * .5), vec3(global_gamma)) * global_gamma); + setAmblitColor(pow(vec3(tmpAmbient * .25), vec3(global_gamma)) * global_gamma); + setAdditiveColor(pow(getAdditiveColor() * vec3(1.0 - temp1), vec3(global_gamma)) * global_gamma);*/ + setSunlitColor(vec3(sunlight * .5)); setAmblitColor(vec3(tmpAmbient * .25)); setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1)); } +#ifdef WATER_FOG +uniform vec4 waterPlane; +uniform vec4 waterFogColor; +uniform float waterFogDensity; +uniform float waterFogKS; + +vec4 applyWaterFogDeferred(vec3 pos, vec4 color) +{ + //normalize view vector + vec3 view = normalize(pos); + float es = -(dot(view, waterPlane.xyz)); + + //find intersection point with water plane and eye vector + + //get eye depth + float e0 = max(-waterPlane.w, 0.0); + + vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0); + + //get object depth + float depth = length(pos - int_v); + + //get "thickness" of water + float l = max(depth, 0.1); + + float kd = waterFogDensity; + float ks = waterFogKS; + vec4 kc = waterFogColor; + + float F = 0.98; + + float t1 = -kd * pow(F, ks * e0); + float t2 = kd + ks * es; + float t3 = pow(F, t2*l) - 1.0; + + float L = min(t1/t2*t3, 1.0); + + float D = pow(0.98, l*kd); + + color.rgb = color.rgb * D + kc.rgb * L; + color.a = kc.a + color.a; + + return color; +} +#endif + vec3 atmosLighting(vec3 light) { light *= getAtmosAttenuation().r; @@ -239,6 +341,15 @@ vec3 atmosTransport(vec3 light) { light += getAdditiveColor() * 2.0; return light; } + +vec3 fullbrightAtmosTransport(vec3 light) { + float brightness = dot(light.rgb, vec3(0.33333)); + + return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness); +} + + + vec3 atmosGetDiffuseSunlightColor() { return getSunlitColor(); @@ -273,18 +384,18 @@ vec3 scaleSoftClip(vec3 light) return light; } -vec3 unpack(vec2 tc) + +vec3 fullbrightScaleSoftClip(vec3 light) { -//#define PACK_NORMALS -#ifdef PACK_NORMALS - vec2 enc = texture2DRect(normalMap, tc).xy; - enc = enc*4.0-2.0; - float prod = dot(enc,enc); - return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); -#else - vec3 norm = texture2DRect(normalMap, tc).xyz; - return norm*2.0-1.0; -#endif + //soft clip effect: + return light; +} + +float luminance(vec3 color) +{ + /// CALCULATING LUMINANCE (Using NTSC lum weights) + /// http://en.wikipedia.org/wiki/Luma_%28video%29 + return dot(color, vec3(0.299, 0.587, 0.114)); } void main() @@ -292,61 +403,107 @@ void main() vec2 tc = vary_fragcoord.xy; float depth = texture2DRect(depthMap, tc.xy).r; vec3 pos = getPosition_d(tc, depth).xyz; - vec3 norm = unpack(tc); // unpack norm + vec4 norm = texture2DRect(normalMap, tc); + float envIntensity = norm.z; + norm.xyz = decode_normal(norm.xy); // unpack norm float da = max(dot(norm.xyz, sun_dir.xyz), 0.0); - - vec4 diffuse = texture2DRect(diffuseRect, tc); - vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + float light_gamma = 1.0/1.3; + da = pow(da, light_gamma); + + + vec4 diffuse = texture2DRect(diffuseRect, tc); + + //convert to gamma space + diffuse.rgb = linear_to_srgb(diffuse.rgb); + vec3 col; float bloom = 0.0; - - if (diffuse.a < 0.9) { + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + bloom = spec.r*norm.w; + + if (norm.w < 0.5) + { vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; + scol_ambocc = pow(scol_ambocc, vec2(light_gamma)); + float scol = max(scol_ambocc.r, diffuse.a); + + + float ambocc = scol_ambocc.g; calcAtmospherics(pos.xyz, ambocc); col = atmosAmbient(vec3(0)); - col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a)); + float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0); + ambient *= 0.5; + ambient *= ambient; + ambient = (1.0-ambient); + + col.rgb *= ambient; + + col += atmosAffectDirectionalLight(max(min(da, scol), 0.0)); col *= diffuse.rgb; + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + if (spec.a > 0.0) // specular reflection { // the old infinite-sky shiny reflection // - vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnormpersp, sun_dir.xyz); - vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*(6 * texture2D(lightFunc, vec2(sa, spec.a)).r); - + vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*(texture2D(lightFunc, vec2(sa, spec.a)).r); + // add the two types of shiny together vec3 spec_contrib = dumbshiny * spec.rgb; - bloom = dot(spec_contrib, spec_contrib) / 4; + bloom = dot(spec_contrib, spec_contrib) / 6; col += spec_contrib; - - //add environmentmap - vec3 env_vec = env_mat * refnormpersp; - vec3 env = textureCube(environmentMap, env_vec).rgb; - bloom = (luminance(env) - .45)*.25; - col = mix(col.rgb, env, - max(spec.a-diffuse.a*2.0, 0.0)); - } - col = atmosLighting(col); - col = scaleSoftClip(col); - - col = mix(col, diffuse.rgb, diffuse.a); - } - else - { - bloom = spec.r; - col = diffuse.rgb; - } + } + + col = mix(col, diffuse.rgb, diffuse.a); + + if (envIntensity > 0.0) + { //add environmentmap + vec3 env_vec = env_mat * refnormpersp; + + vec3 refcol = textureCube(environmentMap, env_vec).rgb*scol_ambocc.r; + bloom = (luminance(refcol) - .45)*.25; + col = mix(col.rgb, refcol, + envIntensity); + + } + + //if (norm.w < 0.5) + { + col = mix(atmosLighting(col), fullbrightAtmosTransport(col), diffuse.a); + col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col), diffuse.a); + //bloom += (luminance(col))*.075; //This looks nice, but requires a larger glow rendertarget. + } + + #ifdef WATER_FOG + vec4 fogged = applyWaterFogDeferred(pos,vec4(col, bloom)); + col = fogged.rgb; + bloom = fogged.a; + #endif + } + else + { + col = diffuse.rgb; + } + + col = srgb_to_linear(col); + + //col = vec3(1,0,1); + //col.g = envIntensity; + } + frag_color.rgb = col; frag_color.a = bloom; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index 3a556e913..7689b72d2 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -24,6 +24,7 @@ */ #extension GL_ARB_texture_rectangle : enable +#extension GL_ARB_shader_texture_lod : enable #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; @@ -39,6 +40,7 @@ uniform samplerCube environmentMap; uniform sampler2DRect lightMap; uniform sampler2D noiseMap; uniform sampler2D projectionMap; +uniform sampler2D lightFunc; uniform mat4 proj_mat; //screen space to light space uniform float proj_near; //near clip for projection @@ -67,9 +69,69 @@ uniform vec2 screen_res; uniform mat4 inv_proj; +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} + +vec3 srgb_to_linear(vec3 cs) +{ + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lte); +#endif + +} + +vec3 linear_to_srgb(vec3 cl) +{ + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); + +#ifdef OLD_SELECT + vec3 result; + result.r = lt.r ? low_range.r : high_range.r; + result.g = lt.g ? low_range.g : high_range.g; + result.b = lt.b ? low_range.b : high_range.b; + return result; +#else + return mix(high_range, low_range, lt); +#endif + +} + +vec4 correctWithGamma(vec4 col) +{ + return vec4(srgb_to_linear(col.rgb), col.a); +} + vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); + ret = correctWithGamma(ret); vec2 dist = tc-vec2(0.5); @@ -85,6 +147,7 @@ vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); + ret = correctWithGamma(ret); vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); @@ -102,6 +165,7 @@ vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); + ret = correctWithGamma(ret); vec2 dist = tc-vec2(0.5); @@ -126,20 +190,6 @@ vec4 getPosition(vec2 pos_screen) return pos; } -vec3 unpack(vec2 tc) -{ -//#define PACK_NORMALS -#ifdef PACK_NORMALS - vec2 enc = texture2DRect(normalMap, tc).xy; - enc = enc*4.0-2.0; - float prod = dot(enc,enc); - return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); -#else - vec3 norm = texture2DRect(normalMap, tc).xyz; - return norm*2.0-1.0; -#endif -} - void main() { vec4 frag = vary_fragcoord; @@ -149,9 +199,9 @@ void main() vec3 pos = getPosition(frag.xy).xyz; vec3 lv = trans_center.xyz-pos.xyz; - float dist2 = dot(lv,lv); - dist2 /= size; - if (dist2 > 1.0) + float dist = length(lv); + dist /= size; + if (dist > 1.0) { discard; } @@ -167,9 +217,11 @@ void main() shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); } - vec3 norm = unpack(frag.xy); // unpack norm + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + float envIntensity = norm.z; + norm = decode_normal(norm.xy); - //norm = normalize(norm); // may be superfluous + norm = normalize(norm); float l_dist = -dot(lv, proj_n); vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); @@ -181,7 +233,10 @@ void main() proj_tc.xyz /= proj_tc.w; float fa = falloff+1.0; - float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); + float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0); + dist_atten *= dist_atten; + dist_atten *= 2.0; + if (dist_atten <= 0.0) { discard; @@ -195,6 +250,10 @@ void main() vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; + vec4 spec = texture2DRect(specularRect, frag.xy); + + vec3 dlit = vec3(0, 0, 0); + float noise = texture2D(noiseMap, frag.xy/128.0).b; if (proj_tc.z > 0.0 && proj_tc.x < 1.0 && @@ -202,21 +261,21 @@ void main() proj_tc.x > 0.0 && proj_tc.y > 0.0) { - float lit = 0.0; float amb_da = proj_ambiance; + float lit = 0.0; if (da > 0.0) { + lit = da * dist_atten * noise; + float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); - vec3 lcol = color.rgb * plcol.rgb * plcol.a; + dlit = color.rgb * plcol.rgb * plcol.a; - lit = da * dist_atten * noise; - - col = lcol*lit*diff_tex*shadow; + col = dlit*lit*diff_tex*shadow; amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; } @@ -232,9 +291,36 @@ void main() col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; } - - vec4 spec = texture2DRect(specularRect, frag.xy); + if (spec.a > 0.0) + { + dlit *= min(da*6.0, 1.0) * dist_atten; + vec3 npos = -normalize(pos); + + //vec3 ref = dot(pos+lv, norm); + vec3 h = normalize(lv+npos); + float nh = dot(norm, h); + float nv = dot(norm, npos); + float vh = dot(npos, h); + float sa = nh; + float fres = pow(1 - dot(h, npos), 5)*0.4+0.5; + + float gtdenom = 2 * nh; + float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); + + if (nh > 0.0) + { + float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); + col += dlit*scol*spec.rgb*shadow; + //col += spec.rgb; + } + } + + + + + + if (envIntensity > 0.0) { vec3 ref = reflect(normalize(pos), norm); @@ -252,8 +338,9 @@ void main() { stc.xy /= stc.w; - float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); + float fatten = clamp(envIntensity*envIntensity+envIntensity*0.5, 0.25, 1.0); + //stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); if (stc.x < 1.0 && @@ -261,13 +348,15 @@ void main() stc.x > 0.0 && stc.y > 0.0) { - vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); - col += dist_atten*scol.rgb*color.rgb*scol.a*spec.rgb*shadow; + col += color.rgb*texture2DLodSpecular(projectionMap, stc.xy, proj_lod-envIntensity*proj_lod).rgb*shadow*spec.rgb; } } } } + //not sure why, but this line prevents MATBUG-194 + col = max(col, vec3(0.0)); + frag_color.rgb = col; frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index f8f57e5e7..18f601f1b 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -35,10 +35,10 @@ out vec4 frag_color; uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; uniform sampler2DShadow shadowMap4; uniform sampler2DShadow shadowMap5; @@ -55,16 +55,33 @@ VARYING vec2 vary_fragcoord; uniform mat4 inv_proj; uniform vec2 screen_res; -uniform vec2 shadow_res; uniform vec2 proj_shadow_res; uniform vec3 sun_dir; +uniform vec2 shadow_res; uniform float shadow_bias; uniform float shadow_offset; uniform float spot_shadow_bias; uniform float spot_shadow_offset; +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} + vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).r; @@ -78,30 +95,31 @@ vec4 getPosition(vec2 pos_screen) return pos; } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; - stc.z += shadow_bias*scl; + stc.z += shadow_bias; - stc.x = floor(stc.x + fract(pos_screen.y*0.666666666)); // add some jitter to X sample pos according to Y to disguise the snapping going on here + stc.x = floor(stc.x*shadow_res.x + fract(pos_screen.y*0.666666666))/shadow_res.x; // add some jitter to X sample pos according to Y to disguise the snapping going on here + float cs = shadow2D(shadowMap, stc.xyz).x; - float cs = shadow2DRect(shadowMap, stc.xyz).x; float shadow = cs; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, 1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, -1.5, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; + - return shadow*0.2; + return shadow*0.2; } -float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) +float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap - + float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; @@ -113,23 +131,7 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x; shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x; - return shadow*0.2; -} - -vec4 unpack(vec2 tc) -{ - vec4 norm = texture2DRect(normalMap, tc).xyzw; -//#define PACK_NORMALS -#ifdef PACK_NORMALS - norm.xy = (norm.xy*4.0)-2.0; - float prod = dot(norm.xy,norm.xy); - norm.xy *= sqrt(1.0-prod*.25); - norm.z = 1.0-prod*.5; -#else - norm.xyz = norm.xyz*2.0-1.0; -#endif - norm.w *= norm.z; - return norm; + return shadow*0.2; } void main() @@ -140,10 +142,9 @@ void main() vec4 pos = getPosition(pos_screen); - vec4 nmap4 = unpack(pos_screen); // unpack norm - float displace = nmap4.w; - vec3 norm = nmap4.xyz; - + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + norm = decode_normal(norm.xy); // unpack norm + /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL { frag_color = vec4(0.0); // doesn't matter @@ -153,7 +154,7 @@ void main() float shadow = 0.0; float dp_directional_light = max(0.0, dot(norm, sun_dir.xyz)); - vec3 shadow_pos = pos.xyz + displace*norm; + vec3 shadow_pos = pos.xyz; vec3 offset = sun_dir.xyz * (1.0-dp_directional_light); vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0); @@ -177,8 +178,7 @@ void main() if (spos.z < near_split.z) { lpos = shadow_matrix[3]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w; @@ -189,8 +189,7 @@ void main() if (spos.z < near_split.y && spos.z > far_split.z) { lpos = shadow_matrix[2]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; @@ -201,7 +200,6 @@ void main() if (spos.z < near_split.x && spos.z > far_split.y) { lpos = shadow_matrix[1]*spos; - lpos.xy *= shadow_res; float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; @@ -213,7 +211,6 @@ void main() if (spos.z > far_split.x) { lpos = shadow_matrix[0]*spos; - lpos.xy *= shadow_res; float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; @@ -252,11 +249,11 @@ void main() //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8, pos_screen); + frag_color[2] = pcfSpotShadow(shadowMap4, lpos, 0.8, pos_screen); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8, pos_screen); + frag_color[3] = pcfSpotShadow(shadowMap5, lpos, 0.8, pos_screen); //frag_color.rgb = pos.xyz; //frag_color.b = shadow; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index ddcb024a9..c6d13db8e 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -34,10 +34,10 @@ out vec4 frag_color; uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; uniform sampler2DShadow shadowMap4; uniform sampler2DShadow shadowMap5; uniform sampler2D noiseMap; @@ -55,16 +55,34 @@ VARYING vec2 vary_fragcoord; uniform mat4 inv_proj; uniform vec2 screen_res; -uniform vec2 shadow_res; uniform vec2 proj_shadow_res; uniform vec3 sun_dir; +uniform vec2 shadow_res; + uniform float shadow_bias; uniform float shadow_offset; uniform float spot_shadow_bias; uniform float spot_shadow_offset; +vec2 encode_normal(vec3 n) +{ + float f = sqrt(8 * n.z + 8); + return n.xy / f + 0.5; +} + +vec3 decode_normal (vec2 enc) +{ + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return n; +} + vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).r; @@ -133,25 +151,25 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) return (rtn * rtn); } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; - stc.z += shadow_bias*scl; + stc.z += shadow_bias; - stc.x = floor(stc.x + fract(pos_screen.y*0.666666666)); + stc.x = floor(stc.x*shadow_res.x + fract(pos_screen.y*0.666666666))/shadow_res.x; + float cs = shadow2D(shadowMap, stc.xyz).x; - float cs = shadow2DRect(shadowMap, stc.xyz).x; float shadow = cs; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; - shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; - + shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; + return shadow*0.2; } -float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) +float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; @@ -171,22 +189,6 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) return shadow*0.2; } -vec4 unpack(vec2 tc) -{ - vec4 norm = texture2DRect(normalMap, tc).xyzw; -//#define PACK_NORMALS -#ifdef PACK_NORMALS - norm.xy = (norm.xy*4.0)-2.0; - float prod = dot(norm.xy,norm.xy); - norm.xy *= sqrt(1.0-prod*.25); - norm.z = 1.0-prod*.5; -#else - norm.xyz = norm.xyz*2.0-1.0; -#endif - norm.w *= norm.z; - return norm; -} - void main() { vec2 pos_screen = vary_fragcoord.xy; @@ -195,10 +197,9 @@ void main() vec4 pos = getPosition(pos_screen); - vec4 nmap4 = unpack(pos_screen); // unpack norm - float displace = nmap4.w; - vec3 norm = nmap4.xyz; - + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + norm = decode_normal(norm.xy); // unpack norm + /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL { frag_color = vec4(0.0); // doesn't matter @@ -207,8 +208,8 @@ void main() float shadow = 0.0; float dp_directional_light = max(0.0, dot(norm, sun_dir.xyz)); - - vec3 shadow_pos = pos.xyz + displace*norm; + + vec3 shadow_pos = pos.xyz; vec3 offset = sun_dir.xyz * (1.0-dp_directional_light); vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0); @@ -232,8 +233,7 @@ void main() if (spos.z < near_split.z) { lpos = shadow_matrix[3]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w; @@ -244,8 +244,7 @@ void main() if (spos.z < near_split.y && spos.z > far_split.z) { lpos = shadow_matrix[2]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; @@ -256,8 +255,7 @@ void main() if (spos.z < near_split.x && spos.z > far_split.y) { lpos = shadow_matrix[1]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; @@ -268,8 +266,7 @@ void main() if (spos.z > far_split.x) { lpos = shadow_matrix[0]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; @@ -307,11 +304,11 @@ void main() //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8, pos_screen); + frag_color[2] = pcfSpotShadow(shadowMap4, lpos, 0.8, pos_screen); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8, pos_screen); + frag_color[3] = pcfSpotShadow(shadowMap5, lpos, 0.8, pos_screen); //frag_color.rgb = pos.xyz; //frag_color.b = shadow; diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 8d0f3e971..78170275b 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -304,6 +304,49 @@ LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep) } +LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep, LLViewerTexture *normalp) +{ + 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) +{ + 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()) @@ -565,10 +608,10 @@ F32 LLDrawable::updateXform(BOOL undamped) mVObjp->dirtySpatialGroup(); } } - else if (!isRoot() && ( - dist_vec_squared(old_pos, target_pos) > 0.f - || old_rot != target_rot )) - { //fix for BUG-860, MAINT-2275, MAINT-1742, MAINT-2247 + else if (!isRoot() && + ((dist_vec_squared(old_pos, target_pos) > 0.f) + || (1.f - dot(old_rot, target_rot)) > 0.f)) + { //fix for BUG-840, MAINT-2275, MAINT-1742, MAINT-2247 gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } else if (!getVOVolume() && !isAvatar()) diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index ba4665a99..421d6b23b 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -151,6 +151,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/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 909cec540..a2aa5abbf 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -35,6 +35,7 @@ #include "lldrawpoolalpha.h" #include "lldrawpoolavatar.h" #include "lldrawpoolbump.h" +#include "lldrawpoolmaterials.h" #include "lldrawpoolground.h" #include "lldrawpoolsimple.h" #include "lldrawpoolsky.h" @@ -47,6 +48,7 @@ #include "llspatialpartition.h" #include "llviewercamera.h" #include "lldrawpoolwlsky.h" +#include "llglslshader.h" S32 LLDrawPool::sNumDrawPools = 0; @@ -64,6 +66,12 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0) case POOL_GRASS: poolp = new LLDrawPoolGrass(); break; + case POOL_ALPHA_MASK: + poolp = new LLDrawPoolAlphaMask(); + break; + case POOL_FULLBRIGHT_ALPHA_MASK: + poolp = new LLDrawPoolFullbrightAlphaMask(); + break; case POOL_FULLBRIGHT: poolp = new LLDrawPoolFullbright(); break; @@ -98,6 +106,9 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0) case POOL_BUMP: poolp = new LLDrawPoolBump(); break; + case POOL_MATERIALS: + poolp = new LLDrawPoolMaterials(); + break; case POOL_WL_SKY: poolp = new LLDrawPoolWLSky(); break; @@ -408,6 +419,27 @@ void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_text } } +void LLRenderPass::pushMaskBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) +{ + for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) + { + LLDrawInfo* pparams = *i; + if (pparams) + { + if (LLGLSLShader::sCurBoundShaderPtr) + { + LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff); + } + else + { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, pparams->mAlphaMaskCutoff); + } + + pushBatch(*pparams, mask, texture, batch_textures); + } + } +} + void LLRenderPass::applyModelMatrix(LLDrawInfo& params) { if (params.mModelMatrix != gGLLastMatrix) diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 384e39837..fa8fc3675 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -50,8 +50,11 @@ public: POOL_GROUND, POOL_FULLBRIGHT, POOL_BUMP, + POOL_MATERIALS, POOL_TERRAIN, POOL_TREE, // Singu Note: Before sky for zcull. + POOL_ALPHA_MASK, + POOL_FULLBRIGHT_ALPHA_MASK, POOL_SKY, POOL_WL_SKY, POOL_GRASS, @@ -129,6 +132,22 @@ public: PASS_SHINY, PASS_BUMP, PASS_POST_BUMP, + PASS_MATERIAL, + PASS_MATERIAL_ALPHA, + PASS_MATERIAL_ALPHA_MASK, + PASS_MATERIAL_ALPHA_EMISSIVE, + PASS_SPECMAP, + PASS_SPECMAP_BLEND, + PASS_SPECMAP_MASK, + PASS_SPECMAP_EMISSIVE, + PASS_NORMMAP, + PASS_NORMMAP_BLEND, + PASS_NORMMAP_MASK, + PASS_NORMMAP_EMISSIVE, + PASS_NORMSPEC, + PASS_NORMSPEC_BLEND, + PASS_NORMSPEC_MASK, + PASS_NORMSPEC_EMISSIVE, PASS_GLOW, PASS_ALPHA, PASS_ALPHA_MASK, @@ -147,6 +166,7 @@ public: static void applyModelMatrix(LLDrawInfo& params); virtual void pushBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); + virtual void pushMaskBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE); virtual void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE); virtual void renderGroups(U32 type, U32 mask, BOOL texture = TRUE); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 5fdedc68e..bab4f75ca 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -77,33 +77,6 @@ void LLDrawPoolAlpha::prerender() mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } -S32 LLDrawPoolAlpha::getNumDeferredPasses() -{ - return 1; -} - -void LLDrawPoolAlpha::beginDeferredPass(S32 pass) -{ - -} - -void LLDrawPoolAlpha::endDeferredPass(S32 pass) -{ - -} - -void LLDrawPoolAlpha::renderDeferred(S32 pass) -{ - LLFastTimer t(FTM_RENDER_GRASS); - gDeferredDiffuseAlphaMaskProgram.bind(); - gDeferredDiffuseAlphaMaskProgram.setMinimumAlpha(0.33f); - - //render alpha masked objects - LLRenderPass::pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - gDeferredDiffuseAlphaMaskProgram.unbind(); -} - - S32 LLDrawPoolAlpha::getNumPostDeferredPasses() { static const LLCachedControl render_depth_of_field("RenderDepthOfField"); @@ -127,25 +100,63 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) if (pass == 0) { + if (LLPipeline::sImpostorRender) + { + simple_shader = &gDeferredAlphaImpostorProgram; + fullbright_shader = &gDeferredFullbrightProgram; + } + else if (LLPipeline::sUnderWaterRender) + { + simple_shader = &gDeferredAlphaWaterProgram; + fullbright_shader = &gDeferredFullbrightWaterProgram; + } + else + { simple_shader = &gDeferredAlphaProgram; - fullbright_shader = &gObjectFullbrightAlphaMaskProgram; + fullbright_shader = &gDeferredFullbrightProgram; + } + + //F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); + + fullbright_shader->bind(); + fullbright_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); + //fullbright_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); + fullbright_shader->unbind(); //prime simple shader (loads shadow relevant uniforms) gPipeline.bindDeferredShader(*simple_shader); + + //simple_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); } - else + else if (!LLPipeline::sImpostorRender) { //update depth buffer sampler gPipeline.mScreen.flush(); gPipeline.mDeferredDepth.copyContents(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), 0, 0, gPipeline.mDeferredDepth.getWidth(), gPipeline.mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); gPipeline.mDeferredDepth.bindTarget(); - simple_shader = NULL; - fullbright_shader = NULL; + simple_shader = fullbright_shader = &gObjectFullbrightAlphaMaskProgram; gObjectFullbrightAlphaMaskProgram.bind(); gObjectFullbrightAlphaMaskProgram.setMinimumAlpha(0.33f); } + + if (LLPipeline::sRenderDeferred) + { + emissive_shader = &gDeferredEmissiveProgram; + } + else + { + if (LLPipeline::sUnderWaterRender) + { + emissive_shader = &gObjectEmissiveWaterProgram; + } + else + { + emissive_shader = &gObjectEmissiveProgram; + } + } + deferred_render = TRUE; if (mVertexShaderLevel > 0) { @@ -157,8 +168,7 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) void LLDrawPoolAlpha::endPostDeferredPass(S32 pass) { - - if (pass == 1) + if (pass == 1 && !LLPipeline::sImpostorRender) { gPipeline.mDeferredDepth.flush(); gPipeline.mScreen.bindTarget(); @@ -178,16 +188,22 @@ void LLDrawPoolAlpha::beginRenderPass(S32 pass) { LLFastTimer t(FTM_RENDER_ALPHA); - if (LLPipeline::sUnderWaterRender) + if (LLPipeline::sImpostorRender) { - simple_shader = &gObjectSimpleWaterAlphaMaskProgram; - fullbright_shader = &gObjectFullbrightWaterAlphaMaskProgram; + simple_shader = &gObjectSimpleImpostorProgram; + fullbright_shader = &gObjectFullbrightProgram; + emissive_shader = &gObjectEmissiveProgram; + } + else if (LLPipeline::sUnderWaterRender) + { + simple_shader = &gObjectSimpleWaterProgram; + fullbright_shader = &gObjectFullbrightWaterProgram; emissive_shader = &gObjectEmissiveWaterProgram; } else { - simple_shader = &gObjectSimpleAlphaMaskProgram; - fullbright_shader = &gObjectFullbrightAlphaMaskProgram; + simple_shader = &gObjectSimpleProgram; + fullbright_shader = &gObjectFullbrightProgram; emissive_shader = &gObjectEmissiveProgram; } @@ -205,7 +221,7 @@ void LLDrawPoolAlpha::endRenderPass( S32 pass ) LLFastTimer t(FTM_RENDER_ALPHA); LLRenderPass::endRenderPass(pass); - if(mVertexShaderLevel > 0) + if(gPipeline.canUseWindLightShaders()) { LLGLSLShader::bindNoShader(); } @@ -225,45 +241,14 @@ void LLDrawPoolAlpha::render(S32 pass) { gGL.setColorMask(true, true); } + + bool write_depth = LLDrawPoolWater::sSkipScreenCopy + || (deferred_render && pass == 1) + // we want depth written so that rendered alpha will + // contribute to the alpha mask used for impostors + || LLPipeline::sImpostorRenderAlphaDepthPass; - if (LLPipeline::sAutoMaskAlphaNonDeferred) - { - mColorSFactor = LLRender::BF_ONE; // } - mColorDFactor = LLRender::BF_ZERO; // } these are like disabling blend on the color channels, but we're still blending on the alpha channel so that we can suppress glow - mAlphaSFactor = LLRender::BF_ZERO; - mAlphaDFactor = LLRender::BF_ZERO; // block (zero-out) glow where the alpha test succeeds - gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - - if (mVertexShaderLevel > 0) - { - if (!LLPipeline::sRenderDeferred || !deferred_render) - { - simple_shader->bind(); - simple_shader->setMinimumAlpha(0.33f); - - pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - } - if (fullbright_shader) - { - fullbright_shader->bind(); - fullbright_shader->setMinimumAlpha(0.33f); - } - pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - //LLGLSLShader::bindNoShader(); - } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.33f); //OK - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); - pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask()); - gPipeline.enableLightsDynamic(); - pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK - } - } - - LLGLDepthTest depth(GL_TRUE, (LLDrawPoolWater::sSkipScreenCopy || - (deferred_render && pass == 1)) ? GL_TRUE : GL_FALSE); + LLGLDepthTest depth(GL_TRUE, write_depth ? GL_TRUE : GL_FALSE); if (deferred_render && pass == 1) { @@ -309,11 +294,11 @@ void LLDrawPoolAlpha::render(S32 pass) if (mVertexShaderLevel > 0) { - renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX); + renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, pass); } else { - renderAlpha(getVertexDataMask()); + renderAlpha(getVertexDataMask(), pass); } gGL.setColorMask(true, false); @@ -335,7 +320,7 @@ void LLDrawPoolAlpha::render(S32 pass) gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); } - gGL.diffuseColor4f(0.9,0,0,0.4); + gGL.diffuseColor4f(1,0,0,1); LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f); gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep, TRUE) ; @@ -386,7 +371,7 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) } } -void LLDrawPoolAlpha::renderAlpha(U32 mask) +void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) { BOOL initialized_lighting = FALSE; BOOL light_enabled = TRUE; @@ -402,13 +387,17 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) if (group->mSpatialPartition->mRenderByGroup && !group->isDead()) { - bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow. - // All particle systems seem to come off the wire with texture entries which claim that they glow. This is probably a bug in the data. Suppress. - group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_PARTICLE && -#if ENABLE_CLASSIC_CLOUDS - group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_CLOUD && -#endif - group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE; + bool is_particle_or_hud_particle = group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_PARTICLE + || group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_CLOUD + || group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; + + bool draw_glow_for_this_partition = mVertexShaderLevel > 0; // no shaders = no glow. + + static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group"); + LLFastTimer t(FTM_RENDER_ALPHA_GROUP_LOOP); + + bool disable_cull = is_particle_or_hud_particle; + LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0); LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; @@ -422,9 +411,32 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) continue; } - LLRenderPass::applyModelMatrix(params); + // Fix for bug - NORSPEC-271 + // If the face is more than 90% transparent, then don't update the Depth buffer for Dof + // We don't want the nearly invisible objects to cause of DoF effects + if(pass == 1 && !LLPipeline::sImpostorRender) + { + LLFace* face = params.mFace; + if(face) + { + const LLTextureEntry* tep = face->getTextureEntry(); + if(tep) + { + if(tep->getColor().mV[3] < 0.1f) + continue; + } + } + } + LLRenderPass::applyModelMatrix(params); + LLMaterial* mat = NULL; + + if (deferred_render) + { + mat = params.mMaterial; + } + if (params.mFullbright) { // Turn off lighting if it hasn't already been so. @@ -455,13 +467,37 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) gPipeline.enableLightsDynamic(); } light_enabled = TRUE; + } + + if (deferred_render && mat) + { + U32 mask = params.mShaderMask; + + llassert(mask < LLMaterial::SHADER_COUNT); + target_shader = &(gDeferredMaterialProgram[mask]); + + if (LLPipeline::sUnderWaterRender) + { + target_shader = &(gDeferredMaterialWaterProgram[mask]); } - // If we need shaders, and we're not ALREADY using the proper shader, then bind it - // (this way we won't rebind shaders unnecessarily). - if(use_shaders && (current_shader != target_shader)) + if (current_shader != target_shader) + { + gPipeline.bindDeferredShader(*target_shader); + } + } + else if (!params.mFullbright) { - llassert(target_shader != NULL); + target_shader = simple_shader; + } + else + { + target_shader = fullbright_shader; + } + + if(use_shaders && (current_shader != target_shader)) + {// If we need shaders, and we're not ALREADY using the proper shader, then bind it + // (this way we won't rebind shaders unnecessarily). current_shader = target_shader; current_shader->bind(); } @@ -470,6 +506,38 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) LLGLSLShader::bindNoShader(); current_shader = NULL; } + + if (use_shaders && mat) + { + // We have a material. Supply the appropriate data here. + if (LLPipeline::sRenderDeferred) + { + current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]); + current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity); + current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, params.mFullbright ? 1.f : 0.f); + + if (params.mNormalMap) + { + params.mNormalMap->addTextureStats(params.mVSize); + current_shader->bindTexture(LLShaderMgr::BUMP_MAP, params.mNormalMap); + } + + if (params.mSpecularMap) + { + params.mSpecularMap->addTextureStats(params.mVSize); + current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, params.mSpecularMap); + } + } + + } else if (LLPipeline::sRenderDeferred && current_shader && (current_shader == simple_shader)) + { + current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, 1.0f, 1.0f, 1.0f, 1.0f); + current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, 0.0f); + LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(params.mVSize); + current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep); + LLViewerFetchedTexture::sWhiteImagep->addTextureStats(params.mVSize); + current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep); + } if (params.mGroup) { @@ -493,7 +561,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) if (params.mTexture.notNull()) { params.mTexture->addTextureStats(params.mVSize); - gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; + if (use_shaders && mat) + { + current_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, params.mTexture); + } + else + { + gGL.getTexUnit(0)->bind(params.mTexture, TRUE); + } + if (params.mTextureMatrix) { tex_setup = true; @@ -509,9 +585,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) } } - params.mVertexBuffer->setBuffer(mask); + static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_PUSH("Alpha Push Verts"); + { + LLFastTimer t(FTM_RENDER_ALPHA_PUSH); + gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); + params.mVertexBuffer->setBuffer(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0)); + params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + } // If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow). Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha. if (current_shader && @@ -547,6 +629,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) } } + gGL.setSceneBlendType(LLRender::BT_ALPHA); + LLVertexBuffer::unbind(); if (!light_enabled) diff --git a/indra/newview/lldrawpoolalpha.h b/indra/newview/lldrawpoolalpha.h index 570ed62e2..08e5068d4 100644 --- a/indra/newview/lldrawpoolalpha.h +++ b/indra/newview/lldrawpoolalpha.h @@ -56,11 +56,6 @@ public: LLDrawPoolAlpha(U32 type = LLDrawPool::POOL_ALPHA); /*virtual*/ ~LLDrawPoolAlpha(); - /*virtual*/ S32 getNumDeferredPasses(); - /*virtual*/ void beginDeferredPass(S32 pass); - /*virtual*/ void endDeferredPass(S32 pass); - /*virtual*/ void renderDeferred(S32 pass); - /*virtual*/ S32 getNumPostDeferredPasses(); /*virtual*/ void beginPostDeferredPass(S32 pass); /*virtual*/ void endPostDeferredPass(S32 pass); @@ -74,9 +69,9 @@ public: /*virtual*/ void prerender(); void renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE); - void renderAlpha(U32 mask); + void renderAlpha(U32 mask, S32 pass); void renderAlphaHighlight(U32 mask); - + static BOOL sShowDebugAlpha; private: diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 2708a0538..9de4dee76 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -55,6 +55,7 @@ #include "llappviewer.h" #include "llrendersphere.h" #include "llviewerpartsim.h" +#include "llviewercontrol.h" // for gSavedSettings static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK; static U32 sBufferUsage = GL_STREAM_DRAW_ARB; @@ -65,9 +66,11 @@ LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL; BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE; S32 LLDrawPoolAvatar::sDiffuseChannel = 0; +F32 LLDrawPoolAvatar::sMinimumAlpha = 0.2f; static bool is_deferred_render = false; +static bool is_post_deferred_render = false; extern BOOL gUseGLPick; @@ -197,6 +200,9 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass) case 4: beginDeferredRiggedBump(); break; + default: + beginDeferredRiggedMaterial(pass-5); + break; } } @@ -229,6 +235,9 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass) case 4: endDeferredRiggedBump(); break; + default: + endDeferredRiggedMaterial(pass-5); + break; } } @@ -239,7 +248,7 @@ void LLDrawPoolAvatar::renderDeferred(S32 pass) S32 LLDrawPoolAvatar::getNumPostDeferredPasses() { - return 6; + return 10; } void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) @@ -261,9 +270,12 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) case 4: beginRiggedFullbrightAlpha(); break; - case 5: + case 9: beginRiggedGlow(); break; + default: + beginDeferredRiggedMaterialAlpha(pass-5); + break; } } @@ -276,7 +288,7 @@ void LLDrawPoolAvatar::beginPostDeferredAlpha() gPipeline.bindDeferredShader(*sVertexProgram); - sVertexProgram->setMinimumAlpha(0.2f); + sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } @@ -289,11 +301,34 @@ void LLDrawPoolAvatar::beginDeferredRiggedAlpha() gPipeline.enableLightsDynamic(); } +void LLDrawPoolAvatar::beginDeferredRiggedMaterialAlpha(S32 pass) +{ + switch (pass) + { + case 0: pass = 1; break; + case 1: pass = 5; break; + case 2: pass = 9; break; + default: pass = 13; break; + } + pass += LLMaterial::SHADER_COUNT; + sVertexProgram = &gDeferredMaterialProgram[pass]; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &(gDeferredMaterialWaterProgram[pass]); + } + gPipeline.bindDeferredShader(*sVertexProgram); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); + specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); + gPipeline.enableLightsDynamic(); +} void LLDrawPoolAvatar::endDeferredRiggedAlpha() { LLVertexBuffer::unbind(); gPipeline.unbindDeferredShader(*sVertexProgram); sDiffuseChannel = 0; + normal_channel = -1; + specular_channel = -1; sVertexProgram = NULL; } @@ -319,6 +354,9 @@ void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) case 5: endRiggedGlow(); break; + default: + endDeferredRiggedAlpha(); + break; } } @@ -343,16 +381,22 @@ void LLDrawPoolAvatar::renderPostDeferred(S32 pass) 7, //rigged alpha 8, //rigged fullbright alpha 9, //rigged glow + 10,//rigged material alpha 2 + 11,//rigged material alpha 3 + 12,//rigged material alpha 4 + 13, //rigged glow }; - pass = actual_pass[pass]; + S32 p = actual_pass[pass]; if (LLPipeline::sImpostorRender) { //HACK for impostors so actual pass ends up being proper pass - pass -= 2; + p -= 2; } - render(pass); + is_post_deferred_render = true; + render(p); + is_post_deferred_render = false; } @@ -439,12 +483,10 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) } else { - renderRigged(avatarp, RIGGED_SIMPLE); - renderRigged(avatarp, RIGGED_ALPHA); - renderRigged(avatarp, RIGGED_FULLBRIGHT); - renderRigged(avatarp, RIGGED_FULLBRIGHT_SHINY); - renderRigged(avatarp, RIGGED_SHINY); - renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA); + for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i) + { + renderRigged(avatarp, i); + } } } @@ -465,11 +507,11 @@ S32 LLDrawPoolAvatar::getNumDeferredPasses() { if (LLPipeline::sImpostorRender) { - return 3; + return 19; } else { - return 5; + return 21; } } @@ -624,7 +666,7 @@ void LLDrawPoolAvatar::beginRigid() if (sVertexProgram != NULL) { //eyeballs render with the specular shader sVertexProgram->bind(); - sVertexProgram->setMinimumAlpha(0.2f); + sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); } } else @@ -666,8 +708,9 @@ void LLDrawPoolAvatar::endDeferredImpostor() sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - sVertexProgram->unbind(); - gGL.getTexUnit(0)->activate(); + gPipeline.unbindDeferredShader(*sVertexProgram); + sVertexProgram = NULL; + sDiffuseChannel = 0; } void LLDrawPoolAvatar::beginDeferredRigid() @@ -675,7 +718,7 @@ void LLDrawPoolAvatar::beginDeferredRigid() sVertexProgram = &gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram; sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); - sVertexProgram->setMinimumAlpha(0.2f); + sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); } void LLDrawPoolAvatar::endDeferredRigid() @@ -733,7 +776,7 @@ void LLDrawPoolAvatar::beginSkinned() if (LLGLSLShader::sNoFixedFunction) { - sVertexProgram->setMinimumAlpha(0.2f); + sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); } } @@ -853,6 +896,9 @@ void LLDrawPoolAvatar::beginRiggedGlow() { sDiffuseChannel = 0; sVertexProgram->bind(); + sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, LLPipeline::sRenderDeferred ? 2.2f : 1.1f); + //F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); + //sVertexProgram->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); } } @@ -871,7 +917,14 @@ void LLDrawPoolAvatar::beginRiggedFullbright() } else { + if (LLPipeline::sRenderDeferred) + { + sVertexProgram = &gDeferredSkinnedFullbrightProgram; + } + else + { sVertexProgram = &gSkinnedObjectFullbrightProgram; + } } } else @@ -890,6 +943,16 @@ void LLDrawPoolAvatar::beginRiggedFullbright() { sDiffuseChannel = 0; sVertexProgram->bind(); + if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred) + { + sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); + } + else + { + sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); + //F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); + //sVertexProgram->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); + } } } @@ -956,7 +1019,14 @@ void LLDrawPoolAvatar::beginRiggedFullbrightShiny() } else { + if (LLPipeline::sRenderDeferred) + { + sVertexProgram = &gDeferredSkinnedFullbrightShinyProgram; + } + else + { sVertexProgram = &gSkinnedObjectFullbrightShinyProgram; + } } } else @@ -976,6 +1046,16 @@ void LLDrawPoolAvatar::beginRiggedFullbrightShiny() { sVertexProgram->bind(); LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); + if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred) + { + sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); + } + else + { + sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); + //F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); + //sVertexProgram->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); + } } } @@ -1024,6 +1104,43 @@ void LLDrawPoolAvatar::endDeferredRiggedBump() sVertexProgram = NULL; } +void LLDrawPoolAvatar::beginDeferredRiggedMaterial(S32 pass) +{ + if (pass == 1 || + pass == 5 || + pass == 9 || + pass == 13) + { //skip alpha passes + return; + } + sVertexProgram = &gDeferredMaterialProgram[pass+LLMaterial::SHADER_COUNT]; + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &(gDeferredMaterialWaterProgram[pass+LLMaterial::SHADER_COUNT]); + } + sVertexProgram->bind(); + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); + specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); +} +void LLDrawPoolAvatar::endDeferredRiggedMaterial(S32 pass) +{ + if (pass == 1 || + pass == 5 || + pass == 9 || + pass == 13) + { + return; + } + LLVertexBuffer::unbind(); + sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP); + sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); + sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sVertexProgram->unbind(); + normal_channel = -1; + sDiffuseChannel = 0; + sVertexProgram = NULL; +} void LLDrawPoolAvatar::beginDeferredSkinned() { sShaderLevel = mVertexShaderLevel; @@ -1031,7 +1148,7 @@ void LLDrawPoolAvatar::beginDeferredSkinned() sRenderingSkinned = TRUE; sVertexProgram->bind(); - sVertexProgram->setMinimumAlpha(0.2f); + sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); gGL.getTexUnit(0)->activate(); @@ -1184,6 +1301,21 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) else { renderRiggedSimple(avatarp); + if (LLPipeline::sRenderDeferred) + { //render "simple" materials + renderRigged(avatarp, RIGGED_MATERIAL); + renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK); + renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE); + renderRigged(avatarp, RIGGED_NORMMAP); + renderRigged(avatarp, RIGGED_NORMMAP_MASK); + renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE); + renderRigged(avatarp, RIGGED_SPECMAP); + renderRigged(avatarp, RIGGED_SPECMAP_MASK); + renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE); + renderRigged(avatarp, RIGGED_NORMSPEC); + renderRigged(avatarp, RIGGED_NORMSPEC_MASK); + renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE); + } } return; } @@ -1202,6 +1334,18 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) return; } + if (is_deferred_render && pass >= 5 && pass <= 21) + { + S32 p = pass-5; + if (p != 1 && + p != 5 && + p != 9 && + p != 13) + { + renderDeferredRiggedMaterial(avatarp, p); + } + return; + } if (pass == 5) { renderRiggedShinySimple(avatarp); @@ -1214,11 +1358,26 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) return; } - if (pass >= 7 && pass < 9) + if (pass >= 7 && pass < 13) { if (pass == 7) { renderRiggedAlpha(avatarp); + if (LLPipeline::sRenderDeferred && !is_post_deferred_render) + { //render transparent materials under water + LLGLEnable blend(GL_BLEND); + gGL.setColorMask(true, true); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA, + LLRender::BF_ZERO, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + renderRigged(avatarp, RIGGED_MATERIAL_ALPHA); + renderRigged(avatarp, RIGGED_SPECMAP_BLEND); + renderRigged(avatarp, RIGGED_NORMMAP_BLEND); + renderRigged(avatarp, RIGGED_NORMSPEC_BLEND); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.setColorMask(true, false); + } return; } @@ -1227,9 +1386,30 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) renderRiggedFullbrightAlpha(avatarp); return; } + if (LLPipeline::sRenderDeferred && is_post_deferred_render) + { + S32 p = 0; + switch (pass) + { + case 9: p = 1; break; + case 10: p = 5; break; + case 11: p = 9; break; + case 12: p = 13; break; + } + { + LLGLEnable blend(GL_BLEND); + renderDeferredRiggedMaterial(avatarp, p); + } + return; + } + else if (pass == 9) + { + renderRiggedGlow(avatarp); + return; + } } - if (pass == 9) + if (pass == 13) { renderRiggedGlow(avatarp); @@ -1267,27 +1447,10 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) } } -void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) +void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) { - LLVector4a* weight = vol_face.mWeights; - if (!weight) - { - return; - } - - LLPointer buffer = face->getVertexBuffer(); - LLDrawable* drawable = face->getDrawable(); - - U32 data_mask = face->getRiggedVertexBufferDataMask(); - - if (buffer.isNull() || - buffer->getTypeMask() != data_mask || - buffer->getNumVerts() != vol_face.mNumVertices || - buffer->getNumIndices() != vol_face.mNumIndices || - (drawable && drawable->isState(LLDrawable::REBUILD_ALL))) - { - face->setGeomIndex(0); - face->setIndicesIndex(0); + face->setGeomIndex(0); + face->setIndicesIndex(0); //rigged faces do not batch textures face->setTextureIndex(255); @@ -1334,12 +1497,55 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* } else { - face->setPoolType(LLDrawPool::POOL_AVATAR); + face->setPoolType(LLDrawPool::POOL_AVATAR); + } + + //llinfos << "Rebuilt face " << face->getTEOffset() << " of " << face->getDrawable() << " at " << gFrameTimeSeconds << llendl; + face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true); + + buffer->flush(); +} + +void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) +{ + LLVector4a* weight = vol_face.mWeights; + if (!weight) + { + return; + } + + LLPointer buffer = face->getVertexBuffer(); + LLDrawable* drawable = face->getDrawable(); + + U32 data_mask = face->getRiggedVertexBufferDataMask(); + + if (buffer.isNull() || + buffer->getTypeMask() != data_mask || + buffer->getNumVerts() != vol_face.mNumVertices || + buffer->getNumIndices() != vol_face.mNumIndices || + (drawable && drawable->isState(LLDrawable::REBUILD_ALL))) + { + if (drawable && drawable->isState(LLDrawable::REBUILD_ALL)) + { //rebuild EVERY face in the drawable, not just this one, to avoid missing drawable wide rebuild issues + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* facep = drawable->getFace(i); + U32 face_data_mask = facep->getRiggedVertexBufferDataMask(); + if (face_data_mask) + { + LLPointer cur_buffer = facep->getVertexBuffer(); + const LLVolumeFace& cur_vol_face = volume->getVolumeFace(i); + getRiggedGeometry(facep, cur_buffer, face_data_mask, skin, volume, cur_vol_face); + } + } + drawable->clearState(LLDrawable::REBUILD_ALL); + + buffer = face->getVertexBuffer(); + } + else + { //just rebuild this face + getRiggedGeometry(face, buffer, data_mask, skin, volume, vol_face); } - - face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true); - - buffer->flush(); } if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime()) @@ -1426,11 +1632,6 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* } } } - - if (drawable && (face->getTEOffset() == drawable->getNumFaces()-1)) - { - drawable->clearState(LLDrawable::REBUILD_ALL); - } } void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) @@ -1531,13 +1732,62 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) gGL.diffuseColor4f(0,0,0,face->getTextureEntry()->getGlow()); }*/ - gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture()); - if (normal_channel > -1) + const LLTextureEntry* te = face->getTextureEntry(); + LLMaterial* mat = te->getMaterialParams().get(); + + if (mat) { - LLDrawPoolBump::bindBumpMap(face, normal_channel); + gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture(LLRender::DIFFUSE_MAP)); + gGL.getTexUnit(normal_channel)->bind(face->getTexture(LLRender::NORMAL_MAP)); + gGL.getTexUnit(specular_channel)->bind(face->getTexture(LLRender::SPECULAR_MAP)); + + LLColor4 col = mat->getSpecularLightColor(); + F32 spec = mat->getSpecularLightExponent()/255.f; + + F32 env = mat->getEnvironmentIntensity()/255.f; + + if (mat->getSpecularID().isNull()) + { + env = te->getShiny()*0.25f; + col.set(env,env,env,0); + spec = env; + } + + BOOL fullbright = te->getFullbright(); + + sVertexProgram->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, fullbright ? 1.f : 0.f); + sVertexProgram->uniform4f(LLShaderMgr::SPECULAR_COLOR, col.mV[0], col.mV[1], col.mV[2], spec); + sVertexProgram->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env); + + if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { + sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff()/255.f); + } + else + { + sVertexProgram->setMinimumAlpha(0.f); + } + + for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) + { + LLViewerTexture* tex = face->getTexture(i); + if (tex) + { + tex->addTextureStats(avatar->getPixelArea()); + } + } + } + else + { + gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture()); + sVertexProgram->setMinimumAlpha(0.f); + if (normal_channel > -1) + { + LLDrawPoolBump::bindBumpMap(face, normal_channel); + } } - if (face->mTextureMatrix) + if (face->mTextureMatrix && vobj->mTexAnimMode) { gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadMatrix((F32*) face->mTextureMatrix->mMatrix); @@ -1551,6 +1801,8 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) buff->setBuffer(data_mask); buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); } + + gPipeline.addTrianglesDrawn(count, LLRender::TRIANGLES); } } } @@ -1565,6 +1817,11 @@ void LLDrawPoolAvatar::renderDeferredRiggedBump(LLVOAvatar* avatar) renderRigged(avatar, RIGGED_DEFERRED_BUMP); } +void LLDrawPoolAvatar::renderDeferredRiggedMaterial(LLVOAvatar* avatar, S32 pass) +{ + renderRigged(avatar, pass); +} + static LLFastTimer::DeclareTimer FTM_RIGGED_VBO("Rigged VBO"); void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar) diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 4b93f47e8..9569a9b1f 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -119,6 +119,8 @@ public: void beginRiggedFullbrightAlpha(); void beginRiggedGlow(); void beginDeferredRiggedAlpha(); + void beginDeferredRiggedMaterial(S32 pass); + void beginDeferredRiggedMaterialAlpha(S32 pass); void endRiggedSimple(); void endRiggedFullbright(); @@ -128,6 +130,8 @@ public: void endRiggedFullbrightAlpha(); void endRiggedGlow(); void endDeferredRiggedAlpha(); + void endDeferredRiggedMaterial(S32 pass); + void endDeferredRiggedMaterialAlpha(S32 pass); void beginDeferredRiggedSimple(); void beginDeferredRiggedBump(); @@ -135,6 +139,7 @@ public: void endDeferredRiggedSimple(); void endDeferredRiggedBump(); + void getRiggedGeometry(LLFace* face, LLPointer& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face); void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* facep, const LLMeshSkinInfo* skin, @@ -152,10 +157,27 @@ public: void renderRiggedGlow(LLVOAvatar* avatar); void renderDeferredRiggedSimple(LLVOAvatar* avatar); void renderDeferredRiggedBump(LLVOAvatar* avatar); - + void renderDeferredRiggedMaterial(LLVOAvatar* avatar, S32 pass); + typedef enum { - RIGGED_SIMPLE = 0, + RIGGED_MATERIAL=0, + RIGGED_MATERIAL_ALPHA, + RIGGED_MATERIAL_ALPHA_MASK, + RIGGED_MATERIAL_ALPHA_EMISSIVE, + RIGGED_SPECMAP, + RIGGED_SPECMAP_BLEND, + RIGGED_SPECMAP_MASK, + RIGGED_SPECMAP_EMISSIVE, + RIGGED_NORMMAP, + RIGGED_NORMMAP_BLEND, + RIGGED_NORMMAP_MASK, + RIGGED_NORMMAP_EMISSIVE, + RIGGED_NORMSPEC, + RIGGED_NORMSPEC_BLEND, + RIGGED_NORMSPEC_MASK, + RIGGED_NORMSPEC_EMISSIVE, + RIGGED_SIMPLE, RIGGED_FULLBRIGHT, RIGGED_SHINY, RIGGED_FULLBRIGHT_SHINY, @@ -170,6 +192,48 @@ public: typedef enum { + RIGGED_MATERIAL_MASK = + LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_MATERIAL_ALPHA_VMASK = RIGGED_MATERIAL_MASK, + RIGGED_MATERIAL_ALPHA_MASK_MASK = RIGGED_MATERIAL_MASK, + RIGGED_MATERIAL_ALPHA_EMISSIVE_MASK = RIGGED_MATERIAL_MASK, + RIGGED_SPECMAP_VMASK = + LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_TEXCOORD2 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_SPECMAP_BLEND_MASK = RIGGED_SPECMAP_VMASK, + RIGGED_SPECMAP_MASK_MASK = RIGGED_SPECMAP_VMASK, + RIGGED_SPECMAP_EMISSIVE_MASK = RIGGED_SPECMAP_VMASK, + RIGGED_NORMMAP_VMASK = + LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TANGENT | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_TEXCOORD1 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_NORMMAP_BLEND_MASK = RIGGED_NORMMAP_VMASK, + RIGGED_NORMMAP_MASK_MASK = RIGGED_NORMMAP_VMASK, + RIGGED_NORMMAP_EMISSIVE_MASK = RIGGED_NORMMAP_VMASK, + RIGGED_NORMSPEC_VMASK = + LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TANGENT | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_TEXCOORD1 | + LLVertexBuffer::MAP_TEXCOORD2 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_NORMSPEC_BLEND_MASK = RIGGED_NORMSPEC_VMASK, + RIGGED_NORMSPEC_MASK_MASK = RIGGED_NORMSPEC_VMASK, + RIGGED_NORMSPEC_EMISSIVE_MASK = RIGGED_NORMSPEC_VMASK, RIGGED_SIMPLE_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0 | @@ -214,6 +278,7 @@ public: static BOOL sSkipOpaque; static BOOL sSkipTransparent; static S32 sDiffuseChannel; + static F32 sMinimumAlpha; static LLGLSLShader* sVertexProgram; }; diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 259c0e495..d9eac7b7b 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -456,9 +456,6 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; if( cube_map ) { - cube_map->disable(); - cube_map->restoreMatrix(); - if (!invisible && shader_level > 1) { shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); @@ -471,6 +468,10 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& } } } + // Moved below shader->disableTexture call to avoid false alarms from auto-re-enable of textures on stage 0 + // MAINT-755 + cube_map->disable(); + cube_map->restoreMatrix(); } if (!LLGLSLShader::sNoFixedFunction) @@ -521,7 +522,14 @@ void LLDrawPoolBump::beginFullbrightShiny() } else { - shader = &gObjectFullbrightShinyProgram; + if (LLPipeline::sRenderDeferred) + { + shader = &gDeferredFullbrightShinyProgram; + } + else + { + shader = &gObjectFullbrightShinyProgram; + } } LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; @@ -1381,7 +1389,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale")); gNormalMapGenProgram.uniform1f(sStepX, 1.f/bump->getWidth()); - gNormalMapGenProgram.uniform1f(sStepX, 1.f/bump->getHeight()); + gNormalMapGenProgram.uniform1f(sStepY, 1.f/bump->getHeight()); LLVector2 v((F32) bump->getWidth()/gPipeline.mScreen.getWidth(), (F32) bump->getHeight()/gPipeline.mScreen.getHeight()); diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp new file mode 100644 index 000000000..d1b508065 --- /dev/null +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -0,0 +1,224 @@ +/** + * @file lldrawpool.cpp + * @brief LLDrawPoolMaterials class implementation + * @author Jonathan "Geenz" Goodman + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lldrawpoolmaterials.h" +#include "llviewershadermgr.h" +#include "pipeline.h" + +S32 diffuse_channel = -1; + +LLDrawPoolMaterials::LLDrawPoolMaterials() +: LLRenderPass(LLDrawPool::POOL_MATERIALS) +{ + +} + +void LLDrawPoolMaterials::prerender() +{ + mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); +} + +S32 LLDrawPoolMaterials::getNumDeferredPasses() +{ + return 12; +} + +void LLDrawPoolMaterials::beginDeferredPass(S32 pass) +{ + U32 shader_idx[] = + { + 0, //LLRenderPass::PASS_MATERIAL, + //1, //LLRenderPass::PASS_MATERIAL_ALPHA, + 2, //LLRenderPass::PASS_MATERIAL_ALPHA_MASK, + 3, //LLRenderPass::PASS_MATERIAL_ALPHA_GLOW, + 4, //LLRenderPass::PASS_SPECMAP, + //5, //LLRenderPass::PASS_SPECMAP_BLEND, + 6, //LLRenderPass::PASS_SPECMAP_MASK, + 7, //LLRenderPass::PASS_SPECMAP_GLOW, + 8, //LLRenderPass::PASS_NORMMAP, + //9, //LLRenderPass::PASS_NORMMAP_BLEND, + 10, //LLRenderPass::PASS_NORMMAP_MASK, + 11, //LLRenderPass::PASS_NORMMAP_GLOW, + 12, //LLRenderPass::PASS_NORMSPEC, + //13, //LLRenderPass::PASS_NORMSPEC_BLEND, + 14, //LLRenderPass::PASS_NORMSPEC_MASK, + 15, //LLRenderPass::PASS_NORMSPEC_GLOW, + }; + + mShader = &(gDeferredMaterialProgram[shader_idx[pass]]); + + if (LLPipeline::sUnderWaterRender) + { + mShader = &(gDeferredMaterialWaterProgram[shader_idx[pass]]); + } + + mShader->bind(); + + diffuse_channel = mShader->enableTexture(LLShaderMgr::DIFFUSE_MAP); + + LLFastTimer t(FTM_RENDER_MATERIALS); +} + +void LLDrawPoolMaterials::endDeferredPass(S32 pass) +{ + LLFastTimer t(FTM_RENDER_MATERIALS); + + mShader->unbind(); + + LLRenderPass::endRenderPass(pass); +} + +void LLDrawPoolMaterials::renderDeferred(S32 pass) +{ + U32 type_list[] = + { + LLRenderPass::PASS_MATERIAL, + //LLRenderPass::PASS_MATERIAL_ALPHA, + LLRenderPass::PASS_MATERIAL_ALPHA_MASK, + LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, + LLRenderPass::PASS_SPECMAP, + //LLRenderPass::PASS_SPECMAP_BLEND, + LLRenderPass::PASS_SPECMAP_MASK, + LLRenderPass::PASS_SPECMAP_EMISSIVE, + LLRenderPass::PASS_NORMMAP, + //LLRenderPass::PASS_NORMMAP_BLEND, + LLRenderPass::PASS_NORMMAP_MASK, + LLRenderPass::PASS_NORMMAP_EMISSIVE, + LLRenderPass::PASS_NORMSPEC, + //LLRenderPass::PASS_NORMSPEC_BLEND, + LLRenderPass::PASS_NORMSPEC_MASK, + LLRenderPass::PASS_NORMSPEC_EMISSIVE, + }; + + llassert(pass < sizeof(type_list)/sizeof(U32)); + + U32 type = type_list[pass]; + + U32 mask = mShader->mAttributeMask; + + LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); + LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); + + for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) + { + LLDrawInfo& params = **i; + + mShader->uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]); + mShader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity); + + if (params.mNormalMap) + { + params.mNormalMap->addTextureStats(params.mVSize); + bindNormalMap(params.mNormalMap); + } + + if (params.mSpecularMap) + { + params.mSpecularMap->addTextureStats(params.mVSize); + bindSpecularMap(params.mSpecularMap); + } + + mShader->setMinimumAlpha(params.mAlphaMaskCutoff); + mShader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, params.mFullbright ? 1.f : 0.f); + + pushBatch(params, mask, TRUE); + } +} + +void LLDrawPoolMaterials::bindSpecularMap(LLViewerTexture* tex) +{ + mShader->bindTexture(LLShaderMgr::SPECULAR_MAP, tex); +} + +void LLDrawPoolMaterials::bindNormalMap(LLViewerTexture* tex) +{ + mShader->bindTexture(LLShaderMgr::BUMP_MAP, tex); +} + +void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) +{ + applyModelMatrix(params); + + bool tex_setup = false; + + if (batch_textures && params.mTextureList.size() > 1) + { + for (U32 i = 0; i < params.mTextureList.size(); ++i) + { + if (params.mTextureList[i].notNull()) + { + gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); + } + } + } + else + { //not batching textures or batch has only 1 texture -- might need a texture matrix + if (params.mTextureMatrix) + { + //if (mShiny) + { + gGL.getTexUnit(0)->activate(); + gGL.matrixMode(LLRender::MM_TEXTURE); + } + + gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + + tex_setup = true; + } + + if (mVertexShaderLevel > 1 && texture) + { + if (params.mTexture.notNull()) + { + gGL.getTexUnit(diffuse_channel)->bind(params.mTexture); + params.mTexture->addTextureStats(params.mVSize); + } + else + { + gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); + } + } + } + + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } + params.mVertexBuffer->setBuffer(mask); + params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + if (tex_setup) + { + gGL.getTexUnit(0)->activate(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } +} + diff --git a/indra/newview/lldrawpoolmaterials.h b/indra/newview/lldrawpoolmaterials.h new file mode 100644 index 000000000..eae1aba87 --- /dev/null +++ b/indra/newview/lldrawpoolmaterials.h @@ -0,0 +1,75 @@ +/** + * @file lldrawpoolmaterials.h + * @brief LLDrawPoolMaterials class definition + * @author Jonathan "Geenz" Goodman + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLDRAWPOOLMATERIALS_H +#define LL_LLDRAWPOOLMATERIALS_H + +#include "v4coloru.h" +#include "v2math.h" +#include "v3math.h" +#include "llvertexbuffer.h" +#include "lldrawpool.h" + +class LLViewerTexture; +class LLDrawInfo; +class LLGLSLShader; + +class LLDrawPoolMaterials : public LLRenderPass +{ + LLGLSLShader *mShader; +public: + LLDrawPoolMaterials(); + + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_TEXCOORD1 | + LLVertexBuffer::MAP_TEXCOORD2 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_TANGENT + }; + + /*virtual*/ U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + + /*virtual*/ void render(S32 pass = 0) { } + /*virtual*/ S32 getNumPasses() {return 0;} + /*virtual*/ void prerender(); + + /*virtual*/ S32 getNumDeferredPasses(); + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + void bindSpecularMap(LLViewerTexture* tex); + void bindNormalMap(LLViewerTexture* tex); + + /*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE); +}; + +#endif //LL_LLDRAWPOOLMATERIALS_H diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index 4bc06580f..638a9dfa0 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -37,6 +37,7 @@ #include "llviewershadermgr.h" #include "llrender.h" +#define GE_FORCE_WORKAROUND LL_DARWIN static LLGLSLShader* simple_shader = NULL; static LLGLSLShader* fullbright_shader = NULL; @@ -47,6 +48,7 @@ static LLFastTimer::DeclareTimer FTM_RENDER_GRASS_DEFERRED("Deferred Grass"); void LLDrawPoolGlow::beginPostDeferredPass(S32 pass) { gDeferredEmissiveProgram.bind(); + gDeferredEmissiveProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); } static LLFastTimer::DeclareTimer FTM_RENDER_GLOW_PUSH("Glow Push"); @@ -110,6 +112,14 @@ void LLDrawPoolGlow::render(S32 pass) LLGLSLShader* shader = LLPipeline::sUnderWaterRender ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; shader->bind(); + if (LLPipeline::sRenderDeferred) + { + shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); + } + else + { + shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.f); + } LLGLDepthTest depth(GL_TRUE, GL_FALSE); gGL.setColorMask(false, true); @@ -146,7 +156,11 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass) { LLFastTimer t(FTM_RENDER_SIMPLE); - if (LLPipeline::sUnderWaterRender) + if (LLPipeline::sImpostorRender) + { + simple_shader = &gObjectSimpleImpostorProgram; + } + else if (LLPipeline::sUnderWaterRender) { simple_shader = &gObjectSimpleWaterProgram; } @@ -198,7 +212,11 @@ void LLDrawPoolSimple::render(S32 pass) if (LLPipeline::sRenderDeferred) { //if deferred rendering is enabled, bump faces aren't registered as simple //render bump faces here as simple so bump faces will appear under water - pushBatches(LLRenderPass::PASS_BUMP, mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_BUMP, mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_MATERIAL, mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_SPECMAP, mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_NORMMAP, mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_NORMSPEC, mask, TRUE, TRUE); } } else @@ -210,6 +228,169 @@ void LLDrawPoolSimple::render(S32 pass) } } + + + + + + + + + +static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_MASK("Alpha Mask"); + +LLDrawPoolAlphaMask::LLDrawPoolAlphaMask() : + LLRenderPass(POOL_ALPHA_MASK) +{ +} + +void LLDrawPoolAlphaMask::prerender() +{ + mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); +} + +void LLDrawPoolAlphaMask::beginRenderPass(S32 pass) +{ + LLFastTimer t(FTM_RENDER_ALPHA_MASK); + + if (LLPipeline::sUnderWaterRender) + { + simple_shader = &gObjectSimpleWaterAlphaMaskProgram; + } + else + { + simple_shader = &gObjectSimpleAlphaMaskProgram; + } + + if (mVertexShaderLevel > 0) + { + simple_shader->bind(); + } + else + { + // don't use shaders! + if (gGLManager.mHasShaderObjects) + { + LLGLSLShader::bindNoShader(); + } + } +} + +void LLDrawPoolAlphaMask::endRenderPass(S32 pass) +{ + LLFastTimer t(FTM_RENDER_ALPHA_MASK); + stop_glerror(); + LLRenderPass::endRenderPass(pass); + stop_glerror(); + if (mVertexShaderLevel > 0) + { + simple_shader->unbind(); + } +} + +void LLDrawPoolAlphaMask::render(S32 pass) +{ + LLGLDisable blend(GL_BLEND); + LLFastTimer t(FTM_RENDER_ALPHA_MASK); + + if (mVertexShaderLevel > 0) + { + simple_shader->bind(); + simple_shader->setMinimumAlpha(0.33f); + + pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + pushMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + pushMaskBatches(LLRenderPass::PASS_SPECMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + pushMaskBatches(LLRenderPass::PASS_NORMMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + pushMaskBatches(LLRenderPass::PASS_NORMSPEC_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + } + else + { + LLGLEnable test(GL_ALPHA_TEST); + pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask(), TRUE, FALSE); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK + } +} + +LLDrawPoolFullbrightAlphaMask::LLDrawPoolFullbrightAlphaMask() : + LLRenderPass(POOL_FULLBRIGHT_ALPHA_MASK) +{ +} + +void LLDrawPoolFullbrightAlphaMask::prerender() +{ + mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); +} + +void LLDrawPoolFullbrightAlphaMask::beginRenderPass(S32 pass) +{ + LLFastTimer t(FTM_RENDER_ALPHA_MASK); + + if (LLPipeline::sUnderWaterRender) + { + simple_shader = &gObjectFullbrightWaterAlphaMaskProgram; + } + else + { + simple_shader = &gObjectFullbrightAlphaMaskProgram; + } + + if (mVertexShaderLevel > 0) + { + simple_shader->bind(); + } + else + { + // don't use shaders! + if (gGLManager.mHasShaderObjects) + { + LLGLSLShader::bindNoShader(); + } + } +} + +void LLDrawPoolFullbrightAlphaMask::endRenderPass(S32 pass) +{ + LLFastTimer t(FTM_RENDER_ALPHA_MASK); + stop_glerror(); + LLRenderPass::endRenderPass(pass); + stop_glerror(); + if (mVertexShaderLevel > 0) + { + simple_shader->unbind(); + } +} + +void LLDrawPoolFullbrightAlphaMask::render(S32 pass) +{ + LLFastTimer t(FTM_RENDER_ALPHA_MASK); + + if (mVertexShaderLevel > 0) + { + if (simple_shader) + { + simple_shader->bind(); + simple_shader->setMinimumAlpha(0.33f); + if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred) + { + simple_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); + } else { + simple_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); + } + } + pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + //LLGLSLShader::bindNoShader(); + } + else + { + LLGLEnable test(GL_ALPHA_TEST); + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask(), TRUE, FALSE); + gPipeline.enableLightsDynamic(); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK + } +} + //=============================== //DEFERRED IMPLEMENTATION //=============================== @@ -239,6 +420,28 @@ void LLDrawPoolSimple::renderDeferred(S32 pass) } } +static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_MASK_DEFERRED("Deferred Alpha Mask"); + +void LLDrawPoolAlphaMask::beginDeferredPass(S32 pass) +{ + +} + +void LLDrawPoolAlphaMask::endDeferredPass(S32 pass) +{ + +} + +void LLDrawPoolAlphaMask::renderDeferred(S32 pass) +{ + LLFastTimer t(FTM_RENDER_ALPHA_MASK_DEFERRED); + gDeferredDiffuseAlphaMaskProgram.bind(); + gDeferredDiffuseAlphaMaskProgram.setMinimumAlpha(0.33f); + pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + gDeferredDiffuseAlphaMaskProgram.unbind(); +} + + // grass drawpool LLDrawPoolGrass::LLDrawPoolGrass() : LLRenderPass(POOL_GRASS) @@ -345,7 +548,15 @@ void LLDrawPoolFullbright::prerender() void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass) { - gDeferredFullbrightProgram.bind(); + if (LLPipeline::sUnderWaterRender) + { + gDeferredFullbrightWaterProgram.bind(); + } + else + { + gDeferredFullbrightProgram.bind(); + } + } void LLDrawPoolFullbright::renderPostDeferred(S32 pass) @@ -362,9 +573,15 @@ void LLDrawPoolFullbright::renderPostDeferred(S32 pass) void LLDrawPoolFullbright::endPostDeferredPass(S32 pass) { - gDeferredFullbrightProgram.unbind(); + if (LLPipeline::sUnderWaterRender) + { + gDeferredFullbrightWaterProgram.unbind(); + } + else + { + gDeferredFullbrightProgram.unbind(); + } LLRenderPass::endRenderPass(pass); - } void LLDrawPoolFullbright::beginRenderPass(S32 pass) @@ -407,14 +624,24 @@ void LLDrawPoolFullbright::render(S32 pass) { fullbright_shader->bind(); fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f); + fullbright_shader->uniform1f(LLViewerShaderMgr::TEXTURE_GAMMA, 1.f); + U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, fullbright_mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE, fullbright_mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE, fullbright_mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE, fullbright_mask, TRUE, TRUE); } else { gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR; renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask); + pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, fullbright_mask); + pushBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE, fullbright_mask); + pushBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE, fullbright_mask); + pushBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE, fullbright_mask); } stop_glerror(); @@ -425,3 +652,75 @@ S32 LLDrawPoolFullbright::getNumPasses() return 1; } + +void LLDrawPoolFullbrightAlphaMask::beginPostDeferredPass(S32 pass) +{ + + if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred) + { + gObjectFullbrightAlphaMaskProgram.bind(); + gObjectFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); + } + else + { + +// Work-around until we can figure out why the right shader causes +// the GeForce driver to go tango uniform on OS X 10.6.8 only +// +#if GE_FORCE_WORKAROUND + gObjectFullbrightAlphaMaskProgram.bind(); + gObjectFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); +#else + if (LLPipeline::sUnderWaterRender) + { + gDeferredFullbrightAlphaMaskWaterProgram.bind(); + gDeferredFullbrightAlphaMaskWaterProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); + } + else + { + gDeferredFullbrightAlphaMaskProgram.bind(); + gDeferredFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); + } +#endif + } + +} + +void LLDrawPoolFullbrightAlphaMask::renderPostDeferred(S32 pass) +{ + LLFastTimer t(FTM_RENDER_FULLBRIGHT); + LLGLDisable blend(GL_BLEND); + U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; + pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, fullbright_mask, TRUE, TRUE); +} + +void LLDrawPoolFullbrightAlphaMask::endPostDeferredPass(S32 pass) +{ + if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred) + { + gObjectFullbrightAlphaMaskProgram.unbind(); + } + else + { + +// Work-around until we can figure out why the right shader causes +// the GeForce driver to go tango uniform on OS X 10.6.8 only +// +#if GE_FORCE_WORKAROUND + gObjectFullbrightAlphaMaskProgram.unbind(); +#else + if (LLPipeline::sUnderWaterRender) + { + gDeferredFullbrightAlphaMaskWaterProgram.unbind(); + } + else + { + gDeferredFullbrightAlphaMaskProgram.unbind(); + } +#endif + + } + LLRenderPass::endRenderPass(pass); +} + + diff --git a/indra/newview/lldrawpoolsimple.h b/indra/newview/lldrawpoolsimple.h index 20a376150..f028b74ff 100644 --- a/indra/newview/lldrawpoolsimple.h +++ b/indra/newview/lldrawpoolsimple.h @@ -90,6 +90,59 @@ public: /*virtual*/ void prerender(); }; +class LLDrawPoolAlphaMask : public LLRenderPass +{ +public: + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR + }; + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + + LLDrawPoolAlphaMask(); + + /*virtual*/ S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + /*virtual*/ S32 getNumPasses() { return 1; } + /*virtual*/ void beginRenderPass(S32 pass); + /*virtual*/ void endRenderPass(S32 pass); + /*virtual*/ void render(S32 pass = 0); + /*virtual*/ void prerender(); + +}; + +class LLDrawPoolFullbrightAlphaMask : public LLRenderPass +{ +public: + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR + }; + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + + LLDrawPoolFullbrightAlphaMask(); + + /*virtual*/ S32 getNumPostDeferredPasses() { return 1; } + /*virtual*/ void beginPostDeferredPass(S32 pass); + /*virtual*/ void endPostDeferredPass(S32 pass); + /*virtual*/ void renderPostDeferred(S32 pass); + + /*virtual*/ S32 getNumPasses() { return 1; } + /*virtual*/ void beginRenderPass(S32 pass); + /*virtual*/ void endRenderPass(S32 pass); + /*virtual*/ void render(S32 pass = 0); + /*virtual*/ void prerender(); +}; + + class LLDrawPoolFullbright : public LLRenderPass { public: diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 756318583..0872f5f9d 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -564,14 +564,21 @@ void LLDrawPoolWater::shade() F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - gAgent.getRegion()->getWaterHeight(); + if (eyedepth < 0.f && LLPipeline::sWaterReflections) + { if (deferred_render) { - shader = &gDeferredWaterProgram; + shader = &gDeferredUnderWaterProgram; } - else if (eyedepth < 0.f && LLPipeline::sWaterReflections) + else { shader = &gUnderWaterProgram; } + } + else if (deferred_render) + { + shader = &gDeferredWaterProgram; + } else { shader = &gWaterProgram; @@ -592,7 +599,7 @@ void LLDrawPoolWater::shade() sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f; } - S32 reftex = shader->enableTexture(LLViewerShaderMgr::WATER_REFTEX); + S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX); if (reftex > -1) { diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index f39812631..04d5f5115 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -57,6 +57,8 @@ #include "llviewerregion.h" #include "llviewerwindow.h" #include "llviewershadermgr.h" +#include "llviewertexture.h" +#include "llvoavatar.h" #define LL_MAX_INDICES_COUNT 1000000 @@ -140,9 +142,13 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) //special value to indicate uninitialized position mIndicesIndex = 0xFFFFFFFF; + + for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) + { + mIndexInTex[i] = 0; + mTexture[i] = NULL; + } - mIndexInTex = 0; - mTexture = NULL; mTEOffset = -1; mTextureIndex = 255; @@ -169,9 +175,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)) @@ -264,47 +273,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) ; - } + 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 ; } @@ -314,10 +352,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(); } @@ -737,7 +782,7 @@ bool less_than_max_mag(const LLVector4a& vec) } BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, - const LLMatrix4& mat_vert_in, const LLMatrix3& mat_normal_in, BOOL global_volume) + const LLMatrix4& mat_vert_in, BOOL global_volume) { //get bounding box if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED)) @@ -746,16 +791,6 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, LLMatrix4a mat_vert; mat_vert.loadu(mat_vert_in); - LLMatrix4a mat_normal; - mat_normal.loadu(mat_normal_in); - - //if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) - //{ //vertex buffer no longer valid - // mVertexBuffer = NULL; - // mLastVertexBuffer = NULL; - //} - - //VECTORIZE THIS LLVector4a min,max; if (f >= volume.getNumVolumeFaces()) @@ -772,100 +807,68 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, llassert(less_than_max_mag(max)); //min, max are in volume space, convert to drawable render space - LLVector4a center; - LLVector4a t; - t.setAdd(min, max); - t.mul(0.5f); - mat_vert.affineTransform(t, center); - LLVector4a size; - size.setSub(max, min); - size.mul(0.5f); - llassert(less_than_max_mag(min)); - llassert(less_than_max_mag(max)); + //get 8 corners of bounding box + LLVector4Logical mask[6]; - if (!global_volume) + for (U32 i = 0; i < 6; ++i) { - //VECTORIZE THIS - LLVector4a scale; - scale.load3(mDrawablep->getVObj()->getScale().mV); - size.mul(scale); + mask[i].clear(); } - // 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(); + mask[0].setElement<2>(); //001 + mask[1].setElement<1>(); //010 + mask[2].setElement<1>(); //011 + mask[2].setElement<2>(); + mask[3].setElement<0>(); //100 + mask[4].setElement<0>(); //101 + mask[4].setElement<2>(); + mask[5].setElement<0>(); //110 + mask[5].setElement<1>(); - LLVector4a v[4]; + LLVector4a v[8]; - //get 4 corners of bounding box - mat_normal.rotate(size,v[0]); + v[6] = min; + v[7] = max; - //VECTORIZE THIS - LLVector4a scale; - - scale.set(-1.f, -1.f, 1.f); - scale.mul(size); - mat_normal.rotate(scale, v[1]); - - scale.set(1.f, -1.f, -1.f); - scale.mul(size); - mat_normal.rotate(scale, v[2]); - - scale.set(-1.f, 1.f, -1.f); - scale.mul(size); - mat_normal.rotate(scale, v[3]); + for (U32 i = 0; i < 6; ++i) + { + v[i].setSelectWithMask(mask[i], min, max); + } + LLVector4a tv[8]; + + //transform bounding box into drawable space + for (U32 i = 0; i < 8; ++i) + { + mat_vert.affineTransform(v[i], tv[i]); + } + + //find bounding box LLVector4a& newMin = mExtents[0]; LLVector4a& newMax = mExtents[1]; - - newMin = newMax = center; - - llassert(less_than_max_mag(center)); - - for (U32 i = 0; i < 4; i++) + + newMin = newMax = tv[0]; + + for (U32 i = 1; i < 8; ++i) { - LLVector4a delta; - delta.setAbs(v[i]); - LLVector4a min; - min.setSub(center, delta); - LLVector4a max; - max.setAdd(center, delta); - - newMin.setMin(newMin,min); - newMax.setMax(newMax,max); - - llassert(less_than_max_mag(newMin)); - llassert(less_than_max_mag(newMax)); + newMin.setMin(newMin, tv[i]); + newMax.setMax(newMax, tv[i]); } if (!mDrawablep->isActive()) - { + { // Shift position for region LLVector4a offset; offset.load3(mDrawablep->getRegion()->getOriginAgent().mV); newMin.add(offset); newMax.add(offset); - - llassert(less_than_max_mag(newMin)); - llassert(less_than_max_mag(newMax)); } - t.setAdd(newMin, newMax); + LLVector4a t; + t.setAdd(newMin,newMax); t.mul(0.5f); - llassert(less_than_max_mag(t)); - - //VECTORIZE THIS mCenterLocal.set(t.getF32ptr()); - - llassert(less_than_max_mag(newMin)); - llassert(less_than_max_mag(newMax)); t.setSub(newMax,newMin); mBoundingSphereRadius = t.getLength3().getF32()*0.5f; @@ -1273,30 +1276,34 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (tep && getPoolType() != LLDrawPool::POOL_ALPHA) // <--- alpha channel MUST contain transparency, not shiny { + LLMaterial* mat = tep->getMaterialParams().get(); + bool shiny_in_alpha = false; if (LLPipeline::sRenderDeferred) { //store shiny in alpha if we don't have a specular map - //if (!mat || mat->getSpecularID().isNull()) + if (!mat || mat->getSpecularID().isNull()) { shiny_in_alpha = true; } } else { - if(LLPipeline::sRenderBump && tep->getShiny()) + if (!mat || mat->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_MASK) { shiny_in_alpha = true; } } - if(shiny_in_alpha) + + if (shiny_in_alpha) { + GLfloat alpha[4] = { - 0.00f, - 0.25f, - 0.5f, - 0.75f + 0.00f, + 0.25f, + 0.5f, + 0.75f }; llassert(tep->getShiny() <= 3); @@ -1555,11 +1562,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; @@ -1600,11 +1607,18 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, 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); @@ -1629,7 +1643,16 @@ 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); + + 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) @@ -1751,47 +1774,99 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, std::vector bump_tc; + if (mat && !mat->getNormalID().isNull()) + { //writing out normal and specular texture coordinates, not bump offsets + do_bump = false; + } + LLStrider dst; - mVertexBuffer->getTexCoord0Strider(dst, mGeomIndex, mGeomCount, map_range); + for (U32 ch = 0; ch < 3; ++ch) + { + switch (ch) + { + case 0: + mVertexBuffer->getTexCoord0Strider(dst, mGeomIndex, mGeomCount, map_range); + break; + case 1: + if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) + { + mVertexBuffer->getTexCoord1Strider(dst, mGeomIndex, mGeomCount, map_range); + if (mat && !tex_anim) + { + r = mat->getNormalRotation(); + mat->getNormalOffset(os, ot); + mat->getNormalRepeat(ms, mt); - - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); + cos_ang = cos(r); + sin_ang = sin(r); + + } + } + else + { + continue; + } + break; + case 2: + if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2)) + { + 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); + } + } + else + { + continue; + } + break; + } + + + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); - LLVector4a& norm = vf.mNormals[i]; + LLVector4a& norm = vf.mNormals[i]; - LLVector4a& center = *(vf.mCenter); + LLVector4a& center = *(vf.mCenter); - if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) - { - LLVector4a vec = vf.mPositions[i]; - - vec.mul(scalea); - - if (texgen == LLTextureEntry::TEX_GEN_PLANAR) + if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) { - planarProjection(tc, norm, center, vec); + LLVector4a vec = vf.mPositions[i]; + + vec.mul(scalea); + + 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); - } + 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); + *dst++ = tc; + if (do_bump) + { + bump_tc.push_back(tc); + } } } @@ -1800,7 +1875,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, mVertexBuffer->flush(); } - if (do_bump) + if (!mat && do_bump) { mVertexBuffer->getTexCoord1Strider(tex_coords1, mGeomIndex, mGeomCount, map_range); @@ -1846,20 +1921,31 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_pos) { - LLFastTimer t(FTM_FACE_GEOM_POSITION); + LLVector4a* src = vf.mPositions; + + //_mm_prefetch((char*)src, _MM_HINT_T0); + + LLVector4a* end = src+num_vertices; + //LLVector4a* end_64 = end-4; + + //LLFastTimer t(FTM_FACE_GEOM_POSITION); llassert(num_vertices > 0); mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); - LLMatrix4a mat_vert; mat_vert.loadu(mat_vert_in); - LLVector4a* src = vf.mPositions; - volatile F32* dst = (volatile F32*) vert.get(); + F32* dst = (F32*) vert.get(); + F32* end_f32 = dst+mGeomCount*4; - volatile F32* end = dst+num_vertices*4; - LLVector4a res; + //_mm_prefetch((char*)dst, _MM_HINT_NTA); + //_mm_prefetch((char*)src, _MM_HINT_NTA); + + //_mm_prefetch((char*)dst, _MM_HINT_NTA); + + + LLVector4a res0; //,res1,res2,res3; LLVector4a texIdx; @@ -1880,29 +1966,53 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, texIdx.set(0,0,0,val); - { - LLFastTimer t(FTM_FACE_POSITION_STORE); - LLVector4a tmp; + LLVector4a tmp; - do + { + //LLFastTimer t2(FTM_FACE_POSITION_STORE); + + /*if (num_vertices > 4) + { //more than 64 bytes + while (src < end_64) + { + _mm_prefetch((char*)src + 64, _MM_HINT_T0); + _mm_prefetch((char*)dst + 64, _MM_HINT_T0); + + mat_vert.affineTransform(*src, res0); + tmp.setSelectWithMask(mask, texIdx, res0); + tmp.store4a((F32*) dst); + + mat_vert.affineTransform(*(src+1), res1); + tmp.setSelectWithMask(mask, texIdx, res1); + tmp.store4a((F32*) dst+4); + + mat_vert.affineTransform(*(src+2), res2); + tmp.setSelectWithMask(mask, texIdx, res2); + tmp.store4a((F32*) dst+8); + + mat_vert.affineTransform(*(src+3), res3); + tmp.setSelectWithMask(mask, texIdx, res3); + tmp.store4a((F32*) dst+12); + + dst += 16; + src += 4; + } + }*/ + + while (src < end) { - mat_vert.affineTransform(*src++, res); - tmp.setSelectWithMask(mask, texIdx, res); + mat_vert.affineTransform(*src++, res0); + tmp.setSelectWithMask(mask, texIdx, res0); tmp.store4a((F32*) dst); dst += 4; } - while(dst < end); } { - LLFastTimer t(FTM_FACE_POSITION_PAD); - S32 aligned_pad_vertices = mGeomCount - num_vertices; - res.set(res[0], res[1], res[2], 0.f); - - while (aligned_pad_vertices > 0) + //LLFastTimer t(FTM_FACE_POSITION_PAD); + while (dst < end_f32) { - --aligned_pad_vertices; - res.store4a((F32*) dst); + res0.store4a((F32*) dst); dst += 4; } } @@ -1916,14 +2026,16 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_normal) { - LLFastTimer t(FTM_FACE_GEOM_NORMAL); + //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* src = vf.mNormals; + LLVector4a* end = src+num_vertices; + + while (src < end) { LLVector4a normal; - mat_normal.rotate(vf.mNormals[i], normal); - normal.normalize3fast(); + mat_normal.rotate(*src++, normal); normal.store4a(normals); normals += 4; } @@ -1946,14 +2058,18 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, mask.clear(); mask.setElement<3>(); - for (S32 i = 0; i < num_vertices; i++) + LLVector4a* src = vf.mTangents; + LLVector4a* end = vf.mTangents+num_vertices; + + while (src < end) { LLVector4a tangent_out; - mat_normal.rotate(vf.mTangents[i], tangent_out); + mat_normal.rotate(*src, tangent_out); tangent_out.normalize3fast(); - tangent_out.setSelectWithMask(mask, vf.mTangents[i], tangent_out); + tangent_out.setSelectWithMask(mask, *src, tangent_out); tangent_out.store4a(tangents); + src++; tangents += 4; } @@ -2073,16 +2189,23 @@ 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. } + const F32 LEAST_IMPORTANCE = 0.05f ; const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ; +void LLFace::resetVirtualSize() +{ + setVirtualSize(0.f); + mImportanceToCamera = 0.f; +} + F32 LLFace::getTextureVirtualSize() { F32 radius; @@ -2118,11 +2241,11 @@ F32 LLFace::getTextureVirtualSize() } face_area = LLFace::adjustPixelArea(mImportanceToCamera, face_area); - if (/*mImportanceToCamera < 1.0f && */face_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping. + 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()) - { - face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius); + 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 ); } } @@ -2148,9 +2271,18 @@ BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) LLVector4a t; t.load3(camera->getOrigin().mV); lookAt.setSub(center, t); + F32 dist = lookAt.getLength3().getF32(); dist = llmax(dist-size.getLength3().getF32(), 0.001f); - lookAt.normalize3fast() ; + //ramp down distance for nearby objects + if (dist < 16.f) + { + dist /= 16.f; + dist *= dist; + dist *= 16.f; + } + + lookAt.normalize3fast(); //get area of circle around node F32 app_angle = atanf((F32) sqrt(size_squared) / dist); @@ -2486,9 +2618,12 @@ LLVector3 LLFace::getPositionAgent() const return mCenterLocal * getRenderMatrix(); } } -LLViewerTexture* LLFace::getTexture() const + +LLViewerTexture* LLFace::getTexture(U32 ch) const { - return mTexture ; + llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); + + return mTexture[ch] ; } void LLFace::setVertexBuffer(LLVertexBuffer* buffer) @@ -2506,6 +2641,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, diff --git a/indra/newview/llface.h b/indra/newview/llface.h index d290ab292..7cdb6272e 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -2,31 +2,25 @@ * @file llface.h * @brief LLFace class definition * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -115,8 +109,12 @@ public: U16 getGeomStart() const { return mGeomIndex; } // index into draw pool void setTextureIndex(U8 index); U8 getTextureIndex() const { return mTextureIndex; } + void setTexture(U32 ch, LLViewerTexture* tex); void setTexture(LLViewerTexture* tex) ; - void switchTexture(LLViewerTexture* new_texture); + void setDiffuseMap(LLViewerTexture* tex); + void setNormalMap(LLViewerTexture* tex); + void setSpecularMap(LLViewerTexture* tex); + void switchTexture(U32 ch, LLViewerTexture* new_texture); void dirtyTexture(); LLXformMatrix* getXform() const { return mXform; } BOOL hasGeometry() const { return mGeomCount > 0; } @@ -135,8 +133,8 @@ public: F32 getVirtualSize() const { return mVSize; } F32 getPixelArea() const { return mPixelArea; } - S32 getIndexInTex() const {return mIndexInTex ;} - void setIndexInTex(S32 index) { mIndexInTex = index ;} + S32 getIndexInTex(U32 ch) const {llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); return mIndexInTex[ch];} + void setIndexInTex(U32 ch, S32 index) { llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); mIndexInTex[ch] = index ;} void renderSetColor() const; S32 renderElements(const U16 *index_array) const; @@ -154,7 +152,7 @@ public: S32 getLOD() const { return mVObjp.notNull() ? mVObjp->getLOD() : 0; } void setPoolType(U32 type) { mPoolType = type; } S32 getTEOffset() { return mTEOffset; } - LLViewerTexture* getTexture() const; + LLViewerTexture* getTexture(U32 ch = LLRender::DIFFUSE_MAP) const; void setViewerObject(LLViewerObject* object); void setPool(LLFacePool *pool, LLViewerTexture *texturep); @@ -196,10 +194,9 @@ public: S32 getColors(LLStrider &colors); S32 getIndices(LLStrider &indices); - void setSize(S32 numVertices, const S32 num_indices = 0, bool align = false); + void setSize(S32 numVertices, S32 num_indices = 0, bool align = false); - BOOL genVolumeBBoxes(const LLVolume &volume, S32 f, - const LLMatrix4& mat, const LLMatrix3& inv_trans_mat, BOOL global_volume = FALSE); + BOOL genVolumeBBoxes(const LLVolume &volume, S32 f,const LLMatrix4& mat, BOOL global_volume = FALSE); void init(LLDrawable* drawablep, LLViewerObject* objp); void destroy(); @@ -224,9 +221,13 @@ public: F32 getTextureVirtualSize() ; F32 getImportanceToCamera()const {return mImportanceToCamera ;} + void resetVirtualSize(); void setHasMedia(bool has_media) { mHasMedia = has_media ;} BOOL hasMedia() const ; + + BOOL switchTexture() ; + //vertex buffer tracking void setVertexBuffer(LLVertexBuffer* buffer); void clearVertexBuffer(); //sets mVertexBuffer and mLastVertexBuffer to NULL @@ -258,6 +259,8 @@ public: F32 mLastSkinTime; F32 mLastMoveTime; LLMatrix4* mTextureMatrix; + LLMatrix4* mSpecMapMatrix; + LLMatrix4* mNormalMapMatrix; LLDrawInfo* mDrawInfo; private: @@ -273,10 +276,12 @@ private: U8 mTextureIndex; // index of texture channel to use for pseudo-atlasing U32 mIndicesCount; U32 mIndicesIndex; // index into draw pool for indices (yeah, I know!) - S32 mIndexInTex ; + S32 mIndexInTex[LLRender::NUM_TEXTURE_CHANNELS]; LLXformMatrix* mXform; - LLPointer mTexture; + + LLPointer mTexture[LLRender::NUM_TEXTURE_CHANNELS]; + LLPointer mDrawablep; LLPointer mVObjp; S32 mTEOffset; diff --git a/indra/newview/llface.inl b/indra/newview/llface.inl index 176c73e38..85c35a88f 100644 --- a/indra/newview/llface.inl +++ b/indra/newview/llface.inl @@ -2,31 +2,25 @@ * @file llface.inl * @brief Inline functions for LLFace * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp index 0648b902a..b9d5177fc 100644 --- a/indra/newview/llmaterialmgr.cpp +++ b/indra/newview/llmaterialmgr.cpp @@ -50,6 +50,7 @@ #define MATERIALS_CAP_MATERIAL_FIELD "Material" #define MATERIALS_CAP_OBJECT_ID_FIELD "ID" #define MATERIALS_CAP_MATERIAL_ID_FIELD "MaterialID" +#define SIM_FEATURE_MAX_MATERIALS_PER_TRANSACTION "MaxMaterialsPerTransaction" #define MATERIALS_GET_MAX_ENTRIES 50 #define MATERIALS_GET_TIMEOUT (60.f * 20) @@ -339,36 +340,29 @@ const LLMaterialPtr LLMaterialMgr::setMaterial(const LLUUID& region_id, const LL itMaterial = ret.first; } - // we may have cleared our queues on leaving a region before we recv'd our - // update for this material...too late now! - // - if (isGetPending(region_id, material_id)) - { - - TEMaterialPair te_mat_pair; - te_mat_pair.materialID = material_id; + TEMaterialPair te_mat_pair; + te_mat_pair.materialID = material_id; - U32 i = 0; - while (i < LLTEContents::MAX_TES) + U32 i = 0; + while (i < LLTEContents::MAX_TES) + { + te_mat_pair.te = i++; + get_callback_te_map_t::iterator itCallbackTE = mGetTECallbacks.find(te_mat_pair); + if (itCallbackTE != mGetTECallbacks.end()) { - te_mat_pair.te = i++; - get_callback_te_map_t::iterator itCallbackTE = mGetTECallbacks.find(te_mat_pair); - if (itCallbackTE != mGetTECallbacks.end()) - { - (*itCallbackTE->second)(material_id, itMaterial->second, te_mat_pair.te); - delete itCallbackTE->second; - mGetTECallbacks.erase(itCallbackTE); - } + (*itCallbackTE->second)(material_id, itMaterial->second, te_mat_pair.te); + delete itCallbackTE->second; + mGetTECallbacks.erase(itCallbackTE); } + } - get_callback_map_t::iterator itCallback = mGetCallbacks.find(material_id); - if (itCallback != mGetCallbacks.end()) - { - (*itCallback->second)(material_id, itMaterial->second); + get_callback_map_t::iterator itCallback = mGetCallbacks.find(material_id); + if (itCallback != mGetCallbacks.end()) + { + (*itCallback->second)(material_id, itMaterial->second); - delete itCallback->second; - mGetCallbacks.erase(itCallback); - } + delete itCallback->second; + mGetCallbacks.erase(itCallback); } mGetPending.erase(pending_material_t(region_id, material_id)); @@ -555,11 +549,9 @@ void LLMaterialMgr::onIdle(void*) instancep->processGetAllQueue(); } - static LLFrameTimer mPutTimer; - if ( (!instancep->mPutQueue.empty()) && (mPutTimer.hasExpired()) ) + if (!instancep->mPutQueue.empty()) { instancep->processPutQueue(); - mPutTimer.reset(MATERIALS_PUT_THROTTLE_SECS); } } @@ -576,14 +568,14 @@ void LLMaterialMgr::processGetQueue() continue; } - const LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id); + LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id); if (!regionp) { LL_WARNS("Materials") << "Unknown region with id " << region_id.asString() << LL_ENDL; mGetQueue.erase(itRegionQueue); continue; } - else if (!regionp->capabilitiesReceived()) + else if (!regionp->capabilitiesReceived() || regionp->materialsCapThrottled()) { continue; } @@ -606,8 +598,9 @@ void LLMaterialMgr::processGetQueue() LLSD materialsData = LLSD::emptyArray(); material_queue_t& materials = itRegionQueue->second; + U32 max_entries = regionp->getMaxMaterialsPerTransaction(); material_queue_t::iterator loopMaterial = materials.begin(); - while ( (materials.end() != loopMaterial) && (materialsData.size() <= MATERIALS_GET_MAX_ENTRIES) ) + while ( (materials.end() != loopMaterial) && (materialsData.size() < (int)max_entries) ) { material_queue_t::iterator itMaterial = loopMaterial++; materialsData.append((*itMaterial).asLLSD()); @@ -639,6 +632,7 @@ void LLMaterialMgr::processGetQueue() LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '"<< capURL << " for " << materialsData.size() << " materials." << "\ndata: " << ll_pretty_print_sd(materialsData) << LL_ENDL; LLHTTPClient::post(capURL, postData, materialsResponder); + regionp->resetMaterialsCapThrottle(); } } @@ -657,7 +651,7 @@ void LLMaterialMgr::processGetAllQueue() clearGetQueues(region_id); // Invalidates region_id continue; } - else if (!regionp->capabilitiesReceived()) + else if (!regionp->capabilitiesReceived() || regionp->materialsCapThrottled()) { continue; } @@ -674,6 +668,7 @@ void LLMaterialMgr::processGetAllQueue() LL_DEBUGS("Materials") << "GET all for region " << region_id << "url " << capURL << LL_ENDL; LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("GET", capURL, boost::bind(&LLMaterialMgr::onGetAllResponse, this, _1, _2, *itRegion)); LLHTTPClient::get(capURL, materialsResponder); + regionp->resetMaterialsCapThrottle(); mGetAllPending.insert(std::pair(region_id, LLFrameTimer::getTotalSeconds())); mGetAllQueue.erase(itRegion); // Invalidates region_id } @@ -681,7 +676,7 @@ void LLMaterialMgr::processGetAllQueue() void LLMaterialMgr::processPutQueue() { - typedef std::map regionput_request_map; + typedef std::map regionput_request_map; regionput_request_map requests; put_queue_t::iterator loopQueue = mPutQueue.begin(); @@ -691,25 +686,27 @@ void LLMaterialMgr::processPutQueue() const LLUUID& object_id = itQueue->first; const LLViewerObject* objectp = gObjectList.findObject(object_id); - if ( (!objectp) || (!objectp->getRegion()) ) + if ( !objectp ) { - LL_WARNS("Materials") << "Object or object region is NULL" << LL_ENDL; - + LL_WARNS("Materials") << "Object is NULL" << LL_ENDL; mPutQueue.erase(itQueue); - continue; } - - const LLViewerRegion* regionp = objectp->getRegion(); - if (!regionp->capabilitiesReceived()) + else { - continue; + LLViewerRegion* regionp = objectp->getRegion(); + if ( !regionp ) + { + LL_WARNS("Materials") << "Object region is NULL" << LL_ENDL; + mPutQueue.erase(itQueue); } - + else if ( regionp->capabilitiesReceived() && !regionp->materialsCapThrottled()) + { LLSD& facesData = requests[regionp]; facematerial_map_t& face_map = itQueue->second; + U32 max_entries = regionp->getMaxMaterialsPerTransaction(); facematerial_map_t::iterator itFace = face_map.begin(); - while ( (face_map.end() != itFace) && (facesData.size() < MATERIALS_GET_MAX_ENTRIES) ) + while ( (face_map.end() != itFace) && (facesData.size() < (int)max_entries) ) { LLSD faceData = LLSD::emptyMap(); faceData[MATERIALS_CAP_FACE_FIELD] = static_cast(itFace->first); @@ -726,14 +723,17 @@ void LLMaterialMgr::processPutQueue() mPutQueue.erase(itQueue); } } + } + } for (regionput_request_map::const_iterator itRequest = requests.begin(); itRequest != requests.end(); ++itRequest) { - std::string capURL = itRequest->first->getCapability(MATERIALS_CAPABILITY_NAME); + LLViewerRegion* regionp = itRequest->first; + std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME); if (capURL.empty()) { LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME - << "' is not defined on region '" << itRequest->first->getName() << "'" << LL_ENDL; + << "' is not defined on region '" << regionp->getName() << "'" << LL_ENDL; continue; } @@ -756,6 +756,7 @@ void LLMaterialMgr::processPutQueue() LL_DEBUGS("Materials") << "put for " << itRequest->second.size() << " faces to region " << itRequest->first->getName() << LL_ENDL; LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("PUT", capURL, boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2)); LLHTTPClient::put(capURL, putData, materialsResponder); + regionp->resetMaterialsCapThrottle(); } else { diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h index e317a791a..e83f1f4e0 100644 --- a/indra/newview/llmaterialmgr.h +++ b/indra/newview/llmaterialmgr.h @@ -124,6 +124,8 @@ protected: put_queue_t mPutQueue; material_map_t mMaterials; + + U32 getMaxEntries(const LLViewerRegion* regionp); }; #endif // LL_LLMATERIALMGR_H diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index e15e08c5a..d08f847a8 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2386,7 +2386,7 @@ void pushBufferVerts(LLVertexBuffer* buffer, U32 mask) } } -void pushBufferVerts(LLSpatialGroup* group, U32 mask) +void pushBufferVerts(LLSpatialGroup* group, U32 mask, bool push_alpha = true) { if (group->mSpatialPartition->mRenderByGroup) { @@ -2395,7 +2395,10 @@ void pushBufferVerts(LLSpatialGroup* group, U32 mask) LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin()); LLRenderPass::applyModelMatrix(*params); - pushBufferVerts(group->mVertexBuffer, mask); + if (push_alpha) + { + pushBufferVerts(group->mVertexBuffer, mask); + } for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) { @@ -2858,20 +2861,23 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) const LLVector4a* ext; LLVector4a pos, size; - //render face bounding boxes - for (S32 i = 0; i < drawable->getNumFaces(); i++) + if (drawable->getVOVolume()) { - LLFace* facep = drawable->getFace(i); - if (facep) + //render face bounding boxes + for (S32 i = 0; i < drawable->getNumFaces(); i++) { - ext = facep->mExtents; + LLFace* facep = drawable->getFace(i); + if (facep) + { + ext = facep->mExtents; - pos.setAdd(ext[0], ext[1]); - pos.mul(0.5f); - size.setSub(ext[1], ext[0]); - size.mul(0.5f); + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + size.setSub(ext[1], ext[0]); + size.mul(0.5f); - drawBoxOutline(pos,size); + drawBoxOutline(pos,size); + } } } @@ -4442,7 +4448,16 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, mGroup(NULL), mFace(NULL), mDistance(0.f), - mDrawMode(LLRender::TRIANGLES) + mDrawMode(LLRender::TRIANGLES), + mMaterial(NULL), + mShaderMask(0), + mSpecColor(1.0f, 1.0f, 1.0f, 0.5f), + mBlendFuncSrc(LLRender::BF_SOURCE_ALPHA), + mBlendFuncDst(LLRender::BF_ONE_MINUS_SOURCE_ALPHA), + mHasGlow(FALSE), + mEnvIntensity(0.0f), + mAlphaMaskCutoff(0.5f), + mDiffuseAlphaMode(0) { mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index f41c3a57c..3ab2d2b68 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -117,6 +117,7 @@ public: U32 mOffset; BOOL mFullbright; U8 mBump; + U8 mShiny; BOOL mParticle; F32 mPartSize; F32 mVSize; @@ -124,6 +125,21 @@ public: LL_ALIGN_16(LLFace* mFace); //associated face F32 mDistance; U32 mDrawMode; + LLMaterialPtr mMaterial; // If this is null, the following parameters are unused. + LLMaterialID mMaterialID; + U32 mShaderMask; + U32 mBlendFuncSrc; + U32 mBlendFuncDst; + BOOL mHasGlow; + LLPointer mSpecularMap; + const LLMatrix4* mSpecularMapMatrix; + LLPointer mNormalMap; + const LLMatrix4* mNormalMapMatrix; + LLVector4 mSpecColor; // XYZ = Specular RGB, W = Specular Exponent + F32 mEnvIntensity; + F32 mAlphaMaskCutoff; + U8 mDiffuseAlphaMode; + struct CompareTexture { diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index eecabfb9f..92278c941 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1158,6 +1158,7 @@ void render_hud_attachments() if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices()) { + LLPipeline::sRenderingHUDs = TRUE; LLCamera hud_cam = *LLViewerCamera::getInstance(); hud_cam.setOrigin(-1.f,0,0); hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1)); @@ -1203,10 +1204,13 @@ void render_hud_attachments() gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA_MASK); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_MATERIAL); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY); @@ -1231,6 +1235,7 @@ void render_hud_attachments() gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); } LLPipeline::sUseOcclusion = use_occlusion; + LLPipeline::sRenderingHUDs = FALSE; } gGL.matrixMode(LLRender::MM_PROJECTION); gGL.popMatrix(); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 45d486784..b81deb190 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -208,6 +208,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), @@ -336,6 +338,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() @@ -1600,6 +1614,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, dp->setPassFlags(value); dp->unpackUUID(owner_id, "Owner"); + mOwnerID = owner_id; + if (value & 0x80) { dp->unpackVector3(new_angv, "Omega"); @@ -1688,9 +1704,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // if (value & 0x8) { - unpackParticleSource(*dp, owner_id); + unpackParticleSource(*dp, owner_id, true); } - else + else if (!(value & 0x400)) { deleteParticleSource(); } @@ -4048,25 +4064,39 @@ void LLViewerObject::setNumTEs(const U8 num_tes) { LLPointer *new_images; new_images = new LLPointer[num_tes]; + + LLPointer *new_normmaps; + new_normmaps = new LLPointer[num_tes]; + + LLPointer *new_specmaps; + new_specmaps = new LLPointer[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[getNumTEs()-1]; + new_specmaps[i] = mTESpecularMaps[getNumTEs()-1]; } else { new_images[i] = NULL; + new_normmaps[i] = NULL; + new_specmaps[i] = NULL; } } deleteTEImages(); mTEImages = new_images; + mTENormalMaps = new_normmaps; + mTESpecularMaps = new_specmaps; } else { @@ -4161,12 +4191,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(); + + const LLUUID& image_id = getTE(te)->getID(); mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); -// } + + if (getTE(te)->getMaterialParams().notNull()) + { + const LLUUID& norm_id = getTE(te)->getMaterialParams()->getNormalID(); + mTENormalMaps[te] = LLViewerTextureManager::getFetchedTexture(norm_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + + const LLUUID& spec_id = getTE(te)->getMaterialParams()->getSpecularID(); + mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } } void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep) @@ -4201,6 +4237,52 @@ S32 LLViewerObject::setTETextureCore(const U8 te, LLViewerTexture *image) return retval; } +S32 LLViewerObject::setTENormalMapCore(const U8 te, LLViewerTexture *image) +{ + S32 retval = TEM_CHANGE_TEXTURE; + const LLUUID& uuid = image ? image->getID() : LLUUID::null; + if (uuid != getTE(te)->getID() || + uuid == LLUUID::null) + { + LLTextureEntry* tep = getTE(te); + LLMaterial* mat = NULL; + if (tep) + { + mat = tep->getMaterialParams(); + } + + if (mat) + { + mat->setNormalID(uuid); + } + } + changeTENormalMap(te,image); + return retval; +} + +S32 LLViewerObject::setTESpecularMapCore(const U8 te, LLViewerTexture *image) +{ + S32 retval = TEM_CHANGE_TEXTURE; + const LLUUID& uuid = image ? image->getID() : LLUUID::null; + if (uuid != getTE(te)->getID() || + uuid == LLUUID::null) + { + LLTextureEntry* tep = getTE(te); + LLMaterial* mat = NULL; + if (tep) + { + mat = tep->getMaterialParams(); + } + + if (mat) + { + mat->setSpecularID(uuid); + } + } + changeTESpecularMap(te, image); + return retval; +} + //virtual void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image) { @@ -4211,6 +4293,25 @@ 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 ; + refreshMaterials(); +} + +void LLViewerObject::changeTESpecularMap(S32 index, LLViewerTexture* new_image) +{ + if(index < 0 || index >= getNumTEs()) + { + return ; + } + mTESpecularMaps[index] = new_image ; + refreshMaterials(); +} S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid) { // Invalid host == get from the agent's sim @@ -4219,6 +4320,19 @@ S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid) return setTETextureCore(te,image); } +S32 LLViewerObject::setTENormalMap(const U8 te, const LLUUID& uuid) +{ + LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( + uuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + return setTENormalMapCore(te, image); +} + +S32 LLViewerObject::setTESpecularMap(const U8 te, const LLUUID& uuid) +{ + LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( + uuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + return setTESpecularMapCore(te, image); +} S32 LLViewerObject::setTEColor(const U8 te, const LLColor3& color) { @@ -4379,6 +4493,59 @@ S32 LLViewerObject::setTEGlow(const U8 te, const F32 glow) return retval; } +S32 LLViewerObject::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) +{ + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS("Material") << "No texture entry for te " << (S32)te + << ", object " << mID + << ", material " << pMaterialID + << LL_ENDL; + } + //else if (pMaterialID != tep->getMaterialID()) + { + LL_DEBUGS("Material") << "Changing texture entry for te " << (S32)te + << ", object " << mID + << ", material " << pMaterialID + << LL_ENDL; + retval = LLPrimitive::setTEMaterialID(te, pMaterialID); + refreshMaterials(); + } + 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; + return 0; + } + + retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams); + LL_DEBUGS("Material") << "Changing material params for te " << (S32)te + << ", object " << mID + << " (" << retval << ")" + << LL_ENDL; + setTENormalMap(te, (pMaterialParams) ? pMaterialParams->getNormalID() : LLUUID::null); + setTESpecularMap(te, (pMaterialParams) ? pMaterialParams->getSpecularID() : LLUUID::null); + + refreshMaterials(); + return retval; +} + +void LLViewerObject::refreshMaterials() +{ + setChanged(TEXTURE); + if (mDrawable.notNull()) + { + gPipeline.markTextured(mDrawable); + } +} S32 LLViewerObject::setTEScale(const U8 te, const F32 s, const F32 t) { @@ -4480,6 +4647,74 @@ LLViewerTexture *LLViewerObject::getTEImage(const U8 face) const } +bool LLViewerObject::isImageAlphaBlended(const U8 te) const +{ + LLViewerTexture* image = getTEImage(te); + LLGLenum format = image ? image->getPrimaryFormat() : GL_RGB; + switch (format) + { + case GL_RGBA: + case GL_ALPHA: + { + return true; + } + break; + + case GL_RGB: break; + default: + { + llwarns << "Unexpected tex format in LLViewerObject::isImageAlphaBlended...returning no alpha." << llendl; + } + break; + } + + return false; +} + +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; @@ -4766,7 +5001,7 @@ void LLViewerObject::unpackParticleSource(const S32 block_num, const LLUUID& own } } -void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id) +void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy) { if (!mPartSourcep.isNull() && mPartSourcep->isDead()) { @@ -4775,7 +5010,7 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_ if (mPartSourcep) { // If we've got one already, just update the existing source (or remove it) - if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp)) + if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp, legacy)) { mPartSourcep->setDead(); mPartSourcep = NULL; @@ -4783,7 +5018,7 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_ } else { - LLPointer pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp); + LLPointer pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp, legacy); //If the owner is muted, don't create the system if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return; // We need to be able to deal with a particle source that hasn't changed, but still got an update! @@ -5633,6 +5868,11 @@ F32 LLAlphaObject::getPartSize(S32 idx) return 0.f; } +void LLAlphaObject::getBlendFunc(S32 face, U32& src, U32& dst) +{ + +} + // virtual void LLStaticViewerObject::updateDrawable(BOOL force_damped) { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index d2ea9512d..2aa0e3869 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -224,6 +224,7 @@ public: virtual BOOL isFlexible() const { return FALSE; } virtual BOOL isSculpted() const { return FALSE; } virtual BOOL isMesh() const { return FALSE; } + virtual BOOL hasLightTexture() const { return FALSE; } // This method returns true if the object is over land owned by // the agent, one of its groups, or it encroaches and @@ -306,7 +307,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); - S32 setTETextureCore(const U8 te, LLViewerTexture *image); + /*virtual*/ S32 setTENormalMap(const U8 te, const LLUUID &uuid); + /*virtual*/ S32 setTESpecularMap(const U8 te, const LLUUID &uuid); + S32 setTETextureCore(const U8 te, LLViewerTexture *image); + S32 setTENormalMapCore(const U8 te, LLViewerTexture *image); + S32 setTESpecularMapCore(const U8 te, LLViewerTexture *image); /*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); @@ -323,11 +328,25 @@ public: /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright ); /*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); + + // Used by Materials update functions to properly kick off rebuilds + // of VBs etc when materials updates require changes. + // + void refreshMaterials(); + /*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 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; + bool isImageAlphaBlended(const U8 te) const; + void fitFaceTexture(const U8 face); void sendTEUpdate() const; // Sends packed representation of all texture entry information @@ -596,6 +615,7 @@ public: } EPhysicsShapeType; LLUUID mID; + LLUUID mOwnerID; //null if unknown // unique within region, not unique across regions // Local ID = 0 is not used @@ -608,6 +628,8 @@ public: S32 mListIndex; LLPointer *mTEImages; + LLPointer *mTENormalMaps; + LLPointer *mTESpecularMaps; // Selection, picking and rendering variables U32 mGLName; // GL "name" used by selection code @@ -679,7 +701,7 @@ protected: BOOL isOnMap(); void unpackParticleSource(const S32 block_num, const LLUUID& owner_id); - void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id); + void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy); void deleteParticleSource(); void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id); @@ -847,8 +869,11 @@ public: LLStrider& normalsp, LLStrider& texcoordsp, LLStrider& colorsp, + LLStrider& emissivep, LLStrider& indicesp) = 0; + virtual void getBlendFunc(S32 face, U32& src, U32& dst); + F32 mDepth; }; diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 92abe4bf2..660e48f22 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -86,12 +86,31 @@ LLViewerPart::LLViewerPart() : mImagep(NULL) { mPartSourcep = NULL; - + mParent = NULL; + mChild = NULL; ++LLViewerPartSim::sParticleCount2 ; } LLViewerPart::~LLViewerPart() { + if (mPartSourcep.notNull() && mPartSourcep->mLastPart == this) + { + mPartSourcep->mLastPart = NULL; + } + + //patch up holes in the ribbon + if (mParent) + { + llassert(mParent->mChild == this); + mParent->mChild = mChild; + } + + if (mChild) + { + llassert (mChild->mParent == this); + mChild->mParent = mParent; + } + mPartSourcep = NULL; --LLViewerPartSim::sParticleCount2 ; @@ -147,7 +166,11 @@ LLViewerPartGroup::LLViewerPartGroup(const LLVector3 ¢er_agent, const F32 bo } mVOPartGroupp->setViewerPartGroup(this); mVOPartGroupp->setPositionAgent(getCenterAgent()); + + mBoxSide = box_side; + F32 scale = box_side * 0.5f; + mVOPartGroupp->setScale(LLVector3(scale,scale,scale)); //gPipeline.addObject(mVOPartGroupp); @@ -373,6 +396,9 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt) part->mScale += frac*part->mEndScale; } + // Do glow interpolation + part->mGlow.mV[3] = (U8) llround(lerp(part->mStartGlow, part->mEndGlow, frac)*255.f); + // Set the last update time to now. part->mLastUpdateTime = cur_time; @@ -491,11 +517,16 @@ void LLViewerPartSim::destroyClass() mViewerPartSources.clear(); } +//static BOOL LLViewerPartSim::shouldAddPart() { + if (sParticleCount >= MAX_PART_COUNT) + { + return FALSE; + } + if (sParticleCount > PART_THROTTLE_THRESHOLD*sMaxParticleCount) { - F32 frac = (F32)sParticleCount/(F32)sMaxParticleCount; frac -= PART_THROTTLE_THRESHOLD; frac *= PART_THROTTLE_RESCALE; @@ -505,7 +536,10 @@ BOOL LLViewerPartSim::shouldAddPart() return FALSE; } } - if (sParticleCount >= MAX_PART_COUNT) + + // Check frame rate, and don't add more if the viewer is really slow + const F32 MIN_FRAME_RATE_FOR_NEW_PARTICLES = 4.f; + if (gFPSClamped < MIN_FRAME_RATE_FOR_NEW_PARTICLES) { return FALSE; } @@ -621,6 +655,9 @@ void LLViewerPartSim::updateSimulation() { static LLFrameTimer update_timer; + //reset VBO cursor + LLVOPartGroup::sVBSlotCursor = 0; + const F32 dt = llmin(update_timer.getElapsedTimeAndResetF32(), 0.1f); if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES))) diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h index 7e625f2c0..73d5096d7 100644 --- a/indra/newview/llviewerpartsim.h +++ b/indra/newview/llviewerpartsim.h @@ -71,15 +71,22 @@ public: LLVPCallback mVPCallback; // Callback function for more complicated behaviors LLPointer mPartSourcep; // Particle source used for this object - + + LLViewerPart* mParent; // particle to connect to if this is part of a particle ribbon + LLViewerPart* mChild; // child particle for clean reference destruction // Current particle state (possibly used for rendering) LLPointer mImagep; LLVector3 mPosAgent; LLVector3 mVelocity; LLVector3 mAccel; + LLVector3 mAxis; LLColor4 mColor; LLVector2 mScale; + F32 mStartGlow; + F32 mEndGlow; + LLColor4U mGlow; + static U32 sNextPartID; }; @@ -104,6 +111,9 @@ public: void shift(const LLVector3 &offset); + F32 getBoxRadius() { return mBoxRadius; } + F32 getBoxSide() { return mBoxSide; } + typedef std::vector part_list_t; part_list_t mParticles; @@ -124,6 +134,7 @@ public: protected: LLVector3 mCenterAgent; F32 mBoxRadius; + F32 mBoxSide; LLVector3 mMinObjPos; LLVector3 mMaxObjPos; @@ -148,7 +159,7 @@ public: void cleanupRegion(LLViewerRegion *regionp); - BOOL shouldAddPart(); // Just decides whether this particle should be added or not (for particle count capping) + static BOOL shouldAddPart(); // Just decides whether this particle should be added or not (for particle count capping) F32 maxRate() // Return maximum particle generation rate { if (sParticleCount >= MAX_PART_COUNT) diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp index d712138fd..ebda6fd78 100644 --- a/indra/newview/llviewerpartsource.cpp +++ b/indra/newview/llviewerpartsource.cpp @@ -58,6 +58,8 @@ LLViewerPartSource::LLViewerPartSource(const U32 type) : static U32 id_seed = 0; mID = ++id_seed; + mLastPart = NULL; + mDelay = 0 ; } @@ -285,6 +287,22 @@ void LLViewerPartSourceScript::update(const F32 dt) { part->mFlags |= LLPartData::LL_PART_HUD; } + + if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK && mLastPart) + { //set previous particle's parent to this particle to chain ribbon together + mLastPart->mParent = part; + part->mChild = mLastPart; + part->mAxis = LLVector3(0,0,1); + + if (mSourceObjectp.notNull()) + { + LLQuaternion rot = mSourceObjectp->getRenderRotation(); + part->mAxis *= rot; + } + } + + mLastPart = part; + part->mMaxAge = mPartSysData.mPartData.mMaxAge; part->mStartColor = mPartSysData.mPartData.mStartColor; part->mEndColor = mPartSysData.mPartData.mEndColor; @@ -296,6 +314,13 @@ void LLViewerPartSourceScript::update(const F32 dt) part->mAccel = mPartSysData.mPartAccel; + part->mBlendFuncDest = mPartSysData.mPartData.mBlendFuncDest; + part->mBlendFuncSource = mPartSysData.mPartData.mBlendFuncSource; + + part->mStartGlow = mPartSysData.mPartData.mStartGlow; + part->mEndGlow = mPartSysData.mPartData.mEndGlow; + part->mGlow = LLColor4U(0, 0, 0, (U8) llround(part->mStartGlow*255.f)); + if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP) { part->mPosAgent = mPosAgent; @@ -436,28 +461,51 @@ LLPointer LLViewerPartSourceScript::unpackPSS(LLViewer } -LLPointer LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer pssp, LLDataPacker &dp) +LLPointer LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer pssp, LLDataPacker &dp, bool legacy) { if (!pssp) { LLPointer new_pssp = new LLViewerPartSourceScript(source_objp); - if (!new_pssp->mPartSysData.unpack(dp)) + if (legacy) { - return NULL; + if (!new_pssp->mPartSysData.unpackLegacy(dp)) + { + return NULL; + } } + else + { + if (!new_pssp->mPartSysData.unpack(dp)) + { + return NULL; + } + } + if (new_pssp->mPartSysData.mTargetUUID.notNull()) { LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID); new_pssp->setTargetObject(target_objp); } + return new_pssp; } else { - if (!pssp->mPartSysData.unpack(dp)) + if (legacy) { - return NULL; + if (!pssp->mPartSysData.unpackLegacy(dp)) + { + return NULL; + } } + else + { + if (!pssp->mPartSysData.unpack(dp)) + { + return NULL; + } + } + if (pssp->mPartSysData.mTargetUUID.notNull()) { LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID); @@ -575,6 +623,11 @@ void LLViewerPartSourceSpiral::update(const F32 dt) part->mScale.mV[0] = 0.25f; part->mScale.mV[1] = 0.25f; part->mParameter = ll_frand(F_TWO_PI); + part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; + part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; + part->mStartGlow = 0.f; + part->mEndGlow = 0.f; + part->mGlow = LLColor4U(0, 0, 0, 0); LLViewerPartSim::getInstance()->addPart(part); } @@ -727,6 +780,12 @@ void LLViewerPartSourceBeam::update(const F32 dt) part->mPosAgent = mPosAgent; part->mVelocity = mTargetPosAgent - mPosAgent; + part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; + part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; + part->mStartGlow = 0.f; + part->mEndGlow = 0.f; + part->mGlow = LLColor4U(0, 0, 0, 0); + LLViewerPartSim::getInstance()->addPart(part); } } @@ -831,6 +890,12 @@ void LLViewerPartSourceChat::update(const F32 dt) part->mScale.mV[0] = 0.25f; part->mScale.mV[1] = 0.25f; part->mParameter = ll_frand(F_TWO_PI); + part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; + part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; + part->mStartGlow = 0.f; + part->mEndGlow = 0.f; + part->mGlow = LLColor4U(0, 0, 0, 0); + LLViewerPartSim::getInstance()->addPart(part); } diff --git a/indra/newview/llviewerpartsource.h b/indra/newview/llviewerpartsource.h index 540e30eb1..d05d50d36 100644 --- a/indra/newview/llviewerpartsource.h +++ b/indra/newview/llviewerpartsource.h @@ -82,6 +82,7 @@ public: LLVector3 mLastUpdatePosAgent; LLPointer mSourceObjectp; U32 mID; + LLViewerPart* mLastPart; //last particle emitted (for making particle ribbons) protected: U32 mType; @@ -120,7 +121,7 @@ public: // Returns a new particle source to attach to an object... static LLPointer unpackPSS(LLViewerObject *source_objp, LLPointer pssp, const S32 block_num); - static LLPointer unpackPSS(LLViewerObject *source_objp, LLPointer pssp, LLDataPacker &dp); + static LLPointer unpackPSS(LLViewerObject *source_objp, LLPointer pssp, LLDataPacker &dp, bool legacy); static LLPointer createPSS(LLViewerObject *source_objp, const LLPartSysData& particle_parameters); LLViewerTexture *getImage() const { return mImagep; } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 9402996b4..161ac8f91 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2093,3 +2093,45 @@ boost::signals2::connection LLViewerRegion::setFeaturesReceivedCallback(const fe return mFeaturesReceivedSignal.connect(cb); } +void LLViewerRegion::resetMaterialsCapThrottle() +{ + F32 requests_per_sec = 1.0f; // original default; + if ( mSimulatorFeatures.has("RenderMaterialsCapability") + && mSimulatorFeatures["RenderMaterialsCapability"].isReal() ) + { + requests_per_sec = mSimulatorFeatures["RenderMaterialsCapability"].asReal(); + if ( requests_per_sec == 0.0f ) + { + requests_per_sec = 1.0f; + LL_WARNS("Materials") + << "region '" << getName() + << "' returned zero for RenderMaterialsCapability; using default " + << requests_per_sec << " per second" + << LL_ENDL; + } + LL_DEBUGS("Materials") << "region '" << getName() + << "' RenderMaterialsCapability " << requests_per_sec + << LL_ENDL; + } + else + { + LL_DEBUGS("Materials") + << "region '" << getName() + << "' did not return RenderMaterialsCapability, using default " + << requests_per_sec << " per second" + << LL_ENDL; + } + + mMaterialsCapThrottleTimer.resetWithExpiry( 1.0f / requests_per_sec ); +} + +U32 LLViewerRegion::getMaxMaterialsPerTransaction() const +{ + U32 max_entries = 50; // original hard coded default + if ( mSimulatorFeatures.has( "MaxMaterialsPerTransaction" ) + && mSimulatorFeatures[ "MaxMaterialsPerTransaction" ].isInteger()) + { + max_entries = mSimulatorFeatures[ "MaxMaterialsPerTransaction" ].asInteger(); + } + return max_entries; +} \ No newline at end of file diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 6b0e73b49..c2cc7fe39 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -358,7 +358,12 @@ public: void setGamingData(const LLSD& info); const U32 getGamingFlags() const { return mGamingFlags; } - + + // implements the materials capability throttle + bool materialsCapThrottled() const { return !mMaterialsCapThrottleTimer.hasExpired(); } + void resetMaterialsCapThrottle(); + + U32 getMaxMaterialsPerTransaction() const; public: struct CompareDistance { @@ -458,6 +463,9 @@ private: LLSD mSimulatorFeatures; U32 mGamingFlags; + // the materials capability throttle + LLFrameTimer mMaterialsCapThrottleTimer; +LLFrameTimer mRenderInfoRequestTimer; }; inline BOOL LLViewerRegion::getRegionProtocol(U64 protocol) const diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 61c4fb06d..57d7e2cc9 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -106,6 +106,7 @@ LLGLSLShader gSolidColorProgram(LLViewerShaderMgr::SHADER_INTERFACE); //object shaders LLGLSLShader gObjectSimpleProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectSimpleImpostorProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectPreviewProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectSimpleWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectSimpleAlphaMaskProgram(LLViewerShaderMgr::SHADER_OBJECT); @@ -185,6 +186,7 @@ LLGLSLShader gPostVignetteProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in // Deferred rendering shaders LLGLSLShader gDeferredImpostorProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredWaterProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics +LLGLSLShader gDeferredUnderWaterProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredDiffuseProgram(LLViewerShaderMgr::SHADER_DEFERRED);//Not in mShaderList LLGLSLShader gDeferredDiffuseAlphaMaskProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredNonIndexedDiffuseProgram(LLViewerShaderMgr::SHADER_DEFERRED); @@ -200,30 +202,44 @@ LLGLSLShader gDeferredTreeShadowProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredAvatarProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList LLGLSLShader gDeferredAvatarAlphaProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics LLGLSLShader gDeferredLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); -LLGLSLShader gDeferredMultiLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShaderArray gDeferredMultiLightProgram[16]; LLGLSLShader gDeferredSpotLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList LLGLSLShader gDeferredMultiSpotLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList LLGLSLShader gDeferredSunProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredBlurLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredSoftenProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredSoftenWaterProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredShadowProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList LLGLSLShader gDeferredShadowCubeProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredShadowAlphaMaskProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredAvatarShadowProgram(LLViewerShaderMgr::SHADER_DEFERRED);//Not in mShaderList LLGLSLShader gDeferredAttachmentShadowProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredAlphaProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics +LLGLSLShader gDeferredAlphaImpostorProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredAlphaWaterProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredFullbrightProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredFullbrightAlphaMaskProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredFullbrightWaterProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredFullbrightAlphaMaskWaterProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredEmissiveProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredPostProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredCoFProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredDoFCombineProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredPostGammaCorrectProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gFXAAProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredPostNoDoFProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredWLSkyProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredWLCloudProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredStarProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredFullbrightShinyProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredSkinnedFullbrightShinyProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredSkinnedFullbrightProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gNormalMapGenProgram(LLViewerShaderMgr::SHADER_DEFERRED); +// Deferred materials shaders +LLGLSLShaderArray gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2]; +LLGLSLShaderArray gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2]; + LLViewerShaderMgr::LLViewerShaderMgr() : mVertexShaderLevel(SHADER_COUNT, 0), mMaxAvatarShaderLevel(0) @@ -343,6 +359,7 @@ void LLViewerShaderMgr::setShaders() { //using shaders, disable fixed function LLGLSLShader::sNoFixedFunction = true; + S32 light_class = 2; S32 env_class = 2; S32 obj_class = 2; @@ -352,6 +369,12 @@ void LLViewerShaderMgr::setShaders() S32 deferred_class = 0; S32 transform_class = gGLManager.mHasTransformFeedback ? 1 : 0; + static LLCachedControl use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); + if (!use_transform_feedback) + { + transform_class = 0; + } + if (LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && gSavedSettings.getBOOL("RenderDeferred") && gSavedSettings.getBOOL("RenderAvatarVP") && @@ -582,9 +605,6 @@ BOOL LLViewerShaderMgr::loadBasicShaders() // Load basic dependency shaders first // All of these have to load for any shaders to function -#if LL_DARWIN // Mac can't currently handle all 8 lights, - S32 sum_lights_class = 2; -#else S32 sum_lights_class = 3; // class one cards will get the lower sum lights @@ -595,7 +615,6 @@ BOOL LLViewerShaderMgr::loadBasicShaders() { sum_lights_class = 2; } -#endif // If we have sun and moon only checked, then only sum those lights. if (gPipeline.getLightingDetail() == 0) @@ -603,6 +622,14 @@ BOOL LLViewerShaderMgr::loadBasicShaders() sum_lights_class = 1; } +#if LL_DARWIN + // Work around driver crashes on older Macs when using deferred rendering + // NORSPEC-59 + // + if (gGLManager.mIsMobileGF) + sum_lights_class = 3; +#endif + // Use the feature table to mask out the max light level to use. Also make sure it's at least 1. S32 max_light_class = gSavedSettings.getS32("RenderShaderLightingMaxLevel"); sum_lights_class = llclamp(sum_lights_class, 1, max_light_class); @@ -1084,20 +1111,19 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader"; - gDeferredSkinnedAlphaProgram.mFeatures.atmosphericHelpers = true; gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true; - gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true; - gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true; - gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true; gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = false; gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = false; gDeferredSkinnedAlphaProgram.mFeatures.isAlphaLighting = true; gDeferredSkinnedAlphaProgram.mFeatures.disableTextureIndex = true; gDeferredSkinnedAlphaProgram.mShaderFiles.clear(); - gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; - + gDeferredSkinnedAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1"); + gDeferredSkinnedAlphaProgram.addPermutation("HAS_SKIN", "1"); + gDeferredSkinnedAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1"); + gDeferredSkinnedAlphaProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL); // Hack to include uniforms for lighting without linking in lighting file @@ -1114,7 +1140,100 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredBumpProgram.createShader(NULL, NULL); } + + gDeferredMaterialProgram[1].mFeatures.hasLighting = false; + gDeferredMaterialProgram[5].mFeatures.hasLighting = false; + gDeferredMaterialProgram[9].mFeatures.hasLighting = false; + gDeferredMaterialProgram[13].mFeatures.hasLighting = false; + gDeferredMaterialProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[1].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[5].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[9].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[13].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + + for (U32 i = 0; i < LLMaterial::SHADER_COUNT*2; ++i) + { + if (success) + { + gDeferredMaterialProgram[i].mName = llformat("Deferred Material Shader %d", i); + + U32 alpha_mode = i & 0x3; + + gDeferredMaterialProgram[i].mShaderFiles.clear(); + gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredMaterialProgram[i].mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredMaterialProgram[i].addPermutation("HAS_NORMAL_MAP", i & 0x8? "1" : "0"); + gDeferredMaterialProgram[i].addPermutation("HAS_SPECULAR_MAP", i & 0x4 ? "1" : "0"); + gDeferredMaterialProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode)); + gDeferredMaterialProgram[i].addPermutation("HAS_SUN_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); + bool has_skin = i & 0x10; + gDeferredMaterialProgram[i].addPermutation("HAS_SKIN",has_skin ? "1" : "0"); + + if (has_skin) + { + gDeferredMaterialProgram[i].mFeatures.hasObjectSkinning = true; + } + + success = gDeferredMaterialProgram[i].createShader(NULL, NULL); + } + + if (success) + { + gDeferredMaterialWaterProgram[i].mName = llformat("Deferred Underwater Material Shader %d", i); + + U32 alpha_mode = i & 0x3; + + gDeferredMaterialWaterProgram[i].mShaderFiles.clear(); + gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredMaterialWaterProgram[i].mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredMaterialWaterProgram[i].mShaderGroup = LLGLSLShader::SG_WATER; + + gDeferredMaterialWaterProgram[i].addPermutation("HAS_NORMAL_MAP", i & 0x8? "1" : "0"); + gDeferredMaterialWaterProgram[i].addPermutation("HAS_SPECULAR_MAP", i & 0x4 ? "1" : "0"); + gDeferredMaterialWaterProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode)); + gDeferredMaterialWaterProgram[i].addPermutation("HAS_SUN_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); + bool has_skin = i & 0x10; + gDeferredMaterialWaterProgram[i].addPermutation("HAS_SKIN",has_skin ? "1" : "0"); + gDeferredMaterialWaterProgram[i].addPermutation("WATER_FOG","1"); + + if (has_skin) + { + gDeferredMaterialWaterProgram[i].mFeatures.hasObjectSkinning = true; + } + + success = gDeferredMaterialWaterProgram[i].createShader(NULL, NULL);//&mWLUniforms); + } + } + + gDeferredMaterialProgram[1].mFeatures.hasLighting = true; + gDeferredMaterialProgram[5].mFeatures.hasLighting = true; + gDeferredMaterialProgram[9].mFeatures.hasLighting = true; + gDeferredMaterialProgram[13].mFeatures.hasLighting = true; + gDeferredMaterialProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + + gDeferredMaterialWaterProgram[1].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[5].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[9].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[13].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + + if (success) { gDeferredTreeProgram.mName = "Deferred Tree Shader"; @@ -1152,17 +1271,22 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredLightProgram.createShader(NULL, NULL); } + for (U32 i = 0; i < LL_DEFERRED_MULTI_LIGHT_COUNT; i++) + { if (success) { - gDeferredMultiLightProgram.mName = "Deferred MultiLight Shader"; - gDeferredMultiLightProgram.mShaderFiles.clear(); - gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredMultiLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; - success = gDeferredMultiLightProgram.createShader(NULL, NULL); + gDeferredMultiLightProgram[i].mName = llformat("Deferred MultiLight Shader %d", i); + gDeferredMultiLightProgram[i].mShaderFiles.clear(); + gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredMultiLightProgram[i].mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredMultiLightProgram[i].addPermutation("LIGHT_COUNT", llformat("%d", i+1)); + success = gDeferredMultiLightProgram[i].createShader(NULL, NULL); + } } if (success) @@ -1224,11 +1348,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredAlphaProgram.mName = "Deferred Alpha Shader"; - gDeferredAlphaProgram.mFeatures.atmosphericHelpers = true; + gDeferredAlphaProgram.mFeatures.calculatesLighting = false; - gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true; - gDeferredAlphaProgram.mFeatures.hasGamma = true; - gDeferredAlphaProgram.mFeatures.hasAtmospherics = true; gDeferredAlphaProgram.mFeatures.hasLighting = false; gDeferredAlphaProgram.mFeatures.isAlphaLighting = true; gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels @@ -1244,6 +1365,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAlphaProgram.mShaderFiles.clear(); gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAlphaProgram.addPermutation("USE_INDEXED_TEX", "1"); + gDeferredAlphaProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); + gDeferredAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1"); gDeferredAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredAlphaProgram.createShader(NULL, NULL); @@ -1253,6 +1377,86 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAlphaProgram.mFeatures.hasLighting = true; } + if (success) + { + gDeferredAlphaImpostorProgram.mName = "Deferred Alpha Shader"; + + gDeferredAlphaImpostorProgram.mFeatures.calculatesLighting = false; + gDeferredAlphaImpostorProgram.mFeatures.hasLighting = false; + gDeferredAlphaImpostorProgram.mFeatures.isAlphaLighting = true; + gDeferredAlphaImpostorProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels + if (mVertexShaderLevel[SHADER_DEFERRED] < 1) + { + gDeferredAlphaImpostorProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + } + else + { //shave off some texture units for shadow maps + gDeferredAlphaImpostorProgram.mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1); + } + + gDeferredAlphaImpostorProgram.mShaderFiles.clear(); + gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAlphaImpostorProgram.addPermutation("USE_INDEXED_TEX", "1"); + gDeferredAlphaImpostorProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); + gDeferredAlphaImpostorProgram.addPermutation("USE_VERTEX_COLOR", "1"); + gDeferredAlphaImpostorProgram.addPermutation("FOR_IMPOSTOR", "1"); + + gDeferredAlphaImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + + success = gDeferredAlphaImpostorProgram.createShader(NULL, NULL); + + // Hack + gDeferredAlphaImpostorProgram.mFeatures.calculatesLighting = true; + gDeferredAlphaImpostorProgram.mFeatures.hasLighting = true; + } + + if (success) + { + gDeferredAlphaWaterProgram.mName = "Deferred Alpha Underwater Shader"; + gDeferredAlphaWaterProgram.mFeatures.calculatesLighting = false; + gDeferredAlphaWaterProgram.mFeatures.hasLighting = false; + gDeferredAlphaWaterProgram.mFeatures.isAlphaLighting = true; + gDeferredAlphaWaterProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels + if (mVertexShaderLevel[SHADER_DEFERRED] < 1) + { + gDeferredAlphaWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + } + else + { //shave off some texture units for shadow maps + gDeferredAlphaWaterProgram.mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1); + } + gDeferredAlphaWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gDeferredAlphaWaterProgram.mShaderFiles.clear(); + gDeferredAlphaWaterProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAlphaWaterProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAlphaWaterProgram.addPermutation("USE_INDEXED_TEX", "1"); + gDeferredAlphaWaterProgram.addPermutation("WATER_FOG", "1"); + gDeferredAlphaWaterProgram.addPermutation("USE_VERTEX_COLOR", "1"); + gDeferredAlphaWaterProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); + gDeferredAlphaWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + + success = gDeferredAlphaWaterProgram.createShader(NULL, NULL); + + // Hack + gDeferredAlphaWaterProgram.mFeatures.calculatesLighting = true; + gDeferredAlphaWaterProgram.mFeatures.hasLighting = true; + } + + /*if (success) + { + gDeferredAvatarEyesProgram.mName = "Deferred Avatar Eyes Shader"; + gDeferredAvatarEyesProgram.mFeatures.calculatesAtmospherics = true; + gDeferredAvatarEyesProgram.mFeatures.hasGamma = true; + gDeferredAvatarEyesProgram.mFeatures.hasTransport = true; + gDeferredAvatarEyesProgram.mFeatures.disableTextureIndex = true; + gDeferredAvatarEyesProgram.mShaderFiles.clear(); + gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/avatarEyesV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAvatarEyesProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredAvatarEyesProgram.createShader(NULL, NULL); + }*/ + if (success) { gDeferredFullbrightProgram.mName = "Deferred Fullbright Shader"; @@ -1267,6 +1471,98 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredFullbrightProgram.createShader(NULL, NULL); } + if (success) + { + gDeferredFullbrightAlphaMaskProgram.mName = "Deferred Fullbright Alpha Masking Shader"; + gDeferredFullbrightAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gDeferredFullbrightAlphaMaskProgram.mFeatures.hasGamma = true; + gDeferredFullbrightAlphaMaskProgram.mFeatures.hasTransport = true; + gDeferredFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredFullbrightAlphaMaskProgram.mShaderFiles.clear(); + gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredFullbrightAlphaMaskProgram.addPermutation("HAS_ALPHA_MASK","1"); + gDeferredFullbrightAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredFullbrightAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredFullbrightWaterProgram.mName = "Deferred Fullbright Underwater Shader"; + gDeferredFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true; + gDeferredFullbrightWaterProgram.mFeatures.hasGamma = true; + gDeferredFullbrightWaterProgram.mFeatures.hasTransport = true; + gDeferredFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredFullbrightWaterProgram.mShaderFiles.clear(); + gDeferredFullbrightWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredFullbrightWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gDeferredFullbrightWaterProgram.addPermutation("WATER_FOG","1"); + success = gDeferredFullbrightWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredFullbrightAlphaMaskWaterProgram.mName = "Deferred Fullbright Underwater Alpha Masking Shader"; + gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.calculatesAtmospherics = true; + gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasGamma = true; + gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasTransport = true; + gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.clear(); + gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredFullbrightAlphaMaskWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredFullbrightAlphaMaskWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gDeferredFullbrightAlphaMaskWaterProgram.addPermutation("HAS_ALPHA_MASK","1"); + gDeferredFullbrightAlphaMaskWaterProgram.addPermutation("WATER_FOG","1"); + success = gDeferredFullbrightAlphaMaskWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredFullbrightShinyProgram.mName = "Deferred FullbrightShiny Shader"; + gDeferredFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true; + gDeferredFullbrightShinyProgram.mFeatures.hasGamma = true; + gDeferredFullbrightShinyProgram.mFeatures.hasTransport = true; + gDeferredFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels-1; + gDeferredFullbrightShinyProgram.mShaderFiles.clear(); + gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredFullbrightShinyProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredSkinnedFullbrightProgram.mName = "Skinned Fullbright Shader"; + gDeferredSkinnedFullbrightProgram.mFeatures.calculatesAtmospherics = true; + gDeferredSkinnedFullbrightProgram.mFeatures.hasGamma = true; + gDeferredSkinnedFullbrightProgram.mFeatures.hasTransport = true; + gDeferredSkinnedFullbrightProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedFullbrightProgram.mFeatures.disableTextureIndex = true; + gDeferredSkinnedFullbrightProgram.mShaderFiles.clear(); + gDeferredSkinnedFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gDeferredSkinnedFullbrightProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredSkinnedFullbrightShinyProgram.mName = "Skinned Fullbright Shiny Shader"; + gDeferredSkinnedFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true; + gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasGamma = true; + gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasTransport = true; + gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedFullbrightShinyProgram.mFeatures.disableTextureIndex = true; + gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.clear(); + gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gDeferredSkinnedFullbrightShinyProgram.createShader(NULL, NULL); + } + if (success) { gDeferredEmissiveProgram.mName = "Deferred Emissive Shader"; @@ -1285,9 +1581,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { // load water shader gDeferredWaterProgram.mName = "Deferred Water Shader"; - gDeferredWaterProgram.mFeatures.atmosphericHelpers = true; gDeferredWaterProgram.mFeatures.calculatesAtmospherics = true; - gDeferredWaterProgram.mFeatures.hasAtmospherics = true; gDeferredWaterProgram.mFeatures.hasGamma = true; gDeferredWaterProgram.mFeatures.hasTransport = true; gDeferredWaterProgram.mShaderFiles.clear(); @@ -1297,6 +1591,20 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredWaterProgram.createShader(NULL, NULL); } + if (success) + { + // load water shader + gDeferredUnderWaterProgram.mName = "Deferred Under Water Shader"; + gDeferredUnderWaterProgram.mFeatures.calculatesAtmospherics = true; + gDeferredUnderWaterProgram.mFeatures.hasGamma = true; + gDeferredUnderWaterProgram.mFeatures.hasTransport = true; + gDeferredUnderWaterProgram.mShaderFiles.clear(); + gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/underWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredUnderWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredUnderWaterProgram.createShader(NULL, NULL); + } + if (success) { gDeferredSoftenProgram.mName = "Deferred Soften Shader"; @@ -1314,6 +1622,25 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredSoftenProgram.createShader(NULL, NULL); } + if (success) + { + gDeferredSoftenWaterProgram.mName = "Deferred Soften Underwater Shader"; + gDeferredSoftenWaterProgram.mShaderFiles.clear(); + gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + + gDeferredSoftenWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredSoftenWaterProgram.addPermutation("WATER_FOG", "1"); + gDeferredSoftenWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + + if (gSavedSettings.getBOOL("RenderDeferredSSAO")) + { //if using SSAO, take screen space light map into account as if shadows are enabled + gDeferredSoftenWaterProgram.mShaderLevel = llmax(gDeferredSoftenWaterProgram.mShaderLevel, 2); + } + + success = gDeferredSoftenWaterProgram.createShader(NULL, NULL); + } + if (success) { gDeferredShadowProgram.mName = "Deferred Shadow Shader"; @@ -1391,18 +1718,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredAvatarAlphaProgram.mName = "Avatar Alpha Shader"; - gDeferredAvatarAlphaProgram.mFeatures.atmosphericHelpers = true; gDeferredAvatarAlphaProgram.mFeatures.hasSkinning = true; gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = false; - gDeferredAvatarAlphaProgram.mFeatures.calculatesAtmospherics = true; - gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true; - gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true; gDeferredAvatarAlphaProgram.mFeatures.hasLighting = false; gDeferredAvatarAlphaProgram.mFeatures.isAlphaLighting = true; gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true; gDeferredAvatarAlphaProgram.mShaderFiles.clear(); - gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaNoColorV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedNoColorF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAvatarAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1"); + gDeferredAvatarAlphaProgram.addPermutation("IS_AVATAR_SKIN", "1"); + gDeferredAvatarAlphaProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredAvatarAlphaProgram.createShader(NULL, NULL); @@ -1410,6 +1736,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true; gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true; } + + if (success) + { + gDeferredPostGammaCorrectProgram.mName = "Deferred Gamma Correction Post Process"; + gDeferredPostGammaCorrectProgram.mShaderFiles.clear(); + gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredPostGammaCorrectProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredPostGammaCorrectProgram.createShader(NULL, NULL); + } if (success) { @@ -1488,10 +1824,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredStarProgram.mName = "Deferred Star Program"; static std::vector shaderUniforms; - static bool bUniformsInitted = false; - if(!bUniformsInitted) + if(shaderUniforms.empty()) { - bUniformsInitted = true; shaderUniforms.push_back(LLStaticHashedString("custom_alpha")); } gDeferredStarProgram.mShaderFiles.clear(); @@ -1903,6 +2237,27 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gObjectSimpleProgram.createShader(NULL, NULL); } + if (success) + { + gObjectSimpleImpostorProgram.mName = "Simple Impostor Shader"; + gObjectSimpleImpostorProgram.mFeatures.calculatesLighting = true; + gObjectSimpleImpostorProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleImpostorProgram.mFeatures.hasGamma = true; + gObjectSimpleImpostorProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleImpostorProgram.mFeatures.hasLighting = true; + gObjectSimpleImpostorProgram.mFeatures.mIndexedTextureChannels = 0; + // force alpha mask version of lighting so we can weed out + // transparent pixels from impostor temp buffer + // + gObjectSimpleImpostorProgram.mFeatures.hasAlphaMask = true; + gObjectSimpleImpostorProgram.mShaderFiles.clear(); + gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + + success = gObjectSimpleImpostorProgram.createShader(NULL, NULL); + } + if (success) { gObjectSimpleWaterProgram.mName = "Simple Water Shader"; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index b5319ae16..8ccd77d4b 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -2,31 +2,25 @@ * @file llviewershadermgr.h * @brief Viewer Shader Manager * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -34,6 +28,9 @@ #define LL_VIEWER_SHADER_MGR_H #include "llshadermgr.h" +#include "llmaterial.h" + +#define LL_DEFERRED_MULTI_LIGHT_COUNT 16 class LLViewerShaderMgr: public LLShaderMgr { @@ -178,6 +175,14 @@ inline bool operator != (LLViewerShaderMgr::shader_iter const & a, LLViewerShade extern LLVector4 gShinyOrigin; +//For arrays, since default ctor must be used for them. +template +class LLGLSLShaderArray : public LLGLSLShader +{ +public: + LLGLSLShaderArray() : LLGLSLShader(type) {}; +}; + //transform shaders extern LLGLSLShader gTransformPositionProgram; extern LLGLSLShader gTransformTexCoordProgram; @@ -204,6 +209,7 @@ extern LLGLSLShader gOneTextureNoColorProgram; //object shaders extern LLGLSLShader gObjectSimpleProgram; +extern LLGLSLShader gObjectSimpleImpostorProgram; extern LLGLSLShader gObjectPreviewProgram; extern LLGLSLShader gObjectSimpleAlphaMaskProgram; extern LLGLSLShader gObjectSimpleWaterProgram; @@ -287,6 +293,7 @@ extern LLGLSLShader gPostGaussianBlurProgram; // Deferred rendering shaders extern LLGLSLShader gDeferredImpostorProgram; extern LLGLSLShader gDeferredWaterProgram; +extern LLGLSLShader gDeferredUnderWaterProgram; extern LLGLSLShader gDeferredDiffuseProgram; extern LLGLSLShader gDeferredDiffuseAlphaMaskProgram; extern LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram; @@ -300,13 +307,14 @@ extern LLGLSLShader gDeferredTerrainProgram; extern LLGLSLShader gDeferredTreeProgram; extern LLGLSLShader gDeferredTreeShadowProgram; extern LLGLSLShader gDeferredLightProgram; -extern LLGLSLShader gDeferredMultiLightProgram; +extern LLGLSLShaderArray gDeferredMultiLightProgram[LL_DEFERRED_MULTI_LIGHT_COUNT]; extern LLGLSLShader gDeferredSpotLightProgram; extern LLGLSLShader gDeferredMultiSpotLightProgram; extern LLGLSLShader gDeferredSunProgram; extern LLGLSLShader gDeferredBlurLightProgram; extern LLGLSLShader gDeferredAvatarProgram; extern LLGLSLShader gDeferredSoftenProgram; +extern LLGLSLShader gDeferredSoftenWaterProgram; extern LLGLSLShader gDeferredShadowProgram; extern LLGLSLShader gDeferredShadowCubeProgram; extern LLGLSLShader gDeferredShadowAlphaMaskProgram; @@ -315,15 +323,27 @@ extern LLGLSLShader gDeferredCoFProgram; extern LLGLSLShader gDeferredDoFCombineProgram; extern LLGLSLShader gFXAAProgram; extern LLGLSLShader gDeferredPostNoDoFProgram; +extern LLGLSLShader gDeferredPostGammaCorrectProgram; extern LLGLSLShader gDeferredAvatarShadowProgram; extern LLGLSLShader gDeferredAttachmentShadowProgram; extern LLGLSLShader gDeferredAlphaProgram; +extern LLGLSLShader gDeferredAlphaImpostorProgram; extern LLGLSLShader gDeferredFullbrightProgram; +extern LLGLSLShader gDeferredFullbrightAlphaMaskProgram; +extern LLGLSLShader gDeferredAlphaWaterProgram; +extern LLGLSLShader gDeferredFullbrightWaterProgram; +extern LLGLSLShader gDeferredFullbrightAlphaMaskWaterProgram; extern LLGLSLShader gDeferredEmissiveProgram; extern LLGLSLShader gDeferredAvatarAlphaProgram; extern LLGLSLShader gDeferredWLSkyProgram; extern LLGLSLShader gDeferredWLCloudProgram; extern LLGLSLShader gDeferredStarProgram; +extern LLGLSLShader gDeferredFullbrightShinyProgram; +extern LLGLSLShader gDeferredSkinnedFullbrightShinyProgram; +extern LLGLSLShader gDeferredSkinnedFullbrightProgram; extern LLGLSLShader gNormalMapGenProgram; +// Deferred materials shaders +extern LLGLSLShaderArray gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2]; +extern LLGLSLShaderArray gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2]; #endif diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index d14a47fa9..a1fbd85a3 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -55,13 +55,12 @@ #include "llappviewer.h" #include "llface.h" #include "llviewercamera.h" -//#include "lltextureatlas.h" -//#include "lltextureatlasmanager.h" #include "lltextureentry.h" #include "lltexturemanagerbridge.h" #include "llmediaentry.h" #include "llvovolume.h" #include "llviewermedia.h" +#include "lltexturecache.h" /////////////////////////////////////////////////////////////////////////////// // statics @@ -71,6 +70,7 @@ LLPointer LLViewerFetchedTexture::sMissingAssetImagep = LLPointer LLViewerFetchedTexture::sWhiteImagep = NULL; LLPointer LLViewerFetchedTexture::sDefaultImagep = NULL; LLPointer LLViewerFetchedTexture::sSmokeImagep = NULL; +LLPointer LLViewerFetchedTexture::sFlatNormalImagep = NULL; LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap ; #if 0 LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL ; @@ -408,6 +408,7 @@ void LLViewerTextureManager::cleanup() LLViewerFetchedTexture::sSmokeImagep = NULL; LLViewerFetchedTexture::sMissingAssetImagep = NULL; LLViewerFetchedTexture::sWhiteImagep = NULL; + LLViewerFetchedTexture::sFlatNormalImagep = NULL; LLViewerMediaTexture::cleanUpClass() ; } @@ -614,9 +615,14 @@ void LLViewerTexture::init(bool firstinit) mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval ; mAdditionalDecodePriority = 0.f ; mParcelMedia = NULL ; - mNumFaces = 0 ; + mNumVolumes = 0; - mFaceList.clear() ; + mFaceList[LLRender::DIFFUSE_MAP].clear() ; + mFaceList[LLRender::NORMAL_MAP].clear() ; + mFaceList[LLRender::SPECULAR_MAP].clear() ; + mNumFaces[LLRender::DIFFUSE_MAP] = + mNumFaces[LLRender::NORMAL_MAP] = + mNumFaces[LLRender::SPECULAR_MAP] = 0 ; mVolumeList.clear(); } @@ -628,7 +634,9 @@ S8 LLViewerTexture::getType() const void LLViewerTexture::cleanup() { - mFaceList.clear() ; + mFaceList[LLRender::DIFFUSE_MAP].clear() ; + mFaceList[LLRender::NORMAL_MAP].clear() ; + mFaceList[LLRender::SPECULAR_MAP].clear() ; mVolumeList.clear(); } @@ -727,38 +735,57 @@ void LLViewerTexture::setKnownDrawSize(S32 width, S32 height) } //virtual -void LLViewerTexture::addFace(LLFace* facep) +void LLViewerTexture::addFace(U32 ch, LLFace* facep) { - if(mNumFaces >= mFaceList.size()) + llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); + + if(mNumFaces[ch] >= mFaceList[ch].size()) { - mFaceList.resize(2 * mNumFaces + 1) ; + mFaceList[ch].resize(2 * mNumFaces[ch] + 1) ; } - mFaceList[mNumFaces] = facep ; - facep->setIndexInTex(mNumFaces) ; - mNumFaces++ ; + mFaceList[ch][mNumFaces[ch]] = facep ; + facep->setIndexInTex(ch, mNumFaces[ch]) ; + mNumFaces[ch]++ ; mLastFaceListUpdateTimer.reset() ; } //virtual -void LLViewerTexture::removeFace(LLFace* facep) +void LLViewerTexture::removeFace(U32 ch, LLFace* facep) { - if(mNumFaces > 1) + llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); + + if(mNumFaces[ch] > 1) { - S32 index = facep->getIndexInTex() ; - mFaceList[index] = mFaceList[--mNumFaces] ; - mFaceList[index]->setIndexInTex(index) ; + S32 index = facep->getIndexInTex(ch) ; + llassert(index < mFaceList[ch].size()); + llassert(index < mNumFaces[ch]); + mFaceList[ch][index] = mFaceList[ch][--mNumFaces[ch]] ; + mFaceList[ch][index]->setIndexInTex(ch, index) ; } else { - mFaceList.clear() ; - mNumFaces = 0 ; + mFaceList[ch].clear() ; + mNumFaces[ch] = 0 ; } mLastFaceListUpdateTimer.reset() ; } -S32 LLViewerTexture::getNumFaces() const +S32 LLViewerTexture::getTotalNumFaces() const { - return mNumFaces ; + S32 ret = 0; + + for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) + { + ret += mNumFaces[i]; + } + + return ret; +} + +S32 LLViewerTexture::getNumFaces(U32 ch) const +{ + llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); + return mNumFaces[ch]; } @@ -781,6 +808,8 @@ void LLViewerTexture::removeVolume(LLVOVolume* volumep) if(mNumVolumes > 1) { S32 index = volumep->getIndexInTex() ; + llassert(index < mVolumeList.size()); + llassert(index < mNumVolumes); mVolumeList[index] = mVolumeList[--mNumVolumes] ; mVolumeList[index]->setIndexInTex(index) ; } @@ -802,18 +831,22 @@ void LLViewerTexture::reorganizeFaceList() static const F32 MAX_WAIT_TIME = 20.f; // seconds static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ; - if(mNumFaces + MAX_EXTRA_BUFFER_SIZE > mFaceList.size()) - { - return ; - } - if(mLastFaceListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME) { - return ; + return; } + for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) + { + if(mNumFaces[i] + MAX_EXTRA_BUFFER_SIZE > mFaceList[i].size()) + { + return ; + } + + mFaceList[i].erase(mFaceList[i].begin() + mNumFaces[i], mFaceList[i].end()); + } + mLastFaceListUpdateTimer.reset() ; - mFaceList.erase(mFaceList.begin() + mNumFaces, mFaceList.end()); } void LLViewerTexture::reorganizeVolumeList() @@ -1141,12 +1174,13 @@ void LLViewerFetchedTexture::addToCreateTexture() mGLTexturep->setComponents(mComponents) ; force_update = true ; - for(U32 i = 0 ; i < mNumFaces ; i++) + for (U32 j = 0; j < LLRender::NUM_TEXTURE_CHANNELS; ++j) { - LLFace* facep = mFaceList[i]; - if(facep) + llassert(mNumFaces[j] <= mFaceList[j].size()); + + for(U32 i = 0 ; i < mNumFaces[j]; i++) { - facep->dirtyTexture() ; + mFaceList[j][i]->dirtyTexture() ; } } @@ -1595,13 +1629,30 @@ void LLViewerFetchedTexture::updateVirtualSize() addTextureStats(0.f, FALSE) ;//reset } - for(U32 i = 0 ; i < mNumFaces ; i++) - { - LLFace* facep = mFaceList[i] ; - if(facep && facep->getDrawable() && facep->getDrawable()->isRecentlyVisible()) - { - addTextureStats(facep->getVirtualSize()) ; - setAdditionalDecodePriority(facep->getImportanceToCamera()) ; + for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) + { + llassert(mNumFaces[ch] <= mFaceList[ch].size()); + + for(U32 i = 0 ; i < mNumFaces[ch]; i++) + { + LLFace* facep = mFaceList[ch][i] ; + if( facep ) + { + LLDrawable* drawable = facep->getDrawable(); + if (drawable) + { + if(drawable->isRecentlyVisible()) + { + if (getBoostLevel() == LLViewerTexture::BOOST_NONE && + drawable->getVObj() && drawable->getVObj()->isSelected()) + { + setBoostLevel(LLViewerTexture::BOOST_SELECTED); + } + addTextureStats(facep->getVirtualSize()) ; + setAdditionalDecodePriority(facep->getImportanceToCamera()) ; + } + } + } } } @@ -3197,11 +3248,14 @@ BOOL LLViewerMediaTexture::findFaces() LLViewerTexture* tex = gTextureList.findImage(mID) ; if(tex) //this media is a parcel media for tex. { - const ll_face_list_t* face_list = tex->getFaceList() ; - U32 end = tex->getNumFaces() ; - for(U32 i = 0 ; i < end ; i++) + for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) { - mMediaFaceList.push_back((*face_list)[i]) ; + const ll_face_list_t* face_list = tex->getFaceList(ch) ; + U32 end = tex->getNumFaces(ch) ; + for(U32 i = 0 ; i < end ; i++) + { + mMediaFaceList.push_back((*face_list)[i]) ; + } } } @@ -3266,7 +3320,7 @@ void LLViewerMediaTexture::addMediaToFace(LLFace* facep) return ; //no need to add the face because the media is not in playing. } - switchTexture(facep) ; + switchTexture(LLRender::DIFFUSE_MAP, facep) ; } void LLViewerMediaTexture::removeMediaFromFace(LLFace* facep) @@ -3283,19 +3337,19 @@ void LLViewerMediaTexture::removeMediaFromFace(LLFace* facep) } mIsPlaying = FALSE ; //set to remove the media from the face. - switchTexture(facep) ; + switchTexture(LLRender::DIFFUSE_MAP, facep) ; mIsPlaying = TRUE ; //set the flag back. - if(getNumFaces() < 1) //no face referencing to this media + if(getTotalNumFaces() < 1) //no face referencing to this media { stopPlaying() ; } } //virtual -void LLViewerMediaTexture::addFace(LLFace* facep) +void LLViewerMediaTexture::addFace(U32 ch, LLFace* facep) { - LLViewerTexture::addFace(facep) ; + LLViewerTexture::addFace(ch, facep) ; const LLTextureEntry* te = facep->getTextureEntry() ; if(te && te->getID().notNull()) @@ -3322,9 +3376,9 @@ void LLViewerMediaTexture::addFace(LLFace* facep) } //virtual -void LLViewerMediaTexture::removeFace(LLFace* facep) +void LLViewerMediaTexture::removeFace(U32 ch, LLFace* facep) { - LLViewerTexture::removeFace(facep) ; + LLViewerTexture::removeFace(ch, facep) ; const LLTextureEntry* te = facep->getTextureEntry() ; if(te && te->getID().notNull()) @@ -3342,24 +3396,35 @@ void LLViewerMediaTexture::removeFace(LLFace* facep) } } - // - //we have some trouble here: the texture of the face is changed. - //we need to find the former texture, and remove it from the list to avoid memory leaking. - if(!mNumFaces) + std::vector te_list; + + for (U32 ch = 0; ch < 3; ++ch) + { + // + //we have some trouble here: the texture of the face is changed. + //we need to find the former texture, and remove it from the list to avoid memory leaking. + + llassert(mNumFaces[ch] <= mFaceList[ch].size()); + + for(U32 j = 0 ; j < mNumFaces[ch] ; j++) + { + te_list.push_back(mFaceList[ch][j]->getTextureEntry());//all textures are in use. + } + } + + if (te_list.empty()) { mTextureList.clear() ; return ; } - S32 end = getNumFaces() ; - std::vector te_list(end) ; - S32 i = 0 ; - for(U32 j = 0 ; j < mNumFaces ; j++) - { - te_list[i++] = mFaceList[j]->getTextureEntry() ;//all textures are in use. - } + + S32 end = te_list.size(); + for(std::list< LLPointer >::iterator iter = mTextureList.begin(); iter != mTextureList.end(); ++iter) { + S32 i = 0; + for(i = 0 ; i < end ; i++) { if(te_list[i] && te_list[i]->getID() == (*iter)->getID())//the texture is in use. @@ -3404,7 +3469,7 @@ void LLViewerMediaTexture::stopPlaying() mIsPlaying = FALSE ; } -void LLViewerMediaTexture::switchTexture(LLFace* facep) +void LLViewerMediaTexture::switchTexture(U32 ch, LLFace* facep) { if(facep) { @@ -3420,7 +3485,7 @@ void LLViewerMediaTexture::switchTexture(LLFace* facep) if(mIsPlaying) //old textures switch to the media texture { - facep->switchTexture(this) ; + facep->switchTexture(ch, this) ; } else //switch to old textures. { @@ -3436,7 +3501,7 @@ void LLViewerMediaTexture::switchTexture(LLFace* facep) { tex = LLViewerFetchedTexture::sDefaultImagep ; } - facep->switchTexture(tex) ; + facep->switchTexture(ch, tex) ; } } } @@ -3475,14 +3540,17 @@ void LLViewerMediaTexture::setPlaying(BOOL playing) for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) { - switchTexture(*iter) ; + switchTexture(LLRender::DIFFUSE_MAP, *iter) ; } } else //stop playing this media { - for(U32 i = mNumFaces ; i ; i--) + U32 ch = LLRender::DIFFUSE_MAP; + + llassert(mNumFaces[ch] <= mFaceList[ch].size()); + for(U32 i = mNumFaces[ch] ; i ; i--) { - switchTexture(mFaceList[i - 1]) ; //current face could be removed in this function. + switchTexture(ch, mFaceList[ch][i - 1]) ; //current face could be removed in this function. } } return ; @@ -3504,14 +3572,18 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() if(mIsPlaying) //media is playing { - for(U32 i = 0 ; i < mNumFaces ; i++) + for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) { - LLFace* facep = mFaceList[i] ; - if(facep->getDrawable()->isRecentlyVisible()) + llassert(mNumFaces[ch] <= mFaceList[ch].size()); + for(U32 i = 0 ; i < mNumFaces[ch] ; i++) { - addTextureStats(facep->getVirtualSize()) ; - } - } + LLFace* facep = mFaceList[ch][i] ; + if(facep->getDrawable()->isRecentlyVisible()) + { + addTextureStats(facep->getVirtualSize()) ; + } + } + } } else //media is not in playing { diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index b378f578d..94eeaf19e 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -36,6 +36,7 @@ #if 0 #include "llmetricperformancetester.h" #endif +#include "llface.h" #include #include @@ -43,7 +44,6 @@ #define MIN_VIDEO_RAM_IN_MEGA_BYTES 32 #define MAX_VIDEO_RAM_IN_MEGA_BYTES 512 // 512MB max for performance reasons. -class LLFace; class LLImageGL ; class LLImageRaw; class LLViewerObject; @@ -59,6 +59,7 @@ class LLVFile; class LLMessageSystem; class LLViewerMediaImpl ; class LLVOVolume ; +class LLFace ; //But llface.h is already included...(?) class LLLoadedCallbackEntry { @@ -147,10 +148,11 @@ public: /*virtual*/ void setKnownDrawSize(S32 width, S32 height); - virtual void addFace(LLFace* facep) ; - virtual void removeFace(LLFace* facep) ; - S32 getNumFaces() const; - const ll_face_list_t* getFaceList() const {return &mFaceList;} + virtual void addFace(U32 channel, LLFace* facep) ; + virtual void removeFace(U32 channel, LLFace* facep) ; + S32 getTotalNumFaces() const; + S32 getNumFaces(U32 ch) const; + const ll_face_list_t* getFaceList(U32 channel) const {llassert(channel < LLRender::NUM_TEXTURE_CHANNELS); return &mFaceList[channel];} virtual void addVolume(LLVOVolume* volumep); virtual void removeVolume(LLVOVolume* volumep); @@ -188,8 +190,8 @@ protected: mutable F32 mAdditionalDecodePriority; // priority add to mDecodePriority. LLFrameTimer mLastReferencedTimer; - ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture - U32 mNumFaces ; + ll_face_list_t mFaceList[LLRender::NUM_TEXTURE_CHANNELS]; //reverse pointer pointing to the faces using this image as texture + U32 mNumFaces[LLRender::NUM_TEXTURE_CHANNELS]; LLFrameTimer mLastFaceListUpdateTimer ; ll_volume_list_t mVolumeList; @@ -483,6 +485,7 @@ public: static LLPointer sWhiteImagep; // Texture to show NOTHING (whiteness) static LLPointer sDefaultImagep; // "Default" texture for error cases, the only case of fetched texture which is generated in local. static LLPointer sSmokeImagep; // Old "Default" translucent texture + static LLPointer sFlatNormalImagep; // Flat normal map denoting no bumpiness on a surface }; // @@ -540,12 +543,12 @@ public: void addMediaToFace(LLFace* facep) ; void removeMediaFromFace(LLFace* facep) ; - /*virtual*/ void addFace(LLFace* facep) ; - /*virtual*/ void removeFace(LLFace* facep) ; + /*virtual*/ void addFace(U32 ch, LLFace* facep) ; + /*virtual*/ void removeFace(U32 ch, LLFace* facep) ; /*virtual*/ F32 getMaxVirtualSize() ; private: - void switchTexture(LLFace* facep) ; + void switchTexture(U32 ch, LLFace* facep) ; BOOL findFaces() ; void stopPlaying() ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 17f4343f4..e86dbfd21 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -126,6 +126,7 @@ void LLViewerTextureList::doPreloadImages() LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); LLUIImageList* image_list = LLUIImageList::getInstance(); + LLViewerFetchedTexture::sFlatNormalImagep = LLViewerTextureManager::getFetchedTextureFromFile("flatnormal.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_BUMP); image_list->initFromFile(); // turn off clamping and bilinear filtering for uv picking images diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp index 59f1b959a..0947e6025 100644 --- a/indra/newview/llvoclouds.cpp +++ b/indra/newview/llvoclouds.cpp @@ -208,6 +208,7 @@ void LLVOClouds::getGeometry(S32 idx, LLStrider& normalsp, LLStrider& texcoordsp, LLStrider& colorsp, + LLStrider& emissivep, LLStrider& indicesp) { diff --git a/indra/newview/llvoclouds.h b/indra/newview/llvoclouds.h index 089f3efc1..95e9dc331 100644 --- a/indra/newview/llvoclouds.h +++ b/indra/newview/llvoclouds.h @@ -60,6 +60,7 @@ public: LLStrider& normalsp, LLStrider& texcoordsp, LLStrider& colorsp, + LLStrider& emissivep, LLStrider& indicesp); /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 769f75978..f45fc6de2 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -500,6 +500,7 @@ void LLVOGrass::getGeometry(S32 idx, LLStrider& normalsp, LLStrider& texcoordsp, LLStrider& colorsp, + LLStrider& emissivep, LLStrider& indicesp) { if(!mNumBlades)//stop rendering grass @@ -733,7 +734,11 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group) facep->setIndicesIndex(index_count); facep->setVertexBuffer(buffer); facep->setPoolType(LLDrawPool::POOL_ALPHA); - object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + + //dummy parameter (unused by this implementation) + LLStrider emissivep; + + object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, emissivep, indicesp); vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h index 941e075bf..7f9b9bee8 100644 --- a/indra/newview/llvograss.h +++ b/indra/newview/llvograss.h @@ -69,6 +69,7 @@ public: LLStrider& normalsp, LLStrider& texcoordsp, LLStrider& colorsp, + LLStrider& emissivep, LLStrider& indicesp); void updateFaceSize(S32 idx) { } diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index f16436493..d9d3f2e18 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -55,23 +55,26 @@ const F32 MAX_PART_LIFETIME = 120.f; extern U64 gFrameTime; LLPointer LLVOPartGroup::sVB = NULL; -S32 LLVOPartGroup::sVBSlotFree[]; -S32* LLVOPartGroup::sVBSlotCursor = NULL; +/*S32 LLVOPartGroup::sVBSlotFree[]; +S32* LLVOPartGroup::sVBSlotCursor = NULL;*/ +S32 LLVOPartGroup::sVBSlotCursor = 0; void LLVOPartGroup::initClass() { - for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) + /*for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) { sVBSlotFree[i] = i; } - sVBSlotCursor = sVBSlotFree; + sVBSlotCursor = sVBSlotFree;*/ } //static void LLVOPartGroup::restoreGL() { - sVB = new LLVertexBuffer(VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + + //TODO: optimize out binormal mask here. Specular and normal coords as well. + sVB = new LLVertexBuffer(VERTEX_DATA_MASK | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, GL_STREAM_DRAW_ARB); U32 count = LL_MAX_PARTICLE_COUNT; sVB->allocateBuffer(count*4, count*6, true); @@ -128,20 +131,22 @@ void LLVOPartGroup::destroyGL() //static S32 LLVOPartGroup::findAvailableVBSlot() { - if (sVBSlotCursor >= sVBSlotFree+LL_MAX_PARTICLE_COUNT) + if (sVBSlotCursor >= /*sVBSlotFree+*/LL_MAX_PARTICLE_COUNT) { //no more available slots return -1; } - S32 ret = *sVBSlotCursor; + /*S32 ret = *sVBSlotCursor; sVBSlotCursor++; - return ret; + return ret;*/ + + return sVBSlotCursor++; } bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end) { - while (start < end) + /*while (start < end) { if (*start == idx) { //not allocated (in free list) @@ -151,13 +156,14 @@ bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end) } //allocated (not in free list) - return true; + return true;*/ + return false; } //static void LLVOPartGroup::freeVBSlot(S32 idx) { - llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); + /*llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); llassert(sVBSlotCursor > sVBSlotFree); llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT)); @@ -165,7 +171,7 @@ void LLVOPartGroup::freeVBSlot(S32 idx) { sVBSlotCursor--; *sVBSlotCursor = idx; - } + }*/ } LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) @@ -189,17 +195,28 @@ BOOL LLVOPartGroup::isActive() const F32 LLVOPartGroup::getBinRadius() { - return mScale.mV[0]*2.f; + return mViewerPartGroupp->getBoxSide(); } void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) { const LLVector3& pos_agent = getPositionAgent(); - newMin.load3( (pos_agent - mScale).mV); - newMax.load3( (pos_agent + mScale).mV); - LLVector4a pos; - pos.load3(pos_agent.mV); - mDrawable->setPositionGroup(pos); + + LLVector4a scale; + LLVector4a p; + + p.load3(pos_agent.mV); + + scale.splat(mScale.mV[0]+mViewerPartGroupp->getBoxSide()*0.5f); + + newMin.setSub(p, scale); + newMax.setAdd(p,scale); + + llassert(newMin.isFinite3()); + llassert(newMax.isFinite3()); + + llassert(p.isFinite3()); + mDrawable->setPositionGroup(p); } void LLVOPartGroup::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) @@ -238,6 +255,37 @@ LLDrawable* LLVOPartGroup::createDrawable(LLPipeline *pipeline) const F32 MAX_PARTICLE_AREA_SCALE = 0.02f; // some tuned constant, limits on how much particle area to draw + LLUUID LLVOPartGroup::getPartOwner(S32 idx) + { + LLUUID ret = LLUUID::null; + + if (idx < (S32) mViewerPartGroupp->mParticles.size()) + { + ret = mViewerPartGroupp->mParticles[idx]->mPartSourcep->getOwnerUUID(); + } + + return ret; + } + + LLUUID LLVOPartGroup::getPartSource(S32 idx) + { + LLUUID ret = LLUUID::null; + + if (idx < (S32) mViewerPartGroupp->mParticles.size()) + { + LLViewerPart* part = mViewerPartGroupp->mParticles[idx]; + if (part && part->mPartSourcep.notNull() && + part->mPartSourcep->mSourceObjectp.notNull()) + { + LLViewerObject* source = part->mPartSourcep->mSourceObjectp; + ret = source->getID(); + } + } + + return ret; + } + + F32 LLVOPartGroup::getPartSize(S32 idx) { if (idx < (S32) mViewerPartGroupp->mParticles.size()) @@ -248,6 +296,16 @@ F32 LLVOPartGroup::getPartSize(S32 idx) return 0.f; } +void LLVOPartGroup::getBlendFunc(S32 idx, U32& src, U32& dst) +{ + if (idx < (S32) mViewerPartGroupp->mParticles.size()) + { + LLViewerPart* part = mViewerPartGroupp->mParticles[idx]; + src = part->mBlendFuncSource; + dst = part->mBlendFuncDest; + } +} + LLVector3 LLVOPartGroup::getCameraPosition() const { return gAgentCamera.getCameraPositionAgent(); @@ -307,19 +365,52 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) mDepth = 0.f; S32 i = 0 ; LLVector3 camera_agent = getCameraPosition(); + + F32 max_scale = 0.f; + + for (i = 0 ; i < (S32)mViewerPartGroupp->mParticles.size(); i++) { const LLViewerPart *part = mViewerPartGroupp->mParticles[i]; + + //remember the largest particle + max_scale = llmax(max_scale, part->mScale.mV[0], part->mScale.mV[1]); + + if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK) + { //include ribbon segment length in scale + const LLVector3* pos_agent = NULL; + if (part->mParent) + { + pos_agent = &(part->mParent->mPosAgent); + } + else if (part->mPartSourcep.notNull()) + { + pos_agent = &(part->mPartSourcep->mPosAgent); + } + + if (pos_agent) + { + F32 dist = (*pos_agent-part->mPosAgent).length(); + + max_scale = llmax(max_scale, dist); + } + } + LLVector3 part_pos_agent(part->mPosAgent); LLVector3 at(part_pos_agent - camera_agent); + F32 camera_dist_squared = at.lengthSquared(); F32 inv_camera_dist_squared; if (camera_dist_squared > 1.f) inv_camera_dist_squared = 1.f / camera_dist_squared; else inv_camera_dist_squared = 1.f; + + llassert(llfinite(inv_camera_dist_squared)); + llassert(!llisnan(inv_camera_dist_squared)); + F32 area = part->mScale.mV[0] * part->mScale.mV[1] * inv_camera_dist_squared; tot_area = llmax(tot_area, area); @@ -386,28 +477,129 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) facep->setSize(0, 0); } + //record max scale (used to stretch bounding box for visibility culling) + + mScale.set(max_scale, max_scale, max_scale); + mDrawable->movePartition(); LLPipeline::sCompiles++; return TRUE; } -void LLVOPartGroup::getGeometry(S32 idx, - LLStrider& verticesp, - LLStrider& normalsp, - LLStrider& texcoordsp, - LLStrider& colorsp, - LLStrider& indicesp) + +BOOL LLVOPartGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + S32 face, + BOOL pick_transparent, + S32* face_hit, + LLVector4a* intersection, + LLVector2* tex_coord, + LLVector4a* normal, + LLVector4a* bi_normal) { - if (idx >= (S32) mViewerPartGroupp->mParticles.size()) + LLVector4a dir; + dir.setSub(end, start); + + F32 closest_t = 2.f; + BOOL ret = FALSE; + + for (U32 idx = 0; idx < mViewerPartGroupp->mParticles.size(); ++idx) { - return; + const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx])); + + LLVector4a v[4]; + LLStrider verticesp; + verticesp = v; + + getGeometry(part, verticesp); + + F32 a,b,t; + if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a,b,t) || + LLTriangleRayIntersect(v[1], v[3], v[2], start, dir, a,b,t)) + { + if (t >= 0.f && + t <= 1.f && + t < closest_t) + { + ret = TRUE; + closest_t = t; + if (face_hit) + { + *face_hit = idx; + } + + if (intersection) + { + LLVector4a intersect = dir; + intersect.mul(closest_t); + intersection->setAdd(intersect, start); + } + } + } } - const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx])); + return ret; +} - LLVector4a part_pos_agent; - part_pos_agent.load3(part.mPosAgent.mV); - LLVector4a camera_agent; +void LLVOPartGroup::getGeometry(const LLViewerPart& part, + LLStrider& verticesp) +{ + if (part.mFlags & LLPartData::LL_PART_RIBBON_MASK) + { + LLVector4a axis, pos, paxis, ppos; + F32 scale, pscale; + + pos.load3(part.mPosAgent.mV); + axis.load3(part.mAxis.mV); + scale = part.mScale.mV[0]; + + if (part.mParent) + { + ppos.load3(part.mParent->mPosAgent.mV); + paxis.load3(part.mParent->mAxis.mV); + pscale = part.mParent->mScale.mV[0]; + } + else + { //use source object as position + + if (part.mPartSourcep->mSourceObjectp.notNull()) + { + LLVector3 v = LLVector3(0,0,1); + v *= part.mPartSourcep->mSourceObjectp->getRenderRotation(); + paxis.load3(v.mV); + ppos.load3(part.mPartSourcep->mPosAgent.mV); + pscale = part.mStartScale.mV[0]; + } + else + { //no source object, no parent, nothing to draw + ppos = pos; + pscale = scale; + paxis = axis; + } + } + + LLVector4a p0, p1, p2, p3; + + scale *= 0.5f; + pscale *= 0.5f; + + axis.mul(scale); + paxis.mul(pscale); + + p0.setAdd(pos, axis); + p1.setSub(pos,axis); + p2.setAdd(ppos, paxis); + p3.setSub(ppos, paxis); + + (*verticesp++) = p2; + (*verticesp++) = p3; + (*verticesp++) = p0; + (*verticesp++) = p1; + } + else + { + LLVector4a part_pos_agent; + part_pos_agent.load3(part.mPosAgent.mV); + LLVector4a camera_agent; camera_agent.load3(getCameraPosition().mV); LLVector4a at; at.setSub(part_pos_agent, camera_agent); @@ -451,45 +643,97 @@ void LLVOPartGroup::getGeometry(S32 idx, right.normalize3fast(); } - right.mul(0.5f*part.mScale.mV[0]); - up.mul(0.5f*part.mScale.mV[1]); + right.mul(0.5f*part.mScale.mV[0]); + up.mul(0.5f*part.mScale.mV[1]); - LLVector3 normal = -LLViewerCamera::getInstance()->getXAxis(); + //HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should) + // this works because there is actually a 4th float stored after the vertex position which is used as a texture index + // also, somebody please VECTORIZE THIS - //HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should) - // this works because there is actually a 4th float stored after the vertex position which is used as a texture index - // also, somebody please VECTORIZE THIS + LLVector4a ppapu; + LLVector4a ppamu; - LLVector4a ppapu; - LLVector4a ppamu; + ppapu.setAdd(part_pos_agent, up); + ppamu.setSub(part_pos_agent, up); - ppapu.setAdd(part_pos_agent, up); - ppamu.setSub(part_pos_agent, up); + verticesp->setSub(ppapu, right); + (*verticesp++).getF32ptr()[3] = 0.f; + verticesp->setSub(ppamu, right); + (*verticesp++).getF32ptr()[3] = 0.f; + verticesp->setAdd(ppapu, right); + (*verticesp++).getF32ptr()[3] = 0.f; + verticesp->setAdd(ppamu, right); + (*verticesp++).getF32ptr()[3] = 0.f; + } +} - verticesp->setSub(ppapu, right); - (*verticesp++).getF32ptr()[3] = 0.f; - verticesp->setSub(ppamu, right); - (*verticesp++).getF32ptr()[3] = 0.f; - verticesp->setAdd(ppapu, right); - (*verticesp++).getF32ptr()[3] = 0.f; - verticesp->setAdd(ppamu, right); - (*verticesp++).getF32ptr()[3] = 0.f; - *colorsp++ = part.mColor; - *colorsp++ = part.mColor; - *colorsp++ = part.mColor; - *colorsp++ = part.mColor; + +void LLVOPartGroup::getGeometry(S32 idx, + LLStrider& verticesp, + LLStrider& normalsp, + LLStrider& texcoordsp, + LLStrider& colorsp, + LLStrider& emissivep, + LLStrider& indicesp) +{ + if (idx >= (S32) mViewerPartGroupp->mParticles.size()) + { + return; + } + + const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx])); + + getGeometry(part, verticesp); + + LLColor4U pcolor; + LLColor4U color = part.mColor; + + LLColor4U pglow; + + if (part.mFlags & LLPartData::LL_PART_RIBBON_MASK) + { //make sure color blends properly + if (part.mParent) + { + pglow = part.mParent->mGlow; + pcolor = part.mParent->mColor; + } + else + { + pglow = LLColor4U(0, 0, 0, (U8) llround(255.f*part.mStartGlow)); + pcolor = part.mStartColor; + } + } + else + { + pglow = part.mGlow; + pcolor = color; + } + + *colorsp++ = pcolor; + *colorsp++ = pcolor; + *colorsp++ = color; + *colorsp++ = color; + + //if (pglow.mV[3] || part.mGlow.mV[3]) + { //only write glow if it is not zero + *emissivep++ = pglow; + *emissivep++ = pglow; + *emissivep++ = part.mGlow; + *emissivep++ = part.mGlow; + } + if (!(part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK)) { //not fullbright, needs normal + LLVector3 normal = -LLViewerCamera::getInstance()->getXAxis(); *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; } } - U32 LLVOPartGroup::getPartitionType() const { return LLViewerRegion::PARTITION_PARTICLE; @@ -622,10 +866,13 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) LLStrider normalsp; LLStrider texcoordsp; LLStrider colorsp; + LLStrider emissivep; buffer->getVertexStrider(verticesp); buffer->getNormalStrider(normalsp); buffer->getColorStrider(colorsp); + buffer->getEmissiveStrider(emissivep); + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; @@ -634,7 +881,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) LLFace* facep = *i; LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); - if (!facep->isState(LLFace::PARTICLE)) + //if (!facep->isState(LLFace::PARTICLE)) { //set the indices of this face S32 idx = LLVOPartGroup::findAvailableVBSlot(); if (idx >= 0) @@ -643,7 +890,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) facep->setIndicesIndex(idx*6); facep->setVertexBuffer(LLVOPartGroup::sVB); facep->setPoolType(LLDrawPool::POOL_ALPHA); - facep->setState(LLFace::PARTICLE); + //facep->setState(LLFace::PARTICLE); } else { @@ -658,9 +905,19 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) LLStrider cur_norm = normalsp + geom_idx; LLStrider cur_tc = texcoordsp + geom_idx; LLStrider cur_col = colorsp + geom_idx; + LLStrider cur_glow = emissivep + geom_idx; - object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_idx); + LLColor4U* start_glow = cur_glow.get(); + + object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_glow, cur_idx); + BOOL has_glow = FALSE; + + if (cur_glow.get() != start_glow) + { + has_glow = TRUE; + } + llassert(facep->getGeomCount() == 4); llassert(facep->getIndicesCount() == 6); @@ -675,24 +932,37 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) bool batched = false; - if (idx >= 0 && - draw_vec[idx]->mTexture == facep->getTexture() && - draw_vec[idx]->mFullbright == fullbright) + U32 bf_src = LLRender::BF_SOURCE_ALPHA; + U32 bf_dst = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; + + object->getBlendFunc(facep->getTEOffset(), bf_src, bf_dst); + + + if (idx >= 0) { - if (draw_vec[idx]->mEnd == facep->getGeomIndex()-1) + LLDrawInfo* info = draw_vec[idx]; + + if (info->mTexture == facep->getTexture() && + info->mHasGlow == has_glow && + info->mFullbright == fullbright && + info->mBlendFuncDst == bf_dst && + info->mBlendFuncSrc == bf_src) { - batched = true; - draw_vec[idx]->mCount += facep->getIndicesCount(); - draw_vec[idx]->mEnd += facep->getGeomCount(); - draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); - } - else if (draw_vec[idx]->mStart == facep->getGeomIndex()+facep->getGeomCount()+1) - { - batched = true; - draw_vec[idx]->mCount += facep->getIndicesCount(); - draw_vec[idx]->mStart -= facep->getGeomCount(); - draw_vec[idx]->mOffset = facep->getIndicesStart(); - draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + if (draw_vec[idx]->mEnd == facep->getGeomIndex()-1) + { + batched = true; + info->mCount += facep->getIndicesCount(); + info->mEnd += facep->getGeomCount(); + info->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } + else if (draw_vec[idx]->mStart == facep->getGeomIndex()+facep->getGeomCount()+1) + { + batched = true; + info->mCount += facep->getIndicesCount(); + info->mStart -= facep->getGeomCount(); + info->mOffset = facep->getIndicesStart(); + info->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } } } @@ -709,6 +979,10 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) info->mExtents[0] = group->mObjectExtents[0]; info->mExtents[1] = group->mObjectExtents[1]; info->mVSize = vsize; + info->mBlendFuncDst = bf_dst; + info->mBlendFuncSrc = bf_src; + info->mHasGlow = has_glow; + info->mParticle = TRUE; draw_vec.push_back(info); //for alpha sorting facep->setDrawInfo(info); diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index ecf149c67..7e3e220a7 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -48,8 +48,9 @@ public: //vertex buffer for holding all particles static LLPointer sVB; - static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT]; - static S32* sVBSlotCursor; + /*static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT]; + static S32* sVBSlotCursor;*/ + static S32 sVBSlotCursor; static void initClass(); static void restoreGL(); @@ -63,6 +64,7 @@ public: LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_EMISSIVE | LLVertexBuffer::MAP_TEXTURE_INDEX }; @@ -75,20 +77,37 @@ public: virtual void updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); virtual U32 getPartitionType() const; + /*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + S32 face, + BOOL pick_transparent, + S32* face_hit, + LLVector4a* intersection, + LLVector2* tex_coord, + LLVector4a* normal, + LLVector4a* tangent); + /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); /*virtual*/ void updateTextures(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); + void getGeometry(const LLViewerPart& part, + LLStrider& verticesp); + void getGeometry(S32 idx, LLStrider& verticesp, LLStrider& normalsp, LLStrider& texcoordsp, LLStrider& colorsp, + LLStrider& emissivep, LLStrider& indicesp); void updateFaceSize(S32 idx) { } F32 getPartSize(S32 idx); + void getBlendFunc(S32 idx, U32& src, U32& dst); + LLUUID getPartOwner(S32 idx); + LLUUID getPartSource(S32 idx); + void setViewerPartGroup(LLViewerPartGroup *part_groupp) { mViewerPartGroupp = part_groupp; } LLViewerPartGroup* getViewerPartGroup() { return mViewerPartGroupp; } diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index ea222c34d..2c3e6fbf9 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -299,7 +299,7 @@ void LLSkyTex::create(const F32 brightness) void LLSkyTex::createGLImage(S32 which) { mTexture[which]->setNeedsAlphaAndPickMask(false); //Needed, else analyzeAlpha is called every frame for each texture. - mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLViewerTexture::LOCAL); + mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLGLTexture::LOCAL); mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP); } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 97802746e..0bc4f4b91 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -340,15 +340,9 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, if (!mTextureAnimp) { mTextureAnimp = new LLViewerTextureAnim(this); + mTexAnimMode = 0; } - else - { - if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) - { - mTextureAnimp->reset(); - } - } - mTexAnimMode = 0; + mTextureAnimp->unpackTAMessage(mesgsys, block_num); } else @@ -461,6 +455,11 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, mFaceMappingChanged = TRUE; mTexAnimMode = 0; } + + if (value & 0x400) + { //particle system (new) + unpackParticleSource(*dp, mOwnerID, false); + } } else { @@ -905,6 +904,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); } @@ -1120,7 +1125,13 @@ void LLVOVolume::sculpt() S32 max_discard = mSculptTexture->getMaxDiscardLevel(); if (discard_level > max_discard) - discard_level = max_discard; // clamp to the best we can do + { + discard_level = max_discard; // clamp to the best we can do + } + if(discard_level > MAX_DISCARD_LEVEL) + { + return; //we think data is not ready yet. + } S32 current_discard = getVolume()->getSculptLevel() ; if(current_discard < -2) @@ -1383,6 +1394,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. @@ -1432,7 +1448,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) continue; } res &= face->genVolumeBBoxes(*volume, i, - mRelativeXform, mRelativeXformInvTrans, + mRelativeXform, (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); if (rebuild) @@ -1725,6 +1741,11 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) void LLVOVolume::updateFaceSize(S32 idx) { + if( mDrawable->getNumFaces() <= idx ) + { + return; + } + LLFace* facep = mDrawable->getFace(idx); if (facep) { @@ -2565,6 +2586,7 @@ void LLVOVolume::setLightTextureID(LLUUID id) if (hasLightTexture()) { setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); mLightTexture = NULL; } } @@ -2582,7 +2604,8 @@ void LLVOVolume::setSpotLightParams(LLVector3 params) void LLVOVolume::setIsLight(BOOL is_light) { - if (is_light != getIsLight()) + BOOL was_light = getIsLight(); + if (is_light != was_light) { if (is_light) { @@ -2767,7 +2790,7 @@ void LLVOVolume::updateSpotLightPriority() bool LLVOVolume::isLightSpotlight() const { LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (params) + if (params && getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) { return params->isLightSpotlight(); } @@ -3705,8 +3728,30 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& { LLFace* face = mDrawable->getFace(face_hit); + bool ignore_alpha = false; + + const LLTextureEntry* te = face->getTextureEntry(); + if (te) + { + LLMaterial* mat = te->getMaterialParams(); + if (mat) + { + U8 mode = mat->getDiffuseAlphaMode(); + + if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE || + mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE) + { + ignore_alpha = true; + } + } + } + if (face && - (pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))) + (ignore_alpha || + pick_transparent || + !face->getTexture() || + !face->getTexture()->hasGLTexture() || + face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))) { local_end = p; if (face_hitp != NULL) @@ -4025,6 +4070,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; @@ -4043,6 +4093,10 @@ 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() && gHideSelectedObjects) // [RLVa:KB] - Checked: 2010-11-29 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c @@ -4099,18 +4153,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()) { @@ -4136,10 +4211,14 @@ 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(); @@ -4167,6 +4246,60 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, 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); @@ -4284,12 +4417,18 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) static LLFace** fullbright_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); static LLFace** bump_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); static LLFace** simple_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); + static LLFace** norm_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*), 64); + static LLFace** spec_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*), 64); + static LLFace** normspec_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*), 64); static LLFace** alpha_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); U32 fullbright_count = 0; U32 bump_count = 0; U32 simple_count = 0; U32 alpha_count = 0; + U32 norm_count = 0; + U32 spec_count = 0; + U32 normspec_count = 0; U32 useage = group->mSpatialPartition->mBufferUsage; @@ -4465,7 +4604,26 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) LLMaterial* mat = te->getMaterialParams().get(); - if (mat) + 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 (mat) { bool fullbright = te->getFullbright(); bool is_alpha = type == LLDrawPool::POOL_ALPHA; @@ -4473,7 +4631,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; - bool is_deferred_simple = LLPipeline::sRenderDeferred && !fullbright; if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && te->getColor().mV[3] >= 0.999f) { pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); @@ -4484,21 +4641,18 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA); } - is_deferred_simple = false; } else if (gPipeline.canUseVertexShaders() && LLPipeline::sRenderBump && te->getShiny() && can_be_shiny) { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : !LLPipeline::sRenderDeferred ? LLDrawPoolAvatar::RIGGED_SHINY : LLDrawPoolAvatar::RIGGED_SIMPLE); + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : LLDrawPoolAvatar::RIGGED_SHINY); } else { pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); } - if(is_deferred_simple) - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); } else { @@ -4674,7 +4828,42 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (gPipeline.canUseWindLightShadersOnObjects() && LLPipeline::sRenderBump) { - if (te->getBumpmap()) + 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) + if (normspec_count < MAX_FACE_COUNT) + { + normspec_faces[normspec_count++] = facep; + } + } + else + { //has normal map (needs texcoord1 and tangent) + if (norm_count < MAX_FACE_COUNT) + { + norm_faces[norm_count++] = facep; + } + } + } + else if (mat->getSpecularID().notNull()) + { //has specular map but no normal map, needs texcoord2 + if (spec_count < MAX_FACE_COUNT) + { + spec_faces[spec_count++] = facep; + } + } + else + { //has neither specular map nor normal map, only needs texcoord0 + if (simple_count < MAX_FACE_COUNT) + { + simple_faces[simple_count++] = facep; + } + } + } + else if (te->getBumpmap()) { //needs normal + tangent if (bump_count < MAX_FACE_COUNT) { @@ -4757,32 +4946,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_TANGENT; - genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, simple_count, FALSE, TRUE); - genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, fullbright_count, FALSE, TRUE); - genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, bump_count, FALSE, TRUE); - genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, alpha_count, 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, simple_count); - genDrawInfo(group, fullbright_mask, fullbright_faces, fullbright_count); - genDrawInfo(group, bump_mask, bump_faces, bump_count, FALSE, TRUE); - genDrawInfo(group, alpha_mask, alpha_faces, alpha_count, TRUE); - } - + + genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, simple_count, FALSE, batch_textures, FALSE); + genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, fullbright_count, FALSE, batch_textures); + genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, alpha_count, TRUE, batch_textures); + genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, bump_count, FALSE, FALSE); + genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, norm_faces, norm_count, FALSE, FALSE); + genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, spec_faces, spec_count, FALSE, FALSE); + genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, normspec_faces, normspec_count, FALSE, FALSE); if (!LLPipeline::sDelayVBUpdate) { @@ -4945,11 +5140,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(); } - } }; @@ -5033,11 +5235,14 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac //NEVER use more than 16 texture index channels (workaround for prevalent driver bug) texture_index_channels = llmin(texture_index_channels, 16); + bool flexi = false; + while (face_iter != end_faces) { //pull off next face LLFace* facep = *face_iter; LLViewerTexture* tex = facep->getTexture(); + LLMaterialPtr mat = facep->getTextureEntry()->getMaterialParams(); if (distance_sort) { @@ -5059,6 +5264,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac U32 index_count = facep->getIndicesCount(); U32 geom_count = facep->getGeomCount(); + flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); //sum up vertices needed for this render batch LLFace** i = face_iter; @@ -5089,6 +5295,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac 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; } if (facep->getTexture() != tex) @@ -5135,6 +5342,9 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac } ++i; + + flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); + index_count += facep->getIndicesCount(); geom_count += facep->getGeomCount(); @@ -5142,11 +5352,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac } tex = texture_list[0]; } + else + { + facep->setTextureIndex(0); + } } else { while (i != end_faces && - (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) + (LLPipeline::sTextureBindTest || + (distance_sort || + ((*i)->getTexture() == tex && + ((*i)->getTextureEntry()->getMaterialParams() == mat))))) { facep = *i; @@ -5163,8 +5380,16 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac ++i; index_count += facep->getIndicesCount(); geom_count += facep->getGeomCount(); + + flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); + } } } + + + if (flexi && buffer_usage && buffer_usage != GL_STREAM_DRAW_ARB) + { + buffer_usage = GL_STREAM_DRAW_ARB; } //create vertex buffer @@ -5262,8 +5487,97 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; } - bool use_legacy_bump = te->getBumpmap(); - if (mat) + bool use_legacy_bump = te->getBumpmap() && (te->getBumpmap() < 18) && (!mat || mat->getNormalID().isNull()); + bool opaque = te->getColor().mV[3] >= 0.999f; + + if (mat && LLPipeline::sRenderDeferred && !hud_group) + { + bool material_pass = false; + + // do NOT use 'fullbright' for this logic or you risk sending + // things without normals down the materials pipeline and will + // render poorly if not crash NORSPEC-240,314 + // + if (te->getFullbright()) + { + if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { + if (opaque) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); + } + 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) @@ -5284,7 +5598,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac && te->getShiny() && can_be_shiny) { - registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_SHINY : (!LLPipeline::sRenderDeferred || hud_group) ? LLRenderPass::PASS_SHINY : LLRenderPass::PASS_SIMPLE); + registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_SHINY : LLRenderPass::PASS_SHINY); } else { diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index b9cb79508..3b6955951 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -164,6 +164,7 @@ public: const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; void markForUpdate(BOOL priority) { LLViewerObject::markForUpdate(priority); mVolumeChanged = TRUE; } + void faceMappingChanged() { mFaceMappingChanged=TRUE; }; /*virtual*/ void onShift(const LLVector4a &shift_vector); // Called when the drawable shifts diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 2d1f229b8..52edd16aa 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -184,6 +184,7 @@ LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY("Windlight Sky"); LLFastTimer::DeclareTimer FTM_RENDER_ALPHA("Alpha Objects"); LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS("Avatars"); LLFastTimer::DeclareTimer FTM_RENDER_BUMP("Bump"); +LLFastTimer::DeclareTimer FTM_RENDER_MATERIALS("Materials"); LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT("Fullbright"); LLFastTimer::DeclareTimer FTM_RENDER_GLOW("Glow"); LLFastTimer::DeclareTimer FTM_GEO_UPDATE("Geo Update"); @@ -204,12 +205,17 @@ LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading"); static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables"); static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort"); +static LLStaticHashedString sTint("tint"); +static LLStaticHashedString sAmbiance("ambiance"); +static LLStaticHashedString sAlphaScale("alpha_scale"); static LLStaticHashedString sNormMat("norm_mat"); static LLStaticHashedString sOffset("offset"); +static LLStaticHashedString sScreenRes("screenRes"); static LLStaticHashedString sDelta("delta"); static LLStaticHashedString sDistFactor("dist_factor"); static LLStaticHashedString sKern("kern"); static LLStaticHashedString sKernScale("kern_scale"); + //---------------------------------------- std::string gPoolNames[] = { @@ -219,8 +225,11 @@ std::string gPoolNames[] = "POOL_GROUND", "POOL_FULLBRIGHT", "POOL_BUMP", + "POOL_MATERIALS", "POOL_TERRAIN", "POOL_TREE", // Singu Note: Before sky for zcull. + "POOL_ALPHA_MASK", + "POOL_FULLBRIGHT_ALPHA_MASK", "POOL_SKY", "POOL_WL_SKY", "POOL_GRASS", @@ -326,6 +335,7 @@ BOOL LLPipeline::sWaterReflections = FALSE; BOOL LLPipeline::sRenderGlow = FALSE; BOOL LLPipeline::sReflectionRender = FALSE; BOOL LLPipeline::sImpostorRender = FALSE; +BOOL LLPipeline::sImpostorRenderAlphaDepthPass = FALSE; BOOL LLPipeline::sUnderWaterRender = FALSE; BOOL LLPipeline::sTextureBindTest = FALSE; BOOL LLPipeline::sRenderFrameTest = FALSE; @@ -335,6 +345,7 @@ BOOL LLPipeline::sRenderDeferred = FALSE; BOOL LLPipeline::sMemAllocationThrottled = FALSE; S32 LLPipeline::sVisibleLightCount = 0; F32 LLPipeline::sMinRenderSize = 0.f; +BOOL LLPipeline::sRenderingHUDs; static LLCullResult* sCull = NULL; @@ -354,9 +365,9 @@ void validate_framebuffer_object(); bool addDeferredAttachments(LLRenderTarget& target) { - static const LLCachedControl SHPrecisionDeferredNormals("SHPrecisionDeferredNormals",false); - return target.addColorAttachment(GL_RGBA) && //specular - target.addColorAttachment(SHPrecisionDeferredNormals ? GL_RGB10_A2 : GL_RGBA); //normal+z + //static const LLCachedControl SHPrecisionDeferredNormals("SHPrecisionDeferredNormals",false); //DEAD + return target.addColorAttachment(GL_SRGB8_ALPHA8) && //specular + target.addColorAttachment(GL_RGB10_A2); //normal+z } LLPipeline::LLPipeline() : @@ -392,10 +403,14 @@ LLPipeline::LLPipeline() : mWaterPool(NULL), mGroundPool(NULL), mSimplePool(NULL), + mGrassPool(NULL), + mAlphaMaskPool(NULL), + mFullbrightAlphaMaskPool(NULL), mFullbrightPool(NULL), mInvisiblePool(NULL), mGlowPool(NULL), mBumpPool(NULL), + mMaterialsPool(NULL), mWLSkyPool(NULL), mLightMask(0), mLightMovingMask(0), @@ -427,10 +442,13 @@ void LLPipeline::init() //create render pass pools getPool(LLDrawPool::POOL_ALPHA); getPool(LLDrawPool::POOL_SIMPLE); + getPool(LLDrawPool::POOL_ALPHA_MASK); + getPool(LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK); getPool(LLDrawPool::POOL_GRASS); getPool(LLDrawPool::POOL_FULLBRIGHT); getPool(LLDrawPool::POOL_INVISIBLE); getPool(LLDrawPool::POOL_BUMP); + getPool(LLDrawPool::POOL_MATERIALS); getPool(LLDrawPool::POOL_GLOW); LLViewerStats::getInstance()->mTrianglesDrawnStat.reset(); @@ -639,14 +657,22 @@ void LLPipeline::resizeScreenTexture() GLuint resX = gViewerWindow->getWorldViewWidthRaw(); GLuint resY = gViewerWindow->getWorldViewHeightRaw(); + if ((resX != mScreen.getWidth()) || (resY != mScreen.getHeight())) + { + releaseScreenBuffers(); if (!allocateScreenBuffer(resX,resY)) - { //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled + { +#if PROBABLE_FALSE_DISABLES_OF_ALM_HERE + //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled //NOTE: if the session closes successfully after this call, deferred rendering will be // disabled on future sessions if (LLPipeline::sRenderDeferred) { gSavedSettings.setBOOL("RenderDeferred", FALSE); LLPipeline::refreshCachedSettings(); + + } +#endif } } } @@ -777,15 +803,26 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) const U32 occlusion_divisor = 3; //allocate deferred rendering color buffers - if (!mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; + if (!mDeferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; if (!mOcclusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; if (!addDeferredAttachments(mDeferredScreen)) return false; + + GLuint screenFormat = GL_RGBA16; + if (gGLManager.mIsATI) + { + screenFormat = GL_RGBA12; + } - if (!mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; + if (gGLManager.mGLVersion < 4.f && gGLManager.mIsNVIDIA) + { + screenFormat = GL_RGBA16F_ARB; + } + + if (!mScreen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; if (samples > 0) { - if (!mFXAABuffer.allocate(nhpo2(resX), nhpo2(resY), GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE)) return false; + if (!mFXAABuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE)) return false; } else { @@ -808,8 +845,8 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) U32 sun_shadow_map_width = ((U32(resX*scale)+1)&~1); // must be even to avoid a stripe in the horizontal shadow blur for (U32 i = 0; i < 4; i++) { - if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; - if (!mShadowOcclusion[i].allocate(mShadow[i].getWidth()/occlusion_divisor, mShadow[i].getHeight()/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; + if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) return false; + if (!mShadowOcclusion[i].allocate(mShadow[i].getWidth()/occlusion_divisor, mShadow[i].getHeight()/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) return false; } } else @@ -821,7 +858,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) } } - U32 width = nhpo2(U32(resX*scale))/2; + U32 width = (U32) (resX*scale); U32 height = width; if (shadow_detail > 1) @@ -902,6 +939,7 @@ void LLPipeline::updateRenderDeferred() sRenderDeferred = (gSavedSettings.getBOOL("RenderDeferred") && LLRenderTarget::sUseFBO && LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && + gSavedSettings.getBOOL("RenderObjectBump") && gSavedSettings.getBOOL("VertexShaderEnable") && gSavedSettings.getBOOL("RenderAvatarVP") && gSavedSettings.getBOOL("WindLightUseAtmosShaders") && @@ -1003,13 +1041,30 @@ void LLPipeline::createGLBuffers() updateRenderDeferred(); + bool materials_in_water = false; + +#if MATERIALS_IN_REFLECTIONS + materials_in_water = gSavedSettings.getS32("RenderWaterMaterials"); +#endif + if (LLPipeline::sWaterReflections) { //water reflection texture U32 res = (U32) llmax(gSavedSettings.getS32("RenderWaterRefResolution"), 512); - mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE); - //always use FBO for mWaterDis so it can be used for avatar texture bakes - mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE, true); + // Set up SRGB targets if we're doing deferred-path reflection rendering + // + if (LLPipeline::sRenderDeferred && materials_in_water) + { + mWaterRef.allocate(res,res,GL_SRGB8_ALPHA8,TRUE,FALSE); + //always use FBO for mWaterDis so it can be used for avatar texture bakes + mWaterDis.allocate(res,res,GL_SRGB8_ALPHA8,TRUE,FALSE,LLTexUnit::TT_TEXTURE, true); + } + else + { + mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE); + //always use FBO for mWaterDis so it can be used for avatar texture bakes + mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE, true); + } } @@ -1118,7 +1173,6 @@ void LLPipeline::createLUTBuffers() // Always sample at a 1.0/2.2 curve. // This "Gamma corrects" our specular term, boosting our lower exponent reflections. - spec = powf(spec, 1.f/2.2f); ls[y*lightResX+x] = spec; // Easy fix for our dynamic range problem: divide by 6 here, multiply by 6 in our shaders. @@ -1354,6 +1408,14 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0) poolp = mGrassPool; break; + case LLDrawPool::POOL_ALPHA_MASK: + poolp = mAlphaMaskPool; + break; + + case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: + poolp = mFullbrightAlphaMaskPool; + break; + case LLDrawPool::POOL_FULLBRIGHT: poolp = mFullbrightPool; break; @@ -1377,7 +1439,9 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0) case LLDrawPool::POOL_BUMP: poolp = mBumpPool; break; - + case LLDrawPool::POOL_MATERIALS: + poolp = mMaterialsPool; + break; case LLDrawPool::POOL_ALPHA: poolp = mAlphaPool; break; @@ -1471,10 +1535,14 @@ U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* ima { return LLDrawPool::POOL_ALPHA; } - else if ((te->getBumpmap() || te->getShiny())) + else if ((te->getBumpmap() || te->getShiny()) && (!mat || mat->getNormalID().isNull())) { return LLDrawPool::POOL_BUMP; } + else if (mat && !alpha) + { + return LLDrawPool::POOL_MATERIALS; + } else { return LLDrawPool::POOL_SIMPLE; @@ -2176,7 +2244,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl if (to_texture) { - if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) + if (LLPipeline::sRenderDeferred) { mOcclusionDepth.bindTarget(); } @@ -2321,7 +2389,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl if (to_texture) { - if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) + if (LLPipeline::sRenderDeferred) { mOcclusionDepth.flush(); } @@ -4601,8 +4669,8 @@ void LLPipeline::renderDebug() LLSpatialPartition* part = region->getSpatialPartition(i); if (part) { - if ( hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES) || - !hud_only && hasRenderType(part->mDrawableType) ) + if ( (hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES)) || + (!hud_only && hasRenderType(part->mDrawableType)) ) { part->renderDebug(); } @@ -4917,6 +4985,32 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) } break; + case LLDrawPool::POOL_ALPHA_MASK: + if (mAlphaMaskPool) + { + llassert(0); + llwarns << "Ignoring duplicate alpha mask pool." << llendl; + break; + } + else + { + mAlphaMaskPool = (LLRenderPass*) new_poolp; + } + break; + + case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: + if (mFullbrightAlphaMaskPool) + { + llassert(0); + llwarns << "Ignoring duplicate alpha mask pool." << llendl; + break; + } + else + { + mFullbrightAlphaMaskPool = (LLRenderPass*) new_poolp; + } + break; + case LLDrawPool::POOL_GRASS: if (mGrassPool) { @@ -4984,7 +5078,17 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) mBumpPool = new_poolp; } break; - + case LLDrawPool::POOL_MATERIALS: + if (mMaterialsPool) + { + llassert(0); + llwarns << "Ignorning duplicate materials pool." << llendl; + } + else + { + mMaterialsPool = new_poolp; + } + break; case LLDrawPool::POOL_ALPHA: if( mAlphaPool ) { @@ -4993,7 +5097,7 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) } else { - mAlphaPool = new_poolp; + mAlphaPool = (LLDrawPoolAlpha*) new_poolp; } break; @@ -5073,6 +5177,16 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) mSimplePool = NULL; break; + case LLDrawPool::POOL_ALPHA_MASK: + llassert(mAlphaMaskPool == poolp); + mAlphaMaskPool = NULL; + break; + + case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: + llassert(mFullbrightAlphaMaskPool == poolp); + mFullbrightAlphaMaskPool = NULL; + break; + case LLDrawPool::POOL_GRASS: llassert(mGrassPool == poolp); mGrassPool = NULL; @@ -5124,7 +5238,12 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) llassert( poolp == mBumpPool ); mBumpPool = NULL; break; - + + case LLDrawPool::POOL_MATERIALS: + llassert(poolp == mMaterialsPool); + mMaterialsPool = NULL; + break; + case LLDrawPool::POOL_ALPHA: llassert( poolp == mAlphaPool ); mAlphaPool = NULL; @@ -5536,7 +5655,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) if (sRenderDeferred) { F32 size = light_radius*1.5f; - light_state->setLinearAttenuation(size*size); + light_state->setLinearAttenuation(size); light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f); } else @@ -6280,6 +6399,48 @@ BOOL LLPipeline::getRenderHighlights(void*) return sRenderHighlight; } +LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection, + S32* face_hit) +{ + LLVector4a local_end = end; + + LLVector4a position; + + LLDrawable* drawable = NULL; + + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_PARTICLE); + if (part && hasRenderType(part->mDrawableType)) + { + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, face_hit, &position, NULL, NULL, NULL); + if (hit) + { + drawable = hit; + local_end = position; + } + } + } + + LLVOPartGroup* ret = NULL; + if (drawable) + { + //make sure we're returning an LLVOPartGroup + llassert(drawable->getVObj()->getPCode() == LLViewerObject::LL_VO_PART_GROUP); + ret = (LLVOPartGroup*) drawable->getVObj().get(); + } + + if (intersection) + { + *intersection = position; + } + + return ret; +} + LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, S32* face_hit, @@ -6585,6 +6746,17 @@ void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture, BOOL batch_text gGLLastMatrix = NULL; } +void LLPipeline::renderMaskedObjects(U32 type, U32 mask, BOOL texture, BOOL batch_texture) +{ + assertInitialized(); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; + mAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; +} + + void apply_cube_face_rotation(U32 face) { switch (face) @@ -7089,7 +7261,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b { //combine result based on alpha if (multisample) { - mDeferredScreen.bindTarget(); + mDeferredLight.bindTarget(); glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); } else @@ -7110,6 +7282,13 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b mScreen.bindTexture(0, channel); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); } + + if (!LLViewerCamera::getInstance()->cameraUnderWater()) + { + shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 2.2); + } else { + shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 1.0); + } shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); @@ -7132,7 +7311,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b if (multisample) { - mDeferredScreen.flush(); + mDeferredLight.flush(); } } } @@ -7140,7 +7319,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b { if (multisample) { - mDeferredScreen.bindTarget(); + mDeferredLight.bindTarget(); } LLGLSLShader* shader = &gDeferredPostNoDoFProgram; @@ -7151,6 +7330,13 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b { mScreen.bindTexture(0, channel); } + + if (!LLViewerCamera::getInstance()->cameraUnderWater()) + { + shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 2.2); + } else { + shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 1.0); + } gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); @@ -7168,7 +7354,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b if (multisample) { - mDeferredScreen.flush(); + mDeferredLight.flush(); } } @@ -7189,7 +7375,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage()); if (channel > -1) { - mDeferredScreen.bindTexture(0, channel); + mDeferredLight.bindTexture(0, channel); } gGL.begin(LLRender::TRIANGLE_STRIP); @@ -7479,7 +7665,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n for (U32 i = 0; i < 4; i++) { - channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE); + channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_TEXTURE); stop_glerror(); if (channel > -1) { @@ -7489,8 +7675,8 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); stop_glerror(); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); stop_glerror(); } } @@ -7563,13 +7749,13 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n LLVector3 ssao_effect = RenderSSAOEffect; shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_EFFECT, ssao_effect[0]); - F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); - F32 shadow_bias_error = 1.f + RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); + //F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); + F32 shadow_bias_error = RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2])/3000.f; shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear()*2.f); - shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset*shadow_offset_error); - shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, RenderShadowBias*shadow_bias_error); + shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset); //*shadow_offset_error); + shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, RenderShadowBias+shadow_bias_error); shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_OFFSET, RenderSpotShadowOffset); shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_BIAS, RenderSpotShadowBias); @@ -7813,7 +7999,7 @@ void LLPipeline::renderDeferredLighting() if (RenderDeferredAtmospheric) { //apply sunlight contribution LLFastTimer ftm(FTM_ATMOSPHERICS); - bindDeferredShader(gDeferredSoftenProgram); + bindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram); { LLGLDepthTest depth(GL_FALSE); LLGLDisable blend(GL_BLEND); @@ -7835,7 +8021,7 @@ void LLPipeline::renderDeferredLighting() gGL.popMatrix(); } - unbindDeferredShader(gDeferredSoftenProgram); + unbindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram); } { //render non-deferred geometry (fullbright, alpha, etc) @@ -7947,7 +8133,7 @@ void LLPipeline::renderDeferredLighting() LLFastTimer ftm(FTM_LOCAL_LIGHTS); gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); - gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s); + gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); gGL.syncMatrices(); @@ -7968,7 +8154,7 @@ void LLPipeline::renderDeferredLighting() glh::vec3f tc(c); mat.mult_matrix_vec(tc); - fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s)); + fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s)); light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); } } @@ -8003,7 +8189,7 @@ void LLPipeline::renderDeferredLighting() LLColor3 col = volume->getLightColor(); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); - gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s); + gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); gGL.syncMatrices(); @@ -8021,10 +8207,6 @@ void LLPipeline::renderDeferredLighting() vert[2].set(3,1,0); { - bindDeferredShader(gDeferredMultiLightProgram); - - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - LLGLDepthTest depth(GL_FALSE); //full screen blit @@ -8036,7 +8218,7 @@ void LLPipeline::renderDeferredLighting() U32 count = 0; - const U32 max_count = 8; + const U32 max_count = LL_DEFERRED_MULTI_LIGHT_COUNT; LLVector4 light[max_count]; LLVector4 col[max_count]; @@ -8049,23 +8231,587 @@ void LLPipeline::renderDeferredLighting() fullscreen_lights.pop_front(); col[count] = light_colors.front(); light_colors.pop_front(); - - far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z); - + + /*col[count].mV[0] = powf(col[count].mV[0], 2.2f); + col[count].mV[1] = powf(col[count].mV[1], 2.2f); + col[count].mV[2] = powf(col[count].mV[2], 2.2f);*/ + + far_z = llmin(light[count].mV[2]-light[count].mV[3], far_z); + //col[count] = pow4fsrgb(col[count], 2.2f); count++; if (count == max_count || fullscreen_lights.empty()) { - gDeferredMultiLightProgram.uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count); - gDeferredMultiLightProgram.uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light); - gDeferredMultiLightProgram.uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col); - gDeferredMultiLightProgram.uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z); + U32 idx = count-1; + bindDeferredShader(gDeferredMultiLightProgram[idx]); + gDeferredMultiLightProgram[idx].uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count); + gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light); + gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col); + gDeferredMultiLightProgram[idx].uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z); far_z = 0.f; count = 0; + mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); + unbindDeferredShader(gDeferredMultiLightProgram[idx]); + } + } + + bindDeferredShader(gDeferredMultiSpotLightProgram); + + gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); + + mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + + for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter) + { + LLFastTimer ftm(FTM_PROJECTORS); + LLDrawable* drawablep = *iter; + + LLVOVolume* volume = drawablep->getVOVolume(); + + LLVector3 center = drawablep->getPositionAgent(); + F32* c = center.mV; + F32 s = volume->getLightRadius()*1.5f; + + sVisibleLightCount++; + + glh::vec3f tc(c); + mat.mult_matrix_vec(tc); + + setupSpotLight(gDeferredMultiSpotLightProgram, drawablep); + + LLColor3 col = volume->getLightColor(); + + /*col.mV[0] = powf(col.mV[0], 2.2f); + col.mV[1] = powf(col.mV[1], 2.2f); + col.mV[2] = powf(col.mV[2], 2.2f);*/ + + gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); + gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); + gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); + gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); + mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } + + gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION); + unbindDeferredShader(gDeferredMultiSpotLightProgram); + + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + } + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } + + gGL.setColorMask(true, true); + } + + mScreen.flush(); + + //gamma correct lighting + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); + + { + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + + LLVector2 tc1(0,0); + LLVector2 tc2((F32) mScreen.getWidth()*2, + (F32) mScreen.getHeight()*2); + + mScreen.bindTarget(); + // Apply gamma correction to the frame here. + gDeferredPostGammaCorrectProgram.bind(); + //mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + S32 channel = 0; + channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); + if (channel > -1) + { + mScreen.bindTexture(0,channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mScreen.getWidth(), mScreen.getHeight()); + + //F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); + + //gDeferredPostGammaCorrectProgram.uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); + gGL.vertex2f(-1,-1); + + gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); + gGL.vertex2f(-1,3); + + gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); + gGL.vertex2f(3,-1); + + gGL.end(); + + gGL.getTexUnit(channel)->unbind(mScreen.getUsage()); + gDeferredPostGammaCorrectProgram.unbind(); + mScreen.flush(); + } + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + + mScreen.bindTarget(); + + { //render non-deferred geometry (alpha, fullbright, glow) + LLGLDisable blend(GL_BLEND); + LLGLDisable stencil(GL_STENCIL_TEST); + + pushRenderTypeMask(); + andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA, + LLPipeline::RENDER_TYPE_FULLBRIGHT, + //LLPipeline::RENDER_TYPE_VOLUME, + LLPipeline::RENDER_TYPE_GLOW, + LLPipeline::RENDER_TYPE_BUMP, + /*LLPipeline::RENDER_TYPE_PASS_SIMPLE, //These aren't used. + LLPipeline::RENDER_TYPE_PASS_ALPHA, + LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_BUMP, + LLPipeline::RENDER_TYPE_PASS_POST_BUMP, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, + LLPipeline::RENDER_TYPE_PASS_GLOW, + LLPipeline::RENDER_TYPE_PASS_GRASS, + LLPipeline::RENDER_TYPE_PASS_SHINY, + LLPipeline::RENDER_TYPE_PASS_INVISIBLE, + LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,*/ + LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_ALPHA_MASK, + LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, + END_RENDER_TYPES); + + renderGeomPostDeferred(*LLViewerCamera::getInstance()); + popRenderTypeMask(); + } + + { + //render highlights, etc. + renderHighlights(); + mHighlightFaces.clear(); + + renderDebug(); + + LLVertexBuffer::unbind(); + + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + // Render debugging beacons. + gObjectList.renderObjectBeacons(); + gObjectList.resetObjectBeacons(); + } + } + + mScreen.flush(); + +} + +void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) +{ + if (!sCull) + { + return; + } + + static const LLCachedControl RenderFSAASamples("RenderFSAASamples",0); + static const LLCachedControl RenderDeferredSSAO("RenderDeferredSSAO",false); + static const LLCachedControl RenderShadowDetail("RenderShadowDetail",0); + static const LLCachedControl RenderShadowGaussian("RenderShadowGaussian",LLVector3(3.f,2.f,0.f)); + static const LLCachedControl RenderShadowBlurSize("RenderShadowBlurSize",1.4f); + static const LLCachedControl RenderShadowBlurDistFactor("RenderShadowBlurDistFactor",.1f); + static const LLCachedControl RenderDeferredAtmospheric("RenderDeferredAtmospheric",false); + static const LLCachedControl RenderLocalLights("RenderLocalLights",false); + + { + LLFastTimer ftm(FTM_RENDER_DEFERRED); + + LLViewerCamera* camera = LLViewerCamera::getInstance(); + { + LLGLDepthTest depth(GL_TRUE); + mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), + 0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); + } + + LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + + if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + } + + //ati doesn't seem to love actually using the stencil buffer on FBO's + LLGLDisable stencil(GL_STENCIL_TEST); + //glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); + //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + gGL.setColorMask(true, true); + + //draw a cube around every light + LLVertexBuffer::unbind(); + + LLGLEnable cull(GL_CULL_FACE); + LLGLEnable blend(GL_BLEND); + + glh::matrix4f mat = glh_copy_matrix(gGLModelView); + + LLStrider vert; + mDeferredVB->getVertexStrider(vert); + + vert[0].set(-1,1,0); + vert[1].set(-1,-3,0); + vert[2].set(3,1,0); + + { + setupHWLights(NULL); //to set mSunDir; + LLVector4 dir(mSunDir, 0.f); + glh::vec4f tc(dir.mV); + mat.mult_matrix_vec(tc); + mTransformedSunDir.set(tc.v); + } + + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + + if (RenderDeferredSSAO || RenderShadowDetail > 0) + { + mDeferredLight.bindTarget(); + { //paint shadow/SSAO light map (direct lighting lightmap) + LLFastTimer ftm(FTM_SUN_SHADOW); + bindDeferredShader(gDeferredSunProgram); + mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + glClearColor(1,1,1,1); + mDeferredLight.clear(GL_COLOR_BUFFER_BIT); + glClearColor(0,0,0,0); + + glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose(); + + const U32 slice = 32; + F32 offset[slice*3]; + for (U32 i = 0; i < 4; i++) + { + for (U32 j = 0; j < 8; j++) + { + glh::vec3f v; + v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i); + v.normalize(); + inv_trans.mult_matrix_vec(v); + v.normalize(); + offset[(i*8+j)*3+0] = v.v[0]; + offset[(i*8+j)*3+1] = v.v[2]; + offset[(i*8+j)*3+2] = v.v[1]; + } + } + + gDeferredSunProgram.uniform3fv(LLShaderMgr::DEFERRED_SHADOW_OFFSET, slice, offset); + gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredLight.getWidth(), mDeferredLight.getHeight()); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); + stop_glerror(); + mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); + stop_glerror(); + } + + unbindDeferredShader(gDeferredSunProgram); + } + mDeferredLight.flush(); + } + + stop_glerror(); + gGL.popMatrix(); + stop_glerror(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + stop_glerror(); + gGL.popMatrix(); + stop_glerror(); + + target->bindTarget(); + + //clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky + glClearColor(0,0,0,0); + target->clear(GL_COLOR_BUFFER_BIT); + + if (RenderDeferredAtmospheric) + { //apply sunlight contribution + LLFastTimer ftm(FTM_ATMOSPHERICS); + bindDeferredShader(gDeferredSoftenProgram); + { + LLGLDepthTest depth(GL_FALSE); + LLGLDisable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + + //full screen blit + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + + mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + + mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + } + + unbindDeferredShader(gDeferredSoftenProgram); + } + + { //render non-deferred geometry (fullbright, alpha, etc) + LLGLDisable blend(GL_BLEND); + LLGLDisable stencil(GL_STENCIL_TEST); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + gPipeline.pushRenderTypeMask(); + + gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS, + LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::END_RENDER_TYPES); + + + renderGeomPostDeferred(*LLViewerCamera::getInstance(), false); + gPipeline.popRenderTypeMask(); + } + + BOOL render_local = RenderLocalLights; + + if (render_local) + { + gGL.setSceneBlendType(LLRender::BT_ADD); + std::list fullscreen_lights; + LLDrawable::drawable_list_t spot_lights; + LLDrawable::drawable_list_t fullscreen_spot_lights; + + for (U32 i = 0; i < 2; i++) + { + mTargetShadowSpotLight[i] = NULL; + } + + std::list light_colors; + + LLVertexBuffer::unbind(); + + { + bindDeferredShader(gDeferredLightProgram); + + if (mCubeVB.isNull()) + { + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) + { + LLDrawable* drawablep = *iter; + + LLVOVolume* volume = drawablep->getVOVolume(); + if (!volume) + { + continue; + } + + if (volume->isAttachment()) + { + if (!sRenderAttachedLights) + { + continue; + } + } + + + LLVector4a center; + center.load3(drawablep->getPositionAgent().mV); + const F32* c = center.getF32ptr(); + F32 s = volume->getLightRadius()*1.5f; + + LLColor3 col = volume->getLightColor(); + + if (col.magVecSquared() < 0.001f) + { + continue; + } + + if (s <= 0.001f) + { + continue; + } + + LLVector4a sa; + sa.splat(s); + if (camera->AABBInFrustumNoFarClip(center, sa) == 0) + { + continue; + } + + sVisibleLightCount++; + + if (camera->getOrigin().mV[0] > c[0] + s + 0.2f || + camera->getOrigin().mV[0] < c[0] - s - 0.2f || + camera->getOrigin().mV[1] > c[1] + s + 0.2f || + camera->getOrigin().mV[1] < c[1] - s - 0.2f || + camera->getOrigin().mV[2] > c[2] + s + 0.2f || + camera->getOrigin().mV[2] < c[2] - s - 0.2f) + { //draw box if camera is outside box + if (render_local) + { + if (volume->isLightSpotlight()) + { + drawablep->getVOVolume()->updateSpotLightPriority(); + spot_lights.push_back(drawablep); + continue; + } + + /*col.mV[0] = powf(col.mV[0], 2.2f); + col.mV[1] = powf(col.mV[1], 2.2f); + col.mV[2] = powf(col.mV[2], 2.2f);*/ + + LLFastTimer ftm(FTM_LOCAL_LIGHTS); + gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); + gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); + gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); + gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); + gGL.syncMatrices(); + + mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); + stop_glerror(); + } + } + else + { + if (volume->isLightSpotlight()) + { + drawablep->getVOVolume()->updateSpotLightPriority(); + fullscreen_spot_lights.push_back(drawablep); + continue; + } + + glh::vec3f tc(c); + mat.mult_matrix_vec(tc); + + fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s)); + light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); + } + } + unbindDeferredShader(gDeferredLightProgram); + } + + if (!spot_lights.empty()) + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + bindDeferredShader(gDeferredSpotLightProgram); + + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + + gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); + + for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter) + { + LLFastTimer ftm(FTM_PROJECTORS); + LLDrawable* drawablep = *iter; + + LLVOVolume* volume = drawablep->getVOVolume(); + + LLVector4a center; + center.load3(drawablep->getPositionAgent().mV); + const F32* c = center.getF32ptr(); + F32 s = volume->getLightRadius()*1.5f; + + sVisibleLightCount++; + + setupSpotLight(gDeferredSpotLightProgram, drawablep); + + LLColor3 col = volume->getLightColor(); + /*col.mV[0] = powf(col.mV[0], 2.2f); + col.mV[1] = powf(col.mV[1], 2.2f); + col.mV[2] = powf(col.mV[2], 2.2f);*/ + + gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); + gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); + gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); + gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); + gGL.syncMatrices(); + + mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); + } + gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION); + unbindDeferredShader(gDeferredSpotLightProgram); + } + + //reset mDeferredVB to fullscreen triangle + mDeferredVB->getVertexStrider(vert); + vert[0].set(-1,1,0); + vert[1].set(-1,-3,0); + vert[2].set(3,1,0); + + { + LLGLDepthTest depth(GL_FALSE); + + //full screen blit + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + + U32 count = 0; + + const U32 max_count = LL_DEFERRED_MULTI_LIGHT_COUNT; + LLVector4 light[max_count]; + LLVector4 col[max_count]; + + F32 far_z = 0.f; + + while (!fullscreen_lights.empty()) + { + LLFastTimer ftm(FTM_FULLSCREEN_LIGHTS); + light[count] = fullscreen_lights.front(); + fullscreen_lights.pop_front(); + col[count] = light_colors.front(); + light_colors.pop_front(); + + /*col[count].mV[0] = powf(col[count].mV[0], 2.2f); + col[count].mV[1] = powf(col[count].mV[1], 2.2f); + col[count].mV[2] = powf(col[count].mV[2], 2.2f);*/ + + far_z = llmin(light[count].mV[2]-light[count].mV[3], far_z); + //col[count] = pow4fsrgb(col[count], 2.2f); + count++; + if (count == max_count || fullscreen_lights.empty()) + { + U32 idx = count-1; + bindDeferredShader(gDeferredMultiLightProgram[idx]); + gDeferredMultiLightProgram[idx].uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count); + gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light); + gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col); + gDeferredMultiLightProgram[idx].uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z); + far_z = 0.f; + count = 0; + mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); } } - unbindDeferredShader(gDeferredMultiLightProgram); + unbindDeferredShader(gDeferredMultiLightProgram[0]); bindDeferredShader(gDeferredMultiSpotLightProgram); @@ -8092,9 +8838,13 @@ void LLPipeline::renderDeferredLighting() setupSpotLight(gDeferredMultiSpotLightProgram, drawablep); LLColor3 col = volume->getLightColor(); - + + /*col.mV[0] = powf(col.mV[0], 2.2f); + col.mV[1] = powf(col.mV[1], 2.2f); + col.mV[2] = powf(col.mV[2], 2.2f);*/ + gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); - gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s); + gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -8107,12 +8857,70 @@ void LLPipeline::renderDeferredLighting() gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.popMatrix(); } - gGL.setSceneBlendType(LLRender::BT_ALPHA); } gGL.setColorMask(true, true); } + /*mScreen.flush(); + + //gamma correct lighting + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); + + { + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + + LLVector2 tc1(0,0); + LLVector2 tc2((F32) mScreen.getWidth()*2, + (F32) mScreen.getHeight()*2); + + mScreen.bindTarget(); + // Apply gamma correction to the frame here. + gDeferredPostGammaCorrectProgram.bind(); + //mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + S32 channel = 0; + channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); + if (channel > -1) + { + mScreen.bindTexture(0,channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mScreen.getWidth(), mScreen.getHeight()); + + F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); + + gDeferredPostGammaCorrectProgram.uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); + gGL.vertex2f(-1,-1); + + gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); + gGL.vertex2f(-1,3); + + gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); + gGL.vertex2f(3,-1); + + gGL.end(); + + gGL.getTexUnit(channel)->unbind(mScreen.getUsage()); + gDeferredPostGammaCorrectProgram.unbind(); + mScreen.flush(); + } + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + + mScreen.bindTarget();*/ + { //render non-deferred geometry (alpha, fullbright, glow) LLGLDisable blend(GL_BLEND); LLGLDisable stencil(GL_STENCIL_TEST); @@ -8120,10 +8928,10 @@ void LLPipeline::renderDeferredLighting() pushRenderTypeMask(); andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA, LLPipeline::RENDER_TYPE_FULLBRIGHT, - //LLPipeline::RENDER_TYPE_VOLUME, + LLPipeline::RENDER_TYPE_VOLUME, LLPipeline::RENDER_TYPE_GLOW, LLPipeline::RENDER_TYPE_BUMP, - /*LLPipeline::RENDER_TYPE_PASS_SIMPLE, //These aren't used. + LLPipeline::RENDER_TYPE_PASS_SIMPLE, LLPipeline::RENDER_TYPE_PASS_ALPHA, LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK, LLPipeline::RENDER_TYPE_PASS_BUMP, @@ -8135,33 +8943,17 @@ void LLPipeline::renderDeferredLighting() LLPipeline::RENDER_TYPE_PASS_GRASS, LLPipeline::RENDER_TYPE_PASS_SHINY, LLPipeline::RENDER_TYPE_PASS_INVISIBLE, - LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,*/ + LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_ALPHA_MASK, + LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, END_RENDER_TYPES); renderGeomPostDeferred(*LLViewerCamera::getInstance()); popRenderTypeMask(); } - { - //render highlights, etc. - renderHighlights(); - mHighlightFaces.clear(); - - renderDebug(); - - LLVertexBuffer::unbind(); - - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - // Render debugging beacons. - gObjectList.renderObjectBeacons(); - gObjectList.resetObjectBeacons(); - } - } - - mScreen.flush(); - + } void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep) @@ -8316,9 +9108,9 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) for (U32 i = 0; i < 4; i++) { - if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE) > -1) + if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i) > -1) { - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); } } @@ -8410,6 +9202,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) water_clip = 1; } + bool materials_in_water = false; + +#if MATERIALS_IN_REFLECTIONS + materials_in_water = gSavedSettings.getS32("RenderWaterMaterials"); +#endif + if (!LLViewerCamera::getInstance()->cameraUnderWater()) { //generate planar reflection map @@ -8467,11 +9265,28 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) updateCull(camera, result); stateSort(camera, result); + if (LLPipeline::sRenderDeferred && materials_in_water) + { + mWaterRef.flush(); + + gPipeline.grabReferences(result); + gPipeline.mDeferredScreen.bindTarget(); + gGL.setColorMask(true, true); + glClearColor(0,0,0,0); + gPipeline.mDeferredScreen.clear(); + + renderGeomDeferred(camera); + } + else + { renderGeom(camera, TRUE); + } gPipeline.popRenderTypeMask(); } + gGL.setColorMask(true, false); + static const LLCachedControl detail("RenderReflectionDetail",0); if (detail > 0) { //mask out selected geometry based on reflection detail @@ -8505,11 +9320,31 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLGLDisable cull(GL_CULL_FACE); updateCull(camera, ref_result, -water_clip, &plane); stateSort(camera, ref_result); + if (LLDrawPoolWater::sNeedsDistortionUpdate) { - gPipeline.grabReferences(ref_result); - renderGeom(camera); + if (detail > 0) + { + gPipeline.grabReferences(ref_result); + LLGLUserClipPlane clip_plane(plane, mat, projection); + + if (LLPipeline::sRenderDeferred && materials_in_water) + { + renderGeomDeferred(camera); + } + else + { + renderGeom(camera); + } + } } + + if (LLPipeline::sRenderDeferred && materials_in_water) + { + gPipeline.mDeferredScreen.flush(); + renderDeferredLightingToRT(&mWaterRef); + } + LLPipeline::sSkipUpdate = FALSE; gPipeline.popRenderTypeMask(); } @@ -8568,13 +9403,36 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) gGL.setColorMask(true, true); mWaterDis.clear(); + + gGL.setColorMask(true, false); + + if (LLPipeline::sRenderDeferred && materials_in_water) + { + mWaterDis.flush(); + gPipeline.mDeferredScreen.bindTarget(); + gGL.setColorMask(true, true); + glClearColor(0,0,0,0); + gPipeline.mDeferredScreen.clear(); + gPipeline.grabReferences(result); + renderGeomDeferred(camera); + } + else + { renderGeom(camera); + } + + if (LLPipeline::sRenderDeferred && materials_in_water) + { + gPipeline.mDeferredScreen.flush(); + renderDeferredLightingToRT(&mWaterDis); + } } - LLPipeline::sUnderWaterRender = FALSE; mWaterDis.flush(); + LLPipeline::sUnderWaterRender = FALSE; + } last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate; @@ -8690,7 +9548,15 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP, - LLRenderPass::PASS_FULLBRIGHT_SHINY + LLRenderPass::PASS_FULLBRIGHT_SHINY , + LLRenderPass::PASS_MATERIAL, + LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, + LLRenderPass::PASS_SPECMAP, + LLRenderPass::PASS_SPECMAP_EMISSIVE, + LLRenderPass::PASS_NORMMAP, + LLRenderPass::PASS_NORMMAP_EMISSIVE, + LLRenderPass::PASS_NORMSPEC, + LLRenderPass::PASS_NORMSPEC_EMISSIVE, }; LLGLEnable cull(GL_CULL_FACE); @@ -8766,7 +9632,6 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera { LLFastTimer ftm(FTM_SHADOW_ALPHA); gDeferredShadowAlphaMaskProgram.bind(); - gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f); gDeferredShadowAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); U32 mask = LLVertexBuffer::MAP_VERTEX | @@ -8774,10 +9639,19 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; - renderObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE); - renderObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE); + renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE); + renderMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE); + gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f); renderObjects(LLRenderPass::PASS_ALPHA, mask, TRUE, TRUE); + + mask = mask & ~LLVertexBuffer::MAP_TEXTURE_INDEX; + gDeferredTreeShadowProgram.bind(); + renderMaskedObjects(LLRenderPass::PASS_NORMSPEC_MASK, mask); + renderMaskedObjects(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, mask); + renderMaskedObjects(LLRenderPass::PASS_SPECMAP_MASK, mask); + renderMaskedObjects(LLRenderPass::PASS_NORMMAP_MASK, mask); + gDeferredTreeShadowProgram.setMinimumAlpha(0.598f); renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); } @@ -9044,6 +9918,22 @@ void LLPipeline::generateSunShadow(LLCamera& camera) LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, LLPipeline::RENDER_TYPE_PASS_SHINY, LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, + LLPipeline::RENDER_TYPE_PASS_MATERIAL, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE, + LLPipeline::RENDER_TYPE_PASS_SPECMAP, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_BLEND, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_MASK, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_EMISSIVE, + LLPipeline::RENDER_TYPE_PASS_NORMMAP, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_BLEND, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_MASK, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_EMISSIVE, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_BLEND, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_MASK, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_EMISSIVE, END_RENDER_TYPES); gGL.setColorMask(false, false); @@ -9787,33 +10677,39 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) assertInitialized(); - bool muted = avatar->isVisuallyMuted(); + bool visually_muted = avatar->isVisuallyMuted(); pushRenderTypeMask(); - if (muted) + if (visually_muted) { andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); } else { - andRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, - LLPipeline::RENDER_TYPE_AVATAR, + andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA, + LLPipeline::RENDER_TYPE_FULLBRIGHT, + LLPipeline::RENDER_TYPE_VOLUME, + LLPipeline::RENDER_TYPE_GLOW, LLPipeline::RENDER_TYPE_BUMP, - LLPipeline::RENDER_TYPE_GRASS, - LLPipeline::RENDER_TYPE_SIMPLE, - LLPipeline::RENDER_TYPE_FULLBRIGHT, - LLPipeline::RENDER_TYPE_ALPHA, - LLPipeline::RENDER_TYPE_INVISIBLE, LLPipeline::RENDER_TYPE_PASS_SIMPLE, LLPipeline::RENDER_TYPE_PASS_ALPHA, LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_BUMP, + LLPipeline::RENDER_TYPE_PASS_POST_BUMP, LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK, LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, + LLPipeline::RENDER_TYPE_PASS_GLOW, + LLPipeline::RENDER_TYPE_PASS_GRASS, LLPipeline::RENDER_TYPE_PASS_SHINY, LLPipeline::RENDER_TYPE_PASS_INVISIBLE, LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, + LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_ALPHA_MASK, + LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, + LLPipeline::RENDER_TYPE_INVISIBLE, + LLPipeline::RENDER_TYPE_SIMPLE, END_RENDER_TYPES); } @@ -9919,19 +10815,23 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (!avatar->mImpostor.isComplete()) { LLFastTimer t(FTM_IMPOSTOR_ALLOCATE); - avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE); + if (LLPipeline::sRenderDeferred) { + avatar->mImpostor.allocate(resX,resY,GL_SRGB8_ALPHA8,TRUE,FALSE); addDeferredAttachments(avatar->mImpostor); } + else + { + avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE); + } gGL.getTexUnit(0)->bind(&avatar->mImpostor); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } - else if(resX != avatar->mImpostor.getWidth() || - resY != avatar->mImpostor.getHeight()) + else if(resX != avatar->mImpostor.getWidth() || resY != avatar->mImpostor.getHeight()) { LLFastTimer t(FTM_IMPOSTOR_RESIZE); avatar->mImpostor.resize(resX,resY); @@ -9940,11 +10840,34 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) avatar->mImpostor.bindTarget(); } + F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha; + + if (visually_muted) + { //disable alpha masking for muted avatars (get whole skin silhouette) + LLDrawPoolAvatar::sMinimumAlpha = 0.f; + } + if (LLPipeline::sRenderDeferred) { avatar->mImpostor.clear(); renderGeomDeferred(camera); + + renderGeomPostDeferred(camera); + + // Shameless hack time: render it all again, + // this time writing the depth + // values we need to generate the alpha mask below + // while preserving the alpha-sorted color rendering + // from the previous pass + // + sImpostorRenderAlphaDepthPass = true; + // depth-only here... + // + gGL.setColorMask(false,false); renderGeomPostDeferred(camera); + + sImpostorRenderAlphaDepthPass = false; + } else { @@ -9952,8 +10875,25 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) glScissor(0, 0, resX, resY); avatar->mImpostor.clear(); renderGeom(camera); + + // Shameless hack time: render it all again, + // this time writing the depth + // values we need to generate the alpha mask below + // while preserving the alpha-sorted color rendering + // from the previous pass + // + sImpostorRenderAlphaDepthPass = true; + + // depth-only here... + // + gGL.setColorMask(false,false); + renderGeom(camera); + + sImpostorRenderAlphaDepthPass = false; } - + + LLDrawPoolAvatar::sMinimumAlpha = old_alpha; + { //create alpha mask based on depth buffer (grey out if muted) LLFastTimer t(FTM_IMPOSTOR_BACKGROUND); if (LLPipeline::sRenderDeferred) @@ -9964,7 +10904,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) LLGLDisable blend(GL_BLEND); - if (muted) + if (visually_muted) { gGL.setColorMask(true, true); } @@ -9989,10 +10929,10 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (LLGLSLShader::sNoFixedFunction) { - gUIProgram.bind(); + gDebugProgram.bind(); } - gGL.color4ub(64,64,64,255); + gGL.diffuseColor4ub(64,64,64,255); gGL.begin(LLRender::QUADS); gGL.vertex3f(-1, -1, clip_plane); gGL.vertex3f(1, -1, clip_plane); @@ -10003,7 +10943,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (LLGLSLShader::sNoFixedFunction) { - gUIProgram.unbind(); + gDebugProgram.unbind(); } gGL.popMatrix(); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index b9204d878..75f03f52c 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -41,7 +41,8 @@ #include "llspatialpartition.h" #include "m4math.h" #include "llpointer.h" -#include "lldrawpool.h" +#include "lldrawpoolalpha.h" +#include "lldrawpoolmaterials.h" #include "llgl.h" #include "lldrawable.h" #include "llrendertarget.h" @@ -64,7 +65,11 @@ class LLRenderFunc; class LLCubeMap; class LLCullResult; class LLVOAvatar; +class LLVOPartGroup; class LLGLSLShader; +class LLDrawPoolAlpha; + +class LLMeshResponder; typedef enum e_avatar_skinning_method { @@ -99,6 +104,7 @@ extern LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY; extern LLFastTimer::DeclareTimer FTM_RENDER_ALPHA; extern LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS; extern LLFastTimer::DeclareTimer FTM_RENDER_BUMP; +extern LLFastTimer::DeclareTimer FTM_RENDER_MATERIALS; extern LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT; extern LLFastTimer::DeclareTimer FTM_RENDER_GLOW; extern LLFastTimer::DeclareTimer FTM_STATESORT; @@ -203,6 +209,12 @@ public: LLVector4a* normal = NULL, // return the surface normal at the intersection point LLVector4a* tangent = NULL // return the surface tangent at the intersection point ); + + //get the closest particle to start between start and end, returns the LLVOPartGroup and particle index + LLVOPartGroup* lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection, + S32* face_hit); + + LLViewerObject* lineSegmentIntersectInHUD(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, S32* face_hit, // return the face hit @@ -266,6 +278,7 @@ public: void forAllVisibleDrawables(void (*func)(LLDrawable*)); void renderObjects(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_texture = FALSE); + void renderMaskedObjects(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_texture = FALSE); void renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture); void grabReferences(LLCullResult& result); @@ -287,6 +300,7 @@ public: void unbindDeferredShader(LLGLSLShader& shader); void renderDeferredLighting(); + void renderDeferredLightingToRT(LLRenderTarget* target); void generateWaterReflection(LLCamera& camera); void generateSunShadow(LLCamera& camera); @@ -429,11 +443,14 @@ public: RENDER_TYPE_WL_SKY = LLDrawPool::POOL_WL_SKY, RENDER_TYPE_GROUND = LLDrawPool::POOL_GROUND, RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN, - RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE, - RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS, - RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT, - RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP, - RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, + RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE, + RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS, + RENDER_TYPE_ALPHA_MASK = LLDrawPool::POOL_ALPHA_MASK, + RENDER_TYPE_FULLBRIGHT_ALPHA_MASK = LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK, + RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT, + RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP, + RENDER_TYPE_MATERIALS = LLDrawPool::POOL_MATERIALS, + RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, RENDER_TYPE_TREE = LLDrawPool::POOL_TREE, RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE, RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER, @@ -453,6 +470,22 @@ public: RENDER_TYPE_PASS_ALPHA = LLRenderPass::PASS_ALPHA, RENDER_TYPE_PASS_ALPHA_MASK = LLRenderPass::PASS_ALPHA_MASK, RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, + RENDER_TYPE_PASS_MATERIAL = LLRenderPass::PASS_MATERIAL, + RENDER_TYPE_PASS_MATERIAL_ALPHA = LLRenderPass::PASS_MATERIAL_ALPHA, + RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK = LLRenderPass::PASS_MATERIAL_ALPHA_MASK, + RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE= LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, + RENDER_TYPE_PASS_SPECMAP = LLRenderPass::PASS_SPECMAP, + RENDER_TYPE_PASS_SPECMAP_BLEND = LLRenderPass::PASS_SPECMAP_BLEND, + RENDER_TYPE_PASS_SPECMAP_MASK = LLRenderPass::PASS_SPECMAP_MASK, + RENDER_TYPE_PASS_SPECMAP_EMISSIVE = LLRenderPass::PASS_SPECMAP_EMISSIVE, + RENDER_TYPE_PASS_NORMMAP = LLRenderPass::PASS_NORMMAP, + RENDER_TYPE_PASS_NORMMAP_BLEND = LLRenderPass::PASS_NORMMAP_BLEND, + RENDER_TYPE_PASS_NORMMAP_MASK = LLRenderPass::PASS_NORMMAP_MASK, + RENDER_TYPE_PASS_NORMMAP_EMISSIVE = LLRenderPass::PASS_NORMMAP_EMISSIVE, + RENDER_TYPE_PASS_NORMSPEC = LLRenderPass::PASS_NORMSPEC, + RENDER_TYPE_PASS_NORMSPEC_BLEND = LLRenderPass::PASS_NORMSPEC_BLEND, + RENDER_TYPE_PASS_NORMSPEC_MASK = LLRenderPass::PASS_NORMSPEC_MASK, + RENDER_TYPE_PASS_NORMSPEC_EMISSIVE = LLRenderPass::PASS_NORMSPEC_EMISSIVE, // Following are object types (only used in drawable mRenderType) RENDER_TYPE_HUD = LLRenderPass::NUM_RENDER_TYPES, RENDER_TYPE_VOLUME, @@ -561,6 +594,7 @@ public: static BOOL sPickAvatar; static BOOL sReflectionRender; static BOOL sImpostorRender; + static BOOL sImpostorRenderAlphaDepthPass; static BOOL sUnderWaterRender; static BOOL sRenderGlow; static BOOL sTextureBindTest; @@ -571,6 +605,7 @@ public: static BOOL sMemAllocationThrottled; static S32 sVisibleLightCount; static F32 sMinRenderSize; + static BOOL sRenderingHUDs; //screen texture @@ -750,17 +785,20 @@ protected: // For quick-lookups into mPools (mapped by texture pointer) std::map mTerrainPools; std::map mTreePools; - LLDrawPool* mAlphaPool; + LLDrawPoolAlpha* mAlphaPool; LLDrawPool* mSkyPool; LLDrawPool* mTerrainPool; LLDrawPool* mWaterPool; LLDrawPool* mGroundPool; LLRenderPass* mSimplePool; LLRenderPass* mGrassPool; + LLRenderPass* mAlphaMaskPool; + LLRenderPass* mFullbrightAlphaMaskPool; LLRenderPass* mFullbrightPool; LLDrawPool* mInvisiblePool; LLDrawPool* mGlowPool; LLDrawPool* mBumpPool; + LLDrawPool* mMaterialsPool; LLDrawPool* mWLSkyPool; // Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar diff --git a/indra/newview/skins/default/textures/flatnormal.tga b/indra/newview/skins/default/textures/flatnormal.tga new file mode 100644 index 000000000..6d5abd178 Binary files /dev/null and b/indra/newview/skins/default/textures/flatnormal.tga differ