2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-11 08:27:43 +00:00

Implement CFluidPlaneGPU for GPU-computed water ripples

This commit is contained in:
Jack Andersen
2018-06-06 18:43:26 -10:00
parent e63102e180
commit ac424ff9eb
31 changed files with 1651 additions and 1060 deletions

View File

@@ -3,13 +3,14 @@
#include "CFluidPlane.hpp"
#include "CRipple.hpp"
#include "Graphics/Shaders/CFluidPlaneShader.hpp"
namespace urde
{
class CFluidUVMotion;
class CFluidPlaneCPU final : public CFluidPlane
class CFluidPlaneCPU : public CFluidPlane
{
protected:
class CTurbulence
{
float x0_speed;
@@ -39,10 +40,10 @@ class CFluidPlaneCPU final : public CFluidPlane
CAssetId xa4_texIdEnvMap;
CAssetId xa8_texIdEnvBumpMap;
CAssetId xac_texId4;
std::experimental::optional<TLockedToken<CTexture>> xb0_bumpMap;
std::experimental::optional<TLockedToken<CTexture>> xc0_envMap;
std::experimental::optional<TLockedToken<CTexture>> xd0_envBumpMap;
std::experimental::optional<TLockedToken<CTexture>> xe0_lightmap;
TLockedToken<CTexture> xb0_bumpMap;
TLockedToken<CTexture> xc0_envMap;
TLockedToken<CTexture> xd0_envBumpMap;
TLockedToken<CTexture> xe0_lightmap;
zeus::CVector3f xf0_bumpLightDir;
float xfc_bumpScale;
float x100_tileSize;
@@ -56,16 +57,41 @@ class CFluidPlaneCPU final : public CFluidPlane
CTurbulence x120_turbulence;
u32 m_maxVertCount;
bool m_tessellation = false;
mutable std::vector<CFluidPlaneShader::Vertex> m_verts;
mutable std::experimental::optional<CFluidPlaneShader> m_shader;
mutable bool m_cachedDoubleLightmapBlend;
mutable bool m_cachedAdditive;
static bool PrepareRipple(const CRipple& ripple, const CFluidPlaneRender::SPatchInfo& info,
CFluidPlaneRender::SRippleInfo& rippleOut);
void ApplyTurbulence(float t, CFluidPlaneRender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9], const float sineWave[256],
const CFluidPlaneRender::SPatchInfo& info,
const zeus::CVector3f& areaCenter) const;
void ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInfo,
CFluidPlaneRender::SHFieldSample (&heights)[46][46],
u8 (&flags)[9][9], const float sineWave[256],
const CFluidPlaneRender::SPatchInfo& info) const;
void ApplyRipples(const rstl::reserved_vector<CFluidPlaneRender::SRippleInfo, 32>& rippleInfos,
CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9],
const float sineWave[256], const CFluidPlaneRender::SPatchInfo& info) const;
static void UpdatePatchNoNormals(CFluidPlaneRender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9],
const CFluidPlaneRender::SPatchInfo& info);
static void UpdatePatchWithNormals(CFluidPlaneRender::SHFieldSample (& heights)[46][46],
const u8 (& flags)[9][9],
const CFluidPlaneRender::SPatchInfo& info);
bool UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo& info,
CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9],
const zeus::CVector3f& areaCenter,
const std::experimental::optional<CRippleManager>& rippleManager,
int fromX, int toX, int fromY, int toY) const;
public:
CFluidPlaneCPU(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, CAssetId bumpMap, CAssetId envMap, CAssetId envBumpMap,
CAssetId lightMap, float unitsPerLightmapTexel, float tileSize, u32 tileSubdivisions,
EFluidType fluidType, float alpha, const zeus::CVector3f& bumpLightDir, float bumpScale,
const CFluidUVMotion& mot, float turbSpeed, float turbDistance, float turbFreqMax,
CFluidPlaneCPU(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, CAssetId bumpMap, CAssetId envMap,
CAssetId envBumpMap, CAssetId lightMap, float unitsPerLightmapTexel, float tileSize,
u32 tileSubdivisions, EFluidType fluidType, float alpha, const zeus::CVector3f& bumpLightDir,
float bumpScale, const CFluidUVMotion& mot, float turbSpeed, float turbDistance, float turbFreqMax,
float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax,
float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend,
float reflectionSize, float rippleIntensity, u32 maxVertCount);
@@ -85,13 +111,13 @@ public:
float GetReflectionSize() const { return x118_reflectionSize; }
float GetBumpScale() const { return xfc_bumpScale; }
bool HasBumpMap() const { return xb0_bumpMap.operator bool(); }
const CTexture& GetBumpMap() const { return **xb0_bumpMap; }
const CTexture& GetBumpMap() const { return *xb0_bumpMap; }
bool HasEnvMap() const { return xc0_envMap.operator bool(); }
const CTexture& GetEnvMap() const { return **xc0_envMap; }
const CTexture& GetEnvMap() const { return *xc0_envMap; }
bool HasEnvBumpMap() const { return xd0_envBumpMap.operator bool(); }
const CTexture& GetEnvBumpMap() const { return **xd0_envBumpMap; }
const CTexture& GetEnvBumpMap() const { return *xd0_envBumpMap; }
bool HasLightMap() const { return xe0_lightmap.operator bool(); }
const CTexture& GetLightMap() const { return **xe0_lightmap; }
const CTexture& GetLightMap() const { return *xe0_lightmap; }
const zeus::CVector3f& GetBumpLightDir() const { return xf0_bumpLightDir; }
float GetTileSize() const { return x100_tileSize; }
int GetTileSubdivisions() const { return x104_tileSubdivisions; }
@@ -102,115 +128,6 @@ public:
bool HasTurbulence() const { return x120_turbulence.HasTurbulence(); }
};
class CFluidPlaneCPURender
{
public:
enum class NormalMode
{
None,
NoNormals,
Normals,
NBT
};
static int numTilesInHField;
static int numSubdivisionsInTile;
static int numSubdivisionsInHField;
struct SPatchInfo
{
u8 x0_xSubdivs, x1_ySubdivs;
zeus::CVector2f x4_localMin, xc_globalMin;
float x14_tileSize;
float x18_rippleResolution;
float x1c_tileHypRadius;
float x20_ooTileSize;
float x24_ooRippleResolution;
u16 x28_tileX;
u16 x2a_gridDimX;
u16 x2c_gridDimY;
u16 x2e_tileY;
const bool* x30_gridFlags;
u8 x34_redShift;
u8 x35_greenShift;
u8 x36_blueShift;
NormalMode x37_normalMode;
float x38_wavecapIntensityScale;
public:
SPatchInfo(const zeus::CVector3f& localMin, const zeus::CVector3f& localMax, const zeus::CVector3f& pos,
float rippleResolution, float tileSize, float wavecapIntensityScale, int numSubdivisionsInHField,
NormalMode normalMode, int redShift, int greenShift, int blueShift, u32 tileX, u32 gridDimX,
u32 gridDimY, u32 tileY, const bool* gridFlags)
{
x0_xSubdivs = std::min(s16((localMax.x - localMin.x) / rippleResolution + 1.f - FLT_EPSILON) + 2,
numSubdivisionsInHField + 2);
x1_ySubdivs = std::min(s16((localMax.y - localMin.y) / rippleResolution + 1.f - FLT_EPSILON) + 2,
numSubdivisionsInHField + 2);
float tileHypRadius = tileSize * tileSize * 2 * 0.25f;
x4_localMin.x = localMin.x;
x4_localMin.y = localMin.y;
xc_globalMin = x4_localMin + zeus::CVector2f(pos.x, pos.y);
x14_tileSize = tileSize;
x18_rippleResolution = rippleResolution;
if (tileHypRadius != 0.f)
tileHypRadius = std::sqrt(tileHypRadius);
x1c_tileHypRadius = tileHypRadius;
x20_ooTileSize = 1.f / x14_tileSize;
x24_ooRippleResolution = 1.f / x18_rippleResolution;
x28_tileX = u16(tileX);
x2a_gridDimX = u16(gridDimX);
x2c_gridDimY = u16(gridDimY);
x2e_tileY = u16(tileY);
x30_gridFlags = gridFlags;
x34_redShift = u8(redShift);
x35_greenShift = u8(greenShift);
x36_blueShift = u8(blueShift);
x37_normalMode = normalMode;
x38_wavecapIntensityScale = wavecapIntensityScale;
}
};
struct SRippleInfo
{
const CRipple& x0_ripple;
int x4_fromX;
int x8_toX;
int xc_fromY;
int x10_toY;
int x14_gfromX;
int x18_gtoX;
int x1c_gfromY;
int x20_gtoY;
public:
SRippleInfo(const CRipple& ripple, int fromX, int toX, int fromY, int toY)
: x0_ripple(ripple), x14_gfromX(fromX), x18_gtoX(toX), x1c_gfromY(fromY), x20_gtoY(toY) {}
};
struct SHFieldSample
{
float height;
s8 nx;
s8 ny;
s8 nz;
u8 wavecapIntensity;
zeus::CVector3f MakeNormal() const { return {nx / 63.f, ny / 63.f, nz / 63.f}; }
zeus::CVector3f MakeBinormal() const { return {nx / 63.f, nz / 63.f, -ny / 63.f}; }
zeus::CVector3f MakeTangent() const { return {nz / 63.f, ny / 63.f, -nx / 63.f}; }
zeus::CColor MakeColor(const CFluidPlaneCPURender::SPatchInfo& info) const
{
return {(wavecapIntensity >> info.x34_redShift) / 255.f,
(wavecapIntensity >> info.x35_greenShift) / 255.f,
(wavecapIntensity >> info.x36_blueShift) / 255.f};
}
};
};
void RenderPatch(const CFluidPlaneCPURender::SPatchInfo& info,
const CFluidPlaneCPURender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9], bool noRipples, bool flagIs1,
std::vector<CFluidPlaneShader::Vertex>& vOut);
}
#endif // __URDE_CFLUIDPLANECPU_HPP__