2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-06-20 11:53:28 +00:00

Implement non-rippling CFluidPlaneCPU render path

This commit is contained in:
Jack Andersen 2017-08-10 13:13:25 -10:00
parent ea2fdc939b
commit fd7589afd5
9 changed files with 507 additions and 120 deletions

View File

@ -12,9 +12,9 @@ struct ITweakGame : ITweak
virtual bool GetSplashScreensDisabled() const = 0; virtual bool GetSplashScreensDisabled() const = 0;
virtual float GetFirstPersonFOV() const = 0; virtual float GetFirstPersonFOV() const = 0;
virtual float GetPressStartDelay() const = 0; virtual float GetPressStartDelay() const = 0;
virtual float GetRippleSideLengthNormal() const = 0; virtual float GetWavecapIntensityNormal() const = 0;
virtual float GetRippleSideLengthPoison() const = 0; virtual float GetWavecapIntensityPoison() const = 0;
virtual float GetRippleSideLengthLava() const = 0; virtual float GetWavecapIntensityLava() const = 0;
virtual float GetFluidEnvBumpScale() const = 0; virtual float GetFluidEnvBumpScale() const = 0;
virtual float GetHardModeDamageMultiplier() const = 0; virtual float GetHardModeDamageMultiplier() const = 0;
virtual float GetHardModeWeaponMultiplier() const = 0; virtual float GetHardModeWeaponMultiplier() const = 0;

View File

@ -20,9 +20,9 @@ struct CTweakGame : ITweakGame
Value<bool> x2b_splashScreensDisabled; Value<bool> x2b_splashScreensDisabled;
Value<float> x2c_unknown5; Value<float> x2c_unknown5;
Value<float> x30_pressStartDelay; Value<float> x30_pressStartDelay;
Value<float> x34_rippleSideLenNormal; Value<float> x34_wavecapIntensityNormal;
Value<float> x38_rippleSideLenPoison; Value<float> x38_wavecapIntensityPoison;
Value<float> x3c_rippleSideLenLava; Value<float> x3c_wavecapIntensityLava;
Value<float> x40_unknown10; Value<float> x40_unknown10;
Value<float> x44_unknown11; Value<float> x44_unknown11;
Value<float> x48_unknown12; Value<float> x48_unknown12;
@ -38,9 +38,9 @@ struct CTweakGame : ITweakGame
bool GetSplashScreensDisabled() const { return x2b_splashScreensDisabled; } bool GetSplashScreensDisabled() const { return x2b_splashScreensDisabled; }
float GetFirstPersonFOV() const { return x24_fov; } float GetFirstPersonFOV() const { return x24_fov; }
float GetPressStartDelay() const { return x30_pressStartDelay; } float GetPressStartDelay() const { return x30_pressStartDelay; }
float GetRippleSideLengthNormal() const { return x34_rippleSideLenNormal; } float GetWavecapIntensityNormal() const { return x34_wavecapIntensityNormal; }
float GetRippleSideLengthPoison() const { return x38_rippleSideLenPoison; } float GetWavecapIntensityPoison() const { return x38_wavecapIntensityPoison; }
float GetRippleSideLengthLava() const { return x3c_rippleSideLenLava; } float GetWavecapIntensityLava() const { return x3c_wavecapIntensityLava; }
float GetFluidEnvBumpScale() const { return x4c_fluidEnvBumpScale; } float GetFluidEnvBumpScale() const { return x4c_fluidEnvBumpScale; }
float GetHardModeDamageMultiplier() const { return x60_hardmodeDamageMult; } float GetHardModeDamageMultiplier() const { return x60_hardmodeDamageMult; }
float GetHardModeWeaponMultiplier() const { return x64_hardmodeWeaponMult; } float GetHardModeWeaponMultiplier() const { return x64_hardmodeWeaponMult; }

View File

@ -178,7 +178,8 @@ CFluidPlaneShader::CFluidPlaneShader(CFluidPlane::EFluidType type,
} }
void CFluidPlaneShader::draw(const zeus::CMatrix4f texMtxs[6], const zeus::CMatrix4f& normMtx, float indScale, void CFluidPlaneShader::draw(const zeus::CMatrix4f texMtxs[6], const zeus::CMatrix4f& normMtx, float indScale,
const std::vector<CLight>& lights, const zeus::CColor kColors[4]) const std::vector<CLight>& lights, const zeus::CColor kColors[4],
const std::vector<Vertex>& verts)
{ {
Uniform& uni = *reinterpret_cast<Uniform*>(m_uniBuf->map(sizeof(Uniform))); Uniform& uni = *reinterpret_cast<Uniform*>(m_uniBuf->map(sizeof(Uniform)));
uni.m_mv = CGraphics::g_GXModelView.toMatrix4f(); uni.m_mv = CGraphics::g_GXModelView.toMatrix4f();
@ -192,8 +193,11 @@ void CFluidPlaneShader::draw(const zeus::CMatrix4f texMtxs[6], const zeus::CMatr
uni.m_lighting.mulColor = kColors[3]; uni.m_lighting.mulColor = kColors[3];
uni.m_lighting.fog.m_rangeScale = indScale; uni.m_lighting.fog.m_rangeScale = indScale;
m_uniBuf->unmap(); m_uniBuf->unmap();
m_vbo->load(verts.data(), verts.size() * sizeof(Vertex));
CGraphics::SetShaderDataBinding(m_dataBind); CGraphics::SetShaderDataBinding(m_dataBind);
CGraphics::DrawArray(0, 0); CGraphics::DrawArray(0, verts.size());
} }
} }

View File

@ -37,6 +37,29 @@ struct SFluidPlaneShaderInfo
class CFluidPlaneShader class CFluidPlaneShader
{ {
public:
struct Vertex
{
zeus::CVector3f m_pos;
zeus::CVector3f m_norm;
zeus::CVector3f m_binorm;
zeus::CVector3f m_tangent;
zeus::CColor m_color;
Vertex() = default;
Vertex(const zeus::CVector3f& position) : m_pos(position) {}
Vertex(const zeus::CVector3f& position, const zeus::CColor& color)
: m_pos(position), m_color(color) {}
Vertex(const zeus::CVector3f& position, const zeus::CVector3f& normal,
const zeus::CColor& color)
: m_pos(position), m_norm(normal), m_color(color) {}
Vertex(const zeus::CVector3f& position, const zeus::CVector3f& normal,
const zeus::CVector3f& binormal, const zeus::CVector3f& tangent,
const zeus::CColor& color)
: m_pos(position), m_norm(normal), m_binorm(binormal), m_tangent(tangent), m_color(color) {}
};
private:
class Cache class Cache
{ {
std::pair<boo::GraphicsDataToken, boo::IShaderPipeline*> m_cache[1024] = {}; std::pair<boo::GraphicsDataToken, boo::IShaderPipeline*> m_cache[1024] = {};
@ -46,15 +69,6 @@ class CFluidPlaneShader
}; };
static Cache _cache; static Cache _cache;
struct Vertex
{
zeus::CVector3f m_pos;
zeus::CVector3f m_norm;
zeus::CVector3f m_binorm;
zeus::CVector3f m_tangent;
zeus::CColor m_color;
};
struct Uniform struct Uniform
{ {
zeus::CMatrix4f m_mv; zeus::CMatrix4f m_mv;
@ -102,7 +116,8 @@ public:
const std::experimental::optional<TLockedToken<CTexture>>& lightmap, const std::experimental::optional<TLockedToken<CTexture>>& lightmap,
bool doubleLightmapBlend, bool additive); bool doubleLightmapBlend, bool additive);
void draw(const zeus::CMatrix4f texMtxs[6], const zeus::CMatrix4f& normMtx, float indScale, void draw(const zeus::CMatrix4f texMtxs[6], const zeus::CMatrix4f& normMtx, float indScale,
const std::vector<CLight>& lights, const zeus::CColor kColors[4]); const std::vector<CLight>& lights, const zeus::CColor kColors[4],
const std::vector<Vertex>& verts);
}; };
} }

View File

@ -46,7 +46,7 @@ public:
CScriptWater& water, CStateManager& mgr); CScriptWater& water, CStateManager& mgr);
virtual void Update(); virtual void Update();
virtual void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf, virtual void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
const zeus::CTransform& areaXf, bool noSubdiv, const zeus::CFrustum& frustum, const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum,
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId, const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const {} const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const {}
float GetAlpha() const { return x40_alpha; } float GetAlpha() const { return x40_alpha; }

View File

@ -281,12 +281,12 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C
class CFluidPlaneCPURender class CFluidPlaneCPURender
{ {
public: public:
enum class RenderMode enum class NormalMode
{ {
None, None,
Normal, NoNormals,
Subdivided, Normals,
BumpMapped NBT
}; };
static int numTilesInHField; static int numTilesInHField;
@ -297,52 +297,52 @@ public:
{ {
u8 x0_xSubdivs, x1_ySubdivs; u8 x0_xSubdivs, x1_ySubdivs;
zeus::CVector2f x4_localMin, xc_globalMin; zeus::CVector2f x4_localMin, xc_globalMin;
float x14_rippleSideLen; float x14_tileSize;
float x18_rippleResolution; float x18_rippleResolution;
float x1c_rippleHypRadius; float x1c_tileHypRadius;
float x20_ooRippleSideLen; float x20_ooTileSize;
float x24_ooRippleResolution; float x24_ooRippleResolution;
u16 x28_tileX; u16 x28_tileX;
u16 x2a_gridDimX; u16 x2a_gridDimX;
u16 x2c_gridDimY; u16 x2c_gridDimY;
u16 x2e_tileY; u16 x2e_tileY;
const bool* x30_gridFlags; const bool* x30_gridFlags;
bool x34_r14; u8 x34_redShift;
u8 x35_r22; u8 x35_greenShift;
u8 x36_r23; u8 x36_blueShift;
RenderMode x37_renderMode; NormalMode x37_normalMode;
float x38_tileSize; float x38_wavecapIntensityScale;
public: public:
SPatchInfo(const zeus::CVector3f& localMin, const zeus::CVector3f& localMax, const zeus::CVector3f& pos, SPatchInfo(const zeus::CVector3f& localMin, const zeus::CVector3f& localMax, const zeus::CVector3f& pos,
float rippleResolution, float rippleSideLen, float tileSize, int numSubdivisionsInHField, float rippleResolution, float tileSize, float wavecapIntensityScale, int numSubdivisionsInHField,
RenderMode renderMode, bool r14, int r22, int r23, u32 tileX, u32 gridDimX, u32 gridDimY, NormalMode normalMode, int redShift, int greenShift, int blueShift, u32 tileX, u32 gridDimX,
u32 tileY, const bool* gridFlags) u32 gridDimY, u32 tileY, const bool* gridFlags)
{ {
x0_xSubdivs = std::min(s16((localMax.x - localMin.x) / rippleResolution + 1.f - FLT_EPSILON) + 2, x0_xSubdivs = std::min(s16((localMax.x - localMin.x) / rippleResolution + 1.f - FLT_EPSILON) + 2,
numSubdivisionsInHField + 2); numSubdivisionsInHField + 2);
x1_ySubdivs = std::min(s16((localMax.y - localMin.y) / rippleResolution + 1.f - FLT_EPSILON) + 2, x1_ySubdivs = std::min(s16((localMax.y - localMin.y) / rippleResolution + 1.f - FLT_EPSILON) + 2,
numSubdivisionsInHField + 2); numSubdivisionsInHField + 2);
float rippleHypRadius = rippleSideLen * rippleSideLen * 2 * 0.25f; float tileHypRadius = tileSize * tileSize * 2 * 0.25f;
x4_localMin.x = localMin.x; x4_localMin.x = localMin.x;
x4_localMin.y = localMin.y; x4_localMin.y = localMin.y;
xc_globalMin = x4_localMin + zeus::CVector2f(pos.x, pos.y); xc_globalMin = x4_localMin + zeus::CVector2f(pos.x, pos.y);
x14_rippleSideLen = rippleSideLen; x14_tileSize = tileSize;
x18_rippleResolution = rippleResolution; x18_rippleResolution = rippleResolution;
if (rippleHypRadius != 0.f) if (tileHypRadius != 0.f)
rippleHypRadius = std::sqrt(rippleHypRadius); tileHypRadius = std::sqrt(tileHypRadius);
x1c_rippleHypRadius = rippleHypRadius; x1c_tileHypRadius = tileHypRadius;
x20_ooRippleSideLen = 1.f / x14_rippleSideLen; x20_ooTileSize = 1.f / x14_tileSize;
x24_ooRippleResolution = 1.f / x18_rippleResolution; x24_ooRippleResolution = 1.f / x18_rippleResolution;
x28_tileX = u16(tileX); x28_tileX = u16(tileX);
x2a_gridDimX = u16(gridDimX); x2a_gridDimX = u16(gridDimX);
x2c_gridDimY = u16(gridDimY); x2c_gridDimY = u16(gridDimY);
x2e_tileY = u16(tileY); x2e_tileY = u16(tileY);
x30_gridFlags = gridFlags; x30_gridFlags = gridFlags;
x34_r14 = r14; x34_redShift = u8(redShift);
x35_r22 = u8(r22); x35_greenShift = u8(greenShift);
x36_r23 = u8(r23); x36_blueShift = u8(blueShift);
x37_renderMode = renderMode; x37_normalMode = normalMode;
x38_tileSize = tileSize; x38_wavecapIntensityScale = wavecapIntensityScale;
} }
}; };
@ -364,8 +364,11 @@ public:
struct SHFieldSample struct SHFieldSample
{ {
float f1; float height;
u8 f2; s8 nx;
s8 ny;
s8 nz;
u8 wavecapIntensity;
}; };
}; };
@ -424,7 +427,7 @@ static void ApplyTurbulence(float t, CFluidPlaneCPURender::SHFieldSample (&heigh
float distFac = curX * curX + curYSq; float distFac = curX * curX + curYSq;
if (distFac != 0.f) if (distFac != 0.f)
distFac = std::sqrt(distFac); distFac = std::sqrt(distFac);
heights[i][j].f1 = fluidPane.GetTurbulenceHeight(fluidPane.GetOOTurbulenceDistance() * distFac + scaledT); heights[i][j].height = fluidPane.GetTurbulenceHeight(fluidPane.GetOOTurbulenceDistance() * distFac + scaledT);
curX += info.x18_rippleResolution; curX += info.x18_rippleResolution;
} }
curY += info.x18_rippleResolution; curY += info.x18_rippleResolution;
@ -457,27 +460,27 @@ static void ApplyRipple(const CFluidPlaneCPURender::SRippleInfo& rippleInfo,
CFluidPlaneCPURender::numSubdivisionsInTile; CFluidPlaneCPURender::numSubdivisionsInTile;
float curY = rippleInfo.x0_ripple.GetCenter().y - info.xc_globalMin.y - float curY = rippleInfo.x0_ripple.GetCenter().y - info.xc_globalMin.y -
(0.5f * info.x14_rippleSideLen + (fromY - 1) * info.x14_rippleSideLen); (0.5f * info.x14_tileSize + (fromY - 1) * info.x14_tileSize);
int curGridY = info.x2a_gridDimX * (info.x2e_tileY + fromY - 1); int curGridY = info.x2a_gridDimX * (info.x2e_tileY + fromY - 1);
int startGridX = (info.x28_tileX + fromX - 1); int startGridX = (info.x28_tileX + fromX - 1);
int gridCells = info.x2a_gridDimX * info.x2c_gridDimY; int gridCells = info.x2a_gridDimX * info.x2c_gridDimY;
float f11 = 64.f * rippleInfo.x0_ripple.GetOODistanceFalloff(); float f11 = 64.f * rippleInfo.x0_ripple.GetOODistanceFalloff();
int curYDiv = rippleInfo.xc_fromY; int curYDiv = rippleInfo.xc_fromY;
for (int i=fromY ; i<=toY ; ++i, curY -= info.x14_rippleSideLen) for (int i=fromY ; i<=toY ; ++i, curY -= info.x14_tileSize)
{ {
int nextYDiv = (i+1) * CFluidPlaneCPURender::numSubdivisionsInTile; int nextYDiv = (i+1) * CFluidPlaneCPURender::numSubdivisionsInTile;
float curYSq = curY * curY; float curYSq = curY * curY;
int curGridX = startGridX; int curGridX = startGridX;
int curXDiv = rippleInfo.x4_fromX; int curXDiv = rippleInfo.x4_fromX;
float curX = rippleInfo.x0_ripple.GetCenter().x - info.xc_globalMin.x - float curX = rippleInfo.x0_ripple.GetCenter().x - info.xc_globalMin.x -
(0.5f * info.x14_rippleSideLen + (fromX - 1) * info.x14_rippleSideLen); (0.5f * info.x14_tileSize + (fromX - 1) * info.x14_tileSize);
for (int j=fromX ; j<=toX ; ++j, curX -= info.x14_rippleSideLen, ++curGridX) for (int j=fromX ; j<=toX ; ++j, curX -= info.x14_tileSize, ++curGridX)
{ {
float dist = curX * curX + curYSq; float dist = curX * curX + curYSq;
if (dist != 0.f) if (dist != 0.f)
dist = std::sqrt(dist); dist = std::sqrt(dist);
if (maxDist < dist - info.x1c_rippleHypRadius || minDist > dist + info.x1c_rippleHypRadius) if (maxDist < dist - info.x1c_tileHypRadius || minDist > dist + info.x1c_tileHypRadius)
continue; continue;
bool addedRipple = false; bool addedRipple = false;
@ -504,12 +507,12 @@ static void ApplyRipple(const CFluidPlaneCPURender::SRippleInfo& rippleInfo,
float divDist = (divDistSq != 0.f) ? std::sqrt(divDistSq) : 0.f; float divDist = (divDistSq != 0.f) ? std::sqrt(divDistSq) : 0.f;
if (u8 val = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * f11)]) if (u8 val = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * f11)])
{ {
heights[k][l].f1 += val * rippleInfo.x0_ripple.GetAmplitude() * heights[k][l].height += val * rippleInfo.x0_ripple.GetAmplitude() *
sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT)]; sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT)];
} }
else else
{ {
heights[k][l].f1 += 0.f; heights[k][l].height += 0.f;
} }
addedRipple = true; addedRipple = true;
} }
@ -557,12 +560,12 @@ static void ApplyRipple(const CFluidPlaneCPURender::SRippleInfo& rippleInfo,
float divDist = (divDistSq != 0.f) ? std::sqrt(divDistSq) : 0.f; float divDist = (divDistSq != 0.f) ? std::sqrt(divDistSq) : 0.f;
if (u8 val = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * f11)]) if (u8 val = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * f11)])
{ {
heights[k][l].f1 += val * rippleInfo.x0_ripple.GetAmplitude() * heights[k][l].height += val * rippleInfo.x0_ripple.GetAmplitude() *
sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT)]; sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT)];
} }
else else
{ {
heights[k][l].f1 += 0.f; heights[k][l].height += 0.f;
} }
addedRipple = true; addedRipple = true;
} }
@ -597,7 +600,7 @@ static void ApplyRipples(const rstl::reserved_vector<CFluidPlaneCPURender::SRipp
flags[CFluidPlaneCPURender::numTilesInHField+1][i+1] |= 2; flags[CFluidPlaneCPURender::numTilesInHField+1][i+1] |= 2;
} }
static void UpdatePatchNormal(CFluidPlaneCPURender::SHFieldSample (&heights)[45][45], const u8 (&flags)[9][9], static void UpdatePatchNoNormals(CFluidPlaneCPURender::SHFieldSample (& heights)[45][45], const u8 (& flags)[9][9],
const CFluidPlaneCPURender::SPatchInfo& info) const CFluidPlaneCPURender::SPatchInfo& info)
{ {
for (int i=1 ; i <= (info.x1_ySubdivs + CFluidPlaneCPURender::numSubdivisionsInTile - 2) / for (int i=1 ; i <= (info.x1_ySubdivs + CFluidPlaneCPURender::numSubdivisionsInTile - 2) /
@ -619,35 +622,38 @@ static void UpdatePatchNormal(CFluidPlaneCPURender::SHFieldSample (&heights)[45]
for (int l=r11 ; l<x28 ; ++l) for (int l=r11 ; l<x28 ; ++l)
{ {
CFluidPlaneCPURender::SHFieldSample& sample = heights[k][l]; CFluidPlaneCPURender::SHFieldSample& sample = heights[k][l];
if (sample.f1 > 0.f) if (sample.height > 0.f)
sample.f2 = u8(std::min(255, int(info.x38_tileSize * sample.f1))); sample.wavecapIntensity =
u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height)));
else else
sample.f2 = 0; sample.wavecapIntensity = 0;
} }
} }
} }
else else
{ {
if (i > 0 && i < CFluidPlaneCPURender::numTilesInHField + 1 && if (i > 0 && i < CFluidPlaneCPURender::numTilesInHField + 1 &&
r10 > 0 && r10 < CFluidPlaneCPURender::numTilesInHField + 1) j > 0 && j < CFluidPlaneCPURender::numTilesInHField + 1)
{ {
int halfSubdivs = CFluidPlaneCPURender::numSubdivisionsInTile / 2; int halfSubdivs = CFluidPlaneCPURender::numSubdivisionsInTile / 2;
CFluidPlaneCPURender::SHFieldSample& sample = heights[halfSubdivs + r9][halfSubdivs + r11]; CFluidPlaneCPURender::SHFieldSample& sample = heights[halfSubdivs + r9][halfSubdivs + r11];
if (sample.f1 > 0.f) if (sample.height > 0.f)
sample.f2 = u8(std::min(255, int(info.x38_tileSize * sample.f1))); sample.wavecapIntensity =
u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height)));
else else
sample.f2 = 0; sample.wavecapIntensity = 0;
} }
if (i != 0) if (i != 0)
{ {
for (int k=r11 ; k<x28 ; ++k) for (int l=r11 ; l<x28 ; ++l)
{ {
CFluidPlaneCPURender::SHFieldSample& sample = heights[i][k]; CFluidPlaneCPURender::SHFieldSample& sample = heights[r9][l];
if (sample.f1 > 0.f) if (sample.height > 0.f)
sample.f2 = u8(std::min(255, int(info.x38_tileSize * sample.f1))); sample.wavecapIntensity =
u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height)));
else else
sample.f2 = 0; sample.wavecapIntensity = 0;
} }
} }
@ -656,10 +662,11 @@ static void UpdatePatchNormal(CFluidPlaneCPURender::SHFieldSample (&heights)[45]
for (int k=r9+1 ; k<x24 ; ++k) for (int k=r9+1 ; k<x24 ; ++k)
{ {
CFluidPlaneCPURender::SHFieldSample& sample = heights[k][r11]; CFluidPlaneCPURender::SHFieldSample& sample = heights[k][r11];
if (sample.f1 > 0.f) if (sample.height > 0.f)
sample.f2 = u8(std::min(255, int(info.x38_tileSize * sample.f1))); sample.wavecapIntensity =
u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height)));
else else
sample.f2 = 0; sample.wavecapIntensity = 0;
} }
} }
} }
@ -667,14 +674,166 @@ static void UpdatePatchNormal(CFluidPlaneCPURender::SHFieldSample (&heights)[45]
} }
} }
static void UpdatePatchSubdivided(const CFluidPlaneCPURender::SHFieldSample (&heights)[45][45], const u8 (&flags)[9][9], static void UpdatePatchWithNormals(CFluidPlaneCPURender::SHFieldSample (& heights)[45][45], const u8 (& flags)[9][9],
const CFluidPlaneCPURender::SPatchInfo& info) const CFluidPlaneCPURender::SPatchInfo& info)
{ {
float normalScale = -(2.f * info.x18_rippleResolution);
float nz = 0.25f * 2.f * info.x18_rippleResolution;
int curGridY = info.x2e_tileY * info.x2a_gridDimX - 1 + info.x28_tileX;
for (int i=1 ; i <= (info.x1_ySubdivs + CFluidPlaneCPURender::numSubdivisionsInTile - 2) /
CFluidPlaneCPURender::numSubdivisionsInTile ; ++i, curGridY += info.x2a_gridDimX)
{
int r11 = i * CFluidPlaneCPURender::numSubdivisionsInTile + 1;
int r9 = std::max(0, r11 - CFluidPlaneCPURender::numSubdivisionsInTile);
int x38 = std::min(r11, info.x1_ySubdivs + 1);
for (int j=1 ; j <= (info.x0_xSubdivs + CFluidPlaneCPURender::numSubdivisionsInTile - 2) /
CFluidPlaneCPURender::numSubdivisionsInTile ; ++j)
{
int r12 = j * CFluidPlaneCPURender::numSubdivisionsInTile + 1;
int x3c = std::min(r12, info.x0_xSubdivs + 1);
r12 -= CFluidPlaneCPURender::numSubdivisionsInTile;
if ((flags[i][j] & 0x1f) == 0x1f)
{
for (int k=r9 ; k<x38 ; ++k)
{
for (int l=r12 ; l<x3c ; ++l)
{
CFluidPlaneCPURender::SHFieldSample& sample = heights[k][l];
CFluidPlaneCPURender::SHFieldSample& up = heights[k+1][l];
CFluidPlaneCPURender::SHFieldSample& down = heights[k-1][l];
CFluidPlaneCPURender::SHFieldSample& right = heights[k][l+1];
CFluidPlaneCPURender::SHFieldSample& left = heights[k][l-1];
float nx = (right.height - left.height) * normalScale;
float ny = (up.height - down.height) * normalScale;
float normalizer = ny * ny + nx * nx + nz * nz;
if (normalizer != 0.f)
normalizer = std::sqrt(normalizer);
normalizer = 63.f / normalizer;
sample.nx = s8(nx * normalizer);
sample.ny = s8(ny * normalizer);
sample.nz = s8(nz * normalizer);
if (sample.height > 0.f)
sample.wavecapIntensity =
u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height)));
else
sample.wavecapIntensity = 0;
}
}
}
else
{
if (!info.x30_gridFlags || info.x30_gridFlags[curGridY+j])
{
if (i > 0 && i < CFluidPlaneCPURender::numTilesInHField + 1 &&
j > 0 && j < CFluidPlaneCPURender::numTilesInHField + 1)
{
int halfSubdivs = CFluidPlaneCPURender::numSubdivisionsInTile / 2;
int k = halfSubdivs + r9;
int l = halfSubdivs + r12;
CFluidPlaneCPURender::SHFieldSample& sample = heights[k][l];
CFluidPlaneCPURender::SHFieldSample& up = heights[k+1][l];
CFluidPlaneCPURender::SHFieldSample& down = heights[k-1][l];
CFluidPlaneCPURender::SHFieldSample& right = heights[k][l+1];
CFluidPlaneCPURender::SHFieldSample& left = heights[k][l-1];
float nx = (right.height - left.height) * normalScale;
float ny = (up.height - down.height) * normalScale;
float normalizer = ny * ny + nx * nx + nz * nz;
if (normalizer != 0.f)
normalizer = std::sqrt(normalizer);
normalizer = 63.f / normalizer;
sample.nx = s8(nx * normalizer);
sample.ny = s8(ny * normalizer);
sample.nz = s8(nz * normalizer);
if (sample.height > 0.f)
sample.wavecapIntensity =
u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height)));
else
sample.wavecapIntensity = 0;
}
}
if (j != 0 && i != 0)
{
if ((flags[i][j] & 2) != 0 || (flags[i-1][j] & 1) != 0 ||
(flags[i][j] & 4) != 0 || (flags[i][j-1] & 8) != 0)
{
for (int l=r12 ; l<x3c ; ++l)
{
CFluidPlaneCPURender::SHFieldSample& sample = heights[r9][l];
CFluidPlaneCPURender::SHFieldSample& up = heights[r9+1][l];
CFluidPlaneCPURender::SHFieldSample& down = heights[r9-1][l];
CFluidPlaneCPURender::SHFieldSample& right = heights[r9][l+1];
CFluidPlaneCPURender::SHFieldSample& left = heights[r9][l-1];
float nx = (right.height - left.height) * normalScale;
float ny = (up.height - down.height) * normalScale;
float normalizer = ny * ny + nx * nx + nz * nz;
if (normalizer != 0.f)
normalizer = std::sqrt(normalizer);
normalizer = 63.f / normalizer;
sample.nx = s8(nx * normalizer);
sample.ny = s8(ny * normalizer);
sample.nz = s8(nz * normalizer);
if (sample.height > 0.f)
sample.wavecapIntensity =
u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height)));
else
sample.wavecapIntensity = 0;
}
for (int k=r9 ; k<x38 ; ++k)
{
CFluidPlaneCPURender::SHFieldSample& sample = heights[k][r12];
CFluidPlaneCPURender::SHFieldSample& up = heights[k+1][r12];
CFluidPlaneCPURender::SHFieldSample& down = heights[k-1][r12];
CFluidPlaneCPURender::SHFieldSample& right = heights[k][r12+1];
CFluidPlaneCPURender::SHFieldSample& left = heights[k][r12-1];
float nx = (right.height - left.height) * normalScale;
float ny = (up.height - down.height) * normalScale;
float normalizer = ny * ny + nx * nx + nz * nz;
if (normalizer != 0.f)
normalizer = std::sqrt(normalizer);
normalizer = 63.f / normalizer;
sample.nx = s8(nx * normalizer);
sample.ny = s8(ny * normalizer);
sample.nz = s8(nz * normalizer);
if (sample.height > 0.f)
sample.wavecapIntensity =
u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height)));
else
sample.wavecapIntensity = 0;
}
}
else
{
CFluidPlaneCPURender::SHFieldSample& sample = heights[r9][r12];
CFluidPlaneCPURender::SHFieldSample& up = heights[r9+1][r12];
CFluidPlaneCPURender::SHFieldSample& down = heights[r9-1][r12];
CFluidPlaneCPURender::SHFieldSample& right = heights[r9][r12+1];
CFluidPlaneCPURender::SHFieldSample& left = heights[r9][r12-1];
float nx = (right.height - left.height) * normalScale;
float ny = (up.height - down.height) * normalScale;
float normalizer = ny * ny + nx * nx + nz * nz;
if (normalizer != 0.f)
normalizer = std::sqrt(normalizer);
normalizer = 63.f / normalizer;
sample.nx = s8(nx * normalizer);
sample.ny = s8(ny * normalizer);
sample.nz = s8(nz * normalizer);
if (sample.height > 0.f)
sample.wavecapIntensity =
u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height)));
else
sample.wavecapIntensity = 0;
}
}
}
}
}
} }
static bool UpdatePatch(float time, const CFluidPlaneCPURender::SPatchInfo& info, const CFluidPlaneCPU& fluidPane, static bool UpdatePatch(float time, const CFluidPlaneCPURender::SPatchInfo& info,
const zeus::CVector3f& areaCenter, CFluidPlaneCPURender::SHFieldSample (&heights)[45][45], u8 (&flags)[9][9],
const CFluidPlaneCPU& fluidPane, const zeus::CVector3f& areaCenter,
const std::experimental::optional<CRippleManager>& rippleManager, const std::experimental::optional<CRippleManager>& rippleManager,
int fromX, int toX, int fromY, int toY) int fromX, int toX, int fromY, int toY)
{ {
@ -694,47 +853,246 @@ static bool UpdatePatch(float time, const CFluidPlaneCPURender::SPatchInfo& info
if (rippleInfos.empty()) if (rippleInfos.empty())
return true; return true;
CFluidPlaneCPURender::SHFieldSample heights[45][45];
u8 flags[9][9] = {};
ApplyTurbulence(time, heights, flags, sGlobalSineWave, info, fluidPane, areaCenter); ApplyTurbulence(time, heights, flags, sGlobalSineWave, info, fluidPane, areaCenter);
ApplyRipples(rippleInfos, heights, flags, sGlobalSineWave, info); ApplyRipples(rippleInfos, heights, flags, sGlobalSineWave, info);
if (info.x37_renderMode == CFluidPlaneCPURender::RenderMode::Normal) if (info.x37_normalMode == CFluidPlaneCPURender::NormalMode::NoNormals)
UpdatePatchNormal(heights, flags, info); UpdatePatchNoNormals(heights, flags, info);
else else
UpdatePatchSubdivided(heights, flags, info); UpdatePatchWithNormals(heights, flags, info);
return false; return false;
} }
static void RenderPatch(const CFluidPlaneCPURender::SPatchInfo& info, bool updateResult) static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFieldSample (&heights)[45][45],
const u8 (&flags)[9][9], int startYDiv,
const CFluidPlaneCPURender::SPatchInfo& info,
std::vector<CFluidPlaneShader::Vertex>& vOut)
{ {
} }
static void RenderPatch(const CFluidPlaneCPURender::SPatchInfo& info,
const CFluidPlaneCPURender::SHFieldSample (&heights)[45][45],
const u8 (&flags)[9][9], bool noRipples, bool flagIs1,
std::vector<CFluidPlaneShader::Vertex>& vOut)
{
if (noRipples)
{
float xMin = info.x4_localMin.x;
float yMin = info.x4_localMin.y;
float xMax = info.x18_rippleResolution * (info.x0_xSubdivs - 2) + xMin;
float yMax = info.x18_rippleResolution * (info.x1_ySubdivs - 2) + yMin;
switch (info.x37_normalMode)
{
case CFluidPlaneCPURender::NormalMode::None:
vOut.emplace_back(zeus::CVector3f(xMin, yMin, 0.f));
vOut.emplace_back(zeus::CVector3f(xMin, yMax, 0.f));
vOut.emplace_back(zeus::CVector3f(xMax, yMin, 0.f));
vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f));
break;
case CFluidPlaneCPURender::NormalMode::NoNormals:
vOut.emplace_back(zeus::CVector3f(xMin, yMin, 0.f), zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMin, yMax, 0.f), zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMin, 0.f), zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f), zeus::CColor::skBlack);
break;
case CFluidPlaneCPURender::NormalMode::Normals:
{
int yTiles = (info.x1_ySubdivs - 3) / CFluidPlaneCPURender::numSubdivisionsInTile + 1;
int xTiles = (info.x0_xSubdivs - 3) / CFluidPlaneCPURender::numSubdivisionsInTile + 1;
int xTileStart = info.x28_tileX + info.x2e_tileY * info.x2a_gridDimX;
for (int curYTile=yTiles ; curYTile>0 ; --curYTile,
yMax += info.x14_tileSize, xTileStart += info.x2a_gridDimX)
{
xMax = xMin;
int nextXTile;
for (int curXTile=0 ; curXTile<xTiles ; curXTile=nextXTile)
{
if (!info.x30_gridFlags || info.x30_gridFlags[xTileStart+curXTile])
{
if (curYTile == yTiles || curYTile == 1 || curXTile == 0 || xTiles - 1 == curXTile)
{
vOut.emplace_back(zeus::CVector3f(xMax + 0.5f * info.x14_tileSize,
yMax + 0.5f * info.x14_tileSize, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
float tmp = xMax;
for (int v=0 ; v<((curYTile == 1) ?
CFluidPlaneCPURender::numSubdivisionsInTile : 1) ; ++v)
{
vOut.emplace_back(zeus::CVector3f(tmp, yMax + info.x14_tileSize, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
tmp += info.x18_rippleResolution;
}
tmp = yMax + info.x14_tileSize;
for (int v=0 ; v<((xTiles - 1 == curXTile) ?
CFluidPlaneCPURender::numSubdivisionsInTile : 1) ; ++v)
{
vOut.emplace_back(zeus::CVector3f(xMax + info.x14_tileSize, tmp, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
tmp -= info.x18_rippleResolution;
}
tmp = xMax + info.x14_tileSize;
for (int v=0 ; v<((curYTile == yTiles) ?
CFluidPlaneCPURender::numSubdivisionsInTile : 1) ; ++v)
{
vOut.emplace_back(zeus::CVector3f(tmp, yMax, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
tmp -= info.x18_rippleResolution;
}
tmp = yMax;
for (int v=0 ; v<((curXTile == 0) ?
CFluidPlaneCPURender::numSubdivisionsInTile : 1) ; ++v)
{
vOut.emplace_back(zeus::CVector3f(xMax, tmp, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
tmp += info.x18_rippleResolution;
}
vOut.emplace_back(zeus::CVector3f(xMax, yMax + info.x14_tileSize, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
nextXTile = curXTile + 1;
xMax += info.x14_tileSize;
}
else
{
nextXTile = curXTile + 1;
while (nextXTile < xTiles - 1 &&
(!info.x30_gridFlags || info.x30_gridFlags[xTileStart+nextXTile]))
++nextXTile;
for (int v = 0 ; v < nextXTile - curXTile + 1 ; ++v)
{
vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f), zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMax + info.x14_tileSize, 0.f),
zeus::CColor::skBlack);
xMax += info.x14_tileSize;
}
++nextXTile;
if (nextXTile == xTiles)
{
--nextXTile;
xMax -= info.x14_tileSize;
}
}
}
else
{
nextXTile = curXTile + 1;
xMax += info.x14_tileSize;
while (nextXTile < xTiles && !info.x30_gridFlags[xTileStart+nextXTile])
{
xMax += info.x14_tileSize;
++nextXTile;
}
}
}
}
break;
}
case CFluidPlaneCPURender::NormalMode::NBT:
{
if (flagIs1 || !info.x30_gridFlags)
{
vOut.emplace_back(zeus::CVector3f(xMin, yMin, 0.f), zeus::CVector3f::skUp,
zeus::CVector3f::skForward, zeus::CVector3f::skRight, zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMin, yMax, 0.f), zeus::CVector3f::skUp,
zeus::CVector3f::skForward, zeus::CVector3f::skRight, zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMin, 0.f), zeus::CVector3f::skUp,
zeus::CVector3f::skForward, zeus::CVector3f::skRight, zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f), zeus::CVector3f::skUp,
zeus::CVector3f::skForward, zeus::CVector3f::skRight, zeus::CColor::skBlack);
}
else
{
int xTiles = (info.x0_xSubdivs - 3) / CFluidPlaneCPURender::numSubdivisionsInTile + 1;
int yTiles = (info.x1_ySubdivs - 3) / CFluidPlaneCPURender::numSubdivisionsInTile + 1;
int xTileStart = info.x28_tileX + info.x2e_tileY * info.x2a_gridDimX;
for (; yTiles>0 ; --yTiles, yMin += info.x14_tileSize, xTileStart += info.x2a_gridDimX)
{
xMax = xMin;
int nextXTile;
for (int curXTile=0 ; curXTile<xTiles ; curXTile=nextXTile)
{
if (info.x30_gridFlags[xTileStart+curXTile])
{
nextXTile = curXTile + 1;
int tile = xTileStart + nextXTile;
while (nextXTile < xTiles && info.x30_gridFlags[tile])
{
++nextXTile;
++tile;
}
for (int v = 0 ; v < nextXTile - curXTile + 1 ; ++v)
{
vOut.emplace_back(zeus::CVector3f(xMax, yMin, 0.f), zeus::CVector3f::skUp,
zeus::CVector3f::skForward, zeus::CVector3f::skRight,
zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMin + info.x14_tileSize, 0.f),
zeus::CVector3f::skUp, zeus::CVector3f::skForward,
zeus::CVector3f::skRight, zeus::CColor::skBlack);
xMax += info.x14_tileSize;
}
}
else
{
nextXTile = curXTile + 1;
xMax += info.x14_tileSize;
int tile = xTileStart + nextXTile;
while (nextXTile < xTiles && !info.x30_gridFlags[tile])
{
xMax += info.x14_tileSize;
++nextXTile;
++tile;
}
}
}
}
}
break;
}
}
}
else
{
float curY = info.x4_localMin.y;
for (int startYDiv=1 ; startYDiv<info.x1_ySubdivs-2 ;
startYDiv += CFluidPlaneCPURender::numSubdivisionsInTile, curY += info.x14_tileSize)
RenderStripWithRipples(curY, heights, flags, startYDiv, info, vOut);
}
}
void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf, void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
const zeus::CTransform& areaXf, bool noSubdiv, const zeus::CFrustum& frustum, const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum,
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId, const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const
{ {
TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(waterId); TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(waterId);
RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, areaXf, aabb, water.GetPtr()); RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, areaXf, aabb, water.GetPtr());
CFluidPlaneCPURender::RenderMode renderMode; CFluidPlaneCPURender::NormalMode normalMode;
if (xb0_bumpMap && kEnableWaterBumpMaps) if (xb0_bumpMap && kEnableWaterBumpMaps)
renderMode = CFluidPlaneCPURender::RenderMode::BumpMapped; normalMode = CFluidPlaneCPURender::NormalMode::NBT;
else if (!noSubdiv) else if (!noNormals)
renderMode = CFluidPlaneCPURender::RenderMode::Subdivided; normalMode = CFluidPlaneCPURender::NormalMode::Normals;
else else
renderMode = CFluidPlaneCPURender::RenderMode::Normal; normalMode = CFluidPlaneCPURender::NormalMode::NoNormals;
// Set Position and color format // Set Position and color format
switch (renderMode) switch (normalMode)
{ {
case CFluidPlaneCPURender::RenderMode::BumpMapped: case CFluidPlaneCPURender::NormalMode::NBT:
// Set NBT format // Set NBT format
break; break;
case CFluidPlaneCPURender::RenderMode::Subdivided: case CFluidPlaneCPURender::NormalMode::Normals:
// Set Normal format // Set Normal format
break; break;
default: default:
@ -751,22 +1109,23 @@ void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::C
zeus::CVector2f center2D(aabbCenter.x, aabbCenter.y); zeus::CVector2f center2D(aabbCenter.x, aabbCenter.y);
zeus::CVector2f ripplePitch(x108_rippleResolution * CFluidPlaneCPURender::numSubdivisionsInHField); zeus::CVector2f ripplePitch(x108_rippleResolution * CFluidPlaneCPURender::numSubdivisionsInHField);
bool r14 = false; // Amount to shift intensity values right (for added wavecap color)
int r22 = 0; int redShift = 0;
int r23 = 0; int greenShift = 0;
float rippleSideLen = g_tweakGame->GetRippleSideLengthNormal(); int blueShift = 0;
float wavecapIntensityScale = g_tweakGame->GetWavecapIntensityNormal();
switch (x44_fluidType) switch (x44_fluidType)
{ {
case EFluidType::PoisonWater: case EFluidType::PoisonWater:
rippleSideLen = g_tweakGame->GetRippleSideLengthPoison(); wavecapIntensityScale = g_tweakGame->GetWavecapIntensityPoison();
r14 = true; redShift = 1;
r23 = 1; blueShift = 1;
break; break;
case EFluidType::Lava: case EFluidType::Lava:
case EFluidType::Five: case EFluidType::Five:
rippleSideLen = g_tweakGame->GetRippleSideLengthLava(); wavecapIntensityScale = g_tweakGame->GetWavecapIntensityLava();
r23 = 8; blueShift = 8;
r22 = 8; greenShift = 8;
break; break;
default: default:
break; break;
@ -777,12 +1136,14 @@ void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::C
float cameraPenetration = float cameraPenetration =
mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation().dot(zeus::CVector3f::skUp) - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation().dot(zeus::CVector3f::skUp) -
water->GetTriggerBoundsWR().max.z; water->GetTriggerBoundsWR().max.z;
rippleSideLen *= (cameraPenetration >= 0.5f || cameraPenetration < 0.f) ? 1.f : 2.f * cameraPenetration; wavecapIntensityScale *= (cameraPenetration >= 0.5f || cameraPenetration < 0.f) ? 1.f : 2.f * cameraPenetration;
} }
u32 patchDimX = (water && water->GetPatchDimensionX()) ? water->GetPatchDimensionX() : 128; u32 patchDimX = (water && water->GetPatchDimensionX()) ? water->GetPatchDimensionX() : 128;
u32 patchDimY = (water && water->GetPatchDimensionY()) ? water->GetPatchDimensionY() : 128; u32 patchDimY = (water && water->GetPatchDimensionY()) ? water->GetPatchDimensionY() : 128;
m_verts.clear();
u32 tileY = 0; u32 tileY = 0;
float curY = aabb.min.y; float curY = aabb.min.y;
for (int i=0 ; curY < aabb.max.y && i<patchDimY ; ++i) for (int i=0 ; curY < aabb.max.y && i<patchDimY ; ++i)
@ -792,7 +1153,7 @@ void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::C
float _remDivsY = (aabb.max.y - curY) * rippleResolutionRecip; float _remDivsY = (aabb.max.y - curY) * rippleResolutionRecip;
for (int j=0 ; curX < aabb.max.x && j<patchDimX ; ++j) for (int j=0 ; curX < aabb.max.x && j<patchDimX ; ++j)
{ {
if (water->CanRenderPatch(j, i)) if (u8 renderFlags = water->GetPatchRenderFlags(j, i))
{ {
s16 remDivsX = std::min(s16((aabb.max.x - curX) * rippleResolutionRecip), s16 remDivsX = std::min(s16((aabb.max.x - curX) * rippleResolutionRecip),
s16(CFluidPlaneCPURender::numSubdivisionsInHField)); s16(CFluidPlaneCPURender::numSubdivisionsInHField));
@ -804,9 +1165,10 @@ void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::C
if (frustum.aabbFrustumTest(testaabb)) if (frustum.aabbFrustumTest(testaabb))
{ {
CFluidPlaneCPURender::SPatchInfo info(localMin, localMax, xf.origin, x108_rippleResolution, CFluidPlaneCPURender::SPatchInfo info(localMin, localMax, xf.origin, x108_rippleResolution,
rippleSideLen, x100_tileSize, x100_tileSize, wavecapIntensityScale,
CFluidPlaneCPURender::numSubdivisionsInHField, renderMode, CFluidPlaneCPURender::numSubdivisionsInHField, normalMode,
r14, r22, r23, tileX, gridDimX, gridDimY, tileY, gridFlags); redShift, greenShift, blueShift, tileX, gridDimX, gridDimY,
tileY, gridFlags);
int fromX = tileX != 0 ? (2 - CFluidPlaneCPURender::numSubdivisionsInTile) : 0; int fromX = tileX != 0 ? (2 - CFluidPlaneCPURender::numSubdivisionsInTile) : 0;
int toX; int toX;
@ -822,9 +1184,12 @@ void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::C
else else
toY = info.x1_ySubdivs; toY = info.x1_ySubdivs;
bool result = UpdatePatch(mgr.GetFluidPlaneManager()->GetUVT(), info, *this, areaCenter, CFluidPlaneCPURender::SHFieldSample heights[45][45];
rippleManager, fromX, toX, fromY, toY); u8 flags[9][9] = {};
RenderPatch(info, result);
bool noRipples = UpdatePatch(mgr.GetFluidPlaneManager()->GetUVT(), info, heights, flags,
*this, areaCenter, rippleManager, fromX, toX, fromY, toY);
RenderPatch(info, heights, flags, noRipples, renderFlags == 1, m_verts);
} }
} }
curX += ripplePitch.x; curX += ripplePitch.x;
@ -834,7 +1199,8 @@ void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::C
tileY += CFluidPlaneCPURender::numTilesInHField; tileY += CFluidPlaneCPURender::numTilesInHField;
} }
//m_shader->draw(setupInfo.texMtxs, setupInfo.normMtx, setupInfo.indScale, setupInfo.lights, setupInfo.kColors); m_shader->draw(setupInfo.texMtxs, setupInfo.normMtx, setupInfo.indScale,
setupInfo.lights, setupInfo.kColors, m_verts);
} }
void CFluidPlaneCPU::RenderCleanup() const void CFluidPlaneCPU::RenderCleanup() const

View File

@ -54,6 +54,8 @@ class CFluidPlaneCPU : public CFluidPlane
float x118_reflectionSize; float x118_reflectionSize;
float x11c_unitsPerLightmapTexel; float x11c_unitsPerLightmapTexel;
CTurbulence x120_turbulence; CTurbulence x120_turbulence;
mutable std::vector<CFluidPlaneShader::Vertex> m_verts;
mutable std::experimental::optional<CFluidPlaneShader> m_shader; mutable std::experimental::optional<CFluidPlaneShader> m_shader;
struct RenderSetupInfo struct RenderSetupInfo
@ -79,7 +81,7 @@ public:
const zeus::CTransform& areaXf, const zeus::CAABox& aabb, const zeus::CTransform& areaXf, const zeus::CAABox& aabb,
const CScriptWater* water) const; const CScriptWater* water) const;
void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf, void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
const zeus::CTransform& areaXf, bool noSubdiv, const zeus::CFrustum& frustum, const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum,
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId, const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const; const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const;
void RenderCleanup() const; void RenderCleanup() const;

View File

@ -100,9 +100,9 @@ void CScriptWater::SetupGrid(bool b)
for (int j=0 ; j<x2c4_gridDimX ; ++j) for (int j=0 ; j<x2c4_gridDimX ; ++j)
x2d8_gridFlags[i * x2c4_gridDimX + j] = true; x2d8_gridFlags[i * x2c4_gridDimX + j] = true;
if (!x2e0_patchFlags || x2d0_patchDimX != 0 || x2d4_patchDimY != 0) if (!x2e0_patchFlags || x2d0_patchDimX != 0 || x2d4_patchDimY != 0)
x2e0_patchFlags.reset(new bool[32]); x2e0_patchFlags.reset(new u8[32]);
for (int i=0 ; i<32 ; ++i) for (int i=0 ; i<32 ; ++i)
x2e0_patchFlags[i] = true; x2e0_patchFlags[i] = 1;
x2d4_patchDimY = 0; x2d4_patchDimY = 0;
x2d0_patchDimX = 0; x2d0_patchDimX = 0;
x2e8_28 = b; x2e8_28 = b;

View File

@ -58,7 +58,7 @@ private:
u32 x2d4_patchDimY = 0; u32 x2d4_patchDimY = 0;
std::unique_ptr<bool[]> x2d8_gridFlags; std::unique_ptr<bool[]> x2d8_gridFlags;
std::unique_ptr<bool[]> x2dc_; std::unique_ptr<bool[]> x2dc_;
std::unique_ptr<bool[]> x2e0_patchFlags; std::unique_ptr<u8[]> x2e0_patchFlags;
u32 x2e4_gridCellCount2 = 0; u32 x2e4_gridCellCount2 = 0;
union union
{ {
@ -123,7 +123,7 @@ public:
u16 GetVisorRunoffSfx() const { return x262_visorRunoffSfx; } u16 GetVisorRunoffSfx() const { return x262_visorRunoffSfx; }
const CScriptWater* GetNextConnectedWater(const CStateManager& mgr) const; const CScriptWater* GetNextConnectedWater(const CStateManager& mgr) const;
float GetLightmapDoubleBlendFactor() const { return x1f8_lightmapDoubleBlendFactor; } float GetLightmapDoubleBlendFactor() const { return x1f8_lightmapDoubleBlendFactor; }
bool CanRenderPatch(int x, int y) const { return x2e0_patchFlags[y * x2d0_patchDimX + x]; } u8 GetPatchRenderFlags(int x, int y) const { return x2e0_patchFlags[y * x2d0_patchDimX + x]; }
u32 GetPatchDimensionX() const { return x2d0_patchDimX; } u32 GetPatchDimensionX() const { return x2d0_patchDimX; }
u32 GetPatchDimensionY() const { return x2d4_patchDimY; } u32 GetPatchDimensionY() const { return x2d4_patchDimY; }
}; };