267 lines
9.3 KiB
C++
267 lines
9.3 KiB
C++
#include "StdAfx.h"
|
|
#include "EtSnowEffect.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
|
|
#endif
|
|
|
|
CEtSnowEffect::CEtSnowEffect(void)
|
|
{
|
|
m_fSnowTimer = 0.f;
|
|
m_bUsePointSprite = false; // 포인트 스프라이트의 경우엔 볼륨텍스처를 사용한 텍스처 애니를 표현할 수 없어서 더 이상 안쓰기로 합니다.
|
|
m_nSnowCount = 1500;
|
|
m_nSnowTimeOut = 7000;
|
|
m_fSnowHeight = 1500.f;
|
|
m_isUp = false;
|
|
|
|
m_fSnowSize = 0.0f;
|
|
m_fSnowAniSpeed = 1.0f;
|
|
}
|
|
|
|
CEtSnowEffect::~CEtSnowEffect(void)
|
|
{
|
|
SAFE_DELETE_PVEC( m_MeshStreamList );
|
|
}
|
|
|
|
void CEtSnowEffect::Initialize( const char *pSnowTexture )
|
|
{
|
|
int i, j, nVertexCount;
|
|
EtVector3 *pvPosition, *pvNormal;
|
|
float *pPointSize;
|
|
|
|
nVertexCount = m_nSnowCount;
|
|
m_hTexture = LoadResource( pSnowTexture, RT_TEXTURE );
|
|
|
|
if( m_bUsePointSprite ) {
|
|
|
|
pvPosition = new EtVector3[ nVertexCount ];
|
|
pvNormal = new EtVector3[ nVertexCount ];
|
|
pPointSize = new float[ nVertexCount ];
|
|
|
|
EtTerrainHandle Terrain = CEtTerrainArea::GetItem( 0 );
|
|
int nCountX, nCountY;
|
|
Terrain->GetBlockCount(nCountX, nCountY);
|
|
for( j = 0; j < nCountX*nCountY; j++)
|
|
{
|
|
SAABox Box = *Terrain->GetBoundingBox( j );
|
|
for( i = 0; i < nVertexCount; i ++ )
|
|
{
|
|
pvPosition[ i ] = EtVector3( Box.Min.x + (Box.Max.x-Box.Min.x) * (rand() / (float)RAND_MAX),
|
|
0.f,
|
|
Box.Min.z + (Box.Max.z-Box.Min.z) * (rand() / (float)RAND_MAX));
|
|
if (m_isUp)
|
|
pvPosition[i].y = Terrain->GetLandHeight( pvPosition[i].x, pvPosition[i].z ) - 5.f;
|
|
else
|
|
pvPosition[i].y = Terrain->GetLandHeight( pvPosition[i].x, pvPosition[i].z ) + 5.f;
|
|
|
|
pvNormal[i].x = -1.0f + 2.0f * (rand() / (float)RAND_MAX);
|
|
pvNormal[i].y = 1.f;
|
|
pvNormal[i].z = -1.0f + 2.0f * (rand() / (float)RAND_MAX);
|
|
EtVec3Normalize( &pvNormal[i], &pvNormal[i] );
|
|
pvNormal[i] *= 1.0f + 0.3f * (rand() / (float)RAND_MAX);
|
|
|
|
pPointSize[i] = 8.f + 5.f * (rand() / (float)RAND_MAX);
|
|
}
|
|
CMemoryStream Stream;
|
|
CEtMeshStream *MeshStream = new CEtMeshStream;
|
|
|
|
Stream.Initialize( pvPosition, nVertexCount * sizeof( EtVector3 ) );
|
|
MeshStream->LoadVertexStream( &Stream, MST_POSITION, 0, nVertexCount );
|
|
Stream.Initialize( pvNormal, nVertexCount * sizeof( EtVector3 ) );
|
|
MeshStream->LoadVertexStream( &Stream, MST_NORMAL, 0, nVertexCount );
|
|
Stream.Initialize( pPointSize, nVertexCount * sizeof( float ) );
|
|
MeshStream->LoadVertexStream( &Stream, MST_PSIZE, 0, nVertexCount );
|
|
if( m_hTexture ) {
|
|
MeshStream->SetPointSpriteTexture( m_hTexture->GetTexturePtr() );
|
|
}
|
|
m_MeshStreamList.push_back( MeshStream );
|
|
}
|
|
delete [] pvPosition;
|
|
delete [] pvNormal;
|
|
delete [] pPointSize;
|
|
}
|
|
else {
|
|
|
|
pvPosition = new EtVector3[ nVertexCount * 4 ];
|
|
pvNormal = new EtVector3[ nVertexCount * 4 ];
|
|
EtVector2 *pTexCoord = new EtVector2[ nVertexCount * 4];
|
|
float *pRadomVector = new float[nVertexCount * 4]; //텍스쳐 애니 시작 랜덤값용
|
|
WORD *pwIndex = new WORD[ nVertexCount * 6];
|
|
|
|
EtTerrainHandle Terrain = CEtTerrainArea::GetItem( 0 );
|
|
int nCountX, nCountY;
|
|
Terrain->GetBlockCount(nCountX, nCountY);
|
|
for( j = 0; j < nCountX*nCountY; j++)
|
|
{
|
|
SAABox Box = *Terrain->GetBoundingBox( j );
|
|
for( i = 0; i < nVertexCount; i ++ )
|
|
{
|
|
pvPosition[ i*4 ] = EtVector3( Box.Min.x + (Box.Max.x-Box.Min.x) * (rand() % 4097 ) / 4097.f,
|
|
0.f,
|
|
Box.Min.z + (Box.Max.z-Box.Min.z) * (rand() % 4097 ) / 4097.f);
|
|
|
|
if (m_isUp)
|
|
pvPosition[i*4].y = Terrain->GetLandHeight( pvPosition[i*4].x, pvPosition[i*4].z ) - 5.f;
|
|
else
|
|
pvPosition[i*4].y = Terrain->GetLandHeight( pvPosition[i*4].x, pvPosition[i*4].z ) + 5.f;
|
|
|
|
pvNormal[i*4].x = -1.0f + 2.0f * (rand() % 255 ) / 255.f;
|
|
pvNormal[i*4].y = 1.f;
|
|
pvNormal[i*4].z = -1.0f + 2.0f * (rand() % 255 ) / 255.f;
|
|
EtVec3Normalize( &pvNormal[i*4], &pvNormal[i*4] );
|
|
|
|
pvPosition[ i*4+1 ] = pvPosition[ i*4];
|
|
pvPosition[ i*4+2 ] = pvPosition[ i*4];
|
|
pvPosition[ i*4+3 ] = pvPosition[ i*4];
|
|
|
|
pvNormal[ i*4+1 ] = pvNormal[ i*4];
|
|
pvNormal[ i*4+2 ] = pvNormal[ i*4];
|
|
pvNormal[ i*4+3 ] = pvNormal[ i*4];
|
|
|
|
pTexCoord[ i*4+0 ] = EtVector2(0, 1);
|
|
pTexCoord[ i*4+1 ] = EtVector2(0, 0);
|
|
pTexCoord[ i*4+2 ] = EtVector2(1, 1);
|
|
pTexCoord[ i*4+3 ] = EtVector2(1, 0);
|
|
|
|
float fRandom = ((float)(rand() % 100));// * 0.01f;
|
|
pRadomVector[ i*4+0 ] = fRandom;
|
|
pRadomVector[ i*4+1 ] = pRadomVector[ i*4+0 ];
|
|
pRadomVector[ i*4+2 ] = pRadomVector[ i*4+0 ];
|
|
pRadomVector[ i*4+3 ] = pRadomVector[ i*4+0 ];
|
|
|
|
pwIndex[ i*6+0 ] = i*4+0;
|
|
pwIndex[ i*6+1 ] = i*4+1;
|
|
pwIndex[ i*6+2 ] = i*4+2;
|
|
pwIndex[ i*6+3 ] = i*4+2;
|
|
pwIndex[ i*6+4 ] = i*4+1;
|
|
pwIndex[ i*6+5 ] = i*4+3;
|
|
|
|
}
|
|
CMemoryStream Stream;
|
|
CEtMeshStream *MeshStream = new CEtMeshStream;
|
|
|
|
Stream.Initialize( pvPosition, nVertexCount * 4 * sizeof( EtVector3 ) );
|
|
MeshStream->LoadVertexStream( &Stream, MST_POSITION, 0, nVertexCount*4 );
|
|
Stream.Initialize( pvNormal, nVertexCount * 4 * sizeof( EtVector3 ) );
|
|
MeshStream->LoadVertexStream( &Stream, MST_NORMAL, 0, nVertexCount*4 );
|
|
Stream.Initialize( pTexCoord, nVertexCount * 4 * sizeof( EtVector2 ) );
|
|
MeshStream->LoadVertexStream( &Stream, MST_TEXCOORD, 0, nVertexCount*4 );
|
|
|
|
Stream.Initialize( pRadomVector, nVertexCount * 4 * sizeof( float ) );
|
|
MeshStream->LoadVertexStream( &Stream, MST_PSIZE, 0, nVertexCount*4 );
|
|
|
|
Stream.Initialize( pwIndex, nVertexCount * 6 * sizeof( WORD ) );
|
|
MeshStream->LoadIndexStream( &Stream, false, nVertexCount*6 );
|
|
|
|
m_MeshStreamList.push_back( MeshStream );
|
|
}
|
|
delete [] pvPosition;
|
|
delete [] pvNormal;
|
|
delete [] pTexCoord;
|
|
delete [] pRadomVector;
|
|
delete [] pwIndex;
|
|
}
|
|
|
|
m_hMaterial = LoadResource( "Snowfall.fx", RT_SHADER );
|
|
AddCustomParam( m_vecCustomParam, EPT_FLOAT_PTR, m_hMaterial, "g_fSnowHeight", &m_fSnowHeight);
|
|
AddCustomParam( m_vecCustomParam, EPT_FLOAT_PTR, m_hMaterial, "g_fSnowTimer", &m_fSnowTimer);
|
|
AddCustomParam( m_vecCustomParam, EPT_VECTOR_PTR, m_hMaterial, "g_CamPos", &m_CamPos);
|
|
if( !m_bUsePointSprite ) {
|
|
AddCustomParam( m_vecCustomParam, EPT_VECTOR_PTR, m_hMaterial, "g_CamXVector", &m_CamXVector);
|
|
AddCustomParam( m_vecCustomParam, EPT_VECTOR_PTR, m_hMaterial, "g_CamYVector", &m_CamYVector);
|
|
AddCustomParam( m_vecCustomParam, EPT_FLOAT_PTR, m_hMaterial, "g_fSnowSize", &m_fSnowSize);
|
|
AddCustomParam( m_vecCustomParam, EPT_FLOAT_PTR, m_hMaterial, "g_fAniSpeed", &m_fSnowAniSpeed);
|
|
if( m_hTexture ) {
|
|
int nTexIndex = m_hTexture->GetMyIndex();
|
|
//AddCustomParam( m_vecCustomParam, EPT_TEX, m_hMaterial, "g_SnowTex", &nTexIndex );
|
|
// gtx460그래픽카드에선 텍스처 타입을 엄격히 따져서 texture2D인지 texture3D인지를 구분해줘야합니다.
|
|
if( m_hTexture->GetTextureType() == ETTEXTURE_NORMAL )
|
|
AddCustomParam( m_vecCustomParam, EPT_TEX, m_hMaterial, "g_SnowTex", &nTexIndex );
|
|
else
|
|
AddCustomParam( m_vecCustomParam, EPT_TEX, m_hMaterial, "g_SnowTex3D", &nTexIndex );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CEtSnowEffect::Render( float fElapsedTime )
|
|
{
|
|
if( !m_hTexture ) {
|
|
return;
|
|
}
|
|
|
|
if (m_isUp)
|
|
{
|
|
m_fSnowTimer += fElapsedTime*1000.f/m_nSnowTimeOut;
|
|
while( m_fSnowTimer > 1 ) m_fSnowTimer-=1.f;
|
|
}
|
|
else
|
|
{
|
|
m_fSnowTimer -= fElapsedTime*1000.f/m_nSnowTimeOut;
|
|
while( m_fSnowTimer < 0 ) m_fSnowTimer+=1.f;
|
|
}
|
|
|
|
EtMatrix WorldMat;
|
|
EtMatrixIdentity( &WorldMat );
|
|
|
|
SRenderStackElement RenderElement;
|
|
|
|
RenderElement.hMaterial = m_hMaterial;
|
|
RenderElement.nTechniqueIndex = m_bUsePointSprite ? 1 : 0;
|
|
RenderElement.WorldMat = WorldMat;
|
|
RenderElement.nSaveMatIndex = -1;
|
|
RenderElement.pvecCustomParam = &m_vecCustomParam;
|
|
RenderElement.nBakeDepthIndex = DT_NONE;
|
|
|
|
// texture2D 혹은 texture3D에 따라 테크닉 구분.
|
|
if( !m_bUsePointSprite ) {
|
|
if( m_hTexture && m_hTexture->GetTextureType() == ETTEXTURE_NORMAL )
|
|
RenderElement.nTechniqueIndex = 2;
|
|
}
|
|
|
|
EtMatrix *CamMat = CEtCamera::GetActiveCamera()->GetInvViewMat();
|
|
|
|
m_CamXVector = *(EtVector3*)&CamMat->_11;
|
|
m_CamYVector = *(EtVector3*)&CamMat->_21;
|
|
|
|
m_CamPos = *(EtVector3*)&CamMat->_41;
|
|
m_CamPos.y = 0.f;
|
|
|
|
const int POS_COUNT = 7;
|
|
EtVector3 camPos[ POS_COUNT ];
|
|
camPos[0] = *(EtVector3*)&CamMat->_41;
|
|
camPos[1] = camPos[0] + (*(EtVector3*)&CamMat->_31) * 4000.f;
|
|
camPos[2] = camPos[0] + (*(EtVector3*)&CamMat->_31) * 2000.f;
|
|
camPos[3] = camPos[0] + (*(EtVector3*)&CamMat->_31) * 3000.f + (*(EtVector3*)&CamMat->_11) * 1500.f;
|
|
camPos[4] = camPos[0] + (*(EtVector3*)&CamMat->_31) * 3000.f - (*(EtVector3*)&CamMat->_11) * 1500.f;
|
|
camPos[5] = camPos[0] + (*(EtVector3*)&CamMat->_31) * 2000.f + (*(EtVector3*)&CamMat->_11) * 1000.f;
|
|
camPos[6] = camPos[0] + (*(EtVector3*)&CamMat->_31) * 2000.f - (*(EtVector3*)&CamMat->_11) * 1000.f;
|
|
EtTerrainHandle Terrain = CEtTerrainArea::GetItem( 0 );
|
|
int i, j, nCountX, nCountY;
|
|
Terrain->GetBlockCount(nCountX, nCountY);
|
|
for( j = 0; j < nCountX*nCountY; j++)
|
|
{
|
|
SAABox Box = *Terrain->GetBoundingBox( j );
|
|
for( i = 0; i < POS_COUNT; i++) {
|
|
if( Box.IsInside( EtVector3( camPos[i].x, (Box.Max.y+Box.Min.y)*0.5f , camPos[i].z ))) {
|
|
break;
|
|
}
|
|
}
|
|
if( i != POS_COUNT ) {
|
|
RenderElement.pRenderMeshStream = m_MeshStreamList[ j ];
|
|
GetCurRenderStack()->AddAlphaRenderElement( RenderElement );
|
|
}
|
|
}
|
|
}
|
|
|
|
EtSnowHandle CEtSnowEffect::CreateSnowEffect( const char *pSnowTexture, int nSnowCount, float fSnowSize )
|
|
{
|
|
CEtSnowEffect *pSnowEffect;
|
|
|
|
pSnowEffect = new CEtSnowEffect();
|
|
pSnowEffect->SetSnowCount( nSnowCount );
|
|
pSnowEffect->SetSnowSize(fSnowSize);
|
|
pSnowEffect->Initialize( pSnowTexture );
|
|
|
|
return pSnowEffect->GetMySmartPtr();
|
|
}
|