diff --git a/Engine/source/T3D/aiPlayer.cpp b/Engine/source/T3D/aiPlayer.cpp index bf00484e4..40fcc4709 100644 --- a/Engine/source/T3D/aiPlayer.cpp +++ b/Engine/source/T3D/aiPlayer.cpp @@ -564,6 +564,21 @@ bool AIPlayer::getAIMove(Move *movePtr) } } + Pose desiredPose = mPose; + + if ( mSwimming ) + desiredPose = SwimPose; + else if ( mAiPose == 1 && canCrouch() ) + desiredPose = CrouchPose; + else if ( mAiPose == 2 && canProne() ) + desiredPose = PronePose; + else if ( mAiPose == 3 && canSprint() ) + desiredPose = SprintPose; + else if ( canStand() ) + desiredPose = StandPose; + + setPose( desiredPose ); + // Replicate the trigger state into the move so that // triggers can be controlled from scripts. for( U32 i = 0; i < MaxTriggerKeys; i++ ) @@ -592,12 +607,24 @@ bool AIPlayer::getAIMove(Move *movePtr) return true; } -void AIPlayer::updateMove(const Move* move) +void AIPlayer::updateMove(const Move* move) +{ + if (!getControllingClient() && isGhost()) + return; + + Parent::updateMove(move); +} + +void AIPlayer::setAiPose( S32 pose ) { if (!getControllingClient() && isGhost()) return; + mAiPose = pose; +} - Parent::updateMove(move); +S32 AIPlayer::getAiPose() +{ + return mAiPose; } /** @@ -1397,3 +1424,18 @@ DefineEngineMethod(AIPlayer, getTargetDistance, bool, (ShapeBase* obj, bool chec { return object->getTargetDistance(obj, checkEnabled); } + +DefineEngineMethod( AIPlayer, setAiPose, void, ( S32 pose ),, + "@brief Sets the AiPose for an AI object.\n" + "@param pose StandPose=0, CrouchPose=1, PronePose=2, SprintPose=3.\n" + "Uses the new AiPose variable from shapebase (as defined in its PlayerData datablock).\n") +{ + object->setAiPose(pose); +} + +DefineEngineMethod( AIPlayer, getAiPose, S32, (),, + "@brief Get the object's current AiPose.\n" + "@return StandPose=0, CrouchPose=1, PronePose=2, SprintPose=3.\n") +{ + return object->getAiPose(); +} diff --git a/Engine/source/T3D/aiPlayer.h b/Engine/source/T3D/aiPlayer.h index 08707c0b8..e4f47eb9a 100644 --- a/Engine/source/T3D/aiPlayer.h +++ b/Engine/source/T3D/aiPlayer.h @@ -182,7 +182,9 @@ public: void setMoveDestination( const Point3F &location, bool slowdown ); Point3F getMoveDestination() const { return mMoveDestination; } void stopMove(); - + void setAiPose( S32 pose ); + S32 getAiPose(); + // Trigger sets/gets void setMoveTrigger( U32 slot, const bool isSet = true ); bool getMoveTrigger( U32 slot ) const; diff --git a/Engine/source/T3D/assets/ShapeAsset.h b/Engine/source/T3D/assets/ShapeAsset.h index 81b716d08..7c87cf8de 100644 --- a/Engine/source/T3D/assets/ShapeAsset.h +++ b/Engine/source/T3D/assets/ShapeAsset.h @@ -39,7 +39,7 @@ #endif #ifndef _TSSHAPE_H_ -#include "ts/TSShape.h" +#include "ts/tsShape.h" #endif #ifndef __RESOURCE_H__ #include "core/resource.h" diff --git a/Engine/source/T3D/decal/decalData.cpp b/Engine/source/T3D/decal/decalData.cpp index 67436e991..e517d2897 100644 --- a/Engine/source/T3D/decal/decalData.cpp +++ b/Engine/source/T3D/decal/decalData.cpp @@ -284,6 +284,7 @@ void DecalData::unpackData( BitStream *stream ) Parent::unpackData( stream ); stream->read( &lookupName ); + assignName(lookupName); stream->read( &size ); stream->read( &materialName ); _updateMaterial(); diff --git a/Engine/source/T3D/decal/decalManager.cpp b/Engine/source/T3D/decal/decalManager.cpp index 6db06a521..f992705d1 100644 --- a/Engine/source/T3D/decal/decalManager.cpp +++ b/Engine/source/T3D/decal/decalManager.cpp @@ -1744,3 +1744,48 @@ DefineEngineFunction( decalManagerRemoveDecal, bool, ( S32 decalID ),, gDecalManager->removeDecal(inst); return true; } + +DefineEngineFunction( decalManagerEditDecal, bool, ( S32 decalID, Point3F pos, Point3F normal, F32 rotAroundNormal, F32 decalScale ),, + "Edit specified decal of the decal manager.\n" + "@param decalID ID of the decal to edit.\n" + "@param pos World position for the decal.\n" + "@param normal Decal normal vector (if the decal was a tire lying flat on a " + "surface, this is the vector pointing in the direction of the axle).\n" + "@param rotAroundNormal Angle (in radians) to rotate this decal around its normal vector.\n" + "@param decalScale Scale factor applied to the decal.\n" + "@return Returns true if successful, false if decalID not found.\n" + "" ) +{ + DecalInstance *decalInstance = gDecalManager->getDecal( decalID ); + if( !decalInstance ) + return false; + + //Internally we need Point3F tangent instead of the user friendly F32 rotAroundNormal + MatrixF mat( true ); + MathUtils::getMatrixFromUpVector( normal, &mat ); + + AngAxisF rot( normal, rotAroundNormal ); + MatrixF rotmat; + rot.setMatrix( &rotmat ); + mat.mul( rotmat ); + + Point3F tangent; + mat.getColumn( 1, &tangent ); + + //if everything is unchanged just do nothing and return "everything is ok" + if ( pos.equal(decalInstance->mPosition) && + normal.equal(decalInstance->mNormal) && + tangent.equal(decalInstance->mTangent) && + mFabs( decalInstance->mSize - (decalInstance->mDataBlock->size * decalScale) ) < POINT_EPSILON ) + return true; + + decalInstance->mPosition = pos; + decalInstance->mNormal = normal; + decalInstance->mTangent = tangent; + decalInstance->mSize = decalInstance->mDataBlock->size * decalScale; + + gDecalManager->clipDecal( decalInstance, NULL, NULL); + + gDecalManager->notifyDecalModified( decalInstance ); + return true; +} diff --git a/Engine/source/T3D/fx/fxFoliageReplicator.cpp b/Engine/source/T3D/fx/fxFoliageReplicator.cpp index 51e044756..59d5af2ec 100644 --- a/Engine/source/T3D/fx/fxFoliageReplicator.cpp +++ b/Engine/source/T3D/fx/fxFoliageReplicator.cpp @@ -426,7 +426,7 @@ void fxFoliageReplicator::CreateFoliage(void) Point3F MaxPoint( 0.5, 0.5, 0.5 ); // Check Host. - AssertFatal(isClientObject(), "Trying to create Foliage on Server, this is bad!") + AssertFatal(isClientObject(), "Trying to create Foliage on Server, this is bad!"); // Cannot continue without Foliage Texture! if (dStrlen(mFieldData.mFoliageFile) == 0) @@ -1134,7 +1134,7 @@ void fxFoliageReplicator::ProcessQuadrant(fxFoliageQuadrantNode* pParentNode, fx void fxFoliageReplicator::SyncFoliageReplicators(void) { // Check Host. - AssertFatal(isServerObject(), "We *MUST* be on server when Synchronising Foliage!") + AssertFatal(isServerObject(), "We *MUST* be on server when Synchronising Foliage!"); // Find the Replicator Set. SimSet *fxFoliageSet = dynamic_cast(Sim::findObject("fxFoliageSet")); @@ -1196,7 +1196,7 @@ void fxFoliageReplicator::DestroyFoliageItems() void fxFoliageReplicator::DestroyFoliage(void) { // Check Host. - AssertFatal(isClientObject(), "Trying to destroy Foliage on Server, this is bad!") + AssertFatal(isClientObject(), "Trying to destroy Foliage on Server, this is bad!"); // Destroy Quad-tree. mPotentialFoliageNodes = 0; diff --git a/Engine/source/T3D/fx/fxShapeReplicator.cpp b/Engine/source/T3D/fx/fxShapeReplicator.cpp index 908212716..6093fa0d5 100644 --- a/Engine/source/T3D/fx/fxShapeReplicator.cpp +++ b/Engine/source/T3D/fx/fxShapeReplicator.cpp @@ -224,7 +224,7 @@ void fxShapeReplicator::CreateShapes(void) } // Check Shapes. - AssertFatal(mCurrentShapeCount==0,"Shapes already present, this should not be possible!") + AssertFatal(mCurrentShapeCount==0,"Shapes already present, this should not be possible!"); // Check that we have a shape... if (!mFieldData.mShapeFile) return; diff --git a/Engine/source/T3D/player.cpp b/Engine/source/T3D/player.cpp index 3c258c374..5f670abed 100644 --- a/Engine/source/T3D/player.cpp +++ b/Engine/source/T3D/player.cpp @@ -3173,18 +3173,21 @@ void Player::updateMove(const Move* move) // Update the PlayerPose Pose desiredPose = mPose; - if ( mSwimming ) - desiredPose = SwimPose; - else if ( runSurface && move->trigger[sCrouchTrigger] && canCrouch() ) - desiredPose = CrouchPose; - else if ( runSurface && move->trigger[sProneTrigger] && canProne() ) - desiredPose = PronePose; - else if ( move->trigger[sSprintTrigger] && canSprint() ) - desiredPose = SprintPose; - else if ( canStand() ) - desiredPose = StandPose; + if ( !mIsAiControlled ) + { + if ( mSwimming ) + desiredPose = SwimPose; + else if ( runSurface && move->trigger[sCrouchTrigger] && canCrouch() ) + desiredPose = CrouchPose; + else if ( runSurface && move->trigger[sProneTrigger] && canProne() ) + desiredPose = PronePose; + else if ( move->trigger[sSprintTrigger] && canSprint() ) + desiredPose = SprintPose; + else if ( canStand() ) + desiredPose = StandPose; - setPose( desiredPose ); + setPose( desiredPose ); + } } @@ -4659,9 +4662,9 @@ Point3F Player::_move( const F32 travelTime, Collision *outCol ) } Point3F distance = end - start; - if (mFabs(distance.x) < mObjBox.len_x() && - mFabs(distance.y) < mObjBox.len_y() && - mFabs(distance.z) < mObjBox.len_z()) + if (mFabs(distance.x) < mScaledBox.len_x() && + mFabs(distance.y) < mScaledBox.len_y() && + mFabs(distance.z) < mScaledBox.len_z()) { // We can potentially early out of this. If there are no polys in the clipped polylist at our // end position, then we can bail, and just set start = end; @@ -6186,6 +6189,10 @@ U32 Player::packUpdate(NetConnection *con, U32 mask, BitStream *stream) { stream->writeFlag(mFalling); + stream->writeFlag(mSwimming); + stream->writeFlag(mJetting); + stream->writeInt(mPose, NumPoseBits); + stream->writeInt(mState,NumStateBits); if (stream->writeFlag(mState == RecoverState)) stream->writeInt(mRecoverTicks,PlayerData::RecoverDelayBits); @@ -6282,7 +6289,11 @@ void Player::unpackUpdate(NetConnection *con, BitStream *stream) if (stream->readFlag()) { mPredictionCount = sMaxPredictionTicks; mFalling = stream->readFlag(); - + + mSwimming = stream->readFlag(); + mJetting = stream->readFlag(); + mPose = (Pose)(stream->readInt(NumPoseBits)); + ActionState actionState = (ActionState)stream->readInt(NumStateBits); if (stream->readFlag()) { mRecoverTicks = stream->readInt(PlayerData::RecoverDelayBits); @@ -6873,31 +6884,13 @@ void Player::playFootstepSound( bool triggeredLeft, Material* contactMaterial, S // Play default sound. S32 sound = -1; - if( contactMaterial && contactMaterial->mFootstepSoundId != -1 ) + if (contactMaterial && (contactMaterial->mImpactSoundId>-1 && contactMaterial->mImpactSoundIdmFootstepSoundId; else if( contactObject && contactObject->getTypeMask() & VehicleObjectType ) sound = 2; - switch ( sound ) - { - case 0: // Soft - SFX->playOnce( mDataBlock->sound[PlayerData::FootSoft], &footMat ); - break; - case 1: // Hard - SFX->playOnce( mDataBlock->sound[PlayerData::FootHard], &footMat ); - break; - case 2: // Metal - SFX->playOnce( mDataBlock->sound[PlayerData::FootMetal], &footMat ); - break; - case 3: // Snow - SFX->playOnce( mDataBlock->sound[PlayerData::FootSnow], &footMat ); - break; - /* - default: //Hard - SFX->playOnce( mDataBlock->sound[PlayerData::FootHard], &footMat ); - break; - */ - } + if (sound>=0) + SFX->playOnce(mDataBlock->sound[sound], &footMat); } } @@ -6922,36 +6915,13 @@ void Player:: playImpactSound() else { S32 sound = -1; - if( material && material->mImpactSoundId ) + if (material && (material->mImpactSoundId>-1 && material->mImpactSoundIdmImpactSoundId; else if( rInfo.object->getTypeMask() & VehicleObjectType ) sound = 2; // Play metal; - switch( sound ) - { - case 0: - //Soft - SFX->playOnce( mDataBlock->sound[ PlayerData::ImpactSoft ], &getTransform() ); - break; - case 1: - //Hard - SFX->playOnce( mDataBlock->sound[ PlayerData::ImpactHard ], &getTransform() ); - break; - case 2: - //Metal - SFX->playOnce( mDataBlock->sound[ PlayerData::ImpactMetal ], &getTransform() ); - break; - case 3: - //Snow - SFX->playOnce( mDataBlock->sound[ PlayerData::ImpactSnow ], &getTransform() ); - break; - /* - default: - //Hard - alxPlay(mDataBlock->sound[PlayerData::ImpactHard], &getTransform()); - break; - */ - } + if (sound >= 0) + SFX->playOnce(mDataBlock->sound[PlayerData::ImpactStart + sound], &getTransform()); } } } diff --git a/Engine/source/T3D/player.h b/Engine/source/T3D/player.h index eb1a39443..4ffd6c95d 100644 --- a/Engine/source/T3D/player.h +++ b/Engine/source/T3D/player.h @@ -190,13 +190,15 @@ struct PlayerData: public ShapeBaseData { FootHard, FootMetal, FootSnow, + MaxSoundOffsets, FootShallowSplash, FootWading, FootUnderWater, FootBubbles, MoveBubbles, WaterBreath, - ImpactSoft, + ImpactStart, + ImpactSoft = ImpactStart, ImpactHard, ImpactMetal, ImpactSnow, diff --git a/Engine/source/T3D/rigid.cpp b/Engine/source/T3D/rigid.cpp index e2441441f..31f4d411a 100644 --- a/Engine/source/T3D/rigid.cpp +++ b/Engine/source/T3D/rigid.cpp @@ -156,7 +156,7 @@ bool Rigid::resolveCollision(const Point3F& p, const Point3F &normal, Rigid* rig return false; // Compute impulse - F32 d, n = -nv * (1.0f + restitution * rigid->restitution); + F32 d, n = -nv * (2.0f + restitution * rigid->restitution); Point3F a1,b1,c1; mCross(r1,normal,&a1); invWorldInertia.mulV(a1,&b1); @@ -173,7 +173,7 @@ bool Rigid::resolveCollision(const Point3F& p, const Point3F &normal, Rigid* rig applyImpulse(r1,impulse); impulse.neg(); - applyImpulse(r2,impulse); + rigid->applyImpulse(r2, impulse); return true; } diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index 55b258a72..52ea070e3 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -879,6 +879,7 @@ IMPLEMENT_CALLBACK( ShapeBase, validateCameraFov, F32, (F32 fov), (fov), ShapeBase::ShapeBase() : mDataBlock( NULL ), mIsAiControlled( false ), + mAiPose( 0 ), mControllingObject( NULL ), mMoveMotion( false ), mShapeBaseMount( NULL ), diff --git a/Engine/source/T3D/shapeBase.h b/Engine/source/T3D/shapeBase.h index fcada642b..5a7ff5eb1 100644 --- a/Engine/source/T3D/shapeBase.h +++ b/Engine/source/T3D/shapeBase.h @@ -874,6 +874,7 @@ protected: /// @name Physical Properties /// @{ + S32 mAiPose; ///< Current pose. F32 mEnergy; ///< Current enery level. F32 mRechargeRate; ///< Energy recharge rate (in units/tick). diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 0ca66b32f..78240ce16 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -91,6 +91,9 @@ ConsoleDocClass( TSStatic, ); TSStatic::TSStatic() +: + cubeDescId( 0 ), + reflectorDesc( NULL ) { mNetFlags.set(Ghostable | ScopeAlways); @@ -186,6 +189,11 @@ void TSStatic::initPersistFields() endGroup("Rendering"); + addGroup( "Reflection" ); + addField( "cubeReflectorDesc", TypeRealString, Offset( cubeDescName, TSStatic ), + "References a ReflectorDesc datablock that defines performance and quality properties for dynamic reflections.\n"); + endGroup( "Reflection" ); + addGroup("Collision"); addField( "collisionType", TypeTSMeshType, Offset( mCollisionType, TSStatic ), @@ -292,6 +300,14 @@ bool TSStatic::onAdd() addToScene(); + if ( isClientObject() ) + { + mCubeReflector.unregisterReflector(); + + if ( reflectorDesc ) + mCubeReflector.registerReflector( this, reflectorDesc ); + } + _updateShouldTick(); // Accumulation @@ -357,6 +373,16 @@ bool TSStatic::_createShape() if ( mAmbientThread ) mShapeInstance->setSequence( mAmbientThread, ambientSeq, 0); + // Resolve CubeReflectorDesc. + if ( cubeDescName.isNotEmpty() ) + { + Sim::findObject( cubeDescName, reflectorDesc ); + } + else if( cubeDescId > 0 ) + { + Sim::findObject( cubeDescId, reflectorDesc ); + } + return true; } @@ -429,6 +455,8 @@ void TSStatic::onRemove() mShapeInstance = NULL; mAmbientThread = NULL; + if ( isClientObject() ) + mCubeReflector.unregisterReflector(); Parent::onRemove(); } @@ -561,6 +589,12 @@ void TSStatic::prepRenderImage( SceneRenderState* state ) F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z)); + // If we're currently rendering our own reflection we + // don't want to render ourselves into it. + if ( mCubeReflector.isRendering() ) + return; + + if ( mForceDetail == -1 ) mShapeInstance->setDetailFromDistance( state, dist * invScale ); else @@ -577,6 +611,9 @@ void TSStatic::prepRenderImage( SceneRenderState* state ) rdata.setFadeOverride( 1.0f ); rdata.setOriginSort( mUseOriginSort ); + if ( mCubeReflector.isEnabled() ) + rdata.setCubemap( mCubeReflector.getCubemap() ); + // Acculumation rdata.setAccuTex(mAccuTex); @@ -604,6 +641,20 @@ void TSStatic::prepRenderImage( SceneRenderState* state ) mat.scale( mObjScale ); GFX->setWorldMatrix( mat ); + if ( state->isDiffusePass() && mCubeReflector.isEnabled() && mCubeReflector.getOcclusionQuery() ) + { + RenderPassManager *pass = state->getRenderPass(); + OccluderRenderInst *ri = pass->allocInst(); + + ri->type = RenderPassManager::RIT_Occluder; + ri->query = mCubeReflector.getOcclusionQuery(); + mObjToWorld.mulP( mObjBox.getCenter(), &ri->position ); + ri->scale.set( mObjBox.getExtents() ); + ri->orientation = pass->allocUniqueXform( mObjToWorld ); + ri->isSphere = false; + state->getRenderPass()->addInst( ri ); + } + mShapeInstance->animate(); if(mShapeInstance) { @@ -715,6 +766,10 @@ U32 TSStatic::packUpdate(NetConnection *con, U32 mask, BitStream *stream) if ( mLightPlugin ) retMask |= mLightPlugin->packUpdate(this, AdvancedStaticOptionsMask, con, mask, stream); + if( stream->writeFlag( reflectorDesc != NULL ) ) + { + stream->writeRangedU32( reflectorDesc->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast ); + } return retMask; } @@ -782,6 +837,11 @@ void TSStatic::unpackUpdate(NetConnection *con, BitStream *stream) mLightPlugin->unpackUpdate(this, con, stream); } + if( stream->readFlag() ) + { + cubeDescId = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast ); + } + if ( isProperlyAdded() ) _updateShouldTick(); } diff --git a/Engine/source/T3D/tsStatic.h b/Engine/source/T3D/tsStatic.h index 704cac783..5bf4b5353 100644 --- a/Engine/source/T3D/tsStatic.h +++ b/Engine/source/T3D/tsStatic.h @@ -39,6 +39,10 @@ #include "ts/tsShape.h" #endif +#ifndef _REFLECTOR_H_ + #include "scene/reflector.h" +#endif + class TSShapeInstance; class TSThread; class TSStatic; @@ -147,6 +151,11 @@ protected: /// Start or stop processing ticks depending on our state. void _updateShouldTick(); + String cubeDescName; + U32 cubeDescId; + ReflectorDesc *reflectorDesc; + CubeReflector mCubeReflector; + protected: Convex *mConvexList; diff --git a/Engine/source/app/game.cpp b/Engine/source/app/game.cpp index 4579b4819..2f0e30c77 100644 --- a/Engine/source/app/game.cpp +++ b/Engine/source/app/game.cpp @@ -202,6 +202,26 @@ DefineConsoleFunction( getRealTime, S32, (), , "()" return Platform::getRealMilliseconds(); } +ConsoleFunction( getLocalTime, const char *, 1, 1, "Return the current local time as: weekday month day year hour min sec.\n\n" + "Local time is platform defined.") +{ + Platform::LocalTime lt; + Platform::getLocalTime(lt); + + static const U32 bufSize = 128; + char *retBuffer = Con::getReturnBuffer(bufSize); + dSprintf(retBuffer, bufSize, "%d %d %d %d %02d %02d %02d", + lt.weekday, + lt.month + 1, + lt.monthday, + lt.year + 1900, + lt.hour, + lt.min, + lt.sec); + + return retBuffer; +} + ConsoleFunctionGroupEnd(Platform); //----------------------------------------------------------------------------- diff --git a/Engine/source/app/net/tcpObject.cpp b/Engine/source/app/net/tcpObject.cpp index f2818b426..06f320576 100644 --- a/Engine/source/app/net/tcpObject.cpp +++ b/Engine/source/app/net/tcpObject.cpp @@ -27,6 +27,7 @@ #include "console/consoleInternal.h" #include "core/strings/stringUnit.h" #include "console/engineAPI.h" +#include "core/stream/fileStream.h" TCPObject *TCPObject::table[TCPObject::TableSize] = {0, }; @@ -138,6 +139,15 @@ IMPLEMENT_CALLBACK(TCPObject, onLine, void, (const char* line), (line), "@param line Data sent from the server.\n" ); +IMPLEMENT_CALLBACK(TCPObject, onPacket, bool, (const char* data), (data), + "@brief Called when we get a packet with no newlines or nulls (probably websocket).\n\n" + "@param data Data sent from the server.\n" + "@return true if script handled the packet.\n" + ); +IMPLEMENT_CALLBACK(TCPObject, onEndReceive, void, (), (), + "@brief Called when we are done reading all lines.\n\n" + ); + IMPLEMENT_CALLBACK(TCPObject, onDNSResolved, void, (),(), "Called whenever the DNS has been resolved.\n" ); @@ -355,7 +365,7 @@ void TCPObject::onConnectFailed() onConnectFailed_callback(); } -void TCPObject::finishLastLine() +bool TCPObject::finishLastLine() { if(mBufferSize) { @@ -364,6 +374,25 @@ void TCPObject::finishLastLine() dFree(mBuffer); mBuffer = 0; mBufferSize = 0; + + return true; + } + + return false; +} + +bool TCPObject::isBufferEmpty() +{ + return (mBufferSize <= 0); +} + +void TCPObject::emptyBuffer() +{ + if(mBufferSize) + { + dFree(mBuffer); + mBuffer = 0; + mBufferSize = 0; } } @@ -400,6 +429,25 @@ void TCPObject::send(const U8 *buffer, U32 len) Net::sendtoSocket(mTag, buffer, S32(len)); } +bool TCPObject::sendFile(const char* fileName) +{ + //Open the file for reading + FileStream readFile; + if(!readFile.open(fileName, Torque::FS::File::Read)) + { + return false; + } + + //Read each byte into our buffer + Vector buffer(readFile.getStreamSize()); + readFile.read(buffer.size(), &buffer); + + //Send the buffer + send(buffer.address(), buffer.size()); + + return true; +} + DefineEngineMethod(TCPObject, send, void, (const char *data),, "@brief Transmits the data string to the connected computer.\n\n" @@ -421,6 +469,20 @@ DefineEngineMethod(TCPObject, send, void, (const char *data),, object->send( (const U8*)data, dStrlen(data) ); } +DefineEngineMethod(TCPObject, sendFile, bool, (const char *fileName),, + "@brief Transmits the file in binary to the connected computer.\n\n" + + "@param fileName The filename of the file to transfer.\n") +{ + return object->sendFile(fileName); +} + +DefineEngineMethod(TCPObject, finishLastLine, void, (),, + "@brief Eat the rest of the lines.\n") +{ + object->finishLastLine(); +} + DefineEngineMethod(TCPObject, listen, void, (U32 port),, "@brief Start listening on the specified port for connections.\n\n" @@ -499,6 +561,29 @@ void processConnectedReceiveEvent(NetSocket sock, RawData incomingData) size -= ret; buffer += ret; } + + //If our buffer now has something in it then it's probably a web socket packet and lets handle it + if(!tcpo->isBufferEmpty()) + { + //Copy all the data into a string (may be a quicker way of doing this) + U8 *data = (U8*)incomingData.data; + String temp; + for(S32 i = 0; i < incomingData.size; i++) + { + temp += data[i]; + } + + //Send the packet to script + bool handled = tcpo->onPacket_callback(temp); + + //If the script did something with it, clear the buffer + if(handled) + { + tcpo->emptyBuffer(); + } + } + + tcpo->onEndReceive_callback(); } void processConnectedAcceptEvent(NetSocket listeningPort, NetSocket newConnection, NetAddress originatingAddress) diff --git a/Engine/source/app/net/tcpObject.h b/Engine/source/app/net/tcpObject.h index 9c4582eab..9a8b5e40d 100644 --- a/Engine/source/app/net/tcpObject.h +++ b/Engine/source/app/net/tcpObject.h @@ -36,6 +36,8 @@ public: DECLARE_CALLBACK(void, onConnectionRequest, (const char* address, const char* ID)); DECLARE_CALLBACK(void, onLine, (const char* line)); + DECLARE_CALLBACK(bool, onPacket, (const char* data)); + DECLARE_CALLBACK(void, onEndReceive, ()); DECLARE_CALLBACK(void, onDNSResolved,()); DECLARE_CALLBACK(void, onDNSFailed, ()); DECLARE_CALLBACK(void, onConnected, ()); @@ -60,7 +62,9 @@ public: virtual ~TCPObject(); void parseLine(U8 *buffer, U32 *start, U32 bufferLen); - void finishLastLine(); + bool finishLastLine(); + bool isBufferEmpty(); + void emptyBuffer(); static TCPObject *find(NetSocket tag); @@ -81,6 +85,12 @@ public: bool processArguments(S32 argc, ConsoleValueRef *argv); void send(const U8 *buffer, U32 bufferLen); + + ///Send an entire file over tcp + ///@arg fileName Full path to file you want to send + ///@return true if file was sent, false if not (file doesn't exist) + bool sendFile(const char* fileName); + void addToTable(NetSocket newTag); void removeFromTable(); diff --git a/Engine/source/console/codeBlock.cpp b/Engine/source/console/codeBlock.cpp index 87958c1af..1559f41d8 100644 --- a/Engine/source/console/codeBlock.cpp +++ b/Engine/source/console/codeBlock.cpp @@ -61,7 +61,7 @@ CodeBlock::CodeBlock() CodeBlock::~CodeBlock() { // Make sure we aren't lingering in the current code block... - AssertFatal(smCurrentCodeBlock != this, "CodeBlock::~CodeBlock - Caught lingering in smCurrentCodeBlock!") + AssertFatal(smCurrentCodeBlock != this, "CodeBlock::~CodeBlock - Caught lingering in smCurrentCodeBlock!"); if(name) removeFromCodeList(); diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index 53dcd84ff..be265add8 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -25,6 +25,11 @@ #include "console/consoleInternal.h" #include "console/engineAPI.h" #include "console/ast.h" + +#ifndef _CONSOLFUNCTIONS_H_ +#include "console/consoleFunctions.h" +#endif + #include "core/strings/findMatch.h" #include "core/strings/stringUnit.h" #include "core/strings/unicode.h" @@ -32,7 +37,11 @@ #include "console/compiler.h" #include "platform/platformInput.h" #include "core/util/journal/journal.h" +#include "gfx/gfxEnums.h" #include "core/util/uuid.h" +#include "core/color.h" +#include "math/mPoint3.h" +#include "math/mathTypes.h" // This is a temporary hack to get tools using the library to // link in this module which contains no other references. @@ -41,6 +50,132 @@ bool LinkConsoleFunctions = false; // Buffer for expanding script filenames. static char scriptFilenameBuffer[1024]; +bool isInt(const char* str) +{ + int len = dStrlen(str); + if(len <= 0) + return false; + + // Ignore whitespace + int start = 0; + for(int i = start; i < len; i++) + if(str[i] != ' ') + { + start = i; + break; + } + + for(int i = start; i < len; i++) + switch(str[i]) + { + case '+': case '-': + if(i != 0) + return false; + break; + case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': + break; + case ' ': // ignore whitespace + for(int j = i+1; j < len; j++) + if(str[j] != ' ') + return false; + return true; + break; + default: + return false; + } + return true; +} + +bool isFloat(const char* str, bool sciOk = false) +{ + int len = dStrlen(str); + if(len <= 0) + return false; + + // Ingore whitespace + int start = 0; + for(int i = start; i < len; i++) + if(str[i] != ' ') + { + start = i; + break; + } + + bool seenDot = false; + int eLoc = -1; + for(int i = 0; i < len; i++) + switch(str[i]) + { + case '+': case '-': + if(sciOk) + { + //Haven't found e or scientific notation symbol + if(eLoc == -1) + { + //only allowed in beginning + if(i != 0) + return false; + } + else + { + //if not right after the e + if(i != (eLoc + 1)) + return false; + } + } + else + { + //only allowed in beginning + if(i != 0) + return false; + } + break; + case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': + break; + case 'e': case 'E': + if(!sciOk) + return false; + else + { + //already saw it so can't have 2 + if(eLoc != -1) + return false; + + eLoc = i; + } + break; + case '.': + if(seenDot | (sciOk && eLoc != -1)) + return false; + seenDot = true; + break; + case ' ': // ignore whitespace + for(int j = i+1; j < len; j++) + if(str[j] != ' ') + return false; + return true; + break; + default: + return false; + } + return true; +} + +bool isValidIP(const char* ip) +{ + unsigned b1, b2, b3, b4; + unsigned char c; + int rc = dSscanf(ip, "%3u.%3u.%3u.%3u%c", &b1, &b2, &b3, &b4, &c); + if (rc != 4 && rc != 5) return false; + if ((b1 | b2 | b3 | b4) > 255) return false; + if (dStrspn(ip, "0123456789.") < dStrlen(ip)) return false; + return true; +} + +bool isValidPort(U16 port) +{ + return (port >= 0 && port <=65535); +} //============================================================================= // String Functions. @@ -235,6 +370,40 @@ DefineConsoleFunction( strlen, S32, ( const char* str ),, return dStrlen( str ); } +//----------------------------------------------------------------------------- +DefineConsoleFunction( strlenskip, S32, ( const char* str, const char* first, const char* last ),, + "Calculate the length of a string in characters, skipping everything between and including first and last.\n" + "@param str A string.\n" + "@param first First character to look for to skip block of text.\n" + "@param last Second character to look for to skip block of text.\n" + "@return The length of the given string skipping blocks of text between characters.\n" + "@ingroup Strings" ) +{ + const UTF8* pos = str; + U32 size = 0; + U32 length = dStrlen(str); + bool count = true; + + //loop through each character counting each character, skipping tags (anything with < followed by >) + for(U32 i = 0; i < length; i++, pos++) + { + if(count) + { + if(*pos == first[0]) + count = false; + else + size++; + } + else + { + if(*pos == last[0]) + count = true; + } + } + + return S32(size); +} + //----------------------------------------------------------------------------- DefineConsoleFunction( strstr, S32, ( const char* string, const char* substring ),, @@ -281,6 +450,33 @@ DefineConsoleFunction( strpos, S32, ( const char* haystack, const char* needle, //----------------------------------------------------------------------------- +DefineConsoleFunction( strposr, S32, ( const char* haystack, const char* needle, S32 offset ), ( 0 ), + "Find the start of @a needle in @a haystack searching from right to left beginning at the given offset.\n" + "@param haystack The string to search.\n" + "@param needle The string to search for.\n" + "@return The index at which the first occurrence of @a needle was found in @a heystack or -1 if no match was found.\n\n" + "@tsexample\n" + "strposr( \"b ab\", \"b\", 1 ) // Returns 2.\n" + "@endtsexample\n" + "@ingroup Strings" ) +{ + U32 sublen = dStrlen( needle ); + U32 strlen = dStrlen( haystack ); + S32 start = strlen - offset; + + if(start < 0 || start > strlen) + return -1; + + if (start + sublen > strlen) + start = strlen - sublen; + for(; start >= 0; start--) + if(!dStrncmp(haystack + start, needle, sublen)) + return start; + return -1; +} + +//----------------------------------------------------------------------------- + DefineConsoleFunction( ltrim, const char*, ( const char* str ),, "Remove leading whitespace from the string.\n" "@param str A string.\n" @@ -627,6 +823,18 @@ DefineConsoleFunction( stripTrailingNumber, String, ( const char* str ),, return String::GetTrailingNumber( str, suffix ); } +//----------------------------------------------------------------------------- + +DefineConsoleFunction( getFirstNumber, String, ( const char* str ),, + "Get the first occuring number from @a str.\n" + "@param str The string from which to read out the first number.\n" + "@return String representation of the number or "" if no number.\n\n") +{ + U32 start; + U32 end; + return String::GetFirstNumber(str, start, end); +} + //---------------------------------------------------------------- DefineConsoleFunction( isspace, bool, ( const char* str, S32 index ),, @@ -811,6 +1019,192 @@ DefineConsoleFunction( strrchrpos, S32, ( const char* str, const char* chr, S32 return index; } +//---------------------------------------------------------------- + +DefineConsoleFunction(ColorFloatToInt, ColorI, (ColorF color), , + "Convert from a float color to an integer color (0.0 - 1.0 to 0 to 255).\n" + "@param color Float color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha.\n" + "@return Converted color value (0 - 255)\n\n" + "@tsexample\n" + "ColorFloatToInt( \"0 0 1 0.5\" ) // Returns \"0 0 255 128\".\n" + "@endtsexample\n" + "@ingroup Strings") +{ + return (ColorI)color; +} + +DefineConsoleFunction(ColorIntToFloat, ColorF, (ColorI color), , + "Convert from a integer color to an float color (0 to 255 to 0.0 - 1.0).\n" + "@param color Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha.\n" + "@return Converted color value (0.0 - 1.0)\n\n" + "@tsexample\n" + "ColorIntToFloat( \"0 0 255 128\" ) // Returns \"0 0 1 0.5\".\n" + "@endtsexample\n" + "@ingroup Strings") +{ + return (ColorF)color; +} + +DefineConsoleFunction(ColorRGBToHEX, const char*, (ColorI color), , + "Convert from a integer RGB (red, green, blue) color to hex color value (0 to 255 to 00 - FF).\n" + "@param color Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha. It excepts an alpha, but keep in mind this will not be converted.\n" + "@return Hex color value (#000000 - #FFFFFF), alpha isn't handled/converted so it is only the RGB value\n\n" + "@tsexample\n" + "ColorRBGToHEX( \"0 0 255 128\" ) // Returns \"#0000FF\".\n" + "@endtsexample\n" + "@ingroup Strings") +{ + return Con::getReturnBuffer(color.getHex()); +} + +DefineConsoleFunction(ColorRGBToHSB, const char*, (ColorI color), , + "Convert from a integer RGB (red, green, blue) color to HSB (hue, saturation, brightness). HSB is also know as HSL or HSV as well, with the last letter standing for lightness or value.\n" + "@param color Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha. It excepts an alpha, but keep in mind this will not be converted.\n" + "@return HSB color value, alpha isn't handled/converted so it is only the RGB value\n\n" + "@tsexample\n" + "ColorRBGToHSB( \"0 0 255 128\" ) // Returns \"240 100 100\".\n" + "@endtsexample\n" + "@ingroup Strings") +{ + ColorI::Hsb hsb(color.getHSB()); + String s(String::ToString(hsb.hue) + " " + String::ToString(hsb.sat) + " " + String::ToString(hsb.brightness)); + return Con::getReturnBuffer(s); +} + +DefineConsoleFunction(ColorHEXToRGB, ColorI, (const char* hex), , + "Convert from a hex color value to an integer RGB (red, green, blue) color (00 - FF to 0 to 255).\n" + "@param hex Hex color value (#000000 - #FFFFFF) to be converted to an RGB (red, green, blue) value.\n" + "@return Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha. Alpha isn't handled/converted so only pay attention to the RGB value\n\n" + "@tsexample\n" + "ColorHEXToRGB( \"#0000FF\" ) // Returns \"0 0 255 0\".\n" + "@endtsexample\n" + "@ingroup Strings") +{ + S32 rgb = dAtoui(hex, 16); + + ColorI color; + color.set(rgb & 0x000000FF, (rgb & 0x0000FF00) >> 8, (rgb & 0x00FF0000) >> 16); + return color; +} + +DefineConsoleFunction(ColorHSBToRGB, ColorI, (Point3I hsb), , + "Convert from a HSB (hue, saturation, brightness) to an integer RGB (red, green, blue) color. HSB is also know as HSL or HSV as well, with the last letter standing for lightness or value.\n" + "@param hsb HSB (hue, saturation, brightness) value to be converted.\n" + "@return Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha. Alpha isn't handled/converted so only pay attention to the RGB value\n\n" + "@tsexample\n" + "ColorHSBToRGB( \"240 100 100\" ) // Returns \"0 0 255 0\".\n" + "@endtsexample\n" + "@ingroup Strings") +{ + ColorI color; + color.set(ColorI::Hsb(hsb.x, hsb.y, hsb.z)); + return color; +} + +//---------------------------------------------------------------- + +DefineConsoleFunction( strToggleCaseToWords, const char*, ( const char* str ),, + "Parse a Toggle Case word into separate words.\n" + "@param str The string to parse.\n" + "@return new string space separated.\n\n" + "@tsexample\n" + "strToggleCaseToWords( \"HelloWorld\" ) // Returns \"Hello World\".\n" + "@endtsexample\n" + "@ingroup Strings" ) +{ + String newStr; + for(S32 i = 0; str[i]; i++) + { + //If capitol add a space + if(i != 0 && str[i] >= 65 && str[i] <= 90) + newStr += " "; + + newStr += str[i]; + } + + return Con::getReturnBuffer(newStr); +} + +//---------------------------------------------------------------- + +// Warning: isInt and isFloat are very 'strict' and might need to be adjusted to allow other values. //seanmc +DefineConsoleFunction( isInt, bool, ( const char* str),, + "Returns true if the string is an integer.\n" + "@param str The string to test.\n" + "@return true if @a str is an integer and false if not\n\n" + "@tsexample\n" + "isInt( \"13\" ) // Returns true.\n" + "@endtsexample\n" + "@ingroup Strings" ) +{ + return isInt(str); +} + +//---------------------------------------------------------------- + +DefineConsoleFunction( isFloat, bool, ( const char* str, bool sciOk), (false), + "Returns true if the string is a float.\n" + "@param str The string to test.\n" + "@param sciOk Test for correct scientific notation and accept it (ex. 1.2e+14)" + "@return true if @a str is a float and false if not\n\n" + "@tsexample\n" + "isFloat( \"13.5\" ) // Returns true.\n" + "@endtsexample\n" + "@ingroup Strings" ) +{ + return isFloat(str, sciOk); +} + +//---------------------------------------------------------------- + +DefineConsoleFunction( isValidPort, bool, ( const char* str),, + "Returns true if the string is a valid port number.\n" + "@param str The string to test.\n" + "@return true if @a str is a port and false if not\n\n" + "@tsexample\n" + "isValidPort( \"8080\" ) // Returns true.\n" + "@endtsexample\n" + "@ingroup Strings" ) +{ + if(isInt(str)) + { + U16 port = dAtous(str); + return isValidPort(port); + } + else + return false; +} + +//---------------------------------------------------------------- + +DefineConsoleFunction( isValidIP, bool, ( const char* str),, + "Returns true if the string is a valid ip address, excepts localhost.\n" + "@param str The string to test.\n" + "@return true if @a str is a valid ip address and false if not\n\n" + "@tsexample\n" + "isValidIP( \"localhost\" ) // Returns true.\n" + "@endtsexample\n" + "@ingroup Strings" ) +{ + if(dStrcmp(str, "localhost") == 0) + { + return true; + } + else + return isValidIP(str); +} + +//---------------------------------------------------------------- + +// Torque won't normally add another string if it already exists with another casing, +// so this forces the addition. It should be called once near the start, such as in main.cs. +ConsoleFunction(addCaseSensitiveStrings,void,2,0,"[string1, string2, ...]" + "Adds case sensitive strings to the StringTable.") +{ + for(int i = 1; i < argc; i++) + StringTable->insert(argv[i], true); +} + //============================================================================= // Field Manipulators. //============================================================================= @@ -829,6 +1223,7 @@ DefineConsoleFunction( getWord, const char*, ( const char* text, S32 index ),, "@endtsexample\n\n" "@see getWords\n" "@see getWordCount\n" + "@see getToken\n" "@see getField\n" "@see getRecord\n" "@ingroup FieldManip" ) @@ -852,6 +1247,7 @@ DefineConsoleFunction( getWords, const char*, ( const char* text, S32 startIndex "@endtsexample\n\n" "@see getWord\n" "@see getWordCount\n" + "@see getTokens\n" "@see getFields\n" "@see getRecords\n" "@ingroup FieldManip" ) @@ -876,6 +1272,7 @@ DefineConsoleFunction( setWord, const char*, ( const char* text, S32 index, cons "setWord( \"a b c d\", 2, \"f\" ) // Returns \"a b f d\"\n" "@endtsexample\n\n" "@see getWord\n" + "@see setToken\n" "@see setField\n" "@see setRecord\n" "@ingroup FieldManip" ) @@ -895,6 +1292,7 @@ DefineConsoleFunction( removeWord, const char*, ( const char* text, S32 index ), "@tsexample\n" "removeWord( \"a b c d\", 2 ) // Returns \"a b d\"\n" "@endtsexample\n\n" + "@see removeToken\n" "@see removeField\n" "@see removeRecord\n" "@ingroup FieldManip" ) @@ -912,6 +1310,7 @@ DefineConsoleFunction( getWordCount, S32, ( const char* text ),, "@tsexample\n" "getWordCount( \"a b c d e\" ) // Returns 5\n" "@endtsexample\n\n" + "@see getTokenCount\n" "@see getFieldCount\n" "@see getRecordCount\n" "@ingroup FieldManip" ) @@ -921,6 +1320,49 @@ DefineConsoleFunction( getWordCount, S32, ( const char* text ),, //----------------------------------------------------------------------------- +DefineEngineFunction( monthNumToStr, String, ( S32 num, bool abbreviate ), (false), + "@brief returns month as a word given a number or \"\" if number is bad" + "@return month as a word given a number or \"\" if number is bad" + "@ingroup FileSystem") +{ + switch(num) + { + case 1: return abbreviate ? "Jan" : "January"; break; + case 2: return abbreviate ? "Feb" : "February"; break; + case 3: return abbreviate ? "Mar" : "March"; break; + case 4: return abbreviate ? "Apr" : "April"; break; + case 5: return "May"; break; + case 6: return abbreviate ? "Jun" : "June"; break; + case 7: return abbreviate ? "Jul" : "July"; break; + case 8: return abbreviate ? "Aug" : "August"; break; + case 9: return abbreviate ? "Sep" : "September"; break; + case 10: return abbreviate ? "Oct" : "October"; break; + case 11: return abbreviate ? "Nov" : "November"; break; + case 12: return abbreviate ? "Dec" : "December"; break; + default: return ""; + } +} + +DefineEngineFunction( weekdayNumToStr, String, ( S32 num, bool abbreviate ), (false), + "@brief returns weekday as a word given a number or \"\" if number is bad" + "@return weekday as a word given a number or \"\" if number is bad" + "@ingroup FileSystem") +{ + switch(num) + { + case 0: return abbreviate ? "Sun" : "Sunday"; break; + case 1: return abbreviate ? "Mon" : "Monday"; break; + case 2: return abbreviate ? "Tue" : "Tuesday"; break; + case 3: return abbreviate ? "Wed" : "Wednesday"; break; + case 4: return abbreviate ? "Thu" : "Thursday"; break; + case 5: return abbreviate ? "Fri" : "Friday"; break; + case 6: return abbreviate ? "Sat" : "Saturday"; break; + default: return ""; + } +} + +//----------------------------------------------------------------------------- + DefineConsoleFunction( getField, const char*, ( const char* text, S32 index ),, "Extract the field at the given @a index in the newline and/or tab separated list in @a text.\n" "Fields in @a text must be separated by newlines and/or tabs.\n" @@ -1242,6 +1684,114 @@ DefineConsoleFunction( nextToken, const char*, ( const char* str1, const char* t return ret; } +//----------------------------------------------------------------------------- + +DefineConsoleFunction( getToken, const char*, ( const char* text, const char* delimiters, S32 index ),, + "Extract the substring at the given @a index in the @a delimiters separated list in @a text.\n" + "@param text A @a delimiters list of substrings.\n" + "@param delimiters Character or characters that separate the list of substrings in @a text.\n" + "@param index The zero-based index of the substring to extract.\n" + "@return The substring at the given index or \"\" if the index is out of range.\n\n" + "@tsexample\n" + "getToken( \"a b c d\", \" \", 2 ) // Returns \"c\"\n" + "@endtsexample\n\n" + "@see getTokens\n" + "@see getTokenCount\n" + "@see getWord\n" + "@see getField\n" + "@see getRecord\n" + "@ingroup FieldManip" ) +{ + return Con::getReturnBuffer( StringUnit::getUnit(text, index, delimiters)); +} + +//----------------------------------------------------------------------------- + +DefineConsoleFunction( getTokens, const char*, ( const char* text, const char* delimiters, S32 startIndex, S32 endIndex ), ( -1 ), + "Extract a range of substrings separated by @a delimiters at the given @a startIndex onwards thru @a endIndex.\n" + "@param text A @a delimiters list of substrings.\n" + "@param delimiters Character or characters that separate the list of substrings in @a text.\n" + "@param startIndex The zero-based index of the first substring to extract from @a text.\n" + "@param endIndex The zero-based index of the last substring to extract from @a text. If this is -1, all words beginning " + "with @a startIndex are extracted from @a text.\n" + "@return A string containing the specified range of substrings from @a text or \"\" if @a startIndex " + "is out of range or greater than @a endIndex.\n\n" + "@tsexample\n" + "getTokens( \"a b c d\", \" \", 1, 2, ) // Returns \"b c\"\n" + "@endtsexample\n\n" + "@see getToken\n" + "@see getTokenCount\n" + "@see getWords\n" + "@see getFields\n" + "@see getRecords\n" + "@ingroup FieldManip" ) +{ + if( endIndex < 0 ) + endIndex = 1000000; + + return Con::getReturnBuffer( StringUnit::getUnits( text, startIndex, endIndex, delimiters ) ); +} + +//----------------------------------------------------------------------------- + +DefineConsoleFunction( setToken, const char*, ( const char* text, const char* delimiters, S32 index, const char* replacement ),, + "Replace the substring in @a text separated by @a delimiters at the given @a index with @a replacement.\n" + "@param text A @a delimiters list of substrings.\n" + "@param delimiters Character or characters that separate the list of substrings in @a text.\n" + "@param index The zero-based index of the substring to replace.\n" + "@param replacement The string with which to replace the substring.\n" + "@return A new string with the substring at the given @a index replaced by @a replacement or the original " + "string if @a index is out of range.\n\n" + "@tsexample\n" + "setToken( \"a b c d\", \" \", 2, \"f\" ) // Returns \"a b f d\"\n" + "@endtsexample\n\n" + "@see getToken\n" + "@see setWord\n" + "@see setField\n" + "@see setRecord\n" + "@ingroup FieldManip" ) +{ + return Con::getReturnBuffer( StringUnit::setUnit( text, index, replacement, delimiters) ); +} + +//----------------------------------------------------------------------------- + +DefineConsoleFunction( removeToken, const char*, ( const char* text, const char* delimiters, S32 index ),, + "Remove the substring in @a text separated by @a delimiters at the given @a index.\n" + "@param text A @a delimiters list of substrings.\n" + "@param delimiters Character or characters that separate the list of substrings in @a text.\n" + "@param index The zero-based index of the word in @a text.\n" + "@return A new string with the substring at the given index removed or the original string if @a index is " + "out of range.\n\n" + "@tsexample\n" + "removeToken( \"a b c d\", \" \", 2 ) // Returns \"a b d\"\n" + "@endtsexample\n\n" + "@see removeWord\n" + "@see removeField\n" + "@see removeRecord\n" + "@ingroup FieldManip" ) +{ + return Con::getReturnBuffer( StringUnit::removeUnit( text, index, delimiters ) ); +} + +//----------------------------------------------------------------------------- + +DefineConsoleFunction( getTokenCount, S32, ( const char* text, const char* delimiters),, + "Return the number of @a delimiters substrings in @a text.\n" + "@param text A @a delimiters list of substrings.\n" + "@param delimiters Character or characters that separate the list of substrings in @a text.\n" + "@return The number of @a delimiters substrings in @a text.\n\n" + "@tsexample\n" + "getTokenCount( \"a b c d e\", \" \" ) // Returns 5\n" + "@endtsexample\n\n" + "@see getWordCount\n" + "@see getFieldCount\n" + "@see getRecordCount\n" + "@ingroup FieldManip" ) +{ + return StringUnit::getUnitCount( text, delimiters ); +} + //============================================================================= // Tagged Strings. //============================================================================= @@ -2597,3 +3147,10 @@ DefineEngineFunction( isToolBuild, bool, (),, return false; #endif } + +DefineEngineFunction( getMaxDynamicVerts, S32, (),, + "Get max number of allowable dynamic vertices in a single vertex buffer.\n\n" + "@return the max number of allowable dynamic vertices in a single vertex buffer" ) +{ + return MAX_DYNAMIC_VERTS / 2; +} diff --git a/Engine/source/console/consoleFunctions.h b/Engine/source/console/consoleFunctions.h new file mode 100644 index 000000000..1cb19d1df --- /dev/null +++ b/Engine/source/console/consoleFunctions.h @@ -0,0 +1,16 @@ +#ifndef _CONSOLFUNCTIONS_H_ +#define _CONSOLFUNCTIONS_H_ + +#ifndef _STRINGFUNCTIONS_H_ +#include "core/strings/stringFunctions.h" +#endif + +bool isInt(const char* str); + +bool isFloat(const char* str); + +bool isValidIP(const char* ip); + +bool isValidPort(U16 port); + +#endif \ No newline at end of file diff --git a/Engine/source/console/consoleObject.h b/Engine/source/console/consoleObject.h index 5e585247e..8ecbb8031 100644 --- a/Engine/source/console/consoleObject.h +++ b/Engine/source/console/consoleObject.h @@ -48,7 +48,7 @@ #include "console/simObjectRef.h" #endif #ifndef TINYXML_INCLUDED - #include "tinyXML/tinyxml.h" + #include "tinyxml.h" #endif /// @file @@ -212,7 +212,7 @@ public: /// /// @param conIdPtr Pointer to the static S32 console ID. /// @param conTypeName Console type name. - AbstractClassRep( S32* conIdPtr, const char* typeName ) + AbstractClassRep( S32* conIdPtr, const char* typeName ) : Parent( sizeof( void* ), conIdPtr, typeName ) { VECTOR_SET_ASSOCIATION( mFieldList ); @@ -323,13 +323,13 @@ public: /// Return the namespace that contains the methods of this class. Namespace* getNameSpace() const { return mNamespace; } - + /// Return the AbstractClassRep of the class that this class is derived from. AbstractClassRep* getParentClass() const { return parentClass; } virtual AbstractClassRep* getContainerChildClass(const bool recurse) = 0; virtual WriteCustomTamlSchema getCustomTamlSchema(void) = 0; - + /// Return the size of instances of this class in bytes. S32 getSizeof() const { return mClassSizeof; } @@ -396,7 +396,7 @@ protected: Namespace * mNamespace; /// @} - + public: bool mIsRenderEnabled; @@ -404,23 +404,23 @@ public: bool isRenderEnabled() const { return mIsRenderEnabled; } bool isSelectionEnabled() const { return mIsSelectionEnabled; } - + /// @name Categories /// @{ - + protected: const char* mCategory; const char* mDescription; - + public: /// Return the space separated category path for the class. const char* getCategory() const { return mCategory; } - + /// Return a short description string suitable for displaying in tooltips. const char* getDescription() const { return mDescription; } - + /// @} /// @name Fields @@ -434,16 +434,12 @@ public: /// This is a function pointer typedef to support optional writing for fields. typedef bool(*WriteDataNotify)(void* obj, StringTableEntry pFieldName); - /// Allows the writing of a custom TAML schema. - typedef void(*WriteCustomTamlSchema)(const AbstractClassRep* pClassRep, TiXmlElement* pParentElement); - - /// These are special field type values used to mark /// groups and arrays in the field list. /// @see Field::type /// @see addArray, endArray - /// @see addGroup, endGroup - /// @see addGroup, endGroup + /// @see addGroup, endGroup + /// @see addGroup, endGroup /// @see addDeprecatedField enum ACRFieldTypes { @@ -451,35 +447,35 @@ public: /// types greater or equal to this one are not /// console data types. ARCFirstCustomField = 0xFFFFFFFB, - + /// Marks the start of a fixed size array of fields. /// @see addArray StartArrayFieldType = 0xFFFFFFFB, - + /// Marks the end of a fixed size array of fields. /// @see endArray EndArrayFieldType = 0xFFFFFFFC, - + /// Marks the beginning of a group of fields. /// @see addGroup StartGroupFieldType = 0xFFFFFFFD, - + /// Marks the beginning of a group of fields. /// @see endGroup EndGroupFieldType = 0xFFFFFFFE, - - /// Marks a field that is depreciated and no + + /// Marks a field that is depreciated and no /// longer stores a value. /// @see addDeprecatedField DeprecatedFieldType = 0xFFFFFFFF }; - + enum FieldFlags { FIELD_HideInInspectors = BIT( 0 ), ///< Do not show the field in inspectors. }; - struct Field + struct Field { Field() : pFieldname( NULL ), @@ -525,10 +521,10 @@ public: /// @name Console Type Interface /// @{ - + virtual void* getNativeVariable() { return new ( AbstractClassRep* ); } // Any pointer-sized allocation will do. virtual void deleteNativeVariable( void* var ) { delete reinterpret_cast< AbstractClassRep** >( var ); } - + /// @} /// @name Abstract Class Database @@ -571,122 +567,141 @@ extern AbstractClassRep::FieldList sg_tempFieldList; /// @see AbtractClassRep /// @see ConsoleObject template< class T > -class ConcreteClassRep : public AbstractClassRep +class ConcreteAbstractClassRep : public AbstractClassRep { - public: - - static EnginePropertyTable _smPropertyTable; - static EnginePropertyTable& smPropertyTable; - - ConcreteClassRep( const char* name, - const char* conTypeName, - S32* conTypeIdPtr, - S32 netClassGroupMask, - S32 netClassType, - S32 netEventDir, - AbstractClassRep* parent, - const char* ( *parentDesc )() ) - : AbstractClassRep( conTypeIdPtr, conTypeName ) +public: + + virtual AbstractClassRep* getContainerChildClass(const bool recurse) + { + // Fetch container children type. + AbstractClassRep* pChildren = T::getContainerChildStaticClassRep(); + if (!recurse || pChildren != NULL) + return pChildren; + + // Fetch parent type. + AbstractClassRep* pParent = T::getParentStaticClassRep(); + if (pParent == NULL) + return NULL; + + // Get parent container children. + return pParent->getContainerChildClass(recurse); + } + + virtual WriteCustomTamlSchema getCustomTamlSchema(void) + { + return T::getStaticWriteCustomTamlSchema(); + } + + static EnginePropertyTable _smPropertyTable; + static EnginePropertyTable& smPropertyTable; + + ConcreteAbstractClassRep(const char* name, + const char* conTypeName, + S32* conTypeIdPtr, + S32 netClassGroupMask, + S32 netClassType, + S32 netEventDir, + AbstractClassRep* parent, + const char* (*parentDesc)()) + : AbstractClassRep(conTypeIdPtr, conTypeName) + { + mClassName = StringTable->insert(name); + mCategory = T::__category(); + mTypeInfo = _MAPTYPE< T >(); + + if (mTypeInfo) + const_cast< EngineTypeInfo* >(mTypeInfo)->mPropertyTable = &smPropertyTable; + + if (&T::__description != parentDesc) + mDescription = T::__description(); + + // Clean up mClassId + for (U32 i = 0; i < NetClassGroupsCount; i++) + mClassId[i] = -1; + + // Set properties for this ACR + mClassType = netClassType; + mClassGroupMask = netClassGroupMask; + mNetEventDir = netEventDir; + parentClass = parent; + mClassSizeof = sizeof(T); + + // Finally, register ourselves. + registerClassRep(this); + }; + + /// Wrap constructor. + ConsoleObject* create() const { return NULL; } + + /// Perform class specific initialization tasks. + /// + /// Link namespaces, call initPersistFields() and consoleInit(). + void init() + { + // Get handle to our parent class, if any, and ourselves (we are our parent's child). + AbstractClassRep *parent = T::getParentStaticClassRep(); + AbstractClassRep *child = T::getStaticClassRep(); + + // If we got reps, then link those namespaces! (To get proper inheritance.) + if (parent && child) + Con::classLinkNamespaces(parent->getNameSpace(), child->getNameSpace()); + + // Finally, do any class specific initialization... + T::initPersistFields(); + T::consoleInit(); + + // Let the base finish up. + AbstractClassRep::init(); + } + + /// @name Console Type Interface + /// @{ + + virtual void setData(void* dptr, S32 argc, const char** argv, const EnumTable* tbl, BitSet32 flag) + { + if (argc == 1) { - mClassName = StringTable->insert( name ); - mCategory = T::__category(); - mTypeInfo = _MAPTYPE< T >(); - - if( mTypeInfo ) - const_cast< EngineTypeInfo* >( mTypeInfo )->mPropertyTable = &smPropertyTable; - - if( &T::__description != parentDesc ) - mDescription = T::__description(); - - // Clean up mClassId - for(U32 i = 0; i < NetClassGroupsCount; i++) - mClassId[i] = -1; - - // Set properties for this ACR - mClassType = netClassType; - mClassGroupMask = netClassGroupMask; - mNetEventDir = netEventDir; - parentClass = parent; - mClassSizeof = sizeof(T); - - // Finally, register ourselves. - registerClassRep(this); - }; - - virtual AbstractClassRep* getContainerChildClass(const bool recurse) - { - // Fetch container children type. - AbstractClassRep* pChildren = T::getContainerChildStaticClassRep(); - if (!recurse || pChildren != NULL) - return pChildren; - - // Fetch parent type. - AbstractClassRep* pParent = T::getParentStaticClassRep(); - if (pParent == NULL) - return NULL; - - // Get parent container children. - return pParent->getContainerChildClass(recurse); + T** obj = (T**)dptr; + *obj = dynamic_cast< T* >(T::__findObject(argv[0])); } + else + Con::errorf("Cannot set multiple args to a single ConsoleObject*."); + } + + virtual const char* getData(void* dptr, const EnumTable* tbl, BitSet32 flag) + { + T** obj = (T**)dptr; + return Con::getReturnBuffer(T::__getObjectId(*obj)); + } + + virtual const char* getTypeClassName() { return mClassName; } + virtual const bool isDatablock() { return T::__smIsDatablock; }; - virtual WriteCustomTamlSchema getCustomTamlSchema(void) - { - return T::getStaticWriteCustomTamlSchema(); - } - - /// Perform class specific initialization tasks. - /// - /// Link namespaces, call initPersistFields() and consoleInit(). - void init() - { - // Get handle to our parent class, if any, and ourselves (we are our parent's child). - AbstractClassRep *parent = T::getParentStaticClassRep(); - AbstractClassRep *child = T::getStaticClassRep(); - - // If we got reps, then link those namespaces! (To get proper inheritance.) - if(parent && child) - Con::classLinkNamespaces(parent->getNameSpace(), child->getNameSpace()); - - // Finally, do any class specific initialization... - T::initPersistFields(); - T::consoleInit(); - - // Let the base finish up. - AbstractClassRep::init(); - } - - /// Wrap constructor. - ConsoleObject* create() const { return new T; } - - /// @name Console Type Interface - /// @{ - - virtual void setData( void* dptr, S32 argc, const char** argv, const EnumTable* tbl, BitSet32 flag ) - { - if( argc == 1 ) - { - T** obj = ( T** ) dptr; - *obj = dynamic_cast< T* >( T::__findObject( argv[ 0 ] ) ); - } - else - Con::errorf( "Cannot set multiple args to a single ConsoleObject*."); - } - - virtual const char* getData( void* dptr, const EnumTable* tbl, BitSet32 flag ) - { - T** obj = ( T** ) dptr; - return Con::getReturnBuffer( T::__getObjectId( *obj ) ); - } - - virtual const char* getTypeClassName() { return mClassName; } - virtual const bool isDatablock() { return T::__smIsDatablock; }; - - /// @} + /// @} + }; + + template< class T > + class ConcreteClassRep : public ConcreteAbstractClassRep + { + public: + ConcreteClassRep(const char* name, + const char* conTypeName, + S32* conTypeIdPtr, + S32 netClassGroupMask, + S32 netClassType, + S32 netEventDir, + AbstractClassRep* parent, + const char* (*parentDesc)()) + : ConcreteAbstractClassRep(name, conTypeName, conTypeIdPtr, netClassGroupMask, netClassType, netEventDir, parent, parentDesc) + { + } + + /// Wrap constructor. + ConsoleObject* create() const { return new T; } }; -template< typename T > EnginePropertyTable ConcreteClassRep< T >::_smPropertyTable( 0, NULL ); -template< typename T > EnginePropertyTable& ConcreteClassRep< T >::smPropertyTable = ConcreteClassRep< T >::_smPropertyTable; - +template< typename T > EnginePropertyTable ConcreteAbstractClassRep< T >::_smPropertyTable(0, NULL); +template< typename T > EnginePropertyTable& ConcreteAbstractClassRep< T >::smPropertyTable = ConcreteAbstractClassRep< T >::_smPropertyTable; //------------------------------------------------------------------------------ // Forward declaration of this function so it can be used in the class @@ -751,7 +766,7 @@ bool defaultProtectedWriteFn(void* obj, StringTableEntry pFieldName); class ConsoleObject : public EngineObject { DECLARE_ABSTRACT_CLASS( ConsoleObject, EngineObject ); - + protected: /// @deprecated This is disallowed. @@ -760,16 +775,25 @@ protected: public: ConsoleObject() {} - + /// Get a reference to a field by name. const AbstractClassRep::Field *findField(StringTableEntry fieldName) const; /// Gets the ClassRep. virtual AbstractClassRep* getClassRep() const; +#define DECLARE_ABSTRACT_CONOBJECT( className ) \ + DECLARE_ABSTRACT_CLASS( className, Parent ); \ + static S32 _smTypeId; \ + static ConcreteAbstractClassRep< className > dynClassRep; \ + static AbstractClassRep* getParentStaticClassRep(); \ + static AbstractClassRep* getStaticClassRep(); \ + static SimObjectRefConsoleBaseType< className > ptrRefType; \ + virtual AbstractClassRep* getClassRep() const + /// Set the value of a field. bool setField(const char *fieldName, const char *value); - + public: /// @name Object Creation @@ -799,11 +823,11 @@ public: static void endGroup(const char* in_pGroupname); /// Marks the start of a fixed size array of fields. - /// @see console_autodoc + /// @see console_autodoc static void addArray( const char *arrayName, S32 count ); /// Marks the end of an array of fields. - /// @see console_autodoc + /// @see console_autodoc static void endArray( const char *arrayName ); /// Register a complex field. @@ -928,16 +952,16 @@ public: static bool removeField(const char* in_pFieldname); /// @} - + /// @name Logging /// @{ - + /// Overload this in subclasses to change the message formatting. /// @param fmt A printf style format string. /// @param args A va_list containing the args passed ot a log function. /// @note It is suggested that you use String::VToString. virtual String _getLogMessage(const char* fmt, va_list args) const; - + /// @} public: @@ -946,16 +970,16 @@ public: /// These functions will try to print out a message along the lines /// of "ObjectClass - ObjectName(ObjectId) - formatted message" /// @{ - + /// Logs with Con::printf. void logMessage(const char* fmt, ...) const; - + /// Logs with Con::warnf. void logWarning(const char* fmt, ...) const; - + /// Logs with Con::errorf. void logError(const char* fmt, ...) const; - + /// @} /// Register dynamic fields in a subclass of ConsoleObject. @@ -1016,16 +1040,16 @@ public: static const char* __category() { return ""; } static const char* __description() { return ""; } - + /// Subclasses of ConsoleObjects that are datablocks should redefine this static member variable /// and set it to true. static const bool __smIsDatablock = false; - + /// @name Object IDs and lookup. /// For a subclass hierarchy based on ConsoleObject to become functional for use as a console object type, /// the hierarchy must implement a naming scheme and indexing function for looking up objects by name. /// @{ - + static ConsoleObject* __findObject( const char* ) { return NULL; } static const char* __getObjectId( ConsoleObject* ) { return ""; } }; @@ -1120,11 +1144,11 @@ inline bool& ConsoleObject::getDynamicGroupExpand() static SimObjectRefConsoleBaseType< className > ptrRefType; \ static AbstractClassRep::WriteCustomTamlSchema getStaticWriteCustomTamlSchema(); \ static AbstractClassRep* getContainerChildStaticClassRep(); \ - virtual AbstractClassRep* getClassRep() const - + virtual AbstractClassRep* getClassRep() const + #define DECLARE_CATEGORY( string ) \ static const char* __category() { return string; } - + #define DECLARE_DESCRIPTION( string ) \ static const char* __description() { return string; } @@ -1140,7 +1164,7 @@ inline bool& ConsoleObject::getDynamicGroupExpand() AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \ ConcreteClassRep className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description ) -#define IMPLEMENT_CONOBJECT_CHILDREN( className ) \ +#define IMPLEMENT_CONOBJECT_CHILDREN( className ) \ IMPLEMENT_CLASS( className, NULL ) \ END_IMPLEMENT_CLASS; \ S32 className::_smTypeId; \ @@ -1148,11 +1172,11 @@ inline bool& ConsoleObject::getDynamicGroupExpand() AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \ AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \ AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \ - AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); } \ + AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); } \ AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \ ConcreteClassRep className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description ) -#define IMPLEMENT_CONOBJECT_SCHEMA( className, schema ) \ +#define IMPLEMENT_CONOBJECT_SCHEMA( className, schema ) \ IMPLEMENT_CLASS( className, NULL ) \ END_IMPLEMENT_CLASS; \ S32 className::_smTypeId; \ @@ -1164,7 +1188,7 @@ inline bool& ConsoleObject::getDynamicGroupExpand() AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return schema; } \ ConcreteClassRep className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description ) -#define IMPLEMENT_CONOBJECT_CHILDREN_SCHEMA( className, schema ) \ +#define IMPLEMENT_CONOBJECT_CHILDREN_SCHEMA( className, schema ) \ IMPLEMENT_CLASS( className, NULL ) \ END_IMPLEMENT_CLASS; \ S32 className::_smTypeId; \ @@ -1172,10 +1196,20 @@ inline bool& ConsoleObject::getDynamicGroupExpand() AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \ AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \ AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \ - AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); } \ + AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); } \ AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return schema; } \ ConcreteClassRep className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description ) +#define IMPLEMENT_ABSTRACT_CONOBJECT( className ) \ + IMPLEMENT_NONINSTANTIABLE_CLASS( className, NULL ) \ + END_IMPLEMENT_CLASS; \ + S32 className::_smTypeId; \ + SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" ); \ + AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \ + AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \ + AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \ + ConcreteAbstractClassRep className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description ) + #define IMPLEMENT_CO_NETOBJECT_V1( className ) \ IMPLEMENT_CLASS( className, NULL ) \ END_IMPLEMENT_CLASS; \ @@ -1185,7 +1219,7 @@ inline bool& ConsoleObject::getDynamicGroupExpand() AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \ AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \ AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; } \ - AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \ + AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \ ConcreteClassRep className::dynClassRep( #className, "Type" #className, &_smTypeId, NetClassGroupGameMask, NetClassTypeObject, 0, className::getParentStaticClassRep(), &Parent::__description ) #define IMPLEMENT_CO_DATABLOCK_V1( className ) \ @@ -1197,9 +1231,9 @@ inline bool& ConsoleObject::getDynamicGroupExpand() AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \ AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \ AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; } \ - AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \ + AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \ ConcreteClassRep className::dynClassRep(#className, "Type" #className, &_smTypeId, NetClassGroupGameMask, NetClassTypeDataBlock, 0, className::getParentStaticClassRep(), &Parent::__description ) - + // Support for adding properties to classes CONOBJECT style. #define PROPERTY_TABLE( className ) \ namespace { namespace _ ## className { \ @@ -1209,13 +1243,13 @@ inline bool& ConsoleObject::getDynamicGroupExpand() ConcreteClassRep< className >::smPropertyTable = _ ## className::_propTable; \ namespace { namespace _ ## className { \ EnginePropertyTable::Property _props[] = { - + #define END_PROPERTY_TABLE \ { NULL } \ }; \ EnginePropertyTable _propTable( sizeof( _props ) / sizeof( _props[ 0 ] ) - 1, _props ); \ } } - + /// Add an auto-doc for a class. #define ConsoleDocClass( className, docString ) \ CLASSDOC( className, docString ) @@ -1225,7 +1259,7 @@ inline bool& ConsoleObject::getDynamicGroupExpand() //------------------------------------------------------------------------------ // Protected field default get/set functions // -// The reason for these functions is that it will save one branch per console +// The reason for these functions is that it will save one branch per console // data request and script functions will still execute at the same speed as // before the modifications to allow protected static fields. These will just // inline and the code should be roughly the same size, and just as fast as diff --git a/Engine/source/console/engineTypeInfo.h b/Engine/source/console/engineTypeInfo.h index 88d78eed7..52d713e9e 100644 --- a/Engine/source/console/engineTypeInfo.h +++ b/Engine/source/console/engineTypeInfo.h @@ -362,7 +362,7 @@ class EngineTypeInfo : public EngineExportScope // them to retroactively install property tables. Will be removed // when the console interop is removed and all classes are migrated // to the new system. - template< typename T > friend class ConcreteClassRep; + template< typename T > friend class ConcreteAbstractClassRep; protected: diff --git a/Engine/source/core/color.h b/Engine/source/core/color.h index b0620fc4f..1fa5d7676 100644 --- a/Engine/source/core/color.h +++ b/Engine/source/core/color.h @@ -30,6 +30,10 @@ #include "math/mPoint4.h" #endif +#ifndef _ENGINEAPI_H_ +#include "console/engineAPI.h" +#endif + class ColorI; @@ -121,9 +125,20 @@ class ColorI U8 blue; U8 alpha; + struct Hsb + { + Hsb() :hue(0), sat(0), brightness(0){}; + Hsb(U32 h, U32 s, U32 b) :hue(h), sat(s), brightness(b){}; + + U32 hue; ///Hue + U32 sat; ///Saturation + U32 brightness; //Brightness/Value/Lightness + }; + public: ColorI() { } ColorI(const ColorI& in_rCopy); + ColorI(const Hsb& color); ColorI(const U8 in_r, const U8 in_g, const U8 in_b, @@ -132,6 +147,12 @@ class ColorI ColorI( const char* pStockColorName ); + void set(const Hsb& color); + + void HSLtoRGB_Subfunction(U32& c, const F64& temp1, const F64& temp2, const F64& temp3); + + void set(const String& hex); + void set(const U8 in_r, const U8 in_g, const U8 in_b, @@ -176,6 +197,11 @@ class ColorI U16 get565() const; U16 get4444() const; + Hsb getHSB() const; + + String getHex() const; + S32 convertFromHex(const String& hex) const; + operator ColorF() const; operator const U8*() const { return &red; } @@ -459,6 +485,174 @@ inline void ColorI::set(const ColorI& in_rCopy, alpha = in_a; } +inline void ColorI::set(const Hsb& color) +{ + U32 r = 0; + U32 g = 0; + U32 b = 0; + + F64 L = ((F64)color.brightness) / 100.0; + F64 S = ((F64)color.sat) / 100.0; + F64 H = ((F64)color.hue) / 360.0; + + if (color.sat == 0) + { + r = color.brightness; + g = color.brightness; + b = color.brightness; + } + else + { + F64 temp1 = 0; + if (L < 0.50) + { + temp1 = L*(1 + S); + } + else + { + temp1 = L + S - (L*S); + } + + F64 temp2 = 2.0*L - temp1; + + F64 temp3 = 0; + for (S32 i = 0; i < 3; i++) + { + switch (i) + { + case 0: // red + { + temp3 = H + 0.33333; + if (temp3 > 1.0) + temp3 -= 1.0; + HSLtoRGB_Subfunction(r, temp1, temp2, temp3); + break; + } + case 1: // green + { + temp3 = H; + HSLtoRGB_Subfunction(g, temp1, temp2, temp3); + break; + } + case 2: // blue + { + temp3 = H - 0.33333; + if (temp3 < 0) + temp3 += 1; + HSLtoRGB_Subfunction(b, temp1, temp2, temp3); + break; + } + default: + { + + } + } + } + } + red = (U32)((((F64)r) / 100) * 255); + green = (U32)((((F64)g) / 100) * 255); + blue = (U32)((((F64)b) / 100) * 255); +} + +// This is a subfunction of HSLtoRGB +inline void ColorI::HSLtoRGB_Subfunction(U32& c, const F64& temp1, const F64& temp2, const F64& temp3) +{ + if ((temp3 * 6.0) < 1.0) + c = (U32)((temp2 + (temp1 - temp2)*6.0*temp3)*100.0); + else + if ((temp3 * 2.0) < 1.0) + c = (U32)(temp1*100.0); + else + if ((temp3 * 3.0) < 2.0) + c = (U32)((temp2 + (temp1 - temp2)*(0.66666 - temp3)*6.0)*100.0); + else + c = (U32)(temp2*100.0); + return; +} + +inline void ColorI::set(const String& hex) +{ + String redString; + String greenString; + String blueString; + + //if the prefix # was attached to hex + if (hex[0] == '#') + { + redString = hex.substr(1, 2); + greenString = hex.substr(3, 2); + blueString = hex.substr(5, 2); + } + else + { + // since there is no prefix attached to hex + redString = hex.substr(0, 2); + greenString = hex.substr(2, 2); + blueString = hex.substr(4, 2); + } + + red = (U8)(convertFromHex(redString)); + green = (U8)(convertFromHex(greenString)); + blue = (U8)(convertFromHex(blueString)); +} + +inline S32 ColorI::convertFromHex(const String& hex) const +{ + S32 hexValue = 0; + + S32 a = 0; + S32 b = hex.length() - 1; + + for (; b >= 0; a++, b--) + { + if (hex[b] >= '0' && hex[b] <= '9') + { + hexValue += (hex[b] - '0') * (1 << (a * 4)); + } + else + { + switch (hex[b]) + { + case 'A': + case 'a': + hexValue += 10 * (1 << (a * 4)); + break; + + case 'B': + case 'b': + hexValue += 11 * (1 << (a * 4)); + break; + + case 'C': + case 'c': + hexValue += 12 * (1 << (a * 4)); + break; + + case 'D': + case 'd': + hexValue += 13 * (1 << (a * 4)); + break; + + case 'E': + case 'e': + hexValue += 14 * (1 << (a * 4)); + break; + + case 'F': + case 'f': + hexValue += 15 * (1 << (a * 4)); + break; + + default: + Con::errorf("Error, invalid character '%c' in hex number", hex[a]); + break; + } + } + } + + return hexValue; +} + inline ColorI::ColorI(const ColorI& in_rCopy) { red = in_rCopy.red; @@ -467,6 +661,11 @@ inline ColorI::ColorI(const ColorI& in_rCopy) alpha = in_rCopy.alpha; } +inline ColorI::ColorI(const Hsb& color) +{ + set(color); +} + inline ColorI::ColorI(const U8 in_r, const U8 in_g, const U8 in_b, @@ -503,6 +702,7 @@ inline ColorI& ColorI::operator*=(const S32 in_mul) inline ColorI& ColorI::operator/=(const S32 in_mul) { + AssertFatal(in_mul != 0.0f, "Error, div by zero..."); red = red / in_mul; green = green / in_mul; blue = blue / in_mul; @@ -647,6 +847,91 @@ inline U16 ColorI::get4444() const U16(U16(blue >> 4) << 0)); } +inline ColorI::Hsb ColorI::getHSB() const +{ + F64 rPercent = ((F64)red) / 255; + F64 gPercent = ((F64)green) / 255; + F64 bPercent = ((F64)blue) / 255; + + F64 maxColor = 0.0; + if ((rPercent >= gPercent) && (rPercent >= bPercent)) + maxColor = rPercent; + if ((gPercent >= rPercent) && (gPercent >= bPercent)) + maxColor = gPercent; + if ((bPercent >= rPercent) && (bPercent >= gPercent)) + maxColor = bPercent; + + F64 minColor = 0.0; + if ((rPercent <= gPercent) && (rPercent <= bPercent)) + minColor = rPercent; + if ((gPercent <= rPercent) && (gPercent <= bPercent)) + minColor = gPercent; + if ((bPercent <= rPercent) && (bPercent <= gPercent)) + minColor = bPercent; + + F64 H = 0.0; + F64 S = 0.0; + F64 B = 0.0; + + B = (maxColor + minColor) / 2.0; + + if (maxColor == minColor) + { + H = 0.0; + S = 0.0; + } + else + { + if (B < 0.50) + { + S = (maxColor - minColor) / (maxColor + minColor); + } + else + { + S = (maxColor - minColor) / (2.0 - maxColor - minColor); + } + if (maxColor == rPercent) + { + H = (gPercent - bPercent) / (maxColor - minColor); + } + if (maxColor == gPercent) + { + H = 2.0 + (bPercent - rPercent) / (maxColor - minColor); + } + if (maxColor == bPercent) + { + H = 4.0 + (rPercent - gPercent) / (maxColor - minColor); + } + } + + ColorI::Hsb val; + val.sat = (U32)(S * 100); + val.brightness = (U32)(B * 100); + H = H*60.0; + if (H < 0.0) + H += 360.0; + val.hue = (U32)H; + + return val; +} + +inline String ColorI::getHex() const +{ + char r[255]; + dSprintf(r, sizeof(r), "%.2X", red); + String result(r); + + char g[255]; + dSprintf(g, sizeof(g), "%.2X", green); + result += g; + + char b[255]; + dSprintf(b, sizeof(b), "%.2X", blue); + result += b; + + return result; +} + //-------------------------------------- INLINE CONVERSION OPERATORS inline ColorF::operator ColorI() const { diff --git a/Engine/source/core/idGenerator.h b/Engine/source/core/idGenerator.h index a0ddc74ed..8c3467673 100644 --- a/Engine/source/core/idGenerator.h +++ b/Engine/source/core/idGenerator.h @@ -74,7 +74,7 @@ public: void free(U32 id) { - AssertFatal(id >= mIdBlockBase, "IdGenerator::alloc: invalid id, id does not belong to this IdGenerator.") + AssertFatal(id >= mIdBlockBase, "IdGenerator::alloc: invalid id, id does not belong to this IdGenerator."); if(id == mNextId - 1) { mNextId--; diff --git a/Engine/source/core/stream/stream.cpp b/Engine/source/core/stream/stream.cpp index da1b1dc82..8a7fb2b40 100644 --- a/Engine/source/core/stream/stream.cpp +++ b/Engine/source/core/stream/stream.cpp @@ -128,7 +128,7 @@ bool Stream::writeFormattedBuffer(const char *format, ...) char buffer[4096]; va_list args; va_start(args, format); - const S32 length = vsprintf(buffer, format, args); + const S32 length = dVsprintf(buffer, sizeof(buffer), format, args); // Sanity! AssertFatal(length <= sizeof(buffer), "writeFormattedBuffer - String format exceeded buffer size. This will cause corruption."); diff --git a/Engine/source/core/strings/stringFunctions.h b/Engine/source/core/strings/stringFunctions.h index d712388d6..9a30382ef 100644 --- a/Engine/source/core/strings/stringFunctions.h +++ b/Engine/source/core/strings/stringFunctions.h @@ -152,11 +152,20 @@ inline U32 dAtoui(const char *str, U32 base = 10) return strtoul(str, NULL, base); } +inline U16 dAtous(const char *str, U32 base = 10) +{ + return strtoul(str, NULL, base); +} + inline F32 dAtof(const char *str) { return strtof(str, NULL); } +inline F64 dAtod(const char *str) +{ + return strtod(str, NULL); +} inline char dToupper(const char c) { diff --git a/Engine/source/core/util/str.cpp b/Engine/source/core/util/str.cpp index 6fc56b346..cc124a45d 100644 --- a/Engine/source/core/util/str.cpp +++ b/Engine/source/core/util/str.cpp @@ -1628,3 +1628,103 @@ String String::GetTrailingNumber(const char* str, S32& number) return base.substr(0, p - base.c_str()); } + +String String::GetFirstNumber(const char* str, U32& startPos, U32& endPos) +{ + // Check for trivial strings + if (!str || !str[0]) + return String::EmptyString; + + // Find the number at the end of the string + String base(str); + const char* p = base.c_str(); + const char* end = base.c_str() + base.length() - 1; + bool dec = false; + startPos = 0; + + //Check if we are just a digit + if(p == end && isdigit(*p)) + return base; + + //Look for the first digit + while ((p != end) && (dIsspace(*p) || !isdigit(*p))) + { + p++; + startPos++; + } + + //Handle if we are at the end and found nothing + if(p == end && !isdigit(*p)) + return ""; + + //update our end position at least to the start of our number + endPos = startPos; + + //Backup our ptr + const char* backup = p; + + //Check for any negative or decimal values + if(startPos > 0) + { + p--; + startPos--; + if(*p == '.') + { + dec = true; + + //ignore any duplicate periods + while ((p != base.c_str()) && (*p == '.')) + { + p--; + startPos--; + } + + //Found a decimal lets still check for negative sign + if(startPos > 0) + { + p--; + startPos--; + if((*p != '-') && (*p != '_')) + { + startPos++; + p++; + } + } + } + else if((*p != '-') && (*p != '_')) + { + //go back to where we where cause no decimal or negative sign found + startPos++; + p++; + } + } + + //Restore where we were + p = backup; + + //look for the end of the digits + bool justFoundDec = false; + while (p != end) + { + if(*p == '.') + { + if(dec && !justFoundDec) + break; + else + { + dec = true; + justFoundDec = true; + } + } + else if(!isdigit(*p)) + break; + else if(justFoundDec) + justFoundDec = false; + + p++; + endPos++; + } + + U32 len = (!isdigit(*p)) ? endPos - startPos : (endPos + 1) - startPos; + return base.substr(startPos, len); +} diff --git a/Engine/source/core/util/str.h b/Engine/source/core/util/str.h index 2f4fec552..046bc1f6f 100644 --- a/Engine/source/core/util/str.h +++ b/Engine/source/core/util/str.h @@ -191,6 +191,7 @@ public: static String ToUpper(const String &string); static String GetTrailingNumber(const char* str, S32& number); + static String GetFirstNumber(const char* str, U32& startPos, U32& endPos); /// @} diff --git a/Engine/source/core/util/swizzle.h b/Engine/source/core/util/swizzle.h index abbff288f..0f1d583f6 100644 --- a/Engine/source/core/util/swizzle.h +++ b/Engine/source/core/util/swizzle.h @@ -120,8 +120,7 @@ inline void Swizzle::ToBuffer( void *destination, const void *sour { // TODO: OpenMP? AssertFatal( size % ( sizeof( T ) * mapLength ) == 0, "Bad buffer size for swizzle, see docs." ); - AssertFatal( destination != NULL, "Swizzle::ToBuffer - got a NULL destination pointer!" ); - AssertFatal( source != NULL, "Swizzle::ToBuffer - got a NULL source pointer!" ); + if (!destination || !source) return; T *dest = reinterpret_cast( destination ); const T *src = reinterpret_cast( source ); diff --git a/Engine/source/environment/VolumetricFog.cpp b/Engine/source/environment/VolumetricFog.cpp new file mode 100644 index 000000000..e6be112dc --- /dev/null +++ b/Engine/source/environment/VolumetricFog.cpp @@ -0,0 +1,1319 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "environment/VolumetricFog.h" +#include "windowManager/platformWindowMgr.h" +#include "gfx/gfxTransformSaver.h" +#include "renderInstance/renderPassManager.h" +#include "math/mathIO.h" +#include "materials/shaderData.h" +#include "math/util/matrixSet.h" +#include "core/resourceManager.h" +#include "core/stream/bitStream.h" +#include "T3D/gameBase/gameConnection.h" +#include "T3D/shapeBase.h" +#include "ts/tsShapeInstance.h" +#include "console/engineAPI.h" +#include "gui/core/guiCanvas.h" +#include "VolumetricFogRTManager.h" +#include "lighting/lightInfo.h" +#include "lighting/lightManager.h" + +#define COLBOX_SCALE Point3F(1.02f, 1.02f, 1.02f) + +IMPLEMENT_CO_NETOBJECT_V1(VolumetricFog); + +ConsoleDocClass(VolumetricFog, +"@brief Volumetric Fog Object class. Main class defining the Volumetric\n" +"Fog objects in the scene. Used in conjunction with the VolumetricFogRTManager\n" +"class which is responsible for the required rendertargets.\n\n" +"Methods (exposed to script):\n" +" setFogColorF(color) Changes the overall fog color (color.rgba range 0.0 - 1.0).\n;" +" setFogColor(color) Changes the overall fog color color.rgba range 0 - 255).\n;" +" setFogDensity(density) Changes the overall fog density.\n" +" setFogModulation(strength, speed1, speed2) changes the strength\n" +" and the speeds of the 2 animation layers.\n\n" +"Callbacks:\n" +"onEnterFog triggered whenever the controlobject (Player or Camera) enters the Fog.\n" +" (current Fog object and the controlobject are exposed to script.\n" +"onLeaveFog triggered whenever the controlobject (Player or Camera) left the Fog.\n" +" (current Fog object and the controlobject are exposed to script.\n\n" +"@tsexample\n" +" new VolumetricFog()\n" +" {\n" +" shapeName = \"art/environment/FogRCube.dts\";\n" +" fogColor = \"200 200 200 128\";\n" +" fogDensity = \"0.2\";\n" +" ignoreWater = \"0\";\n" +" MinSize = \"250\";\n" +" FadeSize = \"750\";\n" +" texture = \"art/environment/FogMod_heavy.dds\";\n" +" tiles = \"1.5\";\n" +" modStrength = \"0.2\";\n" +" PrimSpeed = \"-0.01 0.04\";\n" +" SecSpeed = \"0.02 -0.02\";\n" +" position = \"748.644 656.371 65.3506\"; \n" +" rotation = \"0 0 1 20.354\";\n" +" scale = \"40 30 6\";\n" +" };\n" +"@endtsexample\n" +); + +IMPLEMENT_CALLBACK(VolumetricFog, onEnterFog, void, (SimObjectId obj), (obj), +"@brief Called when an object enters the volume of the Fog instance.\n\n" + +"@param obj the controlobject entering the fog."); + +IMPLEMENT_CALLBACK(VolumetricFog, onLeaveFog, void, (SimObjectId obj), (obj), +"@brief Called when an object left the volume of the Fog instance.\n\n" + +"@param obj the controlobject leaving the fog."); + + +VolumetricFog::VolumetricFog() +{ + AssertFatal(VFRTM != NULL, "VolumetricFog Fatal Error: No Manager found"); + + if (!VFRTM->IsInitialized()) + VFRTM->Init(); + + mNetFlags.set(Ghostable | ScopeAlways); + + mTypeMask |= EnvironmentObjectType | StaticObjectType; + + mPrepassTarget = NULL; + mDepthBufferTarget = NULL; + mFrontBufferTarget = NULL; + + z_buf = NULL; + mTexture = NULL; + + mIsVBDirty = false; + mIsPBDirty = false; + + mFogColor.set(200, 200, 200, 255); + mFogDensity = 0.3f; + mIgnoreWater = false; + mReflect = false; + mCamInFog = false; + mResizing = false; + mFogReflStrength = 20.0; + mUseGlow = false; + mGlowStrength = 0.3f; + mGlowing = 0; + mModifLightRays = false; + mLightRayMod = 1.0f; + mOldLightRayStrength = 0.1f; + + mShapeName = ""; + mShapeLoaded = false; + mMinDisplaySize = 10.0f; + mFadeSize = 0.0f; + mCurDetailLevel = 0; + mNumDetailLevels = 0; + det_size.clear(); + + mTextureName = ""; + mIsTextured = false; + mStrength = 0.5f; + mTexTiles = 1.0f; + mSpeed1.set(0.5f, 0.0f); + mSpeed2.set(0.1f, 0.1f); +} + +VolumetricFog::~VolumetricFog() +{ + if (isClientObject()) + return; + + for (S32 i = 0; i < det_size.size(); i++) + { + if (det_size[i].indices != NULL) + delete(det_size[i].indices); + if (det_size[i].piArray != NULL) + delete(det_size[i].piArray); + if (det_size[i].verts != NULL) + delete(det_size[i].verts); + } + det_size.clear(); + + if (z_buf.isValid()) + SAFE_DELETE(z_buf); + + if (!mTexture.isNull()) + mTexture.free(); +} + +void VolumetricFog::initPersistFields() +{ + addGroup("VolumetricFogData"); + addField("shapeName", TypeShapeFilename, Offset(mShapeName, VolumetricFog), + "Path and filename of the model file (.DTS, .DAE) to use for this Volume."); + addField("FogColor", TypeColorI, Offset(mFogColor, VolumetricFog), + "Fog color RGBA (Alpha is ignored)"); + addField("FogDensity", TypeF32, Offset(mFogDensity, VolumetricFog), + "Overal fog density value (0 disables the fog)."); + addField("IgnoreWater", TypeBool, Offset(mIgnoreWater, VolumetricFog), + "Set to true if volumetric fog should continue while submerged."); + addField("MinSize", TypeF32, Offset(mMinDisplaySize, VolumetricFog), + "Min size (in pixels) for fog to be rendered."); + addField("FadeSize", TypeF32, Offset(mFadeSize, VolumetricFog), + "Object size in pixels at which the FX-fading kicks in (0 disables fading)."); + endGroup("VolumetricFogData"); + + addGroup("VolumetricFogModulation"); + addField("texture", TypeImageFilename, Offset(mTextureName, VolumetricFog), + "A texture which contains Fogdensity modulator in the red channel and color with 1-green channel. No texture disables modulation."); + addField("tiles", TypeF32, Offset(mTexTiles, VolumetricFog), + "How many times the texture is mapped to the object."); + addField("modStrength", TypeF32, Offset(mStrength, VolumetricFog), + "Overall strength of the density modulation (0 disables modulation)."); + addField("PrimSpeed", TypePoint2F, Offset(mSpeed1, VolumetricFog), + "Overall primary speed of the density modulation (x-speed(u) y-speed(v))"); + addField("SecSpeed", TypePoint2F, Offset(mSpeed2, VolumetricFog), + "Overall secundary speed of the density modulation (x-speed(u) y-speed(v))"); + endGroup("VolumetricFogModulation"); + + addGroup("Reflections"); + addField("Reflectable", TypeBool, Offset(mReflect, VolumetricFog), + "Set to true if volumetric fog should be reflected."); + addField("ReflectStrength", TypeF32, Offset(mFogReflStrength, VolumetricFog), + "Strength of the reflections (0 disables the fog)."); + endGroup("Reflections"); + + addGroup("PostFX"); + addField("useGlow", TypeBool, Offset(mUseGlow, VolumetricFog), + "Set to true if volumetric fog should use glow PostFX."); + addField("glowStrength", TypeF32, Offset(mGlowStrength, VolumetricFog), + "Overall strength of the glow PostFX."); + addField("modLightRay", TypeBool, Offset(mModifLightRays, VolumetricFog), + "Set to true if volumetric fog should modify the brightness of the Lightrays."); + addField("lightRayMod", TypeF32, Offset(mLightRayMod, VolumetricFog), + "Modifier for LightRay PostFX when inside Fog."); + endGroup("PostFX"); + Parent::initPersistFields(); +} + +void VolumetricFog::inspectPostApply() +{ + Parent::inspectPostApply(); + mSpeed.set(mSpeed1.x, mSpeed1.y, mSpeed2.x, mSpeed2.y); + setMaskBits(VolumetricFogMask | FogColorMask | FogDensityMask | FogModulationMask | FogPostFXMask | FogShapeMask); +} + +bool VolumetricFog::onAdd() +{ + if (!Parent::onAdd()) + return false; + + if (!VFRTM->IsInitialized()) + { + Con::errorf("No VolumetricFogRTManager present!!"); + return false; + } + + resetWorldBox(); + + mShapeLoaded = LoadShape(); + + setRenderTransform(mObjToWorld); + + addToScene(); + ColBox.set(getTransform(), (mObjBox.getExtents() * getScale() * COLBOX_SCALE)); + mObjSize = mWorldBox.getGreatestDiagonalLength(); + mObjScale = getScale(); + mTexTiles = mAbs(mTexTiles); + mSpeed.set(mSpeed1.x, mSpeed1.y, mSpeed2.x, mSpeed2.y); + mInvScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z)); + + if (isClientObject()) + { + conn = GameConnection::getConnectionToServer(); + if (!conn) + { + Con::errorf("VolumetricFog::onAdd - No Serverconnection"); + return false; + } + + glowFX = static_cast(Sim::findObject("VolFogGlowPostFx")); + + mOldLightRayStrength = Con::getFloatVariable("$LightRayPostFX::brightScalar",1.0f); + + GuiCanvas* cv = dynamic_cast(Sim::findObject("Canvas")); + if (cv == NULL) + { + Con::errorf("VolumetricFog::onAdd - Canvas not found!!"); + return false; + } + mPlatformWindow = cv->getPlatformWindow(); + VolumetricFogRTManager::getVolumetricFogRTMResizeSignal().notify(this, &VolumetricFog::handleResize); + GuiCanvas::getCanvasSizeChangeSignal().notify(this, &VolumetricFog::handleCanvasResize); + + InitTexture(); + return setupRenderer(); + } + + VFRTM->IncFogObjects(); + + return true; +} + +void VolumetricFog::onRemove() +{ + if (isClientObject()) + { + if (isTicking()) + { + setProcessTick(false); + if (mGlowing != 0) + { + mGlowing = 0; + glowFX->disable(); + } + _leaveFog(static_cast(conn->getControlObject())); + } + VolumetricFogRTManager::getVolumetricFogRTMResizeSignal().remove(this, &VolumetricFog::handleResize); + GuiCanvas::getCanvasSizeChangeSignal().remove(this, &VolumetricFog::handleCanvasResize); + } + removeFromScene(); + VFRTM->DecFogObjects(); + Parent::onRemove(); +} +void VolumetricFog::handleCanvasResize(GuiCanvas* canvas) +{ + UpdateBuffers(0,true); +} + +void VolumetricFog::handleResize(VolumetricFogRTManager *RTM, bool resize) +{ + if (resize) + { + mResizing = true; + RTM->FogAnswered(); + } + else + mResizing = false; + + if (mIsTextured) + { + F32 width = (F32)mPlatformWindow->getClientExtent().x; + F32 height = (F32)mPlatformWindow->getClientExtent().y; + if (!mPlatformWindow->isFullscreen()) + height -= 20;//subtract caption bar from rendertarget size. + mTexScale.x = 2.0f - ((F32)mTexture.getWidth() / width); + mTexScale.y = 2.0f - ((F32)mTexture.getHeight() / height); + } + + UpdateBuffers(0,true); +} + +//----------------------------------------------------------------------------- +// Loadshape extracted from TSMesh and TSShapeInstance +//----------------------------------------------------------------------------- + +bool VolumetricFog::LoadShape() +{ + GFXPrimitiveType GFXdrawTypes[] = { GFXTriangleList, GFXTriangleStrip }; + if (!mShapeName || mShapeName[0] == '\0') + { + Con::errorf("VolumetricFog::LoadShape() - No shape name! Volumetric Fog will not be rendered!"); + return false; + } + + // Load shape, server side only reads bounds and radius + + Resource mShape; + mShape = ResourceManager::get().load(mShapeName); + if (bool(mShape) == false) + { + Con::errorf("VolumetricFog::LoadShape() - Unable to load shape: %s", mShapeName); + return false; + } + + mObjBox = mShape->bounds; + mRadius = mShape->radius; + resetWorldBox(); + + if (!isClientObject()) + return false; + + TSShapeInstance *mShapeInstance = new TSShapeInstance(mShape, false); + meshes mesh_detail; + + for (S32 i = 0; i < det_size.size(); i++) + { + if (det_size[i].indices != NULL) + delete(det_size[i].indices); + if (det_size[i].piArray != NULL) + delete(det_size[i].piArray); + if (det_size[i].verts != NULL) + delete(det_size[i].verts); + } + det_size.clear(); + + // browsing model for detail levels + + for (U32 i = 0; i < mShape->details.size(); i++) + { + const TSDetail *detail = &mShape->details[i]; + mesh_detail.det_size = detail->size; + mesh_detail.sub_shape = detail->subShapeNum; + mesh_detail.obj_det = detail->objectDetailNum; + mesh_detail.verts = NULL; + mesh_detail.piArray = NULL; + mesh_detail.indices = NULL; + if (detail->size >= 0.0f && detail->subShapeNum >= 0) + det_size.push_back(mesh_detail); + } + + for (U32 i = 0; i < det_size.size(); i++) + { + const S32 ss = det_size[i].sub_shape; + if (ss >= 0) + { + const S32 start = mShape->subShapeFirstObject[ss]; + const S32 end = start + mShape->subShapeNumObjects[ss]; + for (S32 j = start; j < end; j++) + { + // Loading shape, only the first mesh for each detail will be used! + TSShapeInstance::MeshObjectInstance *meshObj = &mShapeInstance->mMeshObjects[j]; + if (!meshObj) + continue; + TSMesh *mesh = meshObj->getMesh(det_size[i].obj_det); + if (mesh != NULL) + { + const U32 numNrms = mesh->mNumVerts; + GFXVertexPNTT *tmpVerts = NULL; + tmpVerts = new GFXVertexPNTT[numNrms]; + mIsVBDirty = true; + for (U32 k = 0; k < numNrms; k++) + { + Point3F norm = mesh->mVertexData[k].normal(); + Point3F vert = mesh->mVertexData[k].vert(); + Point2F uv = mesh->mVertexData[k].tvert(); + tmpVerts[k].point = vert; + tmpVerts[k].texCoord = uv; + tmpVerts[k].normal = norm; + } + det_size[i].verts = tmpVerts; + det_size[i].num_verts = numNrms; + + det_size[i].piArray = new Vector(); + GFXPrimitive pInfo; + + det_size[i].indices = new Vector(); + + for (U32 k = 0; k < mesh->indices.size(); k++) + det_size[i].indices->push_back(mesh->indices[k]); + + U32 primitivesSize = mesh->primitives.size(); + for (U32 k = 0; k < primitivesSize; k++) + { + const TSDrawPrimitive & draw = mesh->primitives[k]; + GFXPrimitiveType drawType = GFXdrawTypes[draw.matIndex >> 30]; + switch (drawType) + { + case GFXTriangleList: + pInfo.type = drawType; + pInfo.numPrimitives = draw.numElements / 3; + pInfo.startIndex = draw.start; + // Use the first index to determine which 16-bit address space we are operating in + pInfo.startVertex = mesh->indices[draw.start] & 0xFFFF0000; + pInfo.minIndex = pInfo.startVertex; + pInfo.numVertices = getMin((U32)0x10000, mesh->mNumVerts - pInfo.startVertex); + break; + case GFXTriangleStrip: + pInfo.type = drawType; + pInfo.numPrimitives = draw.numElements - 2; + pInfo.startIndex = draw.start; + // Use the first index to determine which 16-bit address space we are operating in + pInfo.startVertex = mesh->indices[draw.start] & 0xFFFF0000; + pInfo.minIndex = pInfo.startVertex; + pInfo.numVertices = getMin((U32)0x10000, mesh->mNumVerts - pInfo.startVertex); + break; + default: + Con::errorf("VolumetricFog::LoadShape Unknown drawtype!?!"); + return false; + break; + } + det_size[i].piArray->push_back(pInfo); + j = end; + } + } + else + { + Con::errorf("VolumetricFog::LoadShape Error loading mesh from shape!"); + delete mShapeInstance; + return false; + } + mIsVBDirty = true; + mIsPBDirty = true; + } + } + } + + mNumDetailLevels = det_size.size(); + mCurDetailLevel = 0; + UpdateBuffers(mCurDetailLevel); + delete mShapeInstance; + + return true; +} + +//----------------------------------------------------------------------------- +// UpdateBuffers called whenever detaillevel changes (LOD) +//----------------------------------------------------------------------------- + + +bool VolumetricFog::UpdateBuffers(U32 dl, bool force) +{ + if (mVB.isNull() || mIsVBDirty || dl != mCurDetailLevel || force) + { + mVB.set(GFX, det_size[dl].num_verts, GFXBufferTypeDynamic); + mIsVBDirty = false; + } + GFXVertexPNTT *vertPtr = mVB.lock(); + if (!vertPtr) + { + mVB.unlock(); + return false; + } + dMemcpy(vertPtr, det_size[dl].verts, sizeof (GFXVertexPNTT)* det_size[dl].num_verts); + mVB.unlock(); + + if (mIsPBDirty || mPB.isNull() || dl != mCurDetailLevel || force) + { + #ifdef TORQUE_DEBUG + mPB.set(GFX, det_size[dl].indices->size(), det_size[dl].piArray->size(), GFXBufferTypeDynamic, avar("%s() - VolFogPrimBuffer (line %d)", __FUNCTION__, __LINE__)); + #else + mPB.set(GFX, det_size[dl].indices->size(), det_size[dl].piArray->size(), GFXBufferTypeDynamic); + #endif + U16 *ibIndices = NULL; + GFXPrimitive *piInput = NULL; + mPB.lock(&ibIndices, &piInput); + dCopyArray(ibIndices, det_size[dl].indices->address(), det_size[dl].indices->size()); + dMemcpy(piInput, det_size[dl].piArray->address(), det_size[dl].piArray->size() * sizeof(GFXPrimitive)); + mPB.unlock(); + mIsPBDirty = false; + } + mCurDetailLevel = dl; + return true; +} + +U32 VolumetricFog::packUpdate(NetConnection *con, U32 mask, BitStream *stream) +{ + U32 retMask = Parent::packUpdate(con, mask, stream); + if (stream->writeFlag(mask & FogColorMask)) + stream->write(mFogColor); + if (stream->writeFlag(mask & FogDensityMask)) + stream->write(mFogDensity); + if (stream->writeFlag(mask & FogModulationMask)) + { + stream->write(mTextureName); + mTexTiles = mFabs(mTexTiles); + stream->write(mTexTiles); + stream->write(mStrength); + mathWrite(*stream, mSpeed); + } + if (stream->writeFlag(mask & FogPostFXMask)) + { + stream->writeFlag(mUseGlow); + stream->write(mGlowStrength); + stream->writeFlag(mModifLightRays); + stream->write(mLightRayMod); + } + if (stream->writeFlag(mask & VolumetricFogMask)) + { + stream->writeFlag(mIgnoreWater); + stream->writeFlag(mReflect); + stream->write(mFogReflStrength); + stream->writeFlag(mResizing); + stream->write(mMinDisplaySize); + stream->write(mFadeSize); + } + if (stream->writeFlag(mask & FogShapeMask)) + { + stream->writeString(mShapeName); + mathWrite(*stream, getTransform()); + mathWrite(*stream, getScale()); + if (!mShapeName || mShapeName[0] == '\0') + return retMask; + Resource mShape; + mShape = ResourceManager::get().load(mShapeName); + if (bool(mShape) == false) + return retMask; + mObjBox = mShape->bounds; + mRadius = mShape->radius; + resetWorldBox(); + mObjSize = mWorldBox.getGreatestDiagonalLength(); + mObjScale = getScale(); + mInvScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z)); + } + return retMask; +} + +void VolumetricFog::unpackUpdate(NetConnection *con, BitStream *stream) +{ + Parent::unpackUpdate(con, stream); + MatrixF mat; + VectorF scale; + VectorF mOldScale = getScale(); + String oldTextureName = mTextureName; + StringTableEntry oldShape = mShapeName; + + if (stream->readFlag())// Fog color + stream->read(&mFogColor); + if (stream->readFlag())// Fog Density + { + stream->read(&mFogDensity); + if (isTicking()) + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mFogDensity); + Con::setVariable("$VolumetricFog::density", buf); + } + } + if (stream->readFlag())// Fog Modulation + { + stream->read(&mTextureName); + stream->read(&mTexTiles); + mTexTiles = mFabs(mTexTiles); + stream->read(&mStrength); + mathRead(*stream, &mSpeed); + mSpeed1.set(mSpeed.x, mSpeed.y); + mSpeed2.set(mSpeed.z, mSpeed.w); + + if (isProperlyAdded()) + { + if (oldTextureName != mTextureName) + InitTexture(); + if (oldTextureName.isNotEmpty() && mTextureName.isEmpty()) + { + mIsTextured = false; + mTexture.free(); + } + } + } + if (stream->readFlag())//Fog PostFX + { + mUseGlow = stream->readFlag(); + stream->read(&mGlowStrength); + mModifLightRays = stream->readFlag(); + stream->read(&mLightRayMod); + if (isTicking()) + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mGlowStrength); + Con::setVariable("$VolFogGlowPostFx::glowStrength", buf); + if (mUseGlow && !glowFX->isEnabled()) + glowFX->enable(); + if (!mUseGlow && glowFX->isEnabled()) + glowFX->disable(); + if (mModifLightRays) + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mOldLightRayStrength * mLightRayMod); + Con::setVariable("$LightRayPostFX::brightScalar", buf); + } + if (!mModifLightRays) + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mOldLightRayStrength); + Con::setVariable("$LightRayPostFX::brightScalar", buf); + } + } + } + if (stream->readFlag())//Volumetric Fog + { + mIgnoreWater = stream->readFlag(); + mReflect = stream->readFlag(); + stream->read(&mFogReflStrength); + mResizing = stream->readFlag(); + stream->read(&mMinDisplaySize); + stream->read(&mFadeSize); + } + if (stream->readFlag())//Fog shape + { + mShapeName = stream->readSTString(); + mathRead(*stream, &mat); + mathRead(*stream, &scale); + if (strcmp(oldShape, mShapeName) != 0) + { + mIsVBDirty = true; + mShapeLoaded = LoadShape(); + } + setScale(scale); + setTransform(mat); + ColBox.set(getTransform(), (mObjBox.getExtents() * getScale() * COLBOX_SCALE)); + mObjSize = mWorldBox.getGreatestDiagonalLength(); + mObjScale = getScale(); + mInvScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z)); + } +} + +void VolumetricFog::processTick(const Move* move) +{ + Parent::processTick(move); + mCounter++; + if ( mGlowing==1 && mCurGlow < mGlowStrength ) + { + mCurGlow += (mGlowStrength / 10.0); + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mCurGlow); + Con::setVariable("$VolFogGlowPostFx::glowStrength", buf); + } + else if ( mGlowing == 2 && mCurGlow > 0.0f ) + { + mCurGlow -= (mGlowStrength / 5.0f); + if (mCurGlow <= 0.0f) + { + glowFX->disable(); + mGlowing = 0; + setProcessTick(false); + return; + } + else + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mCurGlow); + Con::setVariable("$VolFogGlowPostFx::glowStrength", buf); + } + } + if (mCounter == 3) + { + ShapeBase* control = static_cast(conn->getControlObject()); + MatrixF xfm; + control->getRenderEyeTransform(&xfm); + Point3F pos = xfm.getPosition(); + if (!ColBox.isContained(pos)) + _leaveFog(control); + mCounter = 0; + } +} + +void VolumetricFog::_enterFog(ShapeBase *control) +{ + if (mUseGlow) + { + if (glowFX) + { + mCurGlow = 0.0f; + Con::setVariable("$VolFogGlowPostFx::glowStrength", "0.0"); + glowFX->enable(); + mGlowing = 1; + } + } + if (mModifLightRays) + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mOldLightRayStrength * mLightRayMod); + Con::setVariable("$LightRayPostFX::brightScalar", buf); + } + mCounter = 0; + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mFogDensity); + Con::setVariable("$VolumetricFog::density", buf); + setProcessTick(true); + if (control) + onEnterFog_callback(control->getId()); +} + +void VolumetricFog::_leaveFog(ShapeBase *control) +{ + mCamInFog = false; + Con::setVariable("$VolumetricFog::density", "0.0"); + if (mModifLightRays) + { + char buf[20]; + dSprintf(buf, sizeof(buf), "%3.7f", mOldLightRayStrength); + Con::setVariable("$LightRayPostFX::brightScalar", buf); + } + if (mUseGlow) + { + if (glowFX && mGlowing != 2) + { + mCurGlow = mGlowStrength; + mGlowing = 2; + if (control) + onLeaveFog_callback(control->getId()); + } + } + else + { + setProcessTick(false); + if (control) + onLeaveFog_callback(control->getId()); + } +} + +//----------------------------------------------------------------------------- +// Setting up the renderers +//----------------------------------------------------------------------------- + +bool VolumetricFog::setupRenderer() +{ + // Search for the prepass rendertarget and shadermacros. + mPrepassTarget = NamedTexTarget::find("prepass"); + if (!mPrepassTarget.isValid()) + { + Con::errorf("VolumetricFog::setupRenderer - could not find PrepassTarget"); + return false; + } + + Vector macros; + if (mPrepassTarget) + mPrepassTarget->getShaderMacros(¯os); + + // Search the depth and frontbuffers which are created by the VolumetricFogRTManager + + mDepthBufferTarget = NamedTexTarget::find("volfogdepth"); + if (!mDepthBufferTarget.isValid()) + { + Con::errorf("VolumetricFog::setupRenderer - could not find depthbuffer"); + return false; + } + + mFrontBufferTarget = NamedTexTarget::find("volfogfront"); + if (!mFrontBufferTarget.isValid()) + { + Con::errorf("VolumetricFog::setupRenderer - could not find frontbuffer"); + return false; + } + + // Find and setup the prepass Shader + + ShaderData *shaderData; + mPrePassShader = Sim::findObject("VolumetricFogPrePassShader", shaderData) ? + shaderData->getShader() : NULL; + if (!mPrePassShader) + { + Con::errorf("VolumetricFog::setupRenderer - could not find VolumetricFogPrePassShader"); + return false; + } + + // Create ShaderConstBuffer and Handles + + mPPShaderConsts = mPrePassShader->allocConstBuffer(); + if (mPPShaderConsts.isNull()) + { + Con::errorf("VolumetricFog::setupRenderer - could not allocate ShaderConstants 1."); + return false; + } + + mPPModelViewProjSC = mPrePassShader->getShaderConstHandle("$modelView"); + + // Find and setup the VolumetricFog Shader + + shaderData = NULL; + mShader = Sim::findObject("VolumetricFogShader", shaderData) ? + shaderData->getShader(macros) : NULL; + if (!mShader) + { + Con::errorf("VolumetricFog::setupRenderer - could not find VolumetricFogShader"); + return false; + } + + // Create ShaderConstBuffer and Handles + + mShaderConsts = mShader->allocConstBuffer(); + if (mShaderConsts.isNull()) + { + Con::errorf("VolumetricFog::setupRenderer - could not allocate ShaderConstants 2."); + return false; + } + + mModelViewProjSC = mShader->getShaderConstHandle("$modelView"); + mFadeSizeSC = mShader->getShaderConstHandle("$fadesize"); + mFogColorSC = mShader->getShaderConstHandle("$fogColor"); + mFogDensitySC = mShader->getShaderConstHandle("$fogDensity"); + mPreBias = mShader->getShaderConstHandle("$preBias"); + mAccumTime = mShader->getShaderConstHandle("$accumTime"); + mIsTexturedSC = mShader->getShaderConstHandle("$textured"); + mTexTilesSC = mShader->getShaderConstHandle("$numtiles"); + mModStrengthSC = mShader->getShaderConstHandle("$modstrength"); + mModSpeedSC = mShader->getShaderConstHandle("$modspeed"); + mViewPointSC = mShader->getShaderConstHandle("$viewpoint"); + mTexScaleSC = mShader->getShaderConstHandle("$texscale"); + mAmbientColorSC = mShader->getShaderConstHandle("$ambientColor"); + + // Find and setup the reflection Shader + + shaderData = NULL; + mReflectionShader = Sim::findObject("VolumetricFogReflectionShader", shaderData) ? + shaderData->getShader() : NULL; + if (!mReflectionShader) + { + Con::errorf("VolumetricFog::setupRenderer - could not find VolumetricFogReflectionShader"); + return false; + } + + mReflShaderConsts = mReflectionShader->allocConstBuffer(); + if (mReflShaderConsts.isNull()) + { + Con::errorf("VolumetricFog::setupRenderer - could not allocate ShaderConstants for VolumetricFogReflectionShader."); + return false; + } + + mReflModelViewProjSC = mReflectionShader->getShaderConstHandle("$modelView"); + mReflFogColorSC = mReflectionShader->getShaderConstHandle("$fogColor"); + mReflFogDensitySC = mReflectionShader->getShaderConstHandle("$fogDensity"); + mReflFogStrengthSC = mReflectionShader->getShaderConstHandle("$reflStrength"); + + // Create the prepass StateBlock + + desc_preD.setCullMode(GFXCullCW); + desc_preD.setBlend(true); + desc_preD.setZReadWrite(false, false); + desc_preD.stencilEnable = false; + desc_preF.setCullMode(GFXCullCCW); + desc_preF.setBlend(true); + desc_preF.setZReadWrite(true, false); + desc_preF.stencilEnable = false; + + // Create the VolumetricFog StateBlock + + descD.setCullMode(GFXCullCW); + descD.setBlend(true); + descD.setZReadWrite(false, false);// desc.setZReadWrite(true, false); + + // prepassBuffer sampler + descD.samplersDefined = true; + descD.samplers[0].addressModeU = GFXAddressClamp; + descD.samplers[0].addressModeV = GFXAddressClamp; + descD.samplers[0].addressModeW = GFXAddressClamp; + descD.samplers[0].magFilter = GFXTextureFilterLinear; + descD.samplers[0].minFilter = GFXTextureFilterLinear; + descD.samplers[0].mipFilter = GFXTextureFilterLinear; + descD.samplers[0].textureColorOp = GFXTOPDisable; + + // DepthBuffer sampler + descD.samplers[1].addressModeU = GFXAddressClamp; + descD.samplers[1].addressModeV = GFXAddressClamp; + descD.samplers[1].addressModeW = GFXAddressClamp; + descD.samplers[1].magFilter = GFXTextureFilterLinear; + descD.samplers[1].minFilter = GFXTextureFilterLinear; + descD.samplers[1].mipFilter = GFXTextureFilterLinear; + descD.samplers[1].textureColorOp = GFXTOPModulate; + + // FrontBuffer sampler + descD.samplers[2].addressModeU = GFXAddressClamp; + descD.samplers[2].addressModeV = GFXAddressClamp; + descD.samplers[2].addressModeW = GFXAddressClamp; + descD.samplers[2].magFilter = GFXTextureFilterLinear; + descD.samplers[2].minFilter = GFXTextureFilterLinear; + descD.samplers[2].mipFilter = GFXTextureFilterLinear; + descD.samplers[2].textureColorOp = GFXTOPModulate; + + // animated density modifier map sampler + descD.samplers[3].addressModeU = GFXAddressWrap; + descD.samplers[3].addressModeV = GFXAddressWrap; + descD.samplers[3].addressModeW = GFXAddressWrap; + descD.samplers[3].magFilter = GFXTextureFilterLinear; + descD.samplers[3].minFilter = GFXTextureFilterLinear; + descD.samplers[3].mipFilter = GFXTextureFilterLinear; + descD.samplers[3].textureColorOp = GFXTOPModulate; + + dMemcpy(&descF, &descD, sizeof(GFXStateBlockDesc)); + descF.setCullMode(GFXCullCCW); + descF.setBlend(true); + descF.setZReadWrite(true, false); + + desc_refl.setCullMode(GFXCullCCW); + desc_refl.setBlend(true); + desc_refl.setZReadWrite(true, false); + + mStateblock_preD = GFX->createStateBlock(desc_preD); + mStateblock_preF = GFX->createStateBlock(desc_preF); + mStateblockD = GFX->createStateBlock(descD); + mStateblockF = GFX->createStateBlock(descF); + mStateblock_refl = GFX->createStateBlock(desc_refl); + + // Create Rendertarget + + z_buf = GFX->allocRenderToTextureTarget(); + if (z_buf == NULL) + { + Con::errorf("VolumetricFog::setupRenderer - Could not create Render Target"); + return false; + } + + return true; +} + +void VolumetricFog::prepRenderImage(SceneRenderState *state) +{ + if (!mShapeLoaded || mFogDensity <= 0.0f || mResizing) + return; + + if (!state->isDiffusePass()) + { + if (!state->isReflectPass()) + return; + } + + PROFILE_SCOPE(VolumetricFog_prepRenderImage); + + // Time critical therefore static_cast + ShapeBase* control = static_cast(conn->getControlObject()); + if (control->getWaterCoverage() >= 0.9f && !mIgnoreWater) + return; + + camPos = state->getCameraPosition(); + F32 dist = (camPos - getBoxCenter()).len(); + F32 scaleFactor = dist * mInvScale; + if (scaleFactor <= 0.0f) + { + if (mCurDetailLevel != 0) + UpdateBuffers(0); + } + const F32 pixelScale = state->getViewport().extent.y / 300.0f; + + mPixelSize = (mRadius / scaleFactor) * state->getWorldToScreenScale().y * pixelScale; + if (mPixelSize < mMinDisplaySize) + return; + if (mNumDetailLevels > 1) + { + if ((det_size[mCurDetailLevel].det_size > mPixelSize) && (mCurDetailLevel < mNumDetailLevels - 1)) + UpdateBuffers(mCurDetailLevel + 1); + else if (mCurDetailLevel > 0) + { + if (mPixelSize >= det_size[mCurDetailLevel - 1].det_size) + UpdateBuffers(mCurDetailLevel - 1); + } + } + + if (state->isReflectPass() && mReflect) + { + ObjectRenderInst *ri = state->getRenderPass()->allocInst(); + ri->renderDelegate.bind(this, &VolumetricFog::reflect_render); + ri->type = RenderPassManager::RIT_VolumetricFog; + ri->translucentSort = true; + ri->sortDistSq = getRenderWorldBox().getSqDistanceToPoint(camPos); + if (dist < 1.0f) + ri->defaultKey = 1; + else + ri->defaultKey = U32(dist); + state->getRenderPass()->addInst(ri); + return; + } + else if (state->isDiffusePass()) + { + viewDist = state->getFarPlane(); + mFOV = state->getCameraFrustum().getFov() / M_PI_F; + Point3F mEyeVec = state->getVectorEye() * viewDist; + + mViewPoint.x = ((mAtan2(mEyeVec.x, mEyeVec.y) / M_PI_F) + 1.0f) * mTexTiles; + mViewPoint.y = (0.5f - (mAsin(mEyeVec.z) / M_PI_F)) * mTexTiles; + + bool isInside = ColBox.isContained(camPos); + if (isInside && !mCamInFog) + { + mCamInFog = true; + _enterFog(control); + } + else if (!isInside && mCamInFog) + mCamInFog = false; + + ObjectRenderInst *ri = state->getRenderPass()->allocInst(); + ri->renderDelegate.bind(this, &VolumetricFog::render); + ri->type = RenderPassManager::RIT_VolumetricFog; + ri->translucentSort = true; + ri->sortDistSq = getRenderWorldBox().getSqDistanceToPoint(camPos); + if (dist < 1.0f) + ri->defaultKey = 1; + else + ri->defaultKey = U32(dist); + state->getRenderPass()->addInst(ri); + return; + } + return; +} + +void VolumetricFog::render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat) +{ + if (overrideMat || !mShapeLoaded || !isClientObject() || mResizing) + return; + + PROFILE_SCOPE(VolumetricFog_Render); + + GFXTransformSaver saver; + GFX->setVertexBuffer(mVB); + GFX->setPrimitiveBuffer(mPB); + + MatrixF mat = getRenderTransform(); + mat.scale(mObjScale); + GFX->multWorld(mat); + + GFX->setShader(mPrePassShader); + GFX->setShaderConstBuffer(mPPShaderConsts); + GFX->setStateBlock(mStateblock_preD); + + // Set all the shader consts... + + MatrixF xform(GFX->getProjectionMatrix()); + xform *= GFX->getViewMatrix(); + xform *= GFX->getWorldMatrix(); + + mPPShaderConsts->setSafe(mPPModelViewProjSC, xform); + + LightInfo *lightinfo = LIGHTMGR->getSpecialLight(LightManager::slSunLightType); + const ColorF &sunlight = state->getAmbientLightColor(); + + Point3F ambientColor(sunlight.red, sunlight.green, sunlight.blue); + mShaderConsts->setSafe(mAmbientColorSC, ambientColor); + + GFXTextureObject *mDepthBuffer = mDepthBufferTarget ? mDepthBufferTarget->getTexture(0) : NULL; + GFXTextureObject *mFrontBuffer = mFrontBufferTarget ? mFrontBufferTarget->getTexture(0) : NULL; + + GFX->pushActiveRenderTarget(); + + //render backside to target mDepthBuffer + z_buf->attachTexture(GFXTextureTarget::DepthStencil, GFXTextureTarget::sDefaultDepthStencil); + z_buf->attachTexture(GFXTextureTarget::Color0, mDepthBuffer); + + GFX->setActiveRenderTarget(z_buf); + GFX->clear(GFXClearStencil | GFXClearTarget , ColorI(0,0,0,0), 1.0f, 0); + + GFX->drawPrimitive(0); + z_buf->resolve(); + + //render frontside to target mFrontBuffer + z_buf->attachTexture(GFXTextureTarget::DepthStencil, GFXTextureTarget::sDefaultDepthStencil); + z_buf->attachTexture(GFXTextureTarget::Color0, mFrontBuffer); + GFX->clear(GFXClearStencil | GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0); + + GFX->setStateBlock(mStateblock_preF); + + GFX->drawPrimitive(0); + z_buf->resolve(); + + GFX->popActiveRenderTarget(); + z_buf->attachTexture(GFXTextureTarget::Color0, NULL); + + //render Volumetric Fog + GFX->setShader(mShader); + GFX->setShaderConstBuffer(mShaderConsts); + + mShaderConsts->setSafe(mModelViewProjSC, xform); + if (mFadeSize > 0.0f) + mShaderConsts->setSafe(mFadeSizeSC, mClampF(mPixelSize / mFadeSize, 0.0f, 1.0f)); + else + mShaderConsts->setSafe(mFadeSizeSC, 1.0f); + mShaderConsts->setSafe(mFogColorSC, mFogColor); + mShaderConsts->setSafe(mFogDensitySC, mFogDensity); + mShaderConsts->setSafe(mPreBias, viewDist); + mShaderConsts->setSafe(mAccumTime, (F32)Sim::getCurrentTime() / 1000.0f); + mShaderConsts->setSafe(mModStrengthSC, mStrength); + mShaderConsts->setSafe(mModSpeedSC, mSpeed); + mShaderConsts->setSafe(mViewPointSC, mViewPoint); + mShaderConsts->setSafe(mTexScaleSC, mTexScale * mFOV); + mShaderConsts->setSafe(mTexTilesSC, mTexTiles); + + GFXTextureObject *prepasstex = mPrepassTarget ? mPrepassTarget->getTexture(0) : NULL; + + GFX->setTexture(0, prepasstex); + GFX->setTexture(1, mDepthBuffer); + GFX->setTexture(2, mFrontBuffer); + + if (mIsTextured && mStrength > 0.0f) + { + GFX->setTexture(3, mTexture); + mShaderConsts->setSafe(mIsTexturedSC, 1.0f); + } + else + mShaderConsts->setSafe(mIsTexturedSC, 0.0f); + + if (mCamInFog) + { + /*GFXLockedRect *rect=mDepthBuffer->lock(); + U32 pixoffset = 0;// 1572864 + (512 * 4); + U8 red = rect->bits[pixoffset]; + U8 green = rect->bits[pixoffset+1]; + U8 blue = rect->bits[pixoffset+2]; + U8 alpha = rect->bits[pixoffset+3]; + mDepthBuffer->unlock(); + S32 lval = ((alpha << 24) + (blue << 16) + (green << 8) + (red)); + F32 fval = ((F32)lval / S32_MAX); + Con::printf("Color %d %d %d %d %d %f", red, green, blue, alpha, lval, fval);*/ + GFX->setStateBlock(mStateblockD); + } + else + GFX->setStateBlock(mStateblockF); + + GFX->drawPrimitive(0); +} + +void VolumetricFog::reflect_render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat) +{ + if (overrideMat || !mShapeLoaded || !isClientObject() || mResizing || (mFogReflStrength==0.0f)) + return; + + GFXTransformSaver saver; + GFX->setVertexBuffer(mVB); + GFX->setPrimitiveBuffer(mPB); + + MatrixF mat = getRenderTransform(); + mat.scale(mObjScale); + GFX->multWorld(mat); + + GFX->setShader(mReflectionShader); + GFX->setShaderConstBuffer(mReflShaderConsts); + GFX->setStateBlock(mStateblock_refl); + + // Set all the shader consts... + MatrixF xform(GFX->getProjectionMatrix()); + xform *= GFX->getViewMatrix(); + xform *= GFX->getWorldMatrix(); + + mReflShaderConsts->setSafe(mReflModelViewProjSC, xform); + mReflShaderConsts->setSafe(mReflFogColorSC, mFogColor); + mReflShaderConsts->setSafe(mReflFogDensitySC, mFogDensity); + mReflShaderConsts->setSafe(mReflFogStrengthSC, mFogReflStrength); + + GFX->drawPrimitive(0); +} + +//----------------------------------------------------------------------------- +// InitTexture is called whenever a modulation texture is added to the object +//----------------------------------------------------------------------------- + +void VolumetricFog::InitTexture() +{ + mIsTextured = false; + + if (mTextureName.isNotEmpty()) + mTexture.set(mTextureName, &GFXDefaultStaticDiffuseProfile, "VolumetricFogMod"); + + if (!mTexture.isNull()) + { + mIsTextured = true; + + F32 width = (F32)mPlatformWindow->getClientExtent().x; + F32 height = (F32)mPlatformWindow->getClientExtent().y; + + if (!mPlatformWindow->isFullscreen()) + height -= 20;//subtract caption bar from rendertarget size. + + mTexScale.x = 2.0f - ((F32)mTexture.getWidth() / width); + mTexScale.y = 2.0f - ((F32)mTexture.getHeight() / height); + } +} + +void VolumetricFog::setFogColor(ColorF color) +{ + mFogColor.set(255 * color.red,255 * color.green,255 * color.blue); + setMaskBits(FogColorMask); +} + +void VolumetricFog::setFogColor(ColorI color) +{ + mFogColor = color; + setMaskBits(FogColorMask); +} + +void VolumetricFog::setFogDensity(F32 density) +{ + if (density < 0.0f) + density = 0.0f; + mFogDensity = density; + setMaskBits(FogDensityMask); +} + +void VolumetricFog::setFogModulation(F32 strength,Point2F speed1,Point2F speed2) +{ + mStrength = strength; + mSpeed1 = speed1; + mSpeed2 = speed2; + mSpeed.set(speed1.x, speed1.y, speed2.x, speed2.y); + setMaskBits(FogModulationMask); +} + +void VolumetricFog::setFogGlow(bool on_off, F32 strength) +{ + mUseGlow = on_off; + mGlowStrength = strength; + setMaskBits(FogPostFXMask); +} + +void VolumetricFog::setFogLightray(bool on_off, F32 strength) +{ + mModifLightRays = on_off; + mLightRayMod = strength; + setMaskBits(FogPostFXMask); +} + +bool VolumetricFog::isInsideFog() +{ + return mCamInFog; +} + +DefineEngineMethod(VolumetricFog, SetFogColorF, void, (ColorF new_color), , +"@brief Changes the color of the fog\n\n." +"@params new_color the new fog color (rgb 0.0 - 1.0, a is ignored.") +{ + object->setFogColor(new_color); +} + +DefineEngineMethod(VolumetricFog, SetFogColor, void, (ColorI new_color), , +"@brief Changes the color of the fog\n\n." +"@params new_color the new fog color (rgb 0-255, a is ignored.") +{ + object->setFogColor(new_color); +} + +DefineEngineMethod(VolumetricFog, SetFogDensity, void, (F32 new_density), , +"@brief Changes the density of the fog\n\n." +"@params new_density the new fog density.") +{ + object->setFogDensity(new_density); +} + +DefineEngineMethod(VolumetricFog, SetFogModulation, void, (F32 new_strenght, Point2F new_speed1, Point2F new_speed2), , +"@brief Changes the modulation of the fog\n\n." +"@params new_strenght the new strength of the modulation.\n" +"@params new_speed1 the new speed (x y) of the modulation layer 1.\n" +"@params new_speed2 the new speed (x y) of the modulation layer 2.\n") +{ + object->setFogModulation(new_strenght, new_speed1, new_speed2); +} + +DefineEngineMethod(VolumetricFog, SetFogGlow, void, (bool on_off,F32 strength), , +"@brief Changes the glow postfx when inside the fog\n\n." +"@params on_off set to true to enable glow.\n" +"@params strength glow strength.\n") +{ + object->setFogGlow(on_off, strength); +} + +DefineEngineMethod(VolumetricFog, SetFogLightray, void, (bool on_off, F32 strength), , +"@brief Changes the lightrays postfx when inside the fog\n\n." +"@params on_off set to true to modification of the lightray postfx.\n" +"@params strength lightray strength.\n") +{ + object->setFogLightray(on_off, strength); +} + +DefineEngineMethod(VolumetricFog, isInsideFog, bool, (), , +"@brief returns true if control object is inside the fog\n\n.") +{ + return object->isInsideFog(); +} \ No newline at end of file diff --git a/Engine/source/environment/VolumetricFog.h b/Engine/source/environment/VolumetricFog.h new file mode 100644 index 000000000..ef2f39929 --- /dev/null +++ b/Engine/source/environment/VolumetricFog.h @@ -0,0 +1,243 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _VolumetricFog_H_ +#define _VolumetricFog_H_ + +#ifndef _SCENEOBJECT_H_ +#include "scene/sceneObject.h" +#endif +#ifndef _MATTEXTURETARGET_H_ +#include "materials/matTextureTarget.h" +#endif +#ifndef _GFXSHADER_H_ +#include "gfx/gfxShader.h" +#endif +#ifndef _GFXTARGET_H_ +#include "gfx/gfxTarget.h" +#endif +#ifndef _GFXVERTEXBUFFER_H_ +#include "gfx/gfxVertexBuffer.h" +#endif +#ifndef _TSSHAPE_H_ +#include "ts/tsShape.h" +#endif +#ifndef _POST_EFFECT_H_ +#include "postFx/postEffect.h" +#endif + +#include "gui/core/guiCanvas.h" + +class VolumetricFogRTManager; + +class VolumetricFog : public SceneObject +{ + typedef SceneObject Parent; + + // Maskbits for updating + enum + { + VolumetricFogMask = Parent::NextFreeMask, + FogColorMask = Parent::NextFreeMask << 1, + FogDensityMask = Parent::NextFreeMask << 2, + FogModulationMask = Parent::NextFreeMask << 3, + FogPostFXMask = Parent::NextFreeMask << 4, + FogShapeMask = Parent::NextFreeMask << 5, + NextFreeMask = Parent::NextFreeMask << 6 + }; + +// Struct which holds the shape details + struct meshes + { + F32 det_size; + S32 sub_shape; + S32 obj_det; + U32 num_verts; + GFXVertexPNTT *verts; + Vector *piArray; + Vector *indices; + }; + + protected: + // Rendertargets; + GFXTextureTargetRef z_buf; + NamedTexTargetRef mPrepassTarget; + NamedTexTargetRef mDepthBufferTarget; + NamedTexTargetRef mFrontBufferTarget; + + // Fog Modulation texture + GFXTexHandle mTexture; + + // Shaders + GFXShaderRef mShader; + GFXShaderRef mPrePassShader; + GFXShaderRef mReflectionShader; + + // Stateblocks + GFXStateBlockDesc descD; + GFXStateBlockDesc descF; + GFXStateBlockDesc desc_preD; + GFXStateBlockDesc desc_preF; + GFXStateBlockDesc desc_refl; + + GFXStateBlockRef mStateblockD; + GFXStateBlockRef mStateblockF; + GFXStateBlockRef mStateblock_preD; + GFXStateBlockRef mStateblock_preF; + GFXStateBlockRef mStateblock_refl; + + // Shaderconstants + GFXShaderConstBufferRef mShaderConsts; + GFXShaderConstHandle *mModelViewProjSC; + GFXShaderConstHandle *mFadeSizeSC; + GFXShaderConstHandle *mFogColorSC; + GFXShaderConstHandle *mFogDensitySC; + GFXShaderConstHandle *mPreBias; + GFXShaderConstHandle *mAccumTime; + GFXShaderConstHandle *mIsTexturedSC; + GFXShaderConstHandle *mModSpeedSC; + GFXShaderConstHandle *mModStrengthSC; + GFXShaderConstHandle *mViewPointSC; + GFXShaderConstHandle *mTexScaleSC; + GFXShaderConstHandle *mTexTilesSC; + + GFXShaderConstBufferRef mPPShaderConsts; + GFXShaderConstHandle *mPPModelViewProjSC; + + GFXShaderConstHandle *mAmbientColorSC; + + GFXShaderConstBufferRef mReflShaderConsts; + GFXShaderConstHandle *mReflModelViewProjSC; + GFXShaderConstHandle *mReflFogColorSC; + GFXShaderConstHandle *mReflFogDensitySC; + GFXShaderConstHandle *mReflFogStrengthSC; + + // Vertex and Prim. Buffer + GFXVertexBufferHandle mVB; + GFXPrimitiveBufferHandle mPB; + + // Fog volume data; + StringTableEntry mShapeName; + ColorI mFogColor; + F32 mFogDensity; + bool mIgnoreWater; + bool mReflect; + Vector det_size; + bool mShapeLoaded; + F32 mPixelSize; + F32 mFadeSize; + U32 mCurDetailLevel; + U32 mNumDetailLevels; + F32 mObjSize; + F32 mRadius; + OrientedBox3F ColBox; + VectorF mObjScale; + F32 mMinDisplaySize; + F32 mInvScale; + + // Fog Modulation data + String mTextureName; + bool mIsTextured; + F32 mTexTiles; + F32 mStrength; + Point2F mSpeed1; + Point2F mSpeed2; + Point4F mSpeed; + Point2F mTexScale; + + // Fog Rendering data + Point3F camPos; + Point2F mViewPoint; + F32 mFOV; + F32 viewDist; + bool mIsVBDirty; + bool mIsPBDirty; + bool mCamInFog; + bool mResizing; + PlatformWindow *mPlatformWindow; + + // Reflections + F32 mFogReflStrength; + + // PostFX + PostEffect *glowFX; + bool mUseGlow; + F32 mGlowStrength; + U8 mGlowing; + F32 mCurGlow; + + bool mModifLightRays; + F32 mLightRayMod; + F32 mOldLightRayStrength; + + GameConnection* conn; + U32 mCounter; + + void ResizeRT(PlatformWindow *win, bool resize); + + protected: + // Protected methods + bool onAdd(); + void onRemove(); + void handleResize(VolumetricFogRTManager *RTM, bool resize); + void handleCanvasResize(GuiCanvas* canvas); + + bool LoadShape(); + bool setupRenderer(); + void InitTexture(); + bool UpdateBuffers(U32 dl,bool force=true); + + void processTick(const Move *move); + void _enterFog(ShapeBase *control); + void _leaveFog(ShapeBase *control); + + public: + // Public methods + VolumetricFog(); + ~VolumetricFog(); + + static void initPersistFields(); + virtual void inspectPostApply(); + + U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream); + void unpackUpdate(NetConnection *conn, BitStream *stream); + + void prepRenderImage(SceneRenderState* state); + void render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat); + void reflect_render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat); + + // Methods for modifying & networking various fog elements + // Used in script + void setFogColor(ColorF color); + void setFogColor(ColorI color); + void setFogDensity(F32 density); + void setFogModulation(F32 strength, Point2F speed1, Point2F speed2); + void setFogGlow(bool on_off, F32 strength); + void setFogLightray(bool on_off, F32 strength); + bool isInsideFog(); + + DECLARE_CONOBJECT(VolumetricFog); + + DECLARE_CALLBACK(void, onEnterFog, (SimObjectId obj)); + DECLARE_CALLBACK(void, onLeaveFog, (SimObjectId obj)); +}; +#endif \ No newline at end of file diff --git a/Engine/source/environment/VolumetricFogRTManager.cpp b/Engine/source/environment/VolumetricFogRTManager.cpp new file mode 100644 index 000000000..2a927cc09 --- /dev/null +++ b/Engine/source/environment/VolumetricFogRTManager.cpp @@ -0,0 +1,299 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Volumetric Fog Rendertarget Manager +// +// Creates and maintains one set of rendertargets to be used by every +// VolumetricFog object in the scene. +// +// Will be loaded at startup end removed when ending game. +// +//----------------------------------------------------------------------------- + +#include "VolumetricFogRTManager.h" +#include "core/module.h" +#include "scene/sceneManager.h" +#include "windowManager/platformWindowMgr.h" +#include "console/engineAPI.h" +#include "gui/core/guiCanvas.h" + +MODULE_BEGIN(VolumetricFogRTManager) + +MODULE_INIT_AFTER(Scene) +MODULE_SHUTDOWN_BEFORE(Scene) + +MODULE_INIT +{ + gVolumetricFogRTManager = new VolumetricFogRTManager; + gClientSceneGraph->addObjectToScene(gVolumetricFogRTManager); +} + +MODULE_SHUTDOWN +{ + gClientSceneGraph->removeObjectFromScene(gVolumetricFogRTManager); + SAFE_DELETE(gVolumetricFogRTManager); +} + +MODULE_END; + +ConsoleDocClass( VolumetricFogRTManager, +"@brief Creates and maintains one set of rendertargets to be used by every\n" +"VolumetricFog object in the scene.\n\n" +"Will be loaded at startup end removed when ending game.\n\n" +"Methods:\n" +" get() returns the currently loaded VolumetricFogRTManager, also accessible\n" +" through VFRTM define.\n" +" Init() Initializes the rendertargets, called when a VolumetricFog object is\n" +" added to the scene.\n" +" isInitialed() returns true if Rendertargets are present, false if not, then\n" +" Init() should be called to create the rendertargets.\n" +" setQuality(U32 Quality) Normally a rendertarget has the same size as the view,\n" +" with this method you can scale down the size of it.\n" +" Be aware that scaling down will introduce renderartefacts.\n" +"@ingroup Atmosphere" +); + +VolumetricFogRTMResizeSignal VolumetricFogRTManager::smVolumetricFogRTMResizeSignal; + +VolumetricFogRTManager *gVolumetricFogRTManager = NULL; + +S32 VolumetricFogRTManager::mTargetScale = 1; + +IMPLEMENT_CONOBJECT(VolumetricFogRTManager); + +VolumetricFogRTManager::VolumetricFogRTManager() +{ + setGlobalBounds(); + mTypeMask |= EnvironmentObjectType; + mNetFlags.set(IsGhost); + mIsInitialized = false; + mNumFogObjects = 0; +} + +VolumetricFogRTManager::~VolumetricFogRTManager() +{ + if (mFrontTarget.isRegistered()) + mFrontTarget.unregister(); + + if (mDepthTarget.isRegistered()) + mDepthTarget.unregister(); + + if (mDepthBuffer.isValid()) + mDepthBuffer->kill(); + + if (mFrontBuffer.isValid()) + mFrontBuffer->kill(); +} + +void VolumetricFogRTManager::onSceneRemove() +{ + if (mIsInitialized) + mPlatformWindow->getScreenResChangeSignal().remove(this, &VolumetricFogRTManager::ResizeRT); +} + +void VolumetricFogRTManager::onRemove() +{ + removeFromScene(); + Parent::onRemove(); +} + +void VolumetricFogRTManager::consoleInit() +{ + Con::addVariable("$pref::VolumetricFog::Quality", TypeS32, &mTargetScale, + "The scale of the rendertargets.\n" + "@ingroup Rendering\n"); +} + +bool VolumetricFogRTManager::Init() +{ + if (mIsInitialized) + { + Con::errorf("VolumetricFogRTManager allready initialized!!"); + return true; + } + + GuiCanvas* cv = dynamic_cast(Sim::findObject("Canvas")); + if (cv == NULL) + { + Con::errorf("VolumetricFogRTManager::Init() - Canvas not found!!"); + return false; + } + + mPlatformWindow = cv->getPlatformWindow(); + mPlatformWindow->getScreenResChangeSignal().notify(this,&VolumetricFogRTManager::ResizeRT); + + if (mTargetScale < 1) + mTargetScale = 1; + + mWidth = mFloor(mPlatformWindow->getClientExtent().x / mTargetScale); + mHeight = mPlatformWindow->getClientExtent().y; + mFullScreen = mPlatformWindow->isFullscreen(); + if (!mFullScreen) + mHeight -= 20;//subtract caption bar from rendertarget size. + mHeight = mFloor(mHeight / mTargetScale); + + mDepthBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F, + &GFXDefaultRenderTargetProfile, avar("%s() - mDepthBuffer (line %d)", __FUNCTION__, __LINE__)); + if (!mDepthBuffer.isValid()) + { + Con::errorf("VolumetricFogRTManager Fatal Error: Unable to create Depthbuffer"); + return false; + } + if (!mDepthTarget.registerWithName("volfogdepth")) + { + Con::errorf("VolumetricFogRTManager Fatal Error : Unable to register Depthbuffer"); + return false; + } + mDepthTarget.setTexture(mDepthBuffer); + + mFrontBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F, + &GFXDefaultRenderTargetProfile, avar("%s() - mFrontBuffer (line %d)", __FUNCTION__, __LINE__)); + if (!mFrontBuffer.isValid()) + { + Con::errorf("VolumetricFogRTManager Fatal Error: Unable to create front buffer"); + return false; + } + if (!mFrontTarget.registerWithName("volfogfront")) + { + Con::errorf("VolumetricFogRTManager Fatal Error : Unable to register Frontbuffer"); + return false; + } + + mFrontTarget.setTexture(mFrontBuffer); + + Con::setVariable("$VolumetricFog::density", "0.0"); + + mIsInitialized = true; + + return true; +} + +U32 VolumetricFogRTManager::IncFogObjects() +{ + mNumFogObjects++; + return mNumFogObjects; +} + +U32 VolumetricFogRTManager::DecFogObjects() +{ + if (mNumFogObjects > 0) + mNumFogObjects--; + return mNumFogObjects; +} + +void VolumetricFogRTManager::ResizeRT(PlatformWindow* win,bool resize) +{ + mFogHasAnswered = 0; + smVolumetricFogRTMResizeSignal.trigger(this, true); +} + +void VolumetricFogRTManager::FogAnswered() +{ + mFogHasAnswered++; + if (mFogHasAnswered == mNumFogObjects) + { + if (Resize()) + smVolumetricFogRTMResizeSignal.trigger(this, false); + else + Con::errorf("VolumetricFogRTManager::FogAnswered - Error resizing rendertargets!"); + } +} + +bool VolumetricFogRTManager::Resize() +{ + if (mTargetScale < 1) + mTargetScale = 1; + mWidth = mFloor(mPlatformWindow->getClientExtent().x / mTargetScale); + mHeight = mPlatformWindow->getClientExtent().y; + + if (!mPlatformWindow->isFullscreen()) + mHeight -= 20;//subtract caption bar from rendertarget size. + mHeight = mFloor(mHeight / mTargetScale); + + if (mWidth < 16 || mHeight < 16) + return false; + + if (mFrontTarget.isRegistered()) + mFrontTarget.setTexture(NULL); + + if (mDepthTarget.isRegistered()) + mDepthTarget.setTexture(NULL); + + if (mDepthBuffer.isValid()) + mDepthBuffer->kill(); + + if (mFrontBuffer.isValid()) + mFrontBuffer->kill(); + + mFrontBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F, + &GFXDefaultRenderTargetProfile, avar("%s() - mFrontBuffer (line %d)", __FUNCTION__, __LINE__)); + if (!mFrontBuffer.isValid()) + { + Con::errorf("VolumetricFogRTManager::Resize() Fatal Error: Unable to create front buffer"); + return false; + } + mFrontTarget.setTexture(mFrontBuffer); + + mDepthBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F, + &GFXDefaultRenderTargetProfile, avar("%s() - mDepthBuffer (line %d)", __FUNCTION__, __LINE__)); + if (!mDepthBuffer.isValid()) + { + Con::errorf("VolumetricFogRTManager::Resize() Fatal Error: Unable to create Depthbuffer"); + return false; + } + mDepthTarget.setTexture(mDepthBuffer); + return true; +} + +S32 VolumetricFogRTManager::setQuality(U32 Quality) +{ + if (!mIsInitialized) + return (mTargetScale = Quality); + + if (Quality < 1) + Quality = 1; + + if (Quality == mTargetScale) + return mTargetScale; + + mTargetScale = Quality; + + mFogHasAnswered = 0; + smVolumetricFogRTMResizeSignal.trigger(this, true); + + return mTargetScale; +} + +VolumetricFogRTManager* VolumetricFogRTManager::get() +{ + return gVolumetricFogRTManager; +} + +DefineConsoleFunction(SetFogVolumeQuality, S32, (U32 new_quality), , +"@brief Resizes the rendertargets of the Volumetric Fog object.\n" +"@params new_quality new quality for the rendertargets 1 = full size, 2 = halfsize, 3 = 1/3, 4 = 1/4 ...") +{ + if (VFRTM == NULL) + return -1; + return VFRTM->setQuality(new_quality); +} \ No newline at end of file diff --git a/Engine/source/environment/VolumetricFogRTManager.h b/Engine/source/environment/VolumetricFogRTManager.h new file mode 100644 index 000000000..d69bed6bd --- /dev/null +++ b/Engine/source/environment/VolumetricFogRTManager.h @@ -0,0 +1,92 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _VolumetricFogRTManager_H_ +#define _VolumetricFogRTManager_H_ + +#ifndef _SCENEOBJECT_H_ +#include "scene/sceneObject.h" +#endif +#ifndef _MATTEXTURETARGET_H_ +#include "materials/matTextureTarget.h" +#endif +#ifndef _GFXTARGET_H_ +#include "gfx/gfxTarget.h" +#endif +#ifndef _SIGNAL_H_ +#include "core/util/tSignal.h" +#endif + +class VolumetricFogRTManager; + +typedef Signal VolumetricFogRTMResizeSignal; + +#define VFRTM VolumetricFogRTManager::get() + +class VolumetricFogRTManager : public SceneObject +{ + public: + typedef SceneObject Parent; + + protected: + GFXTexHandle mDepthBuffer; + GFXTexHandle mFrontBuffer; + + NamedTexTarget mDepthTarget; + NamedTexTarget mFrontTarget; + + PlatformWindow* mPlatformWindow; + + static S32 mTargetScale; + bool mIsInitialized; + U32 mNumFogObjects; + U32 mFogHasAnswered; + U32 mWidth; + U32 mHeight; + bool mFullScreen; + + void onRemove(); + void onSceneRemove(); + void ResizeRT(PlatformWindow *win, bool resize); + + static VolumetricFogRTMResizeSignal smVolumetricFogRTMResizeSignal; + + public: + VolumetricFogRTManager(); + ~VolumetricFogRTManager(); + static VolumetricFogRTManager *get(); + bool Init(); + bool IsInitialized() { return mIsInitialized; } + static void consoleInit(); + static VolumetricFogRTMResizeSignal& getVolumetricFogRTMResizeSignal() { return smVolumetricFogRTMResizeSignal; } + void FogAnswered(); + S32 setQuality(U32 Quality); + bool Resize(); + U32 IncFogObjects(); + U32 DecFogObjects(); + + DECLARE_CONOBJECT(VolumetricFogRTManager); +}; + +extern VolumetricFogRTManager* gVolumetricFogRTManager; + +#endif \ No newline at end of file diff --git a/Engine/source/environment/basicClouds.cpp b/Engine/source/environment/basicClouds.cpp index 185aa3a97..979579c2f 100644 --- a/Engine/source/environment/basicClouds.cpp +++ b/Engine/source/environment/basicClouds.cpp @@ -141,7 +141,7 @@ bool BasicClouds::onAdd() GFXStateBlockDesc desc; desc.setCullMode( GFXCullNone ); desc.setBlend( true ); - desc.setZReadWrite( false, false ); + desc.setZReadWrite( true, false ); desc.samplersDefined = true; desc.samplers[0].addressModeU = GFXAddressWrap; desc.samplers[0].addressModeV = GFXAddressWrap; diff --git a/Engine/source/environment/cloudLayer.cpp b/Engine/source/environment/cloudLayer.cpp index dca9faf00..3fe02368f 100644 --- a/Engine/source/environment/cloudLayer.cpp +++ b/Engine/source/environment/cloudLayer.cpp @@ -161,7 +161,7 @@ bool CloudLayer::onAdd() GFXStateBlockDesc desc; desc.setCullMode( GFXCullNone ); desc.setBlend( true ); - desc.setZReadWrite( false, false ); + desc.setZReadWrite( true, false ); desc.samplersDefined = true; desc.samplers[0].addressModeU = GFXAddressWrap; desc.samplers[0].addressModeV = GFXAddressWrap; diff --git a/Engine/source/environment/decalRoad.cpp b/Engine/source/environment/decalRoad.cpp index 3cde83149..1cea7ed4a 100644 --- a/Engine/source/environment/decalRoad.cpp +++ b/Engine/source/environment/decalRoad.cpp @@ -732,7 +732,7 @@ void DecalRoad::prepRenderImage( SceneRenderState* state ) MathUtils::getZBiasProjectionMatrix( gDecalBias, frustum, tempMat ); coreRI.projection = tempMat; - coreRI.type = RenderPassManager::RIT_Decal; + coreRI.type = RenderPassManager::RIT_DecalRoad; coreRI.vertBuff = &mVB; coreRI.primBuff = &mPB; coreRI.matInst = matInst; diff --git a/Engine/source/environment/scatterSky.cpp b/Engine/source/environment/scatterSky.cpp index 328a64187..dbdeef48b 100644 --- a/Engine/source/environment/scatterSky.cpp +++ b/Engine/source/environment/scatterSky.cpp @@ -955,12 +955,21 @@ void ScatterSky::_render( ObjectRenderInst *ri, SceneRenderState *state, BaseMat Point3F camPos2 = state->getCameraPosition(); MatrixF xfm(true); - xfm.setPosition(camPos2 - Point3F( 0, 0, mZOffset)); + GFX->multWorld(xfm); MatrixF xform(proj);//GFX->getProjectionMatrix()); xform *= GFX->getViewMatrix(); xform *= GFX->getWorldMatrix(); + if(state->isReflectPass()) + { + static MatrixF rotMat(EulerF(0.0, 0.0, M_PI_F)); + xform.mul(rotMat); + rotMat.set(EulerF(M_PI_F, 0.0, 0.0)); + xform.mul(rotMat); + } + xform.setPosition(xform.getPosition() - Point3F(0, 0, mZOffset)); + mShaderConsts->setSafe( mModelViewProjSC, xform ); mShaderConsts->setSafe( mMiscSC, miscParams ); mShaderConsts->setSafe( mSphereRadiiSC, sphereRadii ); diff --git a/Engine/source/environment/skyBox.cpp b/Engine/source/environment/skyBox.cpp index 6ed2174e5..83c9bb6e7 100644 --- a/Engine/source/environment/skyBox.cpp +++ b/Engine/source/environment/skyBox.cpp @@ -599,7 +599,8 @@ void SkyBox::_initMaterial() // We want to disable culling and z write. GFXStateBlockDesc desc; - desc.setCullMode( GFXCullCW ); + desc.setCullMode( GFXCullNone ); + desc.setBlend( true ); desc.setZReadWrite( true, false ); mMatInstance->addStateBlockDesc( desc ); diff --git a/Engine/source/environment/timeOfDay.cpp b/Engine/source/environment/timeOfDay.cpp index 49b069b64..a0ae2fc83 100644 --- a/Engine/source/environment/timeOfDay.cpp +++ b/Engine/source/environment/timeOfDay.cpp @@ -402,7 +402,7 @@ void TimeOfDay::_getSunColor( ColorF *outColor ) const //simple check if ( mColorTargets[0].elevation != 0.0f ) { - AssertFatal(0, "TimeOfDay::GetColor() - First elevation must be 0.0 radians") + AssertFatal(0, "TimeOfDay::GetColor() - First elevation must be 0.0 radians"); outColor->set(1.0f, 1.0f, 1.0f); //mBandMod = 1.0f; //mCurrentBandColor = color; @@ -411,7 +411,7 @@ void TimeOfDay::_getSunColor( ColorF *outColor ) const if ( mColorTargets[mColorTargets.size()-1].elevation != M_PI_F ) { - AssertFatal(0, "Celestails::GetColor() - Last elevation must be PI") + AssertFatal(0, "Celestails::GetColor() - Last elevation must be PI"); outColor->set(1.0f, 1.0f, 1.0f); //mBandMod = 1.0f; //mCurrentBandColor = color; diff --git a/Engine/source/gfx/D3D9/gfxD3D9CardProfiler.cpp b/Engine/source/gfx/D3D9/gfxD3D9CardProfiler.cpp index 988e3a4e2..c6b169614 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9CardProfiler.cpp +++ b/Engine/source/gfx/D3D9/gfxD3D9CardProfiler.cpp @@ -87,9 +87,11 @@ void GFXD3D9CardProfiler::setupCardCapabilities() bool canDoFourStageDetailBlend = ( caps.TextureOpCaps & D3DTEXOPCAPS_SUBTRACT ) && ( caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP ) && ( caps.MaxTextureBlendStages > 3 ); + bool canDoIndependentMrtBitDepth = (caps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS ? 1 : 0 ); setCapability( "lerpDetailBlend", canDoLERPDetailBlend ); setCapability( "fourStageDetailBlend", canDoFourStageDetailBlend ); + setCapability( "independentMrtBitDepth", canDoIndependentMrtBitDepth); } bool GFXD3D9CardProfiler::_queryCardCap(const String &query, U32 &foundResult) diff --git a/Engine/source/gfx/D3D9/gfxD3D9Device.cpp b/Engine/source/gfx/D3D9/gfxD3D9Device.cpp index 2ad550064..d3eb8ed8a 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9Device.cpp +++ b/Engine/source/gfx/D3D9/gfxD3D9Device.cpp @@ -731,7 +731,8 @@ void GFXD3D9Device::setShader( GFXShader *shader, bool force ) //----------------------------------------------------------------------------- GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, - GFXBufferType bufferType ) + GFXBufferType bufferType, + void* data ) { // Allocate a buffer to return GFXD3D9PrimitiveBuffer * res = new GFXD3D9PrimitiveBuffer(this, numIndices, numPrimitives, bufferType); @@ -741,12 +742,13 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer( U32 numIndices, D3DPOOL pool = D3DPOOL_DEFAULT; // Assumptions: - // - static buffers are write once, use many + // - static buffers are write rarely, use many // - dynamic buffers are write many, use many // - volatile buffers are write once, use once // You may never read from a buffer. switch(bufferType) { + case GFXBufferTypeImmutable: case GFXBufferTypeStatic: pool = isD3D9Ex() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED; break; @@ -781,6 +783,14 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer( U32 numIndices, D3D9Assert(mD3DDevice->CreateIndexBuffer( sizeof(U16) * numIndices , usage, GFXD3D9IndexFormat[GFXIndexFormat16], pool, &res->ib, 0), "Failed to allocate an index buffer."); } + + if(data) + { + void* dest; + res->lock(0, numIndices, &dest); + dMemcpy(dest, data, sizeof(U16) * numIndices); + res->unlock(); + } return res; } @@ -791,7 +801,8 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer( U32 numIndices, GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ) + GFXBufferType bufferType, + void* data) { PROFILE_SCOPE( GFXD3D9Device_allocVertexBuffer ); @@ -808,7 +819,7 @@ GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer( U32 numVerts, res->mNumVerts = 0; // Assumptions: - // - static buffers are write once, use many + // - static buffers are write rarely, use many // - dynamic buffers are write many, use many // - volatile buffers are write once, use once // You may never read from a buffer. @@ -850,6 +861,15 @@ GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer( U32 numVerts, } res->mNumVerts = numVerts; + + if(data) + { + void* dest; + res->lock(0, numVerts, &dest); + dMemcpy(dest, data, vertSize * numVerts); + res->unlock(); + } + return res; } diff --git a/Engine/source/gfx/D3D9/gfxD3D9Device.h b/Engine/source/gfx/D3D9/gfxD3D9Device.h index c928b1a0d..ef1c9be5d 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9Device.h +++ b/Engine/source/gfx/D3D9/gfxD3D9Device.h @@ -298,10 +298,12 @@ public: virtual GFXVertexBuffer* allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ); + GFXBufferType bufferType, + void* data = NULL ); virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, - GFXBufferType bufferType ); + GFXBufferType bufferType, + void* data = NULL ); virtual void deallocVertexBuffer( GFXD3D9VertexBuffer *vertBuff ); virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat ); virtual void setVertexDecl( const GFXVertexDecl *decl ); diff --git a/Engine/source/gfx/D3D9/pc/gfxD3D9PrimitiveBuffer.pc.cpp b/Engine/source/gfx/D3D9/pc/gfxD3D9PrimitiveBuffer.pc.cpp index 21bb586bb..32251438d 100644 --- a/Engine/source/gfx/D3D9/pc/gfxD3D9PrimitiveBuffer.pc.cpp +++ b/Engine/source/gfx/D3D9/pc/gfxD3D9PrimitiveBuffer.pc.cpp @@ -31,6 +31,7 @@ void GFXD3D9PrimitiveBuffer::lock(U32 indexStart, U32 indexEnd, void **indexPtr) U32 flags=0; switch(mBufferType) { + case GFXBufferTypeImmutable: case GFXBufferTypeStatic: // flags |= D3DLOCK_DISCARD; break; diff --git a/Engine/source/gfx/D3D9/pc/gfxPCD3D9Target.cpp b/Engine/source/gfx/D3D9/pc/gfxPCD3D9Target.cpp index d545b5ba2..415801263 100644 --- a/Engine/source/gfx/D3D9/pc/gfxPCD3D9Target.cpp +++ b/Engine/source/gfx/D3D9/pc/gfxPCD3D9Target.cpp @@ -31,6 +31,9 @@ #include "gfx/gfxDebugEvent.h" #include "windowManager/win32/win32Window.h" +#ifndef _GFXDEVICE_H_ +#include "gfx/gfxDevice.h" +#endif GFXPCD3D9TextureTarget::GFXPCD3D9TextureTarget() : mTargetSize( Point2I::Zero ), @@ -451,6 +454,7 @@ void GFXPCD3D9WindowTarget::createAdditionalSwapChain() void GFXPCD3D9WindowTarget::resetMode() { + GFX->beginReset(); mWindow->setSuppressReset(true); if (mSwapChain) @@ -509,6 +513,7 @@ void GFXPCD3D9WindowTarget::zombify() void GFXPCD3D9WindowTarget::resurrect() { + GFX->beginReset(); if(mImplicit) { setImplicitSwapChain(); diff --git a/Engine/source/gfx/Null/gfxNullDevice.cpp b/Engine/source/gfx/Null/gfxNullDevice.cpp index 315336c24..f22e3bc7a 100644 --- a/Engine/source/gfx/Null/gfxNullDevice.cpp +++ b/Engine/source/gfx/Null/gfxNullDevice.cpp @@ -276,14 +276,16 @@ GFXNullDevice::~GFXNullDevice() GFXVertexBuffer *GFXNullDevice::allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ) + GFXBufferType bufferType, + void* data ) { return new GFXNullVertexBuffer(GFX, numVerts, vertexFormat, vertSize, bufferType); } GFXPrimitiveBuffer *GFXNullDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, - GFXBufferType bufferType) + GFXBufferType bufferType, + void* data ) { return new GFXNullPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType); } diff --git a/Engine/source/gfx/Null/gfxNullDevice.h b/Engine/source/gfx/Null/gfxNullDevice.h index 5e137cf01..28d6ad4e9 100644 --- a/Engine/source/gfx/Null/gfxNullDevice.h +++ b/Engine/source/gfx/Null/gfxNullDevice.h @@ -115,10 +115,12 @@ protected: virtual GFXVertexBuffer *allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ); + GFXBufferType bufferType, + void* data = NULL ); virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, - GFXBufferType bufferType ); + GFXBufferType bufferType, + void* data = NULL ); virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat ) { return NULL; } virtual void setVertexDecl( const GFXVertexDecl *decl ) { } diff --git a/Engine/source/gfx/bitmap/gBitmap.cpp b/Engine/source/gfx/bitmap/gBitmap.cpp index 151a792ed..78454d5e3 100644 --- a/Engine/source/gfx/bitmap/gBitmap.cpp +++ b/Engine/source/gfx/bitmap/gBitmap.cpp @@ -326,7 +326,7 @@ void GBitmap::allocateBitmap(const U32 in_width, const U32 in_height, const bool mNumMipLevels++; allocPixels += currWidth * currHeight * mBytesPerPixel; - } while (currWidth != 1 || currHeight != 1); + } while (currWidth != 1 && currHeight != 1); } AssertFatal(mNumMipLevels <= c_maxMipLevels, "GBitmap::allocateBitmap: too many miplevels"); diff --git a/Engine/source/gfx/bitmap/loaders/bitmapTga.cpp b/Engine/source/gfx/bitmap/loaders/bitmapTga.cpp index 15812ff9b..dff46bf03 100644 --- a/Engine/source/gfx/bitmap/loaders/bitmapTga.cpp +++ b/Engine/source/gfx/bitmap/loaders/bitmapTga.cpp @@ -483,7 +483,7 @@ static bool sReadTGA(Stream &stream, GBitmap *bitmap) static bool sWriteTGA(GBitmap *bitmap, Stream &stream, U32 compressionLevel) { - AssertISV(false, "GBitmap::writeTGA - doesn't support writing tga files!") + AssertISV(false, "GBitmap::writeTGA - doesn't support writing tga files!"); return false; } diff --git a/Engine/source/gfx/gfxDevice.cpp b/Engine/source/gfx/gfxDevice.cpp index c72c109d0..3f63fb884 100644 --- a/Engine/source/gfx/gfxDevice.cpp +++ b/Engine/source/gfx/gfxDevice.cpp @@ -148,7 +148,7 @@ GFXDevice::GFXDevice() mGlobalAmbientColor = ColorF(0.0f, 0.0f, 0.0f, 1.0f); mLightMaterialDirty = false; - dMemset(&mCurrentLightMaterial, NULL, sizeof(GFXLightMaterial)); + dMemset(&mCurrentLightMaterial, 0, sizeof(GFXLightMaterial)); // State block mStateBlockDirty = false; diff --git a/Engine/source/gfx/gfxDevice.h b/Engine/source/gfx/gfxDevice.h index b9ff01e8c..aa7ba0edf 100644 --- a/Engine/source/gfx/gfxDevice.h +++ b/Engine/source/gfx/gfxDevice.h @@ -302,6 +302,7 @@ protected: /// This will allow querying to see if a device is initialized and ready to /// have operations performed on it. bool mInitialized; + bool mReset; /// This is called before this, or any other device, is deleted in the global destroy() /// method. It allows the device to clean up anything while everything is still valid. @@ -326,6 +327,10 @@ public: /// @see endScene bool canCurrentlyRender() const { return mCanCurrentlyRender; } + bool recentlyReset(){ return mReset; } + void beginReset(){ mReset = true; } + void finalizeReset(){ mReset = false; } + void setAllowRender( bool render ) { mAllowRender = render; } inline bool allowRender() const { return mAllowRender; } @@ -637,7 +642,8 @@ protected: virtual GFXVertexBuffer *allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ) = 0; + GFXBufferType bufferType, + void* data = NULL ) = 0; /// Called from GFXVertexFormat to allocate the hardware /// specific vertex declaration for rendering. @@ -674,7 +680,8 @@ protected: /// @note All index buffers use unsigned 16-bit indices. virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, - GFXBufferType bufferType ) = 0; + GFXBufferType bufferType, + void* data = NULL ) = 0; /// @} diff --git a/Engine/source/gfx/gfxDrawUtil.cpp b/Engine/source/gfx/gfxDrawUtil.cpp index 1e677685e..34b1c8872 100644 --- a/Engine/source/gfx/gfxDrawUtil.cpp +++ b/Engine/source/gfx/gfxDrawUtil.cpp @@ -526,10 +526,10 @@ void GFXDrawUtil::drawRectFill( const Point2F &upperLeft, const Point2F &lowerRi F32 ulOffset = 0.5f - mDevice->getFillConventionOffset(); - verts[0].point.set( upperLeft.x+nw.x+ulOffset, upperLeft.y+nw.y+ulOffset, 0.0f ); - verts[1].point.set( lowerRight.x+ne.x, upperLeft.y+ne.y+ulOffset, 0.0f ); - verts[2].point.set( upperLeft.x-ne.x+ulOffset, lowerRight.y-ne.y, 0.0f ); - verts[3].point.set( lowerRight.x-nw.x, lowerRight.y-nw.y, 0.0f ); + verts[0].point.set( upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset, 0.0f); + verts[1].point.set( lowerRight.x + ne.x + ulOffset, upperLeft.y + ne.y + ulOffset, 0.0f); + verts[2].point.set( upperLeft.x - ne.x + ulOffset, lowerRight.y - ne.y + ulOffset, 0.0f); + verts[3].point.set( lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset, 0.0f); for (S32 i=0; i<4; i++) verts[i].color = color; diff --git a/Engine/source/gfx/gfxEnums.h b/Engine/source/gfx/gfxEnums.h index 9dfba2f73..e0c560ac8 100644 --- a/Engine/source/gfx/gfxEnums.h +++ b/Engine/source/gfx/gfxEnums.h @@ -39,8 +39,8 @@ enum GFXBufferType { - GFXBufferTypeStatic, ///< Static vertex buffers are created and filled one time. - ///< incur a performance penalty. Resizing a static vertex buffer is not + GFXBufferTypeStatic, ///< Static vertex buffers are created and rarely updated. + ///< Updating might incur a performance penalty. Resizing a static vertex buffer is not ///< allowed. GFXBufferTypeDynamic, ///< Dynamic vertex buffers are meant for vertices that can be changed ///< often. Vertices written into dynamic vertex buffers will remain valid @@ -48,7 +48,8 @@ enum GFXBufferType ///< allowed. GFXBufferTypeVolatile, ///< Volatile vertex or index buffers are meant for vertices or indices that are essentially ///< only used once. They can be resized without any performance penalty. - + GFXBufferTypeImmutable, ///< Immutable buffers must specify the data when creating the buffer. Cannot be modified. + GFXBufferType_COUNT ///< Number of buffer types. }; diff --git a/Engine/source/gfx/gfxPrimitiveBuffer.cpp b/Engine/source/gfx/gfxPrimitiveBuffer.cpp index 9a0a09119..2a06f53e2 100644 --- a/Engine/source/gfx/gfxPrimitiveBuffer.cpp +++ b/Engine/source/gfx/gfxPrimitiveBuffer.cpp @@ -80,3 +80,16 @@ void GFXPrimitiveBufferHandle::set(GFXDevice *theDevice, U32 indexCount, U32 pri getPointer()->mDebugCreationPath = desc; #endif } + +//----------------------------------------------------------------------------- +// immutable +//----------------------------------------------------------------------------- +void GFXPrimitiveBufferHandle::immutable(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, void* data, String desc) +{ + StrongRefPtr::operator=( theDevice->allocPrimitiveBuffer(indexCount, primitiveCount, GFXBufferTypeImmutable, data) ); + +#ifdef TORQUE_DEBUG + if( desc.isNotEmpty() ) + getPointer()->mDebugCreationPath = desc; +#endif +} diff --git a/Engine/source/gfx/gfxPrimitiveBuffer.h b/Engine/source/gfx/gfxPrimitiveBuffer.h index c2955786c..9fa6ed14f 100644 --- a/Engine/source/gfx/gfxPrimitiveBuffer.h +++ b/Engine/source/gfx/gfxPrimitiveBuffer.h @@ -140,6 +140,8 @@ public: } void set(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, GFXBufferType bufferType, String desc = String::EmptyString ); + + void immutable(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, void* data, String desc = String::EmptyString ); void lock(U16 **indexBuffer, GFXPrimitive **primitiveBuffer = NULL, U32 indexStart = 0, U32 indexEnd = 0) { diff --git a/Engine/source/gfx/gfxTextureManager.cpp b/Engine/source/gfx/gfxTextureManager.cpp index e367ed883..b656fcffd 100644 --- a/Engine/source/gfx/gfxTextureManager.cpp +++ b/Engine/source/gfx/gfxTextureManager.cpp @@ -1099,7 +1099,7 @@ void GFXTextureManager::_validateTexParams( const U32 width, const U32 height, currHeight = 1; inOutNumMips++; - } while ( currWidth != 1 || currHeight != 1 ); + } while ( currWidth != 1 && currHeight != 1 ); } } } diff --git a/Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h b/Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h index c291cb229..6d7d0e4b1 100644 --- a/Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h +++ b/Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h @@ -143,6 +143,11 @@ public: init(); } + ~GLCircularVolatileBuffer() + { + glDeleteBuffers(1, &mBufferName); + } + void init() { glGenBuffers(1, &mBufferName); @@ -290,4 +295,4 @@ protected: }; -#endif \ No newline at end of file +#endif diff --git a/Engine/source/gfx/gl/gfxGLDevice.cpp b/Engine/source/gfx/gl/gfxGLDevice.cpp index 9cec609d1..01bbd02ea 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.cpp +++ b/Engine/source/gfx/gl/gfxGLDevice.cpp @@ -355,23 +355,47 @@ GFXPrimitiveBuffer* GFXGLDevice::findVolatilePBO(U32 numIndices, U32 numPrimitiv GFXVertexBuffer *GFXGLDevice::allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ) + GFXBufferType bufferType, + void* data ) { if(bufferType == GFXBufferTypeVolatile) return findVolatileVBO(numVerts, vertexFormat, vertSize); GFXGLVertexBuffer* buf = new GFXGLVertexBuffer( GFX, numVerts, vertexFormat, vertSize, bufferType ); - buf->registerResourceWithDevice(this); + buf->registerResourceWithDevice(this); + + if(data) + { + void* dest; + buf->lock(0, numVerts, &dest); + dMemcpy(dest, data, vertSize * numVerts); + buf->unlock(); + } + return buf; } -GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType ) +GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data ) { + GFXPrimitiveBuffer* buf; + if(bufferType == GFXBufferTypeVolatile) - return findVolatilePBO(numIndices, numPrimitives); - - GFXGLPrimitiveBuffer* buf = new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType); - buf->registerResourceWithDevice(this); + { + buf = findVolatilePBO(numIndices, numPrimitives); + } + else + { + buf = new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType); + buf->registerResourceWithDevice(this); + } + + if(data) + { + void* dest; + buf->lock(0, numIndices, &dest); + dMemcpy(dest, data, sizeof(U16) * numIndices); + buf->unlock(); + } return buf; } diff --git a/Engine/source/gfx/gl/gfxGLDevice.h b/Engine/source/gfx/gl/gfxGLDevice.h index 72193835d..902bfb3f6 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.h +++ b/Engine/source/gfx/gl/gfxGLDevice.h @@ -173,8 +173,9 @@ protected: virtual GFXVertexBuffer *allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ); - virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType ); + GFXBufferType bufferType, + void* data = NULL); + virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data = NULL ); // NOTE: The GL device doesn't need a vertex declaration at // this time, but we need to return something to keep the system diff --git a/Engine/source/gfx/gl/gfxGLEnumTranslate.cpp b/Engine/source/gfx/gl/gfxGLEnumTranslate.cpp index 19f6e1c69..e78d807c1 100644 --- a/Engine/source/gfx/gl/gfxGLEnumTranslate.cpp +++ b/Engine/source/gfx/gl/gfxGLEnumTranslate.cpp @@ -45,6 +45,7 @@ void GFXGLEnumTranslate::init() GFXGLBufferType[GFXBufferTypeStatic] = GL_STATIC_DRAW; GFXGLBufferType[GFXBufferTypeDynamic] = GL_DYNAMIC_DRAW; GFXGLBufferType[GFXBufferTypeVolatile] = GL_STREAM_DRAW; + GFXGLBufferType[GFXBufferTypeImmutable] = GL_STATIC_DRAW; // Primitives GFXGLPrimType[GFXPointList] = GL_POINTS; diff --git a/Engine/source/gfx/gl/gfxGLStateBlock.cpp b/Engine/source/gfx/gl/gfxGLStateBlock.cpp index a1af2910c..34f816dc9 100644 --- a/Engine/source/gfx/gl/gfxGLStateBlock.cpp +++ b/Engine/source/gfx/gl/gfxGLStateBlock.cpp @@ -107,6 +107,14 @@ void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState) if(STATE_CHANGE(blendOp)) glBlendEquation(GFXGLBlendOp[mDesc.blendOp]); + if (mDesc.separateAlphaBlendEnable == true) + { + if (STATE_CHANGE(separateAlphaBlendSrc) || STATE_CHANGE(separateAlphaBlendDest)) + glBlendFuncSeparate(GFXGLBlend[mDesc.blendSrc], GFXGLBlend[mDesc.blendDest], GFXGLBlend[mDesc.separateAlphaBlendSrc], GFXGLBlend[mDesc.separateAlphaBlendDest]); + if (STATE_CHANGE(separateAlphaBlendOp)) + glBlendEquationSeparate(GFXGLBlendOp[mDesc.blendOp], GFXGLBlendOp[mDesc.separateAlphaBlendOp]); + } + // Color write masks if(STATE_CHANGE(colorWriteRed) || STATE_CHANGE(colorWriteBlue) || STATE_CHANGE(colorWriteGreen) || STATE_CHANGE(colorWriteAlpha)) glColorMask(mDesc.colorWriteRed, mDesc.colorWriteBlue, mDesc.colorWriteGreen, mDesc.colorWriteAlpha); diff --git a/Engine/source/gfx/gl/gfxGLTextureTarget.cpp b/Engine/source/gfx/gl/gfxGLTextureTarget.cpp index 1569b9a85..202265107 100644 --- a/Engine/source/gfx/gl/gfxGLTextureTarget.cpp +++ b/Engine/source/gfx/gl/gfxGLTextureTarget.cpp @@ -163,6 +163,10 @@ void _GFXGLTextureTargetFBOImpl::applyState() PRESERVE_FRAMEBUFFER(); glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); + bool drawbufs[16]; + int bufsize = 0; + for (int i = 0; i < 16; i++) + drawbufs[i] = false; bool hasColor = false; for(int i = 0; i < GFXGL->getNumRenderTargets(); ++i) { @@ -200,6 +204,20 @@ void _GFXGLTextureTargetFBOImpl::applyState() glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); } + GLenum *buf = new GLenum[bufsize]; + int count = 0; + for (int i = 0; i < bufsize; i++) + { + if (drawbufs[i]) + { + buf[count] = GL_COLOR_ATTACHMENT0 + i; + count++; + } + } + + glDrawBuffers(bufsize, buf); + + delete[] buf; CHECK_FRAMEBUFFER_STATUS(); } @@ -260,7 +278,10 @@ GFXGLTextureTarget::GFXGLTextureTarget() : mCopyFboSrc(0), mCopyFboDst(0) GFXGLTextureTarget::~GFXGLTextureTarget() { - GFXTextureManager::removeEventDelegate( this, &GFXGLTextureTarget::_onTextureEvent ); + GFXTextureManager::removeEventDelegate(this, &GFXGLTextureTarget::_onTextureEvent); + + glDeleteFramebuffers(1, &mCopyFboSrc); + glDeleteFramebuffers(1, &mCopyFboDst); } const Point2I GFXGLTextureTarget::getSize() diff --git a/Engine/source/gfx/gl/gfxGLWindowTarget.cpp b/Engine/source/gfx/gl/gfxGLWindowTarget.cpp index c02ff1bc3..5f8808cae 100644 --- a/Engine/source/gfx/gl/gfxGLWindowTarget.cpp +++ b/Engine/source/gfx/gl/gfxGLWindowTarget.cpp @@ -42,6 +42,14 @@ GFXGLWindowTarget::GFXGLWindowTarget(PlatformWindow *win, GFXDevice *d) win->appEvent.notify(this, &GFXGLWindowTarget::_onAppSignal); } +GFXGLWindowTarget::~GFXGLWindowTarget() +{ + if(glIsFramebuffer(mCopyFBO)) + { + glDeleteFramebuffers(1, &mCopyFBO); + } +} + void GFXGLWindowTarget::resetMode() { if(mWindow->getVideoMode().fullScreen != mWindow->isFullscreen()) @@ -49,6 +57,7 @@ void GFXGLWindowTarget::resetMode() _teardownCurrentMode(); _setupNewMode(); } + GFX->beginReset(); } void GFXGLWindowTarget::_onAppSignal(WindowId wnd, S32 event) diff --git a/Engine/source/gfx/gl/gfxGLWindowTarget.h b/Engine/source/gfx/gl/gfxGLWindowTarget.h index 4baa6a53f..af368e192 100644 --- a/Engine/source/gfx/gl/gfxGLWindowTarget.h +++ b/Engine/source/gfx/gl/gfxGLWindowTarget.h @@ -30,6 +30,8 @@ class GFXGLWindowTarget : public GFXWindowTarget public: GFXGLWindowTarget(PlatformWindow *win, GFXDevice *d); + ~GFXGLWindowTarget(); + const Point2I getSize() { return mWindow->getClientExtent(); @@ -64,4 +66,4 @@ private: void _WindowPresent(); }; -#endif \ No newline at end of file +#endif diff --git a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp index 10e18deb4..74e1773fc 100644 --- a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp +++ b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp @@ -83,6 +83,10 @@ void GFXGLDevice::enumerateAdapters( Vector &adapterList ) ); SDL_ClearError(); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GLContext tempContext = SDL_GL_CreateContext( tempWindow ); if( !tempContext ) { diff --git a/Engine/source/gfx/gl/tGL/tGL.cpp b/Engine/source/gfx/gl/tGL/tGL.cpp index 94953b487..8d62a7fd1 100644 --- a/Engine/source/gfx/gl/tGL/tGL.cpp +++ b/Engine/source/gfx/gl/tGL/tGL.cpp @@ -29,6 +29,7 @@ namespace GL { void gglPerformBinds() { + glewExperimental = GL_TRUE; GLenum err = glewInit(); AssertFatal(GLEW_OK == err, avar("Error: %s\n", glewGetErrorString(err)) ); } diff --git a/Engine/source/gfx/gl/tGL/tGL.h b/Engine/source/gfx/gl/tGL/tGL.h index aa1275ee5..bb21422b7 100644 --- a/Engine/source/gfx/gl/tGL/tGL.h +++ b/Engine/source/gfx/gl/tGL/tGL.h @@ -24,7 +24,13 @@ #define T_GL_H #include "GL/glew.h" +#if defined (TORQUE_OS_WIN) +// This doesn't work on Mesa drivers. #define gglHasExtension(EXTENSION) GLEW_##EXTENSION +#else +// Slower but reliably detects extensions on Mesa. +#define gglHasExtension(EXTENSION) glewGetExtension("GL_" # EXTENSION) +#endif #endif diff --git a/Engine/source/gfx/sim/debugDraw.cpp b/Engine/source/gfx/sim/debugDraw.cpp index 68b8c835d..b31a6925e 100644 --- a/Engine/source/gfx/sim/debugDraw.cpp +++ b/Engine/source/gfx/sim/debugDraw.cpp @@ -132,6 +132,11 @@ void DebugDrawer::setupStateBlocks() d.setZReadWrite(false); mRenderZOffSB = GFX->createStateBlock(d); + + d.setCullMode(GFXCullCCW); + d.setZReadWrite(true, false); + d.setBlend(true); + mRenderAlpha = GFX->createStateBlock(d); } void DebugDrawer::render() @@ -158,10 +163,13 @@ void DebugDrawer::render() // Set up the state block... GFXStateBlockRef currSB; - if(p->useZ) + if(p->type==DebugPrim::Capsule){ + currSB = mRenderAlpha; + }else if(p->useZ){ currSB = mRenderZOnSB; - else + }else{ currSB = mRenderZOffSB; + } GFX->setStateBlock( currSB ); Point3F d; @@ -180,6 +188,47 @@ void DebugDrawer::render() PrimBuild::end(); break; + case DebugPrim::DirectionLine: + { + const static F32 ARROW_LENGTH = 0.2f, ARROW_RADIUS = 0.035f, CYLINDER_RADIUS = 0.008f; + Point3F &start = p->a, &end = p->b; + Point3F direction = end - start; + F32 length = direction.len(); + if( length>ARROW_LENGTH ){ + //cylinder with arrow on end + direction *= (1.0f/length); + Point3F baseArrow = end - (direction*ARROW_LENGTH); + GFX->getDrawUtil()->drawCone(currSB->getDesc(), baseArrow, end, ARROW_RADIUS, p->color); + GFX->getDrawUtil()->drawCylinder(currSB->getDesc(), start, baseArrow, CYLINDER_RADIUS, p->color); + }else if( length>0 ){ + //short, so just draw arrow + GFX->getDrawUtil()->drawCone(currSB->getDesc(), start, end, ARROW_RADIUS, p->color); + } + } + break; + case DebugPrim::Capsule: + GFX->getDrawUtil()->drawCapsule(currSB->getDesc(), p->a, p->b.x, p->b.y, p->color); + break; + case DebugPrim::OutlinedText: + { + GFXTransformSaver saver; + Point3F result; + if (MathUtils::mProjectWorldToScreen(p->a, &result, GFX->getViewport(), GFX->getWorldMatrix(), GFX->getProjectionMatrix())) + { + GFX->setClipRect(GFX->getViewport()); + Point2I where = Point2I(result.x, result.y); + + GFX->getDrawUtil()->setBitmapModulation(p->color2); + GFX->getDrawUtil()->drawText(mFont, Point2I(where.x-1, where.y), p->mText); + GFX->getDrawUtil()->drawText(mFont, Point2I(where.x+1, where.y), p->mText); + GFX->getDrawUtil()->drawText(mFont, Point2I(where.x, where.y-1), p->mText); + GFX->getDrawUtil()->drawText(mFont, Point2I(where.x, where.y+1), p->mText); + + GFX->getDrawUtil()->setBitmapModulation(p->color); + GFX->getDrawUtil()->drawText(mFont, where, p->mText); + } + } + break; case DebugPrim::Box: d = p->a - p->b; GFX->getDrawUtil()->drawCube(currSB->getDesc(), d * 0.5, (p->a + p->b) * 0.5, p->color); @@ -262,6 +311,63 @@ void DebugDrawer::drawLine(const Point3F &a, const Point3F &b, const ColorF &col mHead = n; } +void DebugDrawer::drawCapsule(const Point3F &a, const F32 &radius, const F32 &height, const ColorF &color) +{ + if(isFrozen || !isDrawing) + return; + + DebugPrim *n = mPrimChunker.alloc(); + + n->useZ = true; + n->dieTime = 0; + n->a = a; + n->b.x = radius; + n->b.y = height; + n->color = color; + n->type = DebugPrim::Capsule; + + n->next = mHead; + mHead = n; + +} + +void DebugDrawer::drawDirectionLine(const Point3F &a, const Point3F &b, const ColorF &color) +{ + if(isFrozen || !isDrawing) + return; + + DebugPrim *n = mPrimChunker.alloc(); + + n->useZ = true; + n->dieTime = 0; + n->a = a; + n->b = b; + n->color = color; + n->type = DebugPrim::DirectionLine; + + n->next = mHead; + mHead = n; +} + +void DebugDrawer::drawOutlinedText(const Point3F& pos, const String& text, const ColorF &color, const ColorF &colorOutline) +{ + if(isFrozen || !isDrawing) + return; + + DebugPrim *n = mPrimChunker.alloc(); + + n->useZ = false; + n->dieTime = 0; + n->a = pos; + n->color = color; + n->color2 = colorOutline; + dStrncpy(n->mText, text.c_str(), 256); + n->type = DebugPrim::OutlinedText; + + n->next = mHead; + mHead = n; +} + void DebugDrawer::drawTri(const Point3F &a, const Point3F &b, const Point3F &c, const ColorF &color) { if(isFrozen || !isDrawing) diff --git a/Engine/source/gfx/sim/debugDraw.h b/Engine/source/gfx/sim/debugDraw.h index b1ab55970..a07f52ca4 100644 --- a/Engine/source/gfx/sim/debugDraw.h +++ b/Engine/source/gfx/sim/debugDraw.h @@ -124,7 +124,10 @@ public: void drawLine(const Point3F &a, const Point3F &b, const ColorF &color = ColorF(1.0f,1.0f,1.0f)); void drawTri(const Point3F &a, const Point3F &b, const Point3F &c, const ColorF &color = ColorF(1.0f,1.0f,1.0f)); void drawText(const Point3F& pos, const String& text, const ColorF &color = ColorF(1.0f,1.0f,1.0f)); - + void drawCapsule(const Point3F &a, const F32 &radius, const F32 &height, const ColorF &color = ColorF(1.0f, 1.0f, 1.0f)); + void drawDirectionLine(const Point3F &a, const Point3F &b, const ColorF &color = ColorF(1.0f, 1.0f, 1.0f)); + void drawOutlinedText(const Point3F& pos, const String& text, const ColorF &color = ColorF(1.0f, 1.0f, 1.0f), const ColorF &colorOutline = ColorF(0.0f, 0.0f, 0.0f)); + /// Render a wireframe view of the given polyhedron. void drawPolyhedron( const AnyPolyhedron& polyhedron, const ColorF& color = ColorF( 1.f, 1.f, 1.f ) ); @@ -161,6 +164,7 @@ private: { /// Color used for this primitive. ColorF color; + ColorF color2; /// Points used to store positional data. Exact semantics determined by type. Point3F a, b, c; @@ -168,7 +172,10 @@ private: Tri, Box, Line, - Text + Text, + DirectionLine, + OutlinedText, + Capsule, } type; ///< Type of the primitive. The meanings of a,b,c are determined by this. SimTime dieTime; ///< Time at which we should remove this from the list. @@ -188,6 +195,7 @@ private: GFXStateBlockRef mRenderZOffSB; GFXStateBlockRef mRenderZOnSB; + GFXStateBlockRef mRenderAlpha; Resource mFont; diff --git a/Engine/source/gui/controls/guiColorPicker.cpp b/Engine/source/gui/controls/guiColorPicker.cpp index 0b8676240..97a8470d8 100644 --- a/Engine/source/gui/controls/guiColorPicker.cpp +++ b/Engine/source/gui/controls/guiColorPicker.cpp @@ -39,13 +39,13 @@ ColorF colorAlpha(0.0f, 0.0f, 0.0f, 0.0f); ColorF colorAlphaW(1.0f, 1.0f, 1.0f, 0.0f); ColorI GuiColorPickerCtrl::mColorRange[7] = { - ColorI(255,0,0), // Red - ColorI(255,0,255), // Pink - ColorI(0,0,255), // Blue - ColorI(0,255,255), // Light blue - ColorI(0,255,0), // Green - ColorI(255,255,0), // Yellow - ColorI(255,0,0), // Red + ColorI(255,0,0), // Red + ColorI(255,0,255), // Pink + ColorI(0,0,255), // Blue + ColorI(0,255,255), // Light blue + ColorI(0,255,0), // Green + ColorI(255,255,0), // Yellow + ColorI(255,0,0), // Red }; /// @} @@ -57,7 +57,6 @@ ConsoleDocClass( GuiColorPickerCtrl, "@internal" ); -//-------------------------------------------------------------------------- GuiColorPickerCtrl::GuiColorPickerCtrl() { setExtent(140, 30); @@ -70,44 +69,50 @@ GuiColorPickerCtrl::GuiColorPickerCtrl() mPositionChanged = false; mSelectorGap = 1; mActionOnMove = false; - mShowReticle = true; + mShowReticle = true; + mSelectColor = false; + mSetColor = mSetColor.BLACK; + mBitmap = NULL; } -//-------------------------------------------------------------------------- +GuiColorPickerCtrl::~GuiColorPickerCtrl() +{ + if (mBitmap) + { + delete mBitmap; + mBitmap = NULL; + } +} ImplementEnumType( GuiColorPickMode, "\n\n" "@ingroup GuiUtil" "@internal" ) - { GuiColorPickerCtrl::pPallet, "Pallete" }, - { GuiColorPickerCtrl::pHorizColorRange, "HorizColor"}, - { GuiColorPickerCtrl::pVertColorRange, "VertColor" }, - { GuiColorPickerCtrl::pHorizColorBrightnessRange, "HorizBrightnessColor"}, - { GuiColorPickerCtrl::pVertColorBrightnessRange, "VertBrightnessColor" }, - { GuiColorPickerCtrl::pBlendColorRange, "BlendColor"}, - { GuiColorPickerCtrl::pHorizAlphaRange, "HorizAlpha"}, - { GuiColorPickerCtrl::pVertAlphaRange, "VertAlpha" }, - { GuiColorPickerCtrl::pDropperBackground, "Dropper" }, + { GuiColorPickerCtrl::pPallet, "Pallete" }, + { GuiColorPickerCtrl::pHorizColorRange, "HorizColor"}, + { GuiColorPickerCtrl::pVertColorRange, "VertColor" }, + { GuiColorPickerCtrl::pHorizColorBrightnessRange, "HorizBrightnessColor" }, + { GuiColorPickerCtrl::pVertColorBrightnessRange, "VertBrightnessColor" }, + { GuiColorPickerCtrl::pBlendColorRange, "BlendColor" }, + { GuiColorPickerCtrl::pHorizAlphaRange, "HorizAlpha" }, + { GuiColorPickerCtrl::pVertAlphaRange, "VertAlpha" }, + { GuiColorPickerCtrl::pDropperBackground, "Dropper" }, EndImplementEnumType; -//-------------------------------------------------------------------------- void GuiColorPickerCtrl::initPersistFields() { addGroup("ColorPicker"); - addField("baseColor", TypeColorF, Offset(mBaseColor, GuiColorPickerCtrl)); addField("pickColor", TypeColorF, Offset(mPickColor, GuiColorPickerCtrl)); addField("selectorGap", TypeS32, Offset(mSelectorGap, GuiColorPickerCtrl)); addField("displayMode", TYPEID< PickMode >(), Offset(mDisplayMode, GuiColorPickerCtrl) ); addField("actionOnMove", TypeBool,Offset(mActionOnMove, GuiColorPickerCtrl)); addField("showReticle", TypeBool, Offset(mShowReticle, GuiColorPickerCtrl)); - endGroup("ColorPicker"); Parent::initPersistFields(); } -//-------------------------------------------------------------------------- // Function to draw a box which can have 4 different colors in each corner blended together void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, ColorF &c3, ColorF &c4) { @@ -119,54 +124,54 @@ void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, Col //A couple of checks to determine if color blend if(c1 == colorWhite && c3 == colorAlpha && c4 == colorBlack) { - //Color - PrimBuild::begin( GFXTriangleFan, 4 ); - PrimBuild::color( c2 ); - PrimBuild::vertex2i( r, t ); + //Color + PrimBuild::begin(GFXTriangleFan, 4); + PrimBuild::color( c2 ); + PrimBuild::vertex2i( r, t ); - PrimBuild::color( c2 ); - PrimBuild::vertex2i( r, b ); + PrimBuild::color( c2 ); + PrimBuild::vertex2i( r, b ); - PrimBuild::color( c2 ); - PrimBuild::vertex2i( l, b ); + PrimBuild::color( c2 ); + PrimBuild::vertex2i( l, b ); - PrimBuild::color( c2 ); - PrimBuild::vertex2i( l, t ); - PrimBuild::end(); + PrimBuild::color( c2 ); + PrimBuild::vertex2i( l, t ); + PrimBuild::end(); - //White - PrimBuild::begin( GFXTriangleFan, 4 ); - PrimBuild::color( colorAlphaW ); - PrimBuild::vertex2i( r, t ); + //White + PrimBuild::begin( GFXTriangleFan, 4 ); + PrimBuild::color( colorAlphaW ); + PrimBuild::vertex2i( r, t ); - PrimBuild::color( colorAlphaW ); - PrimBuild::vertex2i( r, b ); + PrimBuild::color( colorAlphaW ); + PrimBuild::vertex2i( r, b ); - PrimBuild::color( c1 ); - PrimBuild::vertex2i( l, b ); + PrimBuild::color( c1 ); + PrimBuild::vertex2i( l, b ); - PrimBuild::color( c1 ); - PrimBuild::vertex2i( l, t ); - PrimBuild::end(); + PrimBuild::color( c1 ); + PrimBuild::vertex2i( l, t ); + PrimBuild::end(); - //Black - PrimBuild::begin( GFXTriangleFan, 4 ); - PrimBuild::color( c3 ); - PrimBuild::vertex2i( r, t ); + //Black + PrimBuild::begin( GFXTriangleFan, 4 ); + PrimBuild::color( c3 ); + PrimBuild::vertex2i( r, t ); - PrimBuild::color( c4 ); - PrimBuild::vertex2i( r, b ); + PrimBuild::color( c4 ); + PrimBuild::vertex2i( r, b ); - PrimBuild::color( c4 ); - PrimBuild::vertex2i( l, b ); + PrimBuild::color( c4 ); + PrimBuild::vertex2i( l, b ); - PrimBuild::color( c3 ); - PrimBuild::vertex2i( l, t ); - PrimBuild::end(); + PrimBuild::color( c3 ); + PrimBuild::vertex2i( l, t ); + PrimBuild::end(); } else { - PrimBuild::begin( GFXTriangleFan, 4 ); + PrimBuild::begin( GFXTriangleFan, 4 ); PrimBuild::color( c1 ); PrimBuild::vertex2i( l, t ); @@ -233,31 +238,29 @@ void GuiColorPickerCtrl::drawBlendRangeBox(RectI &bounds, bool vertical, U8 numC void GuiColorPickerCtrl::drawSelector(RectI &bounds, Point2I &selectorPos, SelectorMode mode) { - if( !mShowReticle ) - return; + if( !mShowReticle ) + return; - U16 sMax = mSelectorGap*2; - switch (mode) - { - case sVertical: - // Now draw the vertical selector - // Up -> Pos - if (selectorPos.y != bounds.point.y+1) - GFX->getDrawUtil()->drawLine(selectorPos.x, bounds.point.y, selectorPos.x, selectorPos.y-sMax-1, colorWhiteBlend); - // Down -> Pos - if (selectorPos.y != bounds.point.y+bounds.extent.y) - GFX->getDrawUtil()->drawLine(selectorPos.x, selectorPos.y + sMax, selectorPos.x, bounds.point.y + bounds.extent.y, colorWhiteBlend); - break; - case sHorizontal: - // Now draw the horizontal selector - // Left -> Pos - if (selectorPos.x != bounds.point.x) + U16 sMax = mSelectorGap*2; + switch (mode) + { + case sVertical: + // Now draw the vertical selector Up -> Pos + if (selectorPos.y != bounds.point.y+1) + GFX->getDrawUtil()->drawLine(selectorPos.x, bounds.point.y, selectorPos.x, selectorPos.y-sMax-1, colorWhiteBlend); + // Down -> Pos + if (selectorPos.y != bounds.point.y+bounds.extent.y) + GFX->getDrawUtil()->drawLine(selectorPos.x, selectorPos.y + sMax, selectorPos.x, bounds.point.y + bounds.extent.y, colorWhiteBlend); + break; + case sHorizontal: + // Now draw the horizontal selector Left -> Pos + if (selectorPos.x != bounds.point.x) GFX->getDrawUtil()->drawLine(bounds.point.x, selectorPos.y-1, selectorPos.x-sMax, selectorPos.y-1, colorWhiteBlend); - // Right -> Pos - if (selectorPos.x != bounds.point.x) + // Right -> Pos + if (selectorPos.x != bounds.point.x) GFX->getDrawUtil()->drawLine(bounds.point.x+mSelectorPos.x+sMax, selectorPos.y-1, bounds.point.x + bounds.extent.x, selectorPos.y-1, colorWhiteBlend); - break; - } + break; + } } //-------------------------------------------------------------------------- @@ -269,10 +272,10 @@ void GuiColorPickerCtrl::renderColorBox(RectI &bounds) pickerBounds.point.y = bounds.point.y+1; pickerBounds.extent.x = bounds.extent.x-1; pickerBounds.extent.y = bounds.extent.y-1; - + if (mProfile->mBorder) GFX->getDrawUtil()->drawRect(bounds, mProfile->mBorderColor); - + Point2I selectorPos = Point2I(bounds.point.x+mSelectorPos.x+1, bounds.point.y+mSelectorPos.y+1); // Draw color box differently depending on mode @@ -338,56 +341,169 @@ void GuiColorPickerCtrl::onRender(Point2I offset, const RectI& updateRect) desc.setZReadWrite(false); desc.zWriteEnable = false; desc.setCullMode(GFXCullNone); - mStateBlock = GFX->createStateBlock( desc ); + mStateBlock = GFX->createStateBlock(desc); } - RectI boundsRect(offset, getExtent()); + RectI boundsRect(offset, getExtent()); renderColorBox(boundsRect); - if (mPositionChanged) + if (mPositionChanged || mBitmap == NULL) { + bool nullBitmap = false; + + if (mPositionChanged == false && mBitmap == NULL) + nullBitmap = true; + mPositionChanged = false; Point2I extent = getRoot()->getExtent(); + // If we are anything but a pallete, change the pick color if (mDisplayMode != pPallet) { Point2I resolution = getRoot()->getExtent(); U32 buf_x = offset.x + mSelectorPos.x + 1; - U32 buf_y = resolution.y - ( extent.y - ( offset.y + mSelectorPos.y + 1 ) ); + U32 buf_y = resolution.y - (extent.y - (offset.y + mSelectorPos.y + 1)); - GFXTexHandle bb( resolution.x, - resolution.y, - GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, avar("%s() - bb (line %d)", __FUNCTION__, __LINE__) ); - - Point2I tmpPt( buf_x, buf_y ); + GFXTexHandle bb( resolution.x, resolution.y, GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, avar("%s() - bb (line %d)", __FUNCTION__, __LINE__) ); + + Point2I tmpPt(buf_x, buf_y); GFXTarget *targ = GFX->getActiveRenderTarget(); - targ->resolveTo( bb ); - - GBitmap bmp( bb.getWidth(), bb.getHeight() ); + targ->resolveTo(bb); - bb.copyToBmp( &bmp ); - - //bmp.writePNGDebug( "foo.png" ); + if (mBitmap) + { + delete mBitmap; + mBitmap = NULL; + } - ColorI tmp; - bmp.getColor( buf_x, buf_y, tmp ); + mBitmap = new GBitmap(bb.getWidth(), bb.getHeight()); - mPickColor = (ColorF)tmp; + bb.copyToBmp(mBitmap); - // Now do onAction() if we are allowed - if (mActionOnMove) - onAction(); + if (!nullBitmap) + { + if (mSelectColor) + { + Point2I pos = findColor(mSetColor, offset, resolution, *mBitmap); + mSetColor = mSetColor.BLACK; + mSelectColor = false; + setSelectorPos(pos); + } + else + { + ColorI tmp; + mBitmap->getColor(buf_x, buf_y, tmp); + + mPickColor = (ColorF)tmp; + + // Now do onAction() if we are allowed + if (mActionOnMove) + onAction(); + } + } } - } - + //render the children - renderChildControls( offset, updateRect); + renderChildControls(offset, updateRect); +} + +void GuiColorPickerCtrl::setSelectorPos(const ColorF & color) +{ + if (mBitmap && !mPositionChanged) + { + Point2I resolution = getRoot() ? getRoot()->getExtent() : Point2I(1024, 768); + RectI rect(getGlobalBounds()); + Point2I pos = findColor(color, rect.point, resolution, *mBitmap); + mSetColor = mSetColor.BLACK; + mSelectColor = false; + + setSelectorPos(pos); + } + else + { + mSetColor = color; + mSelectColor = true; + mPositionChanged = true; + } +} + +Point2I GuiColorPickerCtrl::findColor(const ColorF & color, const Point2I& offset, const Point2I& resolution, GBitmap& bmp) +{ + RectI rect; + Point2I ext = getExtent(); + if (mDisplayMode != pDropperBackground) + { + ext.x -= 3; + ext.y -= 2; + rect = RectI(Point2I(1, 1), ext); + } + else + { + rect = RectI(Point2I(0, 0), ext); + } + + Point2I closestPos(-1, -1); + + /* Debugging + char filename[256]; + dSprintf( filename, 256, "%s.%s", "colorPickerTest", "png" ); + + // Open up the file on disk. + FileStream fs; + if ( !fs.open( filename, Torque::FS::File::Write ) ) + Con::errorf( "GuiObjectView::saveAsImage() - Failed to open output file '%s'!", filename ); + else + { + // Write it and close. + bmp.writeBitmap( "png", fs ); + + fs.close(); + } + */ + + ColorI tmp; + U32 buf_x; + U32 buf_y; + ColorF curColor; + F32 val(10000.0f); + F32 closestVal(10000.0f); + bool closestSet = false; + + for (S32 x = rect.point.x; x <= rect.extent.x; x++) + { + for (S32 y = rect.point.y; y <= rect.extent.y; y++) + { + buf_x = offset.x + x + 1; + buf_y = (resolution.y - (offset.y + y + 1)); + buf_y = resolution.y - buf_y; + + //Get the color at that position + bmp.getColor(buf_x, buf_y, tmp); + curColor = (ColorF)tmp; + + //Evaluate how close the color is to our desired color + val = mFabs(color.red - curColor.red) + mFabs(color.green - curColor.green) + mFabs(color.blue - curColor.blue); + + if (!closestSet) + { + closestVal = val; + closestPos.set(x, y); + closestSet = true; + } + else if (val < closestVal) + { + closestVal = val; + closestPos.set(x, y); + } + } + } + + return closestPos; } -//-------------------------------------------------------------------------- void GuiColorPickerCtrl::setSelectorPos(const Point2I &pos) { Point2I extent = getExtent(); @@ -432,7 +548,6 @@ void GuiColorPickerCtrl::setSelectorPos(const Point2I &pos) } } -//-------------------------------------------------------------------------- void GuiColorPickerCtrl::onMouseDown(const GuiEvent &event) { if (!mActive) @@ -445,14 +560,14 @@ void GuiColorPickerCtrl::onMouseDown(const GuiEvent &event) if (mProfile->mCanKeyFocus) setFirstResponder(); - - if (mActive && (mDisplayMode != pDropperBackground)) + + if (mActive && (mDisplayMode != pDropperBackground)) onAction(); // Update the picker cross position if (mDisplayMode != pPallet) - setSelectorPos(globalToLocalCoord(event.mousePoint)); - + setSelectorPos(globalToLocalCoord(event.mousePoint)); + mMouseDown = true; } @@ -468,10 +583,8 @@ void GuiColorPickerCtrl::onMouseDragged(const GuiEvent &event) if( !mActionOnMove ) execAltConsoleCallback(); - } -//-------------------------------------------------------------------------- void GuiColorPickerCtrl::onMouseMove(const GuiEvent &event) { // Only for dropper mode @@ -479,45 +592,40 @@ void GuiColorPickerCtrl::onMouseMove(const GuiEvent &event) setSelectorPos(globalToLocalCoord(event.mousePoint)); } -//-------------------------------------------------------------------------- void GuiColorPickerCtrl::onMouseEnter(const GuiEvent &event) { mMouseOver = true; } -//-------------------------------------------------------------------------- void GuiColorPickerCtrl::onMouseLeave(const GuiEvent &) { // Reset state mMouseOver = false; } -//-------------------------------------------------------------------------- void GuiColorPickerCtrl::onMouseUp(const GuiEvent &) { //if we released the mouse within this control, perform the action - if (mActive && mMouseDown && (mDisplayMode != pDropperBackground)) + if (mActive && mMouseDown && (mDisplayMode != pDropperBackground)) mMouseDown = false; - if (mActive && (mDisplayMode == pDropperBackground)) + if (mActive && (mDisplayMode == pDropperBackground)) { // In a dropper, the alt command executes the mouse up action (to signal stopping) execAltConsoleCallback(); } - + mouseUnlock(); } -//-------------------------------------------------------------------------- const char *GuiColorPickerCtrl::getScriptValue() { static char temp[256]; ColorF color = getValue(); - dSprintf(temp,256,"%f %f %f %f",color.red, color.green, color.blue, color.alpha); - return temp; + dSprintf( temp, 256, "%f %f %f %f", color.red, color.green, color.blue, color.alpha ); + return temp; } -//-------------------------------------------------------------------------- void GuiColorPickerCtrl::setScriptValue(const char *value) { ColorF newValue; @@ -537,5 +645,12 @@ DefineConsoleMethod(GuiColorPickerCtrl, setSelectorPos, void, (Point2I newPos), DefineConsoleMethod(GuiColorPickerCtrl, updateColor, void, (), , "Forces update of pick color") { - object->updateColor(); + object->updateColor(); +} + +DefineEngineMethod(GuiColorPickerCtrl, setSelectorColor, void, (ColorF color), , + "Sets the current position of the selector based on a color.n" + "@param color Color to look for.n") +{ + object->setSelectorPos(color); } diff --git a/Engine/source/gui/controls/guiColorPicker.h b/Engine/source/gui/controls/guiColorPicker.h index a9421b7f7..42531c3bb 100644 --- a/Engine/source/gui/controls/guiColorPicker.h +++ b/Engine/source/gui/controls/guiColorPicker.h @@ -59,29 +59,28 @@ class GuiColorPickerCtrl : public GuiControl public: enum PickMode { - pPallet = 0, ///< We just have a solid color; We just act like a pallet - pHorizColorRange, ///< We have a range of base colors going horizontally - pVertColorRange, ///< We have a range of base colors going vertically + pPallet = 0, ///< We just have a solid color; We just act like a pallet + pHorizColorRange, ///< We have a range of base colors going horizontally + pVertColorRange, ///< We have a range of base colors going vertically pHorizColorBrightnessRange, ///< HorizColorRange with brightness - pVertColorBrightnessRange, ///< VertColorRange with brightness - pBlendColorRange, ///< We have a box which shows a range in brightness of the color - pHorizAlphaRange, ///< We have a box which shows a range in alpha going horizontally - pVertAlphaRange, ///< We have a box which shows a range in alpha going vertically - pDropperBackground ///< The control does not draw anything; Only does something when you click, or move the mouse (when active) + pVertColorBrightnessRange, ///< VertColorRange with brightness + pBlendColorRange, ///< We have a box which shows a range in brightness of the color + pHorizAlphaRange, ///< We have a box which shows a range in alpha going horizontally + pVertAlphaRange, ///< We have a box which shows a range in alpha going vertically + pDropperBackground ///< The control does not draw anything; Only does something when you click, or move the mouse (when active) }; enum SelectorMode { - sHorizontal = 0, ///< Horizontal selector with small gap - sVertical, ///< Vertical selector with small gap + sHorizontal = 0, ///< Horizontal selector with small gap + sVertical, ///< Vertical selector with small gap }; - + protected: - /// @name Core Rendering functions /// @{ - void renderColorBox(RectI &bounds); ///< Function that draws the actual color box - void drawSelector(RectI &bounds, Point2I &selectorPos, SelectorMode mode); ///< Function that draws the selection indicator + void renderColorBox(RectI &bounds); ///< Function that draws the actual color box + void drawSelector(RectI &bounds, Point2I &selectorPos, SelectorMode mode); /// < Function that draws the selection indicator void drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, ColorF &c3, ColorF &c4); void drawBlendRangeBox(RectI &bounds, bool vertical, U8 numColors, ColorI *colors); /// @} @@ -98,7 +97,11 @@ class GuiColorPickerCtrl : public GuiControl bool mMouseDown; ///< Mouse button down? bool mActionOnMove; ///< Perform onAction() when position has changed? - + bool mSelectColor; + ColorF mSetColor; + GBitmap* mBitmap; + + Point2I findColor(const ColorF & color, const Point2I& offset, const Point2I& resolution, GBitmap& bmp); S32 mSelectorGap; ///< The half-way "gap" between the selector pos and where the selector is allowed to draw. @@ -107,12 +110,13 @@ class GuiColorPickerCtrl : public GuiControl static ColorI mColorRange[7]; ///< Color range for pHorizColorRange and pVertColorRange /// @} - public: - + public: + DECLARE_CONOBJECT(GuiColorPickerCtrl); DECLARE_CATEGORY( "Gui Editor" ); GuiColorPickerCtrl(); + ~GuiColorPickerCtrl(); static void initPersistFields(); void onRender(Point2I offset, const RectI &updateRect); @@ -122,18 +126,19 @@ class GuiColorPickerCtrl : public GuiControl /// NOTE: setValue only sets baseColor, since setting pickColor wouldn't be useful void setValue(ColorF &value) {mBaseColor = value;} /// NOTE: getValue() returns baseColor if pallet (since pallet controls can't "pick" colours themselves) - ColorF getValue() {return mDisplayMode == pPallet ? mBaseColor : mPickColor;} + ColorF getValue() { return mDisplayMode == pPallet ? mBaseColor : mPickColor; } const char *getScriptValue(); void setScriptValue(const char *value); void updateColor() {mPositionChanged = true;} /// @} - + /// @name Selector Functions /// @{ void setSelectorPos(const Point2I &pos); ///< Set new pos (in local coords) + void setSelectorPos(const ColorF & color); Point2I getSelectorPos() {return mSelectorPos;} /// @} - + /// @name Input Events /// @{ void onMouseDown(const GuiEvent &); diff --git a/Engine/source/gui/controls/guiTextEditCtrl.cpp b/Engine/source/gui/controls/guiTextEditCtrl.cpp index 3ed1ea40f..99a1342c0 100644 --- a/Engine/source/gui/controls/guiTextEditCtrl.cpp +++ b/Engine/source/gui/controls/guiTextEditCtrl.cpp @@ -128,6 +128,8 @@ GuiTextEditCtrl::GuiTextEditCtrl() mActive = true; + mTextValid = true; + mTextOffsetReset = true; mHistoryDirty = false; @@ -1252,14 +1254,16 @@ void GuiTextEditCtrl::onLoseFirstResponder() Parent::onLoseFirstResponder(); } -void GuiTextEditCtrl::onRender(Point2I offset, const RectI &updateRect) +void GuiTextEditCtrl::onRender( Point2I offset, const RectI &updateRect ) { RectI ctrlRect( offset, getExtent() ); //if opaque, fill the update rect with the fill color if ( mProfile->mOpaque ) { - if(isFirstResponder()) + if ( !mTextValid ) + GFX->getDrawUtil()->drawRectFill( ctrlRect, mProfile->mFillColorERR ); + else if ( isFirstResponder() ) GFX->getDrawUtil()->drawRectFill( ctrlRect, mProfile->mFillColorHL ); else GFX->getDrawUtil()->drawRectFill( ctrlRect, mProfile->mFillColor ); @@ -1267,7 +1271,11 @@ void GuiTextEditCtrl::onRender(Point2I offset, const RectI &updateRect) //if there's a border, draw the border if ( mProfile->mBorder ) + { renderBorder( ctrlRect, mProfile ); + if ( !mTextValid ) + GFX->getDrawUtil()->drawRectFill( ctrlRect, mProfile->mFillColorERR ); + } drawText( ctrlRect, isFirstResponder() ); } @@ -1490,7 +1498,25 @@ void GuiTextEditCtrl::drawText( const RectI &drawRect, bool isFocused ) bool GuiTextEditCtrl::hasText() { - return (mTextBuffer.length()); + return ( mTextBuffer.length() ); +} + +void GuiTextEditCtrl::invalidText(bool playSound) +{ + mTextValid = false; + + if ( playSound ) + playDeniedSound(); +} + +void GuiTextEditCtrl::validText() +{ + mTextValid = true; +} + +bool GuiTextEditCtrl::isValidText() +{ + return mTextValid; } void GuiTextEditCtrl::playDeniedSound() @@ -1520,27 +1546,29 @@ void GuiTextEditCtrl::handleCharInput( U16 ascii ) //see if it's a number field if ( mProfile->mNumbersOnly ) { - if ( ascii == '-') - { - //a minus sign only exists at the beginning, and only a single minus sign - if ( mCursorPos != 0 && !isAllTextSelected() ) - { - playDeniedSound(); - return; - } + if (ascii == '-') + { + //a minus sign only exists at the beginning, and only a single minus sign + if (mCursorPos != 0 && !isAllTextSelected()) + { + invalidText(); + return; + } - if ( mInsertOn && ( mTextBuffer.getChar(0) == '-' ) ) - { - playDeniedSound(); - return; - } - } - // BJTODO: This is probably not unicode safe. - else if ( ascii != '.' && (ascii < '0' || ascii > '9') ) - { - playDeniedSound(); - return; - } + if (mInsertOn && (mTextBuffer.getChar(0) == '-')) + { + invalidText(); + return; + } + } + // BJTODO: This is probably not unicode safe. + else if (ascii != '.' && (ascii < '0' || ascii > '9')) + { + invalidText(); + return; + } + else + validText(); } //save the current state @@ -1748,3 +1776,24 @@ DefineEngineMethod( GuiTextEditCtrl, forceValidateText, void, (),, { object->forceValidateText(); } + +DefineEngineMethod(GuiTextEditCtrl, invalidText, void, (bool playSound), (true), + "@brief Trigger the invalid sound and make the box red.nn" + "@param playSound Play the invalid text sound or not.n") +{ + object->invalidText(playSound); +} + + +DefineEngineMethod(GuiTextEditCtrl, validText, void, (), , + "@brief Restores the box to normal color.nn") +{ + object->validText(); +} + +DefineEngineMethod(GuiTextEditCtrl, isValidText, bool, (), , + "@brief Returns if the text is set to valid or not.n" + "@Return true if text is set to valid, false if not.nn") +{ + return object->isValidText(); +} diff --git a/Engine/source/gui/controls/guiTextEditCtrl.h b/Engine/source/gui/controls/guiTextEditCtrl.h index 1821ef182..9d29038f7 100644 --- a/Engine/source/gui/controls/guiTextEditCtrl.h +++ b/Engine/source/gui/controls/guiTextEditCtrl.h @@ -93,6 +93,8 @@ protected: void playDeniedSound(); void execConsoleCallback(); + bool mTextValid; + virtual void handleCharInput( U16 ascii ); S32 findNextWord(); @@ -119,6 +121,10 @@ public: S32 getCursorPos() { return( mCursorPos ); } void setCursorPos( const S32 newPos ); + void invalidText(bool playSound = true); + void validText(); + bool isValidText(); + bool isAllTextSelected(); void selectAllText(); void clearSelectedText(); diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index 84fe6e0c2..a3f2344f2 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -321,8 +321,11 @@ void GuiCanvas::setWindowTitle(const char *newTitle) mPlatformWindow->setCaption(newTitle); } +CanvasSizeChangeSignal GuiCanvas::smCanvasSizeChangeSignal; + void GuiCanvas::handleResize( WindowId did, S32 width, S32 height ) { + getCanvasSizeChangeSignal().trigger(this); if (Journal::IsPlaying() && mPlatformWindow) { mPlatformWindow->lockSize(false); diff --git a/Engine/source/gui/core/guiCanvas.h b/Engine/source/gui/core/guiCanvas.h index b1444ce32..0a2e44fa5 100644 --- a/Engine/source/gui/core/guiCanvas.h +++ b/Engine/source/gui/core/guiCanvas.h @@ -33,6 +33,10 @@ #include "platform/platformInput.h" #endif +#ifndef _SIGNAL_H_ +#include "core/util/tSignal.h" +#endif + #include "component/interfaces/IProcessInput.h" #include "windowManager/platformWindowMgr.h" #include "gfx/gfxFence.h" @@ -74,6 +78,8 @@ /// screen will be painted normally. If you are making an animated GuiControl /// you need to add your control to the dirty areas of the canvas. /// +class guiCanvas; +typedef Signal CanvasSizeChangeSignal; class GuiCanvas : public GuiControl, public IProcessInput { @@ -183,6 +189,8 @@ protected: virtual void setupFences(); void checkLockMouseMove( const GuiEvent& event ); + //Signal used to let others know this canvas has changed size. + static CanvasSizeChangeSignal smCanvasSizeChangeSignal; GuiControl *mMenuBarCtrl; @@ -200,6 +208,8 @@ public: static void initPersistFields(); + static CanvasSizeChangeSignal& getCanvasSizeChangeSignal() { return smCanvasSizeChangeSignal; } + /// @name Rendering methods /// /// @{ diff --git a/Engine/source/gui/core/guiControl.cpp b/Engine/source/gui/core/guiControl.cpp index c0c822a11..f3cacc27a 100644 --- a/Engine/source/gui/core/guiControl.cpp +++ b/Engine/source/gui/core/guiControl.cpp @@ -175,6 +175,9 @@ ImplementEnumType( GuiHorizontalSizing, { GuiControl::horizResizeLeft, "left" }, { GuiControl::horizResizeCenter, "center" }, { GuiControl::horizResizeRelative, "relative" }, + { GuiControl::horizResizeAspectLeft, "aspectLeft" }, + { GuiControl::horizResizeAspectRight, "aspectRight" }, + { GuiControl::horizResizeAspectCenter, "aspectCenter" }, { GuiControl::horizResizeWindowRelative, "windowRelative" } EndImplementEnumType; @@ -186,6 +189,9 @@ ImplementEnumType( GuiVerticalSizing, { GuiControl::vertResizeTop, "top" }, { GuiControl::vertResizeCenter, "center" }, { GuiControl::vertResizeRelative, "relative" }, + { GuiControl::vertResizeAspectTop, "aspectTop" }, + { GuiControl::vertResizeAspectBottom, "aspectBottom" }, + { GuiControl::vertResizeAspectCenter, "aspectCenter" }, { GuiControl::vertResizeWindowRelative, "windowRelative" } EndImplementEnumType; @@ -1370,6 +1376,36 @@ void GuiControl::parentResized(const RectI &oldParentRect, const RectI &newParen newPosition.x = newLeft; newExtent.x = newWidth; } + else if (mHorizSizing == horizResizeAspectLeft && oldParentRect.extent.x != 0) + { + S32 newLeft = mRoundToNearest((F32(newPosition.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); + S32 newWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); + + newPosition.x = newLeft; + newExtent.x = newWidth; + } + else if (mHorizSizing == horizResizeAspectRight && oldParentRect.extent.x != 0) + { + S32 newLeft = mRoundToNearest((F32(newPosition.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); + S32 newWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //origional aspect ratio corrected width + S32 rWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); //parent aspect ratio relative width + + S32 offset = rWidth - newWidth; // account for change in relative width + newLeft += offset; + newPosition.x = newLeft; + newExtent.x = newWidth; + } + else if (mHorizSizing == horizResizeAspectCenter && oldParentRect.extent.x != 0) + { + S32 newLeft = mRoundToNearest((F32(newPosition.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); + S32 newWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //origional aspect ratio corrected width + S32 rWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); //parent aspect ratio relative width + + S32 offset = rWidth - newWidth; // account for change in relative width + newLeft += offset/2; + newPosition.x = newLeft; + newExtent.x = newWidth; + } if (mVertSizing == vertResizeCenter) newPosition.y = (newParentRect.extent.y - getHeight()) >> 1; @@ -1385,6 +1421,36 @@ void GuiControl::parentResized(const RectI &oldParentRect, const RectI &newParen newPosition.y = newTop; newExtent.y = newHeight; } + else if (mVertSizing == vertResizeAspectTop && oldParentRect.extent.y != 0) + { + S32 newTop = mRoundToNearest((F32(newPosition.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); + S32 newHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); + + newPosition.y = newTop; + newExtent.y = newHeight; + } + else if (mVertSizing == vertResizeAspectBottom && oldParentRect.extent.y != 0) + { + S32 newTop = mRoundToNearest((F32(newPosition.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); + S32 newHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); //origional aspect ratio corrected hieght + S32 rHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //parent aspect ratio relative hieght + + S32 offset = rHeight - newHeight; // account for change in relative hieght + newTop += offset; + newPosition.y = newTop; + newExtent.y = newHeight; + } + else if (mVertSizing == vertResizeAspectCenter && oldParentRect.extent.y != 0) + { + S32 newTop = mRoundToNearest((F32(newPosition.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); + S32 newHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); //origional aspect ratio corrected hieght + S32 rHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //parent aspect ratio relative hieght + + S32 offset = rHeight - newHeight; // account for change in relative hieght + newTop += offset / 2; + newPosition.y = newTop; + newExtent.y = newHeight; + } // Resizing Re factor [9/18/2006] // Only resize if our minExtent is satisfied with it. diff --git a/Engine/source/gui/core/guiControl.h b/Engine/source/gui/core/guiControl.h index 4240fbad6..ca873878d 100644 --- a/Engine/source/gui/core/guiControl.h +++ b/Engine/source/gui/core/guiControl.h @@ -121,6 +121,9 @@ class GuiControl : public SimGroup horizResizeLeft, ///< fixed on the right and width horizResizeCenter, horizResizeRelative, ///< resize relative + horizResizeAspectLeft, ///< resize relative to height delta (offset Left) + horizResizeAspectRight, ///< resize relative to height delta (offset Right) + horizResizeAspectCenter, ///< resize relative to height delta (Centered) horizResizeWindowRelative ///< resize window relative }; enum vertSizingOptions @@ -130,6 +133,9 @@ class GuiControl : public SimGroup vertResizeTop, ///< fixed in height and on the bottom vertResizeCenter, vertResizeRelative, ///< resize relative + vertResizeAspectTop, ///< resize relative to width delta (offset Left) + vertResizeAspectBottom, ///< resize relative to width delta (offset Right) + vertResizeAspectCenter, ///< resize relative to width delta Centered) vertResizeWindowRelative ///< resize window relative }; diff --git a/Engine/source/gui/core/guiTypes.cpp b/Engine/source/gui/core/guiTypes.cpp index 4f96884bf..870ef1355 100644 --- a/Engine/source/gui/core/guiTypes.cpp +++ b/Engine/source/gui/core/guiTypes.cpp @@ -269,6 +269,7 @@ GuiControlProfile::GuiControlProfile(void) : mFillColor(255,0,255,255), mFillColorHL(255,0,255,255), mFillColorNA(255,0,255,255), + mFillColorERR(255,0,0,255), mFillColorSEL(255,0,255,255), mBorderColor(255,0,255,255), mBorderColorHL(255,0,255,255), @@ -334,6 +335,7 @@ GuiControlProfile::GuiControlProfile(void) : mFillColor = def->mFillColor; mFillColorHL = def->mFillColorHL; mFillColorNA = def->mFillColorNA; + mFillColorERR = def->mFillColorERR; mFillColorSEL = def->mFillColorSEL; mBorder = def->mBorder; @@ -398,6 +400,7 @@ void GuiControlProfile::initPersistFields() addField("fillColor", TypeColorI, Offset(mFillColor, GuiControlProfile)); addField("fillColorHL", TypeColorI, Offset(mFillColorHL, GuiControlProfile)); addField("fillColorNA", TypeColorI, Offset(mFillColorNA, GuiControlProfile)); + addField("fillColorERR", TypeColorI, Offset(mFillColorERR, GuiControlProfile)); addField("fillColorSEL", TypeColorI, Offset(mFillColorSEL, GuiControlProfile)); addField("border", TypeS32, Offset(mBorder, GuiControlProfile), "Border type (0=no border)." ); diff --git a/Engine/source/gui/core/guiTypes.h b/Engine/source/gui/core/guiTypes.h index c9dc36bad..51f33d21b 100644 --- a/Engine/source/gui/core/guiTypes.h +++ b/Engine/source/gui/core/guiTypes.h @@ -385,6 +385,7 @@ public: ColorI mFillColor; ///< Fill color, this is used to fill the bounds of the control if it is opaque ColorI mFillColorHL; ///< This is used instead of mFillColor if the object is highlighted ColorI mFillColorNA; ///< This is used instead of mFillColor if the object is not active or disabled + ColorI mFillColorERR; ///< This is used instead of mFillColor if the object has an error or is invalid ColorI mFillColorSEL; ///< This is used instead of mFillColor if the object is selected S32 mBorder; ///< For most controls, if mBorder is > 0 a border will be drawn, some controls use this to draw different types of borders however @see guiDefaultControlRender.cc diff --git a/Engine/source/gui/worldEditor/worldEditor.cpp b/Engine/source/gui/worldEditor/worldEditor.cpp index 0273ffeb4..6065b233e 100644 --- a/Engine/source/gui/worldEditor/worldEditor.cpp +++ b/Engine/source/gui/worldEditor/worldEditor.cpp @@ -2810,7 +2810,7 @@ void WorldEditor::clearSelection() void WorldEditor::selectObject( SimObject *obj ) { - if ( mSelectionLocked || !mSelected ) + if ( mSelectionLocked || !mSelected || !obj ) return; // Don't check isSelectionEnabled of SceneObjects here as we @@ -2833,7 +2833,7 @@ void WorldEditor::selectObject( const char* obj ) void WorldEditor::unselectObject( SimObject *obj ) { - if ( mSelectionLocked || !mSelected ) + if ( mSelectionLocked || !mSelected || !obj ) return; if ( !objClassIgnored( obj ) && mSelected->objInSet( obj ) ) diff --git a/Engine/source/lighting/advanced/advancedLightBinManager.cpp b/Engine/source/lighting/advanced/advancedLightBinManager.cpp index dd71afeb0..98330a5de 100644 --- a/Engine/source/lighting/advanced/advancedLightBinManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightBinManager.cpp @@ -318,6 +318,8 @@ void AdvancedLightBinManager::render( SceneRenderState *state ) const U32 numPrims = curEntry.numPrims; const U32 numVerts = curEntry.vertBuffer->mNumVerts; + ShadowMapParams *lsp = curLightInfo->getExtended(); + // Skip lights which won't affect the scene. if ( !curLightMat || curLightInfo->getBrightness() <= 0.001f ) continue; @@ -329,15 +331,12 @@ void AdvancedLightBinManager::render( SceneRenderState *state ) mShadowManager->setLightShadowMap( curEntry.shadowMap ); mShadowManager->setLightDynamicShadowMap( curEntry.dynamicShadowMap ); - // Let the shadow know we're about to render from it. - if ( curEntry.shadowMap ) - curEntry.shadowMap->preLightRender(); - if ( curEntry.dynamicShadowMap ) curEntry.dynamicShadowMap->preLightRender(); - // Set geometry GFX->setVertexBuffer( curEntry.vertBuffer ); GFX->setPrimitiveBuffer( curEntry.primBuffer ); + lsp->getOcclusionQuery()->begin(); + // Render the material passes while( curLightMat->matInstance->setupPass( state, sgData ) ) { @@ -352,10 +351,7 @@ void AdvancedLightBinManager::render( SceneRenderState *state ) GFX->drawPrimitive(GFXTriangleList, 0, numPrims); } - // Tell it we're done rendering. - if ( curEntry.shadowMap ) - curEntry.shadowMap->postLightRender(); - if ( curEntry.dynamicShadowMap ) curEntry.dynamicShadowMap->postLightRender(); + lsp->getOcclusionQuery()->end(); } // Set NULL for active shadow map (so nothing gets confused) diff --git a/Engine/source/lighting/advanced/advancedLightManager.cpp b/Engine/source/lighting/advanced/advancedLightManager.cpp index d82f4f69c..baefa15b5 100644 --- a/Engine/source/lighting/advanced/advancedLightManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightManager.cpp @@ -105,7 +105,7 @@ void AdvancedLightManager::activate( SceneManager *sceneManager ) // we prefer the floating point format if it works. Vector formats; formats.push_back( GFXFormatR16G16B16A16F ); - formats.push_back( GFXFormatR16G16B16A16 ); + //formats.push_back( GFXFormatR16G16B16A16 ); GFXFormat blendTargetFormat = GFX->selectSupportedFormat( &GFXDefaultRenderTargetProfile, formats, true, diff --git a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp index ce90bcc39..c97fbbcf5 100644 --- a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp +++ b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp @@ -156,8 +156,8 @@ void DeferredRTLightingFeatGLSL::processPix( Vector &component oneOverTargetSize->constSortPos = cspPass; } - meta->addStatement( new GenOp( " float id_NL_Att, id_specular;\r\n float3 id_lightcolor;\r\n" ) ); - meta->addStatement( new GenOp( avar( " %s(tex2D(@, @ + float2(0.0, @.y)), id_lightcolor, id_NL_Att, id_specular);\r\n", + meta->addStatement( new GenOp( " float id_NL_Att, id_specular;\r\n vec3 id_lightcolor;\r\n" ) ); + meta->addStatement( new GenOp( avar( " %s(tex2D(@, @ + vec2(0.0, @.y)), id_lightcolor, id_NL_Att, id_specular);\r\n", unconditionLightInfo.c_str() ), lightInfoBuffer, uvScene, oneOverTargetSize ) ); meta->addStatement( new GenOp(" @ = lerp(@, id_lightcolor, 0.5);\r\n", d_lightcolor, d_lightcolor ) ); @@ -167,7 +167,7 @@ void DeferredRTLightingFeatGLSL::processPix( Vector &component // This is kind of weak sauce if( !fd.features[MFT_VertLit] && !fd.features[MFT_ToneMap] && !fd.features[MFT_LightMap] && !fd.features[MFT_SubSurface] ) - meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(@, 1.0)", d_lightcolor ), Material::Mul ) ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(@, 1.0)", d_lightcolor ), Material::Mul ) ) ); output = meta; } @@ -311,7 +311,7 @@ void DeferredBumpFeatGLSL::processPix( Vector &componentList, meta->addStatement( new GenOp( " @.xy += @.xy * @;\r\n", bumpNorm, detailBump, detailBumpScale ) ); } - // This var is read from GBufferConditionerHLSL and + // This var is read from GBufferConditionerGLSL and // used in the prepass output. // // By using the 'half' type here we get a bunch of partial @@ -533,11 +533,13 @@ void DeferredPixelSpecularGLSL::processPix( Vector &component specPow->constSortPos = cspPotentialPrimitive; } - Var *specStrength = new Var; - specStrength->setType( "float" ); - specStrength->setName( "specularStrength" ); - specStrength->uniform = true; - specStrength->constSortPos = cspPotentialPrimitive; + Var *specStrength = (Var*)LangElement::find( "specularStrength" ); + if (!specStrength) + { + specStrength = new Var( "specularStrength", "float" ); + specStrength->uniform = true; + specStrength->constSortPos = cspPotentialPrimitive; + } Var *lightInfoSamp = (Var *)LangElement::find( "lightInfoSample" ); Var *d_specular = (Var*)LangElement::find( "d_specular" ); @@ -555,10 +557,10 @@ void DeferredPixelSpecularGLSL::processPix( Vector &component meta->addStatement(new GenOp(" @ = clamp( lerp( @, @ * @, @.a), 0, 1);\r\n", d_specular, d_specular, accuSpecular, d_specular, accuPlc)); } // (a^m)^n = a^(m*n) - meta->addStatement( new GenOp( " @ = pow( abs(@), max((@ / AL_ConstantSpecularPower),1.0f)) * @;\r\n", + meta->addStatement( new GenOp( " @ = pow( abs(@), max((@ / AL_ConstantSpecularPower),1.0f)) * @;\r\n", specDecl, d_specular, specPow, specStrength ) ); - LangElement *specMul = new GenOp( "float4( @.rgb, 0 ) * @", specCol, specular ); + LangElement *specMul = new GenOp( "vec4( @.rgb, 0 ) * @", specCol, specular ); LangElement *final = specMul; // We we have a normal map then mask the specular @@ -682,10 +684,10 @@ void DeferredMinnaertGLSL::processPix( Vector &componentList, Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" ); - meta->addStatement( new GenOp( avar( " float4 normalDepth = %s(@, @);\r\n", unconditionPrePassMethod.c_str() ), prepassBuffer, uvScene ) ); + meta->addStatement( new GenOp( avar( " vec4 normalDepth = %s(@, @);\r\n", unconditionPrePassMethod.c_str() ), prepassBuffer, uvScene ) ); meta->addStatement( new GenOp( " float vDotN = dot(normalDepth.xyz, @);\r\n", wsViewVec ) ); meta->addStatement( new GenOp( " float Minnaert = pow( @, @) * pow(vDotN, 1.0 - @);\r\n", d_NL_Att, minnaertConstant, minnaertConstant ) ); - meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(Minnaert, Minnaert, Minnaert, 1.0)" ), Material::Mul ) ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(Minnaert, Minnaert, Minnaert, 1.0)" ), Material::Mul ) ) ); output = meta; } @@ -713,7 +715,7 @@ void DeferredSubSurfaceGLSL::processPix( Vector &componentLis MultiLine *meta = new MultiLine; meta->addStatement( new GenOp( " float subLamb = smoothstep(-@.a, 1.0, @) - smoothstep(0.0, 1.0, @);\r\n", subSurfaceParams, d_NL_Att, d_NL_Att ) ); meta->addStatement( new GenOp( " subLamb = max(0.0, subLamb);\r\n" ) ); - meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(@ + (subLamb * @.rgb), 1.0)", d_lightcolor, subSurfaceParams ), Material::Mul ) ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(@ + (subLamb * @.rgb), 1.0)", d_lightcolor, subSurfaceParams ), Material::Mul ) ) ); output = meta; } diff --git a/Engine/source/lighting/advanced/glsl/deferredShadingFeaturesGLSL.cpp b/Engine/source/lighting/advanced/glsl/deferredShadingFeaturesGLSL.cpp new file mode 100644 index 000000000..1dc906989 --- /dev/null +++ b/Engine/source/lighting/advanced/glsl/deferredShadingFeaturesGLSL.cpp @@ -0,0 +1,190 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "platform/platform.h" +#include "lighting/advanced/glsl/deferredShadingFeaturesGLSL.h" + +#include "lighting/advanced/advancedLightBinManager.h" +#include "shaderGen/langElement.h" +#include "shaderGen/shaderOp.h" +#include "shaderGen/conditionerFeature.h" +#include "renderInstance/renderPrePassMgr.h" +#include "materials/processedMaterial.h" +#include "materials/materialFeatureTypes.h" + + +//**************************************************************************** +// Deferred Shading Features +//**************************************************************************** + +// Specular Map -> Blue of Material Buffer ( greyscaled ) +// Gloss Map (Alpha Channel of Specular Map) -> Alpha ( Spec Power ) of Material Info Buffer. +void DeferredSpecMapGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) +{ + // Get the texture coord. + Var *texCoord = getInTexCoord( "texCoord", "vec2", true, componentList ); + + // search for color var + Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + MultiLine * meta = new MultiLine; + if ( !material ) + { + // create color var + material = new Var; + material->setType( "vec4" ); + material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + material->setStructName("OUT"); + } + + // create texture var + Var *specularMap = new Var; + specularMap->setType( "sampler2D" ); + specularMap->setName( "specularMap" ); + specularMap->uniform = true; + specularMap->sampler = true; + specularMap->constNum = Var::getTexUnitNum(); + LangElement *texOp = new GenOp( "tex2D(@, @)", specularMap, texCoord ); + //matinfo.g slot reserved for AO later + meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material)); + meta->addStatement(new GenOp(" @.b = dot(tex2D(@, @).rgb, vec3(0.3, 0.59, 0.11));\r\n", material, specularMap, texCoord)); + meta->addStatement(new GenOp(" @.a = tex2D(@, @).a;\r\n", material, specularMap, texCoord)); + output = meta; +} + +ShaderFeature::Resources DeferredSpecMapGLSL::getResources( const MaterialFeatureData &fd ) +{ + Resources res; + res.numTex = 1; + res.numTexReg = 1; + + return res; +} + +void DeferredSpecMapGLSL::setTexData( Material::StageData &stageDat, + const MaterialFeatureData &fd, + RenderPassData &passData, + U32 &texIndex ) +{ + GFXTextureObject *tex = stageDat.getTex( MFT_SpecularMap ); + if ( tex ) + { + passData.mTexType[ texIndex ] = Material::Standard; + passData.mSamplerNames[ texIndex ] = "specularMap"; + passData.mTexSlot[ texIndex++ ].texObject = tex; + } +} + +void DeferredSpecMapGLSL::processVert( Vector &componentList, + const MaterialFeatureData &fd ) +{ + MultiLine *meta = new MultiLine; + getOutTexCoord( "texCoord", + "vec2", + true, + fd.features[MFT_TexAnim], + meta, + componentList ); + output = meta; +} + +// Material Info Flags -> Red ( Flags ) of Material Info Buffer. +void DeferredMatInfoFlagsGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) +{ + MultiLine *meta = new MultiLine; + + // search for material var + Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + if ( !material ) + { + // create material var + material = new Var; + material->setType( "vec4" ); + material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + material->setStructName("OUT"); + } + + Var *matInfoFlags = new Var; + matInfoFlags->setType( "float" ); + matInfoFlags->setName( "matInfoFlags" ); + matInfoFlags->uniform = true; + matInfoFlags->constSortPos = cspPotentialPrimitive; + + meta->addStatement(output = new GenOp(" @.r = @;\r\n", material, matInfoFlags)); + output = meta; +} + +// Spec Strength -> Blue Channel of Material Info Buffer. +// Spec Power -> Alpha Channel ( of Material Info Buffer. +void DeferredSpecVarsGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) +{ + + // search for material var + Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + if ( !material ) + { + // create material var + material = new Var; + material->setType( "vec4" ); + material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + material->setStructName("OUT"); + } + + Var *specStrength = new Var; + specStrength->setType( "float" ); + specStrength->setName( "specularStrength" ); + specStrength->uniform = true; + specStrength->constSortPos = cspPotentialPrimitive; + + Var *specPower = new Var; + specPower->setType("float"); + specPower->setName("specularPower"); + specPower->uniform = true; + specPower->constSortPos = cspPotentialPrimitive; + + MultiLine *meta = new MultiLine; + //matinfo.g slot reserved for AO later + meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material)); + meta->addStatement(new GenOp(" @.a = @/128;\r\n", material, specPower)); + meta->addStatement(new GenOp(" @.b = @/5;\r\n", material, specStrength)); + output = meta; +} + +// Black -> Blue and Alpha of Color Buffer (representing no specular) +void DeferredEmptySpecGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) +{ + // search for material var + Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + if ( !material ) + { + // create material var + material = new Var; + material->setType( "vec4" ); + material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + material->setStructName("OUT"); + } + + MultiLine * meta = new MultiLine; + //matinfo.g slot reserved for AO later + meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material)); + meta->addStatement(new GenOp(" @.ba = vec2(0.0);\r\n", material)); + output = meta; +} diff --git a/Engine/source/lighting/advanced/glsl/deferredShadingFeaturesGLSL.h b/Engine/source/lighting/advanced/glsl/deferredShadingFeaturesGLSL.h new file mode 100644 index 000000000..f687bd917 --- /dev/null +++ b/Engine/source/lighting/advanced/glsl/deferredShadingFeaturesGLSL.h @@ -0,0 +1,85 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _DEFERREDSHADINGGLSL_H_ +#define _DEFERREDSHADINGGLSL_H_ + +#include "shaderGen/GLSL/shaderFeatureGLSL.h" +#include "shaderGen/GLSL/bumpGLSL.h" +#include "shaderGen/GLSL/pixSpecularGLSL.h" + +// Specular Outputs +class DeferredSpecMapGLSL : public ShaderFeatureGLSL +{ +public: + virtual String getName() { return "Deferred Shading: Specular Map"; } + + virtual void processPix( Vector &componentList, + const MaterialFeatureData &fd ); + + virtual Resources getResources( const MaterialFeatureData &fd ); + + // Sets textures and texture flags for current pass + virtual void setTexData( Material::StageData &stageDat, + const MaterialFeatureData &fd, + RenderPassData &passData, + U32 &texIndex ); + + virtual void processVert( Vector &componentList, + const MaterialFeatureData &fd ); +}; + +class DeferredMatInfoFlagsGLSL : public ShaderFeatureGLSL +{ +public: + virtual String getName() { return "Deferred Shading: Mat Info Flags"; } + + virtual void processPix( Vector &componentList, + const MaterialFeatureData &fd ); + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; } +}; + +class DeferredSpecVarsGLSL : public ShaderFeatureGLSL +{ +public: + virtual String getName() { return "Deferred Shading: Specular Explicit Numbers"; } + + virtual void processPix( Vector &componentList, + const MaterialFeatureData &fd ); + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; } +}; + + +class DeferredEmptySpecGLSL : public ShaderFeatureGLSL +{ +public: + virtual String getName() { return "Deferred Shading: Empty Specular"; } + + virtual void processPix( Vector &componentList, + const MaterialFeatureData &fd ); + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; } +}; + +#endif \ No newline at end of file diff --git a/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp b/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp index 6e5795e83..d2d383148 100644 --- a/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp +++ b/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp @@ -170,7 +170,7 @@ void GBufferConditionerGLSL::processPix( Vector &componentLis if ( fd.features[ MFT_IsTranslucentZWrite ] ) { alphaVal = new Var( "outAlpha", "float" ); - meta->addStatement( new GenOp( " @ = col.a; // MFT_IsTranslucentZWrite\r\n", new DecOp( alphaVal ) ) ); + meta->addStatement( new GenOp( " @ = OUT_col1.a; // MFT_IsTranslucentZWrite\r\n", new DecOp( alphaVal ) ) ); } // If using interlaced normals, invert the normal @@ -397,7 +397,7 @@ Var* GBufferConditionerGLSL::_unconditionInput( Var *conditionedInput, MultiLine // Recover depth from encoding if(mNormalStorageType != CartesianXYZ) { - const U64 maxValPerChannel = 1 << mBitsPerChannel; + const U64 maxValPerChannel = (U64)1 << mBitsPerChannel; meta->addStatement( new GenOp( " \r\n // Decode depth\r\n" ) ); meta->addStatement( new GenOp( avar( " @.w = dot( @.zw, float2(1.0, 1.0/%llu.0));\r\n", maxValPerChannel - 1 ), retVar, conditionedInput ) ); diff --git a/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp b/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp index deda7cbae..0bfbed42a 100644 --- a/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp +++ b/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp @@ -227,7 +227,7 @@ void DeferredBumpFeatHLSL::processVert( Vector &componentLis const bool useTexAnim = fd.features[MFT_TexAnim]; // Make sure there are texcoords - if( !fd.features[MFT_Parallax] && !fd.features[MFT_DiffuseMap] ) + if( !fd.features[MFT_Parallax] && !fd.features[MFT_DiffuseMap]) { getOutTexCoord( "texCoord", @@ -532,11 +532,13 @@ void DeferredPixelSpecularHLSL::processPix( Vector &component specPow->constSortPos = cspPotentialPrimitive; } - Var *specStrength = new Var; - specStrength->setType( "float" ); - specStrength->setName( "specularStrength" ); - specStrength->uniform = true; - specStrength->constSortPos = cspPotentialPrimitive; + Var *specStrength = (Var*)LangElement::find( "specularStrength" ); + if (!specStrength) + { + specStrength = new Var( "specularStrength", "float" ); + specStrength->uniform = true; + specStrength->constSortPos = cspPotentialPrimitive; + } Var *lightInfoSamp = (Var *)LangElement::find( "lightInfoSample" ); Var *d_specular = (Var*)LangElement::find( "d_specular" ); @@ -556,7 +558,7 @@ void DeferredPixelSpecularHLSL::processPix( Vector &component // (a^m)^n = a^(m*n) meta->addStatement( new GenOp( " @ = pow( abs(@), max((@ / AL_ConstantSpecularPower),1.0f)) * @;\r\n", - specDecl, d_specular, specPow, specStrength ) ); + specDecl, d_specular, specPow, specStrength)); LangElement *specMul = new GenOp( "float4( @.rgb, 0 ) * @", specCol, specular ); LangElement *final = specMul; diff --git a/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.cpp b/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.cpp new file mode 100644 index 000000000..3e42af953 --- /dev/null +++ b/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.cpp @@ -0,0 +1,187 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "platform/platform.h" +#include "lighting/advanced/hlsl/deferredShadingFeaturesHLSL.h" + +#include "lighting/advanced/advancedLightBinManager.h" +#include "shaderGen/langElement.h" +#include "shaderGen/shaderOp.h" +#include "shaderGen/conditionerFeature.h" +#include "renderInstance/renderPrePassMgr.h" +#include "materials/processedMaterial.h" +#include "materials/materialFeatureTypes.h" + + +//**************************************************************************** +// Deferred Shading Features +//**************************************************************************** + +// Specular Map -> Blue of Material Buffer ( greyscaled ) +// Gloss Map (Alpha Channel of Specular Map) -> Alpha ( Spec Power ) of Material Info Buffer. +void DeferredSpecMapHLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) +{ + // Get the texture coord. + Var *texCoord = getInTexCoord( "texCoord", "float2", true, componentList ); + + // search for color var + Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + MultiLine * meta = new MultiLine; + if ( !material ) + { + // create color var + material = new Var; + material->setType( "fragout" ); + material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + material->setStructName( "OUT" ); + } + + // create texture var + Var *specularMap = new Var; + specularMap->setType( "sampler2D" ); + specularMap->setName( "specularMap" ); + specularMap->uniform = true; + specularMap->sampler = true; + specularMap->constNum = Var::getTexUnitNum(); + LangElement *texOp = new GenOp( "tex2D(@, @)", specularMap, texCoord ); + + //matinfo.g slot reserved for AO later + meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material)); + meta->addStatement(new GenOp(" @.b = dot(tex2D(@, @).rgb, float3(0.3, 0.59, 0.11));\r\n", material, specularMap, texCoord)); + meta->addStatement(new GenOp(" @.a = tex2D(@, @).a;\r\n", material, specularMap, texCoord)); + output = meta; +} + +ShaderFeature::Resources DeferredSpecMapHLSL::getResources( const MaterialFeatureData &fd ) +{ + Resources res; + res.numTex = 1; + res.numTexReg = 1; + + return res; +} + +void DeferredSpecMapHLSL::setTexData( Material::StageData &stageDat, + const MaterialFeatureData &fd, + RenderPassData &passData, + U32 &texIndex ) +{ + GFXTextureObject *tex = stageDat.getTex( MFT_SpecularMap ); + if ( tex ) + { + passData.mTexType[ texIndex ] = Material::Standard; + passData.mSamplerNames[ texIndex ] = "specularMap"; + passData.mTexSlot[ texIndex++ ].texObject = tex; + } +} + +void DeferredSpecMapHLSL::processVert( Vector &componentList, + const MaterialFeatureData &fd ) +{ + MultiLine *meta = new MultiLine; + getOutTexCoord( "texCoord", + "float2", + true, + fd.features[MFT_TexAnim], + meta, + componentList ); + output = meta; +} + +// Material Info Flags -> Red ( Flags ) of Material Info Buffer. +void DeferredMatInfoFlagsHLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) +{ + // search for material var + Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + if ( !material ) + { + // create material var + material = new Var; + material->setType( "fragout" ); + material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + material->setStructName( "OUT" ); + } + + Var *matInfoFlags = new Var; + matInfoFlags->setType( "float" ); + matInfoFlags->setName( "matInfoFlags" ); + matInfoFlags->uniform = true; + matInfoFlags->constSortPos = cspPotentialPrimitive; + + output = new GenOp( " @.r = @;\r\n", material, matInfoFlags ); +} + +// Spec Strength -> Blue Channel of Material Info Buffer. +// Spec Power -> Alpha Channel ( of Material Info Buffer. +void DeferredSpecVarsHLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) +{ + // search for material var + Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + if ( !material ) + { + // create material var + material = new Var; + material->setType( "fragout" ); + material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + material->setStructName( "OUT" ); + } + + Var *specStrength = new Var; + specStrength->setType( "float" ); + specStrength->setName( "specularStrength" ); + specStrength->uniform = true; + specStrength->constSortPos = cspPotentialPrimitive; + + Var *specPower = new Var; + specPower->setType( "float" ); + specPower->setName( "specularPower" ); + specPower->uniform = true; + specPower->constSortPos = cspPotentialPrimitive; + + MultiLine * meta = new MultiLine; + //matinfo.g slot reserved for AO later + meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material)); + meta->addStatement(new GenOp(" @.a = @/128;\r\n", material, specPower)); + meta->addStatement(new GenOp(" @.b = @/5;\r\n", material, specStrength)); + output = meta; +} + +// Black -> Blue and Alpha of matinfo Buffer (representing no specular), White->G (representing No AO) +void DeferredEmptySpecHLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) +{ + // search for material var + Var *material = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget2)); + if (!material) + { + // create color var + material = new Var; + material->setType("fragout"); + material->setName(getOutputTargetVarName(ShaderFeature::RenderTarget2)); + material->setStructName("OUT"); + } + + MultiLine * meta = new MultiLine; + //matinfo.g slot reserved for AO later + meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material)); + meta->addStatement(new GenOp(" @.ba = 0.0;\r\n", material)); + output = meta; +} diff --git a/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.h b/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.h new file mode 100644 index 000000000..9f43321b7 --- /dev/null +++ b/Engine/source/lighting/advanced/hlsl/deferredShadingFeaturesHLSL.h @@ -0,0 +1,84 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _DEFERREDSHADINGHLSL_H_ +#define _DEFERREDSHADINGHLSL_H_ + +#include "shaderGen/HLSL/shaderFeatureHLSL.h" +#include "shaderGen/HLSL/bumpHLSL.h" +#include "shaderGen/HLSL/pixSpecularHLSL.h" + +// Specular Outputs +class DeferredSpecMapHLSL : public ShaderFeatureHLSL +{ +public: + virtual String getName() { return "Deferred Shading: Specular Map"; } + + virtual void processPix( Vector &componentList, + const MaterialFeatureData &fd ); + + virtual Resources getResources( const MaterialFeatureData &fd ); + + // Sets textures and texture flags for current pass + virtual void setTexData( Material::StageData &stageDat, + const MaterialFeatureData &fd, + RenderPassData &passData, + U32 &texIndex ); + + virtual void processVert( Vector &componentList, + const MaterialFeatureData &fd ); +}; + +class DeferredMatInfoFlagsHLSL : public ShaderFeatureHLSL +{ +public: + virtual String getName() { return "Deferred Shading: Mat Info Flags"; } + + virtual void processPix( Vector &componentList, + const MaterialFeatureData &fd ); + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; } +}; + +class DeferredSpecVarsHLSL : public ShaderFeatureHLSL +{ +public: + virtual String getName() { return "Deferred Shading: Specular Explicit Numbers"; } + + virtual void processPix( Vector &componentList, + const MaterialFeatureData &fd ); + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; } +}; + +class DeferredEmptySpecHLSL : public ShaderFeatureHLSL +{ +public: + virtual String getName() { return "Deferred Shading: Empty Specular"; } + + virtual void processPix( Vector &componentList, + const MaterialFeatureData &fd ); + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; } +}; + +#endif \ No newline at end of file diff --git a/Engine/source/lighting/advanced/hlsl/gBufferConditionerHLSL.cpp b/Engine/source/lighting/advanced/hlsl/gBufferConditionerHLSL.cpp index 93f9477e9..6f99d035c 100644 --- a/Engine/source/lighting/advanced/hlsl/gBufferConditionerHLSL.cpp +++ b/Engine/source/lighting/advanced/hlsl/gBufferConditionerHLSL.cpp @@ -170,7 +170,7 @@ void GBufferConditionerHLSL::processPix( Vector &componentLis if ( fd.features[ MFT_IsTranslucentZWrite ] ) { alphaVal = new Var( "outAlpha", "float" ); - meta->addStatement( new GenOp( " @ = OUT.col.a; // MFT_IsTranslucentZWrite\r\n", new DecOp( alphaVal ) ) ); + meta->addStatement( new GenOp( " @ = OUT.col1.a; // MFT_IsTranslucentZWrite\r\n", new DecOp( alphaVal ) ) ); } // If using interlaced normals, invert the normal diff --git a/Engine/source/lighting/shadowMap/lightShadowMap.cpp b/Engine/source/lighting/shadowMap/lightShadowMap.cpp index 53a6f4e8d..984f6cbc6 100644 --- a/Engine/source/lighting/shadowMap/lightShadowMap.cpp +++ b/Engine/source/lighting/shadowMap/lightShadowMap.cpp @@ -89,8 +89,6 @@ LightShadowMap::LightShadowMap( LightInfo *light ) mLastUpdate( 0 ), mLastCull( 0 ), mIsViewDependent( false ), - mVizQuery( NULL ), - mWasOccluded( false ), mLastScreenSize( 0.0f ), mLastPriority( 0.0f ), mIsDynamic( false ) @@ -98,9 +96,7 @@ LightShadowMap::LightShadowMap( LightInfo *light ) GFXTextureManager::addEventDelegate( this, &LightShadowMap::_onTextureEvent ); mTarget = GFX->allocRenderToTextureTarget(); - mVizQuery = GFX->createOcclusionQuery(); - - smShadowMaps.push_back(this); + smShadowMaps.push_back( this ); mStaticRefreshTimer = PlatformTimer::create(); mDynamicRefreshTimer = PlatformTimer::create(); } @@ -108,8 +104,9 @@ LightShadowMap::LightShadowMap( LightInfo *light ) LightShadowMap::~LightShadowMap() { mTarget = NULL; - SAFE_DELETE( mVizQuery ); - + SAFE_DELETE(mStaticRefreshTimer); + SAFE_DELETE(mDynamicRefreshTimer); + releaseTextures(); smShadowMaps.remove( this ); @@ -334,23 +331,6 @@ void LightShadowMap::render( RenderPassManager* renderPass, mLastUpdate = Sim::getCurrentTime(); } -void LightShadowMap::preLightRender() -{ - PROFILE_SCOPE( LightShadowMap_prepLightRender ); - - if ( mVizQuery ) - { - mWasOccluded = mVizQuery->getStatus( true ) == GFXOcclusionQuery::Occluded; - mVizQuery->begin(); - } -} - -void LightShadowMap::postLightRender() -{ - if ( mVizQuery ) - mVizQuery->end(); -} - BaseMatInstance* LightShadowMap::getShadowMaterial( BaseMatInstance *inMat ) const { // See if we have an existing material hook. @@ -610,11 +590,14 @@ ShadowMapParams::ShadowMapParams( LightInfo *light ) shadowSoftness = 0.15f; fadeStartDist = 0.0f; lastSplitTerrainOnly = false; + mQuery = GFX->createOcclusionQuery(); + _validate(); } ShadowMapParams::~ShadowMapParams() { + SAFE_DELETE( mQuery ); SAFE_DELETE( mShadowMap ); SAFE_DELETE( mDynamicShadowMap ); } diff --git a/Engine/source/lighting/shadowMap/lightShadowMap.h b/Engine/source/lighting/shadowMap/lightShadowMap.h index 2cbb2ca5e..d96481192 100644 --- a/Engine/source/lighting/shadowMap/lightShadowMap.h +++ b/Engine/source/lighting/shadowMap/lightShadowMap.h @@ -47,6 +47,9 @@ #ifndef _GFXSHADER_H_ #include "gfx/gfxShader.h" #endif +#ifndef _GFXOCCLUSIONQUERY_H_ +#include "gfx/gfxOcclusionQuery.h" +#endif #ifndef _PLATFORM_PLATFORMTIMER_H_ #include "platform/platformTimer.h" #endif @@ -61,7 +64,6 @@ struct SceneData; class GFXShaderConstBuffer; class GFXShaderConstHandle; class GFXShader; -class GFXOcclusionQuery; class LightManager; class RenderPassManager; @@ -169,12 +171,6 @@ public: bool isViewDependent() const { return mIsViewDependent; } - bool wasOccluded() const { return mWasOccluded; } - - void preLightRender(); - - void postLightRender(); - void updatePriority( const SceneRenderState *state, U32 currTimeMs ); F32 getLastScreenSize() const { return mLastScreenSize; } @@ -257,15 +253,6 @@ protected: /// The time this shadow was last culled and prioritized. U32 mLastCull; - /// The shadow occlusion query used when the light is - /// rendered to determine if any pixel of it is visible. - GFXOcclusionQuery *mVizQuery; - - /// If true the light was occluded by geometry the - /// last frame it was updated. - //the last frame. - bool mWasOccluded; - F32 mLastScreenSize; F32 mLastPriority; @@ -325,6 +312,8 @@ public: bool hasCookieTex() const { return cookie.isNotEmpty(); } + GFXOcclusionQuery* getOcclusionQuery() const { return mQuery; } + GFXTextureObject* getCookieTex(); GFXCubemap* getCookieCubeTex(); @@ -339,6 +328,7 @@ protected: /// LightShadowMap *mShadowMap; LightShadowMap *mDynamicShadowMap; + GFXOcclusionQuery* mQuery; LightInfo *mLight; diff --git a/Engine/source/lighting/shadowMap/shadowMapPass.cpp b/Engine/source/lighting/shadowMap/shadowMapPass.cpp index 7c17046e1..dea7305b5 100644 --- a/Engine/source/lighting/shadowMap/shadowMapPass.cpp +++ b/Engine/source/lighting/shadowMap/shadowMapPass.cpp @@ -174,12 +174,12 @@ void ShadowMapPass::render( SceneManager *sceneManager, continue; // --- Static Shadow Map --- - LightShadowMap *lsm = params->getOrCreateShadowMap(); - LightShadowMap *dlsm = params->getOrCreateShadowMap(true); + LightShadowMap *lsm = params->getOrCreateShadowMap(); + LightShadowMap *dlsm = params->getOrCreateShadowMap(true); // First check the visiblity query... if it wasn't // visible skip it. - if (lsm->wasOccluded() || dlsm->wasOccluded()) + if(params->getOcclusionQuery()->getStatus(true) == GFXOcclusionQuery::Occluded) continue; // Any shadow that is visible is counted as being @@ -187,9 +187,9 @@ void ShadowMapPass::render( SceneManager *sceneManager, ++smActiveShadowMaps; // Do a priority update for this shadow. - lsm->updatePriority(diffuseState, currTime); + lsm->updatePriority(diffuseState, currTime); - shadowMaps.push_back(lsm); + shadowMaps.push_back(lsm); // --- Dynamic Shadow Map --- @@ -198,7 +198,7 @@ void ShadowMapPass::render( SceneManager *sceneManager, ++smActiveShadowMaps; // Do a priority update for this shadow. - dlsm->updatePriority(diffuseState, currTime); + dlsm->updatePriority(diffuseState, currTime); shadowMaps.push_back( dlsm ); } @@ -306,4 +306,4 @@ void DynamicShadowRenderPassManager::addInst( RenderInst *inst ) } Parent::addInst(inst); -} \ No newline at end of file +} diff --git a/Engine/source/materials/matTextureTarget.cpp b/Engine/source/materials/matTextureTarget.cpp index ba84142f6..f6770c83b 100644 --- a/Engine/source/materials/matTextureTarget.cpp +++ b/Engine/source/materials/matTextureTarget.cpp @@ -47,9 +47,16 @@ bool NamedTexTarget::registerWithName( const String &name ) } // Make sure the target name isn't empty or already taken. - if ( name.isEmpty() || smTargets.contains( name ) ) + if ( name.isEmpty()) + { + Con::errorf("NamedTexTarget::registerWithName( const String &name ) No name given!"); + return false; + } + if (smTargets.contains( name ) ) + { + Con::errorf("NamedTexTarget::registerWithName( %s ) Already used!", name.c_str()); return false; - + } mName = name; mIsRegistered = true; smTargets.insert( mName, this ); diff --git a/Engine/source/materials/materialDefinition.cpp b/Engine/source/materials/materialDefinition.cpp index 408df976f..883d4b7ab 100644 --- a/Engine/source/materials/materialDefinition.cpp +++ b/Engine/source/materials/materialDefinition.cpp @@ -162,6 +162,9 @@ Material::Material() mSeqFramePerSec[i] = 0.0f; mSeqSegSize[i] = 0.0f; + + // Deferred Shading + mMatInfoFlags[i] = 0.0f; } dMemset(mCellIndex, 0, sizeof(mCellIndex)); @@ -170,6 +173,9 @@ Material::Material() dMemset(mNormalMapAtlas, 0, sizeof(mNormalMapAtlas)); dMemset(mUseAnisotropic, 0, sizeof(mUseAnisotropic)); + // Deferred Shading : Metalness + dMemset(mUseMetalness, 0, sizeof(mUseMetalness)); + mImposterLimits = Point4F::Zero; mDoubleSided = false; @@ -204,6 +210,9 @@ Material::Material() mDirectSoundOcclusion = 1.f; mReverbSoundOcclusion = 1.0; + + // Deferred Shading + mIsSky = false; } void Material::initPersistFields() @@ -289,10 +298,7 @@ void Material::initPersistFields() addField( "useAnisotropic", TypeBool, Offset(mUseAnisotropic, Material), MAX_STAGES, "Use anisotropic filtering for the textures of this stage." ); - - addField("envMap", TypeImageFilename, Offset(mEnvMapFilename, Material), MAX_STAGES, - "The name of an environment map cube map to apply to this material." ); - + addField("vertLit", TypeBool, Offset(mVertLit, Material), MAX_STAGES, "If true the vertex color is used for lighting." ); @@ -379,9 +385,6 @@ void Material::initPersistFields() addProtectedField("bumpTex", TypeImageFilename, Offset(mNormalMapFilename, Material), defaultProtectedSetNotEmptyFn, emptyStringProtectedGetFn, MAX_STAGES, "For backwards compatibility.\n@see normalMap\n"); - addProtectedField("envTex", TypeImageFilename, Offset(mEnvMapFilename, Material), - defaultProtectedSetNotEmptyFn, emptyStringProtectedGetFn, MAX_STAGES, - "For backwards compatibility.\n@see envMap\n"); addProtectedField("colorMultiply", TypeColorF, Offset(mDiffuse, Material), defaultProtectedSetNotEmptyFn, emptyStringProtectedGetFn, MAX_STAGES, "For backwards compatibility.\n@see diffuseColor\n"); @@ -417,6 +420,9 @@ void Material::initPersistFields() addField("dynamicCubemap", TypeBool, Offset(mDynamicCubemap, Material), "Enables the material to use the dynamic cubemap from the ShapeBase object its applied to." ); + addField("isSky", TypeBool, Offset(mIsSky, Material), + "Sky support. Alters draw dimensions." ); + addGroup( "Behavioral" ); addField( "showFootprints", TypeBool, Offset( mShowFootprints, Material ), diff --git a/Engine/source/materials/materialDefinition.h b/Engine/source/materials/materialDefinition.h index 491b56cf0..d676c8f02 100644 --- a/Engine/source/materials/materialDefinition.h +++ b/Engine/source/materials/materialDefinition.h @@ -221,8 +221,6 @@ public: /// The strength scalar for the detail normal map. F32 mDetailNormalMapStrength[MAX_STAGES]; - FileName mEnvMapFilename[MAX_STAGES]; - /// This color is the diffuse color of the material /// or if it has a texture it is multiplied against /// the diffuse texture color. @@ -287,12 +285,18 @@ public: /// If the stage should use anisotropic filtering. bool mUseAnisotropic[MAX_STAGES]; + // Deferred Shading: Metalness + bool mUseMetalness[MAX_STAGES]; + bool mDoubleSided; String mCubemapName; CubemapData* mCubemapData; bool mDynamicCubemap; + // Deferred Shading + bool mIsSky; + F32 mMatInfoFlags[MAX_STAGES]; bool mTranslucent; BlendOp mTranslucentBlendOp; bool mTranslucentZWrite; diff --git a/Engine/source/materials/materialFeatureTypes.cpp b/Engine/source/materials/materialFeatureTypes.cpp index f7a63815b..8ea7fbe8c 100644 --- a/Engine/source/materials/materialFeatureTypes.cpp +++ b/Engine/source/materials/materialFeatureTypes.cpp @@ -46,6 +46,7 @@ ImplementFeatureType( MFT_AlphaTest, MFG_Texture, 7.0f, true ); ImplementFeatureType( MFT_SpecularMap, MFG_Texture, 8.0f, true ); ImplementFeatureType( MFT_NormalMap, MFG_Texture, 9.0f, true ); ImplementFeatureType( MFT_DetailNormalMap, MFG_Texture, 10.0f, true ); +ImplementFeatureType( MFT_Imposter, U32(-1), -1, true ); ImplementFeatureType( MFT_AccuMap, MFG_PreLighting, 2.0f, true ); @@ -55,10 +56,9 @@ ImplementFeatureType( MFT_LightMap, MFG_Lighting, 4.0f, true ); ImplementFeatureType( MFT_ToneMap, MFG_Lighting, 5.0f, true ); ImplementFeatureType( MFT_VertLitTone, MFG_Lighting, 6.0f, false ); ImplementFeatureType( MFT_VertLit, MFG_Lighting, 7.0f, true ); -ImplementFeatureType( MFT_EnvMap, MFG_Lighting, 8.0f, true ); -ImplementFeatureType( MFT_CubeMap, MFG_Lighting, 9.0f, true ); -ImplementFeatureType( MFT_PixSpecular, MFG_Lighting, 10.0f, true ); -ImplementFeatureType( MFT_MinnaertShading, MFG_Lighting, 12.0f, true ); +ImplementFeatureType( MFT_PixSpecular, MFG_Lighting, 9.0f, true ); +ImplementFeatureType( MFT_MinnaertShading, MFG_Lighting, 10.0f, true ); +ImplementFeatureType( MFT_CubeMap, MFG_Lighting, 11.0f, true ); ImplementFeatureType( MFT_GlowMask, MFG_PostLighting, 1.0f, true ); ImplementFeatureType( MFT_Visibility, MFG_PostLighting, 2.0f, true ); @@ -84,6 +84,8 @@ ImplementFeatureType( MFT_NormalsOut, MFG_PreLighting, 1.0f, false ); ImplementFeatureType( MFT_LightbufferMRT, MFG_PreLighting, 1.0f, false ); ImplementFeatureType( MFT_RenderTarget1_Zero, MFG_PreTexture, 1.0f, false ); +ImplementFeatureType( MFT_RenderTarget2_Zero, MFG_PreTexture, 1.0f, false ); +ImplementFeatureType( MFT_RenderTarget3_Zero, MFG_PreTexture, 1.0f, false ); ImplementFeatureType( MFT_Foliage, MFG_PreTransform, 1.0f, false ); @@ -91,4 +93,13 @@ ImplementFeatureType( MFT_ParticleNormal, MFG_PreTransform, 2.0f, false ); ImplementFeatureType( MFT_ForwardShading, U32(-1), -1, true ); -ImplementFeatureType( MFT_ImposterVert, MFG_PreTransform, 1.0, false ); \ No newline at end of file +ImplementFeatureType( MFT_ImposterVert, MFG_PreTransform, 1.0, false ); + +// Deferred Shading +ImplementFeatureType( MFT_isDeferred, U32(-1), -1, true ); +ImplementFeatureType( MFT_SkyBox, MFG_Transform, 1.0f, true ); +ImplementFeatureType( MFT_DeferredEmptySpec, MFG_Texture, 8.01f, false ); + +ImplementFeatureType( MFT_DeferredSpecMap, MFG_Texture, 8.2f, false ); +ImplementFeatureType( MFT_DeferredSpecVars, MFG_Texture, 8.5f, false ); +ImplementFeatureType( MFT_DeferredMatInfoFlags, MFG_Texture, 8.7f, false ); diff --git a/Engine/source/materials/materialFeatureTypes.h b/Engine/source/materials/materialFeatureTypes.h index 55b52506c..a002cd190 100644 --- a/Engine/source/materials/materialFeatureTypes.h +++ b/Engine/source/materials/materialFeatureTypes.h @@ -94,6 +94,7 @@ DeclareFeatureType( MFT_OverlayMap ); DeclareFeatureType( MFT_DetailMap ); DeclareFeatureType( MFT_DiffuseColor ); DeclareFeatureType( MFT_DetailNormalMap ); +DeclareFeatureType( MFT_Imposter ); DeclareFeatureType( MFT_AccuMap ); DeclareFeatureType( MFT_AccuScale ); @@ -120,7 +121,6 @@ DeclareFeatureType( MFT_ToneMap ); DeclareFeatureType( MFT_VertLit ); DeclareFeatureType( MFT_VertLitTone ); -DeclareFeatureType( MFT_EnvMap ); DeclareFeatureType( MFT_CubeMap ); DeclareFeatureType( MFT_PixSpecular ); DeclareFeatureType( MFT_SpecularMap ); @@ -157,8 +157,10 @@ DeclareFeatureType( MFT_InterlacedPrePass ); /// to the second render-target DeclareFeatureType( MFT_LightbufferMRT ); -/// This feature outputs black to RenderTarget1 +/// This feature outputs black to RenderTarget3 DeclareFeatureType( MFT_RenderTarget1_Zero ); +DeclareFeatureType( MFT_RenderTarget2_Zero ); +DeclareFeatureType( MFT_RenderTarget3_Zero ); DeclareFeatureType( MFT_Foliage ); @@ -178,4 +180,11 @@ DeclareFeatureType( MFT_ForwardShading ); DeclareFeatureType( MFT_ImposterVert ); +// Deferred Shading +DeclareFeatureType( MFT_isDeferred ); +DeclareFeatureType( MFT_SkyBox ); +DeclareFeatureType( MFT_DeferredSpecMap ); +DeclareFeatureType( MFT_DeferredSpecVars ); +DeclareFeatureType( MFT_DeferredMatInfoFlags ); +DeclareFeatureType( MFT_DeferredEmptySpec ); #endif // _MATERIALFEATURETYPES_H_ diff --git a/Engine/source/materials/processedMaterial.cpp b/Engine/source/materials/processedMaterial.cpp index 10181179e..00a3b8ec2 100644 --- a/Engine/source/materials/processedMaterial.cpp +++ b/Engine/source/materials/processedMaterial.cpp @@ -455,14 +455,6 @@ void ProcessedMaterial::_setStageData() if(!mStages[i].getTex( MFT_SpecularMap )) mMaterial->logError("Failed to load specular map %s for stage %i", _getTexturePath(mMaterial->mSpecularMapFilename[i]).c_str(), i); } - - // EnironmentMap - if( mMaterial->mEnvMapFilename[i].isNotEmpty() ) - { - mStages[i].setTex( MFT_EnvMap, _createTexture( mMaterial->mEnvMapFilename[i], &GFXDefaultStaticDiffuseProfile ) ); - if(!mStages[i].getTex( MFT_EnvMap )) - mMaterial->logError("Failed to load environment map %s for stage %i", _getTexturePath(mMaterial->mEnvMapFilename[i]).c_str(), i); - } } mMaterial->mCubemapData = dynamic_cast(Sim::findObject( mMaterial->mCubemapName )); diff --git a/Engine/source/materials/processedShaderMaterial.cpp b/Engine/source/materials/processedShaderMaterial.cpp index 431e3bce6..37f745253 100644 --- a/Engine/source/materials/processedShaderMaterial.cpp +++ b/Engine/source/materials/processedShaderMaterial.cpp @@ -106,6 +106,9 @@ void ShaderConstHandles::init( GFXShader *shader, CustomMaterial* mat /*=NULL*/ for (S32 i = 0; i < Material::MAX_TEX_PER_PASS; ++i) mTexHandlesSC[i] = shader->getShaderConstHandle(mat->mSamplerNames[i]); } + + // Deferred Shading + mMatInfoFlagsSC = shader->getShaderConstHandle(ShaderGenVars::matInfoFlags); } /// @@ -208,28 +211,6 @@ bool ProcessedShaderMaterial::init( const FeatureSet &features, mInstancingState = new InstancingState(); mInstancingState->setFormat( &_getRPD( 0 )->shader->mInstancingFormat, mVertexFormat ); } - - // Check for a RenderTexTargetBin assignment - // *IMPORTANT NOTE* - // This is a temporary solution for getting diffuse mapping working with tex targets for standard materials - // It should be removed once this is done properly, at that time the sAllowTextureTargetAssignment should also be removed - // from Material (it is necessary for catching shadow maps/post effect this shouldn't be applied to) - if (Material::sAllowTextureTargetAssignment) - if (mMaterial && mMaterial->mDiffuseMapFilename[0].isNotEmpty() && mMaterial->mDiffuseMapFilename[0].substr( 0, 1 ).equal("#")) - { - String texTargetBufferName = mMaterial->mDiffuseMapFilename[0].substr(1, mMaterial->mDiffuseMapFilename[0].length() - 1); - NamedTexTarget *texTarget = NamedTexTarget::find( texTargetBufferName ); - - RenderPassData* rpd = getPass(0); - - if (rpd) - { - rpd->mTexSlot[0].texTarget = texTarget; - rpd->mTexType[0] = Material::TexTarget; - rpd->mSamplerNames[0] = "diffuseMap"; - } - } - return true; } @@ -353,11 +334,18 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum, fd.features.addFeature( MFT_VertLit ); // cubemaps only available on stage 0 for now - bramage - if ( stageNum < 1 && + if ( stageNum < 1 && mMaterial->isTranslucent() && ( ( mMaterial->mCubemapData && mMaterial->mCubemapData->mCubemap ) || mMaterial->mDynamicCubemap ) ) - fd.features.addFeature( MFT_CubeMap ); + { + fd.features.addFeature( MFT_CubeMap ); + } + if (mMaterial->mIsSky) + { + fd.features.addFeature(MFT_CubeMap); + fd.features.addFeature(MFT_SkyBox); + } fd.features.addFeature( MFT_Visibility ); if ( lastStage && @@ -428,7 +416,6 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum, if ( mMaterial->mAccuEnabled[stageNum] ) { - fd.features.addFeature( MFT_AccuMap ); mHasAccumulation = true; } @@ -441,19 +428,7 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum, fd.features.removeFeature( MFT_AccuMap ); mHasAccumulation = false; } - - // if we still have the AccuMap feature, we add all accu constant features - if ( fd.features[ MFT_AccuMap ] ) { - // add the dependencies of the accu map - fd.features.addFeature( MFT_AccuScale ); - fd.features.addFeature( MFT_AccuDirection ); - fd.features.addFeature( MFT_AccuStrength ); - fd.features.addFeature( MFT_AccuCoverage ); - fd.features.addFeature( MFT_AccuSpecular ); - // now remove some features that are not compatible with this - fd.features.removeFeature( MFT_UseInstancing ); - } - + // Without a base texture use the diffuse color // feature to ensure some sort of output. if (!fd.features[MFT_DiffuseMap]) @@ -1175,7 +1150,12 @@ void ProcessedShaderMaterial::_setShaderConstants(SceneRenderState * state, cons 0.0f, 0.0f ); // TODO: Wrap mode flags? shaderConsts->setSafe(handles->mBumpAtlasTileSC, atlasTileParams); } - + + // Deferred Shading: Determine Material Info Flags + S32 matInfoFlags = + (mMaterial->mEmissive[stageNum] ? 1 : 0); + mMaterial->mMatInfoFlags[stageNum] = matInfoFlags / 255.0f; + shaderConsts->setSafe(handles->mMatInfoFlagsSC, mMaterial->mMatInfoFlags[stageNum]); if( handles->mAccuScaleSC->isValid() ) shaderConsts->set( handles->mAccuScaleSC, mMaterial->mAccuScale[stageNum] ); if( handles->mAccuDirectionSC->isValid() ) diff --git a/Engine/source/materials/processedShaderMaterial.h b/Engine/source/materials/processedShaderMaterial.h index dc5dbf872..9bcc0eec7 100644 --- a/Engine/source/materials/processedShaderMaterial.h +++ b/Engine/source/materials/processedShaderMaterial.h @@ -87,6 +87,9 @@ public: GFXShaderConstHandle *mImposterUVs; GFXShaderConstHandle *mImposterLimits; + // Deferred Shading : Material Info Flags + GFXShaderConstHandle* mMatInfoFlagsSC; + GFXShaderConstHandle* mTexHandlesSC[Material::MAX_TEX_PER_PASS]; GFXShaderConstHandle* mRTParamsSC[TEXTURE_STAGE_COUNT]; diff --git a/Engine/source/math/mConsoleFunctions.cpp b/Engine/source/math/mConsoleFunctions.cpp index 1a11fe23e..1d57743e6 100644 --- a/Engine/source/math/mConsoleFunctions.cpp +++ b/Engine/source/math/mConsoleFunctions.cpp @@ -103,6 +103,19 @@ DefineConsoleFunction( mRound, S32, ( F32 v ),, return mRound(v); } +DefineConsoleFunction( mRoundColour, F32, ( F32 v, S32 n ), (0), + "Round v to the nth decimal place or the nearest whole number by default." + "@param v Value to roundn" + "@param n Number of decimal places to round to, 0 by defaultn" + "@return The rounded value as a S32." + "@ingroup Math") +{ + if (n <= 0) + return mRound(v); + else + return mRound(v, n); +} + DefineConsoleFunction( mCeil, S32, ( F32 v ),, "Round v up to the nearest integer.\n" "@param v Number to convert to integer." diff --git a/Engine/source/math/mPoint2.h b/Engine/source/math/mPoint2.h index d4c8180a1..c141400b9 100644 --- a/Engine/source/math/mPoint2.h +++ b/Engine/source/math/mPoint2.h @@ -438,6 +438,7 @@ inline Point2I Point2I::operator/(const Point2I &_vec) const inline Point2I& Point2I::operator/=(const Point2I &_vec) { + AssertFatal(_vec.x != 0 && _vec.y != 0, "Error, div by zero attempted"); x /= _vec.x; y /= _vec.y; return *this; @@ -645,6 +646,7 @@ inline Point2F Point2F::operator/(const Point2F &_vec) const inline Point2F& Point2F::operator/=(const Point2F &_vec) { + AssertFatal(_vec.x != 0 && _vec.y != 0, "Error, div by zero attempted"); x /= _vec.x; y /= _vec.y; return *this; diff --git a/Engine/source/math/mQuat.h b/Engine/source/math/mQuat.h index 2ea1b94c1..ca6ed5d82 100644 --- a/Engine/source/math/mQuat.h +++ b/Engine/source/math/mQuat.h @@ -227,8 +227,8 @@ inline F32 QuatF::dot( const QuatF &q ) const inline F32 QuatF::angleBetween( const QuatF & q ) { - // angle between to quaternions - return mAcos(x * q.x + y * q.y + z * q.z + w * q.w); + // angle between two normalized quaternions. + return mAcos(q.dot(*this)) * 2.0f; } #endif // _MQUAT_H_ diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index f205bf426..29c500b60 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -660,6 +660,66 @@ DefineConsoleFunction( VectorScale, VectorF, ( VectorF a, F32 scalar ),, { return a * scalar; } +DefineConsoleFunction( VectorMul, VectorF, ( VectorF a, VectorF b ),, + "Multiplies two vectors.\n" + "@param a The first vector.\n" + "@param b The second vector.\n" + "@return The vector @a a * @a b.\n\n" + "@tsexample\n" + "//-----------------------------------------------------------------------------\n" + "//\n" + "// VectorMul( %a, %b );\n" + "//\n" + "// The multiplication of vector a, (ax, ay, az), and vector b, (bx, by, bz) is:\n" + "//\n" + "// a * b = ( ax * bx, ay * by, az * bz )\n" + "//\n" + "//-----------------------------------------------------------------------------\n\n" + + "%a = \"1 0 0\";\n" + "%b = \"0 1 0\";\n\n" + + "// %r = \"( 1 * 0, 0 * 1, 0 * 0 )\";\n" + "// %r = \"0 0 0\";\n" + "%r = VectorMul( %a, %b );\n" + "@endtsexample\n\n" + "@ingroup Vectors" ) +{ + return a * b; +} + +DefineConsoleFunction( VectorDiv, VectorF, ( VectorF a, VectorF b ),, + "Divide two vectors.\n" + "@param a The first vector.\n" + "@param b The second vector.\n" + "@return The vector @a a / @a b.\n\n" + "@tsexample\n" + "//-----------------------------------------------------------------------------\n" + "//\n" + "// VectorDiv( %a, %b );\n" + "//\n" + "// The division of vector a, (ax, ay, az), and vector b, (bx, by, bz) is:\n" + "//\n" + "// a * b = ( ax / bx, ay / by, az / bz )\n" + "//\n" + "//-----------------------------------------------------------------------------\n\n" + + "%a = \"1 1 1\";\n" + "%b = \"2 2 2\";\n\n" + + "// %r = \"( 1 / 2, 1 / 2, 1 / 2 )\";\n" + "// %r = \"0.5 0.5 0.5\";\n" + "%r = VectorDiv( %a, %b );\n" + "@endtsexample\n\n" + "@ingroup Vectors" ) +{ + //this is kind of bad, but so is dividing by 0 + if(b.x == 0) b.x = 0.000001f; + if(b.y == 0) b.y = 0.000001f; + if(b.z == 0) b.z = 0.000001f; + + return a / b; +} //----------------------------------------------------------------------------- @@ -790,6 +850,34 @@ DefineConsoleFunction( VectorDist, F32, ( VectorF a, VectorF b ),, //----------------------------------------------------------------------------- +DefineConsoleFunction( VectorMidPoint, VectorF, ( VectorF a, VectorF b ),, + "Gets the midpoint between the two vectors.\n" + "@param a The first vector.\n" + "@param b The second vector.\n" + "@return The vector (@a a + @a b) / 2.\n\n" + "@tsexample\n" + "//-----------------------------------------------------------------------------\n" + "//\n" + "// VectorMidPoint( %a, %b );\n" + "//\n" + "// The midpoint of vector a, (ax, ay, az), and vector b, (bx, by, bz) is:\n" + "//\n" + "// (a + b)/2 = ( (ax + bx) /2, ay + by) /2, (az + bz) /2 )\n" + "//\n" + "//-----------------------------------------------------------------------------\n" +// "%a = \"1 0 0\";\n" +// "%b = \"0 1 0\";\n\n" +// "// %r = \"( 1 + 0, 0 + 1, 0 + 0 )\";\n" +// "// %r = \"1 1 0\";\n" +// "%r = VectorAdd( %a, %b );\n" + "@endtsexample\n\n" + "@ingroup Vectors") +{ + return (a + b)/2.0f; +} + +//----------------------------------------------------------------------------- + DefineConsoleFunction( VectorLen, F32, ( VectorF v ),, "Calculate the magnitude of the given vector.\n" "@param v A vector.\n" diff --git a/Engine/source/math/mathUtils.cpp b/Engine/source/math/mathUtils.cpp index f6086c5e4..5ffd9a870 100644 --- a/Engine/source/math/mathUtils.cpp +++ b/Engine/source/math/mathUtils.cpp @@ -1847,7 +1847,7 @@ U32 extrudePolygonEdgesFromPoint( const Point3F* vertices, U32 numVertices, cons //----------------------------------------------------------------------------- -void MathUtils::mBuildHull2D(const Vector _inPoints, Vector &hullPoints) +void mBuildHull2D(const Vector _inPoints, Vector &hullPoints) { /// Andrew's monotone chain convex hull algorithm implementation diff --git a/Engine/source/navigation/navMesh.cpp b/Engine/source/navigation/navMesh.cpp index 7df05ee2e..f029c5deb 100644 --- a/Engine/source/navigation/navMesh.cpp +++ b/Engine/source/navigation/navMesh.cpp @@ -112,13 +112,39 @@ DefineConsoleFunction(NavMeshUpdateAll, void, (S32 objid, bool remove), (0, fals SimSet *set = NavMesh::getServerSet(); for(U32 i = 0; i < set->size(); i++) { - NavMesh *m = static_cast(set->at(i)); - m->buildTiles(obj->getWorldBox()); + NavMesh *m = dynamic_cast(set->at(i)); + if (m) + { + m->cancelBuild(); + m->buildTiles(obj->getWorldBox()); + } } if(remove) obj->enableCollision(); } +DefineConsoleFunction(NavMeshUpdateAroundObject, void, (S32 objid, bool remove), (0, false), + "@brief Update all NavMesh tiles that intersect the given object's world box.") +{ + SceneObject *obj; + if (!Sim::findObject(objid, obj)) + return; + if (remove) + obj->disableCollision(); + SimSet *set = NavMesh::getServerSet(); + for (U32 i = 0; i < set->size(); i++) + { + NavMesh *m = dynamic_cast(set->at(i)); + if (m) + { + m->cancelBuild(); + m->buildTiles(obj->getWorldBox()); + } + } + if (remove) + obj->enableCollision(); +} + DefineConsoleFunction(NavMeshUpdateOne, void, (S32 meshid, S32 objid, bool remove), (0, 0, false), "@brief Update all tiles in a given NavMesh that intersect the given object's world box.") { @@ -147,7 +173,7 @@ NavMesh::NavMesh() mFileName = StringTable->insert(""); mNetFlags.clear(Ghostable); - mSaveIntermediates = true; + mSaveIntermediates = false; nm = NULL; ctx = NULL; @@ -637,7 +663,7 @@ DefineEngineMethod(NavMesh, build, bool, (bool background, bool save), (true, fa void NavMesh::cancelBuild() { - while(!mDirtyTiles.empty()) mDirtyTiles.pop(); + mDirtyTiles.clear(); ctx->stopTimer(RC_TIMER_TOTAL); mBuilding = false; } @@ -707,7 +733,7 @@ void NavMesh::updateTiles(bool dirty) mTiles.clear(); mTileData.clear(); - while(!mDirtyTiles.empty()) mDirtyTiles.pop(); + mDirtyTiles.clear(); const Box3F &box = DTStoRC(getWorldBox()); if(box.isEmpty()) @@ -741,7 +767,7 @@ void NavMesh::updateTiles(bool dirty) tileBmin, tileBmax)); if(dirty) - mDirtyTiles.push(mTiles.size() - 1); + mDirtyTiles.push_back_unique(mTiles.size() - 1); if(mSaveIntermediates) mTileData.increment(); @@ -760,18 +786,20 @@ void NavMesh::buildNextTile() { // Pop a single dirty tile and process it. U32 i = mDirtyTiles.front(); - mDirtyTiles.pop(); + mDirtyTiles.pop_front(); const Tile &tile = mTiles[i]; // Intermediate data for tile build. TileData tempdata; TileData &tdata = mSaveIntermediates ? mTileData[i] : tempdata; + + // Remove any previous data. + nm->removeTile(nm->getTileRefAt(tile.x, tile.y, 0), 0, 0); + // Generate navmesh for this tile. U32 dataSize = 0; unsigned char* data = buildTileData(tile, tdata, dataSize); if(data) { - // Remove any previous data. - nm->removeTile(nm->getTileRefAt(tile.x, tile.y, 0), 0, 0); // Add new data (navmesh owns and deletes the data). dtStatus status = nm->addTile(data, dataSize, DT_TILE_FREE_DATA, 0, 0); int success = 1; @@ -830,6 +858,7 @@ unsigned char *NavMesh::buildTileData(const Tile &tile, TileData &data, U32 &dat SceneContainer::CallbackInfo info; info.context = PLC_Navigation; info.boundingBox = box; + data.geom.clear(); info.polyList = &data.geom; info.key = this; getContainer()->findObjects(box, StaticShapeObjectType | TerrainObjectType, buildCallback, &info); @@ -843,8 +872,11 @@ unsigned char *NavMesh::buildTileData(const Tile &tile, TileData &data, U32 &dat } // Check for no geometry. - if(!data.geom.getVertCount()) - return false; + if (!data.geom.getVertCount()) + { + data.geom.clear(); + return NULL; + } // Figure out voxel dimensions of this tile. U32 width = 0, height = 0; @@ -1066,7 +1098,7 @@ void NavMesh::buildTiles(const Box3F &box) if(!tile.box.isOverlapped(box)) continue; // Mark as dirty. - mDirtyTiles.push(i); + mDirtyTiles.push_back_unique(i); } if(mDirtyTiles.size()) ctx->startTimer(RC_TIMER_TOTAL); @@ -1082,7 +1114,7 @@ void NavMesh::buildTile(const U32 &tile) { if(tile < mTiles.size()) { - mDirtyTiles.push(tile); + mDirtyTiles.push_back_unique(tile); ctx->startTimer(RC_TIMER_TOTAL); } } @@ -1104,7 +1136,7 @@ void NavMesh::buildLinks() mLinksUnsynced[j]) { // Mark tile for build. - mDirtyTiles.push(i); + mDirtyTiles.push_back_unique(i); // Delete link if necessary if(mDeleteLinks[j]) { diff --git a/Engine/source/navigation/navMesh.h b/Engine/source/navigation/navMesh.h index 1d9eba1b1..ff279c3be 100644 --- a/Engine/source/navigation/navMesh.h +++ b/Engine/source/navigation/navMesh.h @@ -325,7 +325,7 @@ private: Vector mTileData; /// List of indices to the tile array which are dirty. - std::queue mDirtyTiles; + Vector mDirtyTiles; /// Update tile dimensions. void updateTiles(bool dirty = false); diff --git a/Engine/source/persistence/taml/fsTinyXml.cpp b/Engine/source/persistence/taml/fsTinyXml.cpp index 1fb97398b..441169742 100644 --- a/Engine/source/persistence/taml/fsTinyXml.cpp +++ b/Engine/source/persistence/taml/fsTinyXml.cpp @@ -38,7 +38,7 @@ bool fsTiXmlDocument::LoadFile( const char * pFilename, TiXmlEncoding encoding ) #endif // File open for read? - if ( !stream.open( filenameBuffer, Torque::FS::File::AccessMode::Read ) ) + if ( !stream.open( filenameBuffer, Torque::FS::File::Read ) ) { // No, so warn. Con::warnf("TamlXmlParser::parse() - Could not open filename '%s' for parse.", filenameBuffer ); @@ -67,7 +67,7 @@ bool fsTiXmlDocument::SaveFile( const char * pFilename ) const FileStream stream; // File opened? - if ( !stream.open( filenameBuffer, Torque::FS::File::AccessMode::Write ) ) + if ( !stream.open( filenameBuffer, Torque::FS::File::Write ) ) { // No, so warn. Con::warnf("Taml::writeFile() - Could not open filename '%s' for write.", filenameBuffer ); @@ -744,4 +744,4 @@ return 0; // All is well. return p; } -*/ \ No newline at end of file +*/ diff --git a/Engine/source/persistence/taml/fsTinyXml.h b/Engine/source/persistence/taml/fsTinyXml.h index f2fb14129..864abec09 100644 --- a/Engine/source/persistence/taml/fsTinyXml.h +++ b/Engine/source/persistence/taml/fsTinyXml.h @@ -25,7 +25,7 @@ #ifndef TINYXML_INCLUDED -#include "tinyXML/tinyxml.h" +#include "tinyxml/tinyxml.h" #endif #include "platform/platform.h" @@ -245,4 +245,4 @@ static bool AttemptPrintTiNode(class fsTiXmlDocument* node, FileStream& stream, } return false; } -#endif //_FSTINYXML_H_ \ No newline at end of file +#endif //_FSTINYXML_H_ diff --git a/Engine/source/persistence/taml/xml/tamlXmlParser.h b/Engine/source/persistence/taml/xml/tamlXmlParser.h index 85b34079d..28b51a472 100644 --- a/Engine/source/persistence/taml/xml/tamlXmlParser.h +++ b/Engine/source/persistence/taml/xml/tamlXmlParser.h @@ -28,7 +28,7 @@ #endif #ifndef TINYXML_INCLUDED -#include "tinyXML/tinyxml.h" +#include "tinyxml/tinyxml.h" #endif //----------------------------------------------------------------------------- @@ -54,4 +54,4 @@ private: bool mDocumentDirty; }; -#endif // _TAML_XMLPARSER_H_ \ No newline at end of file +#endif // _TAML_XMLPARSER_H_ diff --git a/Engine/source/persistence/taml/xml/tamlXmlReader.cpp b/Engine/source/persistence/taml/xml/tamlXmlReader.cpp index 04b43a5d2..aa8be618f 100644 --- a/Engine/source/persistence/taml/xml/tamlXmlReader.cpp +++ b/Engine/source/persistence/taml/xml/tamlXmlReader.cpp @@ -24,7 +24,7 @@ // Debug Profiling. #include "platform/profiler.h" -#include "persistence/taml/fsTinyxml.h" +#include "persistence/taml/fsTinyXml.h" //----------------------------------------------------------------------------- diff --git a/Engine/source/persistence/taml/xml/tamlXmlWriter.cpp b/Engine/source/persistence/taml/xml/tamlXmlWriter.cpp index 4ffad7223..e8481cb87 100644 --- a/Engine/source/persistence/taml/xml/tamlXmlWriter.cpp +++ b/Engine/source/persistence/taml/xml/tamlXmlWriter.cpp @@ -24,7 +24,7 @@ // Debug Profiling. #include "platform/profiler.h" -#include "persistence/taml/fsTinyxml.h" +#include "persistence/taml/fsTinyXml.h" //----------------------------------------------------------------------------- diff --git a/Engine/source/platform/platformAssert.cpp b/Engine/source/platform/platformAssert.cpp index 0a92bf1a1..5fe428fad 100644 --- a/Engine/source/platform/platformAssert.cpp +++ b/Engine/source/platform/platformAssert.cpp @@ -69,24 +69,6 @@ bool PlatformAssert::displayMessageBox(const char *title, const char *message, b } static const char *typeName[] = { "Unknown", "Fatal-ISV", "Fatal", "Warning" }; -//------------------------------------------------------------------------------ -static bool askToEnterDebugger(const char* message ) -{ - static bool haveAsked = false; - static bool useDebugger = true; - if(!haveAsked ) - { - static char tempBuff[1024]; - dSprintf( tempBuff, 1024, "Torque has encountered an assertion with message\n\n" - "%s\n\n" - "Would you like to use the debugger? If you cancel, you won't be asked" - " again until you restart Torque.", message); - - useDebugger = Platform::AlertOKCancel("Use debugger?", tempBuff ); - haveAsked = true; - } - return useDebugger; -} //-------------------------------------- diff --git a/Engine/source/platform/platformAssert.h b/Engine/source/platform/platformAssert.h index c26f255c0..86ccb1b23 100644 --- a/Engine/source/platform/platformAssert.h +++ b/Engine/source/platform/platformAssert.h @@ -64,19 +64,17 @@ public: #ifdef TORQUE_ENABLE_ASSERTS - /*! - Assert that the statement x is true, and continue processing. +/*! + Assert that the statement x is true, and continue processing. - If the statment x is true, continue processing. + If the statment x is true, continue processing. - If the statement x is false, log the file and line where the assert occured, - the message y and continue processing. + If the statement x is false, log the file and line where the assert occured, + the message y and continue processing. - These asserts are only present in DEBUG builds. - */ - #define AssertWarn(x, y) \ - { if ((x)==0) \ - ::PlatformAssert::processAssert(::PlatformAssert::Warning, __FILE__, __LINE__, y); } + These asserts are only present in DEBUG builds. + */ +#define AssertWarn(x, y) (void)(!!(x) || ::PlatformAssert::processAssert(::PlatformAssert::Warning, __FILE__, __LINE__, y)) /*! Helper macro called when AssertFatal failed. @@ -86,27 +84,27 @@ public: #define ON_FAIL_ASSERTFATAL #endif - /*! - Assert that the statement x is true, otherwise halt. +/*! + Assert that the statement x is true, otherwise halt. - If the statement x is true, continue processing. + If the statement x is true, continue processing. - If the statement x is false, log the file and line where the assert occured, - the message y and displaying a dialog containing the message y. The user then - has the option to halt or continue causing the debugger to break. + If the statement x is false, log the file and line where the assert occured, + the message y and displaying a dialog containing the message y. The user then + has the option to halt or continue causing the debugger to break. - These asserts are only present in DEBUG builds. + These asserts are only present in DEBUG builds. - This assert is very useful for verifying data as well as function entry and - exit conditions. - */ - #define AssertFatal(x, y) \ - { if (((bool)(x))==false) \ - { if ( ::PlatformAssert::processAssert(::PlatformAssert::Fatal, __FILE__, __LINE__, y) ) { ::Platform::debugBreak(); } } } + This assert is very useful for verifying data as well as function entry and + exit conditions. + */ +#define AssertFatal(x, y) ((!(x) && ::PlatformAssert::processAssert(::PlatformAssert::Fatal, __FILE__, __LINE__, y)) ? ::Platform::debugBreak() : (void)0) \ #else - #define AssertFatal(x, y) { TORQUE_UNUSED(x); TORQUE_UNUSED(y); } - #define AssertWarn(x, y) { TORQUE_UNUSED(x); TORQUE_UNUSED(y); } + +#define AssertFatal(x, y) TORQUE_UNUSED(x) +#define AssertWarn(x, y) TORQUE_UNUSED(x) + #endif /*! @@ -121,10 +119,7 @@ public: This assert should only be used for rare conditions where the application cannot continue execution without seg-faulting and you want to display a nice exit message. */ -#define AssertISV(x, y) \ - { if ((x)==0) \ -{ if ( ::PlatformAssert::processAssert(::PlatformAssert::Fatal_ISV, __FILE__, __LINE__, y) ) { ::Platform::debugBreak(); } } } - +#define AssertISV(x, y) ((!(x) && ::PlatformAssert::processAssert(::PlatformAssert::Fatal_ISV, __FILE__, __LINE__, y)) ? ::Platform::debugBreak() : (void)0) \ /*! Sprintf style string formating into a fixed temporary buffer. diff --git a/Engine/source/platform/platformNet.cpp b/Engine/source/platform/platformNet.cpp index f4f5c85b1..6ccef9db1 100644 --- a/Engine/source/platform/platformNet.cpp +++ b/Engine/source/platform/platformNet.cpp @@ -503,7 +503,7 @@ bool Net::openPort(S32 port, bool doBind) } if(error == NoError) - error = setBufferSize(udpSocket, 32768); + error = setBufferSize(udpSocket, 32768*8); if(error == NoError && !useVDP) error = setBroadcast(udpSocket, true); diff --git a/Engine/source/platform/profiler.cpp b/Engine/source/platform/profiler.cpp index ca34b4593..c978b9ac2 100644 --- a/Engine/source/platform/profiler.cpp +++ b/Engine/source/platform/profiler.cpp @@ -215,13 +215,21 @@ void Profiler::reset() { mEnabled = false; // in case we're in a profiler call. ProfilerData * head = mProfileList; - ProfilerData * curr = NULL; - while ((curr = head) != NULL) + ProfilerData * curr = head; + + while ( curr ) { - head = head->mNextProfilerData; - free(curr); + head = curr->mNextProfilerData; + free( curr ); + + if ( head ) + curr = head; + else + curr = NULL; } + mProfileList = NULL; + for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) { walk->mFirstProfilerData = 0; diff --git a/Engine/source/platform/types.visualc.h b/Engine/source/platform/types.visualc.h index 455f007b2..61c2d3af2 100644 --- a/Engine/source/platform/types.visualc.h +++ b/Engine/source/platform/types.visualc.h @@ -32,6 +32,16 @@ typedef signed _int64 S64; typedef unsigned _int64 U64; +// The types.h version of TORQUE_UNUSED no longer works for recent versions of MSVC. +// Since it appears that MS has made this impossible to do in a zero-overhead way, +// just turn the warning off in release builds. +#undef TORQUE_UNUSED +#ifdef TORQUE_DEBUG +#define TORQUE_UNUSED(var) ((0,0) ? (void)(var) : (void)0) +#else +#pragma warning(disable: 4189) // local variable is initialized but not referenced +#define TORQUE_UNUSED(var) ((void)0) +#endif //-------------------------------------- // Compiler Version diff --git a/Engine/source/platformMac/macCarbFileio.mm b/Engine/source/platformMac/macCarbFileio.mm index 7a913986e..a1961d710 100644 --- a/Engine/source/platformMac/macCarbFileio.mm +++ b/Engine/source/platformMac/macCarbFileio.mm @@ -724,6 +724,11 @@ bool Platform::hasSubDirectory(const char *path) return false; // either this dir had no subdirectories, or they were all on the exclude list. } + bool Platform::fileDelete(const char * name) + { + return dFileDelete(name); + } + //----------------------------------------------------------------------------- bool recurseDumpDirectories(const char *basePath, const char *path, Vector &directoryVector, S32 depth, bool noBasePath) { diff --git a/Engine/source/platformSDL/sdlPlatformGL.cpp b/Engine/source/platformSDL/sdlPlatformGL.cpp index 6562f2c80..b71846d8b 100644 --- a/Engine/source/platformSDL/sdlPlatformGL.cpp +++ b/Engine/source/platformSDL/sdlPlatformGL.cpp @@ -13,18 +13,16 @@ namespace PlatformGL return; inited = true; - const U32 majorOGL = 4; + const U32 majorOGL = 3; const U32 minorOGL = 2; U32 debugFlag = 0; #ifdef TORQUE_DEBUG debugFlag |= SDL_GL_CONTEXT_DEBUG_FLAG; #endif -#if 0 // cause problem with glew, no extension load SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, majorOGL); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minorOGL); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); -#endif SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, debugFlag); SDL_ClearError(); diff --git a/Engine/source/platformWin32/winFileio.cpp b/Engine/source/platformWin32/winFileio.cpp index d5fdde104..85f8676a3 100644 --- a/Engine/source/platformWin32/winFileio.cpp +++ b/Engine/source/platformWin32/winFileio.cpp @@ -1321,6 +1321,7 @@ static bool recurseDumpDirectories(const char *basePath, const char *subPath, Ve dsize_t subtrLen = subPath ? dStrlen(subPath) : 0; char trail = trLen > 0 ? basePath[ trLen - 1 ] : '\0'; char subTrail = subtrLen > 0 ? subPath[ subtrLen - 1 ] : '\0'; + char subLead = subtrLen > 0 ? subPath[0] : '\0'; if( trail == '/' ) { @@ -1380,13 +1381,23 @@ static bool recurseDumpDirectories(const char *basePath, const char *subPath, Ve { if( ( subPath && ( dStrncmp( subPath, "", 1 ) != 0 ) ) ) { - char szPath [ 1024 ]; - dMemset( szPath, 0, 1024 ); - if( trail != '/' ) - dSprintf( szPath, 1024, "%s%s", basePath, subPath ); + char szPath[1024]; + dMemset(szPath, 0, 1024); + if (trail == '/') + { + if (subLead == '/') + dSprintf(szPath, 1024, "%s%s", basePath, &subPath[1]); + else + dSprintf(szPath, 1024, "%s%s", basePath, subPath); + } else - dSprintf( szPath, 1024, "%s%s", basePath, &subPath[1] ); - directoryVector.push_back( StringTable->insert( szPath ) ); + { + if (subLead == '/') + dSprintf(szPath, 1024, "%s%s", basePath, subPath); + else + dSprintf(szPath, 1024, "%s/%s", basePath, subPath); + } + directoryVector.push_back(StringTable->insert(szPath)); } else directoryVector.push_back( StringTable->insert( basePath ) ); diff --git a/Engine/source/platformX86UNIX/x86UNIXFileio.cpp b/Engine/source/platformX86UNIX/x86UNIXFileio.cpp index 22c40a187..6c2dd6955 100644 --- a/Engine/source/platformX86UNIX/x86UNIXFileio.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXFileio.cpp @@ -325,7 +325,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) if (modType == TOUCH) return(utime(prefPathName, 0) != -1); else if (modType == DELETE) - return (remove(prefPathName) != -1); + return (remove(prefPathName) == 0); else AssertFatal(false, "Unknown File Mod type"); return false; @@ -1140,6 +1140,11 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) return false; } + bool Platform::fileDelete(const char * name) + { + return ModifyFile(name, DELETE); + } + static bool recurseDumpDirectories(const char *basePath, const char *subPath, Vector &directoryVector, S32 currentDepth, S32 recurseDepth, bool noBasePath) { char Path[1024]; diff --git a/Engine/source/renderInstance/renderBinManager.cpp b/Engine/source/renderInstance/renderBinManager.cpp index 8ebe69334..c3b3f135d 100644 --- a/Engine/source/renderInstance/renderBinManager.cpp +++ b/Engine/source/renderInstance/renderBinManager.cpp @@ -36,7 +36,8 @@ RenderBinManager::RenderBinManager( const RenderInstType& ritype, F32 renderOrde mRenderInstType( ritype ), mRenderOrder( renderOrder ), mProcessAddOrder( processAddOrder ), - mRenderPass( NULL ) + mRenderPass( NULL ), + mBasicOnly ( false ) { VECTOR_SET_ASSOCIATION( mElementList ); mElementList.reserve( 2048 ); @@ -60,6 +61,9 @@ void RenderBinManager::initPersistFields() addField("processAddOrder", TypeF32, Offset(mProcessAddOrder, RenderBinManager), "Defines the order for adding instances in relation to other bins." ); + addField( "basicOnly", TypeBool, Offset(mBasicOnly, RenderBinManager), + "Limites the render bin to basic lighting only." ); + Parent::initPersistFields(); } diff --git a/Engine/source/renderInstance/renderBinManager.h b/Engine/source/renderInstance/renderBinManager.h index cc5bbe6c3..2a1a4cbb5 100644 --- a/Engine/source/renderInstance/renderBinManager.h +++ b/Engine/source/renderInstance/renderBinManager.h @@ -128,6 +128,8 @@ protected: /// RenderInst if available, otherwise, return NULL. inline BaseMatInstance* getMaterial( RenderInst *inst ) const; + // Limits bin to rendering in basic lighting only. + bool mBasicOnly; }; @@ -160,6 +162,7 @@ inline BaseMatInstance* RenderBinManager::getMaterial( RenderInst *inst ) const { if ( inst->type == RenderPassManager::RIT_Mesh || inst->type == RenderPassManager::RIT_Decal || + inst->type == RenderPassManager::RIT_DecalRoad || inst->type == RenderPassManager::RIT_Translucent ) return static_cast(inst)->matInst; diff --git a/Engine/source/renderInstance/renderGlowMgr.cpp b/Engine/source/renderInstance/renderGlowMgr.cpp index ed48c095f..14e6ce016 100644 --- a/Engine/source/renderInstance/renderGlowMgr.cpp +++ b/Engine/source/renderInstance/renderGlowMgr.cpp @@ -79,6 +79,7 @@ void RenderGlowMgr::GlowMaterialHook::_overrideFeatures( ProcessedMaterial *mat, // the glow materials. fd.features.removeFeature( MFT_Fog ); fd.features.removeFeature( MFT_HDROut ); + fd.features.addFeature( MFT_Imposter ); } RenderGlowMgr::RenderGlowMgr() @@ -89,6 +90,7 @@ RenderGlowMgr::RenderGlowMgr() Point2I( 512, 512 ) ) { notifyType( RenderPassManager::RIT_Decal ); + notifyType( RenderPassManager::RIT_DecalRoad ); notifyType( RenderPassManager::RIT_Translucent ); notifyType( RenderPassManager::RIT_Particle ); diff --git a/Engine/source/renderInstance/renderMeshMgr.cpp b/Engine/source/renderInstance/renderMeshMgr.cpp index 67114329d..b224e5469 100644 --- a/Engine/source/renderInstance/renderMeshMgr.cpp +++ b/Engine/source/renderInstance/renderMeshMgr.cpp @@ -144,6 +144,14 @@ void RenderMeshMgr::render(SceneRenderState * state) if( !mat ) mat = MATMGR->getWarningMatInstance(); + // Check if bin is disabled in advanced lighting. + // Allow forward rendering pass on custom materials. + + if ( ( MATMGR->getPrePassEnabled() && mBasicOnly && !mat->isCustomMaterial() ) ) + { + j++; + continue; + } U32 matListEnd = j; lastMiscTex = sgData.miscTex; diff --git a/Engine/source/renderInstance/renderObjectMgr.cpp b/Engine/source/renderInstance/renderObjectMgr.cpp index 6f79f9128..6cfab0aba 100644 --- a/Engine/source/renderInstance/renderObjectMgr.cpp +++ b/Engine/source/renderInstance/renderObjectMgr.cpp @@ -22,6 +22,8 @@ #include "renderObjectMgr.h" #include "console/consoleTypes.h" #include "scene/sceneObject.h" +#include "materials/materialManager.h" +#include "scene/sceneRenderState.h" IMPLEMENT_CONOBJECT(RenderObjectMgr); @@ -66,6 +68,10 @@ void RenderObjectMgr::render( SceneRenderState *state ) if(!mElementList.size()) return; + // Check if bin is disabled in advanced lighting. + if ( MATMGR->getPrePassEnabled() && mBasicOnly ) + return; + for( U32 i=0; i(mElementList[i].inst); diff --git a/Engine/source/renderInstance/renderParticleMgr.cpp b/Engine/source/renderInstance/renderParticleMgr.cpp index 2b475ab7f..dcae9756c 100644 --- a/Engine/source/renderInstance/renderParticleMgr.cpp +++ b/Engine/source/renderInstance/renderParticleMgr.cpp @@ -338,14 +338,10 @@ void RenderParticleMgr::render( SceneRenderState *state ) void RenderParticleMgr::_initGFXResources() { // Screen quad - U16 *prims = NULL; - mScreenQuadPrimBuff.set(GFX, 4, 2, GFXBufferTypeStatic); - mScreenQuadPrimBuff.lock(&prims); - (*prims++) = 0; - (*prims++) = 1; - (*prims++) = 2; - (*prims++) = 3; - mScreenQuadPrimBuff.unlock(); + U16 prims [] = { + 0, 1, 2, 3, + }; + mScreenQuadPrimBuff.immutable(GFX, 4, 2, prims); mScreenQuadVertBuff.set(GFX, 4, GFXBufferTypeStatic); CompositeQuadVert *verts = mScreenQuadVertBuff.lock(); diff --git a/Engine/source/renderInstance/renderPassManager.cpp b/Engine/source/renderInstance/renderPassManager.cpp index 236cccd9b..f620a627b 100644 --- a/Engine/source/renderInstance/renderPassManager.cpp +++ b/Engine/source/renderInstance/renderPassManager.cpp @@ -51,8 +51,10 @@ const RenderInstType RenderPassManager::RIT_Terrain("Terrain"); const RenderInstType RenderPassManager::RIT_Object("Object"); const RenderInstType RenderPassManager::RIT_ObjectTranslucent("ObjectTranslucent"); const RenderInstType RenderPassManager::RIT_Decal("Decal"); +const RenderInstType RenderPassManager::RIT_DecalRoad("DecalRoad"); const RenderInstType RenderPassManager::RIT_Water("Water"); const RenderInstType RenderPassManager::RIT_Foliage("Foliage"); +const RenderInstType RenderPassManager::RIT_VolumetricFog("ObjectVolumetricFog"); const RenderInstType RenderPassManager::RIT_Translucent("Translucent"); const RenderInstType RenderPassManager::RIT_Begin("Begin"); const RenderInstType RenderPassManager::RIT_Custom("Custom"); diff --git a/Engine/source/renderInstance/renderPassManager.h b/Engine/source/renderInstance/renderPassManager.h index b7f72b06c..2aa1e37ee 100644 --- a/Engine/source/renderInstance/renderPassManager.h +++ b/Engine/source/renderInstance/renderPassManager.h @@ -108,8 +108,10 @@ public: static const RenderInstType RIT_Object; // objects that do their own rendering static const RenderInstType RIT_ObjectTranslucent;// self rendering; but sorted with static const RenderInstType RIT_Translucent static const RenderInstType RIT_Decal; + static const RenderInstType RIT_DecalRoad; static const RenderInstType RIT_Water; static const RenderInstType RIT_Foliage; + static const RenderInstType RIT_VolumetricFog; static const RenderInstType RIT_Translucent; static const RenderInstType RIT_Begin; static const RenderInstType RIT_Custom; diff --git a/Engine/source/renderInstance/renderPrePassMgr.cpp b/Engine/source/renderInstance/renderPrePassMgr.cpp index 326f346a0..4f08dc6ea 100644 --- a/Engine/source/renderInstance/renderPrePassMgr.cpp +++ b/Engine/source/renderInstance/renderPrePassMgr.cpp @@ -36,6 +36,7 @@ #include "scene/sceneRenderState.h" #include "gfx/gfxStringEnumTranslate.h" #include "gfx/gfxDebugEvent.h" +#include "gfx/gfxCardProfile.h" #include "materials/customMaterialDefinition.h" #include "lighting/advanced/advancedLightManager.h" #include "lighting/advanced/advancedLightBinManager.h" @@ -44,10 +45,17 @@ #include "terrain/terrCellMaterial.h" #include "math/mathUtils.h" #include "math/util/matrixSet.h" +#include "gfx/gfxTextureManager.h" +#include "gfx/primBuilder.h" +#include "gfx/gfxDrawUtil.h" +#include "materials/shaderData.h" +#include "gfx/sim/cubemapData.h" const MatInstanceHookType PrePassMatInstanceHook::Type( "PrePass" ); const String RenderPrePassMgr::BufferName("prepass"); const RenderInstType RenderPrePassMgr::RIT_PrePass("PrePass"); +const String RenderPrePassMgr::ColorBufferName("color"); +const String RenderPrePassMgr::MatInfoBufferName("matinfo"); IMPLEMENT_CONOBJECT(RenderPrePassMgr); @@ -79,6 +87,7 @@ RenderPrePassMgr::RenderPrePassMgr( bool gatherDepth, mPrePassMatInstance( NULL ) { notifyType( RenderPassManager::RIT_Decal ); + notifyType( RenderPassManager::RIT_DecalRoad ); notifyType( RenderPassManager::RIT_Mesh ); notifyType( RenderPassManager::RIT_Terrain ); notifyType( RenderPassManager::RIT_Object ); @@ -90,6 +99,10 @@ RenderPrePassMgr::RenderPrePassMgr( bool gatherDepth, GFXShader::addGlobalMacro( "TORQUE_LINEAR_DEPTH" ); mNamedTarget.registerWithName( BufferName ); + mColorTarget.registerWithName( ColorBufferName ); + mMatInfoTarget.registerWithName( MatInfoBufferName ); + + mClearGBufferShader = NULL; _registerFeatures(); } @@ -98,6 +111,8 @@ RenderPrePassMgr::~RenderPrePassMgr() { GFXShader::removeGlobalMacro( "TORQUE_LINEAR_DEPTH" ); + mColorTarget.release(); + mMatInfoTarget.release(); _unregisterFeatures(); SAFE_DELETE( mPrePassMatInstance ); } @@ -119,6 +134,8 @@ bool RenderPrePassMgr::setTargetSize(const Point2I &newTargetSize) { bool ret = Parent::setTargetSize( newTargetSize ); mNamedTarget.setViewport( GFX->getViewport() ); + mColorTarget.setViewport( GFX->getViewport() ); + mMatInfoTarget.setViewport( GFX->getViewport() ); return ret; } @@ -135,6 +152,40 @@ bool RenderPrePassMgr::_updateTargets() // reload materials, the conditioner needs to alter the generated shaders } + GFXFormat colorFormat = mTargetFormat; + bool independentMrtBitDepth = GFX->getCardProfiler()->queryProfile("independentMrtBitDepth", false); + //If independent bit depth on a MRT is supported than just use 8bit channels for the albedo color. + if(independentMrtBitDepth) + colorFormat = GFXFormatR8G8B8A8; + + // andrewmac: Deferred Shading Color Buffer + if (mColorTex.getFormat() != colorFormat || mColorTex.getWidthHeight() != mTargetSize || GFX->recentlyReset()) + { + mColorTarget.release(); + mColorTex.set(mTargetSize.x, mTargetSize.y, colorFormat, + &GFXDefaultRenderTargetProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__), + 1, GFXTextureManager::AA_MATCH_BACKBUFFER); + mColorTarget.setTexture(mColorTex); + + for (U32 i = 0; i < mTargetChainLength; i++) + mTargetChain[i]->attachTexture(GFXTextureTarget::Color1, mColorTarget.getTexture()); + } + + // andrewmac: Deferred Shading Material Info Buffer + if (mMatInfoTex.getFormat() != colorFormat || mMatInfoTex.getWidthHeight() != mTargetSize || GFX->recentlyReset()) + { + mMatInfoTarget.release(); + mMatInfoTex.set(mTargetSize.x, mTargetSize.y, colorFormat, + &GFXDefaultRenderTargetProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__), + 1, GFXTextureManager::AA_MATCH_BACKBUFFER); + mMatInfoTarget.setTexture(mMatInfoTex); + + for (U32 i = 0; i < mTargetChainLength; i++) + mTargetChain[i]->attachTexture(GFXTextureTarget::Color2, mMatInfoTarget.getTexture()); + } + + GFX->finalizeReset(); + // Attach the light info buffer as a second render target, if there is // lightmapped geometry in the scene. AdvancedLightBinManager *lightBin; @@ -154,11 +205,13 @@ bool RenderPrePassMgr::_updateTargets() for ( U32 i = 0; i < mTargetChainLength; i++ ) { GFXTexHandle lightInfoTex = lightBin->getTargetTexture(0, i); - mTargetChain[i]->attachTexture(GFXTextureTarget::Color1, lightInfoTex); + mTargetChain[i]->attachTexture(GFXTextureTarget::Color3, lightInfoTex); } } } + _initShaders(); + return ret; } @@ -191,7 +244,7 @@ void RenderPrePassMgr::addElement( RenderInst *inst ) return; // First what type of render instance is it? - const bool isDecalMeshInst = inst->type == RenderPassManager::RIT_Decal; + const bool isDecalMeshInst = ((inst->type == RenderPassManager::RIT_Decal)||(inst->type == RenderPassManager::RIT_DecalRoad)); const bool isMeshInst = inst->type == RenderPassManager::RIT_Mesh; @@ -280,9 +333,8 @@ void RenderPrePassMgr::render( SceneRenderState *state ) // Tell the superclass we're about to render const bool isRenderingToTarget = _onPreRender(state); - // Clear all the buffers to white so that the - // default depth is to the far plane. - GFX->clear( GFXClearTarget | GFXClearZBuffer | GFXClearStencil, ColorI::WHITE, 1.0f, 0); + // Clear all z-buffer, and g-buffer. + clearBuffers(); // Restore transforms MatrixSet &matrixSet = getRenderPass()->getMatrixSet(); @@ -329,7 +381,13 @@ void RenderPrePassMgr::render( SceneRenderState *state ) GFX->drawPrimitive( ri->prim ); } - + // init loop data + GFXTextureObject *lastLM = NULL; + GFXCubemap *lastCubemap = NULL; + GFXTextureObject *lastReflectTex = NULL; + GFXTextureObject *lastMiscTex = NULL; + GFXTextureObject *lastAccuTex = NULL; + // Next render all the meshes. itr = mElementList.begin(); for ( ; itr != mElementList.end(); ) @@ -363,12 +421,11 @@ void RenderPrePassMgr::render( SceneRenderState *state ) // Set up SG data for this instance. setupSGData( passRI, sgData ); + mat->setSceneInfo(state, sgData); matrixSet.setWorld(*passRI->objectToWorld); matrixSet.setView(*passRI->worldToCamera); matrixSet.setProjection(*passRI->projection); - - mat->setSceneInfo(state, sgData); mat->setTransforms(matrixSet, state); // If we're instanced then don't render yet. @@ -385,6 +442,43 @@ void RenderPrePassMgr::render( SceneRenderState *state ) continue; } + bool dirty = false; + + // set the lightmaps if different + if( passRI->lightmap && passRI->lightmap != lastLM ) + { + sgData.lightmap = passRI->lightmap; + lastLM = passRI->lightmap; + dirty = true; + } + + // set the cubemap if different. + if ( passRI->cubemap != lastCubemap ) + { + sgData.cubemap = passRI->cubemap; + lastCubemap = passRI->cubemap; + dirty = true; + } + + if ( passRI->reflectTex != lastReflectTex ) + { + sgData.reflectTex = passRI->reflectTex; + lastReflectTex = passRI->reflectTex; + dirty = true; + } + + // Update accumulation texture if it changed. + // Note: accumulation texture can be NULL, and must be updated. + if (passRI->accuTex != lastAccuTex) + { + sgData.accuTex = passRI->accuTex; + lastAccuTex = lastAccuTex; + dirty = true; + } + + if ( dirty ) + mat->setTextureStages( state, sgData ); + // Setup the vertex and index buffers. mat->setBuffers( passRI->vertBuff, passRI->primBuff ); @@ -525,6 +619,31 @@ void ProcessedPrePassMaterial::_determineFeatures( U32 stageNum, #ifndef TORQUE_DEDICATED + //tag all materials running through prepass as deferred + newFeatures.addFeature(MFT_isDeferred); + + // Deferred Shading : Diffuse + if (mStages[stageNum].getTex( MFT_DiffuseMap )) + { + newFeatures.addFeature(MFT_DiffuseMap); + } + newFeatures.addFeature( MFT_DiffuseColor ); + + // Deferred Shading : Specular + if( mStages[stageNum].getTex( MFT_SpecularMap ) ) + { + newFeatures.addFeature( MFT_DeferredSpecMap ); + } + else if ( mMaterial->mPixelSpecular[stageNum] ) + { + newFeatures.addFeature( MFT_DeferredSpecVars ); + } + else + newFeatures.addFeature(MFT_DeferredEmptySpec); + + // Deferred Shading : Material Info Flags + newFeatures.addFeature( MFT_DeferredMatInfoFlags ); + for ( U32 i=0; i < fd.features.getCount(); i++ ) { const FeatureType &type = fd.features.getAt( i ); @@ -553,7 +672,10 @@ void ProcessedPrePassMaterial::_determineFeatures( U32 stageNum, type == MFT_InterlacedPrePass || type == MFT_Visibility || type == MFT_UseInstancing || - type == MFT_DiffuseVertColor ) + type == MFT_DiffuseVertColor || + type == MFT_DetailMap || + type == MFT_DetailNormalMap || + type == MFT_DiffuseMapAtlas) newFeatures.addFeature( type ); // Add any transform features. @@ -563,11 +685,39 @@ void ProcessedPrePassMaterial::_determineFeatures( U32 stageNum, newFeatures.addFeature( type ); } + if (mMaterial->mAccuEnabled[stageNum]) + { + newFeatures.addFeature(MFT_AccuMap); + mHasAccumulation = true; + } + + // we need both diffuse and normal maps + sm3 to have an accu map + if (newFeatures[MFT_AccuMap] && + (!newFeatures[MFT_DiffuseMap] || + !newFeatures[MFT_NormalMap] || + GFX->getPixelShaderVersion() < 3.0f)) { + AssertWarn(false, "SAHARA: Using an Accu Map requires SM 3.0 and a normal map."); + newFeatures.removeFeature(MFT_AccuMap); + mHasAccumulation = false; + } + + // if we still have the AccuMap feature, we add all accu constant features + if (newFeatures[MFT_AccuMap]) { + // add the dependencies of the accu map + newFeatures.addFeature(MFT_AccuScale); + newFeatures.addFeature(MFT_AccuDirection); + newFeatures.addFeature(MFT_AccuStrength); + newFeatures.addFeature(MFT_AccuCoverage); + newFeatures.addFeature(MFT_AccuSpecular); + // now remove some features that are not compatible with this + newFeatures.removeFeature(MFT_UseInstancing); + } + // If there is lightmapped geometry support, add the MRT light buffer features if(bEnableMRTLightmap) { // If this material has a lightmap, pass it through, and flag it to - // send it's output to RenderTarget1 + // send it's output to RenderTarget3 if( fd.features.hasFeature( MFT_ToneMap ) ) { newFeatures.addFeature( MFT_ToneMap ); @@ -590,10 +740,16 @@ void ProcessedPrePassMaterial::_determineFeatures( U32 stageNum, else { // If this object isn't lightmapped, add a zero-output feature to it - newFeatures.addFeature( MFT_RenderTarget1_Zero ); + newFeatures.addFeature( MFT_RenderTarget3_Zero ); } } + // cubemaps only available on stage 0 for now - bramage + if ( stageNum < 1 && + ( ( mMaterial->mCubemapData && mMaterial->mCubemapData->mCubemap ) || + mMaterial->mDynamicCubemap ) ) + newFeatures.addFeature( MFT_CubeMap ); + #endif // Set the new features. @@ -602,8 +758,54 @@ void ProcessedPrePassMaterial::_determineFeatures( U32 stageNum, U32 ProcessedPrePassMaterial::getNumStages() { - // Return 1 stage so this material gets processed for sure - return 1; + // Loops through all stages to determine how many + // stages we actually use. + // + // The first stage is always active else we shouldn't be + // creating the material to begin with. + U32 numStages = 1; + + U32 i; + for( i=1; imCubemapData || mMaterial->mDynamicCubemap ) + { + numStages++; + continue; + } + } + + // If we have a texture for the a feature the + // stage is active. + if ( mStages[i].hasValidTex() ) + stageActive = true; + + // If this stage has specular lighting, it's active + if ( mMaterial->mPixelSpecular[i] ) + stageActive = true; + + // If this stage has diffuse color, it's active + if ( mMaterial->mDiffuse[i].alpha > 0 && + mMaterial->mDiffuse[i] != ColorF::WHITE ) + stageActive = true; + + // If we have a Material that is vertex lit + // then it may not have a texture + if( mMaterial->mVertLit[i] ) + stageActive = true; + + // Increment the number of active stages + numStages += stageActive; + } + + return numStages; } void ProcessedPrePassMaterial::addStateBlockDesc(const GFXStateBlockDesc& desc) @@ -633,7 +835,7 @@ void ProcessedPrePassMaterial::addStateBlockDesc(const GFXStateBlockDesc& desc) if ( isTranslucent ) { prePassStateBlock.setBlend( true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha ); - prePassStateBlock.setColorWrites( true, true, false, false ); + prePassStateBlock.setColorWrites(false, false, false, true); } // Enable z reads, but only enable zwrites if we're not translucent. @@ -663,7 +865,22 @@ ProcessedMaterial* PrePassMatInstance::getShaderMaterial() bool PrePassMatInstance::init( const FeatureSet &features, const GFXVertexFormat *vertexFormat ) { - return Parent::init( features, vertexFormat ); + bool vaild = Parent::init(features, vertexFormat); + + if (mMaterial && mMaterial->mDiffuseMapFilename[0].isNotEmpty() && mMaterial->mDiffuseMapFilename[0].substr(0, 1).equal("#")) + { + String texTargetBufferName = mMaterial->mDiffuseMapFilename[0].substr(1, mMaterial->mDiffuseMapFilename[0].length() - 1); + NamedTexTarget *texTarget = NamedTexTarget::find(texTargetBufferName); + RenderPassData* rpd = getPass(0); + + if (rpd) + { + rpd->mTexSlot[0].texTarget = texTarget; + rpd->mTexType[0] = Material::TexTarget; + rpd->mSamplerNames[0] = "diffuseMap"; + } + } + return vaild; } PrePassMatInstanceHook::PrePassMatInstanceHook( MatInstance *baseMatInst, @@ -850,3 +1067,77 @@ Var* LinearEyeDepthConditioner::printMethodHeader( MethodType methodType, const return retVal; } + +void RenderPrePassMgr::_initShaders() +{ + if ( mClearGBufferShader ) return; + + // Find ShaderData + ShaderData *shaderData; + mClearGBufferShader = Sim::findObject( "ClearGBufferShader", shaderData ) ? shaderData->getShader() : NULL; + if ( !mClearGBufferShader ) + Con::errorf( "RenderPrePassMgr::_initShaders - could not find ClearGBufferShader" ); + + // Create StateBlocks + GFXStateBlockDesc desc; + desc.setCullMode( GFXCullNone ); + desc.setBlend( true ); + desc.setZReadWrite( false, false ); + desc.samplersDefined = true; + desc.samplers[0].addressModeU = GFXAddressWrap; + desc.samplers[0].addressModeV = GFXAddressWrap; + desc.samplers[0].addressModeW = GFXAddressWrap; + desc.samplers[0].magFilter = GFXTextureFilterLinear; + desc.samplers[0].minFilter = GFXTextureFilterLinear; + desc.samplers[0].mipFilter = GFXTextureFilterLinear; + desc.samplers[0].textureColorOp = GFXTOPModulate; + + mStateblock = GFX->createStateBlock( desc ); + + // Set up shader constants. + mShaderConsts = mClearGBufferShader->allocConstBuffer(); + mSpecularStrengthSC = mClearGBufferShader->getShaderConstHandle( "$specularStrength" ); + mSpecularPowerSC = mClearGBufferShader->getShaderConstHandle( "$specularPower" ); +} + +void RenderPrePassMgr::clearBuffers() +{ + // Clear z-buffer. + GFX->clear( GFXClearTarget | GFXClearZBuffer | GFXClearStencil, ColorI::ZERO, 1.0f, 0); + + if ( !mClearGBufferShader ) + return; + + GFXTransformSaver saver; + + // Clear the g-buffer. + RectI box(-1, -1, 3, 3); + GFX->setWorldMatrix( MatrixF::Identity ); + GFX->setViewMatrix( MatrixF::Identity ); + GFX->setProjectionMatrix( MatrixF::Identity ); + + GFX->setShader(mClearGBufferShader); + GFX->setStateBlock(mStateblock); + + Point2F nw(-0.5,-0.5); + Point2F ne(0.5,-0.5); + + GFXVertexBufferHandle verts(GFX, 4, GFXBufferTypeVolatile); + verts.lock(); + + F32 ulOffset = 0.5f - GFX->getFillConventionOffset(); + + Point2F upperLeft(-1.0, -1.0); + Point2F lowerRight(1.0, 1.0); + + verts[0].point.set( upperLeft.x+nw.x+ulOffset, upperLeft.y+nw.y+ulOffset, 0.0f ); + verts[1].point.set( lowerRight.x+ne.x, upperLeft.y+ne.y+ulOffset, 0.0f ); + verts[2].point.set( upperLeft.x-ne.x+ulOffset, lowerRight.y-ne.y, 0.0f ); + verts[3].point.set( lowerRight.x-nw.x, lowerRight.y-nw.y, 0.0f ); + + verts.unlock(); + + GFX->setVertexBuffer( verts ); + GFX->drawPrimitive( GFXTriangleStrip, 0, 2 ); + GFX->setShader(NULL); +} diff --git a/Engine/source/renderInstance/renderPrePassMgr.h b/Engine/source/renderInstance/renderPrePassMgr.h index 70a36eb84..bf36c6218 100644 --- a/Engine/source/renderInstance/renderPrePassMgr.h +++ b/Engine/source/renderInstance/renderPrePassMgr.h @@ -43,6 +43,10 @@ public: // registered buffer name static const String BufferName; + // andremwac: Deferred Rendering + static const String ColorBufferName; + static const String MatInfoBufferName; + // Generic PrePass Render Instance Type static const RenderInstType RIT_PrePass; @@ -93,6 +97,22 @@ protected: virtual void _createPrePassMaterial(); bool _lightManagerActivate(bool active); + + // Deferred Shading + GFXVertexBufferHandle mClearGBufferVerts; + GFXShaderRef mClearGBufferShader; + GFXStateBlockRef mStateblock; + NamedTexTarget mColorTarget; + NamedTexTarget mMatInfoTarget; + GFXTexHandle mColorTex; + GFXTexHandle mMatInfoTex; + GFXShaderConstBufferRef mShaderConsts; + GFXShaderConstHandle *mSpecularStrengthSC; + GFXShaderConstHandle *mSpecularPowerSC; + +public: + void clearBuffers(); + void _initShaders(); }; //------------------------------------------------------------------------------ diff --git a/Engine/source/renderInstance/renderTerrainMgr.cpp b/Engine/source/renderInstance/renderTerrainMgr.cpp index f298ff51c..4a67e686f 100644 --- a/Engine/source/renderInstance/renderTerrainMgr.cpp +++ b/Engine/source/renderInstance/renderTerrainMgr.cpp @@ -35,6 +35,7 @@ #include "terrain/terrCell.h" #include "terrain/terrCellMaterial.h" #include "math/util/matrixSet.h" +#include "materials/materialManager.h" bool RenderTerrainMgr::smRenderWireframe = false; @@ -117,6 +118,10 @@ void RenderTerrainMgr::render( SceneRenderState *state ) if ( mInstVector.empty() ) return; + // Check if bin is disabled in advanced lighting. + if ( MATMGR->getPrePassEnabled() && mBasicOnly ) + return; + PROFILE_SCOPE( RenderTerrainMgr_Render ); GFXTransformSaver saver; diff --git a/Engine/source/renderInstance/renderTexTargetBinManager.cpp b/Engine/source/renderInstance/renderTexTargetBinManager.cpp index c26231152..5353f4566 100644 --- a/Engine/source/renderInstance/renderTexTargetBinManager.cpp +++ b/Engine/source/renderInstance/renderTexTargetBinManager.cpp @@ -107,8 +107,7 @@ void RenderTexTargetBinManager::initPersistFields() bool RenderTexTargetBinManager::setTargetSize(const Point2I &newTargetSize) { - if( GFX->getAdapterType() != OpenGL && // Targets need to match up exactly in size on OpenGL. - mTargetSize.x >= newTargetSize.x && + if( mTargetSize.x >= newTargetSize.x && mTargetSize.y >= newTargetSize.y ) return true; diff --git a/Engine/source/renderInstance/renderTranslucentMgr.cpp b/Engine/source/renderInstance/renderTranslucentMgr.cpp index b755e12c9..7ad324a26 100644 --- a/Engine/source/renderInstance/renderTranslucentMgr.cpp +++ b/Engine/source/renderInstance/renderTranslucentMgr.cpp @@ -51,6 +51,7 @@ RenderTranslucentMgr::RenderTranslucentMgr() { notifyType( RenderPassManager::RIT_ObjectTranslucent ); notifyType( RenderPassManager::RIT_Particle ); + notifyType( RenderPassManager::RIT_VolumetricFog); } RenderTranslucentMgr::~RenderTranslucentMgr() @@ -187,6 +188,15 @@ void RenderTranslucentMgr::render( SceneRenderState *state ) j++; continue; } + else if (baseRI->type == RenderPassManager::RIT_VolumetricFog) + { + ObjectRenderInst* objRI = static_cast(baseRI); + objRI->renderDelegate(objRI, state, NULL); + lastVB = NULL; + lastPB = NULL; + j++; + continue; + } else if ( baseRI->type == RenderPassManager::RIT_Particle ) { ParticleRenderInst *ri = static_cast(baseRI); diff --git a/Engine/source/scene/reflectionManager.cpp b/Engine/source/scene/reflectionManager.cpp index 057c72c0a..323e11c8a 100644 --- a/Engine/source/scene/reflectionManager.cpp +++ b/Engine/source/scene/reflectionManager.cpp @@ -58,7 +58,7 @@ MODULE_END; GFX_ImplementTextureProfile( ReflectRenderTargetProfile, GFXTextureProfile::DiffuseMap, - GFXTextureProfile::PreserveSize | GFXTextureProfile::NoMipmap | GFXTextureProfile::RenderTarget | GFXTextureProfile::Pooled, + GFXTextureProfile::PreserveSize | GFXTextureProfile::RenderTarget | GFXTextureProfile::Pooled, GFXTextureProfile::NONE ); GFX_ImplementTextureProfile( RefractTextureProfile, diff --git a/Engine/source/scene/reflectionMatHook.cpp b/Engine/source/scene/reflectionMatHook.cpp index b869cabc9..646b0145c 100644 --- a/Engine/source/scene/reflectionMatHook.cpp +++ b/Engine/source/scene/reflectionMatHook.cpp @@ -89,8 +89,6 @@ void ReflectionMaterialHook::_overrideFeatures( ProcessedMaterial *mat, return; } - // Forward shading on materials in reflections - fd.features.addFeature( MFT_ForwardShading ); fd.features.addFeature( MFT_Fog ); } diff --git a/Engine/source/scene/reflector.cpp b/Engine/source/scene/reflector.cpp index 254839813..1addaf191 100644 --- a/Engine/source/scene/reflector.cpp +++ b/Engine/source/scene/reflector.cpp @@ -419,7 +419,6 @@ void CubeReflector::updateFace( const ReflectParams ¶ms, U32 faceidx ) reflectRenderState.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial ); reflectRenderState.setDiffuseCameraTransform( params.query->cameraMatrix ); - reflectRenderState.disableAdvancedLightingBins(true); // render scene LIGHTMGR->registerGlobalLights( &reflectRenderState.getCullingFrustum(), false ); @@ -633,7 +632,6 @@ void PlaneReflector::updateReflection( const ReflectParams ¶ms ) renderStateLeft.setSceneRenderField(0); renderStateLeft.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial ); renderStateLeft.setDiffuseCameraTransform( params.query->eyeTransforms[0] ); - renderStateLeft.disableAdvancedLightingBins(true); gClientSceneGraph->renderSceneNoLights( &renderStateLeft, objTypeFlag ); @@ -672,7 +670,6 @@ void PlaneReflector::updateReflection( const ReflectParams ¶ms ) reflectRenderState.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial ); reflectRenderState.setDiffuseCameraTransform( params.query->cameraMatrix ); - reflectRenderState.disableAdvancedLightingBins(true); gClientSceneGraph->renderSceneNoLights( &reflectRenderState, objTypeFlag ); } diff --git a/Engine/source/sfx/fmod/sfxFMODDevice.h b/Engine/source/sfx/fmod/sfxFMODDevice.h index f710faa20..fc15041e9 100644 --- a/Engine/source/sfx/fmod/sfxFMODDevice.h +++ b/Engine/source/sfx/fmod/sfxFMODDevice.h @@ -105,8 +105,8 @@ struct FModFNTable } ~FModFNTable() { - eventDllRef = NULL; dllRef = NULL; + eventDllRef = NULL; delete mutex; } diff --git a/Engine/source/shaderGen/GLSL/accuFeatureGLSL.cpp b/Engine/source/shaderGen/GLSL/accuFeatureGLSL.cpp index c663b93ea..aa2eda41d 100644 --- a/Engine/source/shaderGen/GLSL/accuFeatureGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/accuFeatureGLSL.cpp @@ -56,7 +56,7 @@ void AccuTexFeatGLSL::processPix(Vector &componentList, output = meta; // OUT.col - Var *color = (Var*) LangElement::find( "col" ); + Var *color = (Var*) LangElement::find( "col1" ); if (!color) { output = new GenOp(" //NULL COLOR!"); diff --git a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp index 7567b5516..78c45a09c 100644 --- a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp @@ -156,10 +156,10 @@ LangElement *ShaderFeatureGLSL::expandNormalMap( LangElement *sampleNormalOp, } else { - // DXT Swizzle trick - meta->addStatement( new GenOp( " @ = float4( @.ag * 2.0 - 1.0, 0.0, 0.0 ); // DXTnm\r\n", normalDecl, sampleNormalOp ) ); - meta->addStatement( new GenOp( " @.z = sqrt( 1.0 - dot( @.xy, @.xy ) ); // DXTnm\r\n", normalVar, normalVar, normalVar ) ); - } + // DXT Swizzle trick + meta->addStatement( new GenOp( " @ = float4( @.ag * 2.0 - 1.0, 0.0, 0.0 ); // DXTnm\r\n", normalDecl, sampleNormalOp ) ); + meta->addStatement( new GenOp( " @.z = sqrt( 1.0 - dot( @.xy, @.xy ) ); // DXTnm\r\n", normalVar, normalVar, normalVar ) ); + } } else { @@ -365,7 +365,7 @@ Var* ShaderFeatureGLSL::getOutTexCoord( const char *name, // Statement allows for casting of different types which // eliminates vector truncation problems. - String statement = String::ToString( " @ = %s(tMul(@, @));\r\n", type ); + String statement = String::ToString( " @ = %s(tMul(@, @).xy);\r\n", type ); meta->addStatement( new GenOp( statement , texCoord, texMat, inTex ) ); } else @@ -708,7 +708,7 @@ void ShaderFeatureGLSL::getWsPosition( Vector &componentList, Var *objTrans = getObjTrans( componentList, useInstancing, meta ); - meta->addStatement( new GenOp( " @ = tMul( @, float4( @.xyz, 1 ) ).xyz;\r\n", + meta->addStatement( new GenOp( " @ = tMul( @, vec4( @.xyz, 1 ) ).xyz;\r\n", wsPosition, objTrans, inPosition ) ); } @@ -813,7 +813,7 @@ Var* ShaderFeatureGLSL::addOutDetailTexCoord( Vector &compon texMat->constSortPos = cspPass; } - meta->addStatement( new GenOp( " @ = tMul(@, @) * @;\r\n", outTex, texMat, inTex, detScale ) ); + meta->addStatement( new GenOp( " @ = tMul(@, @).xy * @;\r\n", outTex, texMat, inTex, detScale ) ); } else { @@ -828,6 +828,12 @@ Var* ShaderFeatureGLSL::addOutDetailTexCoord( Vector &compon // Base Texture //**************************************************************************** +DiffuseMapFeatGLSL::DiffuseMapFeatGLSL() +: mTorqueDep("shaders/common/gl/torque.glsl") +{ + addDependency(&mTorqueDep); +} + void DiffuseMapFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { @@ -841,12 +847,22 @@ void DiffuseMapFeatGLSL::processVert( Vector &componentList, output = meta; } +U32 DiffuseMapFeatGLSL::getOutputTargets(const MaterialFeatureData &fd) const +{ + return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; +} + void DiffuseMapFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { // grab connector texcoord register Var *inTex = getInTexCoord( "texCoord", "vec2", true, componentList ); + //determine output target + ShaderFeature::OutputTarget targ = ShaderFeature::DefaultTarget; + if (fd.features[MFT_isDeferred]) + targ = ShaderFeature::RenderTarget1; + // create texture var Var *diffuseMap = new Var; diffuseMap->setType( "sampler2D" ); @@ -855,30 +871,29 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, diffuseMap->sampler = true; diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here + // create sample color var + Var *diffColor = new Var; + diffColor->setType("vec4"); + diffColor->setName("diffuseColor"); + LangElement *colorDecl = new DecOp( diffColor ); + + MultiLine * meta = new MultiLine; + output = meta; if ( fd.features[MFT_CubeMap] ) { - MultiLine * meta = new MultiLine; - - // create sample color - Var *diffColor = new Var; - diffColor->setType( "vec4" ); - diffColor->setName( "diffuseColor" ); - LangElement *colorDecl = new DecOp( diffColor ); - meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", colorDecl, diffuseMap, inTex ) ); - - meta->addStatement( new GenOp( " @;\r\n", assignColor( diffColor, Material::Mul ) ) ); - output = meta; + if (!fd.features[MFT_Imposter]) + meta->addStatement( new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor) ); + + meta->addStatement( new GenOp( " @;\r\n", assignColor( diffColor, Material::Mul, NULL, targ) ) ); } else if(fd.features[MFT_DiffuseMapAtlas]) { // Handle atlased textures // http://www.infinity-universe.com/Infinity/index.php?option=com_content&task=view&id=65&Itemid=47 - MultiLine * meta = new MultiLine; - output = meta; Var *atlasedTex = new Var; atlasedTex->setName("atlasedTexCoord"); @@ -934,18 +949,13 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, // For the rest of the feature... inTex = atlasedTex; - // create sample color var - Var *diffColor = new Var; - diffColor->setType("vec4"); - diffColor->setName("diffuseColor"); - // To dump out UV coords... //#define DEBUG_ATLASED_UV_COORDS #ifdef DEBUG_ATLASED_UV_COORDS if(!fd.features[MFT_PrePassConditioner]) { - meta->addStatement(new GenOp(" @ = float4(@.xy, mipLod / @.w, 1.0);\r\n", new DecOp(diffColor), inTex, atParams)); - meta->addStatement(new GenOp(" @; return OUT;\r\n", assignColor(diffColor, Material::Mul))); + meta->addStatement(new GenOp(" @ = vec4(@.xy, mipLod / @.w, 1.0);\r\n", new DecOp(diffColor), inTex, atParams)); + meta->addStatement(new GenOp(" @; return OUT;\r\n", assignColor(diffColor, Material::Mul, NULL, targ) ) ); return; } #endif @@ -954,21 +964,26 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, { meta->addStatement(new GenOp( " @ = tex2Dlod(@, float4(@, 0.0, mipLod));\r\n", new DecOp(diffColor), diffuseMap, inTex)); + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor)); } else { - meta->addStatement(new GenOp( " @ = tex2D(@, @);\r\n", - new DecOp(diffColor), diffuseMap, inTex)); + meta->addStatement(new GenOp( " @ = tex2D(@, @);\r\n", + new DecOp(diffColor), diffuseMap, inTex)); + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor)); } - meta->addStatement(new GenOp( " @;\r\n", assignColor(diffColor, Material::Mul))); + meta->addStatement(new GenOp( " @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ) ) ); } else { - LangElement *statement = new GenOp( "tex2D(@, @)", diffuseMap, inTex ); - output = new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ); + meta->addStatement(new GenOp("@ = tex2D(@, @);\r\n", colorDecl, diffuseMap, inTex)); + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor)); + meta->addStatement(new GenOp(" @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ))); } - } ShaderFeature::Resources DiffuseMapFeatGLSL::getResources( const MaterialFeatureData &fd ) @@ -1082,6 +1097,11 @@ void OverlayTexFeatGLSL::setTexData( Material::StageData &stageDat, // Diffuse color //**************************************************************************** +U32 DiffuseFeatureGLSL::getOutputTargets(const MaterialFeatureData &fd) const +{ + return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; +} + void DiffuseFeatureGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { @@ -1092,7 +1112,33 @@ void DiffuseFeatureGLSL::processPix( Vector &componentList, diffuseMaterialColor->constSortPos = cspPotentialPrimitive; MultiLine* meta = new MultiLine; - meta->addStatement( new GenOp( " @;\r\n", assignColor( diffuseMaterialColor, Material::Mul ) ) ); + Var *col = (Var*)LangElement::find("col"); + ShaderFeature::OutputTarget targ = ShaderFeature::DefaultTarget; + if (fd.features[MFT_isDeferred]) + { + targ = ShaderFeature::RenderTarget1; + + col = (Var*)LangElement::find("col1"); + MultiLine * meta = new MultiLine; + if (!col) + { + // create color var + col = new Var; + col->setType("vec4"); + col->setName(getOutputTargetVarName(targ)); + col->setStructName("OUT"); + meta->addStatement(new GenOp(" @ = vec4(1.0);\r\n", col)); + } + } + + Material::BlendOp op; + + if (fd.features[MFT_DiffuseMap]) + op = Material::Mul; + else + op = Material::None; + + meta->addStatement(new GenOp(" @;\r\n", assignColor(diffuseMaterialColor, op, NULL, targ))); output = meta; } @@ -1224,9 +1270,9 @@ void LightmapFeatGLSL::processPix( Vector &componentList, // Lightmap has already been included in the advanced light bin, so // no need to do any sampling or anything if(bPreProcessedLighting) - statement = new GenOp( "float4(@, 1.0)", inColor ); + statement = new GenOp( "vec4(@, 1.0)", inColor ); else - statement = new GenOp( "tex2D(@, @) + float4(@.rgb, 0.0)", lightMap, inTex, inColor ); + statement = new GenOp( "tex2D(@, @) + vec4(@.rgb, 0.0)", lightMap, inTex, inColor ); } } @@ -1238,8 +1284,8 @@ void LightmapFeatGLSL::processPix( Vector &componentList, MultiLine *meta = new MultiLine; if( fd.features[MFT_LightbufferMRT] ) { - meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::None, NULL, ShaderFeature::RenderTarget1 ) ) ); - meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ) ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) ); + meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) ); } else meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ) ); @@ -1271,7 +1317,7 @@ void LightmapFeatGLSL::setTexData( Material::StageData &stageDat, U32 LightmapFeatGLSL::getOutputTargets( const MaterialFeatureData &fd ) const { - return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; + return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget; } //**************************************************************************** @@ -1365,8 +1411,8 @@ void TonemapFeatGLSL::processPix( Vector &componentList, // Assign to proper render target if( fd.features[MFT_LightbufferMRT] ) { - meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, Material::None, NULL, ShaderFeature::RenderTarget1 ) ) ); - meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ) ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) ); + meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) ); } else meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, blendOp ) ) ); @@ -1399,7 +1445,7 @@ void TonemapFeatGLSL::setTexData( Material::StageData &stageDat, U32 TonemapFeatGLSL::getOutputTargets( const MaterialFeatureData &fd ) const { - return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; + return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget; } //**************************************************************************** @@ -1505,17 +1551,17 @@ void VertLitGLSL::processPix( Vector &componentList, // the dynamic light buffer, and it already has the baked-vertex-color // included in it if(bPreProcessedLighting) - outColor = new GenOp( "float4(@.rgb, 1.0)", rtLightingColor ); + outColor = new GenOp( "vec4(@.rgb, 1.0)", rtLightingColor ); else - outColor = new GenOp( "float4(@.rgb + @.rgb, 1.0)", rtLightingColor, outColor ); + outColor = new GenOp( "vec4(@.rgb + @.rgb, 1.0)", rtLightingColor, outColor ); } } // Output the color if ( fd.features[MFT_LightbufferMRT] ) { - meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, Material::None, NULL, ShaderFeature::RenderTarget1 ) ) ); - meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ) ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) ); + meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) ); } else meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, blendOp ) ) ); @@ -1525,7 +1571,7 @@ void VertLitGLSL::processPix( Vector &componentList, U32 VertLitGLSL::getOutputTargets( const MaterialFeatureData &fd ) const { - return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; + return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget; } //**************************************************************************** @@ -1564,7 +1610,10 @@ void DetailFeatGLSL::processPix( Vector &componentList, // and a simple multiplication with the detail map. LangElement *statement = new GenOp( "( tex2D(@, @) * 2.0 ) - 1.0", detailMap, inTex ); - output = new GenOp( " @;\r\n", assignColor( statement, Material::Add ) ); + if ( fd.features[MFT_isDeferred]) + output = new GenOp( " @;\r\n", assignColor( statement, Material::Add, NULL, ShaderFeature::RenderTarget1 ) ); + else + output = new GenOp( " @;\r\n", assignColor( statement, Material::Add ) ); } ShaderFeature::Resources DetailFeatGLSL::getResources( const MaterialFeatureData &fd ) @@ -1623,7 +1672,7 @@ void VertPositionGLSL::processVert( Vector &componentList, Var *modelview = getModelView( componentList, fd.features[MFT_UseInstancing], meta ); - meta->addStatement( new GenOp( " @ = tMul(@, float4(@.xyz,1));\r\n", + meta->addStatement( new GenOp( " @ = tMul(@, vec4(@.xyz,1));\r\n", outPosition, modelview, inPosition ) ); output = meta; @@ -1687,8 +1736,8 @@ void ReflectCubeFeatGLSL::processVert( Vector &componentList, cubeNormal->setName( "cubeNormal" ); cubeNormal->setType( "vec3" ); LangElement *cubeNormDecl = new DecOp( cubeNormal ); - - meta->addStatement( new GenOp( " @ = ( tMul( (@), vec4(@, 0) ) ).xyz;\r\n", + + meta->addStatement( new GenOp( " @ = ( tMul( (@), vec4(@, 0) ) ).xyz;\r\n", cubeNormDecl, cubeTrans, inNormal ) ); meta->addStatement( new GenOp( " @ = bool(length(@)) ? normalize(@) : @;\r\n", @@ -1764,9 +1813,14 @@ void ReflectCubeFeatGLSL::processPix( Vector &componentList, } else { - glossColor = (Var*) LangElement::find( "diffuseColor" ); - if( !glossColor ) - glossColor = (Var*) LangElement::find( "bumpNormal" ); + if (fd.features[MFT_isDeferred]) + glossColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget1)); + if (!glossColor) + glossColor = (Var*)LangElement::find("specularColor"); + if (!glossColor) + glossColor = (Var*)LangElement::find("diffuseColor"); + if (!glossColor) + glossColor = (Var*)LangElement::find("bumpNormal"); } // grab connector texcoord register @@ -1779,7 +1833,7 @@ void ReflectCubeFeatGLSL::processPix( Vector &componentList, // create cubemap var Var *cubeMap = new Var; - cubeMap->setType( "samplerCUBE" ); + cubeMap->setType( "samplerCube" ); cubeMap->setName( "cubeMap" ); cubeMap->uniform = true; cubeMap->sampler = true; @@ -1793,14 +1847,36 @@ void ReflectCubeFeatGLSL::processPix( Vector &componentList, if ( fd.materialFeatures[MFT_RTLighting] ) attn =(Var*)LangElement::find("d_NL_Att"); - LangElement *texCube = new GenOp( "texCUBE( @, @ )", cubeMap, reflectVec ); + LangElement *texCube = NULL; + Var* matinfo = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + //first try and grab the gbuffer + if (fd.features[MFT_isDeferred] && matinfo) + { + + if (fd.features[MFT_DeferredSpecMap]) + texCube = new GenOp("textureLod( @, @, (@.a*5) )", cubeMap, reflectVec, matinfo); + else + texCube = new GenOp("textureLod( @, @, ((1.0-@.a)*6) )", cubeMap, reflectVec, matinfo); + } + else if(glossColor) //failing that, rtry and find color data + texCube = new GenOp("textureLod( @, @, @.a*5)", cubeMap, reflectVec, glossColor); + else + texCube = new GenOp("texture( @, @)", cubeMap, reflectVec); + LangElement *lerpVal = NULL; Material::BlendOp blendOp = Material::LerpAlpha; // Note that the lerpVal needs to be a float4 so that // it will work with the LerpAlpha blend. - - if ( glossColor ) + + if (matinfo) + { + if (attn) + lerpVal = new GenOp("@ * saturate( @ )", matinfo, attn); + else + lerpVal = new GenOp("@", matinfo); + } + else if ( glossColor ) { if ( attn ) lerpVal = new GenOp( "@ * saturate( @ )", glossColor, attn ); @@ -1814,8 +1890,16 @@ void ReflectCubeFeatGLSL::processPix( Vector &componentList, else blendOp = Material::Mul; } - - meta->addStatement( new GenOp( " @;\r\n", assignColor( texCube, blendOp, lerpVal ) ) ); + if (fd.features[MFT_isDeferred]) + { + Var* targ = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget1)); + if (fd.features[MFT_DeferredSpecMap]) + meta->addStatement(new GenOp(" @.rgb = lerp( @.rgb, (@).rgb, (@.b));\r\n", targ, targ, texCube, lerpVal)); + else + meta->addStatement(new GenOp(" @.rgb = lerp( @.rgb, (@).rgb, (@.b));\r\n", targ, targ, texCube, lerpVal)); + } + else + meta->addStatement( new GenOp( " @;\r\n", assignColor( texCube, blendOp, lerpVal ) ) ); output = meta; } @@ -1960,7 +2044,7 @@ void RTLightingFeatGLSL::processVert( Vector &componentList, Var *objTrans = getObjTrans( componentList, fd.features[MFT_UseInstancing], meta ); // Transform the normal to world space. - meta->addStatement( new GenOp( " @ = tMul( @, float4( normalize( @ ), 0.0 ) ).xyz;\r\n", outNormal, objTrans, inNormal ) ); + meta->addStatement( new GenOp( " @ = tMul( @, vec4( normalize( @ ), 0.0 ) ).xyz;\r\n", outNormal, objTrans, inNormal ) ); } addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta ); @@ -2018,7 +2102,7 @@ void RTLightingFeatGLSL::processPix( Vector &componentList, // feature (this is done for BL terrain lightmaps). LangElement *lightMask = LangElement::find( "lightMask" ); if ( !lightMask ) - lightMask = new GenOp( "float4( 1, 1, 1, 1 )" ); + lightMask = new GenOp( "vec4( 1, 1, 1, 1 )" ); // Get all the light constants. Var *inLightPos = new Var( "inLightPos", "vec4" ); @@ -2073,7 +2157,7 @@ void RTLightingFeatGLSL::processPix( Vector &componentList, rtShading, specular ) ); // Apply the lighting to the diffuse color. - LangElement *lighting = new GenOp( "float4( @.rgb + @.rgb, 1 )", rtShading, ambient ); + LangElement *lighting = new GenOp( "vec4( @.rgb + @.rgb, 1 )", rtShading, ambient ); meta->addStatement( new GenOp( " @;\r\n", assignColor( lighting, Material::Mul ) ) ); output = meta; } @@ -2344,7 +2428,9 @@ void AlphaTestGLSL::processPix( Vector &componentList, } // If we don't have a color var then we cannot do an alpha test. - Var *color = (Var*)LangElement::find( "col" ); + Var *color = (Var*)LangElement::find( "col1" ); + if ( !color ) + color = (Var*)LangElement::find("col"); if ( !color ) { output = NULL; @@ -2711,3 +2797,16 @@ void ImposterVertFeatureGLSL::determineFeature( Material *material, outFeatureData->features.addFeature( MFT_ImposterVert ); } +//**************************************************************************** +// Vertex position +//**************************************************************************** +void DeferredSkyGLSL::processVert( Vector &componentList, + const MaterialFeatureData &fd ) +{ + Var *outPosition = (Var*)LangElement::find( "gl_Position" ); + MultiLine *meta = new MultiLine; + meta->addStatement( new GenOp( " @.w = @.z;\r\n", outPosition, outPosition ) ); + + output = meta; +} + diff --git a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h index a0e831e93..c0d5ba832 100644 --- a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h +++ b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h @@ -236,13 +236,20 @@ public: /// Base texture class DiffuseMapFeatGLSL : public ShaderFeatureGLSL { + +protected: + + ShaderIncludeDependency mTorqueDep; public: + DiffuseMapFeatGLSL(); virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ); + virtual U32 getOutputTargets(const MaterialFeatureData &fd) const; + virtual Material::BlendOp getBlendOp(){ return Material::LerpAlpha; } virtual Resources getResources( const MaterialFeatureData &fd ); @@ -296,6 +303,8 @@ public: virtual Material::BlendOp getBlendOp(){ return Material::None; } + virtual U32 getOutputTargets(const MaterialFeatureData &fd) const; + virtual String getName() { return "Diffuse Color"; @@ -651,4 +660,11 @@ public: }; +class DeferredSkyGLSL : public ShaderFeatureGLSL +{ +public: + virtual String getName() { return "Deferred Shading: Sky"; } + virtual void processVert( Vector &componentList, + const MaterialFeatureData &fd ); +}; #endif // _SHADERGEN_GLSL_SHADERFEATUREGLSL_H_ diff --git a/Engine/source/shaderGen/GLSL/shaderGenGLSL.h b/Engine/source/shaderGen/GLSL/shaderGenGLSL.h index c14402875..77305b8e7 100644 --- a/Engine/source/shaderGen/GLSL/shaderGenGLSL.h +++ b/Engine/source/shaderGen/GLSL/shaderGenGLSL.h @@ -30,8 +30,11 @@ class ShaderGenPrinterGLSL : public ShaderGenPrinter { + bool extraRTs[3]; + public: - + ShaderGenPrinterGLSL() { for (int i = 0; i < 3; i++) extraRTs[i] = false; } + // ShaderGenPrinter virtual void printShaderHeader(Stream& stream); virtual void printMainComment(Stream& stream); diff --git a/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp b/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp index 3c4065d44..020b68d43 100644 --- a/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp +++ b/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp @@ -34,6 +34,8 @@ #include "core/module.h" #include "shaderGen/GLSL/accuFeatureGLSL.h" +// Deferred Shading +#include "lighting/advanced/glsl/deferredShadingFeaturesGLSL.h" static ShaderGen::ShaderGenInitDelegate sInitDelegate; @@ -66,8 +68,14 @@ void _initShaderGenGLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_AccuMap, new AccuTexFeatGLSL ); FEATUREMGR->registerFeature( MFT_GlossMap, new NamedFeatureGLSL( "Gloss Map" ) ); FEATUREMGR->registerFeature( MFT_IsTranslucent, new NamedFeatureGLSL( "Translucent" ) ); + FEATUREMGR->registerFeature( MFT_IsTranslucentZWrite, new NamedFeatureGLSL( "Translucent ZWrite" ) ); FEATUREMGR->registerFeature( MFT_Visibility, new VisibilityFeatGLSL ); FEATUREMGR->registerFeature( MFT_Fog, new FogFeatGLSL ); + FEATUREMGR->registerFeature( MFT_LightbufferMRT, new NamedFeatureGLSL( "Lightbuffer MRT" ) ); + FEATUREMGR->registerFeature( MFT_RenderTarget1_Zero, new RenderTargetZeroGLSL( ShaderFeature::RenderTarget1 ) ); + FEATUREMGR->registerFeature( MFT_RenderTarget2_Zero, new RenderTargetZeroGLSL( ShaderFeature::RenderTarget2 ) ); + FEATUREMGR->registerFeature( MFT_RenderTarget3_Zero, new RenderTargetZeroGLSL( ShaderFeature::RenderTarget3 ) ); + FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureGLSL( "Imposter" ) ); FEATUREMGR->registerFeature( MFT_NormalsOut, new NormalsOutFeatGLSL ); @@ -79,9 +87,6 @@ void _initShaderGenGLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_ParaboloidVertTransform, new ParaboloidVertTransformGLSL ); FEATUREMGR->registerFeature( MFT_IsSinglePassParaboloid, new NamedFeatureGLSL( "Single Pass Paraboloid" ) ); FEATUREMGR->registerFeature( MFT_UseInstancing, new NamedFeatureGLSL( "Hardware Instancing" ) ); - - FEATUREMGR->registerFeature( MFT_RenderTarget1_Zero, new RenderTargetZeroGLSL - ( ShaderFeature::RenderTarget1 ) ); FEATUREMGR->registerFeature( MFT_DiffuseMapAtlas, new NamedFeatureGLSL( "Diffuse Map Atlas" ) ); FEATUREMGR->registerFeature( MFT_NormalMapAtlas, new NamedFeatureGLSL( "Normal Map Atlas" ) ); @@ -93,10 +98,13 @@ void _initShaderGenGLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_ImposterVert, new ImposterVertFeatureGLSL ); - FEATUREMGR->registerFeature( MFT_LightbufferMRT, new NamedFeatureGLSL( "Lightbuffer MRT" ) ); - //FEATUREMGR->registerFeature( MFT_IsTranslucentZWrite, new NamedFeatureGLSL( "Translucent ZWrite" ) ); - //FEATUREMGR->registerFeature( MFT_InterlacedPrePass, new NamedFeatureGLSL( "Interlaced Pre Pass" ) ); - + // Deferred Shading + FEATUREMGR->registerFeature( MFT_isDeferred, new NamedFeatureGLSL( "Deferred Material" ) ); + FEATUREMGR->registerFeature( MFT_DeferredSpecMap, new DeferredSpecMapGLSL ); + FEATUREMGR->registerFeature( MFT_DeferredSpecVars, new DeferredSpecVarsGLSL ); + FEATUREMGR->registerFeature( MFT_DeferredMatInfoFlags, new DeferredMatInfoFlagsGLSL ); + FEATUREMGR->registerFeature( MFT_DeferredEmptySpec, new DeferredEmptySpecGLSL ); + FEATUREMGR->registerFeature( MFT_SkyBox, new DeferredSkyGLSL ); } MODULE_BEGIN( ShaderGenGLSL ) diff --git a/Engine/source/shaderGen/HLSL/accuFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/accuFeatureHLSL.cpp index 63161c258..2bafc06f4 100644 --- a/Engine/source/shaderGen/HLSL/accuFeatureHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/accuFeatureHLSL.cpp @@ -56,7 +56,7 @@ void AccuTexFeatHLSL::processPix( Vector &componentList, output = meta; // OUT.col - Var *color = (Var*) LangElement::find( "col" ); + Var *color = (Var*) LangElement::find( "col1" ); if (!color) { output = new GenOp(" //NULL COLOR!"); diff --git a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp index 8f8b5918a..2ab6a75f0 100644 --- a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp @@ -365,7 +365,7 @@ Var* ShaderFeatureHLSL::getOutTexCoord( const char *name, // Statement allows for casting of different types which // eliminates vector truncation problems. - String statement = String::ToString( " @ = (%s)mul(@, @);\r\n", type ); + String statement = String::ToString( " @ = (%s)mul(@, @).xy;\r\n", type ); meta->addStatement( new GenOp( statement, texCoord, texMat, inTex ) ); } else @@ -811,7 +811,7 @@ Var* ShaderFeatureHLSL::addOutDetailTexCoord( Vector &compon texMat->constSortPos = cspPass; } - meta->addStatement( new GenOp( " @ = mul(@, @) * @;\r\n", outTex, texMat, inTex, detScale ) ); + meta->addStatement( new GenOp( " @ = mul(@, @).xy * @;\r\n", outTex, texMat, inTex, detScale ) ); } else { @@ -826,6 +826,12 @@ Var* ShaderFeatureHLSL::addOutDetailTexCoord( Vector &compon // Base Texture //**************************************************************************** +DiffuseMapFeatHLSL::DiffuseMapFeatHLSL() +: mTorqueDep("shaders/common/torque.hlsl") +{ + addDependency(&mTorqueDep); +} + void DiffuseMapFeatHLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { @@ -839,12 +845,22 @@ void DiffuseMapFeatHLSL::processVert( Vector &componentList, output = meta; } +U32 DiffuseMapFeatHLSL::getOutputTargets(const MaterialFeatureData &fd) const +{ + return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; +} + void DiffuseMapFeatHLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { // grab connector texcoord register Var *inTex = getInTexCoord( "texCoord", "float2", true, componentList ); + //determine output target + ShaderFeature::OutputTarget targ = ShaderFeature::DefaultTarget; + if (fd.features[MFT_isDeferred]) + targ = ShaderFeature::RenderTarget1; + // create texture var Var *diffuseMap = new Var; diffuseMap->setType( "sampler2D" ); @@ -853,30 +869,30 @@ void DiffuseMapFeatHLSL::processPix( Vector &componentList, diffuseMap->sampler = true; diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here + // create sample color + Var *diffColor = new Var; + diffColor->setType("float4"); + diffColor->setName("diffuseColor"); + LangElement *colorDecl = new DecOp(diffColor); + + MultiLine * meta = new MultiLine; + output = meta; + if ( fd.features[MFT_CubeMap] ) { - MultiLine * meta = new MultiLine; - - // create sample color - Var *diffColor = new Var; - diffColor->setType( "float4" ); - diffColor->setName( "diffuseColor" ); - LangElement *colorDecl = new DecOp( diffColor ); - meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", colorDecl, diffuseMap, inTex ) ); + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor)); - meta->addStatement( new GenOp( " @;\r\n", assignColor( diffColor, Material::Mul ) ) ); - output = meta; + meta->addStatement(new GenOp(" @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ))); } else if(fd.features[MFT_DiffuseMapAtlas]) { // Handle atlased textures // http://www.infinity-universe.com/Infinity/index.php?option=com_content&task=view&id=65&Itemid=47 - MultiLine * meta = new MultiLine; - output = meta; Var *atlasedTex = new Var; atlasedTex->setName("atlasedTexCoord"); @@ -932,18 +948,13 @@ void DiffuseMapFeatHLSL::processPix( Vector &componentList, // For the rest of the feature... inTex = atlasedTex; - // create sample color var - Var *diffColor = new Var; - diffColor->setType("float4"); - diffColor->setName("diffuseColor"); - // To dump out UV coords... //#define DEBUG_ATLASED_UV_COORDS #ifdef DEBUG_ATLASED_UV_COORDS if(!fd.features[MFT_PrePassConditioner]) { meta->addStatement(new GenOp(" @ = float4(@.xy, mipLod / @.w, 1.0);\r\n", new DecOp(diffColor), inTex, atParams)); - meta->addStatement(new GenOp(" @; return OUT;\r\n", assignColor(diffColor, Material::Mul))); + meta->addStatement(new GenOp(" @; return OUT;\r\n", assignColor(diffColor, Material::Mul, NULL, targ) ) ); return; } #endif @@ -958,15 +969,18 @@ void DiffuseMapFeatHLSL::processPix( Vector &componentList, meta->addStatement(new GenOp( " @ = tex2D(@, @);\r\n", new DecOp(diffColor), diffuseMap, inTex)); } + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor)); - meta->addStatement(new GenOp( " @;\r\n", assignColor(diffColor, Material::Mul))); + meta->addStatement(new GenOp(" @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ) ) ); } else { - LangElement *statement = new GenOp( "tex2D(@, @)", diffuseMap, inTex ); - output = new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ); - } - + meta->addStatement(new GenOp("@ = tex2D(@, @);\r\n", colorDecl, diffuseMap, inTex)); + if (!fd.features[MFT_Imposter]) + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", diffColor, diffColor)); + meta->addStatement(new GenOp(" @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ))); + } } ShaderFeature::Resources DiffuseMapFeatHLSL::getResources( const MaterialFeatureData &fd ) @@ -1083,6 +1097,11 @@ void OverlayTexFeatHLSL::setTexData( Material::StageData &stageDat, // Diffuse color //**************************************************************************** +U32 DiffuseFeatureHLSL::getOutputTargets(const MaterialFeatureData &fd) const +{ + return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; +} + void DiffuseFeatureHLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { @@ -1092,8 +1111,34 @@ void DiffuseFeatureHLSL::processPix( Vector &componentList, diffuseMaterialColor->uniform = true; diffuseMaterialColor->constSortPos = cspPotentialPrimitive; - MultiLine * meta = new MultiLine; - meta->addStatement( new GenOp( " @;\r\n", assignColor( diffuseMaterialColor, Material::Mul ) ) ); + MultiLine* meta = new MultiLine; + Var *col = (Var*)LangElement::find("col"); + ShaderFeature::OutputTarget targ = ShaderFeature::DefaultTarget; + if (fd.features[MFT_isDeferred]) + { + targ = ShaderFeature::RenderTarget1; + + col = (Var*)LangElement::find("col1"); + MultiLine * meta = new MultiLine; + if (!col) + { + // create color var + col = new Var; + col->setType("fragout"); + col->setName(getOutputTargetVarName(targ)); + col->setStructName("OUT"); + meta->addStatement(new GenOp(" @ = float4(1.0);\r\n", col)); + } + } + + Material::BlendOp op; + + if (fd.features[MFT_DiffuseMap]) + op = Material::Mul; + else + op = Material::None; + + meta->addStatement( new GenOp( " @;\r\n", assignColor( diffuseMaterialColor, op, NULL, targ ) ) ); output = meta; } @@ -1239,8 +1284,8 @@ void LightmapFeatHLSL::processPix( Vector &componentList, MultiLine *meta = new MultiLine; if( fd.features[MFT_LightbufferMRT] ) { - meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::None, NULL, ShaderFeature::RenderTarget1 ) ) ); - meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ) ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) ); + meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) ); } else meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ) ); @@ -1272,7 +1317,7 @@ void LightmapFeatHLSL::setTexData( Material::StageData &stageDat, U32 LightmapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const { - return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; + return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget; } //**************************************************************************** @@ -1366,8 +1411,8 @@ void TonemapFeatHLSL::processPix( Vector &componentList, // Assign to proper render target if( fd.features[MFT_LightbufferMRT] ) { - meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, Material::None, NULL, ShaderFeature::RenderTarget1 ) ) ); - meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ) ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) ); + meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) ); } else meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, blendOp ) ) ); @@ -1400,7 +1445,7 @@ void TonemapFeatHLSL::setTexData( Material::StageData &stageDat, U32 TonemapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const { - return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; + return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget; } //**************************************************************************** @@ -1515,8 +1560,8 @@ void VertLitHLSL::processPix( Vector &componentList, // Output the color if ( fd.features[MFT_LightbufferMRT] ) { - meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, Material::None, NULL, ShaderFeature::RenderTarget1 ) ) ); - meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ) ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) ); + meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) ); } else meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, blendOp ) ) ); @@ -1526,7 +1571,7 @@ void VertLitHLSL::processPix( Vector &componentList, U32 VertLitHLSL::getOutputTargets( const MaterialFeatureData &fd ) const { - return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; + return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget; } //**************************************************************************** @@ -1565,7 +1610,10 @@ void DetailFeatHLSL::processPix( Vector &componentList, // and a simple multiplication with the detail map. LangElement *statement = new GenOp( "( tex2D(@, @) * 2.0 ) - 1.0", detailMap, inTex ); - output = new GenOp( " @;\r\n", assignColor( statement, Material::Add ) ); + if ( fd.features[MFT_isDeferred]) + output = new GenOp( " @;\r\n", assignColor( statement, Material::Add, NULL, ShaderFeature::RenderTarget1 ) ); + else + output = new GenOp( " @;\r\n", assignColor( statement, Material::Add ) ); } ShaderFeature::Resources DetailFeatHLSL::getResources( const MaterialFeatureData &fd ) @@ -1690,7 +1738,7 @@ void ReflectCubeFeatHLSL::processVert( Vector &componentList, cubeNormal->setType( "float3" ); LangElement *cubeNormDecl = new DecOp( cubeNormal ); - meta->addStatement( new GenOp( " @ = normalize( mul(@, float4(normalize(@),0.0)).xyz );\r\n", + meta->addStatement( new GenOp( " @ = normalize( mul(@, float4(normalize(@),0.0)).xyz );\r\n", cubeNormDecl, cubeTrans, inNormal ) ); // grab the eye position @@ -1763,9 +1811,14 @@ void ReflectCubeFeatHLSL::processPix( Vector &componentList, } else { - glossColor = (Var*) LangElement::find( "diffuseColor" ); - if( !glossColor ) - glossColor = (Var*) LangElement::find( "bumpNormal" ); + if (fd.features[MFT_isDeferred]) + glossColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget1)); + if (!glossColor) + glossColor = (Var*)LangElement::find("specularColor"); + if (!glossColor) + glossColor = (Var*)LangElement::find("diffuseColor"); + if (!glossColor) + glossColor = (Var*)LangElement::find("bumpNormal"); } // grab connector texcoord register @@ -1791,15 +1844,41 @@ void ReflectCubeFeatHLSL::processPix( Vector &componentList, //else if ( fd.materialFeatures[MFT_RTLighting] ) attn =(Var*)LangElement::find("d_NL_Att"); + + LangElement *texCube = NULL; + Var* matinfo = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); + //first try and grab the gbuffer + if (fd.features[MFT_isDeferred] && matinfo) + { + // Cube LOD level = (1.0 - Roughness) * 8 + // mip_levle = min((1.0 - u_glossiness)*11.0 + 1.0, 8.0) + //LangElement *texCube = new GenOp( "texCUBElod( @, float4(@, min((1.0 - (@ / 128.0)) * 11.0 + 1.0, 8.0)) )", cubeMap, reflectVec, specPower ); + + if (fd.features[MFT_DeferredSpecMap]) + texCube = new GenOp("texCUBElod( @, float4(@, (@.a*5)) )", cubeMap, reflectVec, matinfo); + else + texCube = new GenOp("texCUBElod( @, float4(@, ((1.0-@.a)*6)) )", cubeMap, reflectVec, matinfo); + } + else + if (glossColor) //failing that, rtry and find color data + texCube = new GenOp("texCUBElod( @, float4(@, @.a*5))", cubeMap, reflectVec, glossColor); + else //failing *that*, just draw the cubemap + texCube = new GenOp("texCUBE( @, @)", cubeMap, reflectVec); - LangElement *texCube = new GenOp( "texCUBE( @, @ )", cubeMap, reflectVec ); LangElement *lerpVal = NULL; Material::BlendOp blendOp = Material::LerpAlpha; // Note that the lerpVal needs to be a float4 so that // it will work with the LerpAlpha blend. - if ( glossColor ) + if (matinfo) + { + if (attn) + lerpVal = new GenOp("@ * saturate( @ )", matinfo, attn); + else + lerpVal = new GenOp("@", matinfo); + } + else if ( glossColor ) { if ( attn ) lerpVal = new GenOp( "@ * saturate( @ )", glossColor, attn ); @@ -1813,8 +1892,16 @@ void ReflectCubeFeatHLSL::processPix( Vector &componentList, else blendOp = Material::Mul; } - - meta->addStatement( new GenOp( " @;\r\n", assignColor( texCube, blendOp, lerpVal ) ) ); + if (fd.features[MFT_isDeferred]) + { + Var* targ = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget1)); + if (fd.features[MFT_DeferredSpecMap]) + meta->addStatement(new GenOp(" @.rgb = lerp( @.rgb, (@).rgb, (@.b));\r\n", targ, targ, texCube, lerpVal)); + else + meta->addStatement(new GenOp(" @.rgb = lerp( @.rgb, (@).rgb, (@.b));\r\n", targ, targ, texCube, lerpVal)); + } + else + meta->addStatement( new GenOp( " @;\r\n", assignColor( texCube, blendOp, lerpVal ) ) ); output = meta; } @@ -1861,9 +1948,9 @@ void ReflectCubeFeatHLSL::setTexData( Material::StageData &stageDat, { passData.mSamplerNames[ texIndex ] = "bumpMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; + } } } - } if( stageDat.getCubemap() ) { @@ -2343,7 +2430,9 @@ void AlphaTestHLSL::processPix( Vector &componentList, } // If we don't have a color var then we cannot do an alpha test. - Var *color = (Var*)LangElement::find( "col" ); + Var *color = (Var*)LangElement::find( "col1" ); + if (!color) + color = (Var*)LangElement::find("col"); if ( !color ) { output = NULL; @@ -2710,3 +2799,16 @@ void ImposterVertFeatureHLSL::determineFeature( Material *material, outFeatureData->features.addFeature( MFT_ImposterVert ); } + +//**************************************************************************** +// Vertex position +//**************************************************************************** +void DeferredSkyHLSL::processVert( Vector &componentList, + const MaterialFeatureData &fd ) +{ + Var *outPosition = (Var*)LangElement::find( "hpos" ); + MultiLine *meta = new MultiLine; + meta->addStatement( new GenOp( " @.w = @.z;\r\n", outPosition, outPosition ) ); + + output = meta; +} diff --git a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.h b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.h index 3c2fc821e..b09d4d561 100644 --- a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.h +++ b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.h @@ -236,13 +236,20 @@ public: /// Base texture class DiffuseMapFeatHLSL : public ShaderFeatureHLSL { +protected: + + ShaderIncludeDependency mTorqueDep; + public: + DiffuseMapFeatHLSL(); virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ); + virtual U32 getOutputTargets(const MaterialFeatureData &fd) const; + virtual Material::BlendOp getBlendOp(){ return Material::LerpAlpha; } virtual Resources getResources( const MaterialFeatureData &fd ); @@ -296,6 +303,7 @@ public: virtual Material::BlendOp getBlendOp(){ return Material::None; } + virtual U32 getOutputTargets(const MaterialFeatureData &fd) const; virtual String getName() { return "Diffuse Color"; @@ -651,4 +659,12 @@ public: }; +class DeferredSkyHLSL : public ShaderFeatureHLSL +{ +public: + virtual String getName() { return "Deferred Shading: Sky"; } + virtual void processVert( Vector &componentList, + const MaterialFeatureData &fd ); +}; + #endif // _SHADERGEN_HLSL_SHADERFEATUREHLSL_H_ diff --git a/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp b/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp index c754e1b25..fd30656bd 100644 --- a/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp +++ b/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp @@ -32,6 +32,8 @@ #include "shaderGen/HLSL/paraboloidHLSL.h" #include "materials/materialFeatureTypes.h" #include "core/module.h" +// Deferred Shading +#include "lighting/advanced/hlsl/deferredShadingFeaturesHLSL.h" #include "shaderGen/HLSL/accuFeatureHLSL.h" static ShaderGen::ShaderGenInitDelegate sInitDelegate; @@ -70,6 +72,9 @@ void _initShaderGenHLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_GlossMap, new NamedFeatureHLSL( "Gloss Map" ) ); FEATUREMGR->registerFeature( MFT_LightbufferMRT, new NamedFeatureHLSL( "Lightbuffer MRT" ) ); FEATUREMGR->registerFeature( MFT_RenderTarget1_Zero, new RenderTargetZeroHLSL( ShaderFeature::RenderTarget1 ) ); + FEATUREMGR->registerFeature( MFT_RenderTarget2_Zero, new RenderTargetZeroHLSL( ShaderFeature::RenderTarget2 ) ); + FEATUREMGR->registerFeature( MFT_RenderTarget3_Zero, new RenderTargetZeroHLSL( ShaderFeature::RenderTarget3 ) ); + FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); FEATUREMGR->registerFeature( MFT_DiffuseMapAtlas, new NamedFeatureHLSL( "Diffuse Map Atlas" ) ); FEATUREMGR->registerFeature( MFT_NormalMapAtlas, new NamedFeatureHLSL( "Normal Map Atlas" ) ); @@ -94,6 +99,14 @@ void _initShaderGenHLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_ForwardShading, new NamedFeatureHLSL( "Forward Shaded Material" ) ); FEATUREMGR->registerFeature( MFT_ImposterVert, new ImposterVertFeatureHLSL ); + + // Deferred Shading + FEATUREMGR->registerFeature( MFT_isDeferred, new NamedFeatureHLSL( "Deferred Material" ) ); + FEATUREMGR->registerFeature( MFT_DeferredSpecMap, new DeferredSpecMapHLSL ); + FEATUREMGR->registerFeature( MFT_DeferredSpecVars, new DeferredSpecVarsHLSL ); + FEATUREMGR->registerFeature( MFT_DeferredMatInfoFlags, new DeferredMatInfoFlagsHLSL ); + FEATUREMGR->registerFeature( MFT_DeferredEmptySpec, new DeferredEmptySpecHLSL ); + FEATUREMGR->registerFeature( MFT_SkyBox, new DeferredSkyHLSL ); } MODULE_BEGIN( ShaderGenHLSL ) diff --git a/Engine/source/shaderGen/featureSet.cpp b/Engine/source/shaderGen/featureSet.cpp index 7189beacc..2eff50e1c 100644 --- a/Engine/source/shaderGen/featureSet.cpp +++ b/Engine/source/shaderGen/featureSet.cpp @@ -170,7 +170,7 @@ void FeatureSet::removeFeature( const FeatureType &type ) } } -U32 FeatureSet::getNextFeatureIndex( const FeatureType &type, S32 index ) const +S32 FeatureSet::getNextFeatureIndex( const FeatureType &type, S32 index ) const { for ( U32 i=0; i < mFeatures.size(); i++ ) { diff --git a/Engine/source/shaderGen/featureSet.h b/Engine/source/shaderGen/featureSet.h index e8920dc67..03b46f62a 100644 --- a/Engine/source/shaderGen/featureSet.h +++ b/Engine/source/shaderGen/featureSet.h @@ -106,7 +106,7 @@ public: void removeFeature( const FeatureType &type ); /// - U32 getNextFeatureIndex( const FeatureType &type, S32 index ) const; + S32 getNextFeatureIndex( const FeatureType &type, S32 index ) const; /// Removes features that are not in the input set. void filter( const FeatureSet &features ); diff --git a/Engine/source/shaderGen/shaderFeature.cpp b/Engine/source/shaderGen/shaderFeature.cpp index 9c1d8d955..7e22f72ad 100644 --- a/Engine/source/shaderGen/shaderFeature.cpp +++ b/Engine/source/shaderGen/shaderFeature.cpp @@ -47,10 +47,24 @@ ShaderFeature::Resources ShaderFeature::getResources( const MaterialFeatureData const char* ShaderFeature::getOutputTargetVarName( OutputTarget target ) const { const char* targName = "col"; - if ( target != DefaultTarget ) + + switch(target) { + case DefaultTarget: + targName = "col"; + break; + + case RenderTarget1: targName = "col1"; - AssertFatal(target == RenderTarget1, "yeah Pat is lame and didn't want to do bit math stuff, TODO"); + break; + + case RenderTarget2: + targName = "col2"; + break; + + case RenderTarget3: + targName = "col3"; + break; } return targName; diff --git a/Engine/source/shaderGen/shaderFeature.h b/Engine/source/shaderGen/shaderFeature.h index f18fae7f9..c6ac4955d 100644 --- a/Engine/source/shaderGen/shaderFeature.h +++ b/Engine/source/shaderGen/shaderFeature.h @@ -153,7 +153,7 @@ public: void setProcessIndex( S32 index ) { mProcessIndex = index; } /// - U32 getProcessIndex() const { return mProcessIndex; } + S32 getProcessIndex() const { return mProcessIndex; } //----------------------------------------------------------------------- // Virtual Functions diff --git a/Engine/source/shaderGen/shaderGenVars.cpp b/Engine/source/shaderGen/shaderGenVars.cpp index 3e5a577ee..f4aca6cf5 100644 --- a/Engine/source/shaderGen/shaderGenVars.cpp +++ b/Engine/source/shaderGen/shaderGenVars.cpp @@ -80,4 +80,7 @@ const String ShaderGenVars::cubeMap("$cubeMap"); const String ShaderGenVars::dLightMap("$dlightMap"); const String ShaderGenVars::dLightMapSec("$dlightMapSec"); const String ShaderGenVars::dLightMask("$dlightMask"); -const String ShaderGenVars::toneMap("$toneMap"); \ No newline at end of file +const String ShaderGenVars::toneMap("$toneMap"); + +// Deferred shading +const String ShaderGenVars::matInfoFlags("$matInfoFlags"); \ No newline at end of file diff --git a/Engine/source/shaderGen/shaderGenVars.h b/Engine/source/shaderGen/shaderGenVars.h index a98940101..52ff016d0 100644 --- a/Engine/source/shaderGen/shaderGenVars.h +++ b/Engine/source/shaderGen/shaderGenVars.h @@ -94,6 +94,9 @@ struct ShaderGenVars const static String dLightMapSec; const static String dLightMask; const static String toneMap; + + // Deferred Shading + const static String matInfoFlags; }; #endif diff --git a/Engine/source/sim/netGhost.cpp b/Engine/source/sim/netGhost.cpp index 52fb23f69..1b51b0dde 100644 --- a/Engine/source/sim/netGhost.cpp +++ b/Engine/source/sim/netGhost.cpp @@ -964,7 +964,7 @@ void NetConnection::activateGhosting() // Iterate through the scope always objects... for (j = mGhostZeroUpdateIndex - 1; j >= 0; j--) { - AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting: Non-scope always in the scope always list.") + AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting: Non-scope always in the scope always list."); // Clear the ghost update mask and flags appropriately. mGhostArray[j]->updateMask = 0; @@ -1015,7 +1015,7 @@ void NetConnection::activateGhosting() // Iterate through the scope always objects... for (j = mGhostZeroUpdateIndex - 1; j >= 0; j--) { - AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting: Non-scope always in the scope always list.") + AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting: Non-scope always in the scope always list."); // Clear the ghost update mask and flags appropriately. mGhostArray[j]->updateMask = 0; diff --git a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp index ebe052e00..b9105cdd2 100644 --- a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp +++ b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp @@ -26,6 +26,7 @@ #include "terrain/terrFeatureTypes.h" #include "materials/materialFeatureTypes.h" #include "materials/materialFeatureData.h" +#include "materials/processedMaterial.h" #include "gfx/gfxDevice.h" #include "shaderGen/langElement.h" #include "shaderGen/shaderOp.h" @@ -48,6 +49,10 @@ namespace FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatGLSL ); FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureGLSL( "Terrain Side Projection" ) ); FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatGLSL ); + FEATUREMGR->registerFeature( MFT_DeferredTerrainBaseMap, new TerrainBaseMapFeatGLSL ); + FEATUREMGR->registerFeature( MFT_DeferredTerrainMacroMap, new TerrainMacroMapFeatGLSL ); + FEATUREMGR->registerFeature( MFT_DeferredTerrainDetailMap, new TerrainDetailMapFeatGLSL ); + FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatGLSL ); } }; @@ -64,6 +69,12 @@ MODULE_BEGIN( TerrainFeatGLSL ) MODULE_END; +TerrainFeatGLSL::TerrainFeatGLSL() + : mTorqueDep( "shaders/common/gl/torque.glsl" ) + { + addDependency( &mTorqueDep ); + } + Var* TerrainFeatGLSL::_getUniformVar( const char *name, const char *type, ConstantSortPosition csp ) { Var *theVar = (Var*)LangElement::find( name ); @@ -244,10 +255,6 @@ void TerrainBaseMapFeatGLSL::processPix( Vector &componentLis // grab connector texcoord register Var *texCoord = getInTexCoord( "texCoord", "vec3", true, componentList ); - // We do nothing more if this is a prepass. - if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) - return; - // create texture var Var *diffuseMap = new Var; diffuseMap->setType( "sampler2D" ); @@ -262,7 +269,15 @@ void TerrainBaseMapFeatGLSL::processPix( Vector &componentLis baseColor->setType( "vec4" ); baseColor->setName( "baseColor" ); meta->addStatement( new GenOp( " @ = tex2D( @, @.xy );\r\n", new DecOp( baseColor ), diffuseMap, texCoord ) ); - meta->addStatement( new GenOp( " @;\r\n", assignColor( baseColor, Material::Mul ) ) ); + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", baseColor, baseColor)); + + ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget; + + if(fd.features.hasFeature(MFT_isDeferred)) + { + target= ShaderFeature::RenderTarget1; + } + meta->addStatement( new GenOp( " @;\r\n", assignColor( baseColor, Material::Mul,NULL,target ) ) ); output = meta; } @@ -271,14 +286,16 @@ ShaderFeature::Resources TerrainBaseMapFeatGLSL::getResources( const MaterialFea { Resources res; res.numTexReg = 1; - - // We only sample from the base map during a diffuse pass. - if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) res.numTex = 1; return res; } +U32 TerrainBaseMapFeatGLSL::getOutputTargets( const MaterialFeatureData &fd ) const +{ + return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; +} + TerrainDetailMapFeatGLSL::TerrainDetailMapFeatGLSL() : mTorqueDep( "shaders/common/gl/torque.glsl" ), mTerrainDep( "shaders/common/terrain/terrain.glsl" ) @@ -291,7 +308,7 @@ TerrainDetailMapFeatGLSL::TerrainDetailMapFeatGLSL() void TerrainDetailMapFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); // Grab incoming texture coords... the base map feature // made sure this was created. @@ -376,9 +393,12 @@ void TerrainDetailMapFeatGLSL::processVert( Vector &component void TerrainDetailMapFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); Var *inTex = getVertTexCoord( "texCoord" ); + // new terrain + bool hasNormal = fd.features.hasFeature(MFT_TerrainNormalMap, detailIndex); + MultiLine *meta = new MultiLine; // We need the negative tangent space view vector @@ -447,6 +467,100 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n", new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) ); + // New terrain + + Var *lerpBlend = (Var*)LangElement::find("lerpBlend"); + if (!lerpBlend) + { + lerpBlend = new Var; + lerpBlend->setType("float"); + lerpBlend->setName("lerpBlend"); + lerpBlend->uniform = true; + lerpBlend->constSortPos = cspPrimitive; + } + + + Var *blendDepth = (Var*)LangElement::find(String::ToString("blendDepth%d", detailIndex)); + if (!blendDepth) + { + blendDepth = new Var; + blendDepth->setType("float"); + blendDepth->setName(String::ToString("blendDepth%d", detailIndex)); + blendDepth->uniform = true; + blendDepth->constSortPos = cspPrimitive; + } + + Var *baseColor = (Var*)LangElement::find("baseColor"); + ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget; + + if(fd.features.hasFeature( MFT_DeferredTerrainDetailMap )) + target= ShaderFeature::RenderTarget1; + + Var *outColor = (Var*)LangElement::find( getOutputTargetVarName(target) ); + + if (!outColor) + { + // create color var + outColor = new Var; + outColor->setType("float4"); + outColor->setName("col"); + outColor->setStructName("OUT"); + meta->addStatement(new GenOp(" @;\r\n", outColor)); + } + + Var *detailColor = (Var*)LangElement::find("detailColor"); + if (!detailColor) + { + detailColor = new Var; + detailColor->setType("float4"); + detailColor->setName("detailColor"); + meta->addStatement(new GenOp(" @;\r\n", new DecOp(detailColor))); + } + + // Get the detail texture. + Var *detailMap = new Var; + detailMap->setType("sampler2D"); + detailMap->setName(String::ToString("detailMap%d", detailIndex)); + detailMap->uniform = true; + detailMap->sampler = true; + detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here + + // Get the normal map texture. + Var *normalMap = _getNormalMapTex(); + + // Issue happens somewhere here ----- + + // Sample the normal map. + // + // We take two normal samples and lerp between them for + // side projection layers... else a single sample. + LangElement *texOp; + + // Note that we're doing the standard greyscale detail + // map technique here which can darken and lighten the + // diffuse texture. + // + // We take two color samples and lerp between them for + // side projection layers... else a single sample. + // + if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex)) + { + meta->addStatement(new GenOp(" @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n", + detailColor, detailMap, inDet, detailMap, inDet, inTex)); + + texOp = new GenOp("lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )", + normalMap, inDet, normalMap, inDet, inTex); + } + else + { + meta->addStatement(new GenOp(" @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n", + detailColor, detailMap, inDet)); + + texOp = new GenOp("tex2D(@, @.xy)", normalMap, inDet); + } + + // New terrain + // Get a var and accumulate the blend amount. Var *blendTotal = (Var*)LangElement::find( "blendTotal" ); if ( !blendTotal ) @@ -480,46 +594,6 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component } } - // If this is a prepass then we skip color. - if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) - { - // Check to see if we have a gbuffer normal. - Var *gbNormal = (Var*)LangElement::find( "gbNormal" ); - - // If we have a gbuffer normal and we don't have a - // normal map feature then we need to lerp in a - // default normal else the normals below this layer - // will show thru. - if ( gbNormal && - !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) ) - { - Var *viewToTangent = getInViewToTangent( componentList ); - - meta->addStatement( new GenOp( " @ = lerp( @, tGetMatrix3Row(@, 2), min( @, @.w ) );\r\n", - gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) ); - } - - output = meta; - return; - } - - Var *detailColor = (Var*)LangElement::find( "detailColor" ); - if ( !detailColor ) - { - detailColor = new Var; - detailColor->setType( "vec4" ); - detailColor->setName( "detailColor" ); - meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) ); - } - - // Get the detail texture. - Var *detailMap = new Var; - detailMap->setType( "sampler2D" ); - detailMap->setName( String::ToString( "detailMap%d", detailIndex ) ); - detailMap->uniform = true; - detailMap->sampler = true; - detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here - // If we're using SM 3.0 then take advantage of // dynamic branching to skip layers per-pixel. @@ -550,9 +624,6 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n", detailColor, detailInfo, inDet ) ); - Var *baseColor = (Var*)LangElement::find( "baseColor" ); - Var *outColor = (Var*)LangElement::find( "col" ); - meta->addStatement( new GenOp( " @ = lerp( @, @ + @, @ );\r\n", outColor, outColor, baseColor, detailColor, detailBlend ) ); @@ -578,9 +649,7 @@ ShaderFeature::Resources TerrainDetailMapFeatGLSL::getResources( const MaterialF res.numTexReg += 4; } - // If this isn't the prepass then we sample - // from the detail texture for diffuse coloring. - if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) + // sample from the detail texture for diffuse coloring. res.numTex += 1; // If we have parallax for this layer then we'll also @@ -595,6 +664,11 @@ ShaderFeature::Resources TerrainDetailMapFeatGLSL::getResources( const MaterialF return res; } +U32 TerrainDetailMapFeatGLSL::getOutputTargets( const MaterialFeatureData &fd ) const +{ + return fd.features[MFT_DeferredTerrainDetailMap] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; +} + TerrainMacroMapFeatGLSL::TerrainMacroMapFeatGLSL() : mTorqueDep( "shaders/common/gl/torque.glsl" ), @@ -609,7 +683,7 @@ TerrainMacroMapFeatGLSL::TerrainMacroMapFeatGLSL() void TerrainMacroMapFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); // Grab incoming texture coords... the base map feature // made sure this was created. @@ -667,7 +741,7 @@ void TerrainMacroMapFeatGLSL::processVert( Vector &componentL void TerrainMacroMapFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); Var *inTex = getVertTexCoord( "texCoord" ); MultiLine *meta = new MultiLine; @@ -752,29 +826,6 @@ void TerrainMacroMapFeatGLSL::processPix( Vector &componentL // Add to the blend total. meta->addStatement( new GenOp( " @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend ) ); - // If this is a prepass then we skip color. - if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) - { - // Check to see if we have a gbuffer normal. - Var *gbNormal = (Var*)LangElement::find( "gbNormal" ); - - // If we have a gbuffer normal and we don't have a - // normal map feature then we need to lerp in a - // default normal else the normals below this layer - // will show thru. - if ( gbNormal && - !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) ) - { - Var *viewToTangent = getInViewToTangent( componentList ); - - meta->addStatement( new GenOp( " @ = lerp( @, tGetMatrix3Row(@, 2), min( @, @.w ) );\r\n", - gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) ); - } - - output = meta; - return; - } - Var *detailColor = (Var*)LangElement::find( "macroColor" ); if ( !detailColor ) { @@ -819,8 +870,12 @@ void TerrainMacroMapFeatGLSL::processPix( Vector &componentL meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n", detailColor, detailInfo, inDet ) ); + ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget; - Var *outColor = (Var*)LangElement::find( "col" ); + if(fd.features.hasFeature(MFT_DeferredTerrainMacroMap)) + target= ShaderFeature::RenderTarget1; + + Var *outColor = (Var*)LangElement::find( getOutputTargetVarName(target) ); meta->addStatement( new GenOp( " @ = lerp( @, @ + @, @ );\r\n", outColor, outColor, outColor, detailColor, detailBlend ) ); @@ -843,9 +898,6 @@ ShaderFeature::Resources TerrainMacroMapFeatGLSL::getResources( const MaterialFe res.numTex += 1; } - // If this isn't the prepass then we sample - // from the detail texture for diffuse coloring. - if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) res.numTex += 1; // Finally we always send the detail texture @@ -855,6 +907,11 @@ ShaderFeature::Resources TerrainMacroMapFeatGLSL::getResources( const MaterialFe return res; } +U32 TerrainMacroMapFeatGLSL::getOutputTargets( const MaterialFeatureData &fd ) const +{ + return fd.features[MFT_DeferredTerrainMacroMap] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; +} + void TerrainNormalMapFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { @@ -874,9 +931,6 @@ void TerrainNormalMapFeatGLSL::processVert( Vector &component void TerrainNormalMapFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - // We only need to process normals during the prepass. - if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) - return; MultiLine *meta = new MultiLine; @@ -893,7 +947,7 @@ void TerrainNormalMapFeatGLSL::processPix( Vector &component meta->addStatement( new GenOp( " @ = tGetMatrix3Row(@, 2);\r\n", new DecOp( gbNormal ), viewToTangent ) ); } - const U32 normalIndex = getProcessIndex(); + const S32 normalIndex = getProcessIndex(); Var *detailBlend = (Var*)LangElement::find( String::ToString( "detailBlend%d", normalIndex ) ); AssertFatal( detailBlend, "The detail blend is missing!" ); @@ -1016,7 +1070,12 @@ ShaderFeature::Resources TerrainLightMapFeatGLSL::getResources( const MaterialFe void TerrainAdditiveFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - Var *color = (Var*) LangElement::find( "col" ); + Var *color = NULL; + if (fd.features[MFT_DeferredTerrainDetailMap]) + color = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ); + else + color = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::DefaultTarget) ); + Var *blendTotal = (Var*)LangElement::find( "blendTotal" ); if ( !color || !blendTotal ) return; @@ -1028,3 +1087,40 @@ void TerrainAdditiveFeatGLSL::processPix( Vector &componentLis output = meta; } + +//standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO), +//.b = specular strength, a= spec power. +//here, it's merely a cutout for now, so that lightmapping (target3) doesn't get mangled. +//we'll most likely revisit that later. possibly several ways... + +U32 TerrainBlankInfoMapFeatGLSL::getOutputTargets(const MaterialFeatureData &fd) const +{ + return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget2 : ShaderFeature::RenderTarget1; +} + +void TerrainBlankInfoMapFeatGLSL::processPix(Vector &componentList, + const MaterialFeatureData &fd) +{ + // search for material var + Var *material; + OutputTarget targ = RenderTarget1; + if (fd.features[MFT_isDeferred]) + { + targ = RenderTarget2; + } + material = (Var*)LangElement::find(getOutputTargetVarName(targ)); + + MultiLine * meta = new MultiLine; + if (!material) + { + // create color var + material = new Var; + material->setType("vec4"); + material->setName(getOutputTargetVarName(targ)); + material->setStructName("OUT"); + } + + meta->addStatement(new GenOp(" @ = float4(0.0,0.0,0.0,0.0001);\r\n", material)); + + output = meta; +} diff --git a/Engine/source/terrain/glsl/terrFeatureGLSL.h b/Engine/source/terrain/glsl/terrFeatureGLSL.h index 790a8a342..7839558b1 100644 --- a/Engine/source/terrain/glsl/terrFeatureGLSL.h +++ b/Engine/source/terrain/glsl/terrFeatureGLSL.h @@ -36,7 +36,10 @@ class TerrainFeatGLSL : public ShaderFeatureGLSL { protected: + ShaderIncludeDependency mTorqueDep; +public: + TerrainFeatGLSL(); Var* _getInDetailCoord(Vector &componentList ); Var* _getInMacroCoord(Vector &componentList ); @@ -64,6 +67,8 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); virtual String getName() { return "Terrain Base Texture"; } + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const; }; @@ -87,6 +92,8 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); virtual String getName() { return "Terrain Detail Texture"; } + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const; }; @@ -110,6 +117,8 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); virtual String getName() { return "Terrain Macro Texture"; } + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const; }; @@ -151,4 +160,15 @@ public: virtual String getName() { return "Terrain Additive"; } }; +class TerrainBlankInfoMapFeatGLSL : public ShaderFeatureGLSL +{ +public: + + virtual void processPix(Vector &componentList, + const MaterialFeatureData &fd); + + virtual U32 getOutputTargets(const MaterialFeatureData &fd) const; + virtual String getName() { return "Blank Matinfo map"; } +}; + #endif // _TERRFEATUREGLSL_H_ diff --git a/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp b/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp index 7190d7f82..b0e16bb64 100644 --- a/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp +++ b/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp @@ -26,6 +26,7 @@ #include "terrain/terrFeatureTypes.h" #include "materials/materialFeatureTypes.h" #include "materials/materialFeatureData.h" +#include "materials/processedMaterial.h" #include "gfx/gfxDevice.h" #include "shaderGen/langElement.h" #include "shaderGen/shaderOp.h" @@ -47,9 +48,12 @@ namespace FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new TerrainMacroMapFeatHLSL ); FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatHLSL ); FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureHLSL( "Terrain Side Projection" ) ); - FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatHLSL ); + FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatHLSL ); + FEATUREMGR->registerFeature( MFT_DeferredTerrainBaseMap, new TerrainBaseMapFeatHLSL ); + FEATUREMGR->registerFeature( MFT_DeferredTerrainMacroMap, new TerrainMacroMapFeatHLSL ); + FEATUREMGR->registerFeature( MFT_DeferredTerrainDetailMap, new TerrainDetailMapFeatHLSL ); + FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatHLSL ); } - }; MODULE_BEGIN( TerrainFeatHLSL ) @@ -64,6 +68,12 @@ MODULE_BEGIN( TerrainFeatHLSL ) MODULE_END; +TerrainFeatHLSL::TerrainFeatHLSL() + : mTorqueDep( "shaders/common/torque.hlsl" ) + { + addDependency( &mTorqueDep ); + } + Var* TerrainFeatHLSL::_getUniformVar( const char *name, const char *type, ConstantSortPosition csp ) { Var *theVar = (Var*)LangElement::find( name ); @@ -244,10 +254,6 @@ void TerrainBaseMapFeatHLSL::processPix( Vector &componentLis // grab connector texcoord register Var *texCoord = getInTexCoord( "texCoord", "float3", true, componentList ); - // We do nothing more if this is a prepass. - if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) - return; - // create texture var Var *diffuseMap = new Var; diffuseMap->setType( "sampler2D" ); @@ -262,8 +268,16 @@ void TerrainBaseMapFeatHLSL::processPix( Vector &componentLis baseColor->setType( "float4" ); baseColor->setName( "baseColor" ); meta->addStatement( new GenOp( " @ = tex2D( @, @.xy );\r\n", new DecOp( baseColor ), diffuseMap, texCoord ) ); - meta->addStatement( new GenOp( " @;\r\n", assignColor( baseColor, Material::Mul ) ) ); + meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", baseColor, baseColor)); + ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget; + + if (fd.features.hasFeature(MFT_isDeferred)) + { + target= ShaderFeature::RenderTarget1; + } + + meta->addStatement( new GenOp( " @;\r\n", assignColor( baseColor, Material::Mul,NULL,target ) ) ); output = meta; } @@ -271,14 +285,16 @@ ShaderFeature::Resources TerrainBaseMapFeatHLSL::getResources( const MaterialFea { Resources res; res.numTexReg = 1; - - // We only sample from the base map during a diffuse pass. - if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) res.numTex = 1; return res; } +U32 TerrainBaseMapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const +{ + return fd.features[MFT_DeferredTerrainBaseMap] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; +} + TerrainDetailMapFeatHLSL::TerrainDetailMapFeatHLSL() : mTorqueDep( "shaders/common/torque.hlsl" ), mTerrainDep( "shaders/common/terrain/terrain.hlsl" ) @@ -291,7 +307,7 @@ TerrainDetailMapFeatHLSL::TerrainDetailMapFeatHLSL() void TerrainDetailMapFeatHLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); // Grab incoming texture coords... the base map feature // made sure this was created. @@ -376,7 +392,7 @@ void TerrainDetailMapFeatHLSL::processVert( Vector &component void TerrainDetailMapFeatHLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); Var *inTex = getVertTexCoord( "texCoord" ); MultiLine *meta = new MultiLine; @@ -470,7 +486,7 @@ void TerrainDetailMapFeatHLSL::processPix( Vector &component // Call the library function to do the rest. if(fd.features.hasFeature( MFT_IsDXTnm, detailIndex ) ) { - meta->addStatement( new GenOp( " @.xy += parallaxOffsetDxtnm( @, @.xy, @, @.z * @ );\r\n", + meta->addStatement( new GenOp( " @.xy += parallaxOffsetDxtnm( @, @.xy, @, @.z * @ );\r\n", inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend ) ); } else @@ -480,29 +496,6 @@ void TerrainDetailMapFeatHLSL::processPix( Vector &component } } - // If this is a prepass then we skip color. - if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) - { - // Check to see if we have a gbuffer normal. - Var *gbNormal = (Var*)LangElement::find( "gbNormal" ); - - // If we have a gbuffer normal and we don't have a - // normal map feature then we need to lerp in a - // default normal else the normals below this layer - // will show thru. - if ( gbNormal && - !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) ) - { - Var *viewToTangent = getInViewToTangent( componentList ); - - meta->addStatement( new GenOp( " @ = lerp( @, @[2], min( @, @.w ) );\r\n", - gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) ); - } - - output = meta; - return; - } - Var *detailColor = (Var*)LangElement::find( "detailColor" ); if ( !detailColor ) { @@ -536,21 +529,35 @@ void TerrainDetailMapFeatHLSL::processPix( Vector &component // We take two color samples and lerp between them for // side projection layers... else a single sample. // + + //Sampled detail texture that is not expanded + Var *detailTex = new Var; + detailTex->setType("float4"); + detailTex->setName("detailTex"); + meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailTex ) ) ); + if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) ) { - meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n", - detailColor, detailMap, inDet, detailMap, inDet, inTex ) ); + meta->addStatement( new GenOp(" @ = lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z);\r\n",detailTex,detailMap,inDet,detailMap,inDet,inTex)); + meta->addStatement( new GenOp( " @ = ( @ * 2.0 ) - 1.0;\r\n", detailColor, detailTex) ); } else { - meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n", - detailColor, detailMap, inDet ) ); + meta->addStatement( new GenOp(" @ = tex2D(@,@.xy);\r\n",detailTex,detailMap,inDet)); + meta->addStatement( new GenOp( " @ = ( @ * 2.0 ) - 1.0;\r\n", + detailColor, detailTex) ); } meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n", detailColor, detailInfo, inDet ) ); - Var *outColor = (Var*)LangElement::find( "col" ); + Var *baseColor = (Var*)LangElement::find( "baseColor" ); + ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget; + + if(fd.features.hasFeature( MFT_DeferredTerrainDetailMap )) + target= ShaderFeature::RenderTarget1; + + Var *outColor = (Var*)LangElement::find( getOutputTargetVarName(target) ); meta->addStatement( new GenOp( " @ += @ * @;\r\n", outColor, detailColor, detailBlend)); @@ -577,9 +584,7 @@ ShaderFeature::Resources TerrainDetailMapFeatHLSL::getResources( const MaterialF res.numTexReg += 4; } - // If this isn't the prepass then we sample - // from the detail texture for diffuse coloring. - if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) + // sample from the detail texture for diffuse coloring. res.numTex += 1; // If we have parallax for this layer then we'll also @@ -594,6 +599,11 @@ ShaderFeature::Resources TerrainDetailMapFeatHLSL::getResources( const MaterialF return res; } +U32 TerrainDetailMapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const +{ + return fd.features[MFT_DeferredTerrainDetailMap] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; +} + TerrainMacroMapFeatHLSL::TerrainMacroMapFeatHLSL() : mTorqueDep( "shaders/common/torque.hlsl" ), @@ -608,7 +618,7 @@ TerrainMacroMapFeatHLSL::TerrainMacroMapFeatHLSL() void TerrainMacroMapFeatHLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); // Grab incoming texture coords... the base map feature // made sure this was created. @@ -666,7 +676,7 @@ void TerrainMacroMapFeatHLSL::processVert( Vector &componentL void TerrainMacroMapFeatHLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - const U32 detailIndex = getProcessIndex(); + const S32 detailIndex = getProcessIndex(); Var *inTex = getVertTexCoord( "texCoord" ); MultiLine *meta = new MultiLine; @@ -751,29 +761,6 @@ void TerrainMacroMapFeatHLSL::processPix( Vector &componentL // Add to the blend total. meta->addStatement( new GenOp( " @ += @;\r\n", blendTotal, detailBlend ) ); - // If this is a prepass then we skip color. - if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) - { - // Check to see if we have a gbuffer normal. - Var *gbNormal = (Var*)LangElement::find( "gbNormal" ); - - // If we have a gbuffer normal and we don't have a - // normal map feature then we need to lerp in a - // default normal else the normals below this layer - // will show thru. - if ( gbNormal && - !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) ) - { - Var *viewToTangent = getInViewToTangent( componentList ); - - meta->addStatement( new GenOp( " @ = lerp( @, @[2], min( @, @.w ) );\r\n", - gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) ); - } - - output = meta; - return; - } - Var *detailColor = (Var*)LangElement::find( "macroColor" ); if ( !detailColor ) { @@ -819,8 +806,14 @@ void TerrainMacroMapFeatHLSL::processPix( Vector &componentL meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n", detailColor, detailInfo, inDet ) ); - //Var *baseColor = (Var*)LangElement::find( "baseColor" ); - Var *outColor = (Var*)LangElement::find( "col" ); + Var *baseColor = (Var*)LangElement::find( "baseColor" ); + + ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget; + + if(fd.features.hasFeature(MFT_DeferredTerrainMacroMap)) + target= ShaderFeature::RenderTarget1; + + Var *outColor = (Var*)LangElement::find( getOutputTargetVarName(target) ); meta->addStatement(new GenOp(" @ += @ * @;\r\n", outColor, detailColor, detailBlend)); @@ -830,8 +823,6 @@ void TerrainMacroMapFeatHLSL::processPix( Vector &componentL output = meta; } - - ShaderFeature::Resources TerrainMacroMapFeatHLSL::getResources( const MaterialFeatureData &fd ) { Resources res; @@ -843,9 +834,6 @@ ShaderFeature::Resources TerrainMacroMapFeatHLSL::getResources( const MaterialFe res.numTex += 1; } - // If this isn't the prepass then we sample - // from the detail texture for diffuse coloring. - if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) res.numTex += 1; // Finally we always send the detail texture @@ -855,6 +843,11 @@ ShaderFeature::Resources TerrainMacroMapFeatHLSL::getResources( const MaterialFe return res; } +U32 TerrainMacroMapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const +{ + return fd.features[MFT_DeferredTerrainMacroMap] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; +} + void TerrainNormalMapFeatHLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { @@ -874,9 +867,6 @@ void TerrainNormalMapFeatHLSL::processVert( Vector &component void TerrainNormalMapFeatHLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - // We only need to process normals during the prepass. - if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) - return; MultiLine *meta = new MultiLine; @@ -893,7 +883,7 @@ void TerrainNormalMapFeatHLSL::processPix( Vector &component meta->addStatement( new GenOp( " @ = @[2];\r\n", new DecOp( gbNormal ), viewToTangent ) ); } - const U32 normalIndex = getProcessIndex(); + const S32 normalIndex = getProcessIndex(); Var *detailBlend = (Var*)LangElement::find( String::ToString( "detailBlend%d", normalIndex ) ); AssertFatal( detailBlend, "The detail blend is missing!" ); @@ -1012,11 +1002,15 @@ ShaderFeature::Resources TerrainLightMapFeatHLSL::getResources( const MaterialFe return res; } - void TerrainAdditiveFeatHLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - Var *color = (Var*) LangElement::find( "col" ); + Var *color = NULL; + if (fd.features[MFT_DeferredTerrainDetailMap]) + color = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ); + else + color = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::DefaultTarget) ); + Var *blendTotal = (Var*)LangElement::find( "blendTotal" ); if ( !color || !blendTotal ) return; @@ -1026,5 +1020,43 @@ void TerrainAdditiveFeatHLSL::processPix( Vector &componentLis meta->addStatement( new GenOp( " clip( @ - 0.0001 );\r\n", blendTotal ) ); meta->addStatement( new GenOp( " @.a = @;\r\n", color, blendTotal ) ); + + output = meta; +} + +//standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO), +//.b = specular strength, a= spec power. +//here, it's merely a cutout for now, so that lightmapping (target3) doesn't get mangled. +//we'll most likely revisit that later. possibly several ways... + +U32 TerrainBlankInfoMapFeatHLSL::getOutputTargets(const MaterialFeatureData &fd) const +{ + return fd.features[MFT_DeferredTerrainBaseMap] ? ShaderFeature::RenderTarget2 : ShaderFeature::RenderTarget1; +} + +void TerrainBlankInfoMapFeatHLSL::processPix(Vector &componentList, + const MaterialFeatureData &fd) +{ + // search for material var + Var *material; + OutputTarget targ = RenderTarget1; + if (fd.features[MFT_isDeferred]) + { + targ = RenderTarget2; + } + material = (Var*)LangElement::find(getOutputTargetVarName(targ)); + + MultiLine * meta = new MultiLine; + if (!material) + { + // create color var + material = new Var; + material->setType("fragout"); + material->setName(getOutputTargetVarName(targ)); + material->setStructName("OUT"); + } + + meta->addStatement(new GenOp(" @ = float4(0.0,0.0,0.0,0.0001);\r\n", material)); + output = meta; } diff --git a/Engine/source/terrain/hlsl/terrFeatureHLSL.h b/Engine/source/terrain/hlsl/terrFeatureHLSL.h index 85f75a29e..2effbdc36 100644 --- a/Engine/source/terrain/hlsl/terrFeatureHLSL.h +++ b/Engine/source/terrain/hlsl/terrFeatureHLSL.h @@ -37,6 +37,10 @@ class TerrainFeatHLSL : public ShaderFeatureHLSL { protected: + ShaderIncludeDependency mTorqueDep; + +public: + TerrainFeatHLSL(); Var* _getInDetailCoord(Vector &componentList ); Var* _getInMacroCoord(Vector &componentList ); @@ -64,6 +68,8 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); virtual String getName() { return "Terrain Base Texture"; } + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const; }; @@ -87,6 +93,8 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); virtual String getName() { return "Terrain Detail Texture"; } + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const; }; @@ -110,6 +118,8 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); virtual String getName() { return "Terrain Macro Texture"; } + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const; }; @@ -151,4 +161,15 @@ public: virtual String getName() { return "Terrain Additive"; } }; +class TerrainBlankInfoMapFeatHLSL : public TerrainFeatHLSL +{ +public: + + virtual void processPix(Vector &componentList, + const MaterialFeatureData &fd); + + virtual U32 getOutputTargets(const MaterialFeatureData &fd) const; + virtual String getName() { return "Blank Matinfo map"; } +}; + #endif // _TERRFEATUREHLSL_H_ diff --git a/Engine/source/terrain/terrCellMaterial.cpp b/Engine/source/terrain/terrCellMaterial.cpp index 101c21f0c..3b96a1318 100644 --- a/Engine/source/terrain/terrCellMaterial.cpp +++ b/Engine/source/terrain/terrCellMaterial.cpp @@ -37,6 +37,7 @@ #include "gfx/util/screenspace.h" #include "lighting/advanced/advancedLightBinManager.h" +S32 sgMaxTerrainMaterialsPerPass = 3; AFTER_MODULE_INIT( MaterialManager ) { @@ -310,12 +311,12 @@ bool TerrainCellMaterial::_createPass( Vector *materials, if ( GFX->getPixelShaderVersion() < 3.0f ) baseOnly = true; - // NOTE: At maximum we only try to combine 3 materials + // NOTE: At maximum we only try to combine sgMaxTerrainMaterialsPerPass materials // into a single pass. This is sub-optimal for the simplest // cases, but the most common case results in much fewer // shader generation failures and permutations leading to // faster load time and less hiccups during gameplay. - U32 matCount = getMin( 3, materials->size() ); + U32 matCount = getMin( sgMaxTerrainMaterialsPerPass, materials->size() ); Vector normalMaps; @@ -349,24 +350,27 @@ bool TerrainCellMaterial::_createPass( Vector *materials, { FeatureSet features; features.addFeature( MFT_VertTransform ); - features.addFeature( MFT_TerrainBaseMap ); if ( prePassMat ) { features.addFeature( MFT_EyeSpaceDepthOut ); features.addFeature( MFT_PrePassConditioner ); + features.addFeature( MFT_DeferredTerrainBaseMap ); + features.addFeature(MFT_isDeferred); if ( advancedLightmapSupport ) - features.addFeature( MFT_RenderTarget1_Zero ); + features.addFeature( MFT_RenderTarget3_Zero ); } else { + features.addFeature( MFT_TerrainBaseMap ); features.addFeature( MFT_RTLighting ); // The HDR feature is always added... it will compile out // if HDR is not enabled in the engine. features.addFeature( MFT_HDROut ); } + features.addFeature(MFT_DeferredTerrainBlankInfoMap); // Enable lightmaps and fogging if we're in BL. if ( reflectMat || useBLM ) @@ -405,8 +409,16 @@ bool TerrainCellMaterial::_createPass( Vector *materials, // check for macro detail texture if ( !(mat->getMacroSize() <= 0 || mat->getMacroDistance() <= 0 || mat->getMacroMap().isEmpty() ) ) + { + if(prePassMat) + features.addFeature( MFT_DeferredTerrainMacroMap, featureIndex ); + else features.addFeature( MFT_TerrainMacroMap, featureIndex ); + } + if(prePassMat) + features.addFeature( MFT_DeferredTerrainDetailMap, featureIndex ); + else features.addFeature( MFT_TerrainDetailMap, featureIndex ); pass->materials.push_back( (*materials)[i] ); @@ -536,8 +548,8 @@ bool TerrainCellMaterial::_createPass( Vector *materials, // MFT_TerrainAdditive feature to lerp the // output normal with the previous pass. // - if ( prePassMat ) - desc.setColorWrites( true, true, false, false ); + //if ( prePassMat ) + //desc.setColorWrites( true, true, false, false ); } // We write to the zbuffer if this is a prepass @@ -656,9 +668,9 @@ bool TerrainCellMaterial::_createPass( Vector *materials, if ( prePassMat ) desc.addDesc( RenderPrePassMgr::getOpaqueStenciWriteDesc( false ) ); - // Flip the cull for reflection materials. - if ( reflectMat ) - desc.setCullMode( GFXCullCW ); + // Shut off culling for prepass materials (reflection support). + if ( prePassMat ) + desc.setCullMode( GFXCullNone ); pass->stateBlock = GFX->createStateBlock( desc ); diff --git a/Engine/source/terrain/terrFeatureTypes.cpp b/Engine/source/terrain/terrFeatureTypes.cpp index b65085916..5eb8ff0e0 100644 --- a/Engine/source/terrain/terrFeatureTypes.cpp +++ b/Engine/source/terrain/terrFeatureTypes.cpp @@ -34,4 +34,8 @@ ImplementFeatureType( MFT_TerrainMacroMap, MFG_Texture, 104.0f, false ); ImplementFeatureType( MFT_TerrainLightMap, MFG_Texture, 105.0f, false ); ImplementFeatureType( MFT_TerrainSideProject, MFG_Texture, 106.0f, false ); ImplementFeatureType( MFT_TerrainAdditive, MFG_PostProcess, 999.0f, false ); - +//Deferred Shading +ImplementFeatureType( MFT_DeferredTerrainBaseMap, MFG_Texture, 100.1f, false ); +ImplementFeatureType( MFT_DeferredTerrainDetailMap, MFG_Texture, 102.1f, false ); +ImplementFeatureType( MFT_DeferredTerrainMacroMap, MFG_Texture, 104.1f, false ); +ImplementFeatureType( MFT_DeferredTerrainBlankInfoMap, MFG_Texture, 104.1f, false); diff --git a/Engine/source/terrain/terrFeatureTypes.h b/Engine/source/terrain/terrFeatureTypes.h index 0d2826da9..6246c5fa6 100644 --- a/Engine/source/terrain/terrFeatureTypes.h +++ b/Engine/source/terrain/terrFeatureTypes.h @@ -35,6 +35,12 @@ DeclareFeatureType( MFT_TerrainParallaxMap ); DeclareFeatureType( MFT_TerrainLightMap ); DeclareFeatureType( MFT_TerrainSideProject ); DeclareFeatureType( MFT_TerrainAdditive ); +//Deferred Shading +DeclareFeatureType( MFT_DeferredTerrainBaseMap ); +DeclareFeatureType( MFT_DeferredTerrainDetailMap ); +DeclareFeatureType( MFT_DeferredTerrainMacroMap ); +DeclareFeatureType( MFT_DeferredTerrainBlankInfoMap ); + #endif // _TERRFEATURETYPES_H_ diff --git a/Engine/source/ts/collada/colladaAppMesh.h b/Engine/source/ts/collada/colladaAppMesh.h index 17ac1cad1..72c16e56d 100644 --- a/Engine/source/ts/collada/colladaAppMesh.h +++ b/Engine/source/ts/collada/colladaAppMesh.h @@ -24,7 +24,7 @@ #define _COLLADA_APPMESH_H_ #ifndef _TDICTIONARY_H_ -#include "core/tDictionary.h" +#include "core/util/tDictionary.h" #endif #ifndef _APPMESH_H_ #include "ts/loader/appMesh.h" diff --git a/Engine/source/ts/collada/colladaAppNode.h b/Engine/source/ts/collada/colladaAppNode.h index 472ec505c..f633e7be6 100644 --- a/Engine/source/ts/collada/colladaAppNode.h +++ b/Engine/source/ts/collada/colladaAppNode.h @@ -24,7 +24,7 @@ #define _COLLADA_APPNODE_H_ #ifndef _TDICTIONARY_H_ -#include "core/tDictionary.h" +#include "core/util/tDictionary.h" #endif #ifndef _APPNODE_H_ #include "ts/loader/appNode.h" diff --git a/Engine/source/ts/tsShapeInstance.cpp b/Engine/source/ts/tsShapeInstance.cpp index 821e02dba..03b8c79c3 100644 --- a/Engine/source/ts/tsShapeInstance.cpp +++ b/Engine/source/ts/tsShapeInstance.cpp @@ -593,7 +593,7 @@ S32 TSShapeInstance::setDetailFromDistance( const SceneRenderState *state, F32 s // 4:3 aspect ratio, we've changed the reference value // to 300 to be more compatible with legacy shapes. // - const F32 pixelScale = state->getViewport().extent.y / 300.0f; + const F32 pixelScale = (state->getViewport().extent.x / state->getViewport().extent.y); // This is legacy DTS support for older "multires" based // meshes. The original crossbow weapon uses this. diff --git a/Engine/source/util/catmullRom.cpp b/Engine/source/util/catmullRom.cpp index 10452c18c..7ac676a15 100644 --- a/Engine/source/util/catmullRom.cpp +++ b/Engine/source/util/catmullRom.cpp @@ -48,7 +48,7 @@ CatmullRomBase::CatmullRomBase() void CatmullRomBase::_initialize( U32 count, const F32 *times ) { //AssertFatal( times, "CatmullRomBase::_initialize() - Got null position!" ) - AssertFatal( count > 1, "CatmullRomBase::_initialize() - Must have more than 2 points!" ) + AssertFatal( count > 1, "CatmullRomBase::_initialize() - Must have more than 2 points!" ); // set up arrays mTimes = new F32[count]; diff --git a/Engine/source/util/catmullRom.h b/Engine/source/util/catmullRom.h index f4c9decb0..84bb272aa 100644 --- a/Engine/source/util/catmullRom.h +++ b/Engine/source/util/catmullRom.h @@ -142,8 +142,8 @@ inline void CatmullRom::clear() template inline void CatmullRom::initialize( U32 count, const TYPE *positions, const F32 *times ) { - AssertFatal( positions, "CatmullRom::initialize - Got null position!" ) - AssertFatal( count > 1, "CatmullRom::initialize - Must have more than 2 points!" ) + AssertFatal( positions, "CatmullRom::initialize - Got null position!" ); + AssertFatal( count > 1, "CatmullRom::initialize - Must have more than 2 points!" ); // Clean up any previous state. clear(); diff --git a/Engine/source/util/imposterCapture.cpp b/Engine/source/util/imposterCapture.cpp index fb0786390..f6bcba23f 100644 --- a/Engine/source/util/imposterCapture.cpp +++ b/Engine/source/util/imposterCapture.cpp @@ -136,6 +136,7 @@ void ImposterCaptureMaterialHook::_overrideFeatures( ProcessedMaterial *mat, fd.features.addFeature( MFT_NormalsOut ); fd.features.addFeature( MFT_ForwardShading ); + fd.features.addFeature( MFT_Imposter ); } ImposterCaptureMaterialHook* ImposterCaptureMaterialHook::_getOrCreateHook( BaseMatInstance *inMat ) diff --git a/Engine/source/windowManager/platformWindow.cpp b/Engine/source/windowManager/platformWindow.cpp index 8a7ad65fb..b11ac0bb7 100644 --- a/Engine/source/windowManager/platformWindow.cpp +++ b/Engine/source/windowManager/platformWindow.cpp @@ -22,7 +22,7 @@ #include "windowManager/platformWindow.h" - +ScreenResChangeSignal PlatformWindow::smScreenResChangeSignal; //----------------------------------------------------------------------------- void PlatformWindow::setFullscreen( const bool fullscreen ) @@ -48,3 +48,8 @@ bool PlatformWindow::shouldNotTranslate( U32 modifiers, U32 keyCode ) const else return false; } +void PlatformWindow::setVideoMode(const GFXVideoMode &mode) +{ + _setVideoMode(mode); + getScreenResChangeSignal().trigger(this, true); +} \ No newline at end of file diff --git a/Engine/source/windowManager/platformWindow.h b/Engine/source/windowManager/platformWindow.h index 6db7ce423..df1b51595 100644 --- a/Engine/source/windowManager/platformWindow.h +++ b/Engine/source/windowManager/platformWindow.h @@ -28,6 +28,9 @@ #include "core/util/safeDelete.h" #include "windowManager/platformCursorController.h" #include "windowManager/windowInputGenerator.h" +#ifndef _SIGNAL_H_ //Volumetric Fog +#include "core/util/tSignal.h" +#endif //forward decl's class PlatformWindowManager; @@ -35,7 +38,7 @@ class GFXDevice; struct GFXVideoMode; class GFXWindowTarget; class IProcessInput; - +typedef Signal ScreenResChangeSignal; /// Abstract representation of a native OS window. /// /// Every windowing system has its own representations and conventions as @@ -110,7 +113,7 @@ protected: // This controller maps window input (Mouse/Keyboard) to a generic input consumer mWindowInputGenerator = new WindowInputGenerator( this ); } - + static ScreenResChangeSignal smScreenResChangeSignal; public: /// To get rid of a window, just delete it. Make sure the GFXDevice is @@ -158,7 +161,7 @@ public: virtual GFXWindowTarget *getGFXTarget()=0; /// Set the video mode for this window. - virtual void setVideoMode(const GFXVideoMode &mode)=0; + virtual void setVideoMode(const GFXVideoMode &mode); /// Get our current video mode - if the window has been resized, it will /// reflect this. @@ -497,6 +500,7 @@ public: IdleEvent idleEvent; /// @} + static ScreenResChangeSignal& getScreenResChangeSignal() { return smScreenResChangeSignal; } /// Get the platform specific object needed to create or attach an accelerated /// graohics drawing context on or to the window @@ -507,6 +511,7 @@ public: virtual void* getPlatformDrawable() const = 0; protected: virtual void _setFullscreen(const bool fullScreen) {}; + virtual void _setVideoMode(const GFXVideoMode &mode) {}; }; #endif diff --git a/Engine/source/windowManager/win32/win32Window.cpp b/Engine/source/windowManager/win32/win32Window.cpp index 88be80cf1..c714586b9 100644 --- a/Engine/source/windowManager/win32/win32Window.cpp +++ b/Engine/source/windowManager/win32/win32Window.cpp @@ -26,8 +26,10 @@ #include #include #include "math/mMath.h" +#include "gfx/gfxDevice.h" #include "gfx/gfxStructs.h" +#include "windowManager/platformWindowMgr.h" #include "windowManager/win32/win32Window.h" #include "windowManager/win32/win32WindowMgr.h" #include "windowManager/win32/win32CursorController.h" @@ -39,11 +41,6 @@ // for winState structure #include "platformWin32/platformWin32.h" -#include -#include "gfx/gfxDevice.h" - -#include - const UTF16* _MainWindowClassName = L"TorqueJuggernaughtWindow"; const UTF16* _CurtainWindowClassName = L"TorqueJuggernaughtCurtainWindow"; @@ -148,96 +145,93 @@ const GFXVideoMode & Win32Window::getVideoMode() void Win32Window::setVideoMode( const GFXVideoMode &mode ) { - bool needCurtain = (mVideoMode.fullScreen != mode.fullScreen); + bool needCurtain = ( mVideoMode.fullScreen != mode.fullScreen ); - if(needCurtain) + if( needCurtain ) { - Con::errorf("Win32Window::setVideoMode - invoking curtain"); + Con::printf( "Win32Window::setVideoMode - invoking curtain" ); mOwningManager->lowerCurtain(); } - mVideoMode = mode; - mSuppressReset = true; + mVideoMode = mode; + mSuppressReset = true; // Can't switch to fullscreen while a child of another window - if(mode.fullScreen && !Platform::getWebDeployment() && mOwningManager->getParentWindow()) + if( mode.fullScreen && !Platform::getWebDeployment() && mOwningManager->getParentWindow() ) { - mOldParent = (HWND)mOwningManager->getParentWindow(); - mOwningManager->setParentWindow(NULL); + mOldParent = reinterpret_cast( mOwningManager->getParentWindow() ); + mOwningManager->setParentWindow( NULL ); } - else if(!mode.fullScreen && mOldParent) + else if( !mode.fullScreen && mOldParent ) { - mOwningManager->setParentWindow(mOldParent); + mOwningManager->setParentWindow( mOldParent ); mOldParent = NULL; } - // Set our window to have the right style based on the mode - if(mode.fullScreen && !Platform::getWebDeployment() && !mOffscreenRender) + // Set our window to have the right style based on the mode + if( mode.fullScreen && !Platform::getWebDeployment() && !mOffscreenRender ) { - WINDOWPLACEMENT wplacement = { sizeof(wplacement) }; - DWORD dwStyle = GetWindowLong(getHWND(), GWL_STYLE); - MONITORINFO mi = { sizeof(mi) }; + WINDOWPLACEMENT wplacement = { sizeof( wplacement ) }; + DWORD dwStyle = GetWindowLong( getHWND(), GWL_STYLE ); + MONITORINFO mi = { sizeof(mi) }; - if (GetWindowPlacement(getHWND(), &wplacement) && GetMonitorInfo(MonitorFromWindow(getHWND(), MONITOR_DEFAULTTOPRIMARY), &mi)) - { - DISPLAY_DEVICE dd = GetPrimaryDevice(); - DEVMODE dv; - ZeroMemory(&dv, sizeof(dv)); - dv.dmSize = sizeof(DEVMODE); - EnumDisplaySettings(dd.DeviceName, ENUM_CURRENT_SETTINGS, &dv); - dv.dmPelsWidth = mode.resolution.x; - dv.dmPelsHeight = mode.resolution.y; - dv.dmBitsPerPel = mode.bitDepth; - dv.dmDisplayFrequency = mode.refreshRate; - dv.dmFields = (DM_PELSWIDTH | DM_PELSHEIGHT); - ChangeDisplaySettings(&dv, CDS_FULLSCREEN); - SetWindowLong(getHWND(), GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW); - SetWindowPos(getHWND(), HWND_TOP, - mi.rcMonitor.left, - mi.rcMonitor.top, - mi.rcMonitor.right - mi.rcMonitor.left, - mi.rcMonitor.bottom - mi.rcMonitor.top, - SWP_NOOWNERZORDER | SWP_FRAMECHANGED); - } - - if(mDisplayWindow) - ShowWindow(getHWND(), SW_SHOWNORMAL); - - // Clear the menu bar from the window for full screen - HMENU menu = GetMenu(getHWND()); - if(menu) + if ( GetWindowPlacement( getHWND(), &wplacement ) && GetMonitorInfo( MonitorFromWindow( getHWND(), MONITOR_DEFAULTTOPRIMARY ), &mi ) ) { - SetMenu(getHWND(), NULL); + DISPLAY_DEVICE dd = GetPrimaryDevice(); + DEVMODE dv; + ZeroMemory( &dv, sizeof( dv ) ); + dv.dmSize = sizeof( DEVMODE ); + EnumDisplaySettings( dd.DeviceName, ENUM_CURRENT_SETTINGS, &dv ); + dv.dmPelsWidth = mode.resolution.x; + dv.dmPelsHeight = mode.resolution.y; + dv.dmBitsPerPel = mode.bitDepth; + dv.dmDisplayFrequency = mode.refreshRate; + dv.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; + ChangeDisplaySettings( &dv, CDS_FULLSCREEN ); + SetWindowLong( getHWND(), GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW ); + SetWindowPos( getHWND(), HWND_TOP, mi.rcMonitor.left, + mi.rcMonitor.top, + mi.rcMonitor.right - mi.rcMonitor.left, + mi.rcMonitor.bottom - mi.rcMonitor.top, + SWP_NOOWNERZORDER | SWP_FRAMECHANGED ); } + if( mDisplayWindow ) + ShowWindow( getHWND(), SW_SHOWNORMAL ); + + // Clear the menu bar from the window for full screen + if( GetMenu( getHWND() ) ) + SetMenu( getHWND(), NULL ); + // When switching to Fullscreen, reset device after setting style - if(mTarget.isValid()) - mTarget->resetMode(); + if( mTarget.isValid() ) + mTarget->resetMode(); mFullscreen = true; - } - else - { - DISPLAY_DEVICE dd = GetPrimaryDevice(); - DEVMODE dv; - ZeroMemory(&dv, sizeof(dv)); - dv.dmSize = sizeof(DEVMODE); - EnumDisplaySettings(dd.DeviceName, ENUM_CURRENT_SETTINGS, &dv); + } + else + { + DISPLAY_DEVICE dd = GetPrimaryDevice(); + DEVMODE dv; + ZeroMemory( &dv, sizeof( dv ) ); + dv.dmSize = sizeof( DEVMODE ); + EnumDisplaySettings( dd.DeviceName, ENUM_CURRENT_SETTINGS, &dv ); - if ((mode.resolution.x != dv.dmPelsWidth) || (mode.resolution.y != dv.dmPelsHeight)) - ChangeDisplaySettings(NULL, 0); + if ( ( WindowManager->getDesktopResolution() != mode.resolution || + ( mode.resolution.x != dv.dmPelsWidth ) || ( mode.resolution.y != dv.dmPelsHeight ) ) ) + ChangeDisplaySettings( NULL, 0 ); - // Reset device *first*, so that when we call setSize() and let it - // access the monitor settings, it won't end up with our fullscreen - // geometry that is just about to change. + // Reset device *first*, so that when we call setSize() and let it + // access the monitor settings, it won't end up with our fullscreen + // geometry that is just about to change. - if(mTarget.isValid()) - mTarget->resetMode(); + if( mTarget.isValid() ) + mTarget->resetMode(); - if (!mOffscreenRender) + if ( !mOffscreenRender ) { - SetWindowLong( getHWND(), GWL_STYLE, mWindowedWindowStyle); - SetWindowPos( getHWND(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + SetWindowLong( getHWND(), GWL_STYLE, mWindowedWindowStyle); + SetWindowPos( getHWND(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); // Put back the menu bar, if any if(mMenuHandle) @@ -253,40 +247,37 @@ void Win32Window::setVideoMode( const GFXVideoMode &mode ) } else { - HWND parentWin = (HWND)mOwningManager->getParentWindow(); + HWND parentWin = reinterpret_cast( mOwningManager->getParentWindow() ); RECT windowRect; - GetClientRect(parentWin, &windowRect); - Point2I res(windowRect.right-windowRect.left, windowRect.bottom-windowRect.top); - if (res.x == 0 || res.y == 0) - { - // Must be too early in the window set up to obtain the parent's size. - setSize(mode.resolution); - } + GetClientRect( parentWin, &windowRect ); + Point2I res( windowRect.right - windowRect.left, windowRect.bottom - windowRect.top ); + + if ( res.x == 0 || res.y == 0 ) + setSize( mode.resolution ); // Must be too early in the window set up to obtain the parent's size. else - { - setSize(res); - } + setSize( res ); } - if (!mOffscreenRender) + if ( !mOffscreenRender ) { - // We have to force Win32 to update the window frame and make the window - // visible and no longer topmost - this code might be possible to simplify. - SetWindowPos( getHWND(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + // We have to force Win32 to update the window frame and make the window + // visible and no longer topmost - this code might be possible to simplify. + SetWindowPos( getHWND(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED ); if(mDisplayWindow) - ShowWindow( getHWND(), SW_SHOWNORMAL); + ShowWindow( getHWND(), SW_SHOWNORMAL ); } mFullscreen = false; - } + } - mSuppressReset = false; + mSuppressReset = false; - if(needCurtain) - mOwningManager->raiseCurtain(); + if( needCurtain ) + mOwningManager->raiseCurtain(); - SetForegroundWindow(getHWND()); + SetForegroundWindow( getHWND() ); + getScreenResChangeSignal().trigger( this, true ); } bool Win32Window::clearFullscreen() diff --git a/Templates/Empty/game/art/environment/FogMod_heavy.dds b/Templates/Empty/game/art/environment/FogMod_heavy.dds new file mode 100644 index 000000000..197dd4332 Binary files /dev/null and b/Templates/Empty/game/art/environment/FogMod_heavy.dds differ diff --git a/Templates/Empty/game/art/environment/FogMod_light.dds b/Templates/Empty/game/art/environment/FogMod_light.dds new file mode 100644 index 000000000..d726795fa Binary files /dev/null and b/Templates/Empty/game/art/environment/FogMod_light.dds differ diff --git a/Templates/Empty/game/art/environment/FogMod_med.dds b/Templates/Empty/game/art/environment/FogMod_med.dds new file mode 100644 index 000000000..2b25d3263 Binary files /dev/null and b/Templates/Empty/game/art/environment/FogMod_med.dds differ diff --git a/Templates/Empty/game/art/environment/Fog_Cube.DAE b/Templates/Empty/game/art/environment/Fog_Cube.DAE new file mode 100644 index 000000000..34cad9f48 --- /dev/null +++ b/Templates/Empty/game/art/environment/Fog_Cube.DAE @@ -0,0 +1,177 @@ + + + + + Richard + OpenCOLLADA for 3ds Max; Version: 1.4.1; Revision: exported; Platform: x64; Configuration: Release_Max2011_static + file:///G:/Documents%20and%20Settings/Richard/Mijn%20documenten/3dsmax/scenes/FogVolumes.max + + 2014-08-16T10:10:23 + 2014-08-16T10:10:23 + + Z_UP + + + + + + + + 0 0 0 1 + + + 0.588 0.588 0.588 1 + + + 0.588 0.588 0.588 1 + + + 0.9 0.9 0.9 1 + + + 0 + + + 0 0 0 1 + + + 1 1 1 1 + + + 1 + + + + + + + + 0 + 0 + 0 + 1.5 + 0 + 3 + 1 + 0 + + + 1 + 1 + 0 + 0.1 + 0 + + + + + + + + + + + + + + + -0.85 -1 -0.85 0.85 -0.85 -1 -1 0.85 -0.85 0.85 0.85 -1 -0.85 -1 0.85 1 -0.85 0.85 -1 0.85 0.85 0.85 1 0.85 -1 -0.85 -0.85 -0.85 -0.85 -1 1 -0.85 -0.85 0.85 -1 -0.85 -0.85 1 -0.85 -0.85 0.85 -1 0.85 1 -0.85 1 0.85 -0.85 -0.85 -0.85 1 -1 -0.85 0.85 0.85 -0.85 1 0.85 -1 0.85 -0.85 0.85 1 -0.85 1 0.85 0.85 0.85 1 1 0.85 0.85 + + + + + + + + + + -0.341586 -0.341586 -0.8755786 -0.341586 0.341586 -0.8755788 0.341586 0.341586 -0.8755788 0.341586 -0.341586 -0.8755788 -0.341586 -0.341586 0.8755786 0.341586 -0.341586 0.8755788 0.341586 0.341586 0.8755788 -0.341586 0.341586 0.8755788 -0.341586 -0.8755786 -0.341586 0.341586 -0.8755788 -0.341586 0.341586 -0.8755786 0.341586 -0.341586 -0.8755788 0.341586 0.8755786 -0.341586 -0.341586 0.8755788 0.341586 -0.341586 0.8755786 0.341586 0.341586 0.8755788 -0.341586 0.341586 0.341586 0.8755786 -0.341586 -0.341586 0.8755788 -0.341586 -0.341586 0.8755786 0.341586 0.341586 0.8755788 0.341586 -0.8755786 0.341586 -0.341586 -0.8755788 -0.341586 -0.341586 -0.8755786 -0.341586 0.341586 -0.8755788 0.341586 0.341586 + + + + + + + + + + 0 0 0 1 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 1 0 1 1 0 0.07542458 0.07542461 4.99755e-4 0.07542479 0.07542461 4.99547e-4 0.07542455 0.07542461 4.99755e-4 0.07542461 0.9245752 4.99547e-4 0.07542458 0.9245754 4.99755e-4 0.07542458 0.9245754 0.9995003 0.07542455 0.9245754 4.99755e-4 0.07542455 0.9245754 0.9995003 0.9245752 0.07542461 4.99576e-4 0.9245754 0.07542479 4.99547e-4 0.07542458 0.07542461 0.9995003 0.9245752 0.07542461 4.99576e-4 0.9245752 0.07542461 0.9995004 0.9245752 0.9245754 4.99547e-4 0.07542455 0.07542461 0.9995003 0.9245752 0.07542461 0.9995004 0.07542461 0.07542479 0.9995005 0.9245752 0.9245754 4.99576e-4 0.9245752 0.07542461 0.9995005 0.9245752 0.9245754 4.99576e-4 0.07542479 0.9245754 0.9995005 0.9245752 0.9245754 0.9995004 0.9245754 0.9245752 0.9995005 0.9245752 0.9245754 0.9995004 0.9995003 0.07542461 0.07542458 0.9245752 4.99547e-4 0.07542461 0.9245752 4.99547e-4 0.07542461 0.9995003 0.07542461 0.07542458 0.9995003 0.07542461 0.9245754 0.9245752 4.99547e-4 0.9245754 0.9245752 4.99547e-4 0.9245754 0.9995003 0.07542461 0.9245754 0.9995003 0.9245754 0.07542458 0.9245752 0.9995005 0.07542461 0.9995003 0.9245754 0.07542458 0.9245752 0.9995005 0.07542461 0.9995003 0.9245754 0.9245754 0.9245752 0.9995005 0.9245754 0.9995003 0.9245754 0.9245754 0.9245752 0.9995005 0.9245754 0.9995004 0.07542482 0.07542461 0.9995003 0.9245754 0.07542461 0.9245752 0.9995004 0.07542461 0.07542455 0.9995003 0.07542461 4.99606e-4 0.9245752 0.07542461 4.99725e-4 0.07542458 0.07542461 0.07542479 4.99576e-4 0.07542461 0.9245754 4.99755e-4 0.07542461 0.07542458 4.99755e-4 0.9245754 0.9245752 4.99576e-4 0.9245754 0.9995003 0.07542458 0.9245754 0.9995004 0.9245752 0.9245754 0.9245754 0.9995003 0.9245754 0.07542482 0.9995004 0.9245754 4.99755e-4 0.9245754 0.9245754 4.99576e-4 0.07542482 0.9245754 0.9995003 0.07542461 0.07542458 0.9995003 0.9245754 0.07542458 0.9995003 0.9245754 0.07542458 0.9995003 0.07542461 0.07542458 0.9995003 0.07542461 0.9245754 0.9995003 0.9245754 0.9245754 0.9995003 0.07542461 0.9245754 0.9995003 0.9245754 0.9245754 + + + + + + + + + + -0.8644259 0.01841655 0.3300502 -0.8715108 -0.05526615 0.3184382 -0.8644259 0.01841664 -0.3300501 -0.8715108 -0.05526611 -0.3184382 0.8738725 -0.06754867 0.3145678 0.8597026 -0.006149054 -0.3377912 0.8738725 -0.06754874 -0.3145678 0.8597026 -0.006148929 0.3377911 0.883319 -0.2990854 -0.116681 0.8478944 0.3571441 -0.06756432 0.8597026 0.3377913 0.00614921 0.883319 -0.2990854 0.116681 0.2990854 0.883319 -0.116681 -0.3571441 0.8478944 -0.06756432 -0.3377913 0.8597026 0.00614921 0.2990854 0.883319 0.116681 -0.883319 0.2990854 -0.116681 -0.8478944 -0.3571441 -0.06756432 -0.8597026 -0.3377913 0.00614921 -0.883319 0.2990854 0.116681 -0.2990854 -0.883319 -0.116681 0.3571441 -0.8478944 -0.06756432 0.3377913 -0.8597026 0.00614921 -0.2990854 -0.883319 0.116681 0.8360862 -0.3764972 0.1289794 0.7071068 -0.7071068 0 0.7071068 0.7071068 0 0.3764972 0.8360862 0.1289794 -0.3764972 -0.8360862 0.1289794 -0.7071068 -0.7071068 0 -0.7071068 0.7071068 0 -0.8360862 0.3764972 0.1289794 0.8360862 -0.3764971 -0.1289794 0.7071068 -0.7071068 0 0.3764971 0.8360862 -0.1289794 0.7071068 0.7071068 0 -0.3764971 -0.8360862 -0.1289794 -0.7071068 -0.7071068 0 -0.8360862 0.3764971 -0.1289794 -0.7071068 0.7071068 0 -0.376497 0.1289792 0.8360862 -0.3764973 -0.1289798 0.8360861 -0.8833191 -0.2990855 0.1166808 -0.883319 0.2990853 -0.1166812 -0.3764971 0.1289794 -0.8360862 -0.3764972 -0.1289795 -0.8360862 -0.8833191 -0.2990855 -0.1166807 -0.883319 0.2990853 0.1166812 0.883319 -0.2990853 0.1166812 0.8833191 0.2990855 -0.1166807 0.3764971 0.1289797 -0.8360862 0.3764971 -0.1289793 -0.8360862 0.883319 -0.2990853 -0.1166811 0.8833191 0.2990855 0.1166808 0.3764972 0.1289799 0.8360861 0.3764971 -0.128979 0.8360862 0.3764972 0.8360862 0.1289794 0.3764971 0.8360862 -0.1289794 0.8360862 -0.3764971 -0.1289794 0.8360862 -0.3764972 0.1289794 -0.8360862 0.3764972 0.1289794 -0.8360862 0.3764971 -0.1289794 -0.3764972 -0.8360862 0.1289794 -0.3764971 -0.8360862 -0.1289794 + + + + + + + + + + 0.1043954 -0.9396398 0.3258505 -0.06496345 -0.9379679 -0.3405817 0.1043953 -0.9396398 -0.3258505 -0.06496349 -0.937968 0.3405817 0.05187585 -0.9370471 -0.3453283 -0.1307439 -0.939827 -0.3156443 0.05187577 -0.9370471 0.3453283 -0.1307438 -0.939827 0.3156443 0 0.3634471 -0.9316148 -0.196368 0.2889368 -0.9369926 0.1307441 -0.3156442 -0.939827 0 -0.3634471 -0.9316148 -0.3634471 0 -0.9316148 -0.2889368 -0.196368 -0.9369926 0.3156442 0.1307441 -0.939827 0.3634471 0 -0.9316148 0 -0.3634471 -0.9316148 0.196368 -0.2889368 -0.9369926 -0.1307441 0.3156442 -0.939827 0 0.3634471 -0.9316148 0.3634471 0 -0.9316148 0.2889368 0.196368 -0.9369926 -0.3156442 -0.1307441 -0.939827 -0.3634471 0 -0.9316148 0.2608475 0.2608475 -0.9294714 0.6191276 0.6191276 -0.4830755 -0.6191276 0.6191276 -0.4830755 -0.2608475 0.2608475 -0.9294714 0.2608475 -0.2608475 -0.9294714 0.6191276 -0.6191276 -0.4830755 -0.6191276 -0.6191276 -0.4830755 -0.2608475 -0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 -0.6191276 -0.6191276 -0.4830755 0.2608475 -0.2608475 -0.9294714 0.6191276 -0.6191276 -0.4830755 -0.2608475 0.2608475 -0.9294714 -0.6191276 0.6191276 -0.4830755 0.2608475 0.2608475 -0.9294714 0.6191276 0.6191276 -0.4830755 0.2608476 -0.9294715 0.2608473 -0.2608474 -0.9294714 -0.2608479 1.81809e-7 -0.363447 -0.9316149 2.27262e-7 -0.3634472 -0.9316148 0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 0.2608477 2.72714e-7 -0.363447 0.9316149 2.72714e-7 -0.3634472 0.9316148 2.72714e-7 -0.3634472 -0.9316148 2.72714e-7 -0.363447 -0.9316149 -0.2608474 -0.9294714 -0.2608478 0.2608476 -0.9294714 0.2608474 1.81809e-7 -0.3634472 0.9316148 2.27262e-7 -0.3634471 0.9316149 -0.2608473 -0.9294714 0.260848 0.2608477 -0.9294715 -0.2608472 -0.2608475 0.2608475 -0.9294714 0.2608475 -0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 0.2608475 0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 0.2608475 0.2608475 -0.9294714 0.2608475 -0.2608475 -0.9294714 -0.2608475 0.2608475 -0.9294714 + + + + + + + + + + + + + + + + + +

9 0 21 0 13 1 25 1 3 2 15 2 3 2 15 2 1 3 13 3 9 0 21 0 16 4 28 4 18 5 30 5 22 6 34 6 22 6 34 6 20 7 32 7 16 4 28 4 0 8 12 8 11 9 23 9 19 10 31 10 19 10 31 10 4 11 16 11 0 8 12 8 10 12 22 12 15 13 27 13 23 14 35 14 23 14 35 14 5 15 17 15 10 12 22 12 14 16 26 16 12 17 24 17 21 18 33 18 21 18 33 18 7 19 19 19 14 16 26 16 2 20 14 20 8 21 20 21 17 22 29 22 17 22 29 22 6 23 18 23 2 20 14 20 0 8 36 24 8 21 20 21 9 0 37 25 1 3 38 26 10 12 39 27 11 9 23 9 2 20 40 28 12 17 24 17 13 1 41 29 3 2 42 30 14 16 43 31 15 13 27 13 4 11 44 32 16 4 45 33 17 22 29 22 5 15 46 34 18 5 47 35 19 10 31 10 6 23 48 36 20 7 49 37 21 18 33 18 7 19 50 38 22 6 51 39 23 14 35 14 9 0 21 0 8 21 52 40 2 20 53 41 2 20 53 41 13 1 25 1 9 0 21 0 13 1 25 1 12 17 54 42 14 16 55 43 14 16 55 43 3 2 15 2 13 1 25 1 3 2 15 2 15 13 56 44 10 12 57 45 10 12 57 45 1 3 13 3 3 2 15 2 1 3 13 3 11 9 58 46 0 8 59 47 0 8 59 47 9 0 21 0 1 3 13 3 16 4 28 4 4 11 60 48 19 10 61 49 19 10 61 49 18 5 30 5 16 4 28 4 18 5 30 5 5 15 62 50 23 14 63 51 23 14 63 51 22 6 34 6 18 5 30 5 22 6 34 6 7 19 64 52 21 18 65 53 21 18 65 53 20 7 32 7 22 6 34 6 20 7 32 7 6 23 66 54 17 22 67 55 17 22 67 55 16 4 28 4 20 7 32 7 11 9 23 9 10 12 68 56 5 15 69 57 5 15 69 57 19 10 31 10 11 9 23 9 4 11 70 58 17 22 29 22 8 21 20 21 8 21 20 21 0 8 71 59 4 11 70 58 15 13 27 13 14 16 72 60 7 19 73 61 7 19 73 61 23 14 35 14 15 13 27 13 12 17 24 17 2 20 74 62 6 23 75 63 6 23 75 63 21 18 33 18 12 17 24 17

+
+
+
+
+ + + + + 0 0 0 + + + + + + + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + +
\ No newline at end of file diff --git a/Templates/Empty/game/art/environment/Fog_Cube.cs b/Templates/Empty/game/art/environment/Fog_Cube.cs new file mode 100644 index 000000000..3c686032c --- /dev/null +++ b/Templates/Empty/game/art/environment/Fog_Cube.cs @@ -0,0 +1,8 @@ + +singleton TSShapeConstructor(Fog_CubeDAE) +{ + baseShape = "./Fog_Cube.DAE"; + lodType = "TrailingNumber"; + neverImport = "env*"; + loadLights = "0"; +}; diff --git a/Templates/Empty/game/core/main.cs b/Templates/Empty/game/core/main.cs index 0baeb9364..f666c948c 100644 --- a/Templates/Empty/game/core/main.cs +++ b/Templates/Empty/game/core/main.cs @@ -141,11 +141,11 @@ function parseArgs() switch$ (%arg) { case "-fullscreen": - setFullScreen(true); + $cliFullscreen = true; $argUsed[%i]++; case "-windowed": - setFullScreen(false); + $cliFullscreen = false; $argUsed[%i]++; case "-openGL": diff --git a/Templates/Empty/game/core/scripts/client/canvas.cs b/Templates/Empty/game/core/scripts/client/canvas.cs index 69dd6da71..5c1d377c5 100644 --- a/Templates/Empty/game/core/scripts/client/canvas.cs +++ b/Templates/Empty/game/core/scripts/client/canvas.cs @@ -39,9 +39,14 @@ function configureCanvas() %rate = getWord($pref::Video::mode, $WORD::REFRESH); %fsaa = getWord($pref::Video::mode, $WORD::AA); - echo("--------------"); - echo("Attempting to set resolution to \"" @ $pref::Video::mode @ "\""); + if($cliFullscreen !$= "") { + %fs = $cliFullscreen; + $cliFullscreen = ""; + } + echo("--------------"); + echo("Attempting to set resolution to \"" @ %resX SPC %resY SPC %fs SPC %bpp SPC %rate SPC %fsaa @ "\""); + %deskRes = getDesktopResolution(); %deskResX = getWord(%deskRes, $WORD::RES_X); %deskResY = getWord(%deskRes, $WORD::RES_Y); diff --git a/Templates/Empty/game/core/scripts/client/postFx/glow.cs b/Templates/Empty/game/core/scripts/client/postFx/glow.cs index 3cc946b04..78c46e56d 100644 --- a/Templates/Empty/game/core/scripts/client/postFx/glow.cs +++ b/Templates/Empty/game/core/scripts/client/postFx/glow.cs @@ -106,3 +106,79 @@ singleton PostEffect( GlowPostFx ) target = "$backBuffer"; }; }; + +singleton ShaderData( PFX_VolFogGlowBlurVertShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/glowBlurV.hlsl"; + DXPixelShaderFile = "shaders/common/postFx/VolFogGlowP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/glowBlurV.glsl"; + OGLPixelShaderFile = "shaders/common/postFx/gl/VolFogGlowP.glsl"; + + defines = "BLUR_DIR=float2(0.0,1.0)"; + samplerNames[0] = "$diffuseMap"; + pixVersion = 2.0; +}; +singleton ShaderData( PFX_VolFogGlowBlurHorzShader : PFX_VolFogGlowBlurVertShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/glowBlurV.hlsl"; + DXPixelShaderFile = "shaders/common/postFx/VolFogGlowP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/glowBlurV.glsl"; + OGLPixelShaderFile = "shaders/common/postFx/gl/VolFogGlowP.glsl"; + + defines = "BLUR_DIR=float2(1.0,0.0)"; +}; + +$VolFogGlowPostFx::glowStrength = 0.3; + +singleton PostEffect( VolFogGlowPostFx ) +{ + // Do not allow the glow effect to work in reflection + // passes by default so we don't do the extra drawing. + allowReflectPass = false; + renderTime = "PFXAfterBin"; + renderBin = "FogBin"; + renderPriority = 1; + // First we down sample the glow buffer. + shader = PFX_PassthruShader; + stateBlock = PFX_DefaultStateBlock; + texture[0] = "$backbuffer"; + target = "$outTex"; + targetScale = "0.5 0.5"; + isEnabled = true; + // Blur vertically + new PostEffect() + { + shader = PFX_VolFogGlowBlurVertShader; + stateBlock = PFX_DefaultStateBlock; + internalName = "vert"; + texture[0] = "$inTex"; + target = "$outTex"; + }; + // Blur horizontally + new PostEffect() + { + shader = PFX_VolFogGlowBlurHorzShader; + stateBlock = PFX_DefaultStateBlock; + internalName = "hor"; + texture[0] = "$inTex"; + target = "$outTex"; + }; + // Upsample and combine with the back buffer. + new PostEffect() + { + shader = PFX_PassthruShader; + stateBlock = PFX_GlowCombineStateBlock; + texture[0] = "$inTex"; + target = "$backBuffer"; + }; +}; + +function VolFogGlowPostFx::setShaderConsts( %this ) +{ + %vp=%this-->vert; + %vp.setShaderConst( "$strength", $VolFogGlowPostFx::glowStrength ); + %vp=%this-->hor; + %vp.setShaderConst( "$strength", $VolFogGlowPostFx::glowStrength ); +} \ No newline at end of file diff --git a/Templates/Empty/game/core/scripts/client/postFx/postFxManager.gui.settings.cs b/Templates/Empty/game/core/scripts/client/postFx/postFxManager.gui.settings.cs index d30d2314b..77d664f41 100644 --- a/Templates/Empty/game/core/scripts/client/postFx/postFxManager.gui.settings.cs +++ b/Templates/Empty/game/core/scripts/client/postFx/postFxManager.gui.settings.cs @@ -70,6 +70,7 @@ function PostFXManager::settingsSetEnabled(%this, %bEnablePostFX) postVerbose("% - PostFX Manager - PostFX disabled"); } + VolFogGlowPostFx.disable(); } function PostFXManager::settingsEffectSetEnabled(%this, %sName, %bEnable) diff --git a/Templates/Empty/game/core/scripts/client/renderManager.cs b/Templates/Empty/game/core/scripts/client/renderManager.cs index dcd1628fe..5734bbce6 100644 --- a/Templates/Empty/game/core/scripts/client/renderManager.cs +++ b/Templates/Empty/game/core/scripts/client/renderManager.cs @@ -75,6 +75,8 @@ function initRenderManager() DiffuseRenderPassManager.addManager( new RenderParticleMgr() { renderOrder = 1.35; processAddOrder = 1.35; } ); DiffuseRenderPassManager.addManager( new RenderTranslucentMgr() { renderOrder = 1.4; processAddOrder = 1.4; } ); + DiffuseRenderPassManager.addManager(new RenderObjectMgr(FogBin){ bintype = "ObjectVolumetricFog"; renderOrder = 1.45; processAddOrder = 1.45; } ); + // Note that the GlowPostFx is triggered after this bin. DiffuseRenderPassManager.addManager( new RenderGlowMgr(GlowBin) { renderOrder = 1.5; processAddOrder = 1.5; } ); diff --git a/Templates/Empty/game/scripts/server/VolumetricFog.cs b/Templates/Empty/game/scripts/server/VolumetricFog.cs new file mode 100644 index 000000000..53e03adf3 --- /dev/null +++ b/Templates/Empty/game/scripts/server/VolumetricFog.cs @@ -0,0 +1,106 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +function VolumetricFog::onEnterFog(%this,%obj) +{ + // This method is called whenever the control object (Camera or Player) + // %obj enters the fog area. + + // echo("Control Object " @ %obj @ " enters fog " @ %this); +} + +function VolumetricFog::onLeaveFog(%this,%obj) +{ + // This method is called whenever the control object (Camera or Player) + // %obj leaves the fog area. + + // echo("Control Object " @ %obj @ " left fog " @ %this); +} + +function VolumetricFog::Dissolve(%this,%speed,%delete) +{ + // This method dissolves the fog at speed milliseconds + %this.isBuilding = true; + if (%this.FogDensity > 0) + { + %this.setFogDensity(%this.FogDensity - 0.005); + %this.schedule(%speed,Dissolve,%speed,%delete); + } + else + { + %this.isBuilding = false; + %this.SetFogDensity(0.0); + if (%delete !$= "" && %delete !$="0" && %delete !$="false") + %this.schedule(250,delete); + } +} + +function VolumetricFog::Thicken(%this,%speed, %end_density) +{ + // This method thickens the fog at speed milliseconds to a density of %end_density + + %this.isBuilding = true; + if (%this.FogDensity + 0.005 < %end_density) + { + %this.setFogDensity(%this.FogDensity + 0.005); + %this.schedule(%speed,Thicken,%speed, %end_density); + } + else + { + %this.setFogDensity(%end_density); + %this.isBuilding = false; + } +} + +function GenerateFog(%pos,%scale,%color,%density) +{ + // This function can be used to generate some fog caused by massive gunfire etc. + // Change shape and modulation data to your likings. + + %fog=new VolumetricFog() { + shapeName = "art/environment/Fog_Sphere.dts"; + fogColor = %color; + fogDensity = "0.0"; + ignoreWater = "0"; + MinSize = "250"; + FadeSize = "750"; + texture = "art/environment/FogMod_heavy.dds"; + tiles = "1"; + modStrength = "0.2"; + PrimSpeed = "-0.01 0.04"; + SecSpeed = "0.02 0.02"; + position = %pos; + rotation = "0 0 1 20.354"; + scale = %scale; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + + if (isObject(%fog)) + { + MissionCleanup.add(%fog); + + %fog.Thicken(500,%density); + } + + return %fog; +} \ No newline at end of file diff --git a/Templates/Empty/game/scripts/server/scriptExec.cs b/Templates/Empty/game/scripts/server/scriptExec.cs index f2f2d1f58..77a5d8d27 100644 --- a/Templates/Empty/game/scripts/server/scriptExec.cs +++ b/Templates/Empty/game/scripts/server/scriptExec.cs @@ -22,3 +22,4 @@ // Load up all scripts. This function is called when // a server is constructed. +exec("./VolumetricFog.cs"); \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/VFogP.hlsl b/Templates/Empty/game/shaders/common/VolumetricFog/VFogP.hlsl new file mode 100644 index 000000000..aaadbf479 --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/VFogP.hlsl @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog final pixel shader V2.00 + +#include "shadergen:/autogenConditioners.h" +#include "../torque.hlsl" + +uniform sampler2D prepassTex : register(S0); +uniform sampler2D depthBuffer : register(S1); +uniform sampler2D frontBuffer : register(S2); +uniform sampler2D density : register(S3); + +uniform float accumTime; +uniform float4 fogColor; +uniform float fogDensity; +uniform float preBias; +uniform float textured; +uniform float modstrength; +uniform float4 modspeed;//xy speed layer 1, zw speed layer 2 +uniform float2 viewpoint; +uniform float2 texscale; +uniform float3 ambientColor; +uniform float numtiles; +uniform float fadesize; +uniform float2 PixelSize; + +struct ConnectData +{ + float4 hpos : POSITION; + float4 htpos : TEXCOORD0; + float2 uv0 : TEXCOORD1; +}; + +float4 main( ConnectData IN ) : COLOR0 +{ + float2 uvscreen=((IN.htpos.xy/IN.htpos.w) + 1.0 ) / 2.0; + uvscreen.y = 1.0 - uvscreen.y; + + float obj_test = prepassUncondition( prepassTex, uvscreen).w * preBias; + float depth = tex2D(depthBuffer,uvscreen).r; + float front = tex2D(frontBuffer,uvscreen).r; + + if (depth <= front) + return float4(0,0,0,0); + else if ( obj_test < depth ) + depth = obj_test; + if ( front >= 0.0) + depth -= front; + + float diff = 1.0; + float3 col = fogColor.rgb; + if (textured != 0.0) + { + float2 offset = viewpoint + ((-0.5 + (texscale * uvscreen)) * numtiles); + + float2 mod1 = tex2D(density,(offset + (modspeed.xy*accumTime))).rg; + float2 mod2= tex2D(density,(offset + (modspeed.zw*accumTime))).rg; + diff = (mod2.r + mod1.r) * modstrength; + col *= (2.0 - ((mod1.g + mod2.g) * fadesize))/2.0; + } + + col *= ambientColor; + + float4 resultColor = float4(col, 1.0 - saturate(exp(-fogDensity * depth * diff * fadesize))); + + return hdrEncode(resultColor); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/VFogPreP.hlsl b/Templates/Empty/game/shaders/common/VolumetricFog/VFogPreP.hlsl new file mode 100644 index 000000000..bb06f5f7c --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/VFogPreP.hlsl @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog prepass pixel shader V1.00 + +struct ConnectData +{ + float4 hpos : POSITION; + float4 pos : TEXCOORD0; +}; + +float4 main( ConnectData IN ) : COLOR0 +{ + float OUT; + + clip( IN.pos.w ); + OUT = IN.pos.w; + + return float4(OUT,0,0,1); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/VFogPreV.hlsl b/Templates/Empty/game/shaders/common/VolumetricFog/VFogPreV.hlsl new file mode 100644 index 000000000..2d13cdf01 --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/VFogPreV.hlsl @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog prepass vertex shader V1.00 + +#include "shaders/common/hlslstructs.h" + +struct ConnectData +{ + float4 hpos : POSITION; + float4 pos : TEXCOORD0; +}; + +uniform float4x4 modelView; + +ConnectData main( VertexIn_P IN) +{ + ConnectData OUT; + + float4 inPos = IN.pos; + inPos.w = 1.0; + + OUT.hpos = mul( modelView, inPos ); + OUT.pos = OUT.hpos; + + return OUT; +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/VFogRefl.hlsl b/Templates/Empty/game/shaders/common/VolumetricFog/VFogRefl.hlsl new file mode 100644 index 000000000..87226a1ac --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/VFogRefl.hlsl @@ -0,0 +1,36 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +uniform float4 fogColor; +uniform float fogDensity; +uniform float reflStrength; + +struct ConnectData +{ + float4 hpos : POSITION; + float4 pos : TEXCOORD0; +}; + +float4 main( ConnectData IN ) : COLOR0 +{ + return float4(fogColor.rgb,saturate(fogDensity*reflStrength)); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/VFogV.hlsl b/Templates/Empty/game/shaders/common/VolumetricFog/VFogV.hlsl new file mode 100644 index 000000000..7f86802b5 --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/VFogV.hlsl @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog final vertex shader V1.00 + +#include "shaders/common/hlslstructs.h" + +struct ConnectData +{ + float4 hpos : POSITION; + float4 htpos : TEXCOORD0; + float2 uv0 : TEXCOORD1; +}; + +uniform float4x4 modelView; + +ConnectData main( VertexIn_PNT IN) +{ + ConnectData OUT; + + OUT.hpos = mul(modelView, IN.pos); + OUT.htpos = OUT.hpos; + OUT.uv0 = IN.uv0; + + return OUT; +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogP.glsl b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogP.glsl new file mode 100644 index 000000000..7895d9e2d --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogP.glsl @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" +#include "shadergen:/autogenConditioners.h" +#include "../../gl/torque.glsl" + +uniform sampler2D prepassTex; +uniform sampler2D depthBuffer; +uniform sampler2D frontBuffer; +uniform sampler2D density; + +uniform float accumTime; +uniform vec4 fogColor; +uniform float fogDensity; +uniform float preBias; +uniform float textured; +uniform float modstrength; +uniform vec4 modspeed;//xy speed layer 1, zw speed layer 2 +uniform vec2 viewpoint; +uniform vec2 texscale; +uniform vec3 ambientColor; +uniform float numtiles; +uniform float fadesize; +uniform vec2 PixelSize; + +in vec4 _hpos; +#define IN_hpos _hpos +out vec4 OUT_col; + +void main() +{ + vec2 uvscreen=((IN_hpos.xy/IN_hpos.w) + 1.0 ) / 2.0; + uvscreen.y = 1.0 - uvscreen.y; + + float obj_test = prepassUncondition( prepassTex, uvscreen).w * preBias; + float depth = tex2D(depthBuffer,uvscreen).r; + float front = tex2D(frontBuffer,uvscreen).r; + + if (depth <= front) + { + OUT_col = vec4(0,0,0,0); + return; + } + + else if ( obj_test < depth ) + depth = obj_test; + if ( front >= 0.0) + depth -= front; + + float diff = 1.0; + vec3 col = fogColor.rgb; + if (textured != 0.0) + { + vec2 offset = viewpoint + ((-0.5 + (texscale * uvscreen)) * numtiles); + + vec2 mod1 = tex2D(density,(offset + (modspeed.xy*accumTime))).rg; + vec2 mod2= tex2D(density,(offset + (modspeed.zw*accumTime))).rg; + diff = (mod2.r + mod1.r) * modstrength; + col *= (2.0 - ((mod1.g + mod2.g) * fadesize))/2.0; + } + + col *= ambientColor; + + vec4 returnColor = vec4(col, 1.0 - saturate(exp(-fogDensity * depth * diff * fadesize))); + + OUT_col = hdrEncode(returnColor); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl new file mode 100644 index 000000000..017ea6ef8 --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +in vec4 _hpos; +#define IN_hpos _hpos + +out vec4 OUT_col; + +void main() +{ + float OUT; + clip( IN_hpos.w ); + OUT = IN_hpos.w; + + OUT_col = vec4(OUT,0,0,1); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl new file mode 100644 index 000000000..2f2a1318a --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +in vec4 vPosition; +#define IN_position vPosition + +out vec4 _hpos; +#define OUT_hpos _hpos + +uniform mat4 modelView; + +void main() +{ + vec4 inPos = IN_position; + inPos.w = 1.0; + + OUT_hpos = tMul( modelView, inPos ); + + gl_Position = OUT_hpos; + correctSSP(gl_Position); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl new file mode 100644 index 000000000..78e149fbf --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +uniform vec4 fogColor; +uniform float fogDensity; +uniform float reflStrength; +out vec4 OUT_col; + +void main() +{ + OUT_col = vec4(fogColor.rgb,saturate(fogDensity*reflStrength)); +} diff --git a/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogV.glsl b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogV.glsl new file mode 100644 index 000000000..57b3ba87e --- /dev/null +++ b/Templates/Empty/game/shaders/common/VolumetricFog/gl/VFogV.glsl @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +in vec4 vPosition; +#define IN_position vPosition + +out vec4 _hpos; +#define OUT_hpos _hpos + +uniform mat4 modelView; + +void main() +{ + OUT_hpos = tMul(modelView, IN_position); + gl_Position = OUT_hpos; + correctSSP(gl_Position); +} diff --git a/Templates/Empty/game/shaders/common/postFx/VolFogGlowP.hlsl b/Templates/Empty/game/shaders/common/postFx/VolFogGlowP.hlsl new file mode 100644 index 000000000..8a61b5928 --- /dev/null +++ b/Templates/Empty/game/shaders/common/postFx/VolFogGlowP.hlsl @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 R.G.S. - Richards Game Studio, the Netherlands +// http://www.richardsgamestudio.com/ +// +// If you find this code useful or you are feeling particularly generous I +// would ask that you please go to http://www.richardsgamestudio.com/ then +// choose Donations from the menu on the left side and make a donation to +// Richards Game Studio. It will be highly appreciated. +// +// The MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog Glow postFx pixel shader V1.00 + +#include "./postFx.hlsl" + +uniform sampler2D diffuseMap : register(S0); +uniform float strength; + +struct VertToPix +{ + float4 hpos : POSITION; + + float2 uv0 : TEXCOORD0; + float2 uv1 : TEXCOORD1; + float2 uv2 : TEXCOORD2; + float2 uv3 : TEXCOORD3; + + float2 uv4 : TEXCOORD4; + float2 uv5 : TEXCOORD5; + float2 uv6 : TEXCOORD6; + float2 uv7 : TEXCOORD7; +}; + +float4 main( VertToPix IN ) : COLOR +{ + float4 kernel = float4( 0.175, 0.275, 0.375, 0.475 ) * strength; + + float4 OUT = 0; + OUT += tex2D( diffuseMap, IN.uv0 ) * kernel.x; + OUT += tex2D( diffuseMap, IN.uv1 ) * kernel.y; + OUT += tex2D( diffuseMap, IN.uv2 ) * kernel.z; + OUT += tex2D( diffuseMap, IN.uv3 ) * kernel.w; + + OUT += tex2D( diffuseMap, IN.uv4 ) * kernel.x; + OUT += tex2D( diffuseMap, IN.uv5 ) * kernel.y; + OUT += tex2D( diffuseMap, IN.uv6 ) * kernel.z; + OUT += tex2D( diffuseMap, IN.uv7 ) * kernel.w; + + // Calculate a lumenance value in the alpha so we + // can use alpha test to save fillrate. + float3 rgb2lum = float3( 0.30, 0.59, 0.11 ); + OUT.a = dot( OUT.rgb, rgb2lum ); + + return OUT; +} diff --git a/Templates/Empty/game/shaders/common/postFx/gl/VolFogGlowP.glsl b/Templates/Empty/game/shaders/common/postFx/gl/VolFogGlowP.glsl new file mode 100644 index 000000000..01b072dd9 --- /dev/null +++ b/Templates/Empty/game/shaders/common/postFx/gl/VolFogGlowP.glsl @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 R.G.S. - Richards Game Studio, the Netherlands +// http://www.richardsgamestudio.com/ +// +// If you find this code useful or you are feeling particularly generous I +// would ask that you please go to http://www.richardsgamestudio.com/ then +// choose Donations from the menu on the left side and make a donation to +// Richards Game Studio. It will be highly appreciated. +// +// The MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog Glow postFx pixel shader V1.00 + +uniform sampler2D diffuseMap; +uniform float strength; + +out vec4 OUT_col; + +in vec2 uv0; +in vec2 uv1; +in vec2 uv2; +in vec2 uv3; + +in vec2 uv4; +in vec2 uv5; +in vec2 uv6; +in vec2 uv7; + +void main() +{ + vec4 kernel = vec4( 0.175, 0.275, 0.375, 0.475 ) * strength; + + OUT_col = vec4(0); + OUT_col += texture( diffuseMap, uv0 ) * kernel.x; + OUT_col += texture( diffuseMap, uv1 ) * kernel.y; + OUT_col += texture( diffuseMap, uv2 ) * kernel.z; + OUT_col += texture( diffuseMap, uv3 ) * kernel.w; + + OUT_col += texture( diffuseMap, uv4 ) * kernel.x; + OUT_col += texture( diffuseMap, uv5 ) * kernel.y; + OUT_col += texture( diffuseMap, uv6 ) * kernel.z; + OUT_col += texture( diffuseMap, uv7 ) * kernel.w; + + // Calculate a lumenance value in the alpha so we + // can use alpha test to save fillrate. + vec3 rgb2lum = vec3( 0.30, 0.59, 0.11 ); + OUT_col.a = dot( OUT_col.rgb, rgb2lum ); +} diff --git a/Templates/Empty/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl b/Templates/Empty/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl index 38762baa5..f34cff1ef 100644 --- a/Templates/Empty/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl +++ b/Templates/Empty/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl @@ -42,10 +42,11 @@ uniform vec3 g_fBlueShiftColor; uniform float g_fBloomScale; uniform float g_fOneOverGamma; +uniform float Brightness; +uniform float Contrast; out vec4 OUT_col; - void main() { vec4 _sample = hdrDecode( texture( sceneTex, IN_uv0 ) ); @@ -94,5 +95,11 @@ void main() // Apply gamma correction _sample.rgb = pow( abs(_sample.rgb), vec3(g_fOneOverGamma) ); + // Apply contrast + _sample.rgb = ((_sample.rgb - 0.5f) * Contrast) + 0.5f; + + // Apply brightness + _sample.rgb += Brightness; + OUT_col = _sample; } diff --git a/Templates/Empty/game/tools/classIcons/VolumetricFog.png b/Templates/Empty/game/tools/classIcons/VolumetricFog.png new file mode 100644 index 000000000..5dc516cb5 Binary files /dev/null and b/Templates/Empty/game/tools/classIcons/VolumetricFog.png differ diff --git a/Templates/Empty/game/tools/gui/colorPicker.ed.gui b/Templates/Empty/game/tools/gui/colorPicker.ed.gui index 18dad276e..c203ca52e 100644 --- a/Templates/Empty/game/tools/gui/colorPicker.ed.gui +++ b/Templates/Empty/game/tools/gui/colorPicker.ed.gui @@ -1,289 +1,722 @@ //--- OBJECT WRITE BEGIN --- %guiContent = new GuiColorPickerCtrl(ColorPickerDlg,EditorGuiGroup) { - canSaveDynamicFields = "0"; - isContainer = "1"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; + displayMode = "Dropper"; // this makes the background visible + actionOnMove = "1"; position = "0 0"; - Extent = "800 600"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; + extent = "1024 768"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; hovertime = "1000"; - DisplayMode = "Dropper"; // this makes the background visible - ActionOnMove = "1"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; new GuiWindowCtrl(GuiPickerDlg) { - canSaveDynamicFields = "0"; - isContainer = "1"; - Profile = "ToolsGuiWindowProfile"; - HorizSizing = "windowRelative"; - VertSizing = "windowRelative"; - position = "170 100"; - Extent = "348 347"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; text = "Color Picker"; - maxLength = "255"; resizeWidth = "0"; resizeHeight = "0"; canMove = "1"; canClose = "1"; canMinimize = "0"; canMaximize = "0"; - minSize = "50 50"; + canCollapse = "0"; closeCommand = "DoColorPickerCancelCallback(); ColorPickerDlg.getRoot().popDialog(ColorPickerDlg);"; - + position = "170 100"; + extent = "439 317"; + minExtent = "8 2"; + horizSizing = "windowRelative"; + vertSizing = "windowRelative"; + profile = "ToolsGuiWindowProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + new GuiBitmapBorderCtrl(){ // color blend - Profile = "ToolsGuiGroupBorderProfile"; position = "3 24"; - Extent = "255 258"; + extent = "255 258"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiGroupBorderProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiColorPickerCtrl(ColorBlendSelect) { + baseColor = "1 0 0 1"; + pickColor = "0 0 0 1"; + selectorGap = "1"; + displayMode = "BlendColor"; + actionOnMove = "1"; + position = "1 0"; + extent = "255 258"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "updateRGBValues(1);"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; new GuiBitmapBorderCtrl(){ // Hue - Profile = "ToolsGuiGroupBorderProfile"; position = "263 23"; - Extent = "25 261"; - }; - new GuiBitmapBorderCtrl(){ // new old color - Profile = "ToolsGuiGroupBorderProfile"; - position = "292 37"; - Extent = "52 99"; - }; - new GuiBitmapBorderCtrl(){ // rgb - Profile = "ToolsGuiGroupBorderProfile"; - position = "292 209"; - Extent = "52 75"; - }; - new GuiBitmapBorderCtrl(){ // alpha - Profile = "ToolsGuiGroupBorderProfile"; - position = "3 287"; - Extent = "341 24"; - }; - new GuiColorPickerCtrl(ColorBlendSelect) { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "3 24"; - Extent = "255 258"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - command = "updateRGBValues(1);"; + extent = "25 261"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiGroupBorderProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; hovertime = "1000"; - baseColor = "1 0 0 1"; - PickColor = "0 0 0 1"; - SelectorGap = "1"; - DisplayMode = "BlendColor"; - ActionOnMove = "1"; - }; - new GuiColorPickerCtrl(ColorRangeSelect) { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "264 24"; - Extent = "21 257"; - MinExtent = "8 2"; + isContainer = "1"; canSave = "1"; - Visible = "1"; - Command = "updatePickerBaseColor(1);"; - hovertime = "1000"; - baseColor = "1 0 0 1"; - PickColor = "1 0 0 1"; - SelectorGap = "1"; - DisplayMode = "VertColor"; - ActionOnMove = "1"; - }; - new GuiTextCtrl() { canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "298 215"; - Extent = "8 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; - text = "R"; - maxLength = "255"; - }; - new GuiTextEditCtrl(Channel_R_Val) { // Red Channal - Profile = "ToolsGuiNumericTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "307 215"; - Extent = "34 18"; - text = "0"; - maxLength = "4"; - altCommand = "setColorInfo();"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "297 238"; - Extent = "8 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; - text = "G"; - maxLength = "255"; - }; - new GuiTextEditCtrl(Channel_G_Val) { // Green Channal - Profile = "ToolsGuiNumericTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "307 238"; - Extent = "34 18"; - text = "0"; - maxLength = "4"; - altCommand = "setColorInfo();"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "298 261"; - Extent = "8 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; - text = "B"; - maxLength = "255"; - }; - new GuiTextEditCtrl(Channel_B_Val) { // Blue Channal - Profile = "ToolsGuiNumericTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "307 261"; - Extent = "34 18"; - text = "0"; - maxLength = "4"; - altCommand = "setColorInfo();"; - }; - - - new GuiControl() { - class = "AggregateControl"; - position = "2 290"; - Extent = "341 18"; - - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "267 0"; - Extent = "29 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; + + new GuiColorPickerCtrl(ColorRangeSelect) { + baseColor = "1 0 0 1"; + pickColor = "1 0 0 1"; + selectorGap = "1"; + displayMode = "VertColor"; + actionOnMove = "1"; + position = "1 1"; + extent = "21 257"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "updatePickerBaseColor(1);"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; hovertime = "1000"; - text = "Alpha"; - maxLength = "255"; - }; - new GuiSliderCtrl(ColorAlphaSelect) { - internalName = "slider"; - canSaveDynamicFields = "0"; isContainer = "0"; - Profile = "ToolsGuiSliderProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "5 3"; - Extent = "251 13"; - MinExtent = "8 2"; canSave = "1"; - Visible = "1"; - altCommand = "$ThisControl.getParent().updateFromChild($ThisControl); updateColorPickerAlpha( $ThisControl.getValue() );"; - hovertime = "1000"; - range = "0 1"; - ticks = "0"; - value = "1"; - }; - new GuiTextEditCtrl(Channel_A_Val) { // Alpha Channal - internalName = "textEdit"; - Profile = "ToolsGuiNumericTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "305 0"; - Extent = "34 18"; - text = "0"; - maxLength = "4"; - altCommand = "$ThisControl.getParent().updateFromChild($ThisControl); updateColorPickerAlpha( $ThisControl.getValue() );"; + canSaveDynamicFields = "0"; }; }; - new GuiSwatchButtonCtrl(myColor){ // New Color // - Profile = "ToolsGuiDefaultProfile"; - position = "293 38"; - Extent = "50 50"; - }; - new GuiTextCtrl(){ - Profile = "ToolsGuiDefaultProfile"; + new GuiTextCtrl() { text = "New"; position = "306 22"; - Extent = "26 14"; + extent = "26 14"; + profile = "GuiDefaultProfile"; }; - new GuiSwatchButtonCtrl(oldColor){ // Old Color // - Profile = "ToolsGuiDefaultProfile"; - position = "293 85"; - Extent = "50 50"; + new GuiBitmapBorderCtrl(){ // new old color + position = "292 37"; + extent = "52 99"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiGroupBorderProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiSwatchButtonCtrl(myColor){ // New Color // + position = "1 1"; + extent = "50 50"; + profile = "GuiDefaultProfile"; + }; + new GuiSwatchButtonCtrl(oldColor){ // Old Color // + position = "1 48"; + extent = "50 50"; + profile = "GuiDefaultProfile"; + }; }; - new GuiTextCtrl(){ - Profile = "ToolsGuiDefaultProfile"; + new GuiTextCtrl() { text = "Old"; position = "310 138"; - Extent = "26 14"; + extent = "26 14"; + profile = "GuiDefaultProfile"; + }; + new GuiBitmapBorderCtrl(){ // Color Text Fields + position = "291 165"; + extent = "141 118"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiGroupBorderProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiControl() { // rgb + position = "4 0"; + extent = "52 75"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "R"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "5 6"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Red Channel color value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_R_Val) { // Red Channal + text = "0"; + maxLength = "4"; + position = "14 6"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + class = "ColorPickerRGBClass"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Red Channel color value."; + }; + new GuiTextCtrl() { + text = "G"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "4 29"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Green Channel color value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_G_Val) { // Green Channal + text = "0"; + maxLength = "4"; + position = "14 29"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + class = "ColorPickerRGBClass"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Green Channel color value."; + }; + new GuiTextCtrl() { + text = "B"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "5 52"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Blue Channel color value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_B_Val) { // Blue Channal + text = "0"; + maxLength = "4"; + position = "14 52"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + class = "ColorPickerRGBClass"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Blue Channel color value."; + }; + }; + new GuiControl() { + position = "71 0"; + extent = "61 75"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "H"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "5 6"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Hue Channel color value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_H_Val) { // Hue Channal + text = "0"; + maxLength = "4"; + position = "14 6"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + class = "ColorPickerHSBClass"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Hue Channel color value."; + }; + new GuiTextCtrl() { + text = "o"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "51 2"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "S"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "4 29"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Saturation Channel color value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_S_Val) { // Saturation Channal + text = "0"; + maxLength = "4"; + position = "14 29"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + class = "ColorPickerHSBClass"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Saturation Channel color value."; + }; + new GuiTextCtrl() { + text = "%"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "51 29"; + extent = "10 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "B"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "5 52"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Brightness Channel color value. Aka value or lightness."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_Br_Val) { // Brightness Channal + text = "0"; + maxLength = "4"; + position = "14 52"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + class = "ColorPickerHSBClass"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Brightness Channel color value. Aka value or lightness."; + }; + new GuiTextCtrl() { + text = "%"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "51 52"; + extent = "10 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiControl() { + position = "3 87"; + extent = "138 24"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "#"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "3 5"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Hex representation of Red, Green, Blue Color value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(HexColor_Val) { // Hex Color Field + text = "0"; + maxLength = "6"; + position = "13 5"; + extent = "116 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Hex representation of Red, Green, Blue Color value."; + command = "$thisControl.onKeyDown();"; + }; + }; + }; + new GuiBitmapBorderCtrl(){ // alpha + position = "3 287"; + extent = "429 24"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiGroupBorderProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiControl() { + position = "-1 3"; + extent = "428 18"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + class = "AggregateControl"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiSliderCtrl(ColorAlphaSelect) { + range = "0 1"; + ticks = "0"; + value = "1"; + position = "5 3"; + extent = "341 13"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderProfile"; + visible = "1"; + active = "1"; + altCommand = "$ThisControl.getParent().updateFromChild($ThisControl); updateColorPickerAlpha( $ThisControl.getValue() );"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "slider"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Alpha"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "355 0"; + extent = "28 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_A_Val) { // Alpha Channal + text = "0"; + maxLength = "4"; + position = "392 0"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + altCommand = "$ThisControl.getParent().updateFromChild($ThisControl); updateColorPickerAlpha( $ThisControl.getValue() );"; + internalName = "TextEdit"; + }; + }; }; new GuiButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiButtonProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "144 316"; - Extent = "115 24"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "DoColorPickerCallback();"; - hovertime = "1000"; text = "Select"; groupNum = "-1"; buttonType = "PushButton"; useMouseEvents = "0"; + position = "349 37"; + extent = "84 24"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiButtonProfile"; + visible = "1"; + active = "1"; + command = "DoColorPickerCallback();"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; }; new GuiButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiButtonProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "268 316"; - Extent = "73 24"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "DoColorPickerCancelCallback();"; - hovertime = "1000"; text = "Cancel"; groupNum = "-1"; buttonType = "PushButton"; useMouseEvents = "0"; + position = "349 68"; + extent = "84 24"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiButtonProfile"; + visible = "1"; + active = "1"; + command = "DoColorPickerCancelCallback();"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; }; }; }; @@ -294,26 +727,6 @@ $ColorPickerCancelCallback = ""; $ColorPickerUpdateCallback = ""; $ColorCallbackType = 1; // ColorI -function ColorFloatToInt( %color ) -{ - %red = getWord( %color, 0 ); - %green = getWord( %color, 1 ); - %blue = getWord( %color, 2 ); - %alpha = getWord( %color, 3 ); - - return mCeil( %red * 255 ) SPC mCeil( %green * 255 ) SPC mCeil( %blue * 255 ) SPC mCeil( %alpha * 255 ); -} - -function ColorIntToFloat( %color ) -{ - %red = getWord( %color, 0 ); - %green = getWord( %color, 1 ); - %blue = getWord( %color, 2 ); - %alpha = getWord( %color, 3 ); - - return ( %red / 255 ) SPC ( %green / 255 ) SPC ( %blue / 255 ) SPC ( %alpha / 255 ); -} - // This function pushes the color picker dialog and returns to a callback the selected value function GetColorI( %currentColor, %callback, %root, %updateCallback, %cancelCallback ) { @@ -333,15 +746,18 @@ function GetColorI( %currentColor, %callback, %root, %updateCallback, %cancelCal ColorAlphaSelect.range = "0 255"; // Set the RGBA displays accordingly - %red = getWord(%currentColor, 0) / 255; - %green = getWord(%currentColor, 1) / 255; - %blue = getWord(%currentColor, 2) / 255; + %red = getWord(%currentColor, 0); + %green = getWord(%currentColor, 1); + %blue = getWord(%currentColor, 2); %alpha = getWord(%currentColor, 3); - // set the initial range blend to correct color, no alpha needed - // this should also set the color blend select right now - ColorRangeSelect.baseColor = %red SPC %green SPC %blue SPC "1.0"; - ColorRangeSelect.updateColor(); + //Set the red green blue text fields + Channel_R_Val.setValue(%red); + Channel_G_Val.setValue(%green); + Channel_B_Val.setValue(%blue); + + //Have the rgb text fields update the rest + Channel_R_Val.onValidate(); if(!isObject(%root)) %root = Canvas; @@ -371,15 +787,18 @@ function GetColorF( %currentColor, %callback, %root, %updateCallback, %cancelCal ColorAlphaSelect.range = "0 1"; // Set the RGBA displays accordingly - %red = getWord(%currentColor, 0); - %green = getWord(%currentColor, 1); - %blue = getWord(%currentColor, 2); - %alpha = getWord(%currentColor, 3); + %red = mRoundColour(getWord(%currentColor, 0), 3); + %green = mRoundColour(getWord(%currentColor, 1), 3); + %blue = mRoundColour(getWord(%currentColor, 2), 3); + %alpha = mRoundColour(getWord(%currentColor, 3), 3); - // set the initial range blend to correct color, no alpha needed - // this should also set the color blend select right now - ColorRangeSelect.baseColor = %red SPC %green SPC %blue SPC "1.0"; - ColorRangeSelect.updateColor(); + //Set the red green blue text fields + Channel_R_Val.setValue(%red); + Channel_G_Val.setValue(%green); + Channel_B_Val.setValue(%blue); + + //Have the rgb text fields update the rest + Channel_R_Val.onValidate(); if(!isObject(%root)) %root = Canvas; @@ -390,6 +809,133 @@ function GetColorF( %currentColor, %callback, %root, %updateCallback, %cancelCal Channel_A_Val.setText( %alpha ); } +function ColorPickerRGBClass::onValidate(%this) +{ + %red = Channel_R_Val.getValue(); + %green = Channel_G_Val.getValue(); + %blue = Channel_B_Val.getValue(); + + //Rest of the fields just do everything with ints so convert + if( $ColorCallbackType != 1 ) + { + %rgb = ColorFloatToInt(%red SPC %green SPC %blue SPC "1.0"); + %red = getWord(%rgb, 0); + %green = getWord(%rgb, 1); + %blue = getWord(%rgb, 2); + } + + //Update all the other color fields + %hsb = ColorRGBToHSB(%red SPC %green SPC %blue); + Channel_H_Val.setValue(getWord(%hsb, 0)); + Channel_S_Val.setValue(getWord(%hsb, 1)); + Channel_Br_Val.setValue(getWord(%hsb, 2)); + + %hex = ColorRGBToHEX(%red SPC %green SPC %blue); + HexColor_Val.setValue(%hex); + HexColor_Val.onKeyDown(); + + //Update everything else with our new color + setColorInfo(); +} + +function ColorPickerHSBClass::onValidate(%this) +{ + %hue = Channel_H_Val.getValue(); + %saturation = Channel_S_Val.getValue(); + %brightness = Channel_Br_Val.getValue(); + + //Update all the other color fields + %rgb = ColorHSBToRGB(%hue SPC %saturation SPC %brightness); + %hex = ColorRGBToHEX(%rgb); + HexColor_Val.setValue(%hex); + HexColor_Val.onKeyDown(); + + //convert to float for rgb if we need to + if( $ColorCallbackType != 1 ) + { + %rgb = ColorIntToFloat(%rgb); + } + %red = getWord(%rgb, 0); + %green = getWord(%rgb, 1); + %blue = getWord(%rgb, 2); + Channel_R_Val.setValue(%red); + Channel_G_Val.setValue(%green); + Channel_B_Val.setValue(%blue); + + //Update everything else with our new color + setColorInfo(); +} + +function HexColor_Val::onKeyDown(%this) +{ + //Get the value + %value = %this.getValue(); + + //It's hex so keep it all uppercase + %value = strupr(%value); + %pos = %this.getCursorPos(); + %this.setValue(%value); + %this.setCursorPos(%pos); + + //Verify that it's a hex value + %value = stripChars(%value, "0123456789ABCDEF"); + if(%value $= "") + { + %this.validText(); + } + else + { + %this.invalidText(false); + } +} + +function HexColor_Val::onValidate(%this) +{ + //if the current text is invalid don't do anyting + if(!%this.isValidText()) + { + %this.invalidText(true); + return; + } + + //Get the current value + %hex = %this.getValue(); + + //Make sure we have 6 characters + while(strlen(%hex) < 6) + { + %hex = "0" @ %hex; + } + %hex = strupr(%hex); + + //Update the value in case there were missing characters + %this.setValue(%hex); + + //Update all the other color fields + %rgb = ColorHEXToRGB(%hex); + %hsb = ColorRGBToHSB(%rgb); + + //convert to float for rgb if we need to + if( $ColorCallbackType != 1 ) + { + %rgb = ColorIntToFloat(%rgb); + } + + %red = getWord(%rgb, 0); + %green = getWord(%rgb, 1); + %blue = getWord(%rgb, 2); + Channel_R_Val.setValue(%red); + Channel_G_Val.setValue(%green); + Channel_B_Val.setValue(%blue); + + Channel_H_Val.setValue(getWord(%hsb, 0)); + Channel_S_Val.setValue(getWord(%hsb, 1)); + Channel_Br_Val.setValue(getWord(%hsb, 2)); + + //Update everything else with our new color + setColorInfo(); +} + // This function is used to update the text controls at the top function setColorInfo() { @@ -398,16 +944,40 @@ function setColorInfo() %blue = Channel_B_Val.getValue(); if( $ColorCallbackType == 1) - { - %red = (%red / 255); - %green = (%green / 255); - %blue = (%blue / 255); - } + %rgb = ColorIntToFloat(%red SPC %green SPC %blue SPC "255"); + else + %rgb = %red SPC %green SPC %blue SPC "1.0"; - $ColorPickerSignal = 1; + $ColorPickerSignal = 0; - ColorBlendSelect.baseColor = %red SPC %green SPC %blue SPC "1.0"; + //Convert color over to hue color + %hsb = ColorRGBToHSB(ColorFloatToInt(%rgb)); + %tempColor = ColorHSBToRGB( getWord(%hsb, 0) SPC 100 SPC 50); + %tempColor = ColorIntToFloat(setWord(%tempColor, 3, 255)); + + //Make sure all the text fields and everything don't update because of the cursors + ColorRangeSelect.update = false; + ColorBlendSelect.update = false; + + //Set values for the hue color picker + ColorRangeSelect.baseColor = %tempColor; + ColorRangeSelect.pickColor = %tempColor; + ColorRangeSelect.updateColor(); + + //Set the cursor for the hue picker + ColorRangeSelect.setSelectorColor(%tempColor); + + //Set the values for the gradient color picker + ColorBlendSelect.baseColor = %tempColor; + ColorBlendSelect.pickColor = %rgb; ColorBlendSelect.updateColor(); + + //Set the cursor for the gradiant color picker + ColorBlendSelect.setSelectorColor(%rgb); + + //Update our current color + %alpha = getWord(myColor.color, 3); + myColor.color = setWord(%rgb, 3, %alpha); } // return mycolor.color @@ -433,11 +1003,17 @@ function DoColorPickerUpdateCallback() // this is called from ColorRangeSelect.updateColor function updatePickerBaseColor( %location ) { + if(!ColorRangeSelect.update) + { + ColorRangeSelect.update = true; + return; + } + if( $ColorPickerSignal && %location ) %pickColor = ColorRangeSelect.baseColor; else %pickColor = ColorRangeSelect.pickColor; - $ColorPickerSignal = 1; + $ColorPickerSignal = 0; %red = getWord(%pickColor, 0); %green = getWord(%pickColor, 1); @@ -451,6 +1027,12 @@ function updatePickerBaseColor( %location ) // this is called from ColorBlendSelect.updateColor function updateRGBValues( %location ) { + if(!ColorBlendSelect.update) + { + ColorBlendSelect.update = true; + return; + } + //update the color based on where it came from if( $ColorPickerSignal && %location ) %pickColor = ColorBlendSelect.baseColor; @@ -465,7 +1047,7 @@ function updateRGBValues( %location ) %alpha = getWord(myColor.color, 3); // set the color! - myColor.color = %red SPC %green SPC %blue SPC %alpha ; + myColor.color = %red SPC %green SPC %blue SPC %alpha; DoColorPickerUpdateCallback(); @@ -488,6 +1070,25 @@ function updateRGBValues( %location ) Channel_G_Val.setValue(%green); Channel_B_Val.setValue(%blue); + //Rest of the fields just do everything with ints so convert + if( $ColorCallbackType != 1 ) + { + %rgb = ColorFloatToInt(%red SPC %green SPC %blue SPC "1.0"); + %red = getWord(%rgb, 0); + %green = getWord(%rgb, 1); + %blue = getWord(%rgb, 2); + } + + //Update all the other color fields + %hsb = ColorRGBToHSB(%red SPC %green SPC %blue); + Channel_H_Val.setValue(getWord(%hsb, 0)); + Channel_S_Val.setValue(getWord(%hsb, 1)); + Channel_Br_Val.setValue(getWord(%hsb, 2)); + + %hex = ColorRGBToHEX(%red SPC %green SPC %blue); + HexColor_Val.setValue(%hex); + HexColor_Val.onKeyDown(); + $ColorPickerSignal = 0; } diff --git a/Templates/Empty/game/tools/gui/openFileDialog.ed.cs b/Templates/Empty/game/tools/gui/openFileDialog.ed.cs index b988d3361..50c7cdfcc 100644 --- a/Templates/Empty/game/tools/gui/openFileDialog.ed.cs +++ b/Templates/Empty/game/tools/gui/openFileDialog.ed.cs @@ -20,27 +20,38 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -function getLoadFilename(%filespec, %callback, %currentFile) -{ +function getLoadFilename(%filespec, %callback, %currentFile, %getRelative, %defaultPath) +{ + //If no default path passed in then try to get one from the file + if(%defaultPath $= "") + { + if ( filePath( %currentFile ) !$= "" ) + %defaultPath = filePath(%currentFile); + } + %dlg = new OpenFileDialog() { Filters = %filespec; DefaultFile = %currentFile; + DefaultPath = %defaultPath; ChangePath = false; MustExist = true; MultipleFiles = false; }; - if ( filePath( %currentFile ) !$= "" ) - %dlg.DefaultPath = filePath(%currentFile); - - if ( %dlg.Execute() ) + %ok = %dlg.Execute(); + if ( %ok ) { - eval(%callback @ "(\"" @ %dlg.FileName @ "\");"); + %file = %dlg.FileName; + if(%getRelative) + %file = strreplace(%file,getWorkingDirectory() @ "/", ""); + eval(%callback @ "(\"" @ %file @ "\");"); $Tools::FileDialogs::LastFilePath = filePath( %dlg.FileName ); } %dlg.delete(); + + return %ok; } // Opens a choose file dialog with format filters already loaded diff --git a/Templates/Empty/game/tools/worldEditor/gui/objectBuilderGui.ed.gui b/Templates/Empty/game/tools/worldEditor/gui/objectBuilderGui.ed.gui index ddf2ef68a..74f1200c6 100644 --- a/Templates/Empty/game/tools/worldEditor/gui/objectBuilderGui.ed.gui +++ b/Templates/Empty/game/tools/worldEditor/gui/objectBuilderGui.ed.gui @@ -980,7 +980,19 @@ function ObjectBuilderGui::buildObserverDropPoint(%this) //------------------------------------------------------------------------------ // System //------------------------------------------------------------------------------ - +function ObjectBuilderGui::buildVolumetricFog(%this) +{ + // Change this if you want to default to another Folder + // Otherwise every time you want to add a Fog you will go this. + %defShape = "/art/environment/Fog_Cube.dts"; + %this.lastPath=getMainDotCsDir() @ %defShape; + OBObjectName.setValue( "" ); + %this.objectClassName = "VolumetricFog"; + %this.addField( "shapeName", "TypeFile", "Shape (Fog volume)", "", "*.dts;*.dae"); + %this.addField("Scale", "TypePoint3", "Scale", "1 1 1"); + %this.addField("FogColor", "TypeColorI", "FogColor", "200 200 200 255"); + %this.process(); +} function ObjectBuilderGui::buildPhysicsEntity(%this) { %this.objectClassName = "PhysicsEntity"; diff --git a/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs b/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs index 9bc2cab15..dc5d7f991 100644 --- a/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs +++ b/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs @@ -46,6 +46,7 @@ function EWCreatorWindow::init( %this ) %this.registerMissionObject( "SFXEmitter", "Sound Emitter" ); %this.registerMissionObject( "Precipitation" ); %this.registerMissionObject( "ParticleEmitterNode", "Particle Emitter" ); + %this.registerMissionObject( "VolumetricFog", "Volumetric Fog" ); %this.registerMissionObject( "RibbonNode", "Ribbon" ); // Legacy features. Users should use Ground Cover and the Forest Editor. diff --git a/Templates/Full/game/art/datablocks/environment.cs b/Templates/Full/game/art/datablocks/environment.cs index 386703f67..c9d2b0a51 100644 --- a/Templates/Full/game/art/datablocks/environment.cs +++ b/Templates/Full/game/art/datablocks/environment.cs @@ -84,3 +84,15 @@ datablock LightningData(DefaultStorm) thunderSounds[2] = ThunderCrash3Sound; thunderSounds[3] = ThunderCrash4Sound; }; + +datablock ReflectorDesc( DefaultCubeDesc ) +{ + texSize = 256; + nearDist = 0.1; + farDist = 1000.0; + objectTypeMask = 0xFFFFFFFF; + detailAdjust = 1.0; + priority = 1.0; + maxRateMs = 15; + useOcclusionQuery = true; +}; diff --git a/Templates/Full/game/art/environment/FogMod_heavy.dds b/Templates/Full/game/art/environment/FogMod_heavy.dds new file mode 100644 index 000000000..197dd4332 Binary files /dev/null and b/Templates/Full/game/art/environment/FogMod_heavy.dds differ diff --git a/Templates/Full/game/art/environment/FogMod_light.dds b/Templates/Full/game/art/environment/FogMod_light.dds new file mode 100644 index 000000000..d726795fa Binary files /dev/null and b/Templates/Full/game/art/environment/FogMod_light.dds differ diff --git a/Templates/Full/game/art/environment/FogMod_med.dds b/Templates/Full/game/art/environment/FogMod_med.dds new file mode 100644 index 000000000..2b25d3263 Binary files /dev/null and b/Templates/Full/game/art/environment/FogMod_med.dds differ diff --git a/Templates/Full/game/art/environment/Fog_Cube.DAE b/Templates/Full/game/art/environment/Fog_Cube.DAE new file mode 100644 index 000000000..34cad9f48 --- /dev/null +++ b/Templates/Full/game/art/environment/Fog_Cube.DAE @@ -0,0 +1,177 @@ + + + + + Richard + OpenCOLLADA for 3ds Max; Version: 1.4.1; Revision: exported; Platform: x64; Configuration: Release_Max2011_static + file:///G:/Documents%20and%20Settings/Richard/Mijn%20documenten/3dsmax/scenes/FogVolumes.max + + 2014-08-16T10:10:23 + 2014-08-16T10:10:23 + + Z_UP + + + + + + + + 0 0 0 1 + + + 0.588 0.588 0.588 1 + + + 0.588 0.588 0.588 1 + + + 0.9 0.9 0.9 1 + + + 0 + + + 0 0 0 1 + + + 1 1 1 1 + + + 1 + + + + + + + + 0 + 0 + 0 + 1.5 + 0 + 3 + 1 + 0 + + + 1 + 1 + 0 + 0.1 + 0 + + + + + + + + + + + + + + + -0.85 -1 -0.85 0.85 -0.85 -1 -1 0.85 -0.85 0.85 0.85 -1 -0.85 -1 0.85 1 -0.85 0.85 -1 0.85 0.85 0.85 1 0.85 -1 -0.85 -0.85 -0.85 -0.85 -1 1 -0.85 -0.85 0.85 -1 -0.85 -0.85 1 -0.85 -0.85 0.85 -1 0.85 1 -0.85 1 0.85 -0.85 -0.85 -0.85 1 -1 -0.85 0.85 0.85 -0.85 1 0.85 -1 0.85 -0.85 0.85 1 -0.85 1 0.85 0.85 0.85 1 1 0.85 0.85 + + + + + + + + + + -0.341586 -0.341586 -0.8755786 -0.341586 0.341586 -0.8755788 0.341586 0.341586 -0.8755788 0.341586 -0.341586 -0.8755788 -0.341586 -0.341586 0.8755786 0.341586 -0.341586 0.8755788 0.341586 0.341586 0.8755788 -0.341586 0.341586 0.8755788 -0.341586 -0.8755786 -0.341586 0.341586 -0.8755788 -0.341586 0.341586 -0.8755786 0.341586 -0.341586 -0.8755788 0.341586 0.8755786 -0.341586 -0.341586 0.8755788 0.341586 -0.341586 0.8755786 0.341586 0.341586 0.8755788 -0.341586 0.341586 0.341586 0.8755786 -0.341586 -0.341586 0.8755788 -0.341586 -0.341586 0.8755786 0.341586 0.341586 0.8755788 0.341586 -0.8755786 0.341586 -0.341586 -0.8755788 -0.341586 -0.341586 -0.8755786 -0.341586 0.341586 -0.8755788 0.341586 0.341586 + + + + + + + + + + 0 0 0 1 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 1 0 1 1 0 0.07542458 0.07542461 4.99755e-4 0.07542479 0.07542461 4.99547e-4 0.07542455 0.07542461 4.99755e-4 0.07542461 0.9245752 4.99547e-4 0.07542458 0.9245754 4.99755e-4 0.07542458 0.9245754 0.9995003 0.07542455 0.9245754 4.99755e-4 0.07542455 0.9245754 0.9995003 0.9245752 0.07542461 4.99576e-4 0.9245754 0.07542479 4.99547e-4 0.07542458 0.07542461 0.9995003 0.9245752 0.07542461 4.99576e-4 0.9245752 0.07542461 0.9995004 0.9245752 0.9245754 4.99547e-4 0.07542455 0.07542461 0.9995003 0.9245752 0.07542461 0.9995004 0.07542461 0.07542479 0.9995005 0.9245752 0.9245754 4.99576e-4 0.9245752 0.07542461 0.9995005 0.9245752 0.9245754 4.99576e-4 0.07542479 0.9245754 0.9995005 0.9245752 0.9245754 0.9995004 0.9245754 0.9245752 0.9995005 0.9245752 0.9245754 0.9995004 0.9995003 0.07542461 0.07542458 0.9245752 4.99547e-4 0.07542461 0.9245752 4.99547e-4 0.07542461 0.9995003 0.07542461 0.07542458 0.9995003 0.07542461 0.9245754 0.9245752 4.99547e-4 0.9245754 0.9245752 4.99547e-4 0.9245754 0.9995003 0.07542461 0.9245754 0.9995003 0.9245754 0.07542458 0.9245752 0.9995005 0.07542461 0.9995003 0.9245754 0.07542458 0.9245752 0.9995005 0.07542461 0.9995003 0.9245754 0.9245754 0.9245752 0.9995005 0.9245754 0.9995003 0.9245754 0.9245754 0.9245752 0.9995005 0.9245754 0.9995004 0.07542482 0.07542461 0.9995003 0.9245754 0.07542461 0.9245752 0.9995004 0.07542461 0.07542455 0.9995003 0.07542461 4.99606e-4 0.9245752 0.07542461 4.99725e-4 0.07542458 0.07542461 0.07542479 4.99576e-4 0.07542461 0.9245754 4.99755e-4 0.07542461 0.07542458 4.99755e-4 0.9245754 0.9245752 4.99576e-4 0.9245754 0.9995003 0.07542458 0.9245754 0.9995004 0.9245752 0.9245754 0.9245754 0.9995003 0.9245754 0.07542482 0.9995004 0.9245754 4.99755e-4 0.9245754 0.9245754 4.99576e-4 0.07542482 0.9245754 0.9995003 0.07542461 0.07542458 0.9995003 0.9245754 0.07542458 0.9995003 0.9245754 0.07542458 0.9995003 0.07542461 0.07542458 0.9995003 0.07542461 0.9245754 0.9995003 0.9245754 0.9245754 0.9995003 0.07542461 0.9245754 0.9995003 0.9245754 0.9245754 + + + + + + + + + + -0.8644259 0.01841655 0.3300502 -0.8715108 -0.05526615 0.3184382 -0.8644259 0.01841664 -0.3300501 -0.8715108 -0.05526611 -0.3184382 0.8738725 -0.06754867 0.3145678 0.8597026 -0.006149054 -0.3377912 0.8738725 -0.06754874 -0.3145678 0.8597026 -0.006148929 0.3377911 0.883319 -0.2990854 -0.116681 0.8478944 0.3571441 -0.06756432 0.8597026 0.3377913 0.00614921 0.883319 -0.2990854 0.116681 0.2990854 0.883319 -0.116681 -0.3571441 0.8478944 -0.06756432 -0.3377913 0.8597026 0.00614921 0.2990854 0.883319 0.116681 -0.883319 0.2990854 -0.116681 -0.8478944 -0.3571441 -0.06756432 -0.8597026 -0.3377913 0.00614921 -0.883319 0.2990854 0.116681 -0.2990854 -0.883319 -0.116681 0.3571441 -0.8478944 -0.06756432 0.3377913 -0.8597026 0.00614921 -0.2990854 -0.883319 0.116681 0.8360862 -0.3764972 0.1289794 0.7071068 -0.7071068 0 0.7071068 0.7071068 0 0.3764972 0.8360862 0.1289794 -0.3764972 -0.8360862 0.1289794 -0.7071068 -0.7071068 0 -0.7071068 0.7071068 0 -0.8360862 0.3764972 0.1289794 0.8360862 -0.3764971 -0.1289794 0.7071068 -0.7071068 0 0.3764971 0.8360862 -0.1289794 0.7071068 0.7071068 0 -0.3764971 -0.8360862 -0.1289794 -0.7071068 -0.7071068 0 -0.8360862 0.3764971 -0.1289794 -0.7071068 0.7071068 0 -0.376497 0.1289792 0.8360862 -0.3764973 -0.1289798 0.8360861 -0.8833191 -0.2990855 0.1166808 -0.883319 0.2990853 -0.1166812 -0.3764971 0.1289794 -0.8360862 -0.3764972 -0.1289795 -0.8360862 -0.8833191 -0.2990855 -0.1166807 -0.883319 0.2990853 0.1166812 0.883319 -0.2990853 0.1166812 0.8833191 0.2990855 -0.1166807 0.3764971 0.1289797 -0.8360862 0.3764971 -0.1289793 -0.8360862 0.883319 -0.2990853 -0.1166811 0.8833191 0.2990855 0.1166808 0.3764972 0.1289799 0.8360861 0.3764971 -0.128979 0.8360862 0.3764972 0.8360862 0.1289794 0.3764971 0.8360862 -0.1289794 0.8360862 -0.3764971 -0.1289794 0.8360862 -0.3764972 0.1289794 -0.8360862 0.3764972 0.1289794 -0.8360862 0.3764971 -0.1289794 -0.3764972 -0.8360862 0.1289794 -0.3764971 -0.8360862 -0.1289794 + + + + + + + + + + 0.1043954 -0.9396398 0.3258505 -0.06496345 -0.9379679 -0.3405817 0.1043953 -0.9396398 -0.3258505 -0.06496349 -0.937968 0.3405817 0.05187585 -0.9370471 -0.3453283 -0.1307439 -0.939827 -0.3156443 0.05187577 -0.9370471 0.3453283 -0.1307438 -0.939827 0.3156443 0 0.3634471 -0.9316148 -0.196368 0.2889368 -0.9369926 0.1307441 -0.3156442 -0.939827 0 -0.3634471 -0.9316148 -0.3634471 0 -0.9316148 -0.2889368 -0.196368 -0.9369926 0.3156442 0.1307441 -0.939827 0.3634471 0 -0.9316148 0 -0.3634471 -0.9316148 0.196368 -0.2889368 -0.9369926 -0.1307441 0.3156442 -0.939827 0 0.3634471 -0.9316148 0.3634471 0 -0.9316148 0.2889368 0.196368 -0.9369926 -0.3156442 -0.1307441 -0.939827 -0.3634471 0 -0.9316148 0.2608475 0.2608475 -0.9294714 0.6191276 0.6191276 -0.4830755 -0.6191276 0.6191276 -0.4830755 -0.2608475 0.2608475 -0.9294714 0.2608475 -0.2608475 -0.9294714 0.6191276 -0.6191276 -0.4830755 -0.6191276 -0.6191276 -0.4830755 -0.2608475 -0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 -0.6191276 -0.6191276 -0.4830755 0.2608475 -0.2608475 -0.9294714 0.6191276 -0.6191276 -0.4830755 -0.2608475 0.2608475 -0.9294714 -0.6191276 0.6191276 -0.4830755 0.2608475 0.2608475 -0.9294714 0.6191276 0.6191276 -0.4830755 0.2608476 -0.9294715 0.2608473 -0.2608474 -0.9294714 -0.2608479 1.81809e-7 -0.363447 -0.9316149 2.27262e-7 -0.3634472 -0.9316148 0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 0.2608477 2.72714e-7 -0.363447 0.9316149 2.72714e-7 -0.3634472 0.9316148 2.72714e-7 -0.3634472 -0.9316148 2.72714e-7 -0.363447 -0.9316149 -0.2608474 -0.9294714 -0.2608478 0.2608476 -0.9294714 0.2608474 1.81809e-7 -0.3634472 0.9316148 2.27262e-7 -0.3634471 0.9316149 -0.2608473 -0.9294714 0.260848 0.2608477 -0.9294715 -0.2608472 -0.2608475 0.2608475 -0.9294714 0.2608475 -0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 0.2608475 0.2608475 -0.9294714 -0.2608475 -0.2608475 -0.9294714 0.2608475 0.2608475 -0.9294714 0.2608475 -0.2608475 -0.9294714 -0.2608475 0.2608475 -0.9294714 + + + + + + + + + + + + + + + + + +

9 0 21 0 13 1 25 1 3 2 15 2 3 2 15 2 1 3 13 3 9 0 21 0 16 4 28 4 18 5 30 5 22 6 34 6 22 6 34 6 20 7 32 7 16 4 28 4 0 8 12 8 11 9 23 9 19 10 31 10 19 10 31 10 4 11 16 11 0 8 12 8 10 12 22 12 15 13 27 13 23 14 35 14 23 14 35 14 5 15 17 15 10 12 22 12 14 16 26 16 12 17 24 17 21 18 33 18 21 18 33 18 7 19 19 19 14 16 26 16 2 20 14 20 8 21 20 21 17 22 29 22 17 22 29 22 6 23 18 23 2 20 14 20 0 8 36 24 8 21 20 21 9 0 37 25 1 3 38 26 10 12 39 27 11 9 23 9 2 20 40 28 12 17 24 17 13 1 41 29 3 2 42 30 14 16 43 31 15 13 27 13 4 11 44 32 16 4 45 33 17 22 29 22 5 15 46 34 18 5 47 35 19 10 31 10 6 23 48 36 20 7 49 37 21 18 33 18 7 19 50 38 22 6 51 39 23 14 35 14 9 0 21 0 8 21 52 40 2 20 53 41 2 20 53 41 13 1 25 1 9 0 21 0 13 1 25 1 12 17 54 42 14 16 55 43 14 16 55 43 3 2 15 2 13 1 25 1 3 2 15 2 15 13 56 44 10 12 57 45 10 12 57 45 1 3 13 3 3 2 15 2 1 3 13 3 11 9 58 46 0 8 59 47 0 8 59 47 9 0 21 0 1 3 13 3 16 4 28 4 4 11 60 48 19 10 61 49 19 10 61 49 18 5 30 5 16 4 28 4 18 5 30 5 5 15 62 50 23 14 63 51 23 14 63 51 22 6 34 6 18 5 30 5 22 6 34 6 7 19 64 52 21 18 65 53 21 18 65 53 20 7 32 7 22 6 34 6 20 7 32 7 6 23 66 54 17 22 67 55 17 22 67 55 16 4 28 4 20 7 32 7 11 9 23 9 10 12 68 56 5 15 69 57 5 15 69 57 19 10 31 10 11 9 23 9 4 11 70 58 17 22 29 22 8 21 20 21 8 21 20 21 0 8 71 59 4 11 70 58 15 13 27 13 14 16 72 60 7 19 73 61 7 19 73 61 23 14 35 14 15 13 27 13 12 17 24 17 2 20 74 62 6 23 75 63 6 23 75 63 21 18 33 18 12 17 24 17

+
+
+
+
+ + + + + 0 0 0 + + + + + + + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + +
\ No newline at end of file diff --git a/Templates/Full/game/art/environment/Fog_Cube.cs b/Templates/Full/game/art/environment/Fog_Cube.cs new file mode 100644 index 000000000..3c686032c --- /dev/null +++ b/Templates/Full/game/art/environment/Fog_Cube.cs @@ -0,0 +1,8 @@ + +singleton TSShapeConstructor(Fog_CubeDAE) +{ + baseShape = "./Fog_Cube.DAE"; + lodType = "TrailingNumber"; + neverImport = "env*"; + loadLights = "0"; +}; diff --git a/Templates/Full/game/art/environment/LightVolume_Sphere.DAE b/Templates/Full/game/art/environment/LightVolume_Sphere.DAE new file mode 100644 index 000000000..81c93d8e0 --- /dev/null +++ b/Templates/Full/game/art/environment/LightVolume_Sphere.DAE @@ -0,0 +1,423 @@ + + + + + Richard + OpenCOLLADA for 3ds Max; Version: 1.4.1; Revision: exported; Platform: x64; Configuration: Release_Max2011_static + file:///G:/Documents%20and%20Settings/Richard/Mijn%20documenten/3dsmax/scenes/lightfog.max + + 2014-08-22T22:51:35 + 2014-08-22T22:51:35 + + Z_UP + + + + + + + + 0 0 0 1 + + + 0.588 0.588 0.588 1 + + + 0.588 0.588 0.588 1 + + + 0.9 0.9 0.9 1 + + + 0 + + + 0 0 0 1 + + + 1 1 1 1 + + + 1 + + + + + + + + 0 + 0 + 0 + 1.5 + 0 + 3 + 1 + 0 + + + 1 + 1 + 0 + 0.1 + 0 + + + + + + + + + + + + + + + 0 0 5 -9.48283e-8 2.169419 4.504844 -0.9412758 1.954579 4.504844 -1.69612 1.35261 4.504844 -2.115027 0.4827411 4.504844 -2.115027 -0.482741 4.504844 -1.69612 -1.35261 4.504844 -0.9412759 -1.954579 4.504844 2.58701e-8 -2.169419 4.504844 0.9412759 -1.954579 4.504844 1.696121 -1.35261 4.504844 2.115027 -0.4827399 4.504844 2.115026 0.4827427 4.504844 1.696119 1.352612 4.504844 0.9412734 1.95458 4.504844 -1.70875e-7 3.909158 3.117449 -1.69612 3.522029 3.117449 -3.056303 2.43732 3.117449 -3.811147 0.8698694 3.117449 -3.811147 -0.8698691 3.117449 -3.056303 -2.43732 3.117449 -1.696121 -3.522029 3.117449 4.66162e-8 -3.909158 3.117449 1.696121 -3.522029 3.117449 3.056304 -2.437319 3.117449 3.811147 -0.8698672 3.117449 3.811146 0.8698722 3.117449 3.0563 2.437323 3.117449 1.696116 3.522031 3.117449 -2.13077e-7 4.87464 1.112604 -2.115027 4.391898 1.112604 -3.811147 3.039288 1.112604 -4.752422 1.084709 1.112604 -4.752422 -1.084709 1.112604 -3.811147 -3.039288 1.112604 -2.115028 -4.391898 1.112604 5.81295e-8 -4.87464 1.112604 2.115028 -4.391898 1.112604 3.811148 -3.039287 1.112604 4.752423 -1.084707 1.112604 4.752421 1.084713 1.112604 3.811144 3.039291 1.112604 2.115022 4.391901 1.112604 -2.13077e-7 4.87464 -1.112605 -2.115027 4.391898 -1.112605 -3.811147 3.039288 -1.112605 -4.752422 1.084709 -1.112605 -4.752422 -1.084709 -1.112605 -3.811147 -3.039288 -1.112605 -2.115028 -4.391898 -1.112605 5.81295e-8 -4.87464 -1.112605 2.115028 -4.391898 -1.112605 3.811148 -3.039287 -1.112605 4.752423 -1.084707 -1.112605 4.752421 1.084713 -1.112605 3.811144 3.039291 -1.112605 2.115022 4.391901 -1.112605 -1.70875e-7 3.909157 -3.11745 -1.69612 3.522028 -3.11745 -3.056302 2.437319 -3.11745 -3.811146 0.8698692 -3.11745 -3.811146 -0.869869 -3.11745 -3.056302 -2.437319 -3.11745 -1.69612 -3.522028 -3.11745 4.66162e-8 -3.909157 -3.11745 1.69612 -3.522028 -3.11745 3.056303 -2.437318 -3.11745 3.811146 -0.8698671 -3.11745 3.811145 0.8698721 -3.11745 3.0563 2.437322 -3.11745 1.696116 3.52203 -3.11745 -9.48283e-8 2.169418 -4.504845 -0.9412755 1.954578 -4.504845 -1.696119 1.35261 -4.504845 -2.115026 0.4827409 -4.504845 -2.115026 -0.4827408 -4.504845 -1.69612 -1.35261 -4.504845 -0.9412756 -1.954578 -4.504845 2.58701e-8 -2.169418 -4.504845 0.9412756 -1.954578 -4.504845 1.69612 -1.352609 -4.504845 2.115026 -0.4827397 -4.504845 2.115026 0.4827425 -4.504845 1.696118 1.352612 -4.504845 0.9412731 1.954579 -4.504845 0 0 -5 + + + + + + + + + + 3.34297e-8 3.12427e-8 1 -1.46401e-7 0.4589442 0.8884651 -0.1991285 0.4134944 0.888465 -0.358817 0.286147 0.8884651 -0.4474375 0.1021247 0.888465 -0.4474375 -0.1021246 0.8884651 -0.358817 -0.286147 0.888465 -0.1991284 -0.4134944 0.8884651 -4.96273e-9 -0.4589442 0.888465 0.1991285 -0.4134944 0.888465 0.3588171 -0.2861469 0.888465 0.4474375 -0.1021244 0.8884651 0.4474374 0.102125 0.888465 0.3588168 0.2861473 0.8884651 0.1991281 0.4134945 0.8884651 -2.38195e-7 0.7935484 0.6085071 -0.3443078 0.7149624 0.6085071 -0.6204212 0.4947692 0.6085072 -0.7736526 0.1765811 0.6085071 -0.7736526 -0.176581 0.608507 -0.6204212 -0.4947692 0.6085072 -0.3443078 -0.7149624 0.6085071 -1.26699e-8 -0.7935485 0.6085071 0.3443078 -0.7149624 0.6085072 0.6204213 -0.4947691 0.6085071 0.7736526 -0.1765807 0.6085072 0.7736524 0.1765818 0.6085072 0.6204207 0.4947699 0.608507 0.3443072 0.7149627 0.6085071 -2.56849e-7 0.9764001 0.2159697 -0.4236442 0.879706 0.2159697 -0.7633804 0.6087754 0.2159697 -0.9519197 0.2172694 0.2159697 -0.9519197 -0.2172693 0.2159698 -0.7633804 -0.6087753 0.2159698 -0.4236441 -0.8797061 0.2159698 2.56849e-9 -0.9764001 0.2159697 0.4236443 -0.879706 0.2159698 0.7633805 -0.6087751 0.2159698 0.9519198 -0.2172689 0.2159698 0.9519196 0.2172702 0.2159698 0.7633796 0.6087762 0.2159697 0.4236434 0.8797064 0.2159697 -2.56849e-7 0.9764 -0.2159699 -0.4236442 0.8797059 -0.2159699 -0.7633803 0.6087754 -0.2159699 -0.9519196 0.2172694 -0.2159698 -0.9519197 -0.2172693 -0.2159699 -0.7633804 -0.6087753 -0.2159699 -0.4236442 -0.879706 -0.2159699 2.31164e-8 -0.9764 -0.2159699 0.4236442 -0.8797059 -0.2159699 0.7633805 -0.6087751 -0.2159699 0.9519197 -0.2172689 -0.2159699 0.9519195 0.2172701 -0.2159699 0.7633796 0.6087762 -0.2159699 0.4236434 0.8797063 -0.2159699 -1.95117e-7 0.7935483 -0.6085073 -0.3443078 0.7149623 -0.6085073 -0.6204211 0.4947692 -0.6085073 -0.7736524 0.1765811 -0.6085073 -0.7736524 -0.1765811 -0.6085073 -0.6204211 -0.4947692 -0.6085073 -0.3443078 -0.7149622 -0.6085073 1.77379e-8 -0.7935483 -0.6085073 0.3443078 -0.7149622 -0.6085073 0.6204212 -0.494769 -0.6085073 0.7736525 -0.1765806 -0.6085073 0.7736523 0.1765817 -0.6085073 0.6204206 0.4947698 -0.6085073 0.3443071 0.7149625 -0.6085073 -1.16624e-7 0.4589441 -0.8884652 -0.1991284 0.4134943 -0.8884652 -0.358817 0.2861468 -0.8884652 -0.4474374 0.1021247 -0.8884652 -0.4474373 -0.1021246 -0.8884652 -0.3588169 -0.2861468 -0.8884652 -0.1991284 -0.4134943 -0.8884652 -9.92546e-9 -0.4589441 -0.8884651 0.1991285 -0.4134943 -0.8884651 0.358817 -0.2861468 -0.8884652 0.4474374 -0.1021244 -0.8884651 0.4474373 0.102125 -0.8884652 0.3588167 0.2861473 -0.8884651 0.1991281 0.4134944 -0.8884652 2.59315e-8 -2.62439e-8 -1 + + + + + + + + + + -0.03571416 1 0.999001 3.79455e-8 0.8571429 0.999001 0.0714286 0.8571428 0.9990011 0.1428572 0.8571428 0.9990011 0.2142857 0.8571428 0.9990011 0.2857142 0.8571428 0.9990011 0.3571428 0.8571428 0.9990011 0.4285714 0.8571428 0.9990011 0.4999999 0.8571429 0.999001 0.5714285 0.8571429 0.999001 0.6428571 0.8571429 0.999001 0.7142857 0.8571429 0.999001 0.7857143 0.8571429 0.999001 0.857143 0.8571429 0.999001 0.9285716 0.8571429 0.999001 1 0.7142857 0.9990011 0.0714286 0.7142857 0.9990011 0.1428572 0.7142857 0.9990011 0.2142857 0.7142857 0.9990011 0.2857142 0.7142857 0.9990011 0.3571428 0.7142857 0.9990011 0.4285714 0.7142857 0.9990011 0.5 0.7142857 0.9990011 0.5714285 0.7142857 0.999001 0.6428571 0.7142857 0.999001 0.7142857 0.7142857 0.9990009 0.7857143 0.7142857 0.999001 0.857143 0.7142857 0.999001 0.9285716 0.7142857 0.999001 0.9999999 0.5714285 0.999001 0.0714286 0.5714285 0.999001 0.1428572 0.5714285 0.9990011 0.2142857 0.5714285 0.9990011 0.2857142 0.5714285 0.9990011 0.3571428 0.5714285 0.9990011 0.4285714 0.5714285 0.9990011 0.5 0.5714285 0.999001 0.5714285 0.5714285 0.999001 0.6428571 0.5714285 0.999001 0.7142857 0.5714285 0.9990009 0.7857143 0.5714285 0.9990009 0.8571429 0.5714285 0.999001 0.9285716 0.5714285 0.999001 0.9999999 0.4285714 0.999001 0.0714286 0.4285714 0.999001 0.1428572 0.4285714 0.9990011 0.2142857 0.4285714 0.9990011 0.2857142 0.4285714 0.9990011 0.3571428 0.4285714 0.9990011 0.4285714 0.4285714 0.9990011 0.5 0.4285714 0.999001 0.5714285 0.4285714 0.999001 0.6428571 0.4285714 0.999001 0.7142857 0.4285714 0.999001 0.7857143 0.4285714 0.999001 0.8571429 0.4285714 0.999001 0.9285716 0.4285714 0.999001 1 0.2857142 0.999001 0.0714286 0.2857142 0.9990011 0.1428572 0.2857142 0.9990011 0.2142857 0.2857142 0.9990011 0.2857142 0.2857143 0.9990011 0.3571428 0.2857143 0.9990011 0.4285714 0.2857142 0.9990011 0.5 0.2857142 0.999001 0.5714285 0.2857142 0.999001 0.6428571 0.2857142 0.999001 0.7142857 0.2857142 0.999001 0.7857143 0.2857142 0.999001 0.857143 0.2857142 0.999001 0.9285716 0.2857142 0.999001 3.79455e-8 0.1428571 0.999001 0.0714286 0.1428572 0.9990011 0.1428572 0.1428571 0.999001 0.2142857 0.1428572 0.9990011 0.2857142 0.1428572 0.9990011 0.3571428 0.1428572 0.9990011 0.4285714 0.1428572 0.9990011 0.4999999 0.1428571 0.999001 0.5714285 0.1428571 0.999001 0.6428571 0.1428571 0.999001 0.7142857 0.1428571 0.999001 0.7857143 0.1428571 0.999001 0.857143 0.1428571 0.999001 0.9285716 0.1428571 0.999001 -0.03571416 0 0.999001 0.03571432 1 0.999001 0.1071429 1 0.999001 0.1785714 1 0.999001 0.25 1 0.999001 0.3214285 1 0.999001 0.3928571 1 0.999001 0.4642856 1 0.999001 0.5357142 1 0.999001 0.6071428 1 0.999001 0.6785715 1 0.999001 0.75 1 0.999001 0.8214287 1 0.999001 0.8928573 1 0.999001 -0.07142836 0.8571429 0.999001 0 0.7142857 0.9990011 -0.07142836 0.8571429 0.999001 0 0.7142857 0.9990011 0 0.7142857 0.9990011 -5.96046e-8 0.5714285 0.999001 0 0.7142857 0.9990011 -5.96046e-8 0.5714285 0.999001 -5.96046e-8 0.4285714 0.999001 -5.96046e-8 0.5714285 0.999001 -5.96046e-8 0.4285714 0.999001 0 0.2857142 0.999001 -5.96046e-8 0.4285714 0.999001 0 0.2857142 0.999001 0 0.2857142 0.999001 -0.07142836 0.2857142 0.999001 -0.07142836 0.1428571 0.999001 -0.07142836 0.2857142 0.999001 0 0.2857142 0.999001 0.03571432 0 0.999001 0.1071429 0 0.999001 0.1785714 0 0.999001 0.25 0 0.999001 0.3214285 0 0.999001 0.3928571 0 0.999001 0.4642856 0 0.999001 0.5357142 0 0.999001 0.6071428 0 0.999001 0.6785715 0 0.999001 0.75 0 0.999001 0.8214287 0 0.999001 0.8928573 0 0.999001 -0.07142836 0.1428571 0.999001 + + + + + + + + + + -0.9749277 -0.2225218 3.95437e-8 -0.9749279 -0.03513084 0.01814697 -0.8631371 -0.4546571 0.01814702 -0.7818314 -0.6234899 4.56159e-8 -0.5803916 -0.7841328 0.01814686 -0.4338837 -0.9009689 4.26533e-8 -0.1826924 -0.9583017 0.01814685 1.04443e-15 -1 3.12427e-8 0.2511913 -0.9426673 0.01814685 0.4338836 -0.900969 1.36441e-8 0.6353235 -0.740326 0.01814683 0.7818314 -0.6234899 -6.65688e-9 0.8936221 -0.3913545 0.01814665 0.9749277 -0.2225219 -2.56394e-8 0.9749278 0.03512998 0.01814669 0.9749279 0.222521 -3.95437e-8 0.8631371 0.4546568 0.01814684 0.7818313 0.62349 -4.56159e-8 0.5803913 0.7841329 0.01814687 0.4338832 0.9009691 -4.26533e-8 0.1826917 0.9583018 0.01814686 -7.40827e-7 1 -3.12427e-8 -0.2511921 0.942667 0.01814683 -0.4338844 0.9009686 -1.36441e-8 -0.6353242 0.7403254 0.01814688 -0.7818321 0.623489 6.65693e-9 -0.852976 0.4757568 -0.03024468 -0.974928 0.2225204 2.56394e-8 -0.9545922 0.2647484 0.09073415 -0.974928 -0.08239544 0.1074507 -0.8783796 -0.4230055 1.2098e-7 -0.6078575 -0.7622294 -2.40103e-8 -0.2169419 -0.9504844 3.08126e-9 0.2169418 -0.9504845 1.00124e-8 0.6078575 -0.7622294 -1.22219e-8 0.8783796 -0.4230055 2.27489e-8 0.9749279 -1.0315e-7 -1.14217e-7 0.8783796 0.4230055 2.7348e-8 0.6078573 0.7622295 2.9091e-8 0.2169413 0.9504846 1.53869e-8 -0.2169426 0.9504843 -1.74207e-8 -0.6078583 0.7622288 -1.32728e-8 -0.8783801 0.4230047 1.08194e-8 -0.974928 0.08239487 -0.1074508 -0.9545922 0.2647484 0.09073415 -0.974928 0.08239487 -0.1074508 -0.9749279 -0.08239547 0.1074508 -0.9749279 -0.01037927 0.04692359 -0.8783797 -0.4230054 1.38382e-9 -0.974928 -0.08239544 0.1074507 -0.6078575 -0.7622294 -2.5756e-9 -0.2169418 -0.9504845 -4.34778e-9 0.2169417 -0.9504845 7.21083e-10 0.6078575 -0.7622294 2.68537e-9 0.8783797 -0.4230054 -1.49521e-8 0.9749279 9.89275e-9 3.31305e-8 0.8783796 0.4230055 6.33846e-10 0.6078573 0.7622295 2.8277e-9 0.2169413 0.9504845 1.9462e-9 -0.2169426 0.9504842 3.51617e-9 -0.6078584 0.7622287 -1.28249e-8 -0.8783801 0.4230047 -3.55722e-8 -0.974928 0.01037875 -0.04692358 -0.9749279 -0.01037927 0.04692359 -0.9749279 -0.01037929 -0.04692363 -0.8783796 -0.4230055 7.11577e-9 -0.9749279 -0.01037927 0.04692359 -0.6078576 -0.7622294 -5.38627e-9 -0.2169418 -0.9504845 -4.0761e-8 0.2169417 -0.9504845 -6.37691e-9 0.6078574 -0.7622295 4.32713e-8 0.8783797 -0.4230054 4.91462e-8 0.9749279 7.86884e-9 6.87766e-8 0.8783796 0.4230055 7.54338e-8 0.6078573 0.7622295 -3.74104e-9 0.2169413 0.9504845 -6.87179e-10 -0.2169426 0.9504843 -5.06594e-9 -0.6078584 0.7622287 1.11192e-8 -0.8783801 0.4230047 -7.55682e-8 -0.974928 0.01037875 0.04692348 -0.9749279 -0.01037935 -0.04692387 -0.9749279 -0.08239562 -0.107451 -0.8783797 -0.4230055 5.99473e-9 -0.9749279 -0.01037929 -0.04692363 -0.6078575 -0.7622295 -5.14789e-8 -0.2169418 -0.9504844 -6.99784e-8 0.2169419 -0.9504845 -6.77193e-8 0.6078575 -0.7622295 8.75301e-8 0.8783796 -0.4230056 2.38485e-7 0.9749279 -3.58523e-8 7.51737e-8 0.8783796 0.4230055 1.39721e-9 0.6078573 0.7622295 6.92574e-8 0.2169412 0.9504845 -5.31509e-8 -0.2169425 0.9504843 -5.50918e-9 -0.6078583 0.7622288 -2.65355e-8 -0.8605051 0.4601225 0.05372539 -0.974928 0.08239491 0.1074507 -0.9749278 -0.08239586 -0.1074513 -0.9749279 0.03512977 0.0181467 -0.8936222 -0.3913543 0.01814683 -0.9749279 -0.08239562 -0.107451 -0.6353234 -0.740326 0.01814686 -0.2511912 -0.9426673 0.01814672 0.1826924 -0.9583017 0.01814681 0.5803915 -0.7841328 0.01814685 0.8631371 -0.454657 0.01814701 0.9749278 -0.03513059 0.01814698 0.8936221 0.3913542 0.01814686 0.6353234 0.7403261 0.01814691 0.2511908 0.9426673 0.01814683 -0.1826932 0.9583015 0.01814677 -0.5803923 0.7841322 0.01814686 -0.802168 0.5812611 0.09073409 -0.91413 0.3487692 -0.1074508 -0.9545922 0.2647484 -0.09073412 -0.91413 0.3487692 -0.1074508 -0.974928 0.08239496 0.1074508 -0.9749278 -0.2225216 -1.94415e-8 -0.7818317 -0.6234895 -3.91125e-9 -0.4338831 -0.9009692 1.23937e-8 -6.80542e-16 -1 2.62439e-8 0.4338836 -0.9009689 3.48962e-8 0.7818314 -0.6234899 3.66368e-8 0.9749278 -0.2225216 3.11211e-8 0.9749279 0.222521 1.94415e-8 0.7818313 0.6234901 3.91122e-9 0.4338837 0.9009689 -1.23937e-8 -1.19783e-6 1 -2.62439e-8 -0.4338844 0.9009685 -3.48962e-8 -0.7818321 0.623489 -3.66368e-8 -0.974928 0.2225205 -3.11211e-8 -0.9545922 0.2647484 -0.09073412 + + + + + + + + + + -0.2225218 0.9749277 -2.30205e-8 -0.04052453 0.8877353 -0.4585672 -0.4216851 0.7822389 -0.4585672 -0.6234899 0.7818314 -3.58345e-9 -0.7193257 0.5218109 -0.4585672 -0.9009689 0.4338837 1.65634e-8 -0.8744953 0.1580317 -0.4585672 -1 0 3.34297e-8 -0.8564605 -0.2370475 -0.4585672 -0.900969 -0.4338836 4.36748e-8 -0.6687932 -0.5851767 -0.4585672 -0.6234899 -0.7818314 4.52696e-8 -0.3486635 -0.8174044 -0.4585672 -0.2225219 -0.9749277 3.78982e-8 0.04052361 -0.8877353 -0.4585672 0.222521 -0.9749279 2.30206e-8 0.4216849 -0.7822391 -0.4585672 0.62349 -0.7818313 3.58345e-9 0.7193259 -0.5218107 -0.4585672 0.9009691 -0.4338832 -1.65634e-8 0.8744955 -0.1580312 -0.4585672 1 7.40827e-7 -3.34297e-8 0.8564603 0.2370483 -0.4585672 0.9009686 0.4338844 -4.36748e-8 0.6687926 0.5851774 -0.4585672 0.623489 0.7818321 -4.52696e-8 0.445375 0.7693955 -0.4578992 0.2225204 0.974928 -3.78982e-8 0.1987407 0.8707421 -0.4497891 -0.1375673 0.6027217 -0.7860037 -0.2640215 0.5482458 -0.7935484 -0.4757501 0.3793979 -0.7935484 -0.5932505 0.1354056 -0.7935484 -0.5932505 -0.1354055 -0.7935485 -0.4757501 -0.3793979 -0.7935484 -0.2640214 -0.5482459 -0.7935484 -1.5735e-7 -0.6085071 -0.7935484 0.2640215 -0.5482459 -0.7935484 0.4757502 -0.3793978 -0.7935484 0.5932507 -0.1354052 -0.7935484 0.5932505 0.135406 -0.7935484 0.4757496 0.3793984 -0.7935485 0.2640209 0.5482461 -0.7935484 0.1375669 0.6027217 -0.7860037 0.1987407 0.8707421 -0.4497891 0.137567 0.6027217 -0.7860037 -0.1375673 0.6027217 -0.7860037 -0.04923392 0.2157078 -0.975216 -0.09370578 0.194582 -0.9764001 -0.1375673 0.6027217 -0.7860037 -0.168852 0.1346549 -0.9764001 -0.2105549 0.04805777 -0.9764001 -0.2105549 -0.04805776 -0.9764001 -0.168852 -0.1346549 -0.9764001 -0.09370578 -0.194582 -0.9764001 3.5372e-8 -0.2159697 -0.9764001 0.09370579 -0.194582 -0.9764001 0.168852 -0.1346549 -0.9764 0.210555 -0.04805767 -0.9764 0.2105549 0.04805796 -0.9764 0.1688518 0.1346551 -0.9764001 0.09370564 0.1945821 -0.9764001 0.04923379 0.2157078 -0.975216 -0.04923392 0.2157078 -0.975216 0.04923396 -0.215708 -0.9752159 0.09370587 -0.1945822 -0.9764 -0.04923392 0.2157078 -0.975216 0.1688521 -0.134655 -0.9764 0.2105551 -0.04805776 -0.9764 0.210555 0.04805779 -0.9764 0.1688521 0.134655 -0.9764 0.0937059 0.1945822 -0.9764 6.71373e-8 0.2159699 -0.9764 -0.09370582 0.1945822 -0.9764 -0.1688522 0.134655 -0.9764 -0.2105552 0.04805771 -0.9764 -0.210555 -0.04805798 -0.9764 -0.1688519 -0.1346552 -0.9764 -0.09370562 -0.1945823 -0.9764 -0.0492337 -0.215708 -0.9752159 0.04923421 -0.215708 -0.9752159 0.1375676 -0.6027218 -0.7860035 0.2640215 -0.5482461 -0.7935483 0.04923396 -0.215708 -0.9752159 0.4757503 -0.379398 -0.7935483 0.5932507 -0.1354055 -0.7935483 0.5932507 0.1354057 -0.7935483 0.4757503 0.379398 -0.7935482 0.2640218 0.548246 -0.7935483 8.35655e-8 0.6085073 -0.7935483 -0.2640215 0.5482461 -0.7935483 -0.4757503 0.379398 -0.7935483 -0.5932509 0.1354052 -0.7935483 -0.5932507 -0.135406 -0.7935483 -0.4757498 -0.3793985 -0.7935483 -0.3258031 -0.5168711 -0.7916417 -0.1375669 -0.6027219 -0.7860036 0.137568 -0.6027218 -0.7860035 -0.04052343 -0.8877354 -0.458567 0.3486632 -0.8174045 -0.4585671 0.1375676 -0.6027218 -0.7860035 0.6687933 -0.5851768 -0.458567 0.8564606 -0.2370474 -0.4585671 0.8744955 0.1580318 -0.458567 0.7193258 0.5218109 -0.458567 0.4216851 0.782239 -0.458567 0.04052431 0.8877353 -0.4585671 -0.3486632 0.8174045 -0.4585671 -0.6687933 0.5851767 -0.458567 -0.8564607 0.2370471 -0.4585671 -0.8744953 -0.1580326 -0.458567 -0.7193253 -0.5218116 -0.4585671 -0.5568597 -0.6982815 -0.449789 -0.137567 -0.6027219 -0.7860035 -0.1987408 -0.8707422 -0.449789 -0.137567 -0.6027219 -0.7860035 -0.137567 -0.6027219 -0.7860036 0.2225216 -0.9749278 3.13562e-8 0.6234895 -0.7818317 3.66863e-8 0.9009692 -0.4338831 3.47502e-8 1 0 2.59315e-8 0.9009689 0.4338836 1.19766e-8 0.6234899 0.7818314 -4.35029e-9 0.2225216 0.9749278 -1.98156e-8 -0.222521 0.9749279 -3.13562e-8 -0.6234901 0.7818313 -3.66863e-8 -0.9009689 0.4338837 -3.47502e-8 -1 -1.19783e-6 -2.59314e-8 -0.9009685 -0.4338844 -1.19766e-8 -0.623489 -0.7818321 4.35033e-9 -0.2225205 -0.974928 1.98156e-8 -0.1987408 -0.8707422 -0.449789 + + + + + + + + + + + + + + + + + +

0 0 86 0 1 1 1 1 2 2 2 2 0 0 87 3 2 2 2 2 3 3 3 4 0 0 88 5 3 3 3 4 4 4 4 6 0 0 89 7 4 4 4 6 5 5 5 8 0 0 90 9 5 5 5 8 6 6 6 10 0 0 91 11 6 6 6 10 7 7 7 12 0 0 92 13 7 7 7 12 8 8 8 14 0 0 93 15 8 8 8 14 9 9 9 16 0 0 94 17 9 9 9 16 10 10 10 18 0 0 95 19 10 10 10 18 11 11 11 20 0 0 96 21 11 11 11 20 12 12 12 22 0 0 97 23 12 12 12 22 13 13 13 24 0 0 98 25 13 13 13 24 14 14 14 26 0 0 0 27 14 14 99 28 1 1 1 1 1 1 1 1 15 15 100 29 16 16 16 30 1 1 1 1 16 16 16 30 2 2 2 2 2 2 2 2 16 16 16 30 17 17 17 31 2 2 2 2 17 17 17 31 3 3 3 4 3 3 3 4 17 17 17 31 18 18 18 32 3 3 3 4 18 18 18 32 4 4 4 6 4 4 4 6 18 18 18 32 19 19 19 33 4 4 4 6 19 19 19 33 5 5 5 8 5 5 5 8 19 19 19 33 20 20 20 34 5 5 5 8 20 20 20 34 6 6 6 10 6 6 6 10 20 20 20 34 21 21 21 35 6 6 6 10 21 21 21 35 7 7 7 12 7 7 7 12 21 21 21 35 22 22 22 36 7 7 7 12 22 22 22 36 8 8 8 14 8 8 8 14 22 22 22 36 23 23 23 37 8 8 8 14 23 23 23 37 9 9 9 16 9 9 9 16 23 23 23 37 24 24 24 38 9 9 9 16 24 24 24 38 10 10 10 18 10 10 10 18 24 24 24 38 25 25 25 39 10 10 10 18 25 25 25 39 11 11 11 20 11 11 11 20 25 25 25 39 26 26 26 40 11 11 11 20 26 26 26 40 12 12 12 22 12 12 12 22 26 26 26 40 27 27 27 41 12 12 12 22 27 27 27 41 13 13 13 24 13 13 13 24 27 27 27 41 28 28 28 42 13 13 13 24 28 28 28 42 14 14 14 26 14 14 14 26 28 28 28 42 15 15 15 43 14 14 101 44 15 15 102 45 1 1 1 1 15 15 103 46 29 29 104 47 30 30 30 48 15 15 105 49 30 30 30 48 16 16 16 30 16 16 16 30 30 30 30 48 31 31 31 50 16 16 16 30 31 31 31 50 17 17 17 31 17 17 17 31 31 31 31 50 32 32 32 51 17 17 17 31 32 32 32 51 18 18 18 32 18 18 18 32 32 32 32 51 33 33 33 52 18 18 18 32 33 33 33 52 19 19 19 33 19 19 19 33 33 33 33 52 34 34 34 53 19 19 19 33 34 34 34 53 20 20 20 34 20 20 20 34 34 34 34 53 35 35 35 54 20 20 20 34 35 35 35 54 21 21 21 35 21 21 21 35 35 35 35 54 36 36 36 55 21 21 21 35 36 36 36 55 22 22 22 36 22 22 22 36 36 36 36 55 37 37 37 56 22 22 22 36 37 37 37 56 23 23 23 37 23 23 23 37 37 37 37 56 38 38 38 57 23 23 23 37 38 38 38 57 24 24 24 38 24 24 24 38 38 38 38 57 39 39 39 58 24 24 24 38 39 39 39 58 25 25 25 39 25 25 25 39 39 39 39 58 40 40 40 59 25 25 25 39 40 40 40 59 26 26 26 40 26 26 26 40 40 40 40 59 41 41 41 60 26 26 26 40 41 41 41 60 27 27 27 41 27 27 27 41 41 41 41 60 42 42 42 61 27 27 27 41 42 42 42 61 28 28 28 42 28 28 28 42 42 42 42 61 29 29 29 62 28 28 28 42 29 29 29 62 15 15 15 43 29 29 106 63 43 43 107 64 44 44 44 65 29 29 108 66 44 44 44 65 30 30 30 48 30 30 30 48 44 44 44 65 45 45 45 67 30 30 30 48 45 45 45 67 31 31 31 50 31 31 31 50 45 45 45 67 46 46 46 68 31 31 31 50 46 46 46 68 32 32 32 51 32 32 32 51 46 46 46 68 47 47 47 69 32 32 32 51 47 47 47 69 33 33 33 52 33 33 33 52 47 47 47 69 48 48 48 70 33 33 33 52 48 48 48 70 34 34 34 53 34 34 34 53 48 48 48 70 49 49 49 71 34 34 34 53 49 49 49 71 35 35 35 54 35 35 35 54 49 49 49 71 50 50 50 72 35 35 35 54 50 50 50 72 36 36 36 55 36 36 36 55 50 50 50 72 51 51 51 73 36 36 36 55 51 51 51 73 37 37 37 56 37 37 37 56 51 51 51 73 52 52 52 74 37 37 37 56 52 52 52 74 38 38 38 57 38 38 38 57 52 52 52 74 53 53 53 75 38 38 38 57 53 53 53 75 39 39 39 58 39 39 39 58 53 53 53 75 54 54 54 76 39 39 39 58 54 54 54 76 40 40 40 59 40 40 40 59 54 54 54 76 55 55 55 77 40 40 40 59 55 55 55 77 41 41 41 60 41 41 41 60 55 55 55 77 56 56 56 78 41 41 41 60 56 56 56 78 42 42 42 61 42 42 42 61 56 56 56 78 43 43 43 79 42 42 42 61 43 43 43 79 29 29 29 62 43 43 109 80 57 57 110 81 58 58 58 82 43 43 111 83 58 58 58 82 44 44 44 65 44 44 44 65 58 58 58 82 59 59 59 84 44 44 44 65 59 59 59 84 45 45 45 67 45 45 45 67 59 59 59 84 60 60 60 85 45 45 45 67 60 60 60 85 46 46 46 68 46 46 46 68 60 60 60 85 61 61 61 86 46 46 46 68 61 61 61 86 47 47 47 69 47 47 47 69 61 61 61 86 62 62 62 87 47 47 47 69 62 62 62 87 48 48 48 70 48 48 48 70 62 62 62 87 63 63 63 88 48 48 48 70 63 63 63 88 49 49 49 71 49 49 49 71 63 63 63 88 64 64 64 89 49 49 49 71 64 64 64 89 50 50 50 72 50 50 50 72 64 64 64 89 65 65 65 90 50 50 50 72 65 65 65 90 51 51 51 73 51 51 51 73 65 65 65 90 66 66 66 91 51 51 51 73 66 66 66 91 52 52 52 74 52 52 52 74 66 66 66 91 67 67 67 92 52 52 52 74 67 67 67 92 53 53 53 75 53 53 53 75 67 67 67 92 68 68 68 93 53 53 53 75 68 68 68 93 54 54 54 76 54 54 54 76 68 68 68 93 69 69 69 94 54 54 54 76 69 69 69 94 55 55 55 77 55 55 55 77 69 69 69 94 70 70 70 95 55 55 55 77 70 70 70 95 56 56 56 78 56 56 56 78 70 70 70 95 57 57 57 96 56 56 56 78 57 57 57 96 43 43 43 79 57 57 112 97 71 71 71 98 72 72 72 99 57 57 113 100 72 72 72 99 58 58 58 82 58 58 58 82 72 72 72 99 73 73 73 101 58 58 58 82 73 73 73 101 59 59 59 84 59 59 59 84 73 73 73 101 74 74 74 102 59 59 59 84 74 74 74 102 60 60 60 85 60 60 60 85 74 74 74 102 75 75 75 103 60 60 60 85 75 75 75 103 61 61 61 86 61 61 61 86 75 75 75 103 76 76 76 104 61 61 61 86 76 76 76 104 62 62 62 87 62 62 62 87 76 76 76 104 77 77 77 105 62 62 62 87 77 77 77 105 63 63 63 88 63 63 63 88 77 77 77 105 78 78 78 106 63 63 63 88 78 78 78 106 64 64 64 89 64 64 64 89 78 78 78 106 79 79 79 107 64 64 64 89 79 79 79 107 65 65 65 90 65 65 65 90 79 79 79 107 80 80 80 108 65 65 65 90 80 80 80 108 66 66 66 91 66 66 66 91 80 80 80 108 81 81 81 109 66 66 66 91 81 81 81 109 67 67 67 92 67 67 67 92 81 81 81 109 82 82 82 110 67 67 67 92 82 82 82 110 68 68 68 93 68 68 68 93 82 82 82 110 83 83 83 111 68 68 68 93 83 83 83 111 69 69 69 94 69 69 69 94 83 83 83 111 84 84 84 112 69 69 69 94 84 84 84 112 70 70 70 95 70 70 114 113 84 84 115 114 71 71 71 98 70 70 116 115 71 71 71 98 57 57 117 116 85 85 118 117 72 72 72 99 71 71 71 98 85 85 119 118 73 73 73 101 72 72 72 99 85 85 120 119 74 74 74 102 73 73 73 101 85 85 121 120 75 75 75 103 74 74 74 102 85 85 122 121 76 76 76 104 75 75 75 103 85 85 123 122 77 77 77 105 76 76 76 104 85 85 124 123 78 78 78 106 77 77 77 105 85 85 125 124 79 79 79 107 78 78 78 106 85 85 126 125 80 80 80 108 79 79 79 107 85 85 127 126 81 81 81 109 80 80 80 108 85 85 128 127 82 82 82 110 81 81 81 109 85 85 129 128 83 83 83 111 82 82 82 110 85 85 130 129 84 84 84 112 83 83 83 111 85 85 85 130 71 71 71 98 84 84 131 131

+
+
+
+ + + + 0 0 5 -1.28465e-7 2.938926 4.045085 -1.727457 2.377641 4.045085 -2.795085 0.9081783 4.045085 -2.795085 -0.9081781 4.045085 -1.727458 -2.377641 4.045085 3.50463e-8 -2.938926 4.045085 1.727458 -2.377641 4.045085 2.795085 -0.9081767 4.045085 2.795084 0.9081804 4.045085 1.727455 2.377643 4.045085 -2.0786e-7 4.755283 1.545085 -2.795085 3.847105 1.545085 -4.522542 1.469463 1.545085 -4.522543 -1.469463 1.545085 -2.795086 -3.847104 1.545085 5.67062e-8 -4.755283 1.545085 2.795086 -3.847104 1.545085 4.522543 -1.469461 1.545085 4.522542 1.469467 1.545085 2.795081 3.847108 1.545085 -2.0786e-7 4.755282 -1.545085 -2.795084 3.847104 -1.545085 -4.522542 1.469463 -1.545085 -4.522542 -1.469463 -1.545085 -2.795086 -3.847103 -1.545085 5.67062e-8 -4.755282 -1.545085 2.795086 -3.847103 -1.545085 4.522543 -1.469461 -1.545085 4.522542 1.469467 -1.545085 2.795081 3.847107 -1.545085 -1.28465e-7 2.938926 -4.045085 -1.727457 2.377641 -4.045085 -2.795085 0.9081782 -4.045085 -2.795085 -0.908178 -4.045085 -1.727458 -2.37764 -4.045085 3.50463e-8 -2.938926 -4.045085 1.727458 -2.37764 -4.045085 2.795085 -0.9081766 -4.045085 2.795084 0.9081803 -4.045085 1.727455 2.377643 -4.045085 0 0 -5 + + + + + + + + + + 0 -2.11156e-8 1 -2.11354e-7 0.6252257 0.780444 -0.3674984 0.5058182 0.780444 -0.5946249 0.1932054 0.780444 -0.594625 -0.1932053 0.780444 -0.3674985 -0.5058182 0.780444 1.05677e-8 -0.6252257 0.780444 0.3674986 -0.5058181 0.780444 0.5946251 -0.1932051 0.780444 0.5946248 0.1932058 0.780444 0.3674981 0.5058185 0.780444 -2.70626e-7 0.9562714 0.2924812 -0.5620822 0.7736397 0.2924811 -0.909468 0.2955042 0.2924811 -0.9094681 -0.295504 0.2924812 -0.5620822 -0.7736397 0.2924811 5.52297e-9 -0.9562714 0.2924811 0.5620824 -0.7736396 0.2924811 0.9094682 -0.2955036 0.2924811 0.9094678 0.2955048 0.2924812 0.5620816 0.7736402 0.2924811 -2.70626e-7 0.9562712 -0.2924812 -0.5620822 0.7736397 -0.2924812 -0.909468 0.2955042 -0.2924812 -0.9094681 -0.295504 -0.2924812 -0.5620822 -0.7736396 -0.2924812 2.76149e-9 -0.9562712 -0.2924812 0.5620824 -0.7736395 -0.2924812 0.9094682 -0.2955037 -0.2924812 0.9094678 0.2955048 -0.2924812 0.5620815 0.7736402 -0.2924812 -1.638e-7 0.6252257 -0.780444 -0.3674985 0.5058182 -0.780444 -0.594625 0.1932054 -0.780444 -0.594625 -0.1932053 -0.780444 -0.3674985 -0.5058182 -0.780444 -3.17032e-8 -0.6252257 -0.780444 0.3674986 -0.5058181 -0.780444 0.5946251 -0.1932051 -0.780444 0.5946248 0.1932058 -0.780444 0.3674981 0.5058185 -0.780444 1.51768e-8 -4.22312e-8 -1 + + + + + + + + + + 0.95 1 0.999001 0.9999999 0.8 0.9990011 0.09999996 0.8 0.999001 0.2 0.8 0.999001 0.3 0.8 0.999001 0.3999999 0.8 0.999001 0.5 0.8 0.9990011 0.6 0.8 0.9990011 0.7 0.8 0.9990011 0.8000001 0.8 0.9990011 0.9000001 0.8 0.9990011 0.9999999 0.6 0.9990011 0.09999996 0.6 0.999001 0.2 0.6 0.999001 0.3 0.6 0.9990011 0.3999999 0.6 0.999001 0.5 0.6 0.9990011 0.6 0.6 0.9990011 0.7 0.6 0.9990011 0.8000001 0.6 0.9990011 0.9000001 0.6 0.9990011 0.9999999 0.4 0.9990011 0.09999996 0.4 0.999001 0.2 0.4 0.9990009 0.3 0.4 0.999001 0.3999999 0.4 0.999001 0.5 0.4 0.9990011 0.6 0.4 0.999001 0.7 0.4 0.9990011 0.8000001 0.4 0.9990011 0.9000001 0.4 0.999001 0.9999999 0.2 0.9990011 0.09999996 0.2 0.999001 0.2 0.2 0.999001 0.3 0.2 0.999001 0.3999999 0.2 0.999001 0.5 0.2 0.9990011 0.6 0.2 0.9990011 0.7 0.2 0.9990011 0.8000001 0.2 0.9990011 0.9000001 0.2 0.9990011 0.95 0 0.999001 0.04999995 1 0.999001 -5.96046e-8 0.8 0.9990011 0.15 1 0.999001 0.25 1 0.999001 0.35 1 0.999001 0.45 1 0.999001 0.55 1 0.999001 0.65 1 0.999001 0.7500001 1 0.999001 0.8500001 1 0.999001 -5.96046e-8 0.8 0.9990011 -5.96046e-8 0.6 0.9990011 -5.96046e-8 0.8 0.9990011 -5.96046e-8 0.6 0.9990011 -5.96046e-8 0.4 0.9990011 -5.96046e-8 0.6 0.9990011 -5.96046e-8 0.4 0.9990011 -5.96046e-8 0.2 0.9990011 -5.96046e-8 0.4 0.9990011 0.04999995 0 0.999001 -5.96046e-8 0.2 0.9990011 0.15 0 0.999001 0.25 0 0.999001 0.35 0 0.999001 0.45 0 0.999001 0.55 0 0.999001 0.65 0 0.999001 0.7500001 0 0.999001 0.8500001 0 0.999001 + + + + + + + + + + -0.9510565 -0.3090171 -6.52508e-9 -0.9510565 -0.1882202 0.1507859 -0.7472943 -0.5894716 0.03015721 -0.5877853 -0.809017 -1.70829e-8 -0.2580911 -0.9161411 0.03015718 -1.31262e-7 -1 -2.11156e-8 0.3296941 -0.8928759 0.0301572 0.5877852 -0.809017 -1.70829e-8 0.7915474 -0.5285625 0.03015717 0.9510565 -0.3090172 -6.52508e-9 0.9510565 0.03764403 0.0301572 0.9510565 0.3090172 6.52508e-9 0.7472941 0.5894718 0.03015722 0.587785 0.8090172 1.70829e-8 0.2580906 0.9161412 0.03015722 -6.5631e-7 1 2.11156e-8 -0.3296949 0.8928756 0.0301572 -0.587786 0.8090165 1.70829e-8 -0.7915479 0.5285618 0.03015718 -0.9510567 0.3090165 6.52507e-9 -0.9510567 0.1882196 -0.1507859 -0.9510565 -0.1882202 0.1507858 -0.9510566 -0.02643514 0.08642931 -0.7694209 -0.559017 7.9155e-10 -0.9510565 -0.1882202 0.1507859 -0.2938927 -0.9045085 -4.0073e-9 0.2938925 -0.9045085 -7.41231e-10 0.7694209 -0.5590171 -6.34775e-9 0.9510565 4.77085e-9 -2.3606e-9 0.7694207 0.5590172 -6.72929e-9 0.2938922 0.9045086 -2.86915e-9 -0.2938933 0.9045082 -2.409e-9 -0.7694214 0.5590164 -1.96186e-8 -0.9510566 0.0264346 -0.0864293 -0.9510566 -0.02643514 0.08642932 -0.9510566 -0.02643521 -0.08642933 -0.7694209 -0.559017 1.17386e-8 -0.9510566 -0.02643514 0.08642931 -0.2938927 -0.9045085 -3.27196e-9 0.2938926 -0.9045085 1.16709e-8 0.7694209 -0.5590171 -4.67655e-8 0.9510565 2.37408e-9 1.21738e-9 0.7694207 0.5590172 1.66922e-8 0.2938922 0.9045086 -7.07564e-9 -0.2938933 0.9045082 1.75192e-8 -0.7694214 0.5590164 1.41495e-8 -0.9510566 0.02643467 0.08642932 -0.9510567 -0.0264351 -0.08642897 -0.9510566 -0.1882199 -0.1507856 -0.7915475 -0.5285623 0.03015731 -0.9510566 -0.02643521 -0.08642933 -0.3296942 -0.8928758 0.03015721 0.258091 -0.9161412 0.03015719 0.7472943 -0.5894716 0.03015712 0.9510565 -0.03764394 0.03015711 0.7915473 0.5285625 0.03015719 0.3296938 0.892876 0.03015719 -0.2580917 0.9161409 0.03015721 -0.7472948 0.5894711 0.03015717 -0.9510567 0.1882196 0.1507858 -0.9510566 -0.3090166 -1.38389e-9 -0.9510567 -0.1882199 -0.1507856 -0.5877853 -0.8090169 2.5245e-8 -6.40936e-16 -1 4.22312e-8 0.5877852 -0.809017 4.30865e-8 0.9510566 -0.3090169 2.74842e-8 0.9510565 0.3090172 1.38386e-9 0.587785 0.8090172 -2.5245e-8 -6.5631e-7 1 -4.22312e-8 -0.587786 0.8090165 -4.30865e-8 -0.9510567 0.3090165 -2.74842e-8 + + + + + + + + + + -0.3090171 0.9510565 2.00821e-8 -0.2458018 0.7565 -0.6060439 -0.4991224 0.60081 -0.6244231 -0.809017 0.5877853 1.24114e-8 -0.7569457 0.1926888 -0.6244232 -1 1.31262e-7 2.77168e-15 -0.7256415 -0.289033 -0.6244231 -0.809017 -0.5877852 -1.24114e-8 -0.417167 -0.660354 -0.6244232 -0.3090172 -0.9510565 -2.00821e-8 0.05065125 -0.7794422 -0.6244232 0.3090172 -0.9510565 -2.00821e-8 0.4991225 -0.6008098 -0.6244231 0.8090172 -0.587785 -1.24114e-8 0.7569458 -0.1926883 -0.6244232 1 6.5631e-7 1.38584e-14 0.7256413 0.2890337 -0.6244231 0.8090165 0.587786 1.24115e-8 0.4171665 0.6603543 -0.6244232 0.3090165 0.9510567 2.00821e-8 0.2458013 0.7565002 -0.6060439 -0.2458018 0.7565 -0.6060439 -0.09460663 0.2911693 -0.9519822 -0.1719161 0.2366222 -0.9562713 -0.2458018 0.7565 -0.6060439 -0.2781661 0.09038166 -0.9562713 -0.2781661 -0.09038162 -0.9562713 -0.1719161 -0.2366222 -0.9562713 -9.06353e-10 -0.2924811 -0.9562713 0.1719161 -0.2366221 -0.9562713 0.2781661 -0.09038149 -0.9562713 0.2781661 0.09038187 -0.9562713 0.1719159 0.2366223 -0.9562713 0.09460646 0.2911693 -0.9519822 -0.09460664 0.2911693 -0.9519822 0.09460667 -0.2911693 -0.9519821 0.1719161 -0.2366223 -0.9562713 -0.09460663 0.2911693 -0.9519822 0.2781661 -0.09038168 -0.9562713 0.2781662 0.09038165 -0.9562713 0.1719161 0.2366223 -0.9562713 4.93948e-10 0.2924813 -0.9562713 -0.1719162 0.2366222 -0.9562713 -0.2781662 0.09038154 -0.9562713 -0.2781661 -0.09038187 -0.9562713 -0.171916 -0.2366224 -0.9562713 -0.09460649 -0.2911694 -0.9519821 0.09460628 -0.2911694 -0.9519822 0.2458014 -0.7565001 -0.6060439 0.4171668 -0.6603542 -0.6244231 0.09460667 -0.2911693 -0.9519821 0.7256415 -0.2890331 -0.6244232 0.7569457 0.1926887 -0.6244231 0.4991223 0.60081 -0.6244231 0.05065112 0.7794422 -0.6244232 -0.4171671 0.6603539 -0.6244232 -0.7256416 0.2890327 -0.6244232 -0.7569456 -0.1926893 -0.6244231 -0.4991219 -0.6008104 -0.6244231 -0.2458013 -0.7565002 -0.6060439 0.3090166 -0.9510566 4.48541e-8 0.2458014 -0.7565001 -0.6060439 0.8090169 -0.5877853 3.71012e-8 1 0 1.51768e-8 0.809017 0.5877852 -1.25446e-8 0.3090169 0.9510566 -3.54744e-8 -0.3090172 0.9510565 -4.48541e-8 -0.8090172 0.587785 -3.71012e-8 -1 -6.5631e-7 -1.51768e-8 -0.8090165 -0.587786 1.25446e-8 -0.3090165 -0.9510567 3.54744e-8 + + + + + + + + + + + + + + + + + +

0 0 42 0 1 1 43 1 2 2 2 2 0 0 44 3 2 2 2 2 3 3 3 4 0 0 45 5 3 3 3 4 4 4 4 6 0 0 46 7 4 4 4 6 5 5 5 8 0 0 47 9 5 5 5 8 6 6 6 10 0 0 48 11 6 6 6 10 7 7 7 12 0 0 49 13 7 7 7 12 8 8 8 14 0 0 50 15 8 8 8 14 9 9 9 16 0 0 51 17 9 9 9 16 10 10 10 18 0 0 0 19 10 10 10 18 1 1 1 20 1 1 52 21 11 11 53 22 12 12 12 23 1 1 54 24 12 12 12 23 2 2 2 2 2 2 2 2 12 12 12 23 13 13 13 25 2 2 2 2 13 13 13 25 3 3 3 4 3 3 3 4 13 13 13 25 14 14 14 26 3 3 3 4 14 14 14 26 4 4 4 6 4 4 4 6 14 14 14 26 15 15 15 27 4 4 4 6 15 15 15 27 5 5 5 8 5 5 5 8 15 15 15 27 16 16 16 28 5 5 5 8 16 16 16 28 6 6 6 10 6 6 6 10 16 16 16 28 17 17 17 29 6 6 6 10 17 17 17 29 7 7 7 12 7 7 7 12 17 17 17 29 18 18 18 30 7 7 7 12 18 18 18 30 8 8 8 14 8 8 8 14 18 18 18 30 19 19 19 31 8 8 8 14 19 19 19 31 9 9 9 16 9 9 9 16 19 19 19 31 20 20 20 32 9 9 9 16 20 20 20 32 10 10 10 18 10 10 10 18 20 20 20 32 11 11 11 33 10 10 10 18 11 11 11 33 1 1 1 20 11 11 55 34 21 21 56 35 22 22 22 36 11 11 57 37 22 22 22 36 12 12 12 23 12 12 12 23 22 22 22 36 23 23 23 38 12 12 12 23 23 23 23 38 13 13 13 25 13 13 13 25 23 23 23 38 24 24 24 39 13 13 13 25 24 24 24 39 14 14 14 26 14 14 14 26 24 24 24 39 25 25 25 40 14 14 14 26 25 25 25 40 15 15 15 27 15 15 15 27 25 25 25 40 26 26 26 41 15 15 15 27 26 26 26 41 16 16 16 28 16 16 16 28 26 26 26 41 27 27 27 42 16 16 16 28 27 27 27 42 17 17 17 29 17 17 17 29 27 27 27 42 28 28 28 43 17 17 17 29 28 28 28 43 18 18 18 30 18 18 18 30 28 28 28 43 29 29 29 44 18 18 18 30 29 29 29 44 19 19 19 31 19 19 19 31 29 29 29 44 30 30 30 45 19 19 19 31 30 30 30 45 20 20 20 32 20 20 20 32 30 30 30 45 21 21 21 46 20 20 20 32 21 21 21 46 11 11 11 33 21 21 58 47 31 31 59 48 32 32 32 49 21 21 60 50 32 32 32 49 22 22 22 36 22 22 22 36 32 32 32 49 33 33 33 51 22 22 22 36 33 33 33 51 23 23 23 38 23 23 23 38 33 33 33 51 34 34 34 52 23 23 23 38 34 34 34 52 24 24 24 39 24 24 24 39 34 34 34 52 35 35 35 53 24 24 24 39 35 35 35 53 25 25 25 40 25 25 25 40 35 35 35 53 36 36 36 54 25 25 25 40 36 36 36 54 26 26 26 41 26 26 26 41 36 36 36 54 37 37 37 55 26 26 26 41 37 37 37 55 27 27 27 42 27 27 27 42 37 37 37 55 38 38 38 56 27 27 27 42 38 38 38 56 28 28 28 43 28 28 28 43 38 38 38 56 39 39 39 57 28 28 28 43 39 39 39 57 29 29 29 44 29 29 29 44 39 39 39 57 40 40 40 58 29 29 29 44 40 40 40 58 30 30 30 45 30 30 30 45 40 40 40 58 31 31 31 59 30 30 30 45 31 31 31 59 21 21 21 46 41 41 61 60 32 32 32 49 31 31 62 61 41 41 63 62 33 33 33 51 32 32 32 49 41 41 64 63 34 34 34 52 33 33 33 51 41 41 65 64 35 35 35 53 34 34 34 52 41 41 66 65 36 36 36 54 35 35 35 53 41 41 67 66 37 37 37 55 36 36 36 54 41 41 68 67 38 38 38 56 37 37 37 55 41 41 69 68 39 39 39 57 38 38 38 56 41 41 70 69 40 40 40 58 39 39 39 57 41 41 41 70 31 31 31 59 40 40 40 58

+
+
+
+ + + + 0 0 5 -1.54543e-7 3.535534 3.535534 -2.5 2.5 3.535534 -3.535534 -3.09086e-7 3.535534 -2.5 -2.5 3.535534 4.21608e-8 -3.535534 3.535534 2.5 -2.5 3.535534 3.535534 -1.0677e-6 3.535534 2.500001 2.499999 3.535534 -2.18557e-7 5 -2.18557e-7 -3.535534 3.535534 -2.18557e-7 -5 -4.37114e-7 -2.18557e-7 -3.535533 -3.535534 -2.18557e-7 5.96244e-8 -5 -2.18557e-7 3.535533 -3.535534 -2.18557e-7 5 -1.50996e-6 -2.18557e-7 3.535536 3.535532 -2.18557e-7 -1.54543e-7 3.535534 -3.535534 -2.5 2.5 -3.535534 -3.535534 -3.09086e-7 -3.535534 -2.5 -2.5 -3.535534 4.21608e-8 -3.535534 -3.535534 2.5 -2.5 -3.535534 3.535534 -1.0677e-6 -3.535534 2.500001 2.499999 -3.535534 0 0 -5 + + + + + + + + + + 9.88537e-9 3.95415e-8 1 6.9026e-8 0.7486158 0.6630041 -0.5293514 0.5293513 0.6630041 -0.7486159 -8.05304e-8 0.6630041 -0.5293513 -0.5293514 0.663004 1.15043e-8 -0.7486158 0.6630041 0.5293513 -0.5293514 0.6630041 0.7486158 -2.01326e-7 0.6630041 0.5293515 0.5293512 0.6630041 7.27742e-8 1 -1.2129e-8 -0.7071067 0.7071068 -3.63871e-8 -1 -9.70323e-8 -1.81936e-8 -0.7071068 -0.7071068 -1.2129e-8 0 -1 3.03226e-8 0.7071066 -0.7071069 0 1 -3.21419e-7 -4.24516e-8 0.7071069 0.7071065 -1.2129e-8 6.32739e-8 0.7486157 -0.6630041 -0.5293513 0.5293513 -0.6630042 -0.7486158 -6.9026e-8 -0.6630042 -0.5293512 -0.5293514 -0.663004 2.30087e-8 -0.7486158 -0.6630041 0.5293512 -0.5293514 -0.6630041 0.7486158 -1.86945e-7 -0.6630042 0.5293514 0.5293511 -0.6630041 9.88537e-9 2.82439e-8 -1 + + + + + + + + + + 0.5 0.5 5.5 0.5000007 4.035534 4.035534 -2 3 4.035534 -3.035534 0.5000005 4.035534 -2 -2 4.035534 0.4999992 -3.035534 4.035534 2.999999 -2.000001 4.035534 4.035534 0.4999981 4.035534 3.000002 2.999998 4.035534 0.500001 5.5 0.4999998 -3.035533 4.035535 0.4999998 -4.5 0.5000008 0.4999998 -3.035534 -3.035533 0.4999998 0.4999989 -4.5 0.4999998 4.035532 -3.035535 0.4999998 5.5 0.4999973 0.4999998 4.035537 4.035532 0.4999998 0.5000007 4.035534 -3.035534 -2 3 -3.035534 -3.035534 0.5000005 -3.035534 -2 -2 -3.035534 0.4999992 -3.035534 -3.035534 2.999999 -2.000001 -3.035534 4.035534 0.4999981 -3.035534 3.000002 2.999998 -3.035534 0.5 0.5 -4.5 + + + + + + + + + + 0.954739 2.15833e-7 -9.43795e-9 0.8185035 -0.07019225 0.07925587 0.7049205 -0.02852993 0.5855967 0.6144843 1.61232e-7 0.6938309 0.7364077 -0.004867014 0.5840719 0.8185036 -0.07019225 -0.07925597 0.7049205 -0.02852995 -0.5855966 0.6144844 1.36677e-7 -0.6938309 0.7364076 -0.004866982 -0.584072 0.7071067 -5.4318e-8 -0.2357023 0.2724478 0.2724477 -0.03612882 -1.08617e-14 7.48297e-8 -5.34923e-9 0.2724474 -0.2724474 0.03612879 0.7071068 7.1471e-9 0.2357022 0.2724478 0.2724477 0.03612882 3.23075e-14 2.23624e-7 1.56345e-8 0.2724472 -0.2724473 -0.03612873 0.8185034 0.07019258 0.07925641 0.7364079 0.004867376 -0.5840717 0.6144844 1.60997e-7 -0.6938308 0.7049204 0.02853028 -0.5855968 0.8185035 0.07019259 -0.07925631 0.736408 0.004867405 0.5840716 0.6144844 1.54593e-7 0.6938308 0.7049204 0.02853028 0.5855969 0.954739 2.15833e-7 9.43795e-9 + + + + + + + + + + 2.26065e-7 -1 3.95415e-8 -0.1282771 -0.6575266 0.742431 -0.3587224 -0.8478319 0.3905115 1.75624e-7 -1 7.68394e-8 0.3255071 -0.8483869 -0.4174744 -0.1282772 -0.6575266 -0.742431 -0.3587225 -0.8478319 -0.3905116 -5.29431e-8 -1 -2.43878e-7 0.325507 -0.848387 0.4174741 0.3162278 -1.15066e-8 0.9486833 0.06601453 0.06601457 0.9956325 -2.5066e-8 0.07130344 0.9974547 0.06601458 -0.06601456 -0.9956325 0.3162277 -2.87665e-8 -0.9486833 0.06601455 0.06601453 -0.9956325 -1.99311e-8 0.06974413 -0.9975649 0.06601449 -0.06601451 0.9956325 -0.1282779 0.6575266 0.7424309 0.3255066 0.848387 0.4174746 -1.66844e-7 1 8.42766e-8 -0.3587228 0.8478319 -0.3905113 -0.1282778 0.6575265 -0.7424309 0.3255067 0.8483869 -0.4174747 2.93614e-8 1 -2.48815e-7 -0.3587227 0.847832 0.3905111 -2.26065e-7 1 2.82439e-8 + + + + + + + + + + + + + + + + + +

0 0 0 0 1 1 1 1 2 2 2 2 0 0 0 0 2 2 2 2 3 3 3 3 0 0 0 0 3 3 3 3 4 4 4 4 0 0 0 0 4 4 4 4 5 5 5 5 0 0 0 0 5 5 5 5 6 6 6 6 0 0 0 0 6 6 6 6 7 7 7 7 0 0 0 0 7 7 7 7 8 8 8 8 0 0 0 0 8 8 8 8 1 1 1 1 1 1 1 1 9 9 9 9 10 10 10 10 1 1 1 1 10 10 10 10 2 2 2 2 2 2 2 2 10 10 10 10 11 11 11 11 2 2 2 2 11 11 11 11 3 3 3 3 3 3 3 3 11 11 11 11 12 12 12 12 3 3 3 3 12 12 12 12 4 4 4 4 4 4 4 4 12 12 12 12 13 13 13 13 4 4 4 4 13 13 13 13 5 5 5 5 5 5 5 5 13 13 13 13 14 14 14 14 5 5 5 5 14 14 14 14 6 6 6 6 6 6 6 6 14 14 14 14 15 15 15 15 6 6 6 6 15 15 15 15 7 7 7 7 7 7 7 7 15 15 15 15 16 16 16 16 7 7 7 7 16 16 16 16 8 8 8 8 8 8 8 8 16 16 16 16 9 9 9 9 8 8 8 8 9 9 9 9 1 1 1 1 9 9 9 9 17 17 17 17 18 18 18 18 9 9 9 9 18 18 18 18 10 10 10 10 10 10 10 10 18 18 18 18 19 19 19 19 10 10 10 10 19 19 19 19 11 11 11 11 11 11 11 11 19 19 19 19 20 20 20 20 11 11 11 11 20 20 20 20 12 12 12 12 12 12 12 12 20 20 20 20 21 21 21 21 12 12 12 12 21 21 21 21 13 13 13 13 13 13 13 13 21 21 21 21 22 22 22 22 13 13 13 13 22 22 22 22 14 14 14 14 14 14 14 14 22 22 22 22 23 23 23 23 14 14 14 14 23 23 23 23 15 15 15 15 15 15 15 15 23 23 23 23 24 24 24 24 15 15 15 15 24 24 24 24 16 16 16 16 16 16 16 16 24 24 24 24 17 17 17 17 16 16 16 16 17 17 17 17 9 9 9 9 25 25 25 25 18 18 18 18 17 17 17 17 25 25 25 25 19 19 19 19 18 18 18 18 25 25 25 25 20 20 20 20 19 19 19 19 25 25 25 25 21 21 21 21 20 20 20 20 25 25 25 25 22 22 22 22 21 21 21 21 25 25 25 25 23 23 23 23 22 22 22 22 25 25 25 25 24 24 24 24 23 23 23 23 25 25 25 25 17 17 17 17 24 24 24 24

+
+
+
+ + + + 0 0 5 -1.89276e-7 4.330127 2.5 -3.75 2.165064 2.5 -3.75 -2.165064 2.5 5.16362e-8 -4.330127 2.5 3.75 -2.165064 2.5 3.750001 2.165062 2.5 -1.89276e-7 4.330127 -2.5 -3.75 2.165064 -2.5 -3.75 -2.165063 -2.5 5.16362e-8 -4.330127 -2.5 3.75 -2.165064 -2.5 3.750001 2.165062 -2.5 0 0 -5 + + + + + + + + + + -1.99952e-8 1.33301e-8 1 7.03834e-8 0.8973439 0.441332 -0.7771226 0.448672 0.441332 -0.7771226 -0.448672 0.441332 -3.51917e-8 -0.8973439 0.441332 0.7771224 -0.4486721 0.441332 0.7771227 0.4486718 0.441332 8.44601e-8 0.8973438 -0.4413321 -0.7771226 0.4486719 -0.4413322 -0.7771226 -0.4486719 -0.4413321 -4.92684e-8 -0.8973439 -0.4413321 0.7771225 -0.4486721 -0.4413321 0.7771227 0.4486717 -0.4413321 -6.66506e-9 1.33301e-8 -1 + + + + + + + + + + 0.9166666 1 0.999001 0.9999999 0.6666667 0.9990011 0.1666667 0.6666666 0.9990012 0.3333333 0.6666667 0.9990011 0.5 0.6666667 0.9990011 0.6666666 0.6666667 0.999001 0.8333333 0.6666667 0.999001 0.9999999 0.3333333 0.999001 0.1666666 0.3333333 0.9990011 0.3333333 0.3333333 0.9990011 0.5 0.3333333 0.999001 0.6666666 0.3333333 0.999001 0.8333332 0.3333333 0.9990009 0.9166666 0 0.999001 0.08333331 1 0.999001 -5.96046e-8 0.6666667 0.9990011 0.25 1 0.999001 0.4166666 1 0.999001 0.5833333 1 0.999001 0.7499999 1 0.999001 -5.96046e-8 0.6666667 0.9990011 -5.96046e-8 0.3333333 0.999001 -5.96046e-8 0.6666667 0.9990011 0.08333328 0 0.999001 -5.96046e-8 0.3333333 0.999001 0.25 0 0.999001 0.4166666 0 0.999001 0.5833333 0 0.999001 0.7499999 0 0.999001 + + + + + + + + + + -0.8660253 -0.5000002 -1.06513e-8 -0.8660252 -0.09738706 0.1980136 -0.4161448 -0.7597387 0.03960266 -3.09715e-7 -1 1.33301e-8 0.4498806 -0.7402613 0.03960252 0.8660254 -0.5 2.39814e-8 0.8660254 0.01947738 0.03960269 0.8660254 0.4999999 1.06513e-8 0.416145 0.7597387 0.03960266 3.30363e-7 1 -1.33301e-8 -0.4498804 0.7402614 0.03960264 -0.8660253 0.5000001 -2.39814e-8 -0.8660254 0.09738707 -0.1980133 -0.8660254 -0.09738693 0.1980133 -0.8660254 -0.09738697 -0.1980133 -0.4498806 -0.7402613 0.03960274 -0.8660254 -0.09738709 0.1980137 0.4161448 -0.7597387 0.03960259 0.8660254 -0.01947747 0.03960272 0.4498808 0.7402612 0.03960273 -0.4161446 0.7597387 0.0396026 -0.8660254 0.09738708 0.1980132 -0.8660254 -0.5 -8.92948e-10 -0.8660254 -0.09738697 -0.1980133 0 -1 -1.33301e-8 0.8660254 -0.5 -1.24372e-8 0.8660255 0.4999998 8.92944e-10 2.75302e-7 1 1.33301e-8 -0.8660254 0.5 1.24372e-8 + + + + + + + + + + -0.5000002 0.8660253 -2.15418e-8 -0.2469142 0.4276673 -0.8695597 -0.4071567 0.176304 -0.896181 -1 3.09715e-7 -1.99952e-8 -0.3562622 -0.2644559 -0.896181 -0.5 -0.8660254 1.54663e-9 0.05089461 -0.4407601 -0.896181 0.4999999 -0.8660254 2.15418e-8 0.4071567 -0.1763041 -0.8961809 1 -3.30363e-7 1.99952e-8 0.3562622 0.2644559 -0.896181 0.5000001 0.8660253 -1.54663e-9 0.2469139 0.4276673 -0.8695598 -0.2469138 0.4276673 -0.8695598 0.2469139 -0.4276674 -0.8695598 0.3562622 -0.2644562 -0.8961809 -0.2469142 0.4276672 -0.8695597 0.4071568 0.1763041 -0.8961809 0.05089469 0.4407602 -0.8961809 -0.3562621 0.2644562 -0.8961809 -0.4071568 -0.176304 -0.8961809 -0.2469138 -0.4276673 -0.8695598 0.5 -0.8660254 -1.48767e-8 0.2469139 -0.4276674 -0.8695598 1 0 -6.66506e-9 0.5 0.8660254 8.21169e-9 -0.4999998 0.8660255 1.48767e-8 -1 2.75302e-7 6.66506e-9 -0.5 -0.8660254 -8.21169e-9 + + + + + + + + + + + + + + + + + +

0 0 14 0 1 1 15 1 2 2 2 2 0 0 16 3 2 2 2 2 3 3 3 4 0 0 17 5 3 3 3 4 4 4 4 6 0 0 18 7 4 4 4 6 5 5 5 8 0 0 19 9 5 5 5 8 6 6 6 10 0 0 0 11 6 6 6 10 1 1 1 12 1 1 20 13 7 7 21 14 8 8 8 15 1 1 22 16 8 8 8 15 2 2 2 2 2 2 2 2 8 8 8 15 9 9 9 17 2 2 2 2 9 9 9 17 3 3 3 4 3 3 3 4 9 9 9 17 10 10 10 18 3 3 3 4 10 10 10 18 4 4 4 6 4 4 4 6 10 10 10 18 11 11 11 19 4 4 4 6 11 11 11 19 5 5 5 8 5 5 5 8 11 11 11 19 12 12 12 20 5 5 5 8 12 12 12 20 6 6 6 10 6 6 6 10 12 12 12 20 7 7 7 21 6 6 6 10 7 7 7 21 1 1 1 12 13 13 23 22 8 8 8 15 7 7 24 23 13 13 25 24 9 9 9 17 8 8 8 15 13 13 26 25 10 10 10 18 9 9 9 17 13 13 27 26 11 11 11 19 10 10 10 18 13 13 28 27 12 12 12 20 11 11 11 19 13 13 13 28 7 7 7 21 12 12 12 20

+
+
+
+
+ + + + + 0 0 0 + + + + + + + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + +
\ No newline at end of file diff --git a/Templates/Full/game/art/environment/LightVolume_Sphere.cs b/Templates/Full/game/art/environment/LightVolume_Sphere.cs new file mode 100644 index 000000000..475da3bee --- /dev/null +++ b/Templates/Full/game/art/environment/LightVolume_Sphere.cs @@ -0,0 +1,8 @@ + +singleton TSShapeConstructor(LightVolume_SphereDAE) +{ + baseShape = "./LightVolume_Sphere.DAE"; + lodType = "TrailingNumber"; + neverImport = "env*"; + loadLights = "0"; +}; diff --git a/Templates/Full/game/art/environment/LightVolume_Sphere.dts b/Templates/Full/game/art/environment/LightVolume_Sphere.dts new file mode 100644 index 000000000..223993dd6 Binary files /dev/null and b/Templates/Full/game/art/environment/LightVolume_Sphere.dts differ diff --git a/Templates/Full/game/art/gui/optionsDlg.gui b/Templates/Full/game/art/gui/optionsDlg.gui index fcff1cb95..9f12a272a 100644 --- a/Templates/Full/game/art/gui/optionsDlg.gui +++ b/Templates/Full/game/art/gui/optionsDlg.gui @@ -33,7 +33,7 @@ anchorLeft = "1"; anchorRight = "0"; position = "323 232"; - extent = "377 303"; + extent = "377 355"; minExtent = "8 8"; horizSizing = "center"; vertSizing = "center"; @@ -51,7 +51,7 @@ groupNum = "-1"; buttonType = "PushButton"; useMouseEvents = "0"; - position = "306 271"; + position = "304 319"; extent = "60 23"; minExtent = "8 8"; horizSizing = "right"; @@ -179,47 +179,49 @@ canSave = "1"; canSaveDynamicFields = "0"; }; - - new GuiSliderCtrl(OptMouseSensitivity) { - range = "0.02 2"; - ticks = "10"; - value = "0.75"; - isContainer = "0"; - Profile = "GuiSliderProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "105 182"; - Extent = "244 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "OptMouseSetSensitivity(OptMouseSensitivity.value);"; - tooltipprofile = "GuiToolTipProfile"; - hovertime = "1000"; - canSaveDynamicFields = "0"; - }; - new GuiTextCtrl() { - text = "Mouse Sensitivity:"; - maxLength = "255"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - isContainer = "0"; - Profile = "GuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "15 182"; - Extent = "85 18"; - MinExtent = "8 8"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "GuiToolTipProfile"; - hovertime = "1000"; - canSaveDynamicFields = "0"; - }; + new GuiSliderCtrl(OptMouseSensitivity) { + range = "0.02 2"; + ticks = "10"; + snap = "0"; + value = "1"; + position = "105 182"; + extent = "244 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderProfile"; + visible = "1"; + active = "1"; + command = "OptMouseSetSensitivity(OptMouseSensitivity.value);"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Mouse Sensitivity:"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "15 182"; + extent = "85 18"; + minExtent = "8 8"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; new GuiBitmapBorderCtrl() { position = "9 55"; @@ -601,7 +603,7 @@ }; new GuiBitmapBorderCtrl() { position = "9 55"; - extent = "358 210"; + extent = "358 252"; minExtent = "8 8"; horizSizing = "right"; vertSizing = "bottom"; @@ -1252,6 +1254,66 @@ canSave = "1"; canSaveDynamicFields = "0"; }; + new GuiControl() { + position = "0 227"; + extent = "352 15"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "GammaSliderContainer"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiSliderCtrl() { + range = "0.5 1.5"; + ticks = "0"; + snap = "0"; + value = "1"; + position = "76 -1"; + extent = "268 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderProfile"; + visible = "1"; + active = "1"; + variable = "$pref::Video::Contrast"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Contrast:"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "18 -4"; + extent = "105 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; new GuiControl() { position = "0 190"; extent = "352 15"; @@ -1269,10 +1331,10 @@ canSaveDynamicFields = "0"; new GuiSliderCtrl() { - range = "0.001 2.2"; + range = "2.0 2.5"; ticks = "0"; snap = "0"; - value = "1"; + value = "2.2"; position = "76 -1"; extent = "268 15"; minExtent = "8 2"; @@ -1312,6 +1374,66 @@ canSaveDynamicFields = "0"; }; }; + new GuiControl() { + position = "0 208"; + extent = "352 15"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "GammaSliderContainer"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiSliderCtrl() { + range = "-0.5 0.5"; + ticks = "0"; + snap = "0"; + value = "0"; + position = "76 -1"; + extent = "268 15"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderProfile"; + visible = "1"; + active = "1"; + variable = "$pref::Video::Brightness"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Brightness:"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "6 -3"; + extent = "105 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; }; new GuiControl() { position = "9 55"; @@ -1396,7 +1518,7 @@ groupNum = "-1"; buttonType = "PushButton"; useMouseEvents = "0"; - position = "241 271"; + position = "239 319"; extent = "60 23"; minExtent = "8 8"; horizSizing = "right"; diff --git a/Templates/Full/game/art/prefabs/fire.prefab b/Templates/Full/game/art/prefabs/fire.prefab new file mode 100644 index 000000000..6213e33a8 --- /dev/null +++ b/Templates/Full/game/art/prefabs/fire.prefab @@ -0,0 +1,49 @@ +//--- OBJECT WRITE BEGIN --- +$ThisPrefab = new SimGroup() { + canSave = "1"; + canSaveDynamicFields = "1"; + + new ParticleEmitterNode() { + active = "1"; + emitter = "FireEmitter"; + velocity = "1"; + dataBlock = "EmberNode"; + position = "0 0 0"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new PointLight() { + radius = "10"; + isEnabled = "1"; + color = "1 0.603922 0 1"; + brightness = "1"; + castShadows = "1"; + staticRefreshFreq = "250"; + dynamicRefreshFreq = "8"; + priority = "1"; + animate = "1"; + animationPeriod = "1"; + animationPhase = "1"; + flareScale = "1"; + attenuationRatio = "0 1 1"; + shadowType = "DualParaboloidSinglePass"; + texSize = "512"; + overDarkFactor = "2000 1000 500 100"; + shadowDistance = "400"; + shadowSoftness = "0.15"; + numSplits = "1"; + logWeight = "0.91"; + fadeStartDistance = "0"; + lastSplitTerrainOnly = "0"; + representedInLightmap = "0"; + shadowDarkenColor = "0 0 0 -1"; + includeLightmappedGeometryInShadow = "0"; + position = "0 0 0"; + rotation = "1 0 0 0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; +}; +//--- OBJECT WRITE END --- diff --git a/Templates/Full/game/art/shapes/trees/defaulttree/materials.cs b/Templates/Full/game/art/shapes/trees/defaulttree/materials.cs index f82946ccb..c17ea71eb 100644 --- a/Templates/Full/game/art/shapes/trees/defaulttree/materials.cs +++ b/Templates/Full/game/art/shapes/trees/defaulttree/materials.cs @@ -27,7 +27,6 @@ singleton Material(defaultTree_bark_material) diffuseMap[0] = "art/shapes/trees/defaulttree/defaulttree_bark_diffuse.dds"; normalMap[0] = "art/shapes/trees/defaulttree/defaulttree_bark_normal_specular.dds"; - specularMap[0] = ""; diffuseColor[0] = "1 1 1 1"; specular[0] = "0.9 0.9 0.9 1"; @@ -37,6 +36,7 @@ singleton Material(defaultTree_bark_material) translucent = false; translucentBlendOp = "None"; pixelSpecular[0] = "1"; + castDynamicShadows = "0"; }; singleton Material(defaulttree_material) @@ -45,7 +45,6 @@ singleton Material(defaulttree_material) diffuseMap[0] = "art/shapes/trees/defaulttree/defaulttree_diffuse_transparency.dds"; normalMap[0] = "art/shapes/trees/defaulttree/defaulttree_normal_specular.dds"; - specularMap[0] = ""; diffuseColor[0] = "1 1 1 1"; specular[0] = "0.9 0.9 0.9 1"; @@ -57,6 +56,7 @@ singleton Material(defaulttree_material) pixelSpecular[0] = "1"; alphaTest = "1"; alphaRef = "127"; + castDynamicShadows = "0"; }; singleton Material(defaultTree_fronds_material) @@ -71,6 +71,7 @@ singleton Material(defaultTree_fronds_material) alphaTest = "1"; alphaRef = "114"; translucent = "1"; + castDynamicShadows = "0"; }; singleton Material(defaulttree_ColorEffectR27G177B88_material) @@ -79,4 +80,6 @@ singleton Material(defaulttree_ColorEffectR27G177B88_material) diffuseColor[0] = "0.105882 0.694118 0.345098 1"; specularPower[0] = "10"; translucentBlendOp = "None"; + castDynamicShadows = "0"; + castShadows = "0"; }; diff --git a/Templates/Full/game/art/skies/Desert_Sky/materials.cs b/Templates/Full/game/art/skies/Desert_Sky/materials.cs index af6a979c8..0ee4080d8 100644 --- a/Templates/Full/game/art/skies/Desert_Sky/materials.cs +++ b/Templates/Full/game/art/skies/Desert_Sky/materials.cs @@ -34,4 +34,5 @@ singleton Material( DesertSkyMat ) { cubemap = DesertSkyCubemap; materialTag0 = "Skies"; + isSky = true; }; diff --git a/Templates/Full/game/art/skies/night/materials.cs b/Templates/Full/game/art/skies/night/materials.cs index 79cc050fc..11f9f6348 100644 --- a/Templates/Full/game/art/skies/night/materials.cs +++ b/Templates/Full/game/art/skies/night/materials.cs @@ -34,6 +34,7 @@ singleton Material( NightSkyMat ) { cubemap = NightCubemap; materialTag0 = "Skies"; + isSky = true; }; singleton Material( Moon_Glow_Mat ) @@ -50,4 +51,5 @@ singleton Material( Moon_Mat ) emissive = true; translucent = true; vertColor[ 0 ] = true; + isSky = true; }; diff --git a/Templates/Full/game/core/art/skies/blank/materials.cs b/Templates/Full/game/core/art/skies/blank/materials.cs index 179eafcf2..39f268866 100644 --- a/Templates/Full/game/core/art/skies/blank/materials.cs +++ b/Templates/Full/game/core/art/skies/blank/materials.cs @@ -34,6 +34,7 @@ singleton Material( BlackSkyMat ) { cubemap = BlackSkyCubemap; materialTag0 = "Skies"; + isSky = true; }; singleton CubemapData( BlueSkyCubemap ) @@ -50,6 +51,7 @@ singleton Material( BlueSkyMat ) { cubemap = BlueSkyCubemap; materialTag0 = "Skies"; + isSky = true; }; singleton CubemapData( GreySkyCubemap ) @@ -66,4 +68,5 @@ singleton Material( GreySkyMat ) { cubemap = GreySkyCubemap; materialTag0 = "Skies"; + isSky = true; }; diff --git a/Templates/Full/game/core/main.cs b/Templates/Full/game/core/main.cs index 0baeb9364..f666c948c 100644 --- a/Templates/Full/game/core/main.cs +++ b/Templates/Full/game/core/main.cs @@ -141,11 +141,11 @@ function parseArgs() switch$ (%arg) { case "-fullscreen": - setFullScreen(true); + $cliFullscreen = true; $argUsed[%i]++; case "-windowed": - setFullScreen(false); + $cliFullscreen = false; $argUsed[%i]++; case "-openGL": diff --git a/Templates/Full/game/core/scripts/client/canvas.cs b/Templates/Full/game/core/scripts/client/canvas.cs index 69dd6da71..5c1d377c5 100644 --- a/Templates/Full/game/core/scripts/client/canvas.cs +++ b/Templates/Full/game/core/scripts/client/canvas.cs @@ -39,9 +39,14 @@ function configureCanvas() %rate = getWord($pref::Video::mode, $WORD::REFRESH); %fsaa = getWord($pref::Video::mode, $WORD::AA); - echo("--------------"); - echo("Attempting to set resolution to \"" @ $pref::Video::mode @ "\""); + if($cliFullscreen !$= "") { + %fs = $cliFullscreen; + $cliFullscreen = ""; + } + echo("--------------"); + echo("Attempting to set resolution to \"" @ %resX SPC %resY SPC %fs SPC %bpp SPC %rate SPC %fsaa @ "\""); + %deskRes = getDesktopResolution(); %deskResX = getWord(%deskRes, $WORD::RES_X); %deskResY = getWord(%deskRes, $WORD::RES_Y); diff --git a/Templates/Full/game/core/scripts/client/defaults.cs b/Templates/Full/game/core/scripts/client/defaults.cs index 0142a9410..d1805d337 100644 --- a/Templates/Full/game/core/scripts/client/defaults.cs +++ b/Templates/Full/game/core/scripts/client/defaults.cs @@ -73,7 +73,9 @@ $pref::Video::disableCubemapping = false; /// $pref::Video::disableParallaxMapping = false; -$pref::Video::Gamma = 1.0; +$pref::Video::Gamma = 2.2; +$pref::Video::Contrast = 1.0; +$pref::Video::Brightness = 0; // Console-friendly defaults if($platform $= "xenon") diff --git a/Templates/Full/game/core/scripts/client/lighting/advanced/deferredShading.cs b/Templates/Full/game/core/scripts/client/lighting/advanced/deferredShading.cs new file mode 100644 index 000000000..8a1df2c67 --- /dev/null +++ b/Templates/Full/game/core/scripts/client/lighting/advanced/deferredShading.cs @@ -0,0 +1,147 @@ +singleton ShaderData( ClearGBufferShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; + DXPixelShaderFile = "shaders/common/lighting/advanced/deferredClearGBufferP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; + OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/deferredClearGBufferP.glsl"; + + pixVersion = 2.0; +}; + +singleton ShaderData( DeferredColorShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; + DXPixelShaderFile = "shaders/common/lighting/advanced/deferredColorShaderP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; + OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/deferredColorShaderP.glsl"; + + pixVersion = 2.0; +}; + +// Primary Deferred Shader +new GFXStateBlockData( AL_DeferredShadingState : PFX_DefaultStateBlock ) +{ + cullMode = GFXCullNone; + + blendDefined = true; + blendEnable = true; + blendSrc = GFXBlendSrcAlpha; + blendDest = GFXBlendInvSrcAlpha; + + samplersDefined = true; + samplerStates[0] = SamplerWrapLinear; + samplerStates[1] = SamplerWrapLinear; + samplerStates[2] = SamplerWrapLinear; + samplerStates[3] = SamplerWrapLinear; +}; + +new ShaderData( AL_DeferredShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; + DXPixelShaderFile = "shaders/common/lighting/advanced/deferredShadingP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; + OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/deferredShadingP.glsl"; + + samplerNames[0] = "colorBufferTex"; + samplerNames[1] = "lightPrePassTex"; + samplerNames[2] = "matInfoTex"; + samplerNames[3] = "prepassTex"; + + pixVersion = 2.0; +}; + +singleton PostEffect( AL_DeferredShading ) +{ + renderTime = "PFXBeforeBin"; + renderBin = "SkyBin"; + shader = AL_DeferredShader; + stateBlock = AL_DeferredShadingState; + texture[0] = "#color"; + texture[1] = "#lightinfo"; + texture[2] = "#matinfo"; + texture[3] = "#prepass"; + + target = "$backBuffer"; + renderPriority = 10000; + allowReflectPass = true; +}; + +// Debug Shaders. +new ShaderData( AL_ColorBufferShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; + DXPixelShaderFile = "shaders/common/lighting/advanced/dbgColorBufferP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; + OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgColorBufferP.glsl"; + + samplerNames[0] = "colorBufferTex"; + pixVersion = 2.0; +}; + +singleton PostEffect( AL_ColorBufferVisualize ) +{ + shader = AL_ColorBufferShader; + stateBlock = AL_DefaultVisualizeState; + texture[0] = "#color"; + target = "$backBuffer"; + renderPriority = 9999; +}; + +/// Toggles the visualization of the AL lighting specular power buffer. +function toggleColorBufferViz( %enable ) +{ + if ( %enable $= "" ) + { + $AL_ColorBufferShaderVar = AL_ColorBufferVisualize.isEnabled() ? false : true; + AL_ColorBufferVisualize.toggle(); + } + else if ( %enable ) + { + AL_DeferredShading.disable(); + AL_ColorBufferVisualize.enable(); + } + else if ( !%enable ) + { + AL_ColorBufferVisualize.disable(); + AL_DeferredShading.enable(); + } +} + +new ShaderData( AL_SpecMapShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; + DXPixelShaderFile = "shaders/common/lighting/advanced/dbgSpecMapVisualizeP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; + OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgSpecMapVisualizeP.glsl"; + + samplerNames[0] = "matinfoTex"; + pixVersion = 2.0; +}; + +singleton PostEffect( AL_SpecMapVisualize ) +{ + shader = AL_SpecMapShader; + stateBlock = AL_DefaultVisualizeState; + texture[0] = "#matinfo"; + target = "$backBuffer"; + renderPriority = 9999; +}; + +/// Toggles the visualization of the AL lighting specular power buffer. +function toggleSpecMapViz( %enable ) +{ + if ( %enable $= "" ) + { + $AL_SpecMapShaderVar = AL_SpecMapVisualize.isEnabled() ? false : true; + AL_SpecMapVisualize.toggle(); + } + else if ( %enable ) + AL_SpecMapVisualize.enable(); + else if ( !%enable ) + AL_SpecMapVisualize.disable(); +} \ No newline at end of file diff --git a/Templates/Full/game/core/scripts/client/lighting/advanced/init.cs b/Templates/Full/game/core/scripts/client/lighting/advanced/init.cs index 2c78e9ca4..d74aff69a 100644 --- a/Templates/Full/game/core/scripts/client/lighting/advanced/init.cs +++ b/Templates/Full/game/core/scripts/client/lighting/advanced/init.cs @@ -43,6 +43,7 @@ exec( "./shaders.cs" ); exec( "./lightViz.cs" ); exec( "./shadowViz.cs" ); exec( "./shadowViz.gui" ); +exec( "./deferredShading.cs" ); function onActivateAdvancedLM() { @@ -58,12 +59,18 @@ function onActivateAdvancedLM() // Enable the offscreen target so that AL will work // with MSAA back buffers and for HDR rendering. AL_FormatToken.enable(); + + // Activate Deferred Shading + AL_DeferredShading.enable(); } function onDeactivateAdvancedLM() { // Disable the offscreen render target. AL_FormatToken.disable(); + + // Deactivate Deferred Shading + AL_DeferredShading.disable(); } function setAdvancedLighting() diff --git a/Templates/Full/game/core/scripts/client/lighting/advanced/lightViz.cs b/Templates/Full/game/core/scripts/client/lighting/advanced/lightViz.cs index 22665120d..fcaf72942 100644 --- a/Templates/Full/game/core/scripts/client/lighting/advanced/lightViz.cs +++ b/Templates/Full/game/core/scripts/client/lighting/advanced/lightViz.cs @@ -56,7 +56,7 @@ new ShaderData( AL_DepthVisualizeShader ) OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl"; - samplerNames[0] = "prepassBuffer"; + samplerNames[0] = "prepassTex"; samplerNames[1] = "depthViz"; pixVersion = 2.0; @@ -113,7 +113,7 @@ new ShaderData( AL_NormalsVisualizeShader ) OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl"; - samplerNames[0] = "prepassBuffer"; + samplerNames[0] = "prepassTex"; pixVersion = 2.0; }; @@ -149,7 +149,7 @@ new ShaderData( AL_LightColorVisualizeShader ) OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl"; - samplerNames[0] = "lightInfoBuffer"; + samplerNames[0] = "lightPrePassTex"; pixVersion = 2.0; }; @@ -184,7 +184,7 @@ new ShaderData( AL_LightSpecularVisualizeShader ) OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl"; - samplerNames[0] = "lightInfoBuffer"; + samplerNames[0] = "lightPrePassTex"; pixVersion = 2.0; }; @@ -280,3 +280,16 @@ function toggleLightSpecularViz( %enable ) AL_LightSpecularVisualize.disable(); } +function toggleBackbufferViz( %enable ) +{ + if ( %enable $= "" ) + { + $AL_BackbufferVisualizeVar = AL_DeferredShading.isEnabled() ? true : false; + AL_DeferredShading.toggle(); + } + else if ( %enable ) + AL_DeferredShading.disable(); + else if ( !%enable ) + AL_DeferredShading.enable(); +} + diff --git a/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs b/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs index 2e73b6569..eaf7f70b8 100644 --- a/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs +++ b/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs @@ -36,8 +36,11 @@ new GFXStateBlockData( AL_VectorLightState ) samplersDefined = true; samplerStates[0] = SamplerClampPoint; // G-buffer + mSamplerNames[0] = "prePassBuffer"; samplerStates[1] = SamplerClampPoint; // Shadow Map (Do not change this to linear, as all cards can not filter equally.) + mSamplerNames[1] = "shadowMap"; samplerStates[2] = SamplerClampLinear; // SSAO Mask + mSamplerNames[2] = "ssaoMask"; samplerStates[3] = SamplerWrapPoint; // Random Direction Map cullDefined = true; @@ -66,7 +69,9 @@ new ShaderData( AL_VectorLightShader ) samplerNames[2] = "$dynamicShadowMap"; samplerNames[3] = "$ssaoMask"; samplerNames[4] = "$gTapRotationTex"; - + samplerNames[5] = "$lightBuffer"; + samplerNames[6] = "$colorBuffer"; + samplerNames[7] = "$matInfoBuffer"; pixVersion = 3.0; }; @@ -78,7 +83,10 @@ new CustomMaterial( AL_VectorLightMaterial ) sampler["prePassBuffer"] = "#prepass"; sampler["shadowMap"] = "$dynamiclight"; sampler["dynamicShadowMap"] = "$dynamicShadowMap"; - sampler["ssaoMask"] = "#ssaoMask"; + sampler["ssaoMask"] = "#ssaoMask"; + sampler["lightBuffer"] = "#lightinfo"; + sampler["colorBuffer"] = "#color"; + sampler["matInfoBuffer"] = "#matinfo"; target = "lightinfo"; @@ -103,7 +111,9 @@ new GFXStateBlockData( AL_ConvexLightState ) samplersDefined = true; samplerStates[0] = SamplerClampPoint; // G-buffer + mSamplerNames[0] = "prePassBuffer"; samplerStates[1] = SamplerClampPoint; // Shadow Map (Do not use linear, these are perspective projections) + mSamplerNames[1] = "shadowMap"; samplerStates[2] = SamplerClampLinear; // Cookie Map samplerStates[3] = SamplerWrapPoint; // Random Direction Map @@ -133,6 +143,9 @@ new ShaderData( AL_PointLightShader ) samplerNames[2] = "$dynamicShadowMap"; samplerNames[3] = "$cookieMap"; samplerNames[4] = "$gTapRotationTex"; + samplerNames[5] = "$lightBuffer"; + samplerNames[6] = "$colorBuffer"; + samplerNames[7] = "$matInfoBuffer"; pixVersion = 3.0; }; @@ -146,6 +159,9 @@ new CustomMaterial( AL_PointLightMaterial ) sampler["shadowMap"] = "$dynamiclight"; sampler["dynamicShadowMap"] = "$dynamicShadowMap"; sampler["cookieMap"] = "$dynamiclightmask"; + sampler["lightBuffer"] = "#lightinfo"; + sampler["colorBuffer"] = "#color"; + sampler["matInfoBuffer"] = "#matinfo"; target = "lightinfo"; @@ -166,6 +182,9 @@ new ShaderData( AL_SpotLightShader ) samplerNames[2] = "$dynamicShadowMap"; samplerNames[3] = "$cookieMap"; samplerNames[4] = "$gTapRotationTex"; + samplerNames[5] = "$lightBuffer"; + samplerNames[6] = "$colorBuffer"; + samplerNames[7] = "$matInfoBuffer"; pixVersion = 3.0; }; @@ -179,6 +198,9 @@ new CustomMaterial( AL_SpotLightMaterial ) sampler["shadowMap"] = "$dynamiclight"; sampler["dynamicShadowMap"] = "$dynamicShadowMap"; sampler["cookieMap"] = "$dynamiclightmask"; + sampler["lightBuffer"] = "#lightinfo"; + sampler["colorBuffer"] = "#color"; + sampler["matInfoBuffer"] = "#matinfo"; target = "lightinfo"; diff --git a/Templates/Full/game/core/scripts/client/postFx/GammaPostFX.cs b/Templates/Full/game/core/scripts/client/postFx/GammaPostFX.cs index 383a0c8cd..b88f31305 100644 --- a/Templates/Full/game/core/scripts/client/postFx/GammaPostFX.cs +++ b/Templates/Full/game/core/scripts/client/postFx/GammaPostFX.cs @@ -44,7 +44,7 @@ singleton GFXStateBlockData( GammaStateBlock : PFX_DefaultStateBlock ) singleton PostEffect( GammaPostFX ) { isEnabled = true; - allowReflectPass = false; + allowReflectPass = true; renderTime = "PFXBeforeBin"; renderBin = "EditorBin"; @@ -65,6 +65,8 @@ function GammaPostFX::preProcess( %this ) function GammaPostFX::setShaderConsts( %this ) { - %clampedGamma = mClamp( $pref::Video::Gamma, 0.001, 2.2); + %clampedGamma = mClamp( $pref::Video::Gamma, 2.0, 2.5); %this.setShaderConst( "$OneOverGamma", 1 / %clampedGamma ); + %this.setShaderConst( "$Brightness", $pref::Video::Brightness ); + %this.setShaderConst( "$Contrast", $pref::Video::Contrast ); } \ No newline at end of file diff --git a/Templates/Full/game/core/scripts/client/postFx/caustics.cs b/Templates/Full/game/core/scripts/client/postFx/caustics.cs index 3e8b14de0..11fda8083 100644 --- a/Templates/Full/game/core/scripts/client/postFx/caustics.cs +++ b/Templates/Full/game/core/scripts/client/postFx/caustics.cs @@ -51,7 +51,7 @@ singleton ShaderData( PFX_CausticsShader ) singleton PostEffect( CausticsPFX ) { isEnabled = false; - renderTime = "PFXBeforeBin"; + renderTime = "PFXAfterDiffuse"; renderBin = "ObjTranslucentBin"; //renderPriority = 0.1; diff --git a/Templates/Full/game/core/scripts/client/postFx/glow.cs b/Templates/Full/game/core/scripts/client/postFx/glow.cs index 3cc946b04..78c46e56d 100644 --- a/Templates/Full/game/core/scripts/client/postFx/glow.cs +++ b/Templates/Full/game/core/scripts/client/postFx/glow.cs @@ -106,3 +106,79 @@ singleton PostEffect( GlowPostFx ) target = "$backBuffer"; }; }; + +singleton ShaderData( PFX_VolFogGlowBlurVertShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/glowBlurV.hlsl"; + DXPixelShaderFile = "shaders/common/postFx/VolFogGlowP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/glowBlurV.glsl"; + OGLPixelShaderFile = "shaders/common/postFx/gl/VolFogGlowP.glsl"; + + defines = "BLUR_DIR=float2(0.0,1.0)"; + samplerNames[0] = "$diffuseMap"; + pixVersion = 2.0; +}; +singleton ShaderData( PFX_VolFogGlowBlurHorzShader : PFX_VolFogGlowBlurVertShader ) +{ + DXVertexShaderFile = "shaders/common/postFx/glowBlurV.hlsl"; + DXPixelShaderFile = "shaders/common/postFx/VolFogGlowP.hlsl"; + + OGLVertexShaderFile = "shaders/common/postFx/gl/glowBlurV.glsl"; + OGLPixelShaderFile = "shaders/common/postFx/gl/VolFogGlowP.glsl"; + + defines = "BLUR_DIR=float2(1.0,0.0)"; +}; + +$VolFogGlowPostFx::glowStrength = 0.3; + +singleton PostEffect( VolFogGlowPostFx ) +{ + // Do not allow the glow effect to work in reflection + // passes by default so we don't do the extra drawing. + allowReflectPass = false; + renderTime = "PFXAfterBin"; + renderBin = "FogBin"; + renderPriority = 1; + // First we down sample the glow buffer. + shader = PFX_PassthruShader; + stateBlock = PFX_DefaultStateBlock; + texture[0] = "$backbuffer"; + target = "$outTex"; + targetScale = "0.5 0.5"; + isEnabled = true; + // Blur vertically + new PostEffect() + { + shader = PFX_VolFogGlowBlurVertShader; + stateBlock = PFX_DefaultStateBlock; + internalName = "vert"; + texture[0] = "$inTex"; + target = "$outTex"; + }; + // Blur horizontally + new PostEffect() + { + shader = PFX_VolFogGlowBlurHorzShader; + stateBlock = PFX_DefaultStateBlock; + internalName = "hor"; + texture[0] = "$inTex"; + target = "$outTex"; + }; + // Upsample and combine with the back buffer. + new PostEffect() + { + shader = PFX_PassthruShader; + stateBlock = PFX_GlowCombineStateBlock; + texture[0] = "$inTex"; + target = "$backBuffer"; + }; +}; + +function VolFogGlowPostFx::setShaderConsts( %this ) +{ + %vp=%this-->vert; + %vp.setShaderConst( "$strength", $VolFogGlowPostFx::glowStrength ); + %vp=%this-->hor; + %vp.setShaderConst( "$strength", $VolFogGlowPostFx::glowStrength ); +} \ No newline at end of file diff --git a/Templates/Full/game/core/scripts/client/postFx/hdr.cs b/Templates/Full/game/core/scripts/client/postFx/hdr.cs index a5c450799..6c8e870d0 100644 --- a/Templates/Full/game/core/scripts/client/postFx/hdr.cs +++ b/Templates/Full/game/core/scripts/client/postFx/hdr.cs @@ -172,6 +172,8 @@ singleton ShaderData( HDR_CombineShader ) samplerNames[2] = "$bloomTex"; samplerNames[3] = "$colorCorrectionTex"; + samplerNames[4] = "prepassTex"; + pixVersion = 3.0; }; @@ -253,8 +255,10 @@ function HDRPostFX::setShaderConsts( %this ) %combinePass.setShaderConst( "$g_fEnableBlueShift", $HDRPostFX::enableBlueShift ); %combinePass.setShaderConst( "$g_fBlueShiftColor", $HDRPostFX::blueShiftColor ); - %clampedGamma = mClamp( $pref::Video::Gamma, 0.001, 2.2); + %clampedGamma = mClamp( $pref::Video::Gamma, 2.0, 2.5); %combinePass.setShaderConst( "$g_fOneOverGamma", 1 / %clampedGamma ); + %combinePass.setShaderConst( "$Brightness", $pref::Video::Brightness ); + %combinePass.setShaderConst( "$Contrast", $pref::Video::Contrast ); %whiteCutoff = ( $HDRPostFX::whiteCutoff * $HDRPostFX::whiteCutoff ) * ( $HDRPostFX::whiteCutoff * $HDRPostFX::whiteCutoff ); @@ -329,7 +333,7 @@ function HDRPostFX::onDisabled( %this ) singleton PostEffect( HDRPostFX ) { isEnabled = false; - allowReflectPass = false; + allowReflectPass = true; // Resolve the HDR before we render any editor stuff // and before we resolve the scene to the backbuffer. @@ -355,6 +359,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; shader = HDR_DownScale4x4Shader; stateBlock = HDR_DownSampleStateBlock; texture[0] = "$inTex"; @@ -365,6 +370,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; internalName = "bloomH"; shader = HDR_BloomGaussBlurHShader; @@ -376,6 +382,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; internalName = "bloomV"; shader = HDR_BloomGaussBlurVShader; @@ -390,6 +397,7 @@ singleton PostEffect( HDRPostFX ) // Now calculate the adapted luminance. new PostEffect() { + allowReflectPass = true; internalName = "adaptLum"; shader = HDR_SampleLumShader; @@ -401,6 +409,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; shader = HDR_DownSampleLumShader; stateBlock = HDR_DownSampleStateBlock; texture[0] = "$inTex"; @@ -411,6 +420,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; shader = HDR_DownSampleLumShader; stateBlock = HDR_DownSampleStateBlock; texture[0] = "$inTex"; @@ -421,6 +431,7 @@ singleton PostEffect( HDRPostFX ) new PostEffect() { + allowReflectPass = true; shader = HDR_DownSampleLumShader; stateBlock = HDR_DownSampleStateBlock; texture[0] = "$inTex"; @@ -434,6 +445,7 @@ singleton PostEffect( HDRPostFX ) // one... PostEffect takes care to manage that. new PostEffect() { + allowReflectPass = true; internalName = "finalLum"; shader = HDR_CalcAdaptedLumShader; stateBlock = HDR_DownSampleStateBlock; @@ -450,6 +462,7 @@ singleton PostEffect( HDRPostFX ) // version of the scene. new PostEffect() { + allowReflectPass = true; internalName = "combinePass"; shader = HDR_CombineShader; @@ -458,6 +471,7 @@ singleton PostEffect( HDRPostFX ) texture[1] = "#adaptedLum"; texture[2] = "#bloomFinal"; texture[3] = $HDRPostFX::colorCorrectionRamp; + texture[4] = "#prepass"; target = "$backBuffer"; }; }; diff --git a/Templates/Full/game/core/scripts/client/postFx/postFxManager.gui.settings.cs b/Templates/Full/game/core/scripts/client/postFx/postFxManager.gui.settings.cs index d30d2314b..77d664f41 100644 --- a/Templates/Full/game/core/scripts/client/postFx/postFxManager.gui.settings.cs +++ b/Templates/Full/game/core/scripts/client/postFx/postFxManager.gui.settings.cs @@ -70,6 +70,7 @@ function PostFXManager::settingsSetEnabled(%this, %bEnablePostFX) postVerbose("% - PostFX Manager - PostFX disabled"); } + VolFogGlowPostFx.disable(); } function PostFXManager::settingsEffectSetEnabled(%this, %sName, %bEnable) diff --git a/Templates/Full/game/core/scripts/client/postFx/turbulence.cs b/Templates/Full/game/core/scripts/client/postFx/turbulence.cs index c2309f808..dd8c0e2dc 100644 --- a/Templates/Full/game/core/scripts/client/postFx/turbulence.cs +++ b/Templates/Full/game/core/scripts/client/postFx/turbulence.cs @@ -47,7 +47,7 @@ singleton PostEffect( TurbulenceFx ) isEnabled = false; allowReflectPass = true; - renderTime = "PFXAfterBin"; + renderTime = "PFXAfterDiffuse"; renderBin = "GlowBin"; renderPriority = 0.5; // Render after the glows themselves diff --git a/Templates/Full/game/core/scripts/client/renderManager.cs b/Templates/Full/game/core/scripts/client/renderManager.cs index dcd1628fe..a14287db1 100644 --- a/Templates/Full/game/core/scripts/client/renderManager.cs +++ b/Templates/Full/game/core/scripts/client/renderManager.cs @@ -33,7 +33,7 @@ function initRenderManager() { enabled = "false"; - format = "GFXFormatR8G8B8A8"; + format = "GFXFormatR16G16B16A16F"; depthFormat = "GFXFormatD24S8"; aaLevel = 0; // -1 = match backbuffer @@ -49,20 +49,21 @@ function initRenderManager() // We really need to fix the sky to render after all the // meshes... but that causes issues in reflections. - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Sky"; renderOrder = 0.1; processAddOrder = 0.1; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(SkyBin) { bintype = "Sky"; renderOrder = 0.1; processAddOrder = 0.1; } ); //DiffuseRenderPassManager.addManager( new RenderVistaMgr() { bintype = "Vista"; renderOrder = 0.15; processAddOrder = 0.15; } ); - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Begin"; renderOrder = 0.2; processAddOrder = 0.2; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(BeginBin) { bintype = "Begin"; renderOrder = 0.2; processAddOrder = 0.2; } ); // Normal mesh rendering. - DiffuseRenderPassManager.addManager( new RenderTerrainMgr() { renderOrder = 0.4; processAddOrder = 0.4; } ); - DiffuseRenderPassManager.addManager( new RenderMeshMgr() { bintype = "Mesh"; renderOrder = 0.5; processAddOrder = 0.5; } ); - DiffuseRenderPassManager.addManager( new RenderImposterMgr() { renderOrder = 0.56; processAddOrder = 0.56; } ); - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Object"; renderOrder = 0.6; processAddOrder = 0.6; } ); - - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Shadow"; renderOrder = 0.7; processAddOrder = 0.7; } ); - DiffuseRenderPassManager.addManager( new RenderMeshMgr() { bintype = "Decal"; renderOrder = 0.8; processAddOrder = 0.8; } ); - DiffuseRenderPassManager.addManager( new RenderOcclusionMgr() { bintype = "Occluder"; renderOrder = 0.9; processAddOrder = 0.9; } ); + DiffuseRenderPassManager.addManager( new RenderTerrainMgr(TerrainBin) { renderOrder = 0.4; processAddOrder = 0.4; basicOnly = true; } ); + DiffuseRenderPassManager.addManager( new RenderMeshMgr(MeshBin) { bintype = "Mesh"; renderOrder = 0.5; processAddOrder = 0.5; basicOnly = true; } ); + DiffuseRenderPassManager.addManager( new RenderImposterMgr(ImposterBin) { renderOrder = 0.56; processAddOrder = 0.56; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(ObjectBin) { bintype = "Object"; renderOrder = 0.6; processAddOrder = 0.6; } ); + + DiffuseRenderPassManager.addManager( new RenderObjectMgr(ShadowBin) { bintype = "Shadow"; renderOrder = 0.7; processAddOrder = 0.7; } ); + DiffuseRenderPassManager.addManager( new RenderMeshMgr(DecalRoadBin) { bintype = "DecalRoad"; renderOrder = 0.8; processAddOrder = 0.8; } ); + DiffuseRenderPassManager.addManager( new RenderMeshMgr(DecalBin) { bintype = "Decal"; renderOrder = 0.81; processAddOrder = 0.81; } ); + DiffuseRenderPassManager.addManager( new RenderOcclusionMgr(OccluderBin){ bintype = "Occluder"; renderOrder = 0.9; processAddOrder = 0.9; } ); // We now render translucent objects that should handle // their own fogging and lighting. @@ -70,10 +71,12 @@ function initRenderManager() // Note that the fog effect is triggered before this bin. DiffuseRenderPassManager.addManager( new RenderObjectMgr(ObjTranslucentBin) { bintype = "ObjectTranslucent"; renderOrder = 1.0; processAddOrder = 1.0; } ); - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Water"; renderOrder = 1.2; processAddOrder = 1.2; } ); - DiffuseRenderPassManager.addManager( new RenderObjectMgr() { bintype = "Foliage"; renderOrder = 1.3; processAddOrder = 1.3; } ); - DiffuseRenderPassManager.addManager( new RenderParticleMgr() { renderOrder = 1.35; processAddOrder = 1.35; } ); - DiffuseRenderPassManager.addManager( new RenderTranslucentMgr() { renderOrder = 1.4; processAddOrder = 1.4; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(WaterBin) { bintype = "Water"; renderOrder = 1.2; processAddOrder = 1.2; } ); + DiffuseRenderPassManager.addManager( new RenderObjectMgr(FoliageBin) { bintype = "Foliage"; renderOrder = 1.3; processAddOrder = 1.3; } ); + DiffuseRenderPassManager.addManager( new RenderParticleMgr(ParticleBin) { renderOrder = 1.35; processAddOrder = 1.35; } ); + DiffuseRenderPassManager.addManager( new RenderTranslucentMgr(TranslucentBin){ renderOrder = 1.4; processAddOrder = 1.4; } ); + + DiffuseRenderPassManager.addManager(new RenderObjectMgr(FogBin){ bintype = "ObjectVolumetricFog"; renderOrder = 1.45; processAddOrder = 1.45; } ); // Note that the GlowPostFx is triggered after this bin. DiffuseRenderPassManager.addManager( new RenderGlowMgr(GlowBin) { renderOrder = 1.5; processAddOrder = 1.5; } ); @@ -83,7 +86,7 @@ function initRenderManager() DiffuseRenderPassManager.addManager( new RenderObjectMgr(EditorBin) { bintype = "Editor"; renderOrder = 1.6; processAddOrder = 1.6; } ); // Resolve format change token last. - DiffuseRenderPassManager.addManager( new RenderPassStateBin() { renderOrder = 1.7; stateToken = AL_FormatToken; } ); + DiffuseRenderPassManager.addManager( new RenderPassStateBin(FinalBin) { renderOrder = 1.7; stateToken = AL_FormatToken; } ); } /// This post effect is used to copy data from the non-MSAA back-buffer to the diff --git a/Templates/Full/game/core/scripts/client/scatterSky.cs b/Templates/Full/game/core/scripts/client/scatterSky.cs index 7701b0adf..a2b19ab23 100644 --- a/Templates/Full/game/core/scripts/client/scatterSky.cs +++ b/Templates/Full/game/core/scripts/client/scatterSky.cs @@ -22,13 +22,13 @@ new GFXStateBlockData( ScatterSkySBData ) { - cullDefined = true; + //cullDefined = true; cullMode = "GFXCullNone"; zDefined = true; zEnable = true; zWriteEnable = false; - zFunc = "GFXCmpLessEqual"; + //zFunc = "GFXCmpLessEqual"; samplersDefined = true; samplerStates[0] = SamplerClampLinear; diff --git a/Templates/Full/game/core/scripts/client/shaders.cs b/Templates/Full/game/core/scripts/client/shaders.cs index 98d0529eb..002053a1a 100644 --- a/Templates/Full/game/core/scripts/client/shaders.cs +++ b/Templates/Full/game/core/scripts/client/shaders.cs @@ -101,4 +101,40 @@ new ShaderData( fxFoliageReplicatorShader ) samplerNames[1] = "$alphaMap"; pixVersion = 1.4; +}; + +singleton ShaderData( VolumetricFogPrePassShader ) +{ + DXVertexShaderFile = "shaders/common/VolumetricFog/VFogPreV.hlsl"; + DXPixelShaderFile = "shaders/common/VolumetricFog/VFogPreP.hlsl"; + + OGLVertexShaderFile = "shaders/common/VolumetricFog/gl/VFogPreV.glsl"; + OGLPixelShaderFile = "shaders/common/VolumetricFog/gl/VFogPreP.glsl"; + + pixVersion = 3.0; +}; +singleton ShaderData( VolumetricFogShader ) +{ + DXVertexShaderFile = "shaders/common/VolumetricFog/VFogV.hlsl"; + DXPixelShaderFile = "shaders/common/VolumetricFog/VFogP.hlsl"; + + OGLVertexShaderFile = "shaders/common/VolumetricFog/gl/VFogV.glsl"; + OGLPixelShaderFile = "shaders/common/VolumetricFog/gl/VFogP.glsl"; + + samplerNames[0] = "$prepassTex"; + samplerNames[1] = "$depthBuffer"; + samplerNames[2] = "$frontBuffer"; + samplerNames[3] = "$density"; + + pixVersion = 3.0; +}; +singleton ShaderData( VolumetricFogReflectionShader ) +{ + DXVertexShaderFile = "shaders/common/VolumetricFog/VFogPreV.hlsl"; + DXPixelShaderFile = "shaders/common/VolumetricFog/VFogRefl.hlsl"; + + OGLVertexShaderFile = "shaders/common/VolumetricFog/gl/VFogPreV.glsl"; + OGLPixelShaderFile = "shaders/common/VolumetricFog/gl/VFogRefl.glsl"; + + pixVersion = 3.0; }; \ No newline at end of file diff --git a/Templates/Full/game/scripts/server/VolumetricFog.cs b/Templates/Full/game/scripts/server/VolumetricFog.cs new file mode 100644 index 000000000..53e03adf3 --- /dev/null +++ b/Templates/Full/game/scripts/server/VolumetricFog.cs @@ -0,0 +1,106 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +function VolumetricFog::onEnterFog(%this,%obj) +{ + // This method is called whenever the control object (Camera or Player) + // %obj enters the fog area. + + // echo("Control Object " @ %obj @ " enters fog " @ %this); +} + +function VolumetricFog::onLeaveFog(%this,%obj) +{ + // This method is called whenever the control object (Camera or Player) + // %obj leaves the fog area. + + // echo("Control Object " @ %obj @ " left fog " @ %this); +} + +function VolumetricFog::Dissolve(%this,%speed,%delete) +{ + // This method dissolves the fog at speed milliseconds + %this.isBuilding = true; + if (%this.FogDensity > 0) + { + %this.setFogDensity(%this.FogDensity - 0.005); + %this.schedule(%speed,Dissolve,%speed,%delete); + } + else + { + %this.isBuilding = false; + %this.SetFogDensity(0.0); + if (%delete !$= "" && %delete !$="0" && %delete !$="false") + %this.schedule(250,delete); + } +} + +function VolumetricFog::Thicken(%this,%speed, %end_density) +{ + // This method thickens the fog at speed milliseconds to a density of %end_density + + %this.isBuilding = true; + if (%this.FogDensity + 0.005 < %end_density) + { + %this.setFogDensity(%this.FogDensity + 0.005); + %this.schedule(%speed,Thicken,%speed, %end_density); + } + else + { + %this.setFogDensity(%end_density); + %this.isBuilding = false; + } +} + +function GenerateFog(%pos,%scale,%color,%density) +{ + // This function can be used to generate some fog caused by massive gunfire etc. + // Change shape and modulation data to your likings. + + %fog=new VolumetricFog() { + shapeName = "art/environment/Fog_Sphere.dts"; + fogColor = %color; + fogDensity = "0.0"; + ignoreWater = "0"; + MinSize = "250"; + FadeSize = "750"; + texture = "art/environment/FogMod_heavy.dds"; + tiles = "1"; + modStrength = "0.2"; + PrimSpeed = "-0.01 0.04"; + SecSpeed = "0.02 0.02"; + position = %pos; + rotation = "0 0 1 20.354"; + scale = %scale; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + + if (isObject(%fog)) + { + MissionCleanup.add(%fog); + + %fog.Thicken(500,%density); + } + + return %fog; +} \ No newline at end of file diff --git a/Templates/Full/game/scripts/server/scriptExec.cs b/Templates/Full/game/scripts/server/scriptExec.cs index 64d4adc06..26f4f8280 100644 --- a/Templates/Full/game/scripts/server/scriptExec.cs +++ b/Templates/Full/game/scripts/server/scriptExec.cs @@ -24,6 +24,7 @@ // a server is constructed. exec("./camera.cs"); exec("./triggers.cs"); +exec("./VolumetricFog.cs"); exec("./inventory.cs"); exec("./shapeBase.cs"); exec("./item.cs"); diff --git a/Templates/Full/game/shaders/common/VolumetricFog/VFogP.hlsl b/Templates/Full/game/shaders/common/VolumetricFog/VFogP.hlsl new file mode 100644 index 000000000..aaadbf479 --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/VFogP.hlsl @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog final pixel shader V2.00 + +#include "shadergen:/autogenConditioners.h" +#include "../torque.hlsl" + +uniform sampler2D prepassTex : register(S0); +uniform sampler2D depthBuffer : register(S1); +uniform sampler2D frontBuffer : register(S2); +uniform sampler2D density : register(S3); + +uniform float accumTime; +uniform float4 fogColor; +uniform float fogDensity; +uniform float preBias; +uniform float textured; +uniform float modstrength; +uniform float4 modspeed;//xy speed layer 1, zw speed layer 2 +uniform float2 viewpoint; +uniform float2 texscale; +uniform float3 ambientColor; +uniform float numtiles; +uniform float fadesize; +uniform float2 PixelSize; + +struct ConnectData +{ + float4 hpos : POSITION; + float4 htpos : TEXCOORD0; + float2 uv0 : TEXCOORD1; +}; + +float4 main( ConnectData IN ) : COLOR0 +{ + float2 uvscreen=((IN.htpos.xy/IN.htpos.w) + 1.0 ) / 2.0; + uvscreen.y = 1.0 - uvscreen.y; + + float obj_test = prepassUncondition( prepassTex, uvscreen).w * preBias; + float depth = tex2D(depthBuffer,uvscreen).r; + float front = tex2D(frontBuffer,uvscreen).r; + + if (depth <= front) + return float4(0,0,0,0); + else if ( obj_test < depth ) + depth = obj_test; + if ( front >= 0.0) + depth -= front; + + float diff = 1.0; + float3 col = fogColor.rgb; + if (textured != 0.0) + { + float2 offset = viewpoint + ((-0.5 + (texscale * uvscreen)) * numtiles); + + float2 mod1 = tex2D(density,(offset + (modspeed.xy*accumTime))).rg; + float2 mod2= tex2D(density,(offset + (modspeed.zw*accumTime))).rg; + diff = (mod2.r + mod1.r) * modstrength; + col *= (2.0 - ((mod1.g + mod2.g) * fadesize))/2.0; + } + + col *= ambientColor; + + float4 resultColor = float4(col, 1.0 - saturate(exp(-fogDensity * depth * diff * fadesize))); + + return hdrEncode(resultColor); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/VFogPreP.hlsl b/Templates/Full/game/shaders/common/VolumetricFog/VFogPreP.hlsl new file mode 100644 index 000000000..bb06f5f7c --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/VFogPreP.hlsl @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog prepass pixel shader V1.00 + +struct ConnectData +{ + float4 hpos : POSITION; + float4 pos : TEXCOORD0; +}; + +float4 main( ConnectData IN ) : COLOR0 +{ + float OUT; + + clip( IN.pos.w ); + OUT = IN.pos.w; + + return float4(OUT,0,0,1); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/VFogPreV.hlsl b/Templates/Full/game/shaders/common/VolumetricFog/VFogPreV.hlsl new file mode 100644 index 000000000..2d13cdf01 --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/VFogPreV.hlsl @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog prepass vertex shader V1.00 + +#include "shaders/common/hlslstructs.h" + +struct ConnectData +{ + float4 hpos : POSITION; + float4 pos : TEXCOORD0; +}; + +uniform float4x4 modelView; + +ConnectData main( VertexIn_P IN) +{ + ConnectData OUT; + + float4 inPos = IN.pos; + inPos.w = 1.0; + + OUT.hpos = mul( modelView, inPos ); + OUT.pos = OUT.hpos; + + return OUT; +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/VFogRefl.hlsl b/Templates/Full/game/shaders/common/VolumetricFog/VFogRefl.hlsl new file mode 100644 index 000000000..bd9866cf8 --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/VFogRefl.hlsl @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog Reflection pixel shader V1.00 +uniform float4 fogColor; +uniform float fogDensity; +uniform float reflStrength; + +struct ConnectData +{ + float4 hpos : POSITION; + float4 pos : TEXCOORD0; +}; + +float4 main( ConnectData IN ) : COLOR0 +{ + return float4(fogColor.rgb,saturate(fogDensity*reflStrength)); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/VFogV.hlsl b/Templates/Full/game/shaders/common/VolumetricFog/VFogV.hlsl new file mode 100644 index 000000000..7f86802b5 --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/VFogV.hlsl @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog final vertex shader V1.00 + +#include "shaders/common/hlslstructs.h" + +struct ConnectData +{ + float4 hpos : POSITION; + float4 htpos : TEXCOORD0; + float2 uv0 : TEXCOORD1; +}; + +uniform float4x4 modelView; + +ConnectData main( VertexIn_PNT IN) +{ + ConnectData OUT; + + OUT.hpos = mul(modelView, IN.pos); + OUT.htpos = OUT.hpos; + OUT.uv0 = IN.uv0; + + return OUT; +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogP.glsl b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogP.glsl new file mode 100644 index 000000000..7895d9e2d --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogP.glsl @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" +#include "shadergen:/autogenConditioners.h" +#include "../../gl/torque.glsl" + +uniform sampler2D prepassTex; +uniform sampler2D depthBuffer; +uniform sampler2D frontBuffer; +uniform sampler2D density; + +uniform float accumTime; +uniform vec4 fogColor; +uniform float fogDensity; +uniform float preBias; +uniform float textured; +uniform float modstrength; +uniform vec4 modspeed;//xy speed layer 1, zw speed layer 2 +uniform vec2 viewpoint; +uniform vec2 texscale; +uniform vec3 ambientColor; +uniform float numtiles; +uniform float fadesize; +uniform vec2 PixelSize; + +in vec4 _hpos; +#define IN_hpos _hpos +out vec4 OUT_col; + +void main() +{ + vec2 uvscreen=((IN_hpos.xy/IN_hpos.w) + 1.0 ) / 2.0; + uvscreen.y = 1.0 - uvscreen.y; + + float obj_test = prepassUncondition( prepassTex, uvscreen).w * preBias; + float depth = tex2D(depthBuffer,uvscreen).r; + float front = tex2D(frontBuffer,uvscreen).r; + + if (depth <= front) + { + OUT_col = vec4(0,0,0,0); + return; + } + + else if ( obj_test < depth ) + depth = obj_test; + if ( front >= 0.0) + depth -= front; + + float diff = 1.0; + vec3 col = fogColor.rgb; + if (textured != 0.0) + { + vec2 offset = viewpoint + ((-0.5 + (texscale * uvscreen)) * numtiles); + + vec2 mod1 = tex2D(density,(offset + (modspeed.xy*accumTime))).rg; + vec2 mod2= tex2D(density,(offset + (modspeed.zw*accumTime))).rg; + diff = (mod2.r + mod1.r) * modstrength; + col *= (2.0 - ((mod1.g + mod2.g) * fadesize))/2.0; + } + + col *= ambientColor; + + vec4 returnColor = vec4(col, 1.0 - saturate(exp(-fogDensity * depth * diff * fadesize))); + + OUT_col = hdrEncode(returnColor); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl new file mode 100644 index 000000000..017ea6ef8 --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreP.glsl @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +in vec4 _hpos; +#define IN_hpos _hpos + +out vec4 OUT_col; + +void main() +{ + float OUT; + clip( IN_hpos.w ); + OUT = IN_hpos.w; + + OUT_col = vec4(OUT,0,0,1); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl new file mode 100644 index 000000000..2f2a1318a --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogPreV.glsl @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +in vec4 vPosition; +#define IN_position vPosition + +out vec4 _hpos; +#define OUT_hpos _hpos + +uniform mat4 modelView; + +void main() +{ + vec4 inPos = IN_position; + inPos.w = 1.0; + + OUT_hpos = tMul( modelView, inPos ); + + gl_Position = OUT_hpos; + correctSSP(gl_Position); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl new file mode 100644 index 000000000..78e149fbf --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogRefl.glsl @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +uniform vec4 fogColor; +uniform float fogDensity; +uniform float reflStrength; +out vec4 OUT_col; + +void main() +{ + OUT_col = vec4(fogColor.rgb,saturate(fogDensity*reflStrength)); +} diff --git a/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogV.glsl b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogV.glsl new file mode 100644 index 000000000..57b3ba87e --- /dev/null +++ b/Templates/Full/game/shaders/common/VolumetricFog/gl/VFogV.glsl @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../gl/hlslCompat.glsl" + +in vec4 vPosition; +#define IN_position vPosition + +out vec4 _hpos; +#define OUT_hpos _hpos + +uniform mat4 modelView; + +void main() +{ + OUT_hpos = tMul(modelView, IN_position); + gl_Position = OUT_hpos; + correctSSP(gl_Position); +} diff --git a/Templates/Full/game/shaders/common/basicCloudsV.hlsl b/Templates/Full/game/shaders/common/basicCloudsV.hlsl index 49842fd37..a3d4bb5fe 100644 --- a/Templates/Full/game/shaders/common/basicCloudsV.hlsl +++ b/Templates/Full/game/shaders/common/basicCloudsV.hlsl @@ -46,6 +46,7 @@ ConnectData main( CloudVert IN ) ConnectData OUT; OUT.hpos = mul(modelview, IN.pos); + OUT.hpos.w = OUT.hpos.z; float2 uv = IN.uv0; uv += texOffset; diff --git a/Templates/Full/game/shaders/common/cloudLayerV.hlsl b/Templates/Full/game/shaders/common/cloudLayerV.hlsl index 8c1cc555f..c34a57c05 100644 --- a/Templates/Full/game/shaders/common/cloudLayerV.hlsl +++ b/Templates/Full/game/shaders/common/cloudLayerV.hlsl @@ -60,8 +60,8 @@ uniform float3 texScale; ConnectData main( CloudVert IN ) { ConnectData OUT; - OUT.hpos = mul(modelview, IN.pos); + OUT.hpos.w = OUT.hpos.z; // Offset the uv so we don't have a seam directly over our head. float2 uv = IN.uv0 + float2( 0.5, 0.5 ); diff --git a/Templates/Full/game/shaders/common/gl/basicCloudsV.glsl b/Templates/Full/game/shaders/common/gl/basicCloudsV.glsl index cccbafa8c..40c597120 100644 --- a/Templates/Full/game/shaders/common/gl/basicCloudsV.glsl +++ b/Templates/Full/game/shaders/common/gl/basicCloudsV.glsl @@ -41,6 +41,7 @@ out vec2 texCoord; void main() { gl_Position = tMul(modelview, IN_pos); + gl_Position.w = gl_Position.z; vec2 uv = IN_uv0; uv += texOffset; diff --git a/Templates/Full/game/shaders/common/gl/cloudLayerV.glsl b/Templates/Full/game/shaders/common/gl/cloudLayerV.glsl index 395c6f286..cba5c009a 100644 --- a/Templates/Full/game/shaders/common/gl/cloudLayerV.glsl +++ b/Templates/Full/game/shaders/common/gl/cloudLayerV.glsl @@ -62,6 +62,7 @@ void main() vec2 IN_uv0 = vTexCoord0.st; gl_Position = modelview * IN_pos; + gl_Position.w = gl_Position.z; // Offset the uv so we don't have a seam directly over our head. vec2 uv = IN_uv0 + vec2( 0.5, 0.5 ); diff --git a/Templates/Full/game/shaders/common/gl/lighting.glsl b/Templates/Full/game/shaders/common/gl/lighting.glsl index eb1c9b355..804ab1e3b 100644 --- a/Templates/Full/game/shaders/common/gl/lighting.glsl +++ b/Templates/Full/game/shaders/common/gl/lighting.glsl @@ -20,6 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "./torque.glsl" #ifndef TORQUE_SHADERGEN @@ -207,14 +208,42 @@ void compute4Lights( vec3 wsView, /// float AL_CalcSpecular( vec3 toLight, vec3 normal, vec3 toEye ) { - #ifdef PHONG_SPECULAR - // (R.V)^c - float specVal = dot( normalize( -reflect( toLight, normal ) ), toEye ); - #else - // (N.H)^c [Blinn-Phong, TGEA style, default] - float specVal = dot( normal, normalize( toLight + toEye ) ); - #endif + // (R.V)^c + float specVal = dot( normalize( -reflect( toLight, normal ) ), toEye ); // Return the specular factor. return pow( max( specVal, 0.00001f ), AL_ConstantSpecularPower ); } + +/// The output for Deferred Lighting +/// +/// @param toLight Normalized vector representing direction from the pixel +/// being lit, to the light source, in world space. +/// +/// @param normal Normalized surface normal. +/// +/// @param toEye The normalized vector representing direction from the pixel +/// being lit to the camera. +/// +vec4 AL_DeferredOutput( + vec3 lightColor, + vec3 diffuseColor, + vec4 matInfo, + vec4 ambient, + float specular, + float shadowAttenuation) +{ + vec3 specularColor = vec3(specular); + bool metalness = getFlag(matInfo.r, 3); + if ( metalness ) + { + specularColor = 0.04 * (1 - specular) + diffuseColor * specular; + } + + //specular = color * map * spec^gloss + float specularOut = (specularColor * matInfo.b * min(pow(max(specular,1.0f), max((matInfo.a / AL_ConstantSpecularPower),1.0f)),matInfo.a)).r; + + lightColor *= vec3(shadowAttenuation); + lightColor += ambient.rgb; + return vec4(lightColor.rgb, specularOut); +} diff --git a/Templates/Full/game/shaders/common/gl/scatterSkyP.glsl b/Templates/Full/game/shaders/common/gl/scatterSkyP.glsl index d9fa80bcf..b4e70f902 100644 --- a/Templates/Full/game/shaders/common/gl/scatterSkyP.glsl +++ b/Templates/Full/game/shaders/common/gl/scatterSkyP.glsl @@ -73,5 +73,8 @@ void main() discard; OUT_col.a = 1; + + OUT_col = clamp(OUT_col, 0.0, 1.0); + OUT_col = hdrEncode( OUT_col ); } diff --git a/Templates/Full/game/shaders/common/gl/torque.glsl b/Templates/Full/game/shaders/common/gl/torque.glsl index 9032a57f7..d4a7c4538 100644 --- a/Templates/Full/game/shaders/common/gl/torque.glsl +++ b/Templates/Full/game/shaders/common/gl/torque.glsl @@ -284,4 +284,37 @@ void fizzle(vec2 vpos, float visibility) /// @note This macro will only work in the void main() method of a pixel shader. #define assert(condition, color) { if(!any(condition)) { OUT_col = color; return; } } +// Deferred Shading: Material Info Flag Check +bool getFlag(float flags, float num) +{ + float process = round(flags * 255); + float squareNum = pow(2.0, num); + return (mod(process, pow(2.0, squareNum)) >= squareNum); +} + +// #define TORQUE_STOCK_GAMMA +#ifdef TORQUE_STOCK_GAMMA +// Sample in linear space. Decodes gamma. +vec4 toLinear(vec4 tex) +{ + return tex; +} +// Encodes gamma. +vec4 toGamma(vec4 tex) +{ + return tex; +} +#else +// Sample in linear space. Decodes gamma. +vec4 toLinear(vec4 tex) +{ + return vec4(pow(abs(tex.rgb), vec3(2.2)), tex.a); +} +// Encodes gamma. +vec4 toGamma(vec4 tex) +{ + return vec4(pow(abs(tex.rgb), vec3(1.0/2.2)), tex.a); +} +#endif // + #endif // _TORQUE_GLSL_ diff --git a/Templates/Full/game/shaders/common/lighting.hlsl b/Templates/Full/game/shaders/common/lighting.hlsl index ec8129e94..a2c753618 100644 --- a/Templates/Full/game/shaders/common/lighting.hlsl +++ b/Templates/Full/game/shaders/common/lighting.hlsl @@ -20,6 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "./torque.hlsl" #ifndef TORQUE_SHADERGEN @@ -207,14 +208,42 @@ void compute4Lights( float3 wsView, /// float AL_CalcSpecular( float3 toLight, float3 normal, float3 toEye ) { - #ifdef PHONG_SPECULAR - // (R.V)^c - float specVal = dot( normalize( -reflect( toLight, normal ) ), toEye ); - #else - // (N.H)^c [Blinn-Phong, TGEA style, default] - float specVal = dot( normal, normalize( toLight + toEye ) ); - #endif + // (R.V)^c + float specVal = dot( normalize( -reflect( toLight, normal ) ), toEye ); // Return the specular factor. return pow( max( specVal, 0.00001f ), AL_ConstantSpecularPower ); } + +/// The output for Deferred Lighting +/// +/// @param toLight Normalized vector representing direction from the pixel +/// being lit, to the light source, in world space. +/// +/// @param normal Normalized surface normal. +/// +/// @param toEye The normalized vector representing direction from the pixel +/// being lit to the camera. +/// +float4 AL_DeferredOutput( + float3 lightColor, + float3 diffuseColor, + float4 matInfo, + float4 ambient, + float specular, + float shadowAttenuation) +{ + float3 specularColor = float3(specular, specular, specular); + bool metalness = getFlag(matInfo.r, 3); + if ( metalness ) + { + specularColor = 0.04 * (1 - specular) + diffuseColor * specular; + } + + //specular = color * map * spec^gloss + float specularOut = (specularColor * matInfo.b * min(pow(specular, max(( matInfo.a/ AL_ConstantSpecularPower),1.0f)),matInfo.a)).r; + + lightColor *= shadowAttenuation; + lightColor += ambient.rgb; + return float4(lightColor.rgb, specularOut); +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/dbgColorBufferP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/dbgColorBufferP.hlsl new file mode 100644 index 000000000..349c943f9 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/dbgColorBufferP.hlsl @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "shadergen:/autogenConditioners.h" +#include "../../postfx/postFx.hlsl" + + +float4 main( PFXVertToPix IN, + uniform sampler2D colorBufferTex : register(S0) ) : COLOR0 +{ + return float4(tex2D( colorBufferTex, IN.uv0 ).rgb, 1.0); +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/dbgLightColorVisualizeP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/dbgLightColorVisualizeP.hlsl index 487b4c740..e037ad8b9 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/dbgLightColorVisualizeP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/dbgLightColorVisualizeP.hlsl @@ -27,8 +27,6 @@ float4 main( PFXVertToPix IN, uniform sampler2D lightPrePassTex : register(S0) ) : COLOR0 { - float3 lightcolor; - float nl_Att, specular; - lightinfoUncondition( tex2D( lightPrePassTex, IN.uv0 ), lightcolor, nl_Att, specular ); - return float4( lightcolor, 1.0 ); + float4 lightColor = tex2D( lightPrePassTex, IN.uv0 ); + return float4( lightColor.rgb, 1.0 ); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/dbgLightSpecularVisualizeP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/dbgLightSpecularVisualizeP.hlsl index edc25ed03..8e1074add 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/dbgLightSpecularVisualizeP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/dbgLightSpecularVisualizeP.hlsl @@ -27,8 +27,6 @@ float4 main( PFXVertToPix IN, uniform sampler2D lightPrePassTex : register(S0) ) : COLOR0 { - float3 lightcolor; - float nl_Att, specular; - lightinfoUncondition( tex2D( lightPrePassTex, IN.uv0 ), lightcolor, nl_Att, specular ); + float specular = tex2D( lightPrePassTex, IN.uv0 ).a; return float4( specular, specular, specular, 1.0 ); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/dbgSpecMapVisualizeP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/dbgSpecMapVisualizeP.hlsl new file mode 100644 index 000000000..ba5f2c0e1 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/dbgSpecMapVisualizeP.hlsl @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "shadergen:/autogenConditioners.h" +#include "../../postfx/postFx.hlsl" + + +float4 main( PFXVertToPix IN, + uniform sampler2D matinfoTex : register(S0) ) : COLOR0 +{ + float specular = tex2D( matinfoTex, IN.uv0 ).b; + return float4( specular, specular, specular, 1.0 ); +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/deferredClearGBufferP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/deferredClearGBufferP.hlsl new file mode 100644 index 000000000..df9870248 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/deferredClearGBufferP.hlsl @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +struct Fragout +{ + float4 col : COLOR0; + float4 col1 : COLOR1; + float4 col2 : COLOR2; +}; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ) +{ + Fragout OUT; + + // Clear Prepass Buffer ( Normals/Depth ); + OUT.col = float4(1.0, 1.0, 1.0, 1.0); + + // Clear Color Buffer. + OUT.col1 = float4(0.0, 0.0, 0.0, 1.0); + + // Clear Material Info Buffer. + OUT.col2 = float4(0.0, 0.0, 0.0, 1.0); + + return OUT; +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/deferredColorShaderP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/deferredColorShaderP.hlsl new file mode 100644 index 000000000..5e6d0a984 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/deferredColorShaderP.hlsl @@ -0,0 +1,44 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +struct Fragout +{ + float4 col : COLOR0; + float4 col1 : COLOR1; + float4 col2 : COLOR2; +}; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +Fragout main( ) +{ + Fragout OUT; + + OUT.col = float4(0.0, 0.0, 0.0, 0.0); + OUT.col1 = float4(1.0, 1.0, 1.0, 1.0); + + // Draw on color buffer. + OUT.col2 = float4(1.0, 0.0, 0.0, 1.0); + + return OUT; +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/deferredShadingP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/deferredShadingP.hlsl new file mode 100644 index 000000000..80e6acde0 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/deferredShadingP.hlsl @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "shadergen:/autogenConditioners.h" +#include "../../postfx/postFx.hlsl" +#include "shaders/common/torque.hlsl" + + +float4 main( PFXVertToPix IN, + uniform sampler2D colorBufferTex : register(S0), + uniform sampler2D lightPrePassTex : register(S1), + uniform sampler2D matInfoTex : register(S2), + uniform sampler2D prepassTex : register(S3)) : COLOR0 +{ + float4 lightBuffer = tex2D( lightPrePassTex, IN.uv0 ); + float4 colorBuffer = tex2D( colorBufferTex, IN.uv0 ); + float4 matInfo = tex2D( matInfoTex, IN.uv0 ); + float specular = saturate(lightBuffer.a); + float depth = prepassUncondition( prepassTex, IN.uv0 ).w; + + if (depth>0.9999) + return float4(0,0,0,0); + + // Diffuse Color Altered by Metalness + bool metalness = getFlag(matInfo.r, 3); + if ( metalness ) + { + colorBuffer *= (1.0 - colorBuffer.a); + } + + colorBuffer *= float4(lightBuffer.rgb, 1.0); + colorBuffer += float4(specular, specular, specular, 1.0); + + return hdrEncode( float4(colorBuffer.rgb, 1.0) ); +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgColorBufferP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgColorBufferP.glsl new file mode 100644 index 000000000..48a96d47d --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgColorBufferP.glsl @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../../gl/hlslCompat.glsl" +#include "shadergen:/autogenConditioners.h" +#include "../../../postfx/gl/postFx.glsl" + +uniform sampler2D colorBufferTex; + +out vec4 OUT_FragColor0; + +void main() +{ + OUT_FragColor0 = vec4(texture( colorBufferTex, uv0 ).rgb, 1.0); +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl index 7c1754097..eb3d6f761 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl @@ -24,13 +24,13 @@ #include "shadergen:/autogenConditioners.h" in vec2 uv0; -uniform sampler2D prepassBuffer; +uniform sampler2D prepassTex; uniform sampler1D depthViz; out vec4 OUT_col; void main() { - float depth = prepassUncondition( prepassBuffer, uv0 ).w; + float depth = prepassUncondition( prepassTex, uv0 ).w; OUT_col = vec4( texture( depthViz, depth ).rgb, 1.0 ); } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl index 05645e193..501e261ca 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl @@ -24,14 +24,12 @@ #include "shadergen:/autogenConditioners.h" in vec2 uv0; -uniform sampler2D lightInfoBuffer; +uniform sampler2D lightPrePassTex; out vec4 OUT_col; void main() { - vec3 lightcolor; - float nl_Att, specular; - lightinfoUncondition( texture( lightInfoBuffer, uv0 ), lightcolor, nl_Att, specular ); - OUT_col = vec4( lightcolor, 1.0 ); + vec4 lightColor = texture( lightPrePassTex, uv0 ); + OUT_col = vec4( lightColor.rgb, 1.0 ); } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl index 7e3e41ee9..c21c9b60f 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl @@ -24,14 +24,12 @@ #include "shadergen:/autogenConditioners.h" in vec2 uv0; -uniform sampler2D lightInfoBuffer; +uniform sampler2D lightPrePassTex; out vec4 OUT_col; void main() { - vec3 lightcolor; - float nl_Att, specular; - lightinfoUncondition( texture( lightInfoBuffer, uv0 ), lightcolor, nl_Att, specular ); + float specular = texture( lightPrePassTex, uv0 ).a; OUT_col = vec4( specular, specular, specular, 1.0 ); } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl index dfc611e88..84ea4d3fb 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl @@ -24,12 +24,12 @@ #include "shadergen:/autogenConditioners.h" in vec2 uv0; -uniform sampler2D prepassBuffer; +uniform sampler2D prepassTex; out vec4 OUT_col; void main() { - vec3 normal = prepassUncondition( prepassBuffer, uv0 ).xyz; + vec3 normal = prepassUncondition( prepassTex, uv0 ).xyz; OUT_col = vec4( ( normal + 1.0 ) * 0.5, 1.0 ); } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgSpecMapVisualizeP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgSpecMapVisualizeP.glsl new file mode 100644 index 000000000..4ba9f6734 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgSpecMapVisualizeP.glsl @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" +#include "shadergen:/autogenConditioners.h" +#include "../../../postfx/gl/postFx.glsl" + +uniform sampler2D matinfoTex; + +out vec4 OUT_FragColor0; + +void main() +{ + float specular = texture( matinfoTex, uv0 ).a; + OUT_FragColor0 = vec4( specular, specular, specular, 1.0 ); +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredClearGBufferP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredClearGBufferP.glsl new file mode 100644 index 000000000..39dc0dc9f --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredClearGBufferP.glsl @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +out vec4 OUT_col; +out vec4 OUT_col1; +out vec4 OUT_col2; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + // Clear Prepass Buffer ( Normals/Depth ); + OUT_col = vec4(1.0, 1.0, 1.0, 1.0); + + // Clear Color Buffer. + OUT_col1 = vec4(0.0, 0.0, 0.0, 1.0); + + // Clear Material Info Buffer. + OUT_col2 = vec4(0.0, 0.0, 0.0, 1.0); +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredColorShaderP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredColorShaderP.glsl new file mode 100644 index 000000000..85c553089 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredColorShaderP.glsl @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +layout (location = 0) out vec4 col; +layout (location = 1) out vec4 col1; +layout (location = 2) out vec4 col2; + +//----------------------------------------------------------------------------- +// Main +//----------------------------------------------------------------------------- +void main() +{ + col = vec4(0.0, 0.0, 0.0, 0.0); + col1 = vec4(1.0, 1.0, 1.0, 1.0); + + // Draw on color buffer. + col2 = vec4(1.0, 0.0, 0.0, 1.0); +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredShadingP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredShadingP.glsl new file mode 100644 index 000000000..4ee4b1d81 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredShadingP.glsl @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../../gl/hlslCompat.glsl" +#include "shadergen:/autogenConditioners.h" +#include "../../../postfx/gl/postFx.glsl" +#include "../../../gl/torque.glsl" + +uniform sampler2D colorBufferTex; +uniform sampler2D lightPrePassTex; +uniform sampler2D matInfoTex; +uniform sampler2D prepassTex; + +out vec4 OUT_col; + +void main() +{ + float depth = prepassUncondition( prepassTex, uv0 ).w; + if (depth>0.9999) + { + OUT_col = vec4(0.0); + return; + } + vec4 lightBuffer = texture( lightPrePassTex, uv0 ); + vec4 colorBuffer = texture( colorBufferTex, uv0 ); + vec4 matInfo = texture( matInfoTex, uv0 ); + float specular = clamp(lightBuffer.a,0.0,1.0); + + // Diffuse Color Altered by Metalness + bool metalness = getFlag(matInfo.r, 3); + if ( metalness ) + { + colorBuffer *= (1.0 - colorBuffer.a); + } + + colorBuffer *= vec4(lightBuffer.rgb, 1.0); + colorBuffer += vec4(specular, specular, specular, 1.0); + + OUT_col = hdrEncode( vec4(colorBuffer.rgb, 1.0) ); +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl index 92c9369a7..8a1aae3ca 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl @@ -33,6 +33,7 @@ in vec4 wsEyeDir; in vec4 ssPos; in vec4 vsEyeDir; +in vec4 color; #ifdef USE_COOKIE_TEX @@ -111,6 +112,10 @@ uniform sampler2D prePassBuffer; uniform sampler2D dynamicShadowMap; #endif +uniform sampler2D lightBuffer; +uniform sampler2D colorBuffer; +uniform sampler2D matInfoBuffer; + uniform vec4 rtParams0; uniform vec3 lightPosition; @@ -133,6 +138,15 @@ void main() vec3 ssPos = ssPos.xyz / ssPos.w; vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); + // Emissive. + vec4 matInfo = texture( matInfoBuffer, uvScene ); + bool emissive = getFlag( matInfo.r, 0 ); + if ( emissive ) + { + OUT_col = vec4(0.0, 0.0, 0.0, 0.0); + return; + } + // Sample/unpack the normal/z data vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene ); vec3 normal = prepassSample.rgb; @@ -244,5 +258,6 @@ void main() addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); } - OUT_col = lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult ); + vec4 colorSample = texture( colorBuffer, uvScene ); + OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl index 29c278508..e7f3e88a7 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl @@ -32,10 +32,12 @@ in vec4 wsEyeDir; in vec4 ssPos; in vec4 vsEyeDir; +in vec4 color; #define IN_wsEyeDir wsEyeDir #define IN_ssPos ssPos #define IN_vsEyeDir vsEyeDir +#define IN_color color #ifdef USE_COOKIE_TEX @@ -48,6 +50,10 @@ uniform sampler2D prePassBuffer; uniform sampler2D shadowMap; uniform sampler2D dynamicShadowMap; +uniform sampler2D lightBuffer; +uniform sampler2D colorBuffer; +uniform sampler2D matInfoBuffer; + uniform vec4 rtParams0; uniform vec3 lightPosition; @@ -74,6 +80,15 @@ void main() vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w; vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); + // Emissive. + vec4 matInfo = texture( matInfoBuffer, uvScene ); + bool emissive = getFlag( matInfo.r, 0 ); + if ( emissive ) + { + OUT_col = vec4(0.0, 0.0, 0.0, 0.0); + return; + } + // Sample/unpack the normal/z data vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene ); vec3 normal = prepassSample.rgb; @@ -180,5 +195,6 @@ void main() addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); } - OUT_col = lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult ); + vec4 colorSample = texture( colorBuffer, uvScene ); + OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl index 4eb4973a3..608524a5a 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl @@ -39,10 +39,13 @@ uniform sampler2D dynamicShadowMap; #ifdef USE_SSAO_MASK uniform sampler2D ssaoMask ; -uniform vec4 rtParams2; +uniform vec4 rtParams3; #endif -uniform sampler2D prePassBuffer; +uniform sampler2D prePassBuffer; +uniform sampler2D lightBuffer; +uniform sampler2D colorBuffer; +uniform sampler2D matInfoBuffer; uniform vec3 lightDirection; uniform vec4 lightColor; uniform float lightBrightness; @@ -189,7 +192,16 @@ vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap, out vec4 OUT_col; void main() -{ +{ + // Emissive. + float4 matInfo = texture( matInfoBuffer, uv0 ); + bool emissive = getFlag( matInfo.r, 0 ); + if ( emissive ) + { + OUT_col = vec4(1.0, 1.0, 1.0, 0.0); + return; + } + // Sample/unpack the normal/z data vec4 prepassSample = prepassUncondition( prePassBuffer, uv0 ); vec3 normal = prepassSample.rgb; @@ -228,8 +240,6 @@ void main() shadowSoftness, dotNL, overDarkPSSM); - - vec4 dynamic_shadowed_colors = AL_VectorLightShadowCast( dynamicShadowMap, uv0.xy, dynamicWorldToLightProj, @@ -242,14 +252,13 @@ void main() shadowSoftness, dotNL, overDarkPSSM); - float static_shadowed = static_shadowed_colors.a; float dynamic_shadowed = dynamic_shadowed_colors.a; #ifdef PSSM_DEBUG_RENDER debugColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5; #endif - + // Fade out the shadow at the end of the range. vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth); float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y; @@ -295,7 +304,7 @@ void main() // Sample the AO texture. #ifdef USE_SSAO_MASK - float ao = 1.0 - texture( ssaoMask, viewportCoordToRenderTarget( uv0.xy, rtParams2 ) ).r; + float ao = 1.0 - texture( ssaoMask, viewportCoordToRenderTarget( uv0.xy, rtParams3 ) ).r; addToResult *= ao; #endif @@ -303,6 +312,6 @@ void main() lightColorOut = debugColor; #endif - OUT_col = lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult ); - + vec4 colorSample = texture( colorBuffer, uv0 ); + OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl index 48c0d76e3..9051ff09d 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl @@ -34,6 +34,7 @@ struct ConvexConnectP float4 wsEyeDir : TEXCOORD0; float4 ssPos : TEXCOORD1; float4 vsEyeDir : TEXCOORD2; + float4 color : COLOR0; }; @@ -117,6 +118,10 @@ float4 main( ConvexConnectP IN, uniform sampler2D dynamicShadowMap : register(S2), #endif + uniform sampler2D lightBuffer : register(S5), + uniform sampler2D colorBuffer : register(S6), + uniform sampler2D matInfoBuffer : register(S7), + uniform float4 rtParams0, uniform float3 lightPosition, @@ -136,7 +141,15 @@ float4 main( ConvexConnectP IN, // Compute scene UV float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; float2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); - + + // Emissive. + float4 matInfo = tex2D( matInfoBuffer, uvScene ); + bool emissive = getFlag( matInfo.r, 0 ); + if ( emissive ) + { + return float4(0.0, 0.0, 0.0, 0.0); + } + // Sample/unpack the normal/z data float4 prepassSample = prepassUncondition( prePassBuffer, uvScene ); float3 normal = prepassSample.rgb; @@ -250,5 +263,6 @@ float4 main( ConvexConnectP IN, addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); } - return lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult ); + float4 colorSample = tex2D( colorBuffer, uvScene ); + return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl index 33c7f333e..226b9cfea 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl @@ -34,6 +34,7 @@ struct ConvexConnectP float4 wsEyeDir : TEXCOORD0; float4 ssPos : TEXCOORD1; float4 vsEyeDir : TEXCOORD2; + float4 color : COLOR0; }; #ifdef USE_COOKIE_TEX @@ -50,6 +51,10 @@ float4 main( ConvexConnectP IN, uniform sampler2D shadowMap : register(S1), uniform sampler2D dynamicShadowMap : register(S2), + uniform sampler2D lightBuffer : register(S5), + uniform sampler2D colorBuffer : register(S6), + uniform sampler2D matInfoBuffer : register(S7), + uniform float4 rtParams0, uniform float3 lightPosition, @@ -72,6 +77,14 @@ float4 main( ConvexConnectP IN, float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; float2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); + // Emissive. + float4 matInfo = tex2D( matInfoBuffer, uvScene ); + bool emissive = getFlag( matInfo.r, 0 ); + if ( emissive ) + { + return float4(0.0, 0.0, 0.0, 0.0); + } + // Sample/unpack the normal/z data float4 prepassSample = prepassUncondition( prePassBuffer, uvScene ); float3 normal = prepassSample.rgb; @@ -179,5 +192,6 @@ float4 main( ConvexConnectP IN, addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); } - return lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult ); + float4 colorSample = tex2D( colorBuffer, uvScene ); + return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl index 2d719587e..896576564 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl @@ -157,6 +157,10 @@ float4 main( FarFrustumQuadConnectP IN, uniform sampler2D prePassBuffer : register(S0), + uniform sampler2D lightBuffer : register(S5), + uniform sampler2D colorBuffer : register(S6), + uniform sampler2D matInfoBuffer : register(S7), + uniform float3 lightDirection, uniform float4 lightColor, uniform float lightBrightness, @@ -190,7 +194,15 @@ float4 main( FarFrustumQuadConnectP IN, uniform float4 dynamicFarPlaneScalePSSM ) : COLOR0 -{ +{ + // Emissive. + float4 matInfo = tex2D( matInfoBuffer, IN.uv0 ); + bool emissive = getFlag( matInfo.r, 0 ); + if ( emissive ) + { + return float4(1.0, 1.0, 1.0, 0.0); + } + // Sample/unpack the normal/z data float4 prepassSample = prepassUncondition( prePassBuffer, IN.uv0 ); float3 normal = prepassSample.rgb; @@ -229,7 +241,6 @@ float4 main( FarFrustumQuadConnectP IN, shadowSoftness, dotNL, overDarkPSSM); - float4 dynamic_shadowed_colors = AL_VectorLightShadowCast( dynamicShadowMap, IN.uv0.xy, dynamicWorldToLightProj, @@ -276,6 +287,7 @@ float4 main( FarFrustumQuadConnectP IN, float Sat_NL_Att = saturate( dotNL * shadowed ) * lightBrightness; float3 lightColorOut = lightMapParams.rgb * lightColor.rgb; + float4 addToResult = (lightAmbient * (1 - ambientCameraFactor)) + ( lightAmbient * ambientCameraFactor * saturate(dot(normalize(-IN.vsEyeRay), normal)) ); // TODO: This needs to be removed when lightmapping is disabled @@ -303,5 +315,6 @@ float4 main( FarFrustumQuadConnectP IN, lightColorOut = debugColor; #endif - return lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult ); + float4 colorSample = tex2D( colorBuffer, IN.uv0 ); + return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); } diff --git a/Templates/Full/game/shaders/common/postFx/VolFogGlowP.hlsl b/Templates/Full/game/shaders/common/postFx/VolFogGlowP.hlsl new file mode 100644 index 000000000..8a61b5928 --- /dev/null +++ b/Templates/Full/game/shaders/common/postFx/VolFogGlowP.hlsl @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 R.G.S. - Richards Game Studio, the Netherlands +// http://www.richardsgamestudio.com/ +// +// If you find this code useful or you are feeling particularly generous I +// would ask that you please go to http://www.richardsgamestudio.com/ then +// choose Donations from the menu on the left side and make a donation to +// Richards Game Studio. It will be highly appreciated. +// +// The MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog Glow postFx pixel shader V1.00 + +#include "./postFx.hlsl" + +uniform sampler2D diffuseMap : register(S0); +uniform float strength; + +struct VertToPix +{ + float4 hpos : POSITION; + + float2 uv0 : TEXCOORD0; + float2 uv1 : TEXCOORD1; + float2 uv2 : TEXCOORD2; + float2 uv3 : TEXCOORD3; + + float2 uv4 : TEXCOORD4; + float2 uv5 : TEXCOORD5; + float2 uv6 : TEXCOORD6; + float2 uv7 : TEXCOORD7; +}; + +float4 main( VertToPix IN ) : COLOR +{ + float4 kernel = float4( 0.175, 0.275, 0.375, 0.475 ) * strength; + + float4 OUT = 0; + OUT += tex2D( diffuseMap, IN.uv0 ) * kernel.x; + OUT += tex2D( diffuseMap, IN.uv1 ) * kernel.y; + OUT += tex2D( diffuseMap, IN.uv2 ) * kernel.z; + OUT += tex2D( diffuseMap, IN.uv3 ) * kernel.w; + + OUT += tex2D( diffuseMap, IN.uv4 ) * kernel.x; + OUT += tex2D( diffuseMap, IN.uv5 ) * kernel.y; + OUT += tex2D( diffuseMap, IN.uv6 ) * kernel.z; + OUT += tex2D( diffuseMap, IN.uv7 ) * kernel.w; + + // Calculate a lumenance value in the alpha so we + // can use alpha test to save fillrate. + float3 rgb2lum = float3( 0.30, 0.59, 0.11 ); + OUT.a = dot( OUT.rgb, rgb2lum ); + + return OUT; +} diff --git a/Templates/Full/game/shaders/common/postFx/gammaP.hlsl b/Templates/Full/game/shaders/common/postFx/gammaP.hlsl index dedfe8eb5..20196548b 100644 --- a/Templates/Full/game/shaders/common/postFx/gammaP.hlsl +++ b/Templates/Full/game/shaders/common/postFx/gammaP.hlsl @@ -28,7 +28,8 @@ uniform sampler2D backBuffer : register(S0); uniform sampler1D colorCorrectionTex : register( s1 ); uniform float OneOverGamma; - +uniform float Brightness; +uniform float Contrast; float4 main( PFXVertToPix IN ) : COLOR0 { @@ -42,5 +43,11 @@ float4 main( PFXVertToPix IN ) : COLOR0 // Apply gamma correction color.rgb = pow( abs(color.rgb), OneOverGamma ); + // Apply contrast + color.rgb = ((color.rgb - 0.5f) * Contrast) + 0.5f; + + // Apply brightness + color.rgb += Brightness; + return color; } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/postFx/gl/VolFogGlowP.glsl b/Templates/Full/game/shaders/common/postFx/gl/VolFogGlowP.glsl new file mode 100644 index 000000000..01b072dd9 --- /dev/null +++ b/Templates/Full/game/shaders/common/postFx/gl/VolFogGlowP.glsl @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 R.G.S. - Richards Game Studio, the Netherlands +// http://www.richardsgamestudio.com/ +// +// If you find this code useful or you are feeling particularly generous I +// would ask that you please go to http://www.richardsgamestudio.com/ then +// choose Donations from the menu on the left side and make a donation to +// Richards Game Studio. It will be highly appreciated. +// +// The MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Volumetric Fog Glow postFx pixel shader V1.00 + +uniform sampler2D diffuseMap; +uniform float strength; + +out vec4 OUT_col; + +in vec2 uv0; +in vec2 uv1; +in vec2 uv2; +in vec2 uv3; + +in vec2 uv4; +in vec2 uv5; +in vec2 uv6; +in vec2 uv7; + +void main() +{ + vec4 kernel = vec4( 0.175, 0.275, 0.375, 0.475 ) * strength; + + OUT_col = vec4(0); + OUT_col += texture( diffuseMap, uv0 ) * kernel.x; + OUT_col += texture( diffuseMap, uv1 ) * kernel.y; + OUT_col += texture( diffuseMap, uv2 ) * kernel.z; + OUT_col += texture( diffuseMap, uv3 ) * kernel.w; + + OUT_col += texture( diffuseMap, uv4 ) * kernel.x; + OUT_col += texture( diffuseMap, uv5 ) * kernel.y; + OUT_col += texture( diffuseMap, uv6 ) * kernel.z; + OUT_col += texture( diffuseMap, uv7 ) * kernel.w; + + // Calculate a lumenance value in the alpha so we + // can use alpha test to save fillrate. + vec3 rgb2lum = vec3( 0.30, 0.59, 0.11 ); + OUT_col.a = dot( OUT_col.rgb, rgb2lum ); +} diff --git a/Templates/Full/game/shaders/common/postFx/gl/gammaP.glsl b/Templates/Full/game/shaders/common/postFx/gl/gammaP.glsl index 414a277d3..1bf5d1b8f 100644 --- a/Templates/Full/game/shaders/common/postFx/gl/gammaP.glsl +++ b/Templates/Full/game/shaders/common/postFx/gl/gammaP.glsl @@ -28,6 +28,8 @@ uniform sampler2D backBuffer; uniform sampler1D colorCorrectionTex; uniform float OneOverGamma; +uniform float Brightness; +uniform float Contrast; in vec2 uv0; @@ -45,5 +47,11 @@ void main() // Apply gamma correction color.rgb = pow( abs(color.rgb), vec3(OneOverGamma) ); + // Apply contrast + color.rgb = ((color.rgb - 0.5f) * Contrast) + 0.5f; + + // Apply brightness + color.rgb += Brightness; + OUT_col = color; } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/postFx/hdr/finalPassCombineP.hlsl b/Templates/Full/game/shaders/common/postFx/hdr/finalPassCombineP.hlsl index 7ac71bebd..cb71f01c2 100644 --- a/Templates/Full/game/shaders/common/postFx/hdr/finalPassCombineP.hlsl +++ b/Templates/Full/game/shaders/common/postFx/hdr/finalPassCombineP.hlsl @@ -20,6 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "shadergen:/autogenConditioners.h" #include "../../torque.hlsl" #include "../postFx.hlsl" @@ -27,6 +28,7 @@ uniform sampler2D sceneTex : register( s0 ); uniform sampler2D luminanceTex : register( s1 ); uniform sampler2D bloomTex : register( s2 ); uniform sampler1D colorCorrectionTex : register( s3 ); +uniform sampler2D prepassTex : register(S4); uniform float2 texSize0; uniform float2 texSize2; @@ -41,6 +43,8 @@ uniform float3 g_fBlueShiftColor; uniform float g_fBloomScale; uniform float g_fOneOverGamma; +uniform float Brightness; +uniform float Contrast; float4 main( PFXVertToPix IN ) : COLOR0 @@ -81,15 +85,24 @@ float4 main( PFXVertToPix IN ) : COLOR0 } // Add the bloom effect. - sample += g_fBloomScale * bloom; + float depth = prepassUncondition( prepassTex, IN.uv0 ).w; + if (depth>0.9999) + sample += g_fBloomScale * bloom; // Apply the color correction. sample.r = tex1D( colorCorrectionTex, sample.r ).r; sample.g = tex1D( colorCorrectionTex, sample.g ).g; sample.b = tex1D( colorCorrectionTex, sample.b ).b; + // Apply gamma correction sample.rgb = pow( abs(sample.rgb), g_fOneOverGamma ); + + // Apply contrast + sample.rgb = ((sample.rgb - 0.5f) * Contrast) + 0.5f; + + // Apply brightness + sample.rgb += Brightness; return sample; } diff --git a/Templates/Full/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl b/Templates/Full/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl index 38762baa5..24a516e79 100644 --- a/Templates/Full/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl +++ b/Templates/Full/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl @@ -23,11 +23,13 @@ #include "../../../gl/torque.glsl" #include "../../../gl/hlslCompat.glsl" #include "../../gl/postFX.glsl" +#include "shadergen:/autogenConditioners.h" uniform sampler2D sceneTex; uniform sampler2D luminanceTex; uniform sampler2D bloomTex; uniform sampler1D colorCorrectionTex; +uniform sampler2D prepassTex; uniform vec2 texSize0; uniform vec2 texSize2; @@ -42,6 +44,8 @@ uniform vec3 g_fBlueShiftColor; uniform float g_fBloomScale; uniform float g_fOneOverGamma; +uniform float Brightness; +uniform float Contrast; out vec4 OUT_col; @@ -84,7 +88,9 @@ void main() } // Add the bloom effect. - _sample += g_fBloomScale * bloom; + float depth = prepassUncondition( prepassTex, IN_uv0 ).w; + if (depth>0.9999) + _sample += g_fBloomScale * bloom; // Apply the color correction. _sample.r = texture( colorCorrectionTex, _sample.r ).r; @@ -93,6 +99,12 @@ void main() // Apply gamma correction _sample.rgb = pow( abs(_sample.rgb), vec3(g_fOneOverGamma) ); + + // Apply contrast + _sample.rgb = ((_sample.rgb - 0.5f) * Contrast) + 0.5f; + + // Apply brightness + _sample.rgb += Brightness; OUT_col = _sample; } diff --git a/Templates/Full/game/shaders/common/scatterSkyP.hlsl b/Templates/Full/game/shaders/common/scatterSkyP.hlsl index 572abdd74..1a9433c73 100644 --- a/Templates/Full/game/shaders/common/scatterSkyP.hlsl +++ b/Templates/Full/game/shaders/common/scatterSkyP.hlsl @@ -62,6 +62,6 @@ float4 main( Conn In ) : COLOR0 Out = lerp( color, nightSkyColor, nightInterpAndExposure.y ); Out.a = 1; - + Out = saturate(Out); return hdrEncode( Out ); } diff --git a/Templates/Full/game/shaders/common/terrain/terrain.glsl b/Templates/Full/game/shaders/common/terrain/terrain.glsl index 79f80888c..756edd553 100644 --- a/Templates/Full/game/shaders/common/terrain/terrain.glsl +++ b/Templates/Full/game/shaders/common/terrain/terrain.glsl @@ -32,6 +32,7 @@ float calcBlend( float texId, vec2 layerCoord, float layerSize, vec4 layerSample vec4 diff = clamp( abs( layerSample - texId ), 0.0, 1.0 ); float noBlend = float(any( bvec4(1 - diff) )); + // Check if any of the layer samples // match the current texture id. vec4 factors = vec4(0); for(int i = 0; i < 4; i++) diff --git a/Templates/Full/game/shaders/common/torque.hlsl b/Templates/Full/game/shaders/common/torque.hlsl index 1d253936b..f50832cb8 100644 --- a/Templates/Full/game/shaders/common/torque.hlsl +++ b/Templates/Full/game/shaders/common/torque.hlsl @@ -277,5 +277,37 @@ void fizzle(float2 vpos, float visibility) clip( visibility - frac( determinant( m ) ) ); } +// Deferred Shading: Material Info Flag Check +bool getFlag(float flags, int num) +{ + int process = round(flags * 255); + int squareNum = pow(2, num); + return (fmod(process, pow(2, squareNum)) >= squareNum); +} + +// #define TORQUE_STOCK_GAMMA +#ifdef TORQUE_STOCK_GAMMA +// Sample in linear space. Decodes gamma. +float4 toLinear(float4 tex) +{ + return tex; +} +// Encodes gamma. +float4 toLinear(float4 tex) +{ + return tex; +} +#else +// Sample in linear space. Decodes gamma. +float4 toLinear(float4 tex) +{ + return float4(pow(abs(tex.rgb), 2.2), tex.a); +} +// Encodes gamma. +float4 toGamma(float4 tex) +{ + return float4(pow(abs(tex.rgb), 1.0/2.2), tex.a); +} +#endif // #endif // _TORQUE_HLSL_ diff --git a/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl b/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl index 82c421031..1d5a07c3f 100644 --- a/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl +++ b/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl @@ -120,6 +120,7 @@ void main() { // Modulate baseColor by the ambientColor. vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1 ); + waterBaseColor = toLinear(waterBaseColor); // Get the bumpNorm... vec3 bumpNorm = ( texture( bumpMap, IN_rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; diff --git a/Templates/Full/game/shaders/common/water/gl/waterP.glsl b/Templates/Full/game/shaders/common/water/gl/waterP.glsl index af151020a..a68ede84e 100644 --- a/Templates/Full/game/shaders/common/water/gl/waterP.glsl +++ b/Templates/Full/game/shaders/common/water/gl/waterP.glsl @@ -295,7 +295,7 @@ void main() foamColor.rgb *= FOAM_OPACITY * foamAmt * foamColor.a; // Get reflection map color. - vec4 refMapColor = hdrDecode( texture( reflectMap, reflectCoord ) ); + vec4 refMapColor = texture( reflectMap, reflectCoord ); // If we do not have a reflection texture then we use the cubemap. refMapColor = mix( refMapColor, texture( skyMap, reflectionVec ), NO_REFLECT ); @@ -324,6 +324,7 @@ void main() // Calculate the water "base" color based on depth. vec4 waterBaseColor = baseColor * texture( depthGradMap, saturate( delta / depthGradMax ) ); + waterBaseColor = toLinear(waterBaseColor); // Modulate baseColor by the ambientColor. waterBaseColor *= vec4( ambientColor.rgb, 1 ); diff --git a/Templates/Full/game/shaders/common/water/waterBasicP.hlsl b/Templates/Full/game/shaders/common/water/waterBasicP.hlsl index d27b28c67..7ae933f6f 100644 --- a/Templates/Full/game/shaders/common/water/waterBasicP.hlsl +++ b/Templates/Full/game/shaders/common/water/waterBasicP.hlsl @@ -117,6 +117,7 @@ float4 main( ConnectData IN ) : COLOR { // Modulate baseColor by the ambientColor. float4 waterBaseColor = baseColor * float4( ambientColor.rgb, 1 ); + waterBaseColor = toLinear(waterBaseColor); // Get the bumpNorm... float3 bumpNorm = ( tex2D( bumpMap, IN.rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; diff --git a/Templates/Full/game/shaders/common/water/waterP.hlsl b/Templates/Full/game/shaders/common/water/waterP.hlsl index 851fb471f..c4edff0d7 100644 --- a/Templates/Full/game/shaders/common/water/waterP.hlsl +++ b/Templates/Full/game/shaders/common/water/waterP.hlsl @@ -282,7 +282,7 @@ float4 main( ConnectData IN ) : COLOR foamColor.rgb *= FOAM_OPACITY * foamAmt * foamColor.a; // Get reflection map color. - float4 refMapColor = hdrDecode( tex2D( reflectMap, reflectCoord ) ); + float4 refMapColor = tex2D( reflectMap, reflectCoord ); // If we do not have a reflection texture then we use the cubemap. refMapColor = lerp( refMapColor, texCUBE( skyMap, reflectionVec ), NO_REFLECT ); @@ -311,6 +311,7 @@ float4 main( ConnectData IN ) : COLOR // Calculate the water "base" color based on depth. float4 waterBaseColor = baseColor * tex1D( depthGradMap, saturate( delta / depthGradMax ) ); + waterBaseColor = toLinear(waterBaseColor); // Modulate baseColor by the ambientColor. waterBaseColor *= float4( ambientColor.rgb, 1 ); diff --git a/Templates/Full/game/tools/classIcons/VolumetricFog.png b/Templates/Full/game/tools/classIcons/VolumetricFog.png new file mode 100644 index 000000000..5dc516cb5 Binary files /dev/null and b/Templates/Full/game/tools/classIcons/VolumetricFog.png differ diff --git a/Templates/Full/game/tools/gui/colorPicker.ed.gui b/Templates/Full/game/tools/gui/colorPicker.ed.gui index 18dad276e..c203ca52e 100644 --- a/Templates/Full/game/tools/gui/colorPicker.ed.gui +++ b/Templates/Full/game/tools/gui/colorPicker.ed.gui @@ -1,289 +1,722 @@ //--- OBJECT WRITE BEGIN --- %guiContent = new GuiColorPickerCtrl(ColorPickerDlg,EditorGuiGroup) { - canSaveDynamicFields = "0"; - isContainer = "1"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; + displayMode = "Dropper"; // this makes the background visible + actionOnMove = "1"; position = "0 0"; - Extent = "800 600"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; + extent = "1024 768"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; hovertime = "1000"; - DisplayMode = "Dropper"; // this makes the background visible - ActionOnMove = "1"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; new GuiWindowCtrl(GuiPickerDlg) { - canSaveDynamicFields = "0"; - isContainer = "1"; - Profile = "ToolsGuiWindowProfile"; - HorizSizing = "windowRelative"; - VertSizing = "windowRelative"; - position = "170 100"; - Extent = "348 347"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; text = "Color Picker"; - maxLength = "255"; resizeWidth = "0"; resizeHeight = "0"; canMove = "1"; canClose = "1"; canMinimize = "0"; canMaximize = "0"; - minSize = "50 50"; + canCollapse = "0"; closeCommand = "DoColorPickerCancelCallback(); ColorPickerDlg.getRoot().popDialog(ColorPickerDlg);"; - + position = "170 100"; + extent = "439 317"; + minExtent = "8 2"; + horizSizing = "windowRelative"; + vertSizing = "windowRelative"; + profile = "ToolsGuiWindowProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + new GuiBitmapBorderCtrl(){ // color blend - Profile = "ToolsGuiGroupBorderProfile"; position = "3 24"; - Extent = "255 258"; + extent = "255 258"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiGroupBorderProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiColorPickerCtrl(ColorBlendSelect) { + baseColor = "1 0 0 1"; + pickColor = "0 0 0 1"; + selectorGap = "1"; + displayMode = "BlendColor"; + actionOnMove = "1"; + position = "1 0"; + extent = "255 258"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "updateRGBValues(1);"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; new GuiBitmapBorderCtrl(){ // Hue - Profile = "ToolsGuiGroupBorderProfile"; position = "263 23"; - Extent = "25 261"; - }; - new GuiBitmapBorderCtrl(){ // new old color - Profile = "ToolsGuiGroupBorderProfile"; - position = "292 37"; - Extent = "52 99"; - }; - new GuiBitmapBorderCtrl(){ // rgb - Profile = "ToolsGuiGroupBorderProfile"; - position = "292 209"; - Extent = "52 75"; - }; - new GuiBitmapBorderCtrl(){ // alpha - Profile = "ToolsGuiGroupBorderProfile"; - position = "3 287"; - Extent = "341 24"; - }; - new GuiColorPickerCtrl(ColorBlendSelect) { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "3 24"; - Extent = "255 258"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - command = "updateRGBValues(1);"; + extent = "25 261"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiGroupBorderProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; hovertime = "1000"; - baseColor = "1 0 0 1"; - PickColor = "0 0 0 1"; - SelectorGap = "1"; - DisplayMode = "BlendColor"; - ActionOnMove = "1"; - }; - new GuiColorPickerCtrl(ColorRangeSelect) { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "264 24"; - Extent = "21 257"; - MinExtent = "8 2"; + isContainer = "1"; canSave = "1"; - Visible = "1"; - Command = "updatePickerBaseColor(1);"; - hovertime = "1000"; - baseColor = "1 0 0 1"; - PickColor = "1 0 0 1"; - SelectorGap = "1"; - DisplayMode = "VertColor"; - ActionOnMove = "1"; - }; - new GuiTextCtrl() { canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "298 215"; - Extent = "8 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; - text = "R"; - maxLength = "255"; - }; - new GuiTextEditCtrl(Channel_R_Val) { // Red Channal - Profile = "ToolsGuiNumericTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "307 215"; - Extent = "34 18"; - text = "0"; - maxLength = "4"; - altCommand = "setColorInfo();"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "297 238"; - Extent = "8 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; - text = "G"; - maxLength = "255"; - }; - new GuiTextEditCtrl(Channel_G_Val) { // Green Channal - Profile = "ToolsGuiNumericTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "307 238"; - Extent = "34 18"; - text = "0"; - maxLength = "4"; - altCommand = "setColorInfo();"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "298 261"; - Extent = "8 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; - text = "B"; - maxLength = "255"; - }; - new GuiTextEditCtrl(Channel_B_Val) { // Blue Channal - Profile = "ToolsGuiNumericTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "307 261"; - Extent = "34 18"; - text = "0"; - maxLength = "4"; - altCommand = "setColorInfo();"; - }; - - - new GuiControl() { - class = "AggregateControl"; - position = "2 290"; - Extent = "341 18"; - - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "267 0"; - Extent = "29 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; + + new GuiColorPickerCtrl(ColorRangeSelect) { + baseColor = "1 0 0 1"; + pickColor = "1 0 0 1"; + selectorGap = "1"; + displayMode = "VertColor"; + actionOnMove = "1"; + position = "1 1"; + extent = "21 257"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "updatePickerBaseColor(1);"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; hovertime = "1000"; - text = "Alpha"; - maxLength = "255"; - }; - new GuiSliderCtrl(ColorAlphaSelect) { - internalName = "slider"; - canSaveDynamicFields = "0"; isContainer = "0"; - Profile = "ToolsGuiSliderProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "5 3"; - Extent = "251 13"; - MinExtent = "8 2"; canSave = "1"; - Visible = "1"; - altCommand = "$ThisControl.getParent().updateFromChild($ThisControl); updateColorPickerAlpha( $ThisControl.getValue() );"; - hovertime = "1000"; - range = "0 1"; - ticks = "0"; - value = "1"; - }; - new GuiTextEditCtrl(Channel_A_Val) { // Alpha Channal - internalName = "textEdit"; - Profile = "ToolsGuiNumericTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "305 0"; - Extent = "34 18"; - text = "0"; - maxLength = "4"; - altCommand = "$ThisControl.getParent().updateFromChild($ThisControl); updateColorPickerAlpha( $ThisControl.getValue() );"; + canSaveDynamicFields = "0"; }; }; - new GuiSwatchButtonCtrl(myColor){ // New Color // - Profile = "ToolsGuiDefaultProfile"; - position = "293 38"; - Extent = "50 50"; - }; - new GuiTextCtrl(){ - Profile = "ToolsGuiDefaultProfile"; + new GuiTextCtrl() { text = "New"; position = "306 22"; - Extent = "26 14"; + extent = "26 14"; + profile = "GuiDefaultProfile"; }; - new GuiSwatchButtonCtrl(oldColor){ // Old Color // - Profile = "ToolsGuiDefaultProfile"; - position = "293 85"; - Extent = "50 50"; + new GuiBitmapBorderCtrl(){ // new old color + position = "292 37"; + extent = "52 99"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiGroupBorderProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiSwatchButtonCtrl(myColor){ // New Color // + position = "1 1"; + extent = "50 50"; + profile = "GuiDefaultProfile"; + }; + new GuiSwatchButtonCtrl(oldColor){ // Old Color // + position = "1 48"; + extent = "50 50"; + profile = "GuiDefaultProfile"; + }; }; - new GuiTextCtrl(){ - Profile = "ToolsGuiDefaultProfile"; + new GuiTextCtrl() { text = "Old"; position = "310 138"; - Extent = "26 14"; + extent = "26 14"; + profile = "GuiDefaultProfile"; + }; + new GuiBitmapBorderCtrl(){ // Color Text Fields + position = "291 165"; + extent = "141 118"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiGroupBorderProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiControl() { // rgb + position = "4 0"; + extent = "52 75"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "R"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "5 6"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Red Channel color value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_R_Val) { // Red Channal + text = "0"; + maxLength = "4"; + position = "14 6"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + class = "ColorPickerRGBClass"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Red Channel color value."; + }; + new GuiTextCtrl() { + text = "G"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "4 29"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Green Channel color value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_G_Val) { // Green Channal + text = "0"; + maxLength = "4"; + position = "14 29"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + class = "ColorPickerRGBClass"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Green Channel color value."; + }; + new GuiTextCtrl() { + text = "B"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "5 52"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Blue Channel color value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_B_Val) { // Blue Channal + text = "0"; + maxLength = "4"; + position = "14 52"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + class = "ColorPickerRGBClass"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Blue Channel color value."; + }; + }; + new GuiControl() { + position = "71 0"; + extent = "61 75"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "H"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "5 6"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Hue Channel color value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_H_Val) { // Hue Channal + text = "0"; + maxLength = "4"; + position = "14 6"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + class = "ColorPickerHSBClass"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Hue Channel color value."; + }; + new GuiTextCtrl() { + text = "o"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "51 2"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "S"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "4 29"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Saturation Channel color value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_S_Val) { // Saturation Channal + text = "0"; + maxLength = "4"; + position = "14 29"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + class = "ColorPickerHSBClass"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Saturation Channel color value."; + }; + new GuiTextCtrl() { + text = "%"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "51 29"; + extent = "10 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "B"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "5 52"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Brightness Channel color value. Aka value or lightness."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_Br_Val) { // Brightness Channal + text = "0"; + maxLength = "4"; + position = "14 52"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + class = "ColorPickerHSBClass"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Brightness Channel color value. Aka value or lightness."; + }; + new GuiTextCtrl() { + text = "%"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "51 52"; + extent = "10 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiControl() { + position = "3 87"; + extent = "138 24"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "#"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "3 5"; + extent = "8 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Hex representation of Red, Green, Blue Color value."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(HexColor_Val) { // Hex Color Field + text = "0"; + maxLength = "6"; + position = "13 5"; + extent = "116 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Hex representation of Red, Green, Blue Color value."; + command = "$thisControl.onKeyDown();"; + }; + }; + }; + new GuiBitmapBorderCtrl(){ // alpha + position = "3 287"; + extent = "429 24"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiGroupBorderProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiControl() { + position = "-1 3"; + extent = "428 18"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + class = "AggregateControl"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiSliderCtrl(ColorAlphaSelect) { + range = "0 1"; + ticks = "0"; + value = "1"; + position = "5 3"; + extent = "341 13"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiSliderProfile"; + visible = "1"; + active = "1"; + altCommand = "$ThisControl.getParent().updateFromChild($ThisControl); updateColorPickerAlpha( $ThisControl.getValue() );"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "slider"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Alpha"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "355 0"; + extent = "28 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl(Channel_A_Val) { // Alpha Channal + text = "0"; + maxLength = "4"; + position = "392 0"; + extent = "34 18"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfileNumbersOnly"; + altCommand = "$ThisControl.getParent().updateFromChild($ThisControl); updateColorPickerAlpha( $ThisControl.getValue() );"; + internalName = "TextEdit"; + }; + }; }; new GuiButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiButtonProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "144 316"; - Extent = "115 24"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "DoColorPickerCallback();"; - hovertime = "1000"; text = "Select"; groupNum = "-1"; buttonType = "PushButton"; useMouseEvents = "0"; + position = "349 37"; + extent = "84 24"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiButtonProfile"; + visible = "1"; + active = "1"; + command = "DoColorPickerCallback();"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; }; new GuiButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiButtonProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "268 316"; - Extent = "73 24"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "DoColorPickerCancelCallback();"; - hovertime = "1000"; text = "Cancel"; groupNum = "-1"; buttonType = "PushButton"; useMouseEvents = "0"; + position = "349 68"; + extent = "84 24"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiButtonProfile"; + visible = "1"; + active = "1"; + command = "DoColorPickerCancelCallback();"; + Clickable = "1"; + AffectChildren = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; }; }; }; @@ -294,26 +727,6 @@ $ColorPickerCancelCallback = ""; $ColorPickerUpdateCallback = ""; $ColorCallbackType = 1; // ColorI -function ColorFloatToInt( %color ) -{ - %red = getWord( %color, 0 ); - %green = getWord( %color, 1 ); - %blue = getWord( %color, 2 ); - %alpha = getWord( %color, 3 ); - - return mCeil( %red * 255 ) SPC mCeil( %green * 255 ) SPC mCeil( %blue * 255 ) SPC mCeil( %alpha * 255 ); -} - -function ColorIntToFloat( %color ) -{ - %red = getWord( %color, 0 ); - %green = getWord( %color, 1 ); - %blue = getWord( %color, 2 ); - %alpha = getWord( %color, 3 ); - - return ( %red / 255 ) SPC ( %green / 255 ) SPC ( %blue / 255 ) SPC ( %alpha / 255 ); -} - // This function pushes the color picker dialog and returns to a callback the selected value function GetColorI( %currentColor, %callback, %root, %updateCallback, %cancelCallback ) { @@ -333,15 +746,18 @@ function GetColorI( %currentColor, %callback, %root, %updateCallback, %cancelCal ColorAlphaSelect.range = "0 255"; // Set the RGBA displays accordingly - %red = getWord(%currentColor, 0) / 255; - %green = getWord(%currentColor, 1) / 255; - %blue = getWord(%currentColor, 2) / 255; + %red = getWord(%currentColor, 0); + %green = getWord(%currentColor, 1); + %blue = getWord(%currentColor, 2); %alpha = getWord(%currentColor, 3); - // set the initial range blend to correct color, no alpha needed - // this should also set the color blend select right now - ColorRangeSelect.baseColor = %red SPC %green SPC %blue SPC "1.0"; - ColorRangeSelect.updateColor(); + //Set the red green blue text fields + Channel_R_Val.setValue(%red); + Channel_G_Val.setValue(%green); + Channel_B_Val.setValue(%blue); + + //Have the rgb text fields update the rest + Channel_R_Val.onValidate(); if(!isObject(%root)) %root = Canvas; @@ -371,15 +787,18 @@ function GetColorF( %currentColor, %callback, %root, %updateCallback, %cancelCal ColorAlphaSelect.range = "0 1"; // Set the RGBA displays accordingly - %red = getWord(%currentColor, 0); - %green = getWord(%currentColor, 1); - %blue = getWord(%currentColor, 2); - %alpha = getWord(%currentColor, 3); + %red = mRoundColour(getWord(%currentColor, 0), 3); + %green = mRoundColour(getWord(%currentColor, 1), 3); + %blue = mRoundColour(getWord(%currentColor, 2), 3); + %alpha = mRoundColour(getWord(%currentColor, 3), 3); - // set the initial range blend to correct color, no alpha needed - // this should also set the color blend select right now - ColorRangeSelect.baseColor = %red SPC %green SPC %blue SPC "1.0"; - ColorRangeSelect.updateColor(); + //Set the red green blue text fields + Channel_R_Val.setValue(%red); + Channel_G_Val.setValue(%green); + Channel_B_Val.setValue(%blue); + + //Have the rgb text fields update the rest + Channel_R_Val.onValidate(); if(!isObject(%root)) %root = Canvas; @@ -390,6 +809,133 @@ function GetColorF( %currentColor, %callback, %root, %updateCallback, %cancelCal Channel_A_Val.setText( %alpha ); } +function ColorPickerRGBClass::onValidate(%this) +{ + %red = Channel_R_Val.getValue(); + %green = Channel_G_Val.getValue(); + %blue = Channel_B_Val.getValue(); + + //Rest of the fields just do everything with ints so convert + if( $ColorCallbackType != 1 ) + { + %rgb = ColorFloatToInt(%red SPC %green SPC %blue SPC "1.0"); + %red = getWord(%rgb, 0); + %green = getWord(%rgb, 1); + %blue = getWord(%rgb, 2); + } + + //Update all the other color fields + %hsb = ColorRGBToHSB(%red SPC %green SPC %blue); + Channel_H_Val.setValue(getWord(%hsb, 0)); + Channel_S_Val.setValue(getWord(%hsb, 1)); + Channel_Br_Val.setValue(getWord(%hsb, 2)); + + %hex = ColorRGBToHEX(%red SPC %green SPC %blue); + HexColor_Val.setValue(%hex); + HexColor_Val.onKeyDown(); + + //Update everything else with our new color + setColorInfo(); +} + +function ColorPickerHSBClass::onValidate(%this) +{ + %hue = Channel_H_Val.getValue(); + %saturation = Channel_S_Val.getValue(); + %brightness = Channel_Br_Val.getValue(); + + //Update all the other color fields + %rgb = ColorHSBToRGB(%hue SPC %saturation SPC %brightness); + %hex = ColorRGBToHEX(%rgb); + HexColor_Val.setValue(%hex); + HexColor_Val.onKeyDown(); + + //convert to float for rgb if we need to + if( $ColorCallbackType != 1 ) + { + %rgb = ColorIntToFloat(%rgb); + } + %red = getWord(%rgb, 0); + %green = getWord(%rgb, 1); + %blue = getWord(%rgb, 2); + Channel_R_Val.setValue(%red); + Channel_G_Val.setValue(%green); + Channel_B_Val.setValue(%blue); + + //Update everything else with our new color + setColorInfo(); +} + +function HexColor_Val::onKeyDown(%this) +{ + //Get the value + %value = %this.getValue(); + + //It's hex so keep it all uppercase + %value = strupr(%value); + %pos = %this.getCursorPos(); + %this.setValue(%value); + %this.setCursorPos(%pos); + + //Verify that it's a hex value + %value = stripChars(%value, "0123456789ABCDEF"); + if(%value $= "") + { + %this.validText(); + } + else + { + %this.invalidText(false); + } +} + +function HexColor_Val::onValidate(%this) +{ + //if the current text is invalid don't do anyting + if(!%this.isValidText()) + { + %this.invalidText(true); + return; + } + + //Get the current value + %hex = %this.getValue(); + + //Make sure we have 6 characters + while(strlen(%hex) < 6) + { + %hex = "0" @ %hex; + } + %hex = strupr(%hex); + + //Update the value in case there were missing characters + %this.setValue(%hex); + + //Update all the other color fields + %rgb = ColorHEXToRGB(%hex); + %hsb = ColorRGBToHSB(%rgb); + + //convert to float for rgb if we need to + if( $ColorCallbackType != 1 ) + { + %rgb = ColorIntToFloat(%rgb); + } + + %red = getWord(%rgb, 0); + %green = getWord(%rgb, 1); + %blue = getWord(%rgb, 2); + Channel_R_Val.setValue(%red); + Channel_G_Val.setValue(%green); + Channel_B_Val.setValue(%blue); + + Channel_H_Val.setValue(getWord(%hsb, 0)); + Channel_S_Val.setValue(getWord(%hsb, 1)); + Channel_Br_Val.setValue(getWord(%hsb, 2)); + + //Update everything else with our new color + setColorInfo(); +} + // This function is used to update the text controls at the top function setColorInfo() { @@ -398,16 +944,40 @@ function setColorInfo() %blue = Channel_B_Val.getValue(); if( $ColorCallbackType == 1) - { - %red = (%red / 255); - %green = (%green / 255); - %blue = (%blue / 255); - } + %rgb = ColorIntToFloat(%red SPC %green SPC %blue SPC "255"); + else + %rgb = %red SPC %green SPC %blue SPC "1.0"; - $ColorPickerSignal = 1; + $ColorPickerSignal = 0; - ColorBlendSelect.baseColor = %red SPC %green SPC %blue SPC "1.0"; + //Convert color over to hue color + %hsb = ColorRGBToHSB(ColorFloatToInt(%rgb)); + %tempColor = ColorHSBToRGB( getWord(%hsb, 0) SPC 100 SPC 50); + %tempColor = ColorIntToFloat(setWord(%tempColor, 3, 255)); + + //Make sure all the text fields and everything don't update because of the cursors + ColorRangeSelect.update = false; + ColorBlendSelect.update = false; + + //Set values for the hue color picker + ColorRangeSelect.baseColor = %tempColor; + ColorRangeSelect.pickColor = %tempColor; + ColorRangeSelect.updateColor(); + + //Set the cursor for the hue picker + ColorRangeSelect.setSelectorColor(%tempColor); + + //Set the values for the gradient color picker + ColorBlendSelect.baseColor = %tempColor; + ColorBlendSelect.pickColor = %rgb; ColorBlendSelect.updateColor(); + + //Set the cursor for the gradiant color picker + ColorBlendSelect.setSelectorColor(%rgb); + + //Update our current color + %alpha = getWord(myColor.color, 3); + myColor.color = setWord(%rgb, 3, %alpha); } // return mycolor.color @@ -433,11 +1003,17 @@ function DoColorPickerUpdateCallback() // this is called from ColorRangeSelect.updateColor function updatePickerBaseColor( %location ) { + if(!ColorRangeSelect.update) + { + ColorRangeSelect.update = true; + return; + } + if( $ColorPickerSignal && %location ) %pickColor = ColorRangeSelect.baseColor; else %pickColor = ColorRangeSelect.pickColor; - $ColorPickerSignal = 1; + $ColorPickerSignal = 0; %red = getWord(%pickColor, 0); %green = getWord(%pickColor, 1); @@ -451,6 +1027,12 @@ function updatePickerBaseColor( %location ) // this is called from ColorBlendSelect.updateColor function updateRGBValues( %location ) { + if(!ColorBlendSelect.update) + { + ColorBlendSelect.update = true; + return; + } + //update the color based on where it came from if( $ColorPickerSignal && %location ) %pickColor = ColorBlendSelect.baseColor; @@ -465,7 +1047,7 @@ function updateRGBValues( %location ) %alpha = getWord(myColor.color, 3); // set the color! - myColor.color = %red SPC %green SPC %blue SPC %alpha ; + myColor.color = %red SPC %green SPC %blue SPC %alpha; DoColorPickerUpdateCallback(); @@ -488,6 +1070,25 @@ function updateRGBValues( %location ) Channel_G_Val.setValue(%green); Channel_B_Val.setValue(%blue); + //Rest of the fields just do everything with ints so convert + if( $ColorCallbackType != 1 ) + { + %rgb = ColorFloatToInt(%red SPC %green SPC %blue SPC "1.0"); + %red = getWord(%rgb, 0); + %green = getWord(%rgb, 1); + %blue = getWord(%rgb, 2); + } + + //Update all the other color fields + %hsb = ColorRGBToHSB(%red SPC %green SPC %blue); + Channel_H_Val.setValue(getWord(%hsb, 0)); + Channel_S_Val.setValue(getWord(%hsb, 1)); + Channel_Br_Val.setValue(getWord(%hsb, 2)); + + %hex = ColorRGBToHEX(%red SPC %green SPC %blue); + HexColor_Val.setValue(%hex); + HexColor_Val.onKeyDown(); + $ColorPickerSignal = 0; } diff --git a/Templates/Full/game/tools/gui/openFileDialog.ed.cs b/Templates/Full/game/tools/gui/openFileDialog.ed.cs index b988d3361..50c7cdfcc 100644 --- a/Templates/Full/game/tools/gui/openFileDialog.ed.cs +++ b/Templates/Full/game/tools/gui/openFileDialog.ed.cs @@ -20,27 +20,38 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -function getLoadFilename(%filespec, %callback, %currentFile) -{ +function getLoadFilename(%filespec, %callback, %currentFile, %getRelative, %defaultPath) +{ + //If no default path passed in then try to get one from the file + if(%defaultPath $= "") + { + if ( filePath( %currentFile ) !$= "" ) + %defaultPath = filePath(%currentFile); + } + %dlg = new OpenFileDialog() { Filters = %filespec; DefaultFile = %currentFile; + DefaultPath = %defaultPath; ChangePath = false; MustExist = true; MultipleFiles = false; }; - if ( filePath( %currentFile ) !$= "" ) - %dlg.DefaultPath = filePath(%currentFile); - - if ( %dlg.Execute() ) + %ok = %dlg.Execute(); + if ( %ok ) { - eval(%callback @ "(\"" @ %dlg.FileName @ "\");"); + %file = %dlg.FileName; + if(%getRelative) + %file = strreplace(%file,getWorkingDirectory() @ "/", ""); + eval(%callback @ "(\"" @ %file @ "\");"); $Tools::FileDialogs::LastFilePath = filePath( %dlg.FileName ); } %dlg.delete(); + + return %ok; } // Opens a choose file dialog with format filters already loaded diff --git a/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui b/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui index 2062f43f3..63ce28e2a 100644 --- a/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui +++ b/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui @@ -1354,132 +1354,6 @@ bitmap = "tools/gui/images/delete"; }; }; - new GuiBitmapCtrl(){ - position="6 357"; - extent ="175 2"; - HorizSizing = "width"; - bitmap ="tools/gui/images/separator-v"; - }; - new GuiContainer(){ // Environment Map - profile="ToolsGuiDefaultProfile"; - isContainer = "1"; - position = "6 359"; - Extent = "185 52"; - HorizSizing = "width"; - - new GuiBitmapCtrl() { - canSaveDynamicFields = "0"; - internalName = "envMapDisplayBitmap"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "1 1"; - Extent = "48 48"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; - bitmap = "tools/materialeditor/gui/unknownImage"; - wrap = "0"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - Enabled = "1"; - isContainer = "0"; - Profile = "EditorTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "56 -3"; - Extent = "72 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "Env Map"; - maxLength = "1024"; - }; - new GuiBitmapButtonCtrl() { - canSaveDynamicFields = "0"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "1 1"; - Extent = "48 48"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "MaterialEditorGui.updateTextureMap(\"env\", 1);"; - tooltipprofile = "ToolsGuiDefaultProfile"; - ToolTip = "Change the active Environment Map for this layer."; - hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - bitmap = "tools/materialEditor/gui/cubemapBtnBorder"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - internalName = "envMapNameText"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "width"; - VertSizing = "bottom"; - position = "56 16"; - Extent = "143 17"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "None"; - maxLength = "1024"; - }; - new GuiButtonCtrl(){ - profile="ToolsGuiButtonProfile"; - text ="Edit"; - HorizSizing = "left"; - VertSizing = "bottom"; - position = "134 34"; - Extent = "40 16"; - buttonType = "PushButton"; - command="MaterialEditorGui.updateTextureMap(\"env\", 1);"; - }; - new GuiBitmapButtonCtrl() { - canSaveDynamicFields = "0"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "left"; - VertSizing = "bottom"; - position = "177 34"; - Extent = "16 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "MaterialEditorGui.updateTextureMap(\"env\", 0);"; - hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - bitmap = "tools/gui/images/delete"; - }; - }; }; }; new GuiRolloutCtrl() { @@ -1491,6 +1365,7 @@ Position = "0 0"; Extent = "195 0"; Caption = "Accumulation Properties"; + Expanded = false; Margin = "-1 0 0 0"; DragSizable = false; container = true; @@ -1967,6 +1842,7 @@ Position = "0 0"; Extent = "185 0"; Caption = "Lighting Properties"; + Expanded = false; Margin = "-1 0 0 0"; DragSizable = false; container = true; @@ -2364,101 +2240,6 @@ useMouseEvents = "0"; useInactiveState = "0"; }; - new GuiCheckBoxCtrl() { - canSaveDynamicFields = "0"; - internalName = "subSurfaceCheckbox"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiCheckBoxProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "8 46"; - Extent = "79 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "MaterialEditorGui.updateActiveMaterial(\"subSurface[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());"; - tooltipprofile = "ToolsGuiDefaultProfile"; - ToolTip = "Enables the use of subsurface scattering for this layer."; - hovertime = "1000"; - text = "Sub Surface"; - groupNum = "-1"; - buttonType = "ToggleButton"; - useMouseEvents = "0"; - useInactiveState = "0"; - }; - new GuiSwatchButtonCtrl() { - canSaveDynamicFields = "0"; - internalName = "subSurfaceColorSwatch"; - Enabled = "1"; - isContainer = "0"; - Profile = "GuiInspectorSwatchButtonProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "90 46"; - Extent = "16 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "getColorF(materialEd_PreviewMaterial.subSurfaceColor[MaterialEditorGui.currentLayer], \"MaterialEditorGui.updateSubSurfaceColor\");"; - tooltip = "Set the subsurface scattering color"; - hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - }; - new GuiTextEditCtrl() { - canSaveDynamicFields = "0"; - internalName = "subSurfaceRolloffTextEdit"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "114 45"; - Extent = "29 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltip = "Set the subsurface rolloff factor"; - Command = "MaterialEditorGui.updateActiveMaterial(\"subSurfaceRolloff[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getText());"; - hovertime = "1000"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "32"; - maxLength = "5"; - }; - new GuiTextCtrl() { - HorizSizing = "right"; - VertSizing = "bottom"; - position = "9 65"; - Extent = "89 16"; - text = "Minnaert constant"; - }; - new GuiTextEditCtrl() { - canSaveDynamicFields = "0"; - internalName = "minnaertTextEdit"; - Enabled = "1"; - isContainer = "0"; - Profile = "ToolsGuiTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "114 65"; - Extent = "29 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "MaterialEditorGui.updateActiveMaterial(\"minnaertConstant[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getText());"; - hovertime = "1000"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "32"; - maxLength = "3"; - }; }; }; }; @@ -2471,9 +2252,9 @@ Position = "0 0"; Extent = "185 0"; Caption = "Animation Properties"; + Expanded = false; Margin = "-1 0 0 0"; DragSizable = false; - Expanded = false; container = true; parentRollout = %this.rollout; object = %behavior; @@ -3283,6 +3064,7 @@ Position = "0 0"; Extent = "202 0"; Caption = "Advanced (all layers)"; + Expanded = false; Margin = "4 4 4 0"; DragSizable = false; container = true; @@ -3519,7 +3301,7 @@ Profile = "ToolsGuiCheckBoxProfile"; HorizSizing = "right"; VertSizing = "bottom"; - position = "100 56"; + position = "105 55"; Extent = "85 16"; MinExtent = "8 2"; canSave = "1"; diff --git a/Templates/Full/game/tools/worldEditor/gui/objectBuilderGui.ed.gui b/Templates/Full/game/tools/worldEditor/gui/objectBuilderGui.ed.gui index ddf2ef68a..74f1200c6 100644 --- a/Templates/Full/game/tools/worldEditor/gui/objectBuilderGui.ed.gui +++ b/Templates/Full/game/tools/worldEditor/gui/objectBuilderGui.ed.gui @@ -980,7 +980,19 @@ function ObjectBuilderGui::buildObserverDropPoint(%this) //------------------------------------------------------------------------------ // System //------------------------------------------------------------------------------ - +function ObjectBuilderGui::buildVolumetricFog(%this) +{ + // Change this if you want to default to another Folder + // Otherwise every time you want to add a Fog you will go this. + %defShape = "/art/environment/Fog_Cube.dts"; + %this.lastPath=getMainDotCsDir() @ %defShape; + OBObjectName.setValue( "" ); + %this.objectClassName = "VolumetricFog"; + %this.addField( "shapeName", "TypeFile", "Shape (Fog volume)", "", "*.dts;*.dae"); + %this.addField("Scale", "TypePoint3", "Scale", "1 1 1"); + %this.addField("FogColor", "TypeColorI", "FogColor", "200 200 200 255"); + %this.process(); +} function ObjectBuilderGui::buildPhysicsEntity(%this) { %this.objectClassName = "PhysicsEntity"; diff --git a/Templates/Full/game/tools/worldEditor/main.cs b/Templates/Full/game/tools/worldEditor/main.cs index a6ecb2872..59301ea53 100644 --- a/Templates/Full/game/tools/worldEditor/main.cs +++ b/Templates/Full/game/tools/worldEditor/main.cs @@ -120,6 +120,9 @@ function initializeWorldEditor() EVisibility.addOption( "AL: Light Specular Viz", "$AL_LightSpecularVisualizeVar", "toggleLightSpecularViz" ); EVisibility.addOption( "AL: Normals Viz", "$AL_NormalsVisualizeVar", "toggleNormalsViz" ); EVisibility.addOption( "AL: Depth Viz", "$AL_DepthVisualizeVar", "toggleDepthViz" ); + EVisibility.addOption( "AL: Color Buffer", "$AL_ColorBufferShaderVar", "toggleColorBufferViz" ); + EVisibility.addOption( "AL: Spec Map", "$AL_SpecMapShaderVar", "toggleSpecMapViz"); + EVisibility.addOption( "AL: Backbuffer", "$AL_BackbufferVisualizeVar", "toggleBackbufferViz" ); EVisibility.addOption( "AL: Glow Buffer", "$AL_GlowVisualizeVar", "toggleGlowViz" ); EVisibility.addOption( "AL: PSSM Cascade Viz", "$AL::PSSMDebugRender", "" ); EVisibility.addOption( "Frustum Lock", "$Scene::lockCull", "" ); diff --git a/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs index 9bc2cab15..6832410dd 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs @@ -46,6 +46,7 @@ function EWCreatorWindow::init( %this ) %this.registerMissionObject( "SFXEmitter", "Sound Emitter" ); %this.registerMissionObject( "Precipitation" ); %this.registerMissionObject( "ParticleEmitterNode", "Particle Emitter" ); + %this.registerMissionObject( "VolumetricFog", "Volumetric Fog" ); %this.registerMissionObject( "RibbonNode", "Ribbon" ); // Legacy features. Users should use Ground Cover and the Forest Editor.