mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 20:54:46 +00:00
while that certainly works for most cases it falls apart when dealing with postfx where it's an unnamed array of variable types of inputs. shifted the profile assignment to #define INIT_IMAGEASSET_ARRAY(name, profile, index) so there's still a really obvious point where you can see the default setting, even if it's not in the more desireable OG definition spot for postfx in particular, given we can swap that, provided an example of how to do just that
416 lines
12 KiB
C++
416 lines
12 KiB
C++
//-----------------------------------------------------------------------------
|
|
// 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 "platform/profiler.h"
|
|
#include "console/consoleTypes.h"
|
|
#include "basicClouds.h"
|
|
|
|
#include "gfx/gfxTransformSaver.h"
|
|
#include "gfx/gfxTextureManager.h"
|
|
#include "core/stream/fileStream.h"
|
|
#include "core/stream/bitStream.h"
|
|
#include "scene/sceneRenderState.h"
|
|
#include "renderInstance/renderPassManager.h"
|
|
#include "materials/shaderData.h"
|
|
#include "math/mathIO.h"
|
|
|
|
|
|
ConsoleDocClass( BasicClouds,
|
|
"@brief Renders up to three layers of scrolling cloud-cover textures overhead.\n\n"
|
|
|
|
"%BasicClouds always renders overhead, following the camera. It is intended "
|
|
"as part of the background of your level, rendering in front of Sky/Sun "
|
|
"type objects and behind everything else.\n\n"
|
|
|
|
"The parameters controlling the rendering of each texture are refered to "
|
|
"and grouped as 'layers'. They are rendered in sequential order, so, layer 1 "
|
|
"obscures layer 0, and so on.\n\n"
|
|
|
|
"BasicClouds is not affected by scene lighting and is therefore not appropriate "
|
|
"for scenes in which lighting radically changes, such as day/night.\n\n"
|
|
|
|
"@ingroup Atmosphere"
|
|
);
|
|
|
|
|
|
U32 BasicClouds::smVertStride = 50;
|
|
U32 BasicClouds::smStrideMinusOne = 49;
|
|
U32 BasicClouds::smVertCount = 50 * 50;
|
|
U32 BasicClouds::smTriangleCount = smStrideMinusOne * smStrideMinusOne * 2;
|
|
|
|
BasicClouds::BasicClouds()
|
|
{
|
|
mTypeMask |= EnvironmentObjectType | StaticObjectType;
|
|
mNetFlags.set(Ghostable | ScopeAlways);
|
|
|
|
mTimeSC = NULL;
|
|
mModelViewProjSC = NULL;
|
|
mTexScaleSC = NULL;
|
|
mTexDirectionSC = NULL;
|
|
mTexOffsetSC = NULL;
|
|
mDiffuseMapSC = NULL;
|
|
|
|
mLayerEnabled[0] = true;
|
|
mLayerEnabled[1] = true;
|
|
mLayerEnabled[2] = true;
|
|
|
|
// Default textures are assigned by the ObjectBuilderGui.
|
|
//mTexName[0] = "art/skies/clouds/cloud1";
|
|
//mTexName[1] = "art/skies/clouds/cloud2";
|
|
//mTexName[2] = "art/skies/clouds/cloud3";
|
|
|
|
mHeight[0] = 4.0f;
|
|
mHeight[1] = 3.0f;
|
|
mHeight[2] = 2.0f;
|
|
|
|
mTexSpeed[0] = 0.0005f;
|
|
mTexSpeed[1] = 0.001f;
|
|
mTexSpeed[2] = 0.0003f;
|
|
|
|
mTexScale[0] = 1.0;
|
|
mTexScale[1] = 1.0;
|
|
mTexScale[2] = 1.0;
|
|
|
|
mTexDirection[0].set( 1.0f, 0.0f );
|
|
mTexDirection[1].set( 1.0f, 0.0f );
|
|
mTexDirection[2].set( 1.0f, 0.0f );
|
|
|
|
mTexOffset[0].set( 0.5f, 0.5f );
|
|
mTexOffset[1].set( 0.5f, 0.5f );
|
|
mTexOffset[2].set( 0.5f, 0.5f );
|
|
|
|
for (U32 i=0; i< TEX_COUNT;i++)
|
|
INIT_IMAGEASSET_ARRAY(Texture, GFXStaticTextureSRGBProfile, i);
|
|
}
|
|
|
|
IMPLEMENT_CO_NETOBJECT_V1( BasicClouds );
|
|
|
|
// ConsoleObject...
|
|
|
|
|
|
bool BasicClouds::onAdd()
|
|
{
|
|
if ( !Parent::onAdd() )
|
|
return false;
|
|
|
|
setGlobalBounds();
|
|
resetWorldBox();
|
|
|
|
addToScene();
|
|
|
|
if ( isClientObject() )
|
|
{
|
|
_initTexture();
|
|
_initBuffers();
|
|
|
|
// Find ShaderData
|
|
ShaderData *shaderData;
|
|
mShader = Sim::findObject( "BasicCloudsShader", shaderData ) ? shaderData->getShader() : NULL;
|
|
if ( !mShader )
|
|
{
|
|
Con::errorf( "BasicClouds::onAdd - could not find BasicCloudsShader" );
|
|
return false;
|
|
}
|
|
|
|
// Create ShaderConstBuffer and Handles
|
|
mShaderConsts = mShader->allocConstBuffer();
|
|
mModelViewProjSC = mShader->getShaderConstHandle( "$modelView" );
|
|
mTimeSC = mShader->getShaderConstHandle( "$accumTime" );
|
|
mTexScaleSC = mShader->getShaderConstHandle( "$texScale" );
|
|
mTexDirectionSC = mShader->getShaderConstHandle( "$texDirection" );
|
|
mTexOffsetSC = mShader->getShaderConstHandle( "$texOffset" );
|
|
mDiffuseMapSC = mShader->getShaderConstHandle( "$diffuseMap" );
|
|
|
|
// Create StateBlocks
|
|
GFXStateBlockDesc desc;
|
|
desc.setCullMode( GFXCullNone );
|
|
desc.setBlend( true );
|
|
desc.setZReadWrite( true, 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;
|
|
|
|
mStateblock = GFX->createStateBlock( desc );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void BasicClouds::onRemove()
|
|
{
|
|
removeFromScene();
|
|
|
|
Parent::onRemove();
|
|
}
|
|
|
|
void BasicClouds::initPersistFields()
|
|
{
|
|
addGroup( "BasicClouds" );
|
|
|
|
addArray( "Layers", TEX_COUNT );
|
|
|
|
addField( "layerEnabled", TypeBool, Offset( mLayerEnabled, BasicClouds ), TEX_COUNT,
|
|
"Enable or disable rendering of this layer." );
|
|
|
|
INITPERSISTFIELD_IMAGEASSET_ARRAY(Texture, TEX_COUNT, BasicClouds, "Texture for this layer.");
|
|
|
|
addField( "texScale", TypeF32, Offset( mTexScale, BasicClouds ), TEX_COUNT,
|
|
"Texture repeat for this layer." );
|
|
|
|
addField( "texDirection", TypePoint2F, Offset( mTexDirection, BasicClouds ), TEX_COUNT,
|
|
"Texture scroll direction for this layer, relative to the world axis." );
|
|
|
|
addField( "texSpeed", TypeF32, Offset( mTexSpeed, BasicClouds ), TEX_COUNT,
|
|
"Texture scroll speed for this layer." );
|
|
|
|
addField( "texOffset", TypePoint2F, Offset( mTexOffset, BasicClouds ), TEX_COUNT,
|
|
"UV offset for this layer." );
|
|
|
|
addField( "height", TypeF32, Offset( mHeight, BasicClouds ), TEX_COUNT,
|
|
"Abstract number which controls the curvature and height of the dome mesh" );
|
|
|
|
endArray( "Layers" );
|
|
|
|
endGroup( "BasicClouds" );
|
|
|
|
Parent::initPersistFields();
|
|
}
|
|
|
|
void BasicClouds::inspectPostApply()
|
|
{
|
|
Parent::inspectPostApply();
|
|
setMaskBits( BasicCloudsMask );
|
|
}
|
|
|
|
|
|
// NetObject...
|
|
|
|
|
|
U32 BasicClouds::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
|
|
{
|
|
U32 retMask = Parent::packUpdate( conn, mask, stream );
|
|
|
|
for ( U32 i = 0; i < TEX_COUNT; i++ )
|
|
{
|
|
stream->writeFlag( mLayerEnabled[i] );
|
|
|
|
PACK_ASSET_ARRAY(conn, Texture, i);
|
|
|
|
stream->write( mTexScale[i] );
|
|
mathWrite( *stream, mTexDirection[i] );
|
|
stream->write( mTexSpeed[i] );
|
|
mathWrite( *stream, mTexOffset[i] );
|
|
|
|
stream->write( mHeight[i] );
|
|
}
|
|
|
|
return retMask;
|
|
}
|
|
|
|
void BasicClouds::unpackUpdate( NetConnection *conn, BitStream *stream )
|
|
{
|
|
Parent::unpackUpdate( conn, stream );
|
|
|
|
for ( U32 i = 0; i < TEX_COUNT; i++ )
|
|
{
|
|
mLayerEnabled[i] = stream->readFlag();
|
|
|
|
UNPACK_ASSET_ARRAY(conn, Texture, i);
|
|
|
|
stream->read( &mTexScale[i] );
|
|
mathRead( *stream, &mTexDirection[i] );
|
|
stream->read( &mTexSpeed[i] );
|
|
mathRead( *stream, &mTexOffset[i] );
|
|
|
|
stream->read( &mHeight[i] );
|
|
}
|
|
|
|
if ( isProperlyAdded() )
|
|
{
|
|
// We could check if the height or texture have actually changed.
|
|
_initBuffers();
|
|
_initTexture();
|
|
}
|
|
}
|
|
|
|
|
|
// SceneObject...
|
|
|
|
|
|
void BasicClouds::prepRenderImage( SceneRenderState *state )
|
|
{
|
|
PROFILE_SCOPE( BasicClouds_prepRenderImage );
|
|
|
|
bool isEnabled = false;
|
|
for ( U32 i = 0; i < TEX_COUNT; i++ )
|
|
{
|
|
if ( mLayerEnabled[i] )
|
|
{
|
|
isEnabled = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !isEnabled )
|
|
return;
|
|
|
|
// This should be sufficient for most objects that don't manage zones, and
|
|
// don't need to return a specialized RenderImage...
|
|
ObjectRenderInst *ri = state->getRenderPass()->allocInst< ObjectRenderInst >();
|
|
ri->renderDelegate.bind( this, &BasicClouds::renderObject );
|
|
ri->type = RenderPassManager::RIT_Sky;
|
|
ri->defaultKey = 0;
|
|
ri->defaultKey2 = 0;
|
|
state->getRenderPass()->addInst( ri );
|
|
}
|
|
|
|
void BasicClouds::renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *mi )
|
|
{
|
|
GFXTransformSaver saver;
|
|
|
|
Point3F camPos = state->getCameraPosition();
|
|
MatrixF xfm(true);
|
|
xfm.setPosition(camPos);
|
|
GFX->multWorld(xfm);
|
|
|
|
if ( state->isReflectPass() )
|
|
GFX->setProjectionMatrix( state->getSceneManager()->getNonClipProjection() );
|
|
|
|
GFX->setShader( mShader );
|
|
GFX->setShaderConstBuffer( mShaderConsts );
|
|
GFX->setStateBlock( mStateblock );
|
|
|
|
MatrixF xform(GFX->getProjectionMatrix());
|
|
xform *= GFX->getViewMatrix();
|
|
xform *= GFX->getWorldMatrix();
|
|
|
|
mShaderConsts->setSafe( mModelViewProjSC, xform );
|
|
mShaderConsts->setSafe( mTimeSC, (F32)Sim::getCurrentTime() / 1000.0f );
|
|
GFX->setPrimitiveBuffer( mPB );
|
|
|
|
for ( U32 i = 0; i < TEX_COUNT; i++ )
|
|
{
|
|
if ( !mLayerEnabled[i] )
|
|
continue;
|
|
|
|
mShaderConsts->setSafe( mTexScaleSC, mTexScale[i] );
|
|
mShaderConsts->setSafe( mTexDirectionSC, mTexDirection[i] * mTexSpeed[i] );
|
|
mShaderConsts->setSafe( mTexOffsetSC, mTexOffset[i] );
|
|
|
|
GFX->setTexture( mDiffuseMapSC->getSamplerRegister(), mTexture[i] );
|
|
GFX->setVertexBuffer( mVB[i] );
|
|
|
|
GFX->drawIndexedPrimitive( GFXTriangleList, 0, 0, smVertCount, 0, smTriangleCount );
|
|
}
|
|
}
|
|
|
|
|
|
// BasicClouds Internal Methods....
|
|
|
|
|
|
void BasicClouds::_initTexture()
|
|
{
|
|
for ( U32 i = 0; i < TEX_COUNT; i++ )
|
|
{
|
|
if ( !mLayerEnabled[i] )
|
|
{
|
|
mTexture[i] = NULL;
|
|
continue;
|
|
}
|
|
|
|
_setTexture(getTexture(i), i);
|
|
}
|
|
}
|
|
|
|
void BasicClouds::_initBuffers()
|
|
{
|
|
// Primitive Buffer... Is shared for all Layers.
|
|
|
|
mPB.set( GFX, smTriangleCount * 3, smTriangleCount, GFXBufferTypeStatic );
|
|
|
|
U16 *pIdx = NULL;
|
|
mPB.lock(&pIdx);
|
|
U32 curIdx = 0;
|
|
|
|
for ( U32 y = 0; y < smStrideMinusOne; y++ )
|
|
{
|
|
for ( U32 x = 0; x < smStrideMinusOne; x++ )
|
|
{
|
|
U32 offset = x + y * smVertStride;
|
|
|
|
pIdx[curIdx] = offset;
|
|
curIdx++;
|
|
pIdx[curIdx] = offset + 1;
|
|
curIdx++;
|
|
pIdx[curIdx] = offset + smVertStride + 1;
|
|
curIdx++;
|
|
|
|
pIdx[curIdx] = offset;
|
|
curIdx++;
|
|
pIdx[curIdx] = offset + smVertStride + 1;
|
|
curIdx++;
|
|
pIdx[curIdx] = offset + smVertStride;
|
|
curIdx++;
|
|
}
|
|
}
|
|
|
|
mPB.unlock();
|
|
|
|
// Vertex Buffer...
|
|
// Each layer has their own so they can be at different heights.
|
|
|
|
for ( U32 i = 0; i < TEX_COUNT; i++ )
|
|
{
|
|
Point3F vertScale( 16.0f, 16.0f, mHeight[i] );
|
|
F32 zOffset = -( mCos( mSqrt( 1.0f ) ) + 0.01f );
|
|
|
|
mVB[i].set( GFX, smVertCount, GFXBufferTypeStatic );
|
|
GFXVertexPT *pVert = mVB[i].lock();
|
|
|
|
for ( U32 y = 0; y < smVertStride; y++ )
|
|
{
|
|
F32 v = ( (F32)y / (F32)smStrideMinusOne - 0.5f ) * 2.0f;
|
|
|
|
for ( U32 x = 0; x < smVertStride; x++ )
|
|
{
|
|
F32 u = ( (F32)x / (F32)smStrideMinusOne - 0.5f ) * 2.0f;
|
|
|
|
F32 sx = u;
|
|
F32 sy = v;
|
|
F32 sz = mCos( mSqrt( sx*sx + sy*sy ) ) + zOffset;
|
|
|
|
pVert->point.set( sx, sy, sz );
|
|
pVert->point *= vertScale;
|
|
pVert->texCoord.set( u, v );
|
|
pVert++;
|
|
}
|
|
}
|
|
|
|
mVB[i].unlock();
|
|
}
|
|
}
|