You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/CryEngine/RenderDll/Common/RendElements/CREVolumeObject.cpp

192 lines
5.0 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "RenderDll_precompiled.h"
#include "CREVolumeObject.h"
#include <IEntityRenderState.h> // <> required for Interfuscator
#include <AzCore/std/containers/vector.h>
#if !defined(NULL_RENDERER)
#include "../../XRenderD3D9/DriverD3D.h"
#endif
//////////////////////////////////////////////////////////////////////////
//
class CVolumeTexture
: public IVolumeTexture
{
public:
void Release() override;
bool Create(unsigned int width, unsigned int height, unsigned int depth, unsigned char* pData) override;
bool Update(unsigned int width, unsigned int height, unsigned int depth, const unsigned char* pData) override;
int GetTexID() const override;
uint32 GetWidth() const override { return m_width; }
uint32 GetHeight() const override { return m_height; }
uint32 GetDepth() const override { return m_depth; }
CTexture* GetTexture() const override { return m_pTex; }
CVolumeTexture();
~CVolumeTexture();
private:
unsigned int m_width;
unsigned int m_height;
unsigned int m_depth;
static const size_t StagingBufferFrameCount = 2;
AZStd::vector<uint8_t> m_StagingData;
uint8_t m_FrameIndex;
inline uint8_t* GetCurrentStagingData()
{
const size_t sliceSize = m_StagingData.size() / StagingBufferFrameCount;
return &m_StagingData[m_FrameIndex * sliceSize];
}
CTexture* m_pTex;
};
CVolumeTexture::CVolumeTexture()
: m_width(0)
, m_height(0)
, m_depth(0)
, m_pTex(0)
, m_FrameIndex(0)
{
}
CVolumeTexture::~CVolumeTexture()
{
if (m_pTex)
{
gRenDev->RemoveTexture(m_pTex->GetTextureID());
}
}
void CVolumeTexture::Release()
{
delete this;
}
bool CVolumeTexture::Create(unsigned int width, unsigned int height, unsigned int depth, unsigned char* pData)
{
assert(!m_pTex);
if (!m_pTex)
{
char name[128];
name[sizeof(name) - 1] = '\0';
azsnprintf(name, sizeof(name) - 1, "$VolObj_%d", gRenDev->m_TexGenID++);
const uint32_t totalByteCount = width * height * depth;
m_StagingData.resize(totalByteCount * StagingBufferFrameCount);
if (pData)
{
uint8_t* currentStagingData = GetCurrentStagingData();
memcpy(currentStagingData, pData, totalByteCount);
pData = currentStagingData;
}
int flags(FT_DONT_STREAM);
m_pTex = CTexture::Create3DTexture(name, width, height, depth, 1, flags, pData, eTF_A8, eTF_A8);
m_width = width;
m_height = height;
m_depth = depth;
}
return m_pTex != 0;
}
bool CVolumeTexture::Update([[maybe_unused]] unsigned int width, [[maybe_unused]] unsigned int height, [[maybe_unused]] unsigned int depth, [[maybe_unused]] const unsigned char* pData)
{
if (!CTexture::IsTextureExist(m_pTex))
{
return false;
}
m_FrameIndex ^= m_FrameIndex;
#if !defined(NULL_RENDERER)
uint8_t* stagingData = GetCurrentStagingData();
unsigned int cpyWidth = min(width, m_width);
unsigned int cpyHeight = min(height, m_height);
unsigned int cpyDepth = min(depth, m_depth);
memcpy(stagingData, pData, cpyWidth * cpyHeight * cpyDepth);
m_pTex->UpdateTextureRegion(stagingData, 0, 0, 0, cpyWidth, cpyHeight, cpyDepth, m_pTex->GetDstFormat());
#endif
return true;
}
int CVolumeTexture::GetTexID() const
{
return m_pTex ? m_pTex->GetTextureID() : 0;
}
//////////////////////////////////////////////////////////////////////////
//
CREVolumeObject::CREVolumeObject()
: CRendElementBase()
, m_center(0, 0, 0)
, m_matInv()
, m_eyePosInWS(0, 0, 0)
, m_eyePosInOS(0, 0, 0)
, m_volumeTraceStartPlane(Vec3(0, 0, 1), 0)
, m_renderBoundsOS(Vec3(-1, -1, -1), Vec3(1, 1, 1))
, m_viewerInsideVolume(false)
, m_nearPlaneIntersectsVolume(false)
, m_alpha(1)
, m_scale(1)
, m_pDensVol(0)
, m_pShadVol(0)
, m_pHullMesh(0)
{
mfSetType(eDATA_VolumeObject);
mfUpdateFlags(FCEF_TRANSFORM);
m_matInv.SetIdentity();
}
CREVolumeObject::~CREVolumeObject()
{
}
void CREVolumeObject::mfPrepare(bool bCheckOverflow)
{
if (bCheckOverflow)
{
gRenDev->FX_CheckOverflow(0, 0, this);
}
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
gRenDev->m_RP.m_CurVFormat = eVF_P3F;
}
IVolumeTexture* CREVolumeObject::CreateVolumeTexture() const
{
return new CVolumeTexture();
}