hsh pipelines for ThermalCold, ThermalHot, ElemenGen

Plus various fixes
This commit is contained in:
Luke Street 2020-10-02 18:58:57 -04:00
parent 485e0afb43
commit 6c56f6452e
16 changed files with 277 additions and 402 deletions

View File

@ -577,7 +577,8 @@ void CBooRenderer::ReallyRenderFogVolume(const zeus::CColor& color, const zeus::
} }
void CBooRenderer::GenerateFogVolumeRampTex() { void CBooRenderer::GenerateFogVolumeRampTex() {
x1b8_fogVolumeRamp = hsh::create_texture2d({FOGVOL_RAMP_RES, FOGVOL_RAMP_RES}, hsh::R16_UNORM, 1, [&](u16* data, std::size_t size) { x1b8_fogVolumeRamp = hsh::create_texture2d({FOGVOL_RAMP_RES, FOGVOL_RAMP_RES}, hsh::R16_UNORM, 1, [&](void* data, std::size_t size) {
auto* out = static_cast<u16*>(data);
for (size_t y = 0; y < FOGVOL_RAMP_RES; ++y) { for (size_t y = 0; y < FOGVOL_RAMP_RES; ++y) {
for (size_t x = 0; x < FOGVOL_RAMP_RES; ++x) { for (size_t x = 0; x < FOGVOL_RAMP_RES; ++x) {
const int tmp = int(y << 16 | x << 8 | 0x7f); const int tmp = int(y << 16 | x << 8 | 0x7f);
@ -586,19 +587,20 @@ void CBooRenderer::GenerateFogVolumeRampTex() {
(-150.0 / (tmp / double(0xffffff) * (FOGVOL_FAR - FOGVOL_NEAR) - FOGVOL_FAR) - FOGVOL_NEAR) * (-150.0 / (tmp / double(0xffffff) * (FOGVOL_FAR - FOGVOL_NEAR) - FOGVOL_FAR) - FOGVOL_NEAR) *
3.0 / (FOGVOL_FAR - FOGVOL_NEAR), 3.0 / (FOGVOL_FAR - FOGVOL_NEAR),
1.0); 1.0);
data[x + y * FOGVOL_RAMP_RES] = u16((a * a + a) / 2.0 * 65535); out[x + y * FOGVOL_RAMP_RES] = u16((a * a + a) / 2.0 * 65535);
} }
} }
}); });
} }
void CBooRenderer::GenerateSphereRampTex() { void CBooRenderer::GenerateSphereRampTex() {
x220_sphereRamp = hsh::create_texture2d({SPHERE_RAMP_RES, SPHERE_RAMP_RES}, hsh::R8_UNORM, 1, [&](u8* data, std::size_t size) { x220_sphereRamp = hsh::create_texture2d({SPHERE_RAMP_RES, SPHERE_RAMP_RES}, hsh::R8_UNORM, 1, [&](void* data, std::size_t size) {
auto* out = static_cast<u8*>(data);
constexpr float halfRes = SPHERE_RAMP_RES / 2.f; constexpr float halfRes = SPHERE_RAMP_RES / 2.f;
for (size_t y = 0; y < SPHERE_RAMP_RES; ++y) { for (size_t y = 0; y < SPHERE_RAMP_RES; ++y) {
for (size_t x = 0; x < SPHERE_RAMP_RES; ++x) { for (size_t x = 0; x < SPHERE_RAMP_RES; ++x) {
const zeus::CVector2f vec((float(x) - halfRes) / halfRes, (float(y) - halfRes) / halfRes); const zeus::CVector2f vec((float(x) - halfRes) / halfRes, (float(y) - halfRes) / halfRes);
data[x + y * SPHERE_RAMP_RES] = 255 - zeus::clamp(0.f, vec.canBeNormalized() ? vec.magnitude() : 0.f, 1.f) * 255; out[x + y * SPHERE_RAMP_RES] = 255 - zeus::clamp(0.f, vec.canBeNormalized() ? vec.magnitude() : 0.f, 1.f) * 255;
} }
} }
}); });
@ -647,8 +649,9 @@ hsh::texture2d CBooRenderer::GetColorTexture(const zeus::CColor& color) {
return search->second; return search->second;
} }
m_colorTextures.emplace(color, hsh::create_texture2d({1, 1}, hsh::RGBA8_UNORM, 1, [&](zeus::Comp8* data, std::size_t size) { m_colorTextures.emplace(color, hsh::create_texture2d({1, 1}, hsh::RGBA8_UNORM, 1, [&](void* data, std::size_t size) {
color.toRGBA8(data[0], data[1], data[2], data[3]); auto* out = static_cast<zeus::Comp8*>(data);
color.toRGBA8(out[0], out[1], out[2], out[3]);
})); }));
return m_colorTextures[color].get(); return m_colorTextures[color].get();
} }
@ -690,7 +693,7 @@ CBooRenderer::CBooRenderer(IObjectStore& store, IFactory& resFac)
GenerateFogVolumeRampTex(); GenerateFogVolumeRampTex();
GenerateSphereRampTex(); GenerateSphereRampTex();
m_ballShadowId = hsh::create_render_texture2d({m_ballShadowIdW, m_ballShadowIdH}, hsh::RGBA8_UNORM, 1, 0); m_ballShadowId = hsh::create_render_texture2d({skBallShadowIdSize, skBallShadowIdSize}, hsh::RGBA8_UNORM, 1, 0);
x14c_reflectionTex = hsh::create_render_texture2d({256, 256}, hsh::RGBA8_UNORM, 1, 0); x14c_reflectionTex = hsh::create_render_texture2d({256, 256}, hsh::RGBA8_UNORM, 1, 0);
GenerateScanLinesVBO(); GenerateScanLinesVBO();

View File

@ -289,15 +289,15 @@ public:
void ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, const CModel* model, void ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, const CModel* model,
const CSkinnedModel* sModel); const CSkinnedModel* sModel);
auto GetThermoPalette() const { return x288_thermoPalette.get(); } hsh::texture2d GetThermoPalette() const { return x288_thermoPalette; }
auto GetFogRampTex() const { return x1b8_fogVolumeRamp.get(); } hsh::texture2d GetFogRampTex() const { return x1b8_fogVolumeRamp.get(); }
auto GetRandomStaticEntropyTex() const { return m_staticEntropy->GetBooTexture(); } hsh::texture2d GetRandomStaticEntropyTex() const { return m_staticEntropy->GetBooTexture(); }
auto GetScanLinesEvenVBO() const { return m_scanLinesEvenVBO.get(); } auto GetScanLinesEvenVBO() const { return m_scanLinesEvenVBO.get(); }
auto GetScanLinesOddVBO() const { return m_scanLinesOddVBO.get(); } auto GetScanLinesOddVBO() const { return m_scanLinesOddVBO.get(); }
auto GetClearTexture() const { return m_clearTexture.get(); } hsh::texture2d GetClearTexture() const { return m_clearTexture.get(); }
auto GetBlackTexture() const { return m_blackTexture.get(); } hsh::texture2d GetBlackTexture() const { return m_blackTexture.get(); }
auto GetWhiteTexture() const { return m_whiteTexture.get(); } hsh::texture2d GetWhiteTexture() const { return m_whiteTexture.get(); }
hsh::texture2d GetColorTexture(const zeus::CColor& color); hsh::texture2d GetColorTexture(const zeus::CColor& color);

View File

@ -59,4 +59,7 @@ runtime_add_hsh(Graphics
Shaders/CColoredStripShader.cpp Shaders/CColoredStripShader.cpp
Shaders/CDecalShaders.cpp Shaders/CDecalShaders.cpp
Shaders/CEnergyBarShader.cpp Shaders/CEnergyBarShader.cpp
Shaders/CThermalColdFilter.cpp
Shaders/CThermalHotFilter.cpp
Shaders/CElementGenShaders.cpp
) )

View File

@ -12,12 +12,7 @@ CRainSplashGenerator::CRainSplashGenerator(const zeus::CVector3f& scale, u32 max
: x14_scale(scale), x2c_minZ(minZ) { : x14_scale(scale), x2c_minZ(minZ) {
x30_alpha = std::min(1.f, alpha); x30_alpha = std::min(1.f, alpha);
x44_genRate = std::min(maxSplashes, genRate); x44_genRate = std::min(maxSplashes, genRate);
x0_rainSplashes.reserve(maxSplashes); x0_rainSplashes.resize(maxSplashes);
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
for (u32 i = 0; i < maxSplashes; ++i)
x0_rainSplashes.emplace_back(ctx);
return true;
} BooTrace);
} }
void CRainSplashGenerator::SSplashLine::Draw(float alpha, float dt, const zeus::CVector3f& pos) { void CRainSplashGenerator::SSplashLine::Draw(float alpha, float dt, const zeus::CVector3f& pos) {
@ -73,13 +68,11 @@ void CRainSplashGenerator::Draw(const zeus::CTransform& xf) {
DoDraw(xf); DoDraw(xf);
} }
CRainSplashGenerator::SSplashLine::SSplashLine(boo::IGraphicsDataFactory::Context& ctx) CRainSplashGenerator::SSplashLine::SSplashLine()
: m_renderer(ctx, CLineRenderer::EPrimitiveMode::LineStrip, 3, nullptr, false) {} : m_renderer(CLineRenderer::EPrimitiveMode::LineStrip, 3, hsh::texture2d{}, false, hsh::LEqual) {}
CRainSplashGenerator::SRainSplash::SRainSplash(boo::IGraphicsDataFactory::Context& ctx) { CRainSplashGenerator::SRainSplash::SRainSplash() {
for (size_t i = 0; i < x0_lines.capacity(); ++i) { x0_lines.resize(x0_lines.capacity());
x0_lines.emplace_back(ctx);
}
} }
void CRainSplashGenerator::SSplashLine::Update(float dt, CStateManager& mgr) { void CRainSplashGenerator::SSplashLine::Update(float dt, CStateManager& mgr) {
@ -158,8 +151,7 @@ u32 CRainSplashGenerator::GetNextBestPt(u32 pt, const std::vector<std::pair<zeus
const auto idx = u32(rand.Range(0, int(vn.size() - 1))); const auto idx = u32(rand.Range(0, int(vn.size() - 1)));
const auto& vert = vn[idx]; const auto& vert = vn[idx];
const float distSq = (refVert.first - vert.first).magSquared(); const float distSq = (refVert.first - vert.first).magSquared();
if (distSq > maxDist && vert.second.dot(zeus::skUp) >= 0.f && if (distSq > maxDist && vert.second.dot(zeus::skUp) >= 0.f && (vert.first.z() <= 0.f || vert.first.z() > minZ)) {
(vert.first.z() <= 0.f || vert.first.z() > minZ)) {
nextPt = idx; nextPt = idx;
maxDist = distSq; maxDist = distSq;
} }

View File

@ -32,20 +32,20 @@ void CSkinnedModel::Calculate(const CPoseAsTransforms& pose, const CModelFlags&
const std::optional<CVertexMorphEffect>& morphEffect, const std::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes) { const float* morphMagnitudes) {
if (morphEffect || g_PointGenFunc) { if (morphEffect || g_PointGenFunc) {
if (auto vertBuf = m_modelInst->UpdateUniformData(drawFlags, nullptr, nullptr)) { if (auto* vertBuf = m_modelInst->UpdateUniformData(drawFlags, nullptr, nullptr)) {
x10_skinRules->TransformVerticesCPU(m_vertWorkspace, pose, *x4_model); x10_skinRules->TransformVerticesCPU(m_vertWorkspace, pose, *x4_model);
if (morphEffect) if (morphEffect)
morphEffect->MorphVertices(m_vertWorkspace, morphMagnitudes, x10_skinRules, pose); morphEffect->MorphVertices(m_vertWorkspace, morphMagnitudes, x10_skinRules, pose);
if (g_PointGenFunc) if (g_PointGenFunc)
g_PointGenFunc(g_PointGenCtx, m_vertWorkspace); g_PointGenFunc(g_PointGenCtx, m_vertWorkspace);
x4_model->ApplyVerticesCPU(vertBuf, m_vertWorkspace); x4_model->ApplyVerticesCPU(*vertBuf, m_vertWorkspace);
m_modifiedVBO = true; m_modifiedVBO = true;
} }
} else { } else {
if (auto vertBuf = if (auto* vertBuf =
m_modelInst->UpdateUniformData(drawFlags, x10_skinRules.GetObj(), &pose)) { m_modelInst->UpdateUniformData(drawFlags, x10_skinRules.GetObj(), &pose)) {
if (m_modifiedVBO) { if (m_modifiedVBO) {
x4_model->RestoreVerticesCPU(vertBuf); x4_model->RestoreVerticesCPU(*vertBuf);
m_modifiedVBO = false; m_modifiedVBO = false;
} }
} }

View File

@ -19,11 +19,13 @@ struct CAABoxShaderPipeline
this->color_out[0] = uniBuf->m_color; this->color_out[0] = uniBuf->m_color;
} }
}; };
template struct CAABoxShaderPipeline<ERglCullMode::None, ERglEnum::Always, true, ERglBlendMode::Blend, template struct CAABoxShaderPipeline<ERglCullMode::None, ERglEnum::LEqual, true, ERglBlendMode::Blend,
ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear, true>; ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear, true>;
constexpr size_t VertexCount = 34;
CAABoxShader::CAABoxShader(const zeus::CAABox& aabb) { CAABoxShader::CAABoxShader(const zeus::CAABox& aabb) {
const std::array<Vert, 34> verts{{ const std::array<Vert, VertexCount> verts{{
{{aabb.max.x(), aabb.max.y(), aabb.min.z()}}, {{aabb.max.x(), aabb.min.y(), aabb.min.z()}}, {{aabb.max.x(), aabb.max.y(), aabb.min.z()}}, {{aabb.max.x(), aabb.min.y(), aabb.min.z()}},
{{aabb.max.x(), aabb.max.y(), aabb.max.z()}}, {{aabb.max.x(), aabb.min.y(), aabb.max.z()}}, {{aabb.max.x(), aabb.max.y(), aabb.max.z()}}, {{aabb.max.x(), aabb.min.y(), aabb.max.z()}},
{{aabb.max.x(), aabb.min.y(), aabb.max.z()}}, {{aabb.max.x(), aabb.min.y(), aabb.max.z()}},
@ -62,7 +64,7 @@ void CAABoxShader::draw(const zeus::CColor& color) {
m_uniform.m_color = color; m_uniform.m_color = color;
m_uniBuf.load(m_uniform); m_uniBuf.load(m_uniform);
m_dataBind.draw(0, 34); m_dataBind.draw(0, VertexCount);
} }
} // namespace urde } // namespace urde

View File

@ -7,6 +7,8 @@ namespace urde {
class CCameraBlurFilter { class CCameraBlurFilter {
friend struct CCameraBlurFilterPipeline; friend struct CCameraBlurFilterPipeline;
public:
struct Vert { struct Vert {
hsh::float2 m_pos; hsh::float2 m_pos;
hsh::float2 m_uv; hsh::float2 m_uv;
@ -16,6 +18,7 @@ class CCameraBlurFilter {
float m_opacity = 1.f; float m_opacity = 1.f;
}; };
private:
hsh::dynamic_owner<hsh::vertex_buffer<Vert>> m_vbo; hsh::dynamic_owner<hsh::vertex_buffer<Vert>> m_vbo;
hsh::dynamic_owner<hsh::uniform_buffer<Uniform>> m_uniBuf; hsh::dynamic_owner<hsh::uniform_buffer<Uniform>> m_uniBuf;
hsh::binding m_dataBind; hsh::binding m_dataBind;

View File

@ -31,7 +31,7 @@ template struct CDecalShaderTexPipeline<false, false>;
template <bool Additive> template <bool Additive>
struct CDecalShaderNoTexPipeline : pipeline<std::conditional_t<Additive, AdditiveAttachment<>, BlendAttachment<>>, struct CDecalShaderNoTexPipeline : pipeline<std::conditional_t<Additive, AdditiveAttachment<>, BlendAttachment<>>,
depth_compare<hsh::LEqual>, depth_write<!Additive>> { depth_compare<hsh::LEqual>, depth_write<!Additive>> {
CDecalShaderNoTexPipeline(hsh::vertex_buffer<SParticleInstanceTex> vbo, CDecalShaderNoTexPipeline(hsh::vertex_buffer<SParticleInstanceNoTex> vbo,
hsh::uniform_buffer<SParticleUniforms> uniBuf) { hsh::uniform_buffer<SParticleUniforms> uniBuf) {
this->position = uniBuf->mvp * vbo->pos[this->vertex_id]; this->position = uniBuf->mvp * vbo->pos[this->vertex_id];
this->color_out[0] = vbo->color * uniBuf->moduColor; this->color_out[0] = vbo->color * uniBuf->moduColor;

View File

@ -1,274 +1,133 @@
#include "Runtime/Graphics/Shaders/CElementGenShaders.hpp" #include "Runtime/Graphics/Shaders/CElementGenShaders.hpp"
#include <iterator> #include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Graphics/CBooRenderer.hpp"
#include "Runtime/Particle/CElementGen.hpp" #include "Runtime/Particle/CElementGen.hpp"
#include <hecl/Pipeline.hpp> enum class BlendMode {
Regular,
Additive,
Subtract,
};
#include "CElementGenShaders.cpp.hshhead"
namespace urde { namespace urde {
using namespace hsh::pipeline;
void CElementGenShaders::Initialize() { template <BlendMode Mode, bool AlphaWrite>
m_texZTestZWrite = {hecl::conv->convert(Shader_CElementGenShaderTexZTestZWrite{}), struct BlendModeAttachmentExt {
hecl::conv->convert(Shader_CElementGenShaderTexZTestZWrite{})}; using type = BlendAttachment<AlphaWrite>;
m_texNoZTestZWrite = {hecl::conv->convert(Shader_CElementGenShaderTexNoZTestZWrite{}), };
hecl::conv->convert(Shader_CElementGenShaderTexNoZTestZWriteAWrite{})}; template <bool AlphaWrite>
m_texZTestNoZWrite = {hecl::conv->convert(Shader_CElementGenShaderTexZTestNoZWrite{}), struct BlendModeAttachmentExt<BlendMode::Additive, AlphaWrite> {
hecl::conv->convert(Shader_CElementGenShaderTexZTestNoZWriteAWrite{})}; using type = AdditiveAttachment<AlphaWrite>;
m_texNoZTestNoZWrite = {hecl::conv->convert(Shader_CElementGenShaderTexNoZTestNoZWrite{}), };
hecl::conv->convert(Shader_CElementGenShaderTexNoZTestNoZWriteAWrite{})}; template <bool AlphaWrite>
m_texAdditiveZTest = {hecl::conv->convert(Shader_CElementGenShaderTexAdditiveZTest{}), struct BlendModeAttachmentExt<BlendMode::Subtract, AlphaWrite> {
hecl::conv->convert(Shader_CElementGenShaderTexAdditiveZTestAWrite{})}; using type = SubtractAttachment<AlphaWrite>;
m_texAdditiveNoZTest = {hecl::conv->convert(Shader_CElementGenShaderTexAdditiveNoZTest{}), };
hecl::conv->convert(Shader_CElementGenShaderTexAdditiveNoZTestAWrite{})}; template <BlendMode Mode, bool AlphaWrite>
m_texRedToAlphaZTest = {hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaZTest{}), using BlendModeAttachment = typename BlendModeAttachmentExt<Mode, AlphaWrite>::type;
hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaZTestAWrite{})};
m_texRedToAlphaNoZTest = {hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaNoZTest{}),
hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaNoZTestAWrite{})};
m_texZTestNoZWriteSub = {hecl::conv->convert(Shader_CElementGenShaderTexZTestNoZWriteSub{}),
hecl::conv->convert(Shader_CElementGenShaderTexZTestNoZWriteSubAWrite{})};
m_texNoZTestNoZWriteSub = {hecl::conv->convert(Shader_CElementGenShaderTexNoZTestNoZWriteSub{}),
hecl::conv->convert(Shader_CElementGenShaderTexNoZTestNoZWriteSubAWrite{})};
m_texRedToAlphaZTestSub = {hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaZTestSub{}),
hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaZTestSubAWrite{})};
m_texRedToAlphaNoZTestSub = {hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaNoZTestSub{}),
hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaNoZTestSubAWrite{})};
m_indTexZWrite = {hecl::conv->convert(Shader_CElementGenShaderIndTexZWrite{}), template <BlendMode Mode, bool AlphaWrite, bool ZTest, bool ZWrite, bool RedToAlpha>
hecl::conv->convert(Shader_CElementGenShaderIndTexZWriteAWrite{})}; struct CElementGenShadersTexPipeline : pipeline<topology<hsh::TriangleStrip>, BlendModeAttachment<Mode, AlphaWrite>,
m_indTexNoZWrite = {hecl::conv->convert(Shader_CElementGenShaderIndTexNoZWrite{}), depth_compare<ZTest ? hsh::LEqual : hsh::Always>, depth_write<ZWrite>> {
hecl::conv->convert(Shader_CElementGenShaderIndTexNoZWriteAWrite{})}; CElementGenShadersTexPipeline(hsh::vertex_buffer<SParticleInstanceTex> vbo,
m_indTexAdditive = {hecl::conv->convert(Shader_CElementGenShaderIndTexAdditive{}), hsh::uniform_buffer<SParticleUniforms> uniBuf, hsh::texture2d tex) {
hecl::conv->convert(Shader_CElementGenShaderIndTexAdditiveAWrite{})}; this->position = uniBuf->mvp * vbo->pos[this->vertex_id];
this->color_out[0] = vbo->color * uniBuf->moduColor * tex.sample<float>(vbo->uvs[this->vertex_id]);
m_cindTexZWrite = {hecl::conv->convert(Shader_CElementGenShaderCindTexZWrite{}), if constexpr (RedToAlpha) {
hecl::conv->convert(Shader_CElementGenShaderCindTexZWriteAWrite{})}; this->color_out[0].w = this->color_out[0].x;
m_cindTexNoZWrite = {hecl::conv->convert(Shader_CElementGenShaderCindTexNoZWrite{}),
hecl::conv->convert(Shader_CElementGenShaderCindTexNoZWriteAWrite{})};
m_cindTexAdditive = {hecl::conv->convert(Shader_CElementGenShaderCindTexAdditive{}),
hecl::conv->convert(Shader_CElementGenShaderCindTexAdditiveAWrite{})};
m_noTexZTestZWrite = {hecl::conv->convert(Shader_CElementGenShaderNoTexZTestZWrite{}),
hecl::conv->convert(Shader_CElementGenShaderNoTexZTestZWriteAWrite{})};
m_noTexNoZTestZWrite = {hecl::conv->convert(Shader_CElementGenShaderNoTexNoZTestZWrite{}),
hecl::conv->convert(Shader_CElementGenShaderNoTexNoZTestZWriteAWrite{})};
m_noTexZTestNoZWrite = {hecl::conv->convert(Shader_CElementGenShaderNoTexZTestNoZWrite{}),
hecl::conv->convert(Shader_CElementGenShaderNoTexZTestNoZWriteAWrite{})};
m_noTexNoZTestNoZWrite = {hecl::conv->convert(Shader_CElementGenShaderNoTexNoZTestNoZWrite{}),
hecl::conv->convert(Shader_CElementGenShaderNoTexNoZTestNoZWriteAWrite{})};
m_noTexAdditiveZTest = {hecl::conv->convert(Shader_CElementGenShaderNoTexAdditiveZTest{}),
hecl::conv->convert(Shader_CElementGenShaderNoTexAdditiveZTestAWrite{})};
m_noTexAdditiveNoZTest = {hecl::conv->convert(Shader_CElementGenShaderNoTexAdditiveNoZTest{}),
hecl::conv->convert(Shader_CElementGenShaderNoTexAdditiveNoZTestAWrite{})};
} }
void CElementGenShaders::Shutdown() {
for (auto& s : m_texZTestZWrite) s.reset();
for (auto& s : m_texNoZTestZWrite) s.reset();
for (auto& s : m_texZTestNoZWrite) s.reset();
for (auto& s : m_texNoZTestNoZWrite) s.reset();
for (auto& s : m_texAdditiveZTest) s.reset();
for (auto& s : m_texAdditiveNoZTest) s.reset();
for (auto& s : m_texRedToAlphaZTest) s.reset();
for (auto& s : m_texRedToAlphaNoZTest) s.reset();
for (auto& s : m_texZTestNoZWriteSub) s.reset();
for (auto& s : m_texNoZTestNoZWriteSub) s.reset();
for (auto& s : m_texRedToAlphaZTestSub) s.reset();
for (auto& s : m_texRedToAlphaNoZTestSub) s.reset();
for (auto& s : m_indTexZWrite) s.reset();
for (auto& s : m_indTexNoZWrite) s.reset();
for (auto& s : m_indTexAdditive) s.reset();
for (auto& s : m_cindTexZWrite) s.reset();
for (auto& s : m_cindTexNoZWrite) s.reset();
for (auto& s : m_cindTexAdditive) s.reset();
for (auto& s : m_noTexZTestZWrite) s.reset();
for (auto& s : m_noTexNoZTestZWrite) s.reset();
for (auto& s : m_noTexZTestNoZWrite) s.reset();
for (auto& s : m_noTexNoZTestNoZWrite) s.reset();
for (auto& s : m_noTexAdditiveZTest) s.reset();
for (auto& s : m_noTexAdditiveNoZTest) s.reset();
} }
};
template struct CElementGenShadersTexPipeline<BlendMode::Regular, true, true, true, false>;
template struct CElementGenShadersTexPipeline<BlendMode::Additive, true, true, true, true>;
template struct CElementGenShadersTexPipeline<BlendMode::Subtract, true, true, true, true>;
template <BlendMode Mode, bool AlphaWrite, bool ZTest, bool ZWrite, bool ColoredIndirect>
struct CElementGenShadersIndTexPipeline
: pipeline<topology<hsh::TriangleStrip>, BlendModeAttachment<Mode, AlphaWrite>,
depth_compare<ZTest ? hsh::LEqual : hsh::Always>, depth_write<ZWrite>> {
CElementGenShadersIndTexPipeline(hsh::vertex_buffer<SParticleInstanceIndTex> vbo,
hsh::uniform_buffer<SParticleUniforms> uniBuf, hsh::texture2d texrTex,
hsh::texture2d tindTex, hsh::render_texture2d sceneTex) {
this->position = uniBuf->mvp * vbo->pos[this->vertex_id];
hsh::float4 texrTexel = texrTex.sample<float>(vbo->texrTindUVs[this->vertex_id].xy());
hsh::float2 tindTexel = tindTex.sample<float>(vbo->texrTindUVs[this->vertex_id].zw()).xy();
hsh::float4 sceneTexel = sceneTex.sample<float>(hsh::lerp(vbo->sceneUVs.xy(), vbo->sceneUVs.zw(), tindTexel));
if constexpr (ColoredIndirect) {
this->color_out[0] = vbo->color * hsh::float4(sceneTexel.xyz(), 1.f) * texrTexel;
} else {
this->color_out[0] = vbo->color * hsh::float4(sceneTexel.xyz(), 1.f) + texrTexel;
this->color_out[0].w *= texrTexel.x;
}
}
};
template struct CElementGenShadersIndTexPipeline<BlendMode::Regular, true, true, true, true>;
template struct CElementGenShadersIndTexPipeline<BlendMode::Additive, true, true, true, false>;
template <BlendMode Mode, bool AlphaWrite, bool ZTest, bool ZWrite>
struct CElementGenShadersNoTexPipeline
: pipeline<topology<hsh::TriangleStrip>, BlendModeAttachment<Mode, AlphaWrite>,
depth_compare<ZTest ? hsh::LEqual : hsh::Always>, depth_write<ZWrite>> {
CElementGenShadersNoTexPipeline(hsh::vertex_buffer<SParticleInstanceNoTex> vbo,
hsh::uniform_buffer<SParticleUniforms> uniBuf) {
this->position = uniBuf->mvp * vbo->pos[this->vertex_id];
this->color_out[0] = vbo->color * uniBuf->moduColor;
}
};
template struct CElementGenShadersNoTexPipeline<BlendMode::Regular, true, true, true>;
template struct CElementGenShadersNoTexPipeline<BlendMode::Additive, true, true, true>;
template struct CElementGenShadersNoTexPipeline<BlendMode::Subtract, true, true, true>;
CElementGenShaders::EShaderClass CElementGenShaders::GetShaderClass(CElementGen& gen) { CElementGenShaders::EShaderClass CElementGenShaders::GetShaderClass(CElementGen& gen) {
CGenDescription* desc = gen.x1c_genDesc.GetObj(); const auto* desc = gen.x1c_genDesc.GetObj();
if (desc->x54_x40_TEXR) { if (desc->x54_x40_TEXR) {
if (desc->x58_x44_TIND) if (desc->x58_x44_TIND) {
return EShaderClass::IndTex; return EShaderClass::IndTex;
else }
return EShaderClass::Tex; return EShaderClass::Tex;
} else }
return EShaderClass::NoTex; return EShaderClass::NoTex;
} }
void CElementGenShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CElementGen& gen) { hsh::binding& CElementGenShaders::BuildShaderDataBinding(CElementGen& gen, bool pmus) {
CGenDescription* desc = gen.x1c_genDesc.GetObj(); const auto& desc = gen.x1c_genDesc;
std::array<boo::ObjToken<boo::IShaderPipeline>, 2>* regPipeline = nullptr; BlendMode mode = BlendMode::Regular;
std::array<boo::ObjToken<boo::IShaderPipeline>, 2>* regPipelineSub = nullptr; if (CElementGen::g_subtractBlend) {
std::array<boo::ObjToken<boo::IShaderPipeline>, 2>* redToAlphaPipeline = nullptr; mode = BlendMode::Subtract;
std::array<boo::ObjToken<boo::IShaderPipeline>, 2>* redToAlphaPipelineSub = nullptr; } else if (gen.x26c_26_AAPH) {
std::array<boo::ObjToken<boo::IShaderPipeline>, 2>* regPipelinePmus = nullptr; mode = BlendMode::Additive;
std::array<boo::ObjToken<boo::IShaderPipeline>, 2>* redToAlphaPipelinePmus = nullptr;
if (desc->x54_x40_TEXR) {
if (desc->x58_x44_TIND) {
if (desc->x45_30_x32_24_CIND) {
if (gen.x26c_26_AAPH)
regPipeline = &m_cindTexAdditive;
else {
if (gen.x26c_27_ZBUF)
regPipeline = &m_cindTexZWrite;
else
regPipeline = &m_cindTexNoZWrite;
}
} else {
if (gen.x26c_26_AAPH)
regPipeline = &m_indTexAdditive;
else {
if (gen.x26c_27_ZBUF)
regPipeline = &m_indTexZWrite;
else
regPipeline = &m_indTexNoZWrite;
}
}
} else {
if (gen.x26c_28_zTest) {
redToAlphaPipeline = &m_texRedToAlphaZTest;
regPipelineSub = &m_texZTestNoZWriteSub;
redToAlphaPipelineSub = &m_texRedToAlphaZTestSub;
} else {
redToAlphaPipeline = &m_texRedToAlphaNoZTest;
regPipelineSub = &m_texNoZTestNoZWriteSub;
redToAlphaPipelineSub = &m_texRedToAlphaNoZTestSub;
}
if (gen.x26c_26_AAPH) {
if (gen.x26c_28_zTest)
regPipeline = &m_texAdditiveZTest;
else
regPipeline = &m_texAdditiveNoZTest;
} else {
if (gen.x26c_28_zTest) {
if (gen.x26c_27_ZBUF)
regPipeline = &m_texZTestZWrite;
else
regPipeline = &m_texZTestNoZWrite;
} else {
if (gen.x26c_27_ZBUF)
regPipeline = &m_texNoZTestZWrite;
else
regPipeline = &m_texNoZTestNoZWrite;
}
}
}
} else {
if (gen.x26c_26_AAPH) {
if (gen.x26c_28_zTest)
regPipeline = &m_noTexAdditiveZTest;
else
regPipeline = &m_noTexAdditiveNoZTest;
} else {
if (gen.x26c_28_zTest) {
if (gen.x26c_27_ZBUF)
regPipeline = &m_noTexZTestZWrite;
else
regPipeline = &m_noTexZTestNoZWrite;
} else {
if (gen.x26c_27_ZBUF)
regPipeline = &m_noTexNoZTestZWrite;
else
regPipeline = &m_noTexNoZTestNoZWrite;
}
}
}
if (desc->x45_24_x31_26_PMUS) {
if (desc->x54_x40_TEXR) {
redToAlphaPipelinePmus = &m_texRedToAlphaZTest;
if (desc->x44_31_x31_25_PMAB)
regPipelinePmus = &m_texAdditiveZTest;
else
regPipelinePmus = &m_texZTestZWrite;
} else {
if (desc->x44_31_x31_25_PMAB)
regPipelinePmus = &m_noTexAdditiveZTest;
else
regPipelinePmus = &m_noTexZTestZWrite;
}
}
const CUVElement* const texr = desc->x54_x40_TEXR.get();
const CUVElement* const tind = desc->x58_x44_TIND.get();
int texCount = 0;
std::array<boo::ObjToken<boo::ITexture>, 3> textures;
if (texr) {
textures[0] = texr->GetValueTexture(0).GetObj()->GetBooTexture();
texCount = 1;
if (gen.m_instBuf) {
if (tind) {
textures[1] = CGraphics::g_SpareTexture.get();
textures[2] = tind->GetValueTexture(0).GetObj()->GetBooTexture();
texCount = 3;
}
}
}
if (gen.m_instBuf) {
const std::array<boo::ObjToken<boo::IGraphicsBuffer>, 1> uniforms{gen.m_uniformBuf.get()};
if (regPipeline != nullptr) {
for (size_t i = 0; i < gen.m_normalDataBind.size(); ++i) {
gen.m_normalDataBind[i] =
ctx.newShaderDataBinding((*regPipeline)[i], nullptr, gen.m_instBuf.get(), nullptr, uniforms.size(),
uniforms.data(), nullptr, texCount, textures.data(), nullptr, nullptr);
}
}
if (regPipelineSub != nullptr) {
for (size_t i = 0; i < gen.m_normalSubDataBind.size(); ++i) {
gen.m_normalSubDataBind[i] =
ctx.newShaderDataBinding((*regPipelineSub)[i], nullptr, gen.m_instBuf.get(), nullptr, uniforms.size(),
uniforms.data(), nullptr, texCount, textures.data(), nullptr, nullptr);
}
}
if (redToAlphaPipeline != nullptr) {
for (size_t i = 0; i < gen.m_redToAlphaDataBind.size(); ++i) {
gen.m_redToAlphaDataBind[i] =
ctx.newShaderDataBinding((*redToAlphaPipeline)[i], nullptr, gen.m_instBuf.get(), nullptr, uniforms.size(),
uniforms.data(), nullptr, texCount, textures.data(), nullptr, nullptr);
}
}
if (redToAlphaPipelineSub != nullptr) {
for (size_t i = 0; i < gen.m_redToAlphaSubDataBind.size(); ++i) {
gen.m_redToAlphaSubDataBind[i] = ctx.newShaderDataBinding(
(*redToAlphaPipelineSub)[i], nullptr, gen.m_instBuf.get(), nullptr, uniforms.size(), uniforms.data(),
nullptr, texCount, textures.data(), nullptr, nullptr);
}
}
}
if (gen.m_instBufPmus) {
const std::array<boo::ObjToken<boo::IGraphicsBuffer>, 1> uniforms{gen.m_uniformBufPmus.get()};
texCount = std::min(texCount, 1);
if (regPipelinePmus != nullptr) {
for (size_t i = 0; i < gen.m_normalDataBindPmus.size(); ++i) {
gen.m_normalDataBindPmus[i] =
ctx.newShaderDataBinding((*regPipelinePmus)[i], nullptr, gen.m_instBufPmus.get(), nullptr, uniforms.size(),
uniforms.data(), nullptr, texCount, textures.data(), nullptr, nullptr);
}
}
if (redToAlphaPipelinePmus != nullptr) {
for (size_t i = 0; i < gen.m_redToAlphaDataBindPmus.size(); ++i) {
gen.m_redToAlphaDataBindPmus[i] = ctx.newShaderDataBinding(
(*redToAlphaPipelinePmus)[i], nullptr, gen.m_instBufPmus.get(), nullptr, uniforms.size(), uniforms.data(),
nullptr, texCount, textures.data(), nullptr, nullptr);
} }
hsh::vertex_buffer_typeless instBuf = pmus ? gen.m_instBufPmus.get() : gen.m_instBuf.get();
hsh::uniform_buffer_typeless uniBuf = pmus ? gen.m_uniformBufPmus.get() : gen.m_uniformBuf.get();
switch (GetShaderClass(gen)) {
case EShaderClass::Tex: {
hsh::texture2d tex = desc->x54_x40_TEXR->GetValueTexture(0)->GetBooTexture();
m_shaderBind.hsh_tex_bind(
CElementGenShadersTexPipeline<mode, g_Renderer->IsThermalVisorHotPass(), gen.x26c_28_zTest, gen.x26c_27_ZBUF,
CElementGen::sMoveRedToAlphaBuffer>(instBuf, uniBuf, tex));
break;
}
case EShaderClass::IndTex: {
hsh::texture2d texrTex = desc->x54_x40_TEXR->GetValueTexture(0)->GetBooTexture();
hsh::texture2d tindTex = desc->x58_x44_TIND->GetValueTexture(0)->GetBooTexture();
hsh::render_texture2d sceneTex = CGraphics::g_SpareTexture.get_color(0);
m_shaderBind.hsh_indtex_bind(
CElementGenShadersIndTexPipeline<mode, g_Renderer->IsThermalVisorHotPass(), gen.x26c_28_zTest, gen.x26c_27_ZBUF,
desc->x45_30_x32_24_CIND>(instBuf, uniBuf, texrTex, tindTex, sceneTex));
break;
}
case EShaderClass::NoTex: {
m_shaderBind.hsh_notex_bind(
CElementGenShadersNoTexPipeline<mode, g_Renderer->IsThermalVisorHotPass(), gen.x26c_28_zTest, gen.x26c_27_ZBUF>(
instBuf, uniBuf));
break;
} }
} }
return m_shaderBind;
} }
} // namespace urde } // namespace urde

View File

@ -8,11 +8,12 @@ class CElementGen;
class CElementGenShaders { class CElementGenShaders {
hsh::binding m_shaderBind; hsh::binding m_shaderBind;
public: public:
enum class EShaderClass { Tex, IndTex, NoTex }; enum class EShaderClass { Tex, IndTex, NoTex };
static EShaderClass GetShaderClass(CElementGen& gen); static EShaderClass GetShaderClass(CElementGen& gen);
hsh::binding& BuildShaderDataBinding(CElementGen& gen); hsh::binding& BuildShaderDataBinding(CElementGen& gen, bool pmus);
}; };
} // namespace urde } // namespace urde

View File

@ -4,31 +4,54 @@
#include "Runtime/Graphics/CBooRenderer.hpp" #include "Runtime/Graphics/CBooRenderer.hpp"
#include "Runtime/Graphics/CGraphics.hpp" #include "Runtime/Graphics/CGraphics.hpp"
#include "zeus/CVector2f.hpp" #include "CThermalColdFilter.cpp.hshhead"
namespace urde { namespace urde {
using namespace hsh::pipeline;
struct CThermalColdFilterPipeline : pipeline<topology<hsh::TriangleStrip>,
ERglBlendModeAttachment<ERglBlendMode::Blend, ERglBlendFactor::One,
ERglBlendFactor::Zero, ERglLogicOp::Clear, true>,
depth_write<false>> {
CThermalColdFilterPipeline(hsh::vertex_buffer<CThermalColdFilter::Vert> vbo,
hsh::uniform_buffer<CThermalColdFilter::Uniform> ubo, hsh::render_texture2d sceneTex,
hsh::texture2d noiseTex) {
static hsh::float4 kRGBToYPrime = {0.257f, 0.504f, 0.098f, 0.f};
this->position = hsh::float4(vbo->m_pos, 0.f, 1.f);
hsh::float4 noiseTexel = noiseTex.read<float>(Lookup8BPP(vbo->m_uvNoise, ubo->m_randOff));
hsh::float2 indCoord = (hsh::float3x3(ubo->m_indMtx[0].xyz(), ubo->m_indMtx[1].xyz(), ubo->m_indMtx[2].xyz()) *
hsh::float3(noiseTexel.x - 0.5f, noiseTexel.w - 0.5f, 1.f))
.xy();
hsh::float2 sceneUv = vbo->m_uv + indCoord;
sceneUv.y = 1.f - sceneUv.y;
float indScene = hsh::dot(sceneTex.sample<float>(sceneUv), kRGBToYPrime) + 16.f / 255.f;
this->color_out[0] = ubo->m_colorRegs[0] * indScene + ubo->m_colorRegs[2] - ubo->m_colorRegs[1] * noiseTexel.x;
this->color_out[0].w = ubo->m_colorRegs[1].x + ubo->m_colorRegs[1].w * noiseTexel.x + ubo->m_colorRegs[2].w;
}
static constexpr hsh::uint2 Lookup8BPP(hsh::float2 uv, float randOff) {
int bx = int(uv.x) >> 3;
int rx = int(uv.x) & 0x7;
int by = int(uv.y) >> 2;
int ry = int(uv.y) & 0x3;
int bidx = by * 128 + bx;
int addr = bidx * 32 + ry * 8 + rx + int(randOff);
return hsh::uint2(addr & 0x3ff, addr >> 10);
}
};
CThermalColdFilter::CThermalColdFilter() { CThermalColdFilter::CThermalColdFilter() {
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
const std::array<Vert, 4> verts{{ const std::array<Vert, 4> verts{{
{{-1.f, -1.f}, {0.f, 0.f}, {0.f, 0.f}}, {{-1.f, -1.f}, {0.f, 0.f}, {0.f, 0.f}},
{{-1.f, 1.f}, {0.f, 1.f}, {0.f, 448.f}}, {{-1.f, 1.f}, {0.f, 1.f}, {0.f, 448.f}},
{{1.f, -1.f}, {1.f, 0.f}, {640.f, 0.f}}, {{1.f, -1.f}, {1.f, 0.f}, {640.f, 0.f}},
{{1.f, 1.f}, {1.f, 1.f}, {640.f, 448.f}}, {{1.f, 1.f}, {1.f, 1.f}, {640.f, 448.f}},
}}; }};
m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts.data(), 48, verts.size()); m_vbo = hsh::create_vertex_buffer(verts);
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); m_uniBuf = hsh::create_dynamic_uniform_buffer<Uniform>();
m_dataBind.hsh_bind(CThermalColdFilterPipeline(m_vbo.get(), m_uniBuf.get(), CGraphics::g_SpareTexture.get_color(0),
const std::array<boo::ObjToken<boo::IGraphicsBuffer>, 1> bufs{m_uniBuf.get()}; g_Renderer->GetRandomStaticEntropyTex()));
constexpr std::array<boo::PipelineStage, 1> stages{boo::PipelineStage::Vertex};
const std::array<boo::ObjToken<boo::ITexture>, 2> texs{
CGraphics::g_SpareTexture.get(),
g_Renderer->GetRandomStaticEntropyTex(),
};
m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, bufs.size(), bufs.data(),
stages.data(), nullptr, nullptr, texs.size(), texs.data(), nullptr, nullptr);
return true;
} BooTrace);
setNoiseOffset(0); setNoiseOffset(0);
setScale(0.f); setScale(0.f);
@ -38,9 +61,8 @@ void CThermalColdFilter::draw() {
SCOPED_GRAPHICS_DEBUG_GROUP("CThermalColdFilter::draw", zeus::skMagenta); SCOPED_GRAPHICS_DEBUG_GROUP("CThermalColdFilter::draw", zeus::skMagenta);
CGraphics::ResolveSpareTexture(CGraphics::g_CroppedViewport); CGraphics::ResolveSpareTexture(CGraphics::g_CroppedViewport);
m_uniBuf->load(&m_uniform, sizeof(m_uniform)); m_uniBuf.load(m_uniform);
CGraphics::SetShaderDataBinding(m_dataBind); m_dataBind.draw(0, 4);
CGraphics::DrawArray(0, 4);
} }
} // namespace urde } // namespace urde

View File

@ -8,20 +8,23 @@
namespace urde { namespace urde {
class CThermalColdFilter { class CThermalColdFilter {
public:
struct Uniform { struct Uniform {
zeus::CMatrix4f m_indMtx; hsh::float4x4 m_indMtx;
std::array<zeus::CColor, 3> m_colorRegs; std::array<hsh::float4, 3> m_colorRegs;
float m_randOff = 0.f; float m_randOff = 0.f;
}; };
struct Vert { struct Vert {
zeus::CVector2f m_pos; hsh::float2 m_pos;
zeus::CVector2f m_uv; hsh::float2 m_uv;
zeus::CVector2f m_uvNoise; hsh::float2 m_uvNoise;
}; };
private:
hsh::owner<hsh::vertex_buffer<Vert>> m_vbo; hsh::owner<hsh::vertex_buffer<Vert>> m_vbo;
hsh::dynamic_owner<hsh::uniform_buffer<Uniform>> m_uniBuf; hsh::dynamic_owner<hsh::uniform_buffer<Uniform>> m_uniBuf;
hsh::binding m_dataBind; hsh::binding m_dataBind;
Uniform m_uniform; Uniform m_uniform{};
public: public:
CThermalColdFilter(); CThermalColdFilter();

View File

@ -4,42 +4,49 @@
#include "Runtime/Graphics/CBooRenderer.hpp" #include "Runtime/Graphics/CBooRenderer.hpp"
#include "Runtime/Graphics/CGraphics.hpp" #include "Runtime/Graphics/CGraphics.hpp"
#include "zeus/CVector2f.hpp" #include "CThermalHotFilter.cpp.hshhead"
namespace urde { namespace urde {
using namespace hsh::pipeline;
struct CThermalHotFilterPipeline
: pipeline<ERglBlendModeAttachment<ERglBlendMode::Blend, ERglBlendFactor::DstAlpha, ERglBlendFactor::InvDstAlpha,
ERglLogicOp::Clear, true>,
depth_write<false>> {
CThermalHotFilterPipeline(hsh::vertex_buffer<CThermalHotFilter::Vert> vbo,
hsh::uniform_buffer<CThermalHotFilter::Uniform> ubo, hsh::render_texture2d sceneTex,
hsh::texture2d paletteTex) {
static hsh::float4 kRGBToYPrime = {0.257f, 0.504f, 0.098f, 0.f};
this->position = hsh::float4(vbo->m_pos, 0.f, 1.f);
hsh::float2 sceneUv = vbo->m_uv;
sceneUv.y = 1.f - sceneUv.y;
float sceneSample = hsh::dot(sceneTex.sample<float>(sceneUv), kRGBToYPrime) + 16.f / 255.f;
hsh::float4 colorSample = paletteTex.sample<float>(hsh::float2(sceneSample / 16.f, 0.5f));
this->color_out[0] = hsh::float4(colorSample.xyz(), 0.f);
}
};
CThermalHotFilter::CThermalHotFilter() { CThermalHotFilter::CThermalHotFilter() {
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
const std::array<Vert, 4> verts{{ const std::array<Vert, 4> verts{{
{{-1.0, -1.0}, {0.0, 0.0}}, {{-1.0, -1.0}, {0.0, 0.0}},
{{-1.0, 1.0}, {0.0, 1.0}}, {{-1.0, 1.0}, {0.0, 1.0}},
{{1.0, -1.0}, {1.0, 0.0}}, {{1.0, -1.0}, {1.0, 0.0}},
{{1.0, 1.0}, {1.0, 1.0}}, {{1.0, 1.0}, {1.0, 1.0}},
}}; }};
m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts.data(), 32, verts.size()); m_vbo = hsh::create_vertex_buffer(verts);
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); m_uniBuf = hsh::create_dynamic_uniform_buffer<Uniform>();
m_dataBind.hsh_bind(CThermalHotFilterPipeline(m_vbo.get(), m_uniBuf.get(), CGraphics::g_SpareTexture.get_color(0),
const std::array<boo::ObjToken<boo::IGraphicsBuffer>, 1> bufs{m_uniBuf.get()}; g_Renderer->GetThermoPalette()));
constexpr std::array<boo::PipelineStage, 1> stages{boo::PipelineStage::Vertex};
const std::array<boo::ObjToken<boo::ITexture>, 2> texs{
CGraphics::g_SpareTexture.get(),
g_Renderer->GetThermoPalette(),
};
m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, bufs.size(), bufs.data(),
stages.data(), nullptr, nullptr, texs.size(), texs.data(), nullptr, nullptr);
return true;
} BooTrace);
} }
void CThermalHotFilter::draw() { void CThermalHotFilter::draw() {
SCOPED_GRAPHICS_DEBUG_GROUP("CThermalHotFilter::draw", zeus::skMagenta); SCOPED_GRAPHICS_DEBUG_GROUP("CThermalHotFilter::draw", zeus::skMagenta);
CGraphics::ResolveSpareTexture(CGraphics::g_CroppedViewport); CGraphics::ResolveSpareTexture(CGraphics::g_CroppedViewport);
m_uniBuf.load(m_uniform);
// m_uniBuf->load(&m_uniform, sizeof(m_uniform)); m_dataBind.draw(0, 4);
CGraphics::SetShaderDataBinding(m_dataBind);
CGraphics::DrawArray(0, 4);
} }
} // namespace urde } // namespace urde

View File

@ -2,22 +2,26 @@
#include <array> #include <array>
#include "hsh/hsh.h"
#include "zeus/CColor.hpp" #include "zeus/CColor.hpp"
namespace urde { namespace urde {
class CThermalHotFilter { class CThermalHotFilter {
public:
struct Uniform { struct Uniform {
std::array<zeus::CColor, 3> m_colorRegs; std::array<hsh::float4, 3> m_colorRegs;
}; };
struct Vert { struct Vert {
zeus::CVector2f m_pos; hsh::float2 m_pos;
zeus::CVector2f m_uv; hsh::float2 m_uv;
}; };
private:
hsh::owner<hsh::vertex_buffer<Vert>> m_vbo; hsh::owner<hsh::vertex_buffer<Vert>> m_vbo;
hsh::dynamic_owner<hsh::uniform_buffer<Uniform>> m_uniBuf; hsh::dynamic_owner<hsh::uniform_buffer<Uniform>> m_uniBuf;
hsh::binding m_dataBind; hsh::binding m_dataBind;
Uniform m_uniform; Uniform m_uniform{};
public: public:
CThermalHotFilter(); CThermalHotFilter();

View File

@ -200,8 +200,8 @@ void CGuiFrame::ProcessUserInput(const CFinalInput& input) const {
bool CGuiFrame::ProcessMouseInput(const CFinalInput& input, const CGuiWidgetDrawParms& parms) { bool CGuiFrame::ProcessMouseInput(const CFinalInput& input, const CGuiWidgetDrawParms& parms) {
if (const auto& kbm = input.GetKBM()) { if (const auto& kbm = input.GetKBM()) {
zeus::CVector2f point(kbm->m_mouseCoord.norm[0] * 2.f - 1.f, zeus::CVector2f point(kbm->m_mouseCoord.x * 2.f - 1.f,
kbm->m_mouseCoord.norm[1] * 2.f - 1.f); kbm->m_mouseCoord.y * 2.f - 1.f);
CGuiWidget* hit = BestCursorHit(point, parms); CGuiWidget* hit = BestCursorHit(point, parms);
if (hit != m_lastMouseOverWidget) { if (hit != m_lastMouseOverWidget) {
if (m_inMouseDown && m_mouseDownWidget != hit) { if (m_inMouseDown && m_mouseDownWidget != hit) {
@ -220,14 +220,14 @@ bool CGuiFrame::ProcessMouseInput(const CFinalInput& input, const CGuiWidgetDraw
m_lastMouseOverWidget = hit; m_lastMouseOverWidget = hit;
} }
if (hit && hit->m_lastScroll) { if (hit && hit->m_lastScroll) {
boo::SScrollDelta delta = kbm->m_accumScroll - *hit->m_lastScroll; auto delta = kbm->m_accumScroll - *hit->m_lastScroll;
hit->m_lastScroll.emplace(kbm->m_accumScroll); hit->m_lastScroll.emplace(kbm->m_accumScroll);
if (!delta.isZero()) { if (delta.x != 0.0 || delta.y != 0.0) {
hit->m_integerScroll += delta; hit->m_integerScroll += delta;
if (m_mouseScrollCb) if (m_mouseScrollCb)
m_mouseScrollCb(hit, delta, int(hit->m_integerScroll.delta[0]), int(hit->m_integerScroll.delta[1])); m_mouseScrollCb(hit, delta, int(hit->m_integerScroll.x), int(hit->m_integerScroll.y));
hit->m_integerScroll.delta[0] -= std::trunc(hit->m_integerScroll.delta[0]); hit->m_integerScroll.x -= std::trunc(hit->m_integerScroll.x);
hit->m_integerScroll.delta[1] -= std::trunc(hit->m_integerScroll.delta[1]); hit->m_integerScroll.y -= std::trunc(hit->m_integerScroll.y);
} }
} }
if (!m_inMouseDown && kbm->m_mouseButtons[size_t(boo2::MouseButton::Primary)]) { if (!m_inMouseDown && kbm->m_mouseButtons[size_t(boo2::MouseButton::Primary)]) {

View File

@ -213,22 +213,28 @@ CElementGen::CElementGen(TToken<CGenDescription> gen, EModelOrientationType orie
if (!x26c_31_LINE) { if (!x26c_31_LINE) {
switch (m_shaderClass) { switch (m_shaderClass) {
case CElementGenShaders::EShaderClass::Tex: case CElementGenShaders::EShaderClass::Tex:
m_instBuf = hsh::create_dynamic_vertex_buffer<SParticleInstanceTex>(maxInsts); break; m_instBuf = hsh::create_dynamic_vertex_buffer<SParticleInstanceTex>(maxInsts);
break;
case CElementGenShaders::EShaderClass::IndTex: case CElementGenShaders::EShaderClass::IndTex:
m_instBuf = hsh::create_dynamic_vertex_buffer<SParticleInstanceIndTex>(maxInsts); break; m_instBuf = hsh::create_dynamic_vertex_buffer<SParticleInstanceIndTex>(maxInsts);
break;
case CElementGenShaders::EShaderClass::NoTex: case CElementGenShaders::EShaderClass::NoTex:
m_instBuf = hsh::create_dynamic_vertex_buffer<SParticleInstanceNoTex>(maxInsts); break; m_instBuf = hsh::create_dynamic_vertex_buffer<SParticleInstanceNoTex>(maxInsts);
break;
} }
m_uniformBuf = hsh::create_dynamic_uniform_buffer<SParticleUniforms>(); m_uniformBuf = hsh::create_dynamic_uniform_buffer<SParticleUniforms>();
} }
if (desc->x45_24_x31_26_PMUS) { if (desc->x45_24_x31_26_PMUS) {
switch (m_shaderClass) { switch (m_shaderClass) {
case CElementGenShaders::EShaderClass::Tex: case CElementGenShaders::EShaderClass::Tex:
m_instBufPmus = hsh::create_dynamic_vertex_buffer<SParticleInstanceTex>(maxInsts); break; m_instBufPmus = hsh::create_dynamic_vertex_buffer<SParticleInstanceTex>(maxInsts);
break;
case CElementGenShaders::EShaderClass::IndTex: case CElementGenShaders::EShaderClass::IndTex:
m_instBufPmus = hsh::create_dynamic_vertex_buffer<SParticleInstanceIndTex>(maxInsts); break; m_instBufPmus = hsh::create_dynamic_vertex_buffer<SParticleInstanceIndTex>(maxInsts);
break;
case CElementGenShaders::EShaderClass::NoTex: case CElementGenShaders::EShaderClass::NoTex:
m_instBufPmus = hsh::create_dynamic_vertex_buffer<SParticleInstanceNoTex>(maxInsts); break; m_instBufPmus = hsh::create_dynamic_vertex_buffer<SParticleInstanceNoTex>(maxInsts);
break;
} }
m_uniformBufPmus = hsh::create_dynamic_uniform_buffer<SParticleUniforms>(); m_uniformBufPmus = hsh::create_dynamic_uniform_buffer<SParticleUniforms>();
} }
@ -907,14 +913,6 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
} }
m_uniformBufPmus.load({CGraphics::GetPerspectiveProjectionMatrix(true), {1.f, 1.f, 1.f, 1.f}}); m_uniformBufPmus.load({CGraphics::GetPerspectiveProjectionMatrix(true), {1.f, 1.f, 1.f, 1.f}});
// TODO: Implement in builder
#if 0
if (moveRedToAlphaBuffer)
CGraphics::SetShaderDataBinding(m_redToAlphaDataBindPmus[g_Renderer->IsThermalVisorHotPass()]);
else
CGraphics::SetShaderDataBinding(m_normalDataBindPmus[g_Renderer->IsThermalVisorHotPass()]);
#endif
} }
zeus::CTransform orient = zeus::CTransform(); zeus::CTransform orient = zeus::CTransform();
@ -1064,11 +1062,11 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
switch (m_shaderClass) { switch (m_shaderClass) {
case CElementGenShaders::EShaderClass::Tex: case CElementGenShaders::EShaderClass::Tex:
m_instBufPmus.load<SParticleInstanceTex>(g_instTexData); m_instBufPmus.load<SParticleInstanceTex>(g_instTexData);
m_shaderBuilder.BuildShaderDataBinding(*this).draw_instanced(0, 4, g_instTexData.size()); m_shaderBuilder.BuildShaderDataBinding(*this, true).draw_instanced(0, 4, g_instTexData.size());
break; break;
case CElementGenShaders::EShaderClass::NoTex: case CElementGenShaders::EShaderClass::NoTex:
m_instBufPmus.load<SParticleInstanceNoTex>(g_instNoTexData); m_instBufPmus.load<SParticleInstanceNoTex>(g_instNoTexData);
m_shaderBuilder.BuildShaderDataBinding(*this).draw_instanced(0, 4, g_instNoTexData.size()); m_shaderBuilder.BuildShaderDataBinding(*this, true).draw_instanced(0, 4, g_instNoTexData.size());
break; break;
default: default:
break; break;
@ -1194,12 +1192,12 @@ void CElementGen::RenderParticles() {
return; return;
} }
CRealElement* size = desc->x4c_x38_SIZE.get(); CRealElement* sizeElem = desc->x4c_x38_SIZE.get();
if (size && size->IsConstant()) { if (sizeElem && sizeElem->IsConstant()) {
float sizeVal; float sizeVal;
size->GetValue(0, sizeVal); sizeElem->GetValue(0, sizeVal);
if (sizeVal == 0.f) { if (sizeVal == 0.f) {
size->GetValue(1, sizeVal); sizeElem->GetValue(1, sizeVal);
if (sizeVal == 0.f) if (sizeVal == 0.f)
return; return;
} }
@ -1263,22 +1261,6 @@ void CElementGen::RenderParticles() {
if (sMoveRedToAlphaBuffer && x26c_26_AAPH) if (sMoveRedToAlphaBuffer && x26c_26_AAPH)
moveRedToAlphaBuffer = true; moveRedToAlphaBuffer = true;
// TODO: Implement in builder
#if 0
if (g_subtractBlend) {
// FIXME should there be NoTex specializations for RedToAlpha?
if (moveRedToAlphaBuffer && desc->x54_x40_TEXR)
CGraphics::SetShaderDataBinding(m_redToAlphaSubDataBind[g_Renderer->IsThermalVisorHotPass()]);
else
CGraphics::SetShaderDataBinding(m_normalSubDataBind[g_Renderer->IsThermalVisorHotPass()]);
} else {
if (moveRedToAlphaBuffer && desc->x54_x40_TEXR)
CGraphics::SetShaderDataBinding(m_redToAlphaDataBind[g_Renderer->IsThermalVisorHotPass()]);
else
CGraphics::SetShaderDataBinding(m_normalDataBind[g_Renderer->IsThermalVisorHotPass()]);
}
#endif
int mbspVal = std::max(1, x270_MBSP); int mbspVal = std::max(1, x270_MBSP);
CParticleGlobals::instance()->SetEmitterTime(x74_curFrame); CParticleGlobals::instance()->SetEmitterTime(x74_curFrame);
@ -1490,11 +1472,11 @@ void CElementGen::RenderParticles() {
switch (m_shaderClass) { switch (m_shaderClass) {
case CElementGenShaders::EShaderClass::Tex: case CElementGenShaders::EShaderClass::Tex:
m_instBuf.load<SParticleInstanceTex>(g_instTexData); m_instBuf.load<SParticleInstanceTex>(g_instTexData);
m_shaderBuilder.BuildShaderDataBinding(*this).draw_instanced(0, 4, g_instTexData.size()); m_shaderBuilder.BuildShaderDataBinding(*this, false).draw_instanced(0, 4, g_instTexData.size());
break; break;
case CElementGenShaders::EShaderClass::NoTex: case CElementGenShaders::EShaderClass::NoTex:
m_instBuf.load<SParticleInstanceNoTex>(g_instNoTexData); m_instBuf.load<SParticleInstanceNoTex>(g_instNoTexData);
m_shaderBuilder.BuildShaderDataBinding(*this).draw_instanced(0, 4, g_instNoTexData.size()); m_shaderBuilder.BuildShaderDataBinding(*this, false).draw_instanced(0, 4, g_instNoTexData.size());
break; break;
default: default:
break; break;
@ -1604,11 +1586,11 @@ void CElementGen::RenderParticles() {
switch (m_shaderClass) { switch (m_shaderClass) {
case CElementGenShaders::EShaderClass::Tex: case CElementGenShaders::EShaderClass::Tex:
m_instBuf.load<SParticleInstanceTex>(g_instTexData); m_instBuf.load<SParticleInstanceTex>(g_instTexData);
m_shaderBuilder.BuildShaderDataBinding(*this).draw_instanced(0, 4, g_instTexData.size()); m_shaderBuilder.BuildShaderDataBinding(*this, false).draw_instanced(0, 4, g_instTexData.size());
break; break;
case CElementGenShaders::EShaderClass::NoTex: case CElementGenShaders::EShaderClass::NoTex:
m_instBuf.load<SParticleInstanceNoTex>(g_instNoTexData); m_instBuf.load<SParticleInstanceNoTex>(g_instNoTexData);
m_shaderBuilder.BuildShaderDataBinding(*this).draw_instanced(0, 4, g_instNoTexData.size()); m_shaderBuilder.BuildShaderDataBinding(*this, false).draw_instanced(0, 4, g_instNoTexData.size());
break; break;
default: default:
break; break;
@ -1681,12 +1663,6 @@ void CElementGen::RenderParticlesIndirectTexture() {
g_instIndTexData.clear(); g_instIndTexData.clear();
g_instIndTexData.reserve(x30_particles.size()); g_instIndTexData.reserve(x30_particles.size());
// TODO: move to builder
#if 0
if (!x30_particles.empty())
CGraphics::SetShaderDataBinding(m_normalDataBind[g_Renderer->IsThermalVisorHotPass()]);
#endif
for (size_t i = 0; i < x30_particles.size(); ++i) { for (size_t i = 0; i < x30_particles.size(); ++i) {
const int partIdx = desc->x44_28_x30_28_SORT ? sortItems[i].x0_partIdx : int(i); const int partIdx = desc->x44_28_x30_28_SORT ? sortItems[i].x0_partIdx : int(i);
CParticle& particle = x30_particles[partIdx]; CParticle& particle = x30_particles[partIdx];
@ -1743,9 +1719,9 @@ void CElementGen::RenderParticlesIndirectTexture() {
inst.texrTindUVs[1] = zeus::CVector4f{uvs.xMin, uvs.yMax, uvsInd.xMin, uvsInd.yMax}; inst.texrTindUVs[1] = zeus::CVector4f{uvs.xMin, uvs.yMax, uvsInd.xMin, uvsInd.yMax};
inst.texrTindUVs[2] = zeus::CVector4f{uvs.xMax, uvs.yMin, uvsInd.xMax, uvsInd.yMin}; inst.texrTindUVs[2] = zeus::CVector4f{uvs.xMax, uvs.yMin, uvsInd.xMax, uvsInd.yMin};
inst.texrTindUVs[3] = zeus::CVector4f{uvs.xMin, uvs.yMin, uvsInd.xMin, uvsInd.yMin}; inst.texrTindUVs[3] = zeus::CVector4f{uvs.xMin, uvs.yMin, uvsInd.xMin, uvsInd.yMin};
inst.sceneUVs = zeus::CVector4f{clipRect.x18_uvXMin, 1.f - clipRect.x24_uvYMax, clipRect.x1c_uvXMax, inst.sceneUVs =
1.f - clipRect.x20_uvYMin}; zeus::CVector4f{clipRect.x18_uvXMin, 1.f - clipRect.x24_uvYMax, clipRect.x1c_uvXMax, 1.f - clipRect.x20_uvYMin};
m_shaderBuilder.BuildShaderDataBinding(*this).draw_instanced(0, 4, g_instIndTexData.size() - 1); m_shaderBuilder.BuildShaderDataBinding(*this, false).draw_instanced(0, 4, g_instIndTexData.size() - 1);
} }
if (!g_instIndTexData.empty()) { if (!g_instIndTexData.empty()) {