mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-05-14 07:11:21 +00:00
aurora: GX Stream API, VtxDesc, TevSwap & more
This commit is contained in:
parent
ecb4645e89
commit
b9b635b311
@ -813,9 +813,7 @@ void CCubeRenderer::SetThermal(bool thermal, float level, const zeus::CColor& co
|
|||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCubeRenderer::SetThermalColdScale(float scale) {
|
void CCubeRenderer::SetThermalColdScale(float scale) { x2f8_thermColdScale = zeus::clamp(0.f, scale, 1.f); }
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCubeRenderer::DoThermalBlendCold() {
|
void CCubeRenderer::DoThermalBlendCold() {
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -3,11 +3,12 @@
|
|||||||
#include "Graphics/CTexture.hpp"
|
#include "Graphics/CTexture.hpp"
|
||||||
|
|
||||||
namespace metaforce::CGX {
|
namespace metaforce::CGX {
|
||||||
SGXState sGXState;
|
SGXState sGXState{};
|
||||||
|
std::array<GX::VtxDescList, 11> sVtxDescList{};
|
||||||
|
|
||||||
void ResetGXStates() noexcept {
|
void ResetGXStates() noexcept {
|
||||||
sGXState.x48_descList = nullptr;
|
sGXState.x48_descList = 0;
|
||||||
// GXClearVtxDesc();
|
GXClearVtxDesc();
|
||||||
sGXState.x0_arrayPtrs.fill(nullptr);
|
sGXState.x0_arrayPtrs.fill(nullptr);
|
||||||
for (GX::TexMapID id = GX::TEXMAP0; id < GX::MAX_TEXMAP; id = static_cast<GX::TexMapID>(id + 1)) {
|
for (GX::TexMapID id = GX::TEXMAP0; id < GX::MAX_TEXMAP; id = static_cast<GX::TexMapID>(id + 1)) {
|
||||||
CTexture::InvalidateTexMap(id);
|
CTexture::InvalidateTexMap(id);
|
||||||
@ -16,7 +17,9 @@ void ResetGXStates() noexcept {
|
|||||||
GXSetTevKColor(id, item);
|
GXSetTevKColor(id, item);
|
||||||
id = static_cast<GX::TevKColorID>(id + 1);
|
id = static_cast<GX::TevKColorID>(id + 1);
|
||||||
}
|
}
|
||||||
// GXSetTevSwapModeTable
|
GXSetTevSwapModeTable(GX::TEV_SWAP1, GX::CH_RED, GX::CH_GREEN, GX::CH_BLUE, GX::CH_RED);
|
||||||
|
GXSetTevSwapModeTable(GX::TEV_SWAP2, GX::CH_RED, GX::CH_GREEN, GX::CH_BLUE, GX::CH_GREEN);
|
||||||
|
GXSetTevSwapModeTable(GX::TEV_SWAP3, GX::CH_RED, GX::CH_GREEN, GX::CH_BLUE, GX::CH_BLUE);
|
||||||
SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_AND, GX::ALWAYS, 0);
|
SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_AND, GX::ALWAYS, 0);
|
||||||
// GXSetCurrentMtx(0);
|
// GXSetCurrentMtx(0);
|
||||||
SetNumIndStages(0);
|
SetNumIndStages(0);
|
||||||
|
@ -31,7 +31,7 @@ struct SGXState {
|
|||||||
std::array<u16, 2> x34_chanCtrls{0x4000, 0x4000};
|
std::array<u16, 2> x34_chanCtrls{0x4000, 0x4000};
|
||||||
std::array<GXColor, 2> x38_chanAmbColors;
|
std::array<GXColor, 2> x38_chanAmbColors;
|
||||||
std::array<GXColor, 2> x40_chanMatColors;
|
std::array<GXColor, 2> x40_chanMatColors;
|
||||||
GX::VtxDescList* x48_descList = nullptr;
|
u32 x48_descList = 0;
|
||||||
u8 x4c_dirtyChans = 0;
|
u8 x4c_dirtyChans = 0;
|
||||||
u8 x4d_prevNumChans = 0;
|
u8 x4d_prevNumChans = 0;
|
||||||
u8 x4e_numChans = 0;
|
u8 x4e_numChans = 0;
|
||||||
@ -53,6 +53,7 @@ struct SGXState {
|
|||||||
GXColor x25c_fogColor;
|
GXColor x25c_fogColor;
|
||||||
};
|
};
|
||||||
extern SGXState sGXState;
|
extern SGXState sGXState;
|
||||||
|
extern std::array<GX::VtxDescList, 11> sVtxDescList;
|
||||||
|
|
||||||
static inline void update_fog(u32 value) noexcept {
|
static inline void update_fog(u32 value) noexcept {
|
||||||
if (sGXState.x53_fogType == GX::FOG_NONE || (sGXState.x56_blendMode & 0xE0) == (value & 0xE0)) {
|
if (sGXState.x53_fogType == GX::FOG_NONE || (sGXState.x56_blendMode & 0xE0) == (value & 0xE0)) {
|
||||||
@ -92,9 +93,11 @@ static inline void Begin(GX::Primitive primitive, GX::VtxFmt fmt, u16 nverts) no
|
|||||||
if (sGXState.x4c_dirtyChans != 0) {
|
if (sGXState.x4c_dirtyChans != 0) {
|
||||||
FlushState();
|
FlushState();
|
||||||
}
|
}
|
||||||
// TODO GXBegin(type, fmt, nverts);
|
GXBegin(primitive, fmt, nverts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void End() noexcept { GXEnd(); }
|
||||||
|
|
||||||
static inline void CallDisplayList(const void* data, u32 nbytes) noexcept {
|
static inline void CallDisplayList(const void* data, u32 nbytes) noexcept {
|
||||||
if (sGXState.x4c_dirtyChans != 0) {
|
if (sGXState.x4c_dirtyChans != 0) {
|
||||||
FlushState();
|
FlushState();
|
||||||
@ -102,10 +105,6 @@ static inline void CallDisplayList(const void* data, u32 nbytes) noexcept {
|
|||||||
GXCallDisplayList(data, nbytes);
|
GXCallDisplayList(data, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void End() noexcept {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline const GXColor& GetChanAmbColor(EChannelId id) noexcept {
|
static inline const GXColor& GetChanAmbColor(EChannelId id) noexcept {
|
||||||
const auto idx = std::underlying_type_t<EChannelId>(id);
|
const auto idx = std::underlying_type_t<EChannelId>(id);
|
||||||
return sGXState.x38_chanAmbColors[idx];
|
return sGXState.x38_chanAmbColors[idx];
|
||||||
@ -394,11 +393,33 @@ static inline void SetTexCoordGen(GX::TexCoordID dstCoord, u32 flags) noexcept {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetVtxDescv(GX::VtxDescList* descList) noexcept;
|
|
||||||
|
|
||||||
static inline void SetVtxDescv_Compressed(u32 descList) noexcept {
|
static inline void SetVtxDescv_Compressed(u32 descList) noexcept {
|
||||||
// TODO convert to GX::VtxDescList
|
u32 currentDescList = sGXState.x48_descList;
|
||||||
aurora::gfx::model::set_vtx_desc_compressed(descList);
|
if (descList != currentDescList) {
|
||||||
|
size_t remain = sVtxDescList.size();
|
||||||
|
u32 shift = 0;
|
||||||
|
u32 attrIdx = 0;
|
||||||
|
do {
|
||||||
|
sVtxDescList[attrIdx] = {
|
||||||
|
GX::Attr(GX::VA_POS + attrIdx),
|
||||||
|
GX::AttrType(descList >> shift & 3),
|
||||||
|
};
|
||||||
|
shift += 2;
|
||||||
|
++attrIdx;
|
||||||
|
--remain;
|
||||||
|
} while (remain != 0);
|
||||||
|
sVtxDescList[attrIdx] = {};
|
||||||
|
GXSetVtxDescv(sVtxDescList.data());
|
||||||
|
sGXState.x48_descList = descList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void SetVtxDescv(const GX::VtxDescList* descList) noexcept {
|
||||||
|
u32 flags = 0;
|
||||||
|
for (; descList->attr != GX::VA_NULL; ++descList) {
|
||||||
|
flags |= (descList->type & 3) << (descList->attr - GX::VA_POS) * 2;
|
||||||
|
}
|
||||||
|
SetVtxDescv_Compressed(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void SetZMode(GXBool compareEnable, GX::Compare func, GXBool updateEnable) noexcept {
|
static inline void SetZMode(GXBool compareEnable, GX::Compare func, GXBool updateEnable) noexcept {
|
||||||
|
@ -59,9 +59,16 @@ const std::array<zeus::CMatrix3f, 6> CGraphics::skCubeBasisMats{{
|
|||||||
|
|
||||||
// Stream API
|
// Stream API
|
||||||
static EStreamFlags sStreamFlags;
|
static EStreamFlags sStreamFlags;
|
||||||
static zeus::CColor sQueuedColor;
|
static GX::Primitive sStreamPrimitive;
|
||||||
static zeus::CVector2f sQueuedTexCoord;
|
static u32 sVerticesCount;
|
||||||
static zeus::CVector3f sQueuedNormal;
|
// Originally writes directly to GX FIFO
|
||||||
|
struct StreamVertex {
|
||||||
|
zeus::CColor color;
|
||||||
|
zeus::CVector2f texCoord;
|
||||||
|
zeus::CVector3f normal;
|
||||||
|
zeus::CVector3f vertex;
|
||||||
|
};
|
||||||
|
static std::vector<StreamVertex> sQueuedVertices;
|
||||||
|
|
||||||
void CGraphics::DisableAllLights() {
|
void CGraphics::DisableAllLights() {
|
||||||
g_LightActive.reset();
|
g_LightActive.reset();
|
||||||
@ -518,55 +525,102 @@ void CGraphics::SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CGraphics::StreamBegin(GX::Primitive primitive) {
|
void CGraphics::StreamBegin(GX::Primitive primitive) {
|
||||||
sStreamFlags = {};
|
// Originally ResetVertexDataStream(true);
|
||||||
aurora::gfx::stream_begin(primitive);
|
sQueuedVertices.clear();
|
||||||
|
sQueuedVertices.emplace_back();
|
||||||
|
sVerticesCount = 0;
|
||||||
|
// End
|
||||||
|
sStreamFlags = EStreamFlagBits::fHasColor;
|
||||||
|
sStreamPrimitive = primitive;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGraphics::StreamNormal(const zeus::CVector3f& nrm) {
|
void CGraphics::StreamNormal(const zeus::CVector3f& nrm) {
|
||||||
sQueuedNormal = nrm;
|
sQueuedVertices.back().normal = nrm;
|
||||||
sStreamFlags |= EStreamFlagBits::fHasNormal;
|
sStreamFlags |= EStreamFlagBits::fHasNormal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGraphics::StreamColor(float r, float g, float b, float a) {
|
|
||||||
sQueuedColor = zeus::CColor{r, g, b, a};
|
|
||||||
sStreamFlags |= EStreamFlagBits::fHasColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGraphics::StreamColor(const zeus::CColor& color) {
|
void CGraphics::StreamColor(const zeus::CColor& color) {
|
||||||
sQueuedColor = color;
|
sQueuedVertices.back().color = color;
|
||||||
sStreamFlags |= EStreamFlagBits::fHasColor;
|
sStreamFlags |= EStreamFlagBits::fHasColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGraphics::StreamTexcoord(float x, float y) {
|
|
||||||
sQueuedTexCoord = {x, y};
|
|
||||||
sStreamFlags |= EStreamFlagBits::fHasTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGraphics::StreamTexcoord(const zeus::CVector2f& uv) {
|
void CGraphics::StreamTexcoord(const zeus::CVector2f& uv) {
|
||||||
sQueuedTexCoord = uv;
|
sQueuedVertices.back().texCoord = uv;
|
||||||
sStreamFlags |= EStreamFlagBits::fHasTexture;
|
sStreamFlags |= EStreamFlagBits::fHasTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGraphics::StreamVertex(float xyz) {
|
|
||||||
const zeus::CVector3f pos{xyz, xyz, xyz};
|
|
||||||
aurora::gfx::stream_vertex(sStreamFlags, pos, sQueuedNormal, sQueuedColor, sQueuedTexCoord);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGraphics::StreamVertex(float x, float y, float z) {
|
|
||||||
const zeus::CVector3f pos{x, y, z};
|
|
||||||
aurora::gfx::stream_vertex(sStreamFlags, pos, sQueuedNormal, sQueuedColor, sQueuedTexCoord);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGraphics::StreamVertex(const zeus::CVector3f& pos) {
|
void CGraphics::StreamVertex(const zeus::CVector3f& pos) {
|
||||||
aurora::gfx::stream_vertex(sStreamFlags, pos, sQueuedNormal, sQueuedColor, sQueuedTexCoord);
|
sQueuedVertices.back().vertex = pos;
|
||||||
|
UpdateVertexDataStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGraphics::StreamEnd() {
|
void CGraphics::StreamEnd() {
|
||||||
SetTevStates(sStreamFlags);
|
if (sVerticesCount != 0) {
|
||||||
aurora::gfx::stream_end();
|
FlushStream();
|
||||||
|
}
|
||||||
sStreamFlags = {};
|
sStreamFlags = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGraphics::UpdateVertexDataStream() {
|
||||||
|
++sVerticesCount;
|
||||||
|
if (sVerticesCount == 240) {
|
||||||
|
FlushStream();
|
||||||
|
ResetVertexDataStream(false);
|
||||||
|
} else {
|
||||||
|
sQueuedVertices.emplace_back(sQueuedVertices.back());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGraphics::FlushStream() {
|
||||||
|
std::array<GX::VtxDescList, 5> vtxDescList{};
|
||||||
|
size_t idx = 0;
|
||||||
|
vtxDescList[idx++] = {GX::VA_POS, GX::DIRECT};
|
||||||
|
if (sStreamFlags & EStreamFlagBits::fHasNormal) {
|
||||||
|
vtxDescList[idx++] = {GX::VA_NRM, GX::DIRECT};
|
||||||
|
}
|
||||||
|
if (sStreamFlags & EStreamFlagBits::fHasColor) {
|
||||||
|
vtxDescList[idx++] = {GX::VA_CLR0, GX::DIRECT};
|
||||||
|
}
|
||||||
|
if (sStreamFlags & EStreamFlagBits::fHasTexture) {
|
||||||
|
vtxDescList[idx++] = {GX::VA_TEX0, GX::DIRECT};
|
||||||
|
}
|
||||||
|
CGX::SetVtxDescv(vtxDescList.data());
|
||||||
|
SetTevStates(sStreamFlags);
|
||||||
|
FullRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGraphics::FullRender() {
|
||||||
|
CGX::Begin(sStreamPrimitive, GX::VTXFMT0, sVerticesCount);
|
||||||
|
for (size_t i = 0; i < sVerticesCount; ++i) {
|
||||||
|
const auto& item = sQueuedVertices[i];
|
||||||
|
GXPosition3f32(item.vertex);
|
||||||
|
if (sStreamFlags & EStreamFlagBits::fHasNormal) {
|
||||||
|
GXNormal3f32(item.normal);
|
||||||
|
}
|
||||||
|
if (sStreamFlags & EStreamFlagBits::fHasColor) {
|
||||||
|
GXColor4f32(item.color);
|
||||||
|
}
|
||||||
|
if (sStreamFlags & EStreamFlagBits::fHasTexture) {
|
||||||
|
GXTexCoord2f32(item.texCoord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CGX::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGraphics::ResetVertexDataStream(bool end) {
|
||||||
|
if (end) {
|
||||||
|
sQueuedVertices.clear();
|
||||||
|
} else {
|
||||||
|
const auto lastVertex = sQueuedVertices.back();
|
||||||
|
sQueuedVertices.clear();
|
||||||
|
sQueuedVertices.emplace_back(lastVertex);
|
||||||
|
}
|
||||||
|
sVerticesCount = 0;
|
||||||
|
if (!end) {
|
||||||
|
// TODO something with triangle fans
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CGraphics::DrawPrimitive(GX::Primitive primitive, const zeus::CVector3f* pos, const zeus::CVector3f& normal,
|
void CGraphics::DrawPrimitive(GX::Primitive primitive, const zeus::CVector3f* pos, const zeus::CVector3f& normal,
|
||||||
const zeus::CColor& col, s32 numVerts) {
|
const zeus::CColor& col, s32 numVerts) {
|
||||||
StreamBegin(primitive);
|
StreamBegin(primitive);
|
||||||
@ -580,12 +634,12 @@ void CGraphics::DrawPrimitive(GX::Primitive primitive, const zeus::CVector3f* po
|
|||||||
|
|
||||||
void CGraphics::SetTevStates(EStreamFlags flags) noexcept {
|
void CGraphics::SetTevStates(EStreamFlags flags) noexcept {
|
||||||
if (flags & EStreamFlagBits::fHasTexture) {
|
if (flags & EStreamFlagBits::fHasTexture) {
|
||||||
CGX::SetNumTexGens(0);
|
CGX::SetNumTexGens(1); // sTextureUsed & 3?
|
||||||
CGX::SetNumTevStages(1);
|
|
||||||
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR0A0);
|
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR0A0);
|
||||||
CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD1, GX::TEXMAP1, GX::COLOR0A0);
|
CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD1, GX::TEXMAP1, GX::COLOR0A0);
|
||||||
} else /* if (flags < 8) ? */ {
|
} else {
|
||||||
CGX::SetNumTexGens(2); // sTextureUsed & 3?
|
CGX::SetNumTexGens(0);
|
||||||
|
CGX::SetNumTevStages(1);
|
||||||
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR0A0);
|
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR0A0);
|
||||||
CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR0A0);
|
CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR0A0);
|
||||||
}
|
}
|
||||||
@ -599,4 +653,67 @@ void CGraphics::SetTevStates(EStreamFlags flags) noexcept {
|
|||||||
hasLights ? GX::DF_CLAMP : GX::DF_NONE, hasLights ? GX::AF_SPOT : GX::AF_NONE);
|
hasLights ? GX::DF_CLAMP : GX::DF_NONE, hasLights ? GX::AF_SPOT : GX::AF_NONE);
|
||||||
CGX::FlushState(); // normally would be handled in FullRender TODO
|
CGX::FlushState(); // normally would be handled in FullRender TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGraphics::Startup() {
|
||||||
|
// Setup GXFifo
|
||||||
|
CGX::ResetGXStates();
|
||||||
|
InitGraphicsVariables();
|
||||||
|
// ConfigureFrameBuffer(...);
|
||||||
|
InitGraphicsDefaults();
|
||||||
|
// GXInitTexCacheRegion
|
||||||
|
// GXSetTexRegionCallback
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGraphics::InitGraphicsVariables() {
|
||||||
|
// g_lightTypes[0..n] = Directional;
|
||||||
|
g_LightActive = {};
|
||||||
|
SetDepthWriteMode(false, g_depthFunc, false);
|
||||||
|
SetCullMode(ERglCullMode::None);
|
||||||
|
SetAmbientColor(zeus::CColor{0.2f, 1.f});
|
||||||
|
g_IsGXModelMatrixIdentity = false;
|
||||||
|
// SetIdentityViewPointMatrix();
|
||||||
|
// SetIdentityModelMatrix();
|
||||||
|
// SetViewport(...);
|
||||||
|
// SetPerspective(...);
|
||||||
|
SetCopyClear(g_ClearColor, 1.f);
|
||||||
|
CGX::SetChanMatColor(CGX::EChannelId::Channel0, zeus::skWhite);
|
||||||
|
// g_RenderState.ResetFlushAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGraphics::InitGraphicsDefaults() {
|
||||||
|
SetDepthRange(0.f, 1.f);
|
||||||
|
g_IsGXModelMatrixIdentity = false;
|
||||||
|
SetModelMatrix(g_GXModelMatrix);
|
||||||
|
SetViewPointMatrix(g_GXModelView);
|
||||||
|
SetDepthWriteMode(false, g_depthFunc, false);
|
||||||
|
SetCullMode(g_cullMode);
|
||||||
|
SetViewport(g_Viewport.x0_left, g_Viewport.x4_top, g_Viewport.x8_width, g_Viewport.xc_height);
|
||||||
|
FlushProjection();
|
||||||
|
CTevCombiners::Init();
|
||||||
|
DisableAllLights();
|
||||||
|
SetDefaultVtxAttrFmt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGraphics::SetDefaultVtxAttrFmt() {
|
||||||
|
// Unneeded, all attributes are expected to be full floats
|
||||||
|
// Left here for reference
|
||||||
|
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT0, GX::VA_POS, GX::POS_XYZ, GX::F32, 0);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT1, GX::VA_POS, GX::POS_XYZ, GX::F32, 0);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT2, GX::VA_POS, GX::POS_XYZ, GX::F32, 0);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT0, GX::VA_NRM, GX::NRM_XYZ, GX::F32, 0);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT1, GX::VA_NRM, GX::NRM_XYZ, GX::S16, 14);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT2, GX::VA_NRM, GX::NRM_XYZ, GX::S16, 14);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT0, GX::VA_CLR0, GX::CLR_RGBA, GX::RGBA8, 0);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT1, GX::VA_CLR0, GX::CLR_RGBA, GX::RGBA8, 0);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT2, GX::VA_CLR0, GX::CLR_RGBA, GX::RGBA8, 0);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT0, GX::VA_TEX0, GX::TEX_ST, GX::F32, 0);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT1, GX::VA_TEX0, GX::TEX_ST, GX::F32, 0);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT2, GX::VA_TEX0, GX::TEX_ST, GX::U16, 15);
|
||||||
|
// for (GX::Attr attr = GX::VA_TEX1; attr <= GX::VA_TEX7; attr = GX::Attr(attr + 1)) {
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT0, attr, GX::TEX_ST, GX::F32, 0);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT1, attr, GX::TEX_ST, GX::F32, 0);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT2, attr, GX::TEX_ST, GX::F32, 0);
|
||||||
|
// }
|
||||||
|
}
|
||||||
} // namespace metaforce
|
} // namespace metaforce
|
||||||
|
@ -205,6 +205,10 @@ public:
|
|||||||
static ERglEnum g_depthFunc;
|
static ERglEnum g_depthFunc;
|
||||||
static ERglCullMode g_cullMode;
|
static ERglCullMode g_cullMode;
|
||||||
|
|
||||||
|
static void Startup();
|
||||||
|
static void InitGraphicsVariables();
|
||||||
|
static void InitGraphicsDefaults();
|
||||||
|
static void SetDefaultVtxAttrFmt();
|
||||||
static void DisableAllLights();
|
static void DisableAllLights();
|
||||||
static void LoadLight(ERglLight light, const CLight& info);
|
static void LoadLight(ERglLight light, const CLight& info);
|
||||||
static void EnableLight(ERglLight light);
|
static void EnableLight(ERglLight light);
|
||||||
@ -353,14 +357,18 @@ public:
|
|||||||
static void SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass);
|
static void SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass);
|
||||||
static void StreamBegin(GX::Primitive primitive);
|
static void StreamBegin(GX::Primitive primitive);
|
||||||
static void StreamNormal(const zeus::CVector3f& nrm);
|
static void StreamNormal(const zeus::CVector3f& nrm);
|
||||||
static void StreamColor(float r, float g, float b, float a);
|
|
||||||
static void StreamColor(const zeus::CColor& color);
|
static void StreamColor(const zeus::CColor& color);
|
||||||
static void StreamTexcoord(float x, float y);
|
static inline void StreamColor(float r, float g, float b, float a) { StreamColor({r, g, b, a}); }
|
||||||
static void StreamTexcoord(const zeus::CVector2f& uv);
|
static void StreamTexcoord(const zeus::CVector2f& uv);
|
||||||
static void StreamVertex(float xyz);
|
static inline void StreamTexcoord(float x, float y) { StreamTexcoord({x, y}); }
|
||||||
static void StreamVertex(float x, float y, float z);
|
|
||||||
static void StreamVertex(const zeus::CVector3f& pos);
|
static void StreamVertex(const zeus::CVector3f& pos);
|
||||||
|
static inline void StreamVertex(float xyz) { StreamVertex({xyz, xyz, xyz}); }
|
||||||
|
static inline void StreamVertex(float x, float y, float z) { StreamVertex({x, y, z}); }
|
||||||
static void StreamEnd();
|
static void StreamEnd();
|
||||||
|
static void UpdateVertexDataStream();
|
||||||
|
static void ResetVertexDataStream(bool end);
|
||||||
|
static void FlushStream();
|
||||||
|
static void FullRender();
|
||||||
static void DrawPrimitive(GX::Primitive primitive, const zeus::CVector3f* pos, const zeus::CVector3f& normal,
|
static void DrawPrimitive(GX::Primitive primitive, const zeus::CVector3f* pos, const zeus::CVector3f& normal,
|
||||||
const zeus::CColor& col, s32 numVerts);
|
const zeus::CColor& col, s32 numVerts);
|
||||||
};
|
};
|
||||||
|
@ -49,8 +49,9 @@ enum AttrType {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct VtxDescList {
|
struct VtxDescList {
|
||||||
Attr attr;
|
Attr attr = GX::VA_NULL;
|
||||||
AttrType type;
|
AttrType type = GX::NONE;
|
||||||
|
operator bool() const { return attr != GX::VA_NULL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
enum VtxFmt {
|
enum VtxFmt {
|
||||||
@ -665,6 +666,32 @@ enum ProjectionType {
|
|||||||
ORTHOGRAPHIC,
|
ORTHOGRAPHIC,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum CompCnt {
|
||||||
|
CLR_RGB = 0,
|
||||||
|
POS_XY = 0,
|
||||||
|
TEX_S = 0,
|
||||||
|
NRM_XYZ = 0,
|
||||||
|
CLR_RGBA = 1,
|
||||||
|
POS_XYZ = 1,
|
||||||
|
NRM_NBT = 1,
|
||||||
|
TEX_ST = 1,
|
||||||
|
NRM_NBT3 = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CompType {
|
||||||
|
RGB565 = 0,
|
||||||
|
U8 = 0,
|
||||||
|
RGB8 = 1,
|
||||||
|
S8 = 1,
|
||||||
|
U16 = 2,
|
||||||
|
RGBX8 = 2,
|
||||||
|
S16 = 3,
|
||||||
|
RGBA4 = 3,
|
||||||
|
F32 = 4,
|
||||||
|
RGBA6 = 4,
|
||||||
|
RGBA8 = 5,
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace GX
|
} // namespace GX
|
||||||
|
|
||||||
using GXColor = zeus::CColor;
|
using GXColor = zeus::CColor;
|
||||||
@ -700,6 +727,7 @@ void GXSetChanCtrl(GX::ChannelID id, GXBool lightingEnabled, GX::ColorSrc ambSrc
|
|||||||
GX::LightMask lightState, GX::DiffuseFn diffFn, GX::AttnFn attnFn) noexcept;
|
GX::LightMask lightState, GX::DiffuseFn diffFn, GX::AttnFn attnFn) noexcept;
|
||||||
// Originally u8 instead of floats
|
// Originally u8 instead of floats
|
||||||
void GXSetAlphaCompare(GX::Compare comp0, float ref0, GX::AlphaOp op, GX::Compare comp1, float ref1) noexcept;
|
void GXSetAlphaCompare(GX::Compare comp0, float ref0, GX::AlphaOp op, GX::Compare comp1, float ref1) noexcept;
|
||||||
|
void GXSetVtxDesc(GX::Attr attr, GX::AttrType type) noexcept;
|
||||||
void GXSetVtxDescv(GX::VtxDescList* list) noexcept;
|
void GXSetVtxDescv(GX::VtxDescList* list) noexcept;
|
||||||
void GXClearVtxDesc() noexcept;
|
void GXClearVtxDesc() noexcept;
|
||||||
void GXSetArray(GX::Attr attr, const void* data, u8 stride) noexcept;
|
void GXSetArray(GX::Attr attr, const void* data, u8 stride) noexcept;
|
||||||
@ -715,3 +743,21 @@ void GXLoadNrmMtxImm(const zeus::CTransform& xf, GX::PosNrmMtx id) noexcept;
|
|||||||
void GXSetProjection(const zeus::CMatrix4f& mtx, GX::ProjectionType type) noexcept;
|
void GXSetProjection(const zeus::CMatrix4f& mtx, GX::ProjectionType type) noexcept;
|
||||||
void GXSetViewport(float left, float top, float width, float height, float nearZ, float farZ) noexcept;
|
void GXSetViewport(float left, float top, float width, float height, float nearZ, float farZ) noexcept;
|
||||||
void GXSetScissor(u32 left, u32 top, u32 width, u32 height) noexcept;
|
void GXSetScissor(u32 left, u32 top, u32 width, u32 height) noexcept;
|
||||||
|
// Unneeded, all attributes are expected to be full floats
|
||||||
|
// void GXSetVtxAttrFmt(GX::VtxFmt vtxfmt, GX::Attr attr, GX::CompCnt cnt, GX::CompType type, u8 frac) noexcept;
|
||||||
|
// Streaming
|
||||||
|
void GXBegin(GX::Primitive primitive, GX::VtxFmt vtxFmt, u16 nVerts) noexcept;
|
||||||
|
void GXMatrixIndex1u8(u8 idx) noexcept;
|
||||||
|
void GXPosition3f32(const zeus::CVector3f& pos) noexcept;
|
||||||
|
static inline void GXPosition3f32(float x, float y, float z) noexcept { GXPosition3f32({x, y, z}); }
|
||||||
|
void GXNormal3f32(const zeus::CVector3f& nrm) noexcept;
|
||||||
|
static inline void GXNormal3f32(float x, float y, float z) noexcept { GXNormal3f32({x, y, z}); }
|
||||||
|
void GXColor4f32(const zeus::CColor& color) noexcept;
|
||||||
|
static inline void GXColor4f32(float r, float g, float b, float a) noexcept { GXColor4f32({r, g, b, a}); }
|
||||||
|
void GXTexCoord2f32(const zeus::CVector2f& uv) noexcept;
|
||||||
|
static inline void GXTexCoord2f32(float u, float v) noexcept { GXTexCoord2f32({u, v}); }
|
||||||
|
void GXEnd() noexcept;
|
||||||
|
// End streaming
|
||||||
|
void GXSetTevSwapModeTable(GX::TevSwapSel id, GX::TevColorChan red, GX::TevColorChan green, GX::TevColorChan blue,
|
||||||
|
GX::TevColorChan alpha) noexcept;
|
||||||
|
void GXSetTevSwapMode(GX::TevStageID stage, GX::TevSwapSel rasSel, GX::TevSwapSel texSel) noexcept;
|
||||||
|
@ -87,8 +87,8 @@ void CDecal::RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) const {
|
|||||||
modXf.origin += offset;
|
modXf.origin += offset;
|
||||||
CGraphics::SetModelMatrix(modXf);
|
CGraphics::SetModelMatrix(modXf);
|
||||||
|
|
||||||
SParticleUniforms uniformData = {
|
// SParticleUniforms uniformData = {
|
||||||
CGraphics::GetPerspectiveProjectionMatrix(/*true*/) * CGraphics::g_GXModelView.toMatrix4f(), {1.f, 1.f, 1.f, 1.f}};
|
// CGraphics::GetPerspectiveProjectionMatrix(/*true*/) * CGraphics::g_GXModelView.toMatrix4f(), {1.f, 1.f, 1.f, 1.f}};
|
||||||
// decal.m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
|
// decal.m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
|
||||||
|
|
||||||
bool redToAlpha = sMoveRedToAlphaBuffer && desc.x18_ADD && desc.x14_TEX;
|
bool redToAlpha = sMoveRedToAlphaBuffer && desc.x18_ADD && desc.x14_TEX;
|
||||||
@ -104,52 +104,52 @@ void CDecal::RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) const {
|
|||||||
// else
|
// else
|
||||||
// CGraphics::SetShaderDataBinding(decal.m_normalDataBind);
|
// CGraphics::SetShaderDataBinding(decal.m_normalDataBind);
|
||||||
|
|
||||||
g_instTexData.clear();
|
// g_instTexData.clear();
|
||||||
g_instTexData.reserve(1);
|
// g_instTexData.reserve(1);
|
||||||
|
|
||||||
SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
// SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||||
if (decal.x8_rotation == 0.f) {
|
// if (decal.x8_rotation == 0.f) {
|
||||||
inst.pos[0] = zeus::CVector3f(-size, 0.001f, size);
|
// inst.pos[0] = zeus::CVector3f(-size, 0.001f, size);
|
||||||
inst.pos[1] = zeus::CVector3f(size, 0.001f, size);
|
// inst.pos[1] = zeus::CVector3f(size, 0.001f, size);
|
||||||
inst.pos[2] = zeus::CVector3f(-size, 0.001f, -size);
|
// inst.pos[2] = zeus::CVector3f(-size, 0.001f, -size);
|
||||||
inst.pos[3] = zeus::CVector3f(size, 0.001f, -size);
|
// inst.pos[3] = zeus::CVector3f(size, 0.001f, -size);
|
||||||
} else {
|
// } else {
|
||||||
float ang = zeus::degToRad(decal.x8_rotation);
|
// float ang = zeus::degToRad(decal.x8_rotation);
|
||||||
float sinSize = std::sin(ang) * size;
|
// float sinSize = std::sin(ang) * size;
|
||||||
float cosSize = std::cos(ang) * size;
|
// float cosSize = std::cos(ang) * size;
|
||||||
inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 0.001f, cosSize + sinSize);
|
// inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 0.001f, cosSize + sinSize);
|
||||||
inst.pos[1] = zeus::CVector3f(cosSize + sinSize, 0.001f, cosSize - sinSize);
|
// inst.pos[1] = zeus::CVector3f(cosSize + sinSize, 0.001f, cosSize - sinSize);
|
||||||
inst.pos[2] = zeus::CVector3f(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize));
|
// inst.pos[2] = zeus::CVector3f(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize));
|
||||||
inst.pos[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize);
|
// inst.pos[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize);
|
||||||
}
|
// }
|
||||||
inst.color = color;
|
// inst.color = color;
|
||||||
inst.uvs[0] = zeus::CVector2f(uvSet.xMin, uvSet.yMin);
|
// inst.uvs[0] = zeus::CVector2f(uvSet.xMin, uvSet.yMin);
|
||||||
inst.uvs[1] = zeus::CVector2f(uvSet.xMax, uvSet.yMin);
|
// inst.uvs[1] = zeus::CVector2f(uvSet.xMax, uvSet.yMin);
|
||||||
inst.uvs[2] = zeus::CVector2f(uvSet.xMin, uvSet.yMax);
|
// inst.uvs[2] = zeus::CVector2f(uvSet.xMin, uvSet.yMax);
|
||||||
inst.uvs[3] = zeus::CVector2f(uvSet.xMax, uvSet.yMax);
|
// inst.uvs[3] = zeus::CVector2f(uvSet.xMax, uvSet.yMax);
|
||||||
|
|
||||||
// decal.m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
|
// decal.m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
|
||||||
// CGraphics::DrawInstances(0, 4, g_instTexData.size());
|
// CGraphics::DrawInstances(0, 4, g_instTexData.size());
|
||||||
} else {
|
} else {
|
||||||
g_instNoTexData.clear();
|
// g_instNoTexData.clear();
|
||||||
g_instNoTexData.reserve(1);
|
// g_instNoTexData.reserve(1);
|
||||||
|
|
||||||
SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
// SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||||
if (decal.x8_rotation == 0.f) {
|
// if (decal.x8_rotation == 0.f) {
|
||||||
inst.pos[0] = zeus::CVector3f(-size, 0.001f, size);
|
// inst.pos[0] = zeus::CVector3f(-size, 0.001f, size);
|
||||||
inst.pos[1] = zeus::CVector3f(size, 0.001f, size);
|
// inst.pos[1] = zeus::CVector3f(size, 0.001f, size);
|
||||||
inst.pos[2] = zeus::CVector3f(-size, 0.001f, -size);
|
// inst.pos[2] = zeus::CVector3f(-size, 0.001f, -size);
|
||||||
inst.pos[3] = zeus::CVector3f(size, 0.001f, -size);
|
// inst.pos[3] = zeus::CVector3f(size, 0.001f, -size);
|
||||||
} else {
|
// } else {
|
||||||
float ang = zeus::degToRad(decal.x8_rotation);
|
// float ang = zeus::degToRad(decal.x8_rotation);
|
||||||
float sinSize = std::sin(ang) * size;
|
// float sinSize = std::sin(ang) * size;
|
||||||
float cosSize = std::cos(ang) * size;
|
// float cosSize = std::cos(ang) * size;
|
||||||
inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 0.001f, cosSize + sinSize);
|
// inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 0.001f, cosSize + sinSize);
|
||||||
inst.pos[1] = zeus::CVector3f(cosSize + sinSize, 0.001f, cosSize - sinSize);
|
// inst.pos[1] = zeus::CVector3f(cosSize + sinSize, 0.001f, cosSize - sinSize);
|
||||||
inst.pos[2] = zeus::CVector3f(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize));
|
// inst.pos[2] = zeus::CVector3f(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize));
|
||||||
inst.pos[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize);
|
// inst.pos[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize);
|
||||||
}
|
// }
|
||||||
inst.color = color;
|
// inst.color = color;
|
||||||
|
|
||||||
// decal.m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
|
// decal.m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
|
||||||
// CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
|
// CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "Runtime/GameGlobalObjects.hpp"
|
#include "Runtime/GameGlobalObjects.hpp"
|
||||||
#include "Runtime/Character/CActorLights.hpp"
|
#include "Runtime/Character/CActorLights.hpp"
|
||||||
#include "Runtime/Graphics/CCubeRenderer.hpp"
|
#include "Runtime/Graphics/CCubeRenderer.hpp"
|
||||||
|
#include "Runtime/Graphics/CGX.hpp"
|
||||||
#include "Runtime/Graphics/CModel.hpp"
|
#include "Runtime/Graphics/CModel.hpp"
|
||||||
#include "Runtime/Graphics/Shaders/CElementGenShaders.hpp"
|
#include "Runtime/Graphics/Shaders/CElementGenShaders.hpp"
|
||||||
#include "Runtime/Particle/CElectricDescription.hpp"
|
#include "Runtime/Particle/CElectricDescription.hpp"
|
||||||
@ -19,11 +20,11 @@ namespace metaforce {
|
|||||||
namespace {
|
namespace {
|
||||||
logvisor::Module Log("metaforce::CElementGen");
|
logvisor::Module Log("metaforce::CElementGen");
|
||||||
|
|
||||||
constexpr std::array ShadClsSizes{
|
// constexpr std::array ShadClsSizes{
|
||||||
sizeof(SParticleInstanceTex),
|
// sizeof(SParticleInstanceTex),
|
||||||
sizeof(SParticleInstanceIndTex),
|
// sizeof(SParticleInstanceIndTex),
|
||||||
sizeof(SParticleInstanceNoTex),
|
// sizeof(SParticleInstanceNoTex),
|
||||||
};
|
// };
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
u16 CElementGen::g_GlobalSeed = 99;
|
u16 CElementGen::g_GlobalSeed = 99;
|
||||||
@ -35,9 +36,9 @@ bool CElementGen::g_ParticleSystemInitialized = false;
|
|||||||
bool CElementGen::sMoveRedToAlphaBuffer = false;
|
bool CElementGen::sMoveRedToAlphaBuffer = false;
|
||||||
CParticle* CElementGen::g_currentParticle = nullptr;
|
CParticle* CElementGen::g_currentParticle = nullptr;
|
||||||
|
|
||||||
std::vector<SParticleInstanceTex> g_instTexData;
|
// std::vector<SParticleInstanceTex> g_instTexData;
|
||||||
std::vector<SParticleInstanceIndTex> g_instIndTexData;
|
// std::vector<SParticleInstanceIndTex> g_instIndTexData;
|
||||||
std::vector<SParticleInstanceNoTex> g_instNoTexData;
|
// std::vector<SParticleInstanceNoTex> g_instNoTexData;
|
||||||
|
|
||||||
void CElementGen::Initialize() {
|
void CElementGen::Initialize() {
|
||||||
if (g_ParticleSystemInitialized)
|
if (g_ParticleSystemInitialized)
|
||||||
@ -210,21 +211,21 @@ CElementGen::CElementGen(TToken<CGenDescription> gen, EModelOrientationType orie
|
|||||||
if (x26c_31_LINE) {
|
if (x26c_31_LINE) {
|
||||||
CUVElement* texr = desc->x54_x40_TEXR.get();
|
CUVElement* texr = desc->x54_x40_TEXR.get();
|
||||||
// TODO
|
// TODO
|
||||||
// aurora::gfx::TextureHandle tex;
|
// aurora::gfx::TextureHandle tex;
|
||||||
// if (texr)
|
// if (texr)
|
||||||
// tex = texr->GetValueTexture(0).GetObj()->GetTexture();
|
// tex = texr->GetValueTexture(0).GetObj()->GetTexture();
|
||||||
int maxVerts = x90_MAXP;
|
int maxVerts = x90_MAXP;
|
||||||
// m_lineRenderer.reset(
|
// m_lineRenderer.reset(
|
||||||
// new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, maxVerts * 2, tex, x26c_26_AAPH, x26c_28_zTest));
|
// new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, maxVerts * 2, tex, x26c_26_AAPH, x26c_28_zTest));
|
||||||
} else {
|
} else {
|
||||||
m_shaderClass = CElementGenShaders::GetShaderClass(*this);
|
m_shaderClass = CElementGenShaders::GetShaderClass(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_RecreatePipelines();
|
_RecreatePipelines();
|
||||||
// CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
|
// CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
|
||||||
// CElementGenShaders::BuildShaderDataBinding(ctx, *this);
|
// CElementGenShaders::BuildShaderDataBinding(ctx, *this);
|
||||||
// return true;
|
// return true;
|
||||||
// } BooTrace);
|
// } BooTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
CElementGen::~CElementGen() {
|
CElementGen::~CElementGen() {
|
||||||
@ -260,17 +261,17 @@ void CElementGen::_RecreatePipelines() {
|
|||||||
size_t maxInsts = x26c_30_MBLR ? 2560 * 2 : 2560; // x26c_30_MBLR ? (x270_MBSP * x90_MAXP) : x90_MAXP;
|
size_t maxInsts = x26c_30_MBLR ? 2560 * 2 : 2560; // x26c_30_MBLR ? (x270_MBSP * x90_MAXP) : x90_MAXP;
|
||||||
maxInsts = (maxInsts == 0 ? 256 : maxInsts);
|
maxInsts = (maxInsts == 0 ? 256 : maxInsts);
|
||||||
|
|
||||||
// CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
|
// CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
|
||||||
// if (!x26c_31_LINE) {
|
// if (!x26c_31_LINE) {
|
||||||
// m_instBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, ShadClsSizes[size_t(m_shaderClass)], maxInsts);
|
// m_instBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, ShadClsSizes[size_t(m_shaderClass)], maxInsts);
|
||||||
// m_uniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1);
|
// m_uniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1);
|
||||||
// }
|
// }
|
||||||
// if (x28_loadedGenDesc->x45_24_x31_26_PMUS) {
|
// if (x28_loadedGenDesc->x45_24_x31_26_PMUS) {
|
||||||
// m_instBufPmus = ctx.newDynamicBuffer(boo::BufferUse::Vertex, ShadClsSizes[size_t(m_shaderClass)], maxInsts);
|
// m_instBufPmus = ctx.newDynamicBuffer(boo::BufferUse::Vertex, ShadClsSizes[size_t(m_shaderClass)], maxInsts);
|
||||||
// m_uniformBufPmus = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1);
|
// m_uniformBufPmus = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1);
|
||||||
// }
|
// }
|
||||||
// return true;
|
// return true;
|
||||||
// } BooTrace);
|
// } BooTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CElementGen::InternalUpdate(double dt) {
|
bool CElementGen::InternalUpdate(double dt) {
|
||||||
@ -838,12 +839,12 @@ u32 CElementGen::GetSystemCount() const {
|
|||||||
|
|
||||||
void CElementGen::Render(const CActorLights* actorLights) {
|
void CElementGen::Render(const CActorLights* actorLights) {
|
||||||
// Check to make sure our buffers are ready to render
|
// Check to make sure our buffers are ready to render
|
||||||
if (!x26c_31_LINE) { // && (!m_instBuf || !m_uniformBuf)
|
// if (!x26c_31_LINE) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
if (x28_loadedGenDesc->x45_24_x31_26_PMUS) { // && (!m_instBufPmus || !m_uniformBufPmus)
|
// if (x28_loadedGenDesc->x45_24_x31_26_PMUS) { // && (!m_instBufPmus || !m_uniformBufPmus)
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CElementGen::Render {}"), *x1c_genDesc.GetObjectTag()).c_str(),
|
SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CElementGen::Render {}"), *x1c_genDesc.GetObjectTag()).c_str(),
|
||||||
zeus::skYellow);
|
zeus::skYellow);
|
||||||
@ -876,16 +877,19 @@ void CElementGen::Render(const CActorLights* actorLights) {
|
|||||||
|
|
||||||
void CElementGen::RenderModels(const CActorLights* actorLights) {
|
void CElementGen::RenderModels(const CActorLights* actorLights) {
|
||||||
// Check to make sure our buffers are ready to render
|
// Check to make sure our buffers are ready to render
|
||||||
if (!x26c_31_LINE) { // && (!m_instBuf || !m_uniformBuf)
|
// if (!x26c_31_LINE) { // && (!m_instBuf || !m_uniformBuf)
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
if (x28_loadedGenDesc->x45_24_x31_26_PMUS) { // && (!m_instBufPmus || !m_uniformBufPmus)
|
// if (x28_loadedGenDesc->x45_24_x31_26_PMUS) { // && (!m_instBufPmus || !m_uniformBufPmus)
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
CParticleGlobals::instance()->m_particleAccessParameters = nullptr;
|
CParticleGlobals::instance()->m_particleAccessParameters = nullptr;
|
||||||
if (x26d_26_modelsUseLights)
|
if (x26d_26_modelsUseLights) {
|
||||||
CGraphics::SetLightState(x274_backupLightActive);
|
CGraphics::SetLightState(x274_backupLightActive);
|
||||||
|
} else {
|
||||||
|
CGraphics::SetAmbientColor(zeus::skWhite);
|
||||||
|
}
|
||||||
CGlobalRandom gr(x27c_randState);
|
CGlobalRandom gr(x27c_randState);
|
||||||
|
|
||||||
CGenDescription* desc = x1c_genDesc.GetObj();
|
CGenDescription* desc = x1c_genDesc.GetObj();
|
||||||
@ -897,20 +901,24 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
|
|||||||
bool moveRedToAlphaBuffer = false;
|
bool moveRedToAlphaBuffer = false;
|
||||||
|
|
||||||
if (desc->x45_24_x31_26_PMUS) {
|
if (desc->x45_24_x31_26_PMUS) {
|
||||||
if (sMoveRedToAlphaBuffer && desc->x44_31_x31_25_PMAB && desc->x54_x40_TEXR)
|
if (sMoveRedToAlphaBuffer && desc->x44_31_x31_25_PMAB && desc->x54_x40_TEXR) {
|
||||||
moveRedToAlphaBuffer = true;
|
moveRedToAlphaBuffer = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (desc->x44_31_x31_25_PMAB) {
|
if (desc->x44_31_x31_25_PMAB) {
|
||||||
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false);
|
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false);
|
||||||
if (moveRedToAlphaBuffer)
|
if (moveRedToAlphaBuffer) {
|
||||||
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear);
|
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear);
|
||||||
else
|
} else {
|
||||||
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One,
|
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One,
|
||||||
ERglLogicOp::Clear);
|
ERglLogicOp::Clear);
|
||||||
|
CGraphics::SetAlphaCompare(ERglAlphaFunc::Greater, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true);
|
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true);
|
||||||
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha,
|
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha,
|
||||||
ERglLogicOp::Clear);
|
ERglLogicOp::Clear);
|
||||||
|
CGraphics::SetAlphaCompare(ERglAlphaFunc::Greater, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGraphics::SetCullMode(ERglCullMode::None);
|
CGraphics::SetCullMode(ERglCullMode::None);
|
||||||
@ -920,37 +928,60 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
|
|||||||
int partFrame = x74_curFrame - target.x28_startFrame;
|
int partFrame = x74_curFrame - target.x28_startFrame;
|
||||||
cachedTex = texr->GetValueTexture(partFrame).GetObj();
|
cachedTex = texr->GetValueTexture(partFrame).GetObj();
|
||||||
cachedTex->Load(GX::TEXMAP0, EClampMode::Repeat);
|
cachedTex->Load(GX::TEXMAP0, EClampMode::Repeat);
|
||||||
/* Shade as TEXC * RASC and TEXA * RASA */
|
|
||||||
|
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc);
|
||||||
if (moveRedToAlphaBuffer) {
|
if (moveRedToAlphaBuffer) {
|
||||||
/* Color = Prev.rgb * Prev.a */
|
CGX::SetTevColorIn(GX::TEVSTAGE1, GX::CC_ZERO, GX::CC_CPREV, GX::CC_APREV, GX::CC_ZERO);
|
||||||
/* Alpha = Tex.r * Prev.a */
|
CGX::SetTevAlphaIn(GX::TEVSTAGE1, GX::CA_ZERO, GX::CA_TEXA, GX::CA_APREV, GX::CA_ZERO);
|
||||||
|
CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE1);
|
||||||
|
CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL);
|
||||||
|
GXSetTevSwapMode(GX::TEVSTAGE1, GX::TEV_SWAP0, GX::TEV_SWAP1);
|
||||||
|
CGX::SetNumTevStages(2);
|
||||||
|
constexpr std::array vtxDescList{
|
||||||
|
GX::VtxDescList{GX::VA_POS, GX::DIRECT},
|
||||||
|
GX::VtxDescList{GX::VA_CLR0, GX::DIRECT},
|
||||||
|
GX::VtxDescList{GX::VA_TEX0, GX::DIRECT},
|
||||||
|
GX::VtxDescList{},
|
||||||
|
};
|
||||||
|
CGX::SetVtxDescv(vtxDescList.data());
|
||||||
|
CGX::SetChanCtrl(CGX::EChannelId::Channel0, {});
|
||||||
|
CGX::SetNumChans(1);
|
||||||
|
CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY);
|
||||||
|
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR0A0);
|
||||||
|
CGX::SetNumTexGens(1);
|
||||||
|
} else {
|
||||||
|
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
|
||||||
}
|
}
|
||||||
|
|
||||||
texConst = texr->HasConstantTexture();
|
texConst = texr->HasConstantTexture();
|
||||||
texr->GetValueUV(partFrame, uvs);
|
texr->GetValueUV(partFrame, uvs);
|
||||||
|
} else {
|
||||||
|
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::skPassThru);
|
||||||
|
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m_shaderClass) {
|
// switch (m_shaderClass) {
|
||||||
case CElementGenShaders::EShaderClass::Tex:
|
// case CElementGenShaders::EShaderClass::Tex:
|
||||||
g_instTexData.clear();
|
// g_instTexData.clear();
|
||||||
g_instTexData.reserve(x30_particles.size());
|
// g_instTexData.reserve(x30_particles.size());
|
||||||
break;
|
// break;
|
||||||
case CElementGenShaders::EShaderClass::NoTex:
|
// case CElementGenShaders::EShaderClass::NoTex:
|
||||||
g_instNoTexData.clear();
|
// g_instNoTexData.clear();
|
||||||
g_instNoTexData.reserve(x30_particles.size());
|
// g_instNoTexData.reserve(x30_particles.size());
|
||||||
break;
|
// break;
|
||||||
default:
|
// default:
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
// Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
SParticleUniforms uniformData = {CGraphics::GetPerspectiveProjectionMatrix(/*true*/), {1.f, 1.f, 1.f, 1.f}};
|
// SParticleUniforms uniformData = {CGraphics::GetPerspectiveProjectionMatrix(/*true*/), {1.f, 1.f, 1.f, 1.f}};
|
||||||
|
|
||||||
// m_uniformBufPmus->load(&uniformData, sizeof(SParticleUniforms));
|
// m_uniformBufPmus->load(&uniformData, sizeof(SParticleUniforms));
|
||||||
//
|
//
|
||||||
// if (moveRedToAlphaBuffer)
|
// if (moveRedToAlphaBuffer)
|
||||||
// CGraphics::SetShaderDataBinding(m_redToAlphaDataBindPmus[g_Renderer->IsThermalVisorHotPass()]);
|
// CGraphics::SetShaderDataBinding(m_redToAlphaDataBindPmus[g_Renderer->IsThermalVisorHotPass()]);
|
||||||
// else
|
// else
|
||||||
// CGraphics::SetShaderDataBinding(m_normalDataBindPmus[g_Renderer->IsThermalVisorHotPass()]);
|
// CGraphics::SetShaderDataBinding(m_normalDataBindPmus[g_Renderer->IsThermalVisorHotPass()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
zeus::CTransform orient = zeus::CTransform();
|
zeus::CTransform orient = zeus::CTransform();
|
||||||
@ -1041,54 +1072,44 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
|
|||||||
CGraphics::SetModelMatrix((x10c_globalScaleTransform * partTrans) * x178_localScaleTransform);
|
CGraphics::SetModelMatrix((x10c_globalScaleTransform * partTrans) * x178_localScaleTransform);
|
||||||
|
|
||||||
if (desc->x45_24_x31_26_PMUS) {
|
if (desc->x45_24_x31_26_PMUS) {
|
||||||
if (!texConst) {
|
if (moveRedToAlphaBuffer) {
|
||||||
CTexture* tex = texr->GetValueTexture(x74_curFrame - particle.x28_startFrame).GetObj();
|
CGX::Begin(GX::QUADS, GX::VTXFMT0, 4);
|
||||||
if (tex != cachedTex) {
|
GXPosition3f32(0.5f, 0.f, 0.5f);
|
||||||
tex->Load(GX::TEXMAP0, EClampMode::Repeat);
|
GXColor4f32(col);
|
||||||
cachedTex = tex;
|
GXTexCoord2f32(uvs.xMax, uvs.yMax);
|
||||||
}
|
GXPosition3f32(-0.5f, 0.f, 0.5f);
|
||||||
}
|
GXColor4f32(col);
|
||||||
|
GXTexCoord2f32(uvs.xMin, uvs.yMax);
|
||||||
switch (m_shaderClass) {
|
GXPosition3f32(-0.5f, 0.f, -0.5f);
|
||||||
case CElementGenShaders::EShaderClass::Tex: {
|
GXColor4f32(col);
|
||||||
SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
GXTexCoord2f32(uvs.xMin, uvs.yMin);
|
||||||
inst.pos[0] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, 0.5f};
|
GXPosition3f32(0.5f, 0.f, -0.5f);
|
||||||
inst.pos[1] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, 0.5f};
|
GXColor4f32(col);
|
||||||
inst.pos[2] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, -0.5f};
|
GXTexCoord2f32(uvs.xMax, uvs.yMin);
|
||||||
inst.pos[3] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, -0.5f};
|
CGX::End();
|
||||||
inst.color = col;
|
} else {
|
||||||
inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
CGraphics::StreamBegin(GX::QUADS);
|
||||||
inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
CGraphics::StreamColor(col);
|
||||||
inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
CGraphics::StreamTexcoord(uvs.xMax, uvs.yMax);
|
||||||
inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
CGraphics::StreamVertex(0.5f, 0.f, 0.5f);
|
||||||
break;
|
CGraphics::StreamTexcoord(uvs.xMin, uvs.yMax);
|
||||||
}
|
CGraphics::StreamVertex(-0.5f, 0.f, 0.5f);
|
||||||
case CElementGenShaders::EShaderClass::NoTex: {
|
CGraphics::StreamTexcoord(uvs.xMin, uvs.yMin);
|
||||||
SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
CGraphics::StreamVertex(-0.5f, 0.f, -0.5f);
|
||||||
inst.pos[0] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, 0.5f};
|
CGraphics::StreamTexcoord(uvs.xMax, uvs.yMin);
|
||||||
inst.pos[1] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, 0.5f};
|
CGraphics::StreamVertex(0.5f, 0.f, -0.5f);
|
||||||
inst.pos[2] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, -0.5f};
|
CGraphics::StreamEnd();
|
||||||
inst.pos[3] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, -0.5f};
|
|
||||||
inst.color = col;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CModel* model = desc->x5c_x48_PMDL.GetObj();
|
CModel* model = desc->x5c_x48_PMDL.GetObj();
|
||||||
if (actorLights)
|
|
||||||
actorLights->ActivateLights();
|
|
||||||
if (g_subtractBlend) {
|
if (g_subtractBlend) {
|
||||||
model->Draw({5, 0, 1, zeus::CColor(1.f, 0.5f)});
|
model->Draw({5, 0, 1, zeus::CColor{1.f, 0.5f}});
|
||||||
} else if (desc->x44_31_x31_25_PMAB) {
|
} else if (desc->x44_31_x31_25_PMAB) {
|
||||||
CModelFlags flags{7, 0, 1, col};
|
model->Draw({7, 0, 1, col});
|
||||||
// flags.m_extendedShader = EExtendedShader::ForcedAdditiveNoZWrite;
|
|
||||||
model->Draw(flags);
|
|
||||||
} else if (1.f == col.a()) {
|
} else if (1.f == col.a()) {
|
||||||
model->Draw({0, 0, 3, zeus::skWhite});
|
model->Draw({0, 0, 3, zeus::skWhite});
|
||||||
} else {
|
} else {
|
||||||
model->Draw({5, 0, 1, zeus::CColor(1.f, col.a())});
|
model->Draw({5, 0, 1, zeus::CColor{1.f, col.a()}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1096,28 +1117,15 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
|
|||||||
++matrixIt;
|
++matrixIt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desc->x45_24_x31_26_PMUS) {
|
if (x26d_26_modelsUseLights) {
|
||||||
switch (m_shaderClass) {
|
|
||||||
case CElementGenShaders::EShaderClass::Tex:
|
|
||||||
// m_instBufPmus->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
|
|
||||||
// CGraphics::DrawInstances(0, 4, g_instTexData.size());
|
|
||||||
break;
|
|
||||||
case CElementGenShaders::EShaderClass::NoTex:
|
|
||||||
// m_instBufPmus->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
|
|
||||||
// CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x26d_26_modelsUseLights)
|
|
||||||
CGraphics::DisableAllLights();
|
CGraphics::DisableAllLights();
|
||||||
|
}
|
||||||
|
|
||||||
CGraphics::SetCullMode(ERglCullMode::Front);
|
CGraphics::SetCullMode(ERglCullMode::Front);
|
||||||
if (moveRedToAlphaBuffer) {
|
if (moveRedToAlphaBuffer) {
|
||||||
/* Restore passthrough */
|
GXSetTevSwapMode(GX::TEVSTAGE1, GX::TEV_SWAP0, GX::TEV_SWAP0);
|
||||||
}
|
}
|
||||||
|
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CElementGen::RenderLines() {
|
void CElementGen::RenderLines() {
|
||||||
@ -1258,8 +1266,9 @@ void CElementGen::RenderParticles() {
|
|||||||
bool constUVs = true;
|
bool constUVs = true;
|
||||||
CTexture* cachedTex = nullptr;
|
CTexture* cachedTex = nullptr;
|
||||||
|
|
||||||
SParticleUniforms uniformData = {
|
// SParticleUniforms uniformData = {CGraphics::GetPerspectiveProjectionMatrix(/*true*/) *
|
||||||
CGraphics::GetPerspectiveProjectionMatrix(/*true*/) * CGraphics::g_GXModelView.toMatrix4f(), {1.f, 1.f, 1.f, 1.f}};
|
// CGraphics::g_GXModelView.toMatrix4f(),
|
||||||
|
// {1.f, 1.f, 1.f, 1.f}};
|
||||||
|
|
||||||
if (texr) {
|
if (texr) {
|
||||||
CParticle& target = x30_particles[0];
|
CParticle& target = x30_particles[0];
|
||||||
@ -1269,14 +1278,14 @@ void CElementGen::RenderParticles() {
|
|||||||
|
|
||||||
if (x338_moduColor != zeus::skBlack) {
|
if (x338_moduColor != zeus::skBlack) {
|
||||||
/* Add RASC * PREVC pass for MODU color loaded into channel mat-color */
|
/* Add RASC * PREVC pass for MODU color loaded into channel mat-color */
|
||||||
uniformData.moduColor = x338_moduColor;
|
// uniformData.moduColor = x338_moduColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
texr->GetValueUV(partFrame, uvs);
|
texr->GetValueUV(partFrame, uvs);
|
||||||
constUVs = texr->HasConstantUV();
|
constUVs = texr->HasConstantUV();
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
|
// m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
|
||||||
|
|
||||||
std::vector<CParticleListItem> sortItems;
|
std::vector<CParticleListItem> sortItems;
|
||||||
if (desc->x44_28_x30_28_SORT) {
|
if (desc->x44_28_x30_28_SORT) {
|
||||||
@ -1301,15 +1310,15 @@ void CElementGen::RenderParticles() {
|
|||||||
|
|
||||||
if (g_subtractBlend) {
|
if (g_subtractBlend) {
|
||||||
// FIXME should there be NoTex specializations for RedToAlpha?
|
// FIXME should there be NoTex specializations for RedToAlpha?
|
||||||
// if (moveRedToAlphaBuffer && desc->x54_x40_TEXR)
|
// if (moveRedToAlphaBuffer && desc->x54_x40_TEXR)
|
||||||
// CGraphics::SetShaderDataBinding(m_redToAlphaSubDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
// CGraphics::SetShaderDataBinding(m_redToAlphaSubDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||||
// else
|
// else
|
||||||
// CGraphics::SetShaderDataBinding(m_normalSubDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
// CGraphics::SetShaderDataBinding(m_normalSubDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||||
} else {
|
} else {
|
||||||
// if (moveRedToAlphaBuffer && desc->x54_x40_TEXR)
|
// if (moveRedToAlphaBuffer && desc->x54_x40_TEXR)
|
||||||
// CGraphics::SetShaderDataBinding(m_redToAlphaDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
// CGraphics::SetShaderDataBinding(m_redToAlphaDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||||
// else
|
// else
|
||||||
// CGraphics::SetShaderDataBinding(m_normalDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
// CGraphics::SetShaderDataBinding(m_normalDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mbspVal = std::max(1, x270_MBSP);
|
int mbspVal = std::max(1, x270_MBSP);
|
||||||
@ -1344,19 +1353,19 @@ void CElementGen::RenderParticles() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (m_shaderClass) {
|
// switch (m_shaderClass) {
|
||||||
case CElementGenShaders::EShaderClass::Tex:
|
// case CElementGenShaders::EShaderClass::Tex:
|
||||||
g_instTexData.clear();
|
// g_instTexData.clear();
|
||||||
g_instTexData.reserve(x30_particles.size());
|
// g_instTexData.reserve(x30_particles.size());
|
||||||
break;
|
// break;
|
||||||
case CElementGenShaders::EShaderClass::NoTex:
|
// case CElementGenShaders::EShaderClass::NoTex:
|
||||||
g_instNoTexData.clear();
|
// g_instNoTexData.clear();
|
||||||
g_instNoTexData.reserve(x30_particles.size());
|
// g_instNoTexData.reserve(x30_particles.size());
|
||||||
break;
|
// break;
|
||||||
default:
|
// default:
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
// Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (!x26c_29_ORNT) {
|
if (!x26c_29_ORNT) {
|
||||||
for (size_t i = 0; i < x30_particles.size(); ++i) {
|
for (size_t i = 0; i < x30_particles.size(); ++i) {
|
||||||
@ -1381,67 +1390,67 @@ void CElementGen::RenderParticles() {
|
|||||||
|
|
||||||
const float size = 0.5f * particle.x2c_lineLengthOrSize;
|
const float size = 0.5f * particle.x2c_lineLengthOrSize;
|
||||||
if (0.f == particle.x30_lineWidthOrRota) {
|
if (0.f == particle.x30_lineWidthOrRota) {
|
||||||
switch (m_shaderClass) {
|
// switch (m_shaderClass) {
|
||||||
case CElementGenShaders::EShaderClass::Tex: {
|
// case CElementGenShaders::EShaderClass::Tex: {
|
||||||
SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
// SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||||
inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
// inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
||||||
inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
// inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
||||||
inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
// inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
||||||
inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
// inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
||||||
inst.color = particle.x34_color;
|
// inst.color = particle.x34_color;
|
||||||
inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
// inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||||
inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
// inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||||
inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
// inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||||
inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
// inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case CElementGenShaders::EShaderClass::NoTex: {
|
// case CElementGenShaders::EShaderClass::NoTex: {
|
||||||
SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
// SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||||
inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
// inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
||||||
inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
// inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
||||||
inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
// inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
||||||
inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
// inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
||||||
inst.color = particle.x34_color;
|
// inst.color = particle.x34_color;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
default:
|
// default:
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
} else {
|
} else {
|
||||||
float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
|
float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
|
||||||
float sinT = std::sin(theta) * size;
|
float sinT = std::sin(theta) * size;
|
||||||
float cosT = std::cos(theta) * size;
|
float cosT = std::cos(theta) * size;
|
||||||
|
|
||||||
switch (m_shaderClass) {
|
// switch (m_shaderClass) {
|
||||||
case CElementGenShaders::EShaderClass::Tex: {
|
// case CElementGenShaders::EShaderClass::Tex: {
|
||||||
SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
// SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||||
inst.pos[0] = zeus::CVector4f{viewPoint.x() + sinT + cosT, viewPoint.y(), viewPoint.z() + cosT - sinT, 1.f};
|
// inst.pos[0] = zeus::CVector4f{viewPoint.x() + sinT + cosT, viewPoint.y(), viewPoint.z() + cosT - sinT, 1.f};
|
||||||
inst.pos[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f};
|
// inst.pos[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f};
|
||||||
inst.pos[2] =
|
// inst.pos[2] =
|
||||||
zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), 1.f};
|
// zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), 1.f};
|
||||||
inst.pos[3] =
|
// inst.pos[3] =
|
||||||
zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), 1.f};
|
// zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), 1.f};
|
||||||
inst.color = particle.x34_color;
|
// inst.color = particle.x34_color;
|
||||||
inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
// inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||||
inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
// inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||||
inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
// inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||||
inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
// inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case CElementGenShaders::EShaderClass::NoTex: {
|
// case CElementGenShaders::EShaderClass::NoTex: {
|
||||||
SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
// SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||||
inst.pos[0] = zeus::CVector4f{viewPoint.x() + sinT + cosT, viewPoint.y(), viewPoint.z() + cosT - sinT, 1.f};
|
// inst.pos[0] = zeus::CVector4f{viewPoint.x() + sinT + cosT, viewPoint.y(), viewPoint.z() + cosT - sinT, 1.f};
|
||||||
inst.pos[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f};
|
// inst.pos[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f};
|
||||||
inst.pos[2] =
|
// inst.pos[2] =
|
||||||
zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), 1.f};
|
// zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), 1.f};
|
||||||
inst.pos[3] =
|
// inst.pos[3] =
|
||||||
zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), 1.f};
|
// zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), 1.f};
|
||||||
inst.color = particle.x34_color;
|
// inst.color = particle.x34_color;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
default:
|
// default:
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1487,65 +1496,65 @@ void CElementGen::RenderParticles() {
|
|||||||
texr->GetValueUV(partFrame, uvs);
|
texr->GetValueUV(partFrame, uvs);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m_shaderClass) {
|
// switch (m_shaderClass) {
|
||||||
case CElementGenShaders::EShaderClass::Tex: {
|
// case CElementGenShaders::EShaderClass::Tex: {
|
||||||
SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
// SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||||
viewPoint += rightVec * 0.5f;
|
// viewPoint += rightVec * 0.5f;
|
||||||
inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
// inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
||||||
inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
// inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
||||||
viewPoint -= rightVec;
|
// viewPoint -= rightVec;
|
||||||
inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
// inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
||||||
inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
// inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
||||||
inst.color = particle.x34_color;
|
// inst.color = particle.x34_color;
|
||||||
inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
// inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||||
inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
// inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||||
inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
// inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||||
inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
// inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case CElementGenShaders::EShaderClass::NoTex: {
|
// case CElementGenShaders::EShaderClass::NoTex: {
|
||||||
SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
// SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||||
viewPoint += rightVec * 0.5f;
|
// viewPoint += rightVec * 0.5f;
|
||||||
inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
// inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
||||||
inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
// inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
||||||
viewPoint -= rightVec;
|
// viewPoint -= rightVec;
|
||||||
inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
// inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
||||||
inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
// inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
||||||
inst.color = particle.x34_color;
|
// inst.color = particle.x34_color;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
default:
|
// default:
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m_shaderClass) {
|
switch (m_shaderClass) {
|
||||||
case CElementGenShaders::EShaderClass::Tex:
|
case CElementGenShaders::EShaderClass::Tex:
|
||||||
// m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
|
// m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
|
||||||
// CGraphics::DrawInstances(0, 4, g_instTexData.size());
|
// CGraphics::DrawInstances(0, 4, g_instTexData.size());
|
||||||
break;
|
break;
|
||||||
case CElementGenShaders::EShaderClass::NoTex:
|
case CElementGenShaders::EShaderClass::NoTex:
|
||||||
// m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
|
// m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
|
||||||
// CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
|
// CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (m_shaderClass) {
|
// switch (m_shaderClass) {
|
||||||
case CElementGenShaders::EShaderClass::Tex:
|
// case CElementGenShaders::EShaderClass::Tex:
|
||||||
g_instTexData.clear();
|
// g_instTexData.clear();
|
||||||
g_instTexData.reserve(x30_particles.size() * mbspVal);
|
// g_instTexData.reserve(x30_particles.size() * mbspVal);
|
||||||
break;
|
// break;
|
||||||
case CElementGenShaders::EShaderClass::NoTex:
|
// case CElementGenShaders::EShaderClass::NoTex:
|
||||||
g_instNoTexData.clear();
|
// g_instNoTexData.clear();
|
||||||
g_instNoTexData.reserve(x30_particles.size() * mbspVal);
|
// g_instNoTexData.reserve(x30_particles.size() * mbspVal);
|
||||||
break;
|
// break;
|
||||||
default:
|
// default:
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
// Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
const float mbspFac = 1.f / float(mbspVal);
|
const float mbspFac = 1.f / float(mbspVal);
|
||||||
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);
|
||||||
@ -1569,32 +1578,32 @@ void CElementGen::RenderParticles() {
|
|||||||
vec += mbspVec;
|
vec += mbspVec;
|
||||||
zeus::CVector3f vec2 = systemCameraMatrix * vec;
|
zeus::CVector3f vec2 = systemCameraMatrix * vec;
|
||||||
|
|
||||||
switch (m_shaderClass) {
|
// switch (m_shaderClass) {
|
||||||
case CElementGenShaders::EShaderClass::Tex: {
|
// case CElementGenShaders::EShaderClass::Tex: {
|
||||||
SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
// SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||||
inst.pos[0] = zeus::CVector4f{vec2.x() + size, vec2.y(), vec2.z() + size, 1.f};
|
// inst.pos[0] = zeus::CVector4f{vec2.x() + size, vec2.y(), vec2.z() + size, 1.f};
|
||||||
inst.pos[1] = zeus::CVector4f{vec2.x() - size, vec2.y(), vec2.z() + size, 1.f};
|
// inst.pos[1] = zeus::CVector4f{vec2.x() - size, vec2.y(), vec2.z() + size, 1.f};
|
||||||
inst.pos[2] = zeus::CVector4f{vec2.x() + size, vec2.y(), vec2.z() - size, 1.f};
|
// inst.pos[2] = zeus::CVector4f{vec2.x() + size, vec2.y(), vec2.z() - size, 1.f};
|
||||||
inst.pos[3] = zeus::CVector4f{vec2.x() - size, vec2.y(), vec2.z() - size, 1.f};
|
// inst.pos[3] = zeus::CVector4f{vec2.x() - size, vec2.y(), vec2.z() - size, 1.f};
|
||||||
inst.color = particle.x34_color;
|
// inst.color = particle.x34_color;
|
||||||
inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
// inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||||
inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
// inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||||
inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
// inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||||
inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
// inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case CElementGenShaders::EShaderClass::NoTex: {
|
// case CElementGenShaders::EShaderClass::NoTex: {
|
||||||
SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
// SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||||
inst.pos[0] = zeus::CVector4f{vec2.x() + size, vec2.y(), vec2.z() + size, 1.f};
|
// inst.pos[0] = zeus::CVector4f{vec2.x() + size, vec2.y(), vec2.z() + size, 1.f};
|
||||||
inst.pos[1] = zeus::CVector4f{vec2.x() - size, vec2.y(), vec2.z() + size, 1.f};
|
// inst.pos[1] = zeus::CVector4f{vec2.x() - size, vec2.y(), vec2.z() + size, 1.f};
|
||||||
inst.pos[2] = zeus::CVector4f{vec2.x() + size, vec2.y(), vec2.z() - size, 1.f};
|
// inst.pos[2] = zeus::CVector4f{vec2.x() + size, vec2.y(), vec2.z() - size, 1.f};
|
||||||
inst.pos[3] = zeus::CVector4f{vec2.x() - size, vec2.y(), vec2.z() - size, 1.f};
|
// inst.pos[3] = zeus::CVector4f{vec2.x() - size, vec2.y(), vec2.z() - size, 1.f};
|
||||||
inst.color = particle.x34_color;
|
// inst.color = particle.x34_color;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
default:
|
// default:
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
|
float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
|
||||||
@ -1605,43 +1614,43 @@ void CElementGen::RenderParticles() {
|
|||||||
vec += mbspVec;
|
vec += mbspVec;
|
||||||
zeus::CVector3f vec2 = systemCameraMatrix * vec;
|
zeus::CVector3f vec2 = systemCameraMatrix * vec;
|
||||||
|
|
||||||
switch (m_shaderClass) {
|
// switch (m_shaderClass) {
|
||||||
case CElementGenShaders::EShaderClass::Tex: {
|
// case CElementGenShaders::EShaderClass::Tex: {
|
||||||
SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
// SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||||
inst.pos[0] = zeus::CVector4f{vec2.x() + sinT + cosT, vec2.y(), vec2.z() + cosT - sinT, 1.f};
|
// inst.pos[0] = zeus::CVector4f{vec2.x() + sinT + cosT, vec2.y(), vec2.z() + cosT - sinT, 1.f};
|
||||||
inst.pos[1] = zeus::CVector4f{vec2.x() + sinT - cosT, vec2.y(), vec2.z() + sinT + cosT, 1.f};
|
// inst.pos[1] = zeus::CVector4f{vec2.x() + sinT - cosT, vec2.y(), vec2.z() + sinT + cosT, 1.f};
|
||||||
inst.pos[2] = zeus::CVector4f{vec2.x() + (cosT - sinT), vec2.y(), vec2.z() + (-cosT - sinT), 1.f};
|
// inst.pos[2] = zeus::CVector4f{vec2.x() + (cosT - sinT), vec2.y(), vec2.z() + (-cosT - sinT), 1.f};
|
||||||
inst.pos[3] = zeus::CVector4f{vec2.x() - (sinT + cosT), vec2.y(), vec2.z() - (cosT - sinT), 1.f};
|
// inst.pos[3] = zeus::CVector4f{vec2.x() - (sinT + cosT), vec2.y(), vec2.z() - (cosT - sinT), 1.f};
|
||||||
inst.color = particle.x34_color;
|
// inst.color = particle.x34_color;
|
||||||
inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
// inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||||
inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
// inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||||
inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
// inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||||
inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
// inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case CElementGenShaders::EShaderClass::NoTex: {
|
// case CElementGenShaders::EShaderClass::NoTex: {
|
||||||
SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
// SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||||
inst.pos[0] = zeus::CVector4f{vec2.x() + sinT + cosT, vec2.y(), vec2.z() + cosT - sinT, 1.f};
|
// inst.pos[0] = zeus::CVector4f{vec2.x() + sinT + cosT, vec2.y(), vec2.z() + cosT - sinT, 1.f};
|
||||||
inst.pos[1] = zeus::CVector4f{vec2.x() + sinT - cosT, vec2.y(), vec2.z() + sinT + cosT, 1.f};
|
// inst.pos[1] = zeus::CVector4f{vec2.x() + sinT - cosT, vec2.y(), vec2.z() + sinT + cosT, 1.f};
|
||||||
inst.pos[2] = zeus::CVector4f{vec2.x() + (cosT - sinT), vec2.y(), vec2.z() + (-cosT - sinT), 1.f};
|
// inst.pos[2] = zeus::CVector4f{vec2.x() + (cosT - sinT), vec2.y(), vec2.z() + (-cosT - sinT), 1.f};
|
||||||
inst.pos[3] = zeus::CVector4f{vec2.x() - (sinT + cosT), vec2.y(), vec2.z() - (cosT - sinT), 1.f};
|
// inst.pos[3] = zeus::CVector4f{vec2.x() - (sinT + cosT), vec2.y(), vec2.z() - (cosT - sinT), 1.f};
|
||||||
inst.color = particle.x34_color;
|
// inst.color = particle.x34_color;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
default:
|
// default:
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (m_shaderClass) {
|
switch (m_shaderClass) {
|
||||||
case CElementGenShaders::EShaderClass::Tex:
|
case CElementGenShaders::EShaderClass::Tex:
|
||||||
// m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
|
// m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
|
||||||
// CGraphics::DrawInstances(0, 4, g_instTexData.size());
|
// CGraphics::DrawInstances(0, 4, g_instTexData.size());
|
||||||
break;
|
break;
|
||||||
case CElementGenShaders::EShaderClass::NoTex:
|
case CElementGenShaders::EShaderClass::NoTex:
|
||||||
// m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
|
// m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
|
||||||
// CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
|
// CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -1660,9 +1669,10 @@ void CElementGen::RenderParticlesIndirectTexture() {
|
|||||||
x178_localScaleTransform;
|
x178_localScaleTransform;
|
||||||
CGraphics::SetModelMatrix(systemViewPointMatrix);
|
CGraphics::SetModelMatrix(systemViewPointMatrix);
|
||||||
|
|
||||||
SParticleUniforms uniformData = {
|
// SParticleUniforms uniformData = {CGraphics::GetPerspectiveProjectionMatrix(/*true*/) *
|
||||||
CGraphics::GetPerspectiveProjectionMatrix(/*true*/) * CGraphics::g_GXModelView.toMatrix4f(), {1.f, 1.f, 1.f, 1.f}};
|
// CGraphics::g_GXModelView.toMatrix4f(),
|
||||||
// m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
|
// {1.f, 1.f, 1.f, 1.f}};
|
||||||
|
// m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
|
||||||
|
|
||||||
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
|
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
|
||||||
|
|
||||||
@ -1712,11 +1722,11 @@ void CElementGen::RenderParticlesIndirectTexture() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
g_instIndTexData.clear();
|
// g_instIndTexData.clear();
|
||||||
g_instIndTexData.reserve(x30_particles.size());
|
// g_instIndTexData.reserve(x30_particles.size());
|
||||||
|
|
||||||
// if (!x30_particles.empty())
|
// if (!x30_particles.empty())
|
||||||
// CGraphics::SetShaderDataBinding(m_normalDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
// CGraphics::SetShaderDataBinding(m_normalDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||||
|
|
||||||
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);
|
||||||
@ -1764,35 +1774,35 @@ void CElementGen::RenderParticlesIndirectTexture() {
|
|||||||
|
|
||||||
CGraphics::ResolveSpareTexture(clipRect);
|
CGraphics::ResolveSpareTexture(clipRect);
|
||||||
|
|
||||||
SParticleInstanceIndTex& inst = g_instIndTexData.emplace_back();
|
// SParticleInstanceIndTex& inst = g_instIndTexData.emplace_back();
|
||||||
inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
// inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
||||||
inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
// inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
||||||
inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
// inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
||||||
inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
// inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
||||||
inst.color = particle.x34_color;
|
// inst.color = particle.x34_color;
|
||||||
inst.texrTindUVs[0] = zeus::CVector4f{uvs.xMax, uvs.yMax, uvsInd.xMax, uvsInd.yMax};
|
// inst.texrTindUVs[0] = zeus::CVector4f{uvs.xMax, uvs.yMax, uvsInd.xMax, uvsInd.yMax};
|
||||||
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};
|
||||||
// switch (CGraphics::g_BooPlatform) {
|
// switch (CGraphics::g_BooPlatform) {
|
||||||
// case boo::IGraphicsDataFactory::Platform::OpenGL:
|
// case boo::IGraphicsDataFactory::Platform::OpenGL:
|
||||||
|
// inst.sceneUVs =
|
||||||
|
// zeus::CVector4f{clipRect.x18_uvXMin, clipRect.x24_uvYMax, clipRect.x1c_uvXMax, clipRect.x20_uvYMin};
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
// inst.sceneUVs =
|
// inst.sceneUVs =
|
||||||
// zeus::CVector4f{clipRect.x18_uvXMin, clipRect.x24_uvYMax, clipRect.x1c_uvXMax, clipRect.x20_uvYMin};
|
// zeus::CVector4f{clipRect.x18_uvXMin, 1.f - clipRect.x24_uvYMax, clipRect.x1c_uvXMax, 1.f - clipRect.x20_uvYMin};
|
||||||
// break;
|
// break;
|
||||||
// default:
|
// }
|
||||||
inst.sceneUVs = zeus::CVector4f{clipRect.x18_uvXMin, 1.f - clipRect.x24_uvYMax, clipRect.x1c_uvXMax,
|
// CGraphics::DrawInstances(0, 4, 1, g_instIndTexData.size() - 1);
|
||||||
1.f - clipRect.x20_uvYMin};
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// CGraphics::DrawInstances(0, 4, 1, g_instIndTexData.size() - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_instIndTexData.size()) {
|
// if (g_instIndTexData.size()) {
|
||||||
// m_instBuf->load(g_instIndTexData.data(), g_instIndTexData.size() * sizeof(SParticleInstanceIndTex));
|
// m_instBuf->load(g_instIndTexData.data(), g_instIndTexData.size() * sizeof(SParticleInstanceIndTex));
|
||||||
// TODO! this looks like a bug
|
// TODO! this looks like a bug
|
||||||
// CGraphics::SetShaderDataBinding(m_normalDataBind);
|
// CGraphics::SetShaderDataBinding(m_normalDataBind);
|
||||||
// CGraphics::DrawInstances(0, 4, g_instIndTexData.size());
|
// CGraphics::DrawInstances(0, 4, g_instIndTexData.size());
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void CElementGen::SetOrientation(const zeus::CTransform& orientation) {
|
void CElementGen::SetOrientation(const zeus::CTransform& orientation) {
|
||||||
|
@ -59,30 +59,30 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SParticleInstanceTex {
|
//struct SParticleInstanceTex {
|
||||||
std::array<zeus::CVector4f, 4> pos;
|
// std::array<zeus::CVector4f, 4> pos;
|
||||||
zeus::CColor color;
|
// zeus::CColor color;
|
||||||
std::array<zeus::CVector2f, 4> uvs;
|
// std::array<zeus::CVector2f, 4> uvs;
|
||||||
};
|
//};
|
||||||
extern std::vector<SParticleInstanceTex> g_instTexData;
|
//extern std::vector<SParticleInstanceTex> g_instTexData;
|
||||||
|
//
|
||||||
struct SParticleInstanceIndTex {
|
//struct SParticleInstanceIndTex {
|
||||||
std::array<zeus::CVector4f, 4> pos;
|
// std::array<zeus::CVector4f, 4> pos;
|
||||||
zeus::CColor color;
|
// zeus::CColor color;
|
||||||
std::array<zeus::CVector4f, 4> texrTindUVs;
|
// std::array<zeus::CVector4f, 4> texrTindUVs;
|
||||||
zeus::CVector4f sceneUVs;
|
// zeus::CVector4f sceneUVs;
|
||||||
};
|
//};
|
||||||
extern std::vector<SParticleInstanceIndTex> g_instIndTexData;
|
//extern std::vector<SParticleInstanceIndTex> g_instIndTexData;
|
||||||
|
//
|
||||||
struct SParticleInstanceNoTex {
|
//struct SParticleInstanceNoTex {
|
||||||
std::array<zeus::CVector4f, 4> pos;
|
// std::array<zeus::CVector4f, 4> pos;
|
||||||
zeus::CColor color;
|
// zeus::CColor color;
|
||||||
};
|
//};
|
||||||
extern std::vector<SParticleInstanceNoTex> g_instNoTexData;
|
//extern std::vector<SParticleInstanceNoTex> g_instNoTexData;
|
||||||
|
//
|
||||||
struct SParticleUniforms {
|
//struct SParticleUniforms {
|
||||||
zeus::CMatrix4f mvp;
|
// zeus::CMatrix4f mvp;
|
||||||
zeus::CColor moduColor;
|
// zeus::CColor moduColor;
|
||||||
};
|
//};
|
||||||
|
|
||||||
} // namespace metaforce
|
} // namespace metaforce
|
||||||
|
@ -132,11 +132,6 @@ struct Light {
|
|||||||
|
|
||||||
[[nodiscard]] bool get_dxt_compression_supported() noexcept;
|
[[nodiscard]] bool get_dxt_compression_supported() noexcept;
|
||||||
|
|
||||||
void stream_begin(GX::Primitive primitive) noexcept;
|
|
||||||
void stream_vertex(metaforce::EStreamFlags flags, const zeus::CVector3f& pos, const zeus::CVector3f& nrm,
|
|
||||||
const zeus::CColor& color, const zeus::CVector2f& uv) noexcept;
|
|
||||||
void stream_end() noexcept;
|
|
||||||
|
|
||||||
// GX state
|
// GX state
|
||||||
void bind_texture(GX::TexMapID id, metaforce::EClampMode clamp, const TextureHandle& tex, float lod) noexcept;
|
void bind_texture(GX::TexMapID id, metaforce::EClampMode clamp, const TextureHandle& tex, float lod) noexcept;
|
||||||
void unbind_texture(GX::TexMapID id) noexcept;
|
void unbind_texture(GX::TexMapID id) noexcept;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "gx.hpp"
|
#include "gx.hpp"
|
||||||
|
|
||||||
#include "../gpu.hpp"
|
#include "../gpu.hpp"
|
||||||
|
#include "Runtime/Graphics/GX.hpp"
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
|
||||||
#include <absl/container/flat_hash_map.h>
|
#include <absl/container/flat_hash_map.h>
|
||||||
@ -187,6 +188,28 @@ void GXSetFog(GX::FogType type, float startZ, float endZ, float nearZ, float far
|
|||||||
g_gxState.fog = {type, startZ, endZ, nearZ, farZ, color};
|
g_gxState.fog = {type, startZ, endZ, nearZ, farZ, color};
|
||||||
}
|
}
|
||||||
void GXSetFogColor(const GXColor& color) noexcept { g_gxState.fog.color = color; }
|
void GXSetFogColor(const GXColor& color) noexcept { g_gxState.fog.color = color; }
|
||||||
|
void GXSetVtxDesc(GX::Attr attr, GX::AttrType type) noexcept { g_gxState.vtxDesc[attr] = type; }
|
||||||
|
void GXSetVtxDescv(GX::VtxDescList* list) noexcept {
|
||||||
|
g_gxState.vtxDesc.fill({});
|
||||||
|
while (*list) {
|
||||||
|
g_gxState.vtxDesc[list->attr] = list->type;
|
||||||
|
++list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void GXClearVtxDesc() noexcept { g_gxState.vtxDesc.fill({}); }
|
||||||
|
void GXSetTevSwapModeTable(GX::TevSwapSel id, GX::TevColorChan red, GX::TevColorChan green, GX::TevColorChan blue,
|
||||||
|
GX::TevColorChan alpha) noexcept {
|
||||||
|
if (id < GX::TEV_SWAP0 || id >= GX::MAX_TEVSWAP) {
|
||||||
|
Log.report(logvisor::Fatal, FMT_STRING("invalid tev swap sel {}"), id);
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
g_gxState.tevSwapTable[id] = {red, green, blue, alpha};
|
||||||
|
}
|
||||||
|
void GXSetTevSwapMode(GX::TevStageID stageId, GX::TevSwapSel rasSel, GX::TevSwapSel texSel) noexcept {
|
||||||
|
auto& stage = g_gxState.tevStages[stageId];
|
||||||
|
stage.tevSwapRas = rasSel;
|
||||||
|
stage.tevSwapTex = texSel;
|
||||||
|
}
|
||||||
|
|
||||||
namespace aurora::gfx {
|
namespace aurora::gfx {
|
||||||
static logvisor::Module Log("aurora::gfx::gx");
|
static logvisor::Module Log("aurora::gfx::gx");
|
||||||
@ -387,6 +410,9 @@ wgpu::RenderPipeline build_pipeline(const PipelineConfig& config, const ShaderIn
|
|||||||
|
|
||||||
ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive,
|
ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive,
|
||||||
const BindGroupRanges& ranges) noexcept {
|
const BindGroupRanges& ranges) noexcept {
|
||||||
|
config.shaderConfig.fogType = g_gxState.fog.type;
|
||||||
|
config.shaderConfig.vtxAttrs = g_gxState.vtxDesc;
|
||||||
|
config.shaderConfig.tevSwapTable = g_gxState.tevSwapTable;
|
||||||
for (u8 i = 0; i < g_gxState.numTevStages; ++i) {
|
for (u8 i = 0; i < g_gxState.numTevStages; ++i) {
|
||||||
config.shaderConfig.tevStages[i] = g_gxState.tevStages[i];
|
config.shaderConfig.tevStages[i] = g_gxState.tevStages[i];
|
||||||
}
|
}
|
||||||
@ -397,7 +423,10 @@ ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primit
|
|||||||
config.shaderConfig.tcgs[i] = g_gxState.tcgs[i];
|
config.shaderConfig.tcgs[i] = g_gxState.tcgs[i];
|
||||||
}
|
}
|
||||||
config.shaderConfig.alphaDiscard = g_gxState.alphaDiscard;
|
config.shaderConfig.alphaDiscard = g_gxState.alphaDiscard;
|
||||||
config.shaderConfig.fogType = g_gxState.fog.type;
|
if (std::any_of(config.shaderConfig.vtxAttrs.begin(), config.shaderConfig.vtxAttrs.end(),
|
||||||
|
[](const auto type) { return type == GX::INDEX8 || type == GX::INDEX16; })) {
|
||||||
|
config.shaderConfig.hasIndexedAttributes = true;
|
||||||
|
}
|
||||||
config = {
|
config = {
|
||||||
.shaderConfig = config.shaderConfig,
|
.shaderConfig = config.shaderConfig,
|
||||||
.primitive = primitive,
|
.primitive = primitive,
|
||||||
@ -601,7 +630,7 @@ GXBindGroups build_bind_groups(const ShaderInfo& info, const ShaderConfig& confi
|
|||||||
.uniformBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{
|
.uniformBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{
|
||||||
.label = "GX Uniform Bind Group",
|
.label = "GX Uniform Bind Group",
|
||||||
.layout = layouts.uniformLayout,
|
.layout = layouts.uniformLayout,
|
||||||
.entryCount = static_cast<uint32_t>(config.denormalizedVertexAttributes ? 1 : uniformEntries.size()),
|
.entryCount = static_cast<uint32_t>(config.hasIndexedAttributes ? uniformEntries.size() : 1),
|
||||||
.entries = uniformEntries.data(),
|
.entries = uniformEntries.data(),
|
||||||
}),
|
}),
|
||||||
.samplerBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{
|
.samplerBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{
|
||||||
@ -621,7 +650,7 @@ GXBindGroups build_bind_groups(const ShaderInfo& info, const ShaderConfig& confi
|
|||||||
|
|
||||||
GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info, const ShaderConfig& config) noexcept {
|
GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info, const ShaderConfig& config) noexcept {
|
||||||
GXBindGroupLayouts out;
|
GXBindGroupLayouts out;
|
||||||
u32 uniformSizeKey = info.uniformSize + (config.denormalizedVertexAttributes ? 0 : 1);
|
u32 uniformSizeKey = info.uniformSize + (config.hasIndexedAttributes ? 1 : 0);
|
||||||
const auto uniformIt = sUniformBindGroupLayouts.find(uniformSizeKey);
|
const auto uniformIt = sUniformBindGroupLayouts.find(uniformSizeKey);
|
||||||
if (uniformIt != sUniformBindGroupLayouts.end()) {
|
if (uniformIt != sUniformBindGroupLayouts.end()) {
|
||||||
out.uniformLayout = uniformIt->second;
|
out.uniformLayout = uniformIt->second;
|
||||||
@ -676,7 +705,7 @@ GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info, const Shader
|
|||||||
};
|
};
|
||||||
const auto uniformLayoutDescriptor = wgpu::BindGroupLayoutDescriptor{
|
const auto uniformLayoutDescriptor = wgpu::BindGroupLayoutDescriptor{
|
||||||
.label = "GX Uniform Bind Group Layout",
|
.label = "GX Uniform Bind Group Layout",
|
||||||
.entryCount = static_cast<uint32_t>(config.denormalizedVertexAttributes ? 1 : uniformLayoutEntries.size()),
|
.entryCount = static_cast<uint32_t>(config.hasIndexedAttributes ? uniformLayoutEntries.size() : 1),
|
||||||
.entries = uniformLayoutEntries.data(),
|
.entries = uniformLayoutEntries.data(),
|
||||||
};
|
};
|
||||||
out.uniformLayout = g_device.CreateBindGroupLayout(&uniformLayoutDescriptor);
|
out.uniformLayout = g_device.CreateBindGroupLayout(&uniformLayoutDescriptor);
|
||||||
|
@ -13,6 +13,8 @@ constexpr u32 MaxKColors = GX::MAX_KCOLOR;
|
|||||||
constexpr u32 MaxTexMtx = 10;
|
constexpr u32 MaxTexMtx = 10;
|
||||||
constexpr u32 MaxPTTexMtx = 20;
|
constexpr u32 MaxPTTexMtx = 20;
|
||||||
constexpr u32 MaxTexCoord = GX::MAX_TEXCOORD;
|
constexpr u32 MaxTexCoord = GX::MAX_TEXCOORD;
|
||||||
|
constexpr u32 MaxVtxAttr = GX::VA_MAX_ATTR;
|
||||||
|
constexpr u32 MaxTevSwap = GX::MAX_TEVSWAP;
|
||||||
|
|
||||||
template <typename Arg, Arg Default>
|
template <typename Arg, Arg Default>
|
||||||
struct TevPass {
|
struct TevPass {
|
||||||
@ -40,6 +42,8 @@ struct TevStage {
|
|||||||
GX::TexCoordID texCoordId = GX::TEXCOORD_NULL;
|
GX::TexCoordID texCoordId = GX::TEXCOORD_NULL;
|
||||||
GX::TexMapID texMapId = GX::TEXMAP_NULL;
|
GX::TexMapID texMapId = GX::TEXMAP_NULL;
|
||||||
GX::ChannelID channelId = GX::COLOR_NULL;
|
GX::ChannelID channelId = GX::COLOR_NULL;
|
||||||
|
GX::TevSwapSel tevSwapRas = GX::TEV_SWAP0;
|
||||||
|
GX::TevSwapSel tevSwapTex = GX::TEV_SWAP0;
|
||||||
bool operator==(const TevStage&) const = default;
|
bool operator==(const TevStage&) const = default;
|
||||||
};
|
};
|
||||||
struct TextureBind {
|
struct TextureBind {
|
||||||
@ -86,6 +90,14 @@ struct FogState {
|
|||||||
float farZ = 0.f;
|
float farZ = 0.f;
|
||||||
zeus::CColor color;
|
zeus::CColor color;
|
||||||
};
|
};
|
||||||
|
struct TevSwap {
|
||||||
|
GX::TevColorChan red = GX::CH_RED;
|
||||||
|
GX::TevColorChan green = GX::CH_GREEN;
|
||||||
|
GX::TevColorChan blue = GX::CH_BLUE;
|
||||||
|
GX::TevColorChan alpha = GX::CH_ALPHA;
|
||||||
|
bool operator==(const TevSwap&) const = default;
|
||||||
|
operator bool() const { return *this != TevSwap{}; }
|
||||||
|
};
|
||||||
|
|
||||||
struct GXState {
|
struct GXState {
|
||||||
zeus::CMatrix4f mv;
|
zeus::CMatrix4f mv;
|
||||||
@ -111,6 +123,13 @@ struct GXState {
|
|||||||
std::array<TexMtxVariant, MaxTexMtx> texMtxs;
|
std::array<TexMtxVariant, MaxTexMtx> texMtxs;
|
||||||
std::array<Mat4x4<float>, MaxPTTexMtx> ptTexMtxs;
|
std::array<Mat4x4<float>, MaxPTTexMtx> ptTexMtxs;
|
||||||
std::array<TcgConfig, MaxTexCoord> tcgs;
|
std::array<TcgConfig, MaxTexCoord> tcgs;
|
||||||
|
std::array<GX::AttrType, MaxVtxAttr> vtxDesc;
|
||||||
|
std::array<TevSwap, MaxTevSwap> tevSwapTable{
|
||||||
|
TevSwap{},
|
||||||
|
TevSwap{GX::CH_RED, GX::CH_RED, GX::CH_RED, GX::CH_ALPHA},
|
||||||
|
TevSwap{GX::CH_GREEN, GX::CH_GREEN, GX::CH_GREEN, GX::CH_ALPHA},
|
||||||
|
TevSwap{GX::CH_BLUE, GX::CH_BLUE, GX::CH_BLUE, GX::CH_ALPHA},
|
||||||
|
};
|
||||||
bool depthCompare = true;
|
bool depthCompare = true;
|
||||||
bool depthUpdate = true;
|
bool depthUpdate = true;
|
||||||
bool alphaUpdate = true;
|
bool alphaUpdate = true;
|
||||||
@ -128,12 +147,13 @@ const TextureBind& get_texture(GX::TexMapID id) noexcept;
|
|||||||
|
|
||||||
struct ShaderConfig {
|
struct ShaderConfig {
|
||||||
GX::FogType fogType;
|
GX::FogType fogType;
|
||||||
|
std::array<GX::AttrType, MaxVtxAttr> vtxAttrs;
|
||||||
|
std::array<TevSwap, MaxTevSwap> tevSwapTable;
|
||||||
std::array<std::optional<TevStage>, MaxTevStages> tevStages;
|
std::array<std::optional<TevStage>, MaxTevStages> tevStages;
|
||||||
std::array<ColorChannelConfig, MaxColorChannels> colorChannels;
|
std::array<ColorChannelConfig, MaxColorChannels> colorChannels;
|
||||||
std::array<TcgConfig, MaxTexCoord> tcgs;
|
std::array<TcgConfig, MaxTexCoord> tcgs;
|
||||||
std::optional<float> alphaDiscard;
|
std::optional<float> alphaDiscard;
|
||||||
bool denormalizedVertexAttributes = false;
|
bool hasIndexedAttributes = false;
|
||||||
bool denormalizedHasNrm = false; // TODO this is a hack
|
|
||||||
bool operator==(const ShaderConfig&) const = default;
|
bool operator==(const ShaderConfig&) const = default;
|
||||||
};
|
};
|
||||||
struct PipelineConfig {
|
struct PipelineConfig {
|
||||||
@ -168,8 +188,6 @@ struct ShaderInfo {
|
|||||||
std::bitset<MaxPTTexMtx> usesPTTexMtx;
|
std::bitset<MaxPTTexMtx> usesPTTexMtx;
|
||||||
std::array<GX::TexGenType, MaxTexMtx> texMtxTypes;
|
std::array<GX::TexGenType, MaxTexMtx> texMtxTypes;
|
||||||
u32 uniformSize = 0;
|
u32 uniformSize = 0;
|
||||||
bool usesVtxColor : 1 = false;
|
|
||||||
bool usesNormal : 1 = false;
|
|
||||||
bool usesFog : 1 = false;
|
bool usesFog : 1 = false;
|
||||||
};
|
};
|
||||||
struct BindGroupRanges {
|
struct BindGroupRanges {
|
||||||
@ -248,6 +266,9 @@ inline void xxh3_update(XXH3_state_t& state, const gfx::gx::TcgConfig& input) {
|
|||||||
}
|
}
|
||||||
template <>
|
template <>
|
||||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input) {
|
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input) {
|
||||||
|
XXH3_64bits_update(&state, &input.fogType, sizeof(gfx::gx::ShaderConfig::fogType));
|
||||||
|
XXH3_64bits_update(&state, &input.vtxAttrs, sizeof(gfx::gx::ShaderConfig::vtxAttrs));
|
||||||
|
XXH3_64bits_update(&state, &input.tevSwapTable, sizeof(gfx::gx::ShaderConfig::tevSwapTable));
|
||||||
for (const auto& item : input.tevStages) {
|
for (const auto& item : input.tevStages) {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
break;
|
break;
|
||||||
@ -263,9 +284,6 @@ inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input)
|
|||||||
if (input.alphaDiscard) {
|
if (input.alphaDiscard) {
|
||||||
XXH3_64bits_update(&state, &*input.alphaDiscard, sizeof(float));
|
XXH3_64bits_update(&state, &*input.alphaDiscard, sizeof(float));
|
||||||
}
|
}
|
||||||
XXH3_64bits_update(&state, &input.denormalizedVertexAttributes,
|
XXH3_64bits_update(&state, &input.hasIndexedAttributes, sizeof(gfx::gx::ShaderConfig::hasIndexedAttributes));
|
||||||
sizeof(gfx::gx::ShaderConfig::denormalizedVertexAttributes));
|
|
||||||
XXH3_64bits_update(&state, &input.denormalizedHasNrm, sizeof(gfx::gx::ShaderConfig::denormalizedHasNrm));
|
|
||||||
XXH3_64bits_update(&state, &input.fogType, sizeof(gfx::gx::ShaderConfig::fogType));
|
|
||||||
}
|
}
|
||||||
} // namespace aurora
|
} // namespace aurora
|
||||||
|
@ -15,7 +15,21 @@ absl::flat_hash_map<ShaderRef, std::pair<wgpu::ShaderModule, gx::ShaderInfo>> g_
|
|||||||
static absl::flat_hash_map<ShaderRef, gx::ShaderConfig> g_gxCachedShaderConfigs;
|
static absl::flat_hash_map<ShaderRef, gx::ShaderConfig> g_gxCachedShaderConfigs;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const TevStage& stage, ShaderInfo& info) {
|
static inline std::string_view chan_comp(GX::TevColorChan chan) noexcept {
|
||||||
|
switch (chan) {
|
||||||
|
case GX::CH_RED:
|
||||||
|
return "r";
|
||||||
|
case GX::CH_GREEN:
|
||||||
|
return "g";
|
||||||
|
case GX::CH_BLUE:
|
||||||
|
return "b";
|
||||||
|
case GX::CH_ALPHA:
|
||||||
|
return "a";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const ShaderConfig& config,
|
||||||
|
const TevStage& stage, ShaderInfo& info) {
|
||||||
switch (arg) {
|
switch (arg) {
|
||||||
case GX::CC_CPREV:
|
case GX::CC_CPREV:
|
||||||
return "prev.rgb";
|
return "prev.rgb";
|
||||||
@ -48,7 +62,9 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const Tev
|
|||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
info.sampledTextures.set(stage.texMapId);
|
info.sampledTextures.set(stage.texMapId);
|
||||||
return fmt::format(FMT_STRING("sampled{}.rgb"), stage.texMapId);
|
const auto swap = config.tevSwapTable[stage.tevSwapTex];
|
||||||
|
return fmt::format(FMT_STRING("sampled{}.{}{}{}"), stage.texMapId, chan_comp(swap.red), chan_comp(swap.green),
|
||||||
|
chan_comp(swap.blue));
|
||||||
}
|
}
|
||||||
case GX::CC_TEXA: {
|
case GX::CC_TEXA: {
|
||||||
if (stage.texMapId == GX::TEXMAP_NULL) {
|
if (stage.texMapId == GX::TEXMAP_NULL) {
|
||||||
@ -59,7 +75,8 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const Tev
|
|||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
info.sampledTextures.set(stage.texMapId);
|
info.sampledTextures.set(stage.texMapId);
|
||||||
return fmt::format(FMT_STRING("sampled{}.a"), stage.texMapId);
|
const auto swap = config.tevSwapTable[stage.tevSwapTex];
|
||||||
|
return fmt::format(FMT_STRING("sampled{}.{}"), stage.texMapId, chan_comp(swap.alpha));
|
||||||
}
|
}
|
||||||
case GX::CC_RASC: {
|
case GX::CC_RASC: {
|
||||||
if (stage.channelId == GX::COLOR_NULL) {
|
if (stage.channelId == GX::COLOR_NULL) {
|
||||||
@ -71,7 +88,9 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const Tev
|
|||||||
}
|
}
|
||||||
u32 idx = stage.channelId - GX::COLOR0A0;
|
u32 idx = stage.channelId - GX::COLOR0A0;
|
||||||
info.sampledColorChannels.set(idx);
|
info.sampledColorChannels.set(idx);
|
||||||
return fmt::format(FMT_STRING("rast{}.rgb"), idx);
|
const auto swap = config.tevSwapTable[stage.tevSwapRas];
|
||||||
|
return fmt::format(FMT_STRING("rast{}.{}{}{}"), idx, chan_comp(swap.red), chan_comp(swap.green),
|
||||||
|
chan_comp(swap.blue));
|
||||||
}
|
}
|
||||||
case GX::CC_RASA: {
|
case GX::CC_RASA: {
|
||||||
if (stage.channelId == GX::COLOR_NULL) {
|
if (stage.channelId == GX::COLOR_NULL) {
|
||||||
@ -83,7 +102,8 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const Tev
|
|||||||
}
|
}
|
||||||
u32 idx = stage.channelId - GX::COLOR0A0;
|
u32 idx = stage.channelId - GX::COLOR0A0;
|
||||||
info.sampledColorChannels.set(idx);
|
info.sampledColorChannels.set(idx);
|
||||||
return fmt::format(FMT_STRING("rast{}.a"), idx);
|
const auto swap = config.tevSwapTable[stage.tevSwapRas];
|
||||||
|
return fmt::format(FMT_STRING("rast{}.{}"), idx, chan_comp(swap.alpha));
|
||||||
}
|
}
|
||||||
case GX::CC_ONE:
|
case GX::CC_ONE:
|
||||||
return "1.0";
|
return "1.0";
|
||||||
@ -180,7 +200,8 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const Tev
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const TevStage& stage, ShaderInfo& info) {
|
static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const ShaderConfig& config,
|
||||||
|
const TevStage& stage, ShaderInfo& info) {
|
||||||
switch (arg) {
|
switch (arg) {
|
||||||
case GX::CA_APREV:
|
case GX::CA_APREV:
|
||||||
return "prev.a";
|
return "prev.a";
|
||||||
@ -202,7 +223,8 @@ static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const Tev
|
|||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
info.sampledTextures.set(stage.texMapId);
|
info.sampledTextures.set(stage.texMapId);
|
||||||
return fmt::format(FMT_STRING("sampled{}.a"), stage.texMapId);
|
const auto swap = config.tevSwapTable[stage.tevSwapTex];
|
||||||
|
return fmt::format(FMT_STRING("sampled{}.{}"), stage.texMapId, chan_comp(swap.alpha));
|
||||||
}
|
}
|
||||||
case GX::CA_RASA: {
|
case GX::CA_RASA: {
|
||||||
if (stage.channelId == GX::COLOR_NULL) {
|
if (stage.channelId == GX::COLOR_NULL) {
|
||||||
@ -214,7 +236,8 @@ static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const Tev
|
|||||||
}
|
}
|
||||||
u32 idx = stage.channelId - GX::COLOR0A0;
|
u32 idx = stage.channelId - GX::COLOR0A0;
|
||||||
info.sampledColorChannels.set(idx);
|
info.sampledColorChannels.set(idx);
|
||||||
return fmt::format(FMT_STRING("rast{}.a"), idx);
|
const auto swap = config.tevSwapTable[stage.tevSwapRas];
|
||||||
|
return fmt::format(FMT_STRING("rast{}.{}"), idx, chan_comp(swap.alpha));
|
||||||
}
|
}
|
||||||
case GX::CA_KONST: {
|
case GX::CA_KONST: {
|
||||||
switch (stage.kaSel) {
|
switch (stage.kaSel) {
|
||||||
@ -337,7 +360,41 @@ static std::string_view tev_scale(GX::TevScale scale) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string in_uv(u32 idx) {
|
static inline std::string vtx_attr(const ShaderConfig& config, GX::Attr attr) {
|
||||||
|
const auto type = config.vtxAttrs[attr];
|
||||||
|
if (type == GX::NONE) {
|
||||||
|
if (attr == GX::VA_NRM) {
|
||||||
|
// Default normal
|
||||||
|
return "vec3<f32>(1.0, 0.0, 0.0)";
|
||||||
|
}
|
||||||
|
Log.report(logvisor::Fatal, FMT_STRING("unmapped attr {}"), attr);
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
if (attr == GX::VA_POS) {
|
||||||
|
if (type == GX::DIRECT) {
|
||||||
|
return "in_pos";
|
||||||
|
}
|
||||||
|
return "v_verts.data[in_pos_nrm_idx[0]].xyz";
|
||||||
|
}
|
||||||
|
if (attr == GX::VA_NRM) {
|
||||||
|
if (type == GX::DIRECT) {
|
||||||
|
return "in_nrm";
|
||||||
|
}
|
||||||
|
return "v_norms.data[in_pos_nrm_idx[1]].xyz";
|
||||||
|
}
|
||||||
|
if (attr == GX::VA_CLR0 || attr == GX::VA_CLR1) {
|
||||||
|
const auto idx = attr - GX::VA_CLR0;
|
||||||
|
if (type == GX::DIRECT) {
|
||||||
|
return fmt::format(FMT_STRING("in_clr{}"), idx);
|
||||||
|
}
|
||||||
|
Log.report(logvisor::Fatal, FMT_STRING("indexed color unsupported"));
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
if (attr >= GX::VA_TEX0 && attr <= GX::VA_TEX7) {
|
||||||
|
const auto idx = attr - GX::VA_TEX0;
|
||||||
|
if (type == GX::DIRECT) {
|
||||||
|
return fmt::format(FMT_STRING("in_tex{}_uv"), idx);
|
||||||
|
}
|
||||||
if (idx == 0) {
|
if (idx == 0) {
|
||||||
return "v_packed_uvs.data[in_uv_0_4_idx[0]]";
|
return "v_packed_uvs.data[in_uv_0_4_idx[0]]";
|
||||||
}
|
}
|
||||||
@ -345,6 +402,9 @@ static std::string in_uv(u32 idx) {
|
|||||||
return fmt::format(FMT_STRING("v_uvs.data[in_uv_0_4_idx[{}]]"), idx);
|
return fmt::format(FMT_STRING("v_uvs.data[in_uv_0_4_idx[{}]]"), idx);
|
||||||
}
|
}
|
||||||
return fmt::format(FMT_STRING("v_uvs.data[in_uv_5_7_idx[{}]]"), idx - 4);
|
return fmt::format(FMT_STRING("v_uvs.data[in_uv_5_7_idx[{}]]"), idx - 4);
|
||||||
|
}
|
||||||
|
Log.report(logvisor::Fatal, FMT_STRING("unhandled attr {}"), attr);
|
||||||
|
unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& config) noexcept {
|
std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& config) noexcept {
|
||||||
@ -409,7 +469,7 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.report(logvisor::Info, FMT_STRING(" alphaDiscard: {}"), config.alphaDiscard.value_or(0.f));
|
Log.report(logvisor::Info, FMT_STRING(" alphaDiscard: {}"), config.alphaDiscard.value_or(0.f));
|
||||||
Log.report(logvisor::Info, FMT_STRING(" denormalizedVertexAttributes: {}"), config.denormalizedVertexAttributes);
|
Log.report(logvisor::Info, FMT_STRING(" hasIndexedAttributes: {}"), config.hasIndexedAttributes);
|
||||||
Log.report(logvisor::Info, FMT_STRING(" fogType: {}"), config.fogType);
|
Log.report(logvisor::Info, FMT_STRING(" fogType: {}"), config.fogType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,23 +483,14 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
|
|||||||
std::string vtxXfrAttrsPre;
|
std::string vtxXfrAttrsPre;
|
||||||
std::string vtxXfrAttrs;
|
std::string vtxXfrAttrs;
|
||||||
size_t locIdx = 0;
|
size_t locIdx = 0;
|
||||||
if (config.denormalizedVertexAttributes) {
|
size_t vtxOutIdx = 0;
|
||||||
vtxInAttrs += "\n @location(0) in_pos: vec3<f32>";
|
if (config.hasIndexedAttributes) {
|
||||||
vtxOutAttrs += "\n @builtin(position) pos: vec4<f32>;";
|
// Display list attributes
|
||||||
vtxXfrAttrsPre +=
|
vtxInAttrs +=
|
||||||
"\n var obj_pos = vec4<f32>(in_pos, 1.0);"
|
"\n @location(0) in_pos_nrm_idx: vec2<i32>"
|
||||||
"\n var mv_pos = ubuf.mv * obj_pos;"
|
"\n , @location(1) in_uv_0_4_idx: vec4<i32>"
|
||||||
"\n out.pos = ubuf.proj * mv_pos;";
|
"\n , @location(2) in_uv_5_7_idx: vec4<i32>";
|
||||||
if (config.denormalizedHasNrm) {
|
locIdx += 3;
|
||||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) nrm: vec3<f32>;"), locIdx);
|
|
||||||
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_nrm: vec3<f32>"), ++locIdx);
|
|
||||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.nrm = in_nrm;"));
|
|
||||||
vtxXfrAttrsPre +=
|
|
||||||
"\n var obj_norm = vec4<f32>(in_nrm, 0.0);"
|
|
||||||
"\n var mv_norm = ubuf.mv_inv * obj_norm;";
|
|
||||||
info.usesNormal = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
uniformBindings += R"""(
|
uniformBindings += R"""(
|
||||||
struct Vec3Block {
|
struct Vec3Block {
|
||||||
data: array<vec4<f32>>;
|
data: array<vec4<f32>>;
|
||||||
@ -456,18 +507,33 @@ var<storage, read> v_uvs: Vec2Block;
|
|||||||
@group(0) @binding(4)
|
@group(0) @binding(4)
|
||||||
var<storage, read> v_packed_uvs: Vec2Block;
|
var<storage, read> v_packed_uvs: Vec2Block;
|
||||||
)""";
|
)""";
|
||||||
vtxInAttrs +=
|
}
|
||||||
"\n @location(0) in_pos_nrm_idx: vec2<i32>"
|
for (GX::Attr attr{}; attr < MaxVtxAttr; attr = GX::Attr(attr + 1)) {
|
||||||
"\n , @location(1) in_uv_0_4_idx: vec4<i32>"
|
// Direct attributes
|
||||||
"\n , @location(2) in_uv_5_7_idx: vec4<i32>";
|
if (config.vtxAttrs[attr] != GX::DIRECT) {
|
||||||
vtxOutAttrs += "\n @builtin(position) pos: vec4<f32>;";
|
continue;
|
||||||
vtxXfrAttrsPre +=
|
}
|
||||||
"\n var obj_pos = vec4<f32>(v_verts.data[in_pos_nrm_idx[0]].xyz, 1.0);"
|
if (locIdx > 0) {
|
||||||
"\n var obj_norm = vec4<f32>(v_norms.data[in_pos_nrm_idx[1]].xyz, 0.0);"
|
vtxInAttrs += "\n , ";
|
||||||
|
} else {
|
||||||
|
vtxInAttrs += "\n ";
|
||||||
|
}
|
||||||
|
if (attr == GX::VA_POS) {
|
||||||
|
vtxInAttrs += fmt::format(FMT_STRING("@location({}) in_pos: vec3<f32>"), locIdx++);
|
||||||
|
} else if (attr == GX::VA_NRM) {
|
||||||
|
vtxInAttrs += fmt::format(FMT_STRING("@location({}) in_nrm: vec3<f32>"), locIdx++);
|
||||||
|
} else if (attr == GX::VA_CLR0 || attr == GX::VA_CLR1) {
|
||||||
|
vtxInAttrs += fmt::format(FMT_STRING("@location({}) in_clr{}: vec4<f32>"), locIdx++, attr - GX::VA_CLR0);
|
||||||
|
} else if (attr >= GX::VA_TEX0 && attr <= GX::VA_TEX7) {
|
||||||
|
vtxInAttrs += fmt::format(FMT_STRING("@location({}) in_tex{}_uv: vec2<f32>"), locIdx++, attr - GX::VA_TEX0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vtxXfrAttrsPre += fmt::format(FMT_STRING("\n var obj_pos = vec4<f32>({}, 1.0);"
|
||||||
|
"\n var obj_norm = vec4<f32>({}, 0.0);"
|
||||||
"\n var mv_pos = ubuf.mv * obj_pos;"
|
"\n var mv_pos = ubuf.mv * obj_pos;"
|
||||||
"\n var mv_norm = ubuf.mv_inv * obj_norm;"
|
"\n var mv_norm = ubuf.mv_inv * obj_norm;"
|
||||||
"\n out.pos = ubuf.proj * mv_pos;";
|
"\n out.pos = ubuf.proj * mv_pos;"),
|
||||||
}
|
vtx_attr(config, GX::VA_POS), vtx_attr(config, GX::VA_NRM));
|
||||||
|
|
||||||
std::string fragmentFnPre;
|
std::string fragmentFnPre;
|
||||||
std::string fragmentFn;
|
std::string fragmentFn;
|
||||||
@ -478,7 +544,7 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||||||
{
|
{
|
||||||
std::string outReg;
|
std::string outReg;
|
||||||
switch (stage->colorOp.outReg) {
|
switch (stage->colorOp.outReg) {
|
||||||
case GX::TevRegID::TEVPREV:
|
case GX::TEVPREV:
|
||||||
outReg = "prev";
|
outReg = "prev";
|
||||||
break;
|
break;
|
||||||
case GX::TEVREG0:
|
case GX::TEVREG0:
|
||||||
@ -496,11 +562,13 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||||||
default:
|
default:
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("invalid colorOp outReg {}"), stage->colorOp.outReg);
|
Log.report(logvisor::Fatal, FMT_STRING("invalid colorOp outReg {}"), stage->colorOp.outReg);
|
||||||
}
|
}
|
||||||
std::string op = fmt::format(
|
std::string op =
|
||||||
FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
fmt::format(FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
||||||
color_arg_reg(stage->colorPass.a, idx, *stage, info), color_arg_reg(stage->colorPass.b, idx, *stage, info),
|
color_arg_reg(stage->colorPass.a, idx, config, *stage, info),
|
||||||
color_arg_reg(stage->colorPass.c, idx, *stage, info), color_arg_reg(stage->colorPass.d, idx, *stage, info),
|
color_arg_reg(stage->colorPass.b, idx, config, *stage, info),
|
||||||
tev_op(stage->colorOp.op), tev_bias(stage->colorOp.bias), tev_scale(stage->colorOp.scale));
|
color_arg_reg(stage->colorPass.c, idx, config, *stage, info),
|
||||||
|
color_arg_reg(stage->colorPass.d, idx, config, *stage, info), tev_op(stage->colorOp.op),
|
||||||
|
tev_bias(stage->colorOp.bias), tev_scale(stage->colorOp.scale));
|
||||||
if (stage->colorOp.clamp) {
|
if (stage->colorOp.clamp) {
|
||||||
op = fmt::format(FMT_STRING("clamp(vec3<f32>({}), vec3<f32>(0.0), vec3<f32>(1.0))"), op);
|
op = fmt::format(FMT_STRING("clamp(vec3<f32>({}), vec3<f32>(0.0), vec3<f32>(1.0))"), op);
|
||||||
}
|
}
|
||||||
@ -509,7 +577,7 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||||||
{
|
{
|
||||||
std::string outReg;
|
std::string outReg;
|
||||||
switch (stage->alphaOp.outReg) {
|
switch (stage->alphaOp.outReg) {
|
||||||
case GX::TevRegID::TEVPREV:
|
case GX::TEVPREV:
|
||||||
outReg = "prev.a";
|
outReg = "prev.a";
|
||||||
break;
|
break;
|
||||||
case GX::TEVREG0:
|
case GX::TEVREG0:
|
||||||
@ -527,11 +595,13 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||||||
default:
|
default:
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("invalid alphaOp outReg {}"), stage->alphaOp.outReg);
|
Log.report(logvisor::Fatal, FMT_STRING("invalid alphaOp outReg {}"), stage->alphaOp.outReg);
|
||||||
}
|
}
|
||||||
std::string op = fmt::format(
|
std::string op =
|
||||||
FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
fmt::format(FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
||||||
alpha_arg_reg(stage->alphaPass.a, idx, *stage, info), alpha_arg_reg(stage->alphaPass.b, idx, *stage, info),
|
alpha_arg_reg(stage->alphaPass.a, idx, config, *stage, info),
|
||||||
alpha_arg_reg(stage->alphaPass.c, idx, *stage, info), alpha_arg_reg(stage->alphaPass.d, idx, *stage, info),
|
alpha_arg_reg(stage->alphaPass.b, idx, config, *stage, info),
|
||||||
tev_op(stage->alphaOp.op), tev_bias(stage->alphaOp.bias), tev_scale(stage->alphaOp.scale));
|
alpha_arg_reg(stage->alphaPass.c, idx, config, *stage, info),
|
||||||
|
alpha_arg_reg(stage->alphaPass.d, idx, config, *stage, info), tev_op(stage->alphaOp.op),
|
||||||
|
tev_bias(stage->alphaOp.bias), tev_scale(stage->alphaOp.scale));
|
||||||
if (stage->alphaOp.clamp) {
|
if (stage->alphaOp.clamp) {
|
||||||
op = fmt::format(FMT_STRING("clamp({}, 0.0, 1.0)"), op);
|
op = fmt::format(FMT_STRING("clamp({}, 0.0, 1.0)"), op);
|
||||||
}
|
}
|
||||||
@ -557,11 +627,6 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||||||
uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_mat: vec4<f32>;"), i);
|
uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_mat: vec4<f32>;"), i);
|
||||||
info.uniformSize += 32;
|
info.uniformSize += 32;
|
||||||
|
|
||||||
if (config.denormalizedVertexAttributes && !info.usesVtxColor) {
|
|
||||||
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_clr: vec4<f32>"), ++locIdx);
|
|
||||||
info.usesVtxColor = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.colorChannels[i].lightingEnabled) {
|
if (config.colorChannels[i].lightingEnabled) {
|
||||||
if (!addedLightStruct) {
|
if (!addedLightStruct) {
|
||||||
uniformPre +=
|
uniformPre +=
|
||||||
@ -580,7 +645,7 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||||||
uniBufAttrs += fmt::format(FMT_STRING("\n lighting_ambient{}: vec4<f32>;"), i);
|
uniBufAttrs += fmt::format(FMT_STRING("\n lighting_ambient{}: vec4<f32>;"), i);
|
||||||
info.uniformSize += (80 * GX::MaxLights) + 16;
|
info.uniformSize += (80 * GX::MaxLights) + 16;
|
||||||
|
|
||||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), locIdx++, i);
|
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), vtxOutIdx++, i);
|
||||||
vtxXfrAttrs += fmt::format(FMT_STRING(R"""(
|
vtxXfrAttrs += fmt::format(FMT_STRING(R"""(
|
||||||
{{
|
{{
|
||||||
var lighting = ubuf.lighting_ambient{0} + ubuf.cc{0}_amb;
|
var lighting = ubuf.lighting_ambient{0} + ubuf.cc{0}_amb;
|
||||||
@ -604,13 +669,9 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||||||
i, GX::MaxLights);
|
i, GX::MaxLights);
|
||||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
||||||
} else if (config.colorChannels[i].matSrc == GX::SRC_VTX) {
|
} else if (config.colorChannels[i].matSrc == GX::SRC_VTX) {
|
||||||
if (config.denormalizedVertexAttributes) {
|
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), vtxOutIdx++, i);
|
||||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), locIdx - 1, i);
|
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.cc{} = {};"), i, vtx_attr(config, GX::Attr(GX::VA_CLR0 + i)));
|
||||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.cc{} = in_clr;"), i);
|
|
||||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
||||||
} else {
|
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("SRC_VTX unsupported with normalized vertex attributes"));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = ubuf.cc{0}_mat;"), i);
|
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = ubuf.cc{0}_mat;"), i);
|
||||||
}
|
}
|
||||||
@ -628,15 +689,10 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto& tcg = config.tcgs[i];
|
const auto& tcg = config.tcgs[i];
|
||||||
if (config.denormalizedVertexAttributes) {
|
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2<f32>;"), vtxOutIdx++, i);
|
||||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2<f32>;"), locIdx, i);
|
|
||||||
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_tex{}_uv: vec2<f32>"), locIdx + 1, i);
|
|
||||||
// TODO check tcg src for denorm?
|
|
||||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0} = vec4<f32>(in_tex{0}_uv, 0.0, 1.0);"), i);
|
|
||||||
} else {
|
|
||||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2<f32>;"), locIdx, i);
|
|
||||||
if (tcg.src >= GX::TG_TEX0 && tcg.src <= GX::TG_TEX7) {
|
if (tcg.src >= GX::TG_TEX0 && tcg.src <= GX::TG_TEX7) {
|
||||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4<f32>({}, 0.0, 1.0);"), i, in_uv(tcg.src - GX::TG_TEX0));
|
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4<f32>({}, 0.0, 1.0);"), i,
|
||||||
|
vtx_attr(config, GX::Attr(GX::VA_TEX0 + (tcg.src - GX::TG_TEX0))));
|
||||||
} else if (tcg.src == GX::TG_POS) {
|
} else if (tcg.src == GX::TG_POS) {
|
||||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4<f32>(obj_pos.xyz, 1.0);"), i);
|
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4<f32>(obj_pos.xyz, 1.0);"), i);
|
||||||
} else if (tcg.src == GX::TG_NRM) {
|
} else if (tcg.src == GX::TG_NRM) {
|
||||||
@ -645,7 +701,6 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled tcg src {}"), tcg.src);
|
Log.report(logvisor::Fatal, FMT_STRING("unhandled tcg src {}"), tcg.src);
|
||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// TODO this all assumes MTX3x4 currently
|
// TODO this all assumes MTX3x4 currently
|
||||||
if (tcg.mtx == GX::IDENTITY) {
|
if (tcg.mtx == GX::IDENTITY) {
|
||||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_tmp = tc{0}.xyz;"), i);
|
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_tmp = tc{0}.xyz;"), i);
|
||||||
@ -663,12 +718,12 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||||||
} else {
|
} else {
|
||||||
u32 postMtxIdx = (tcg.postMtx - GX::PTTEXMTX0) / 3;
|
u32 postMtxIdx = (tcg.postMtx - GX::PTTEXMTX0) / 3;
|
||||||
info.usesPTTexMtx.set(postMtxIdx);
|
info.usesPTTexMtx.set(postMtxIdx);
|
||||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_proj = ubuf.postmtx{1} * vec4<f32>(tc{0}_tmp.xyz, 1.0);"), i, postMtxIdx);
|
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_proj = ubuf.postmtx{1} * vec4<f32>(tc{0}_tmp.xyz, 1.0);"),
|
||||||
|
i, postMtxIdx);
|
||||||
}
|
}
|
||||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{0}_uv = tc{0}_proj.xy;"), i);
|
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{0}_uv = tc{0}_proj.xy;"), i);
|
||||||
fragmentFnPre += fmt::format(
|
fragmentFnPre += fmt::format(
|
||||||
FMT_STRING("\n var sampled{0} = textureSampleBias(tex{0}, tex{0}_samp, in.tex{0}_uv, ubuf.tex{0}_lod);"), i);
|
FMT_STRING("\n var sampled{0} = textureSampleBias(tex{0}, tex{0}_samp, in.tex{0}_uv, ubuf.tex{0}_lod);"), i);
|
||||||
locIdx++;
|
|
||||||
}
|
}
|
||||||
for (int i = 0; i < info.usesTexMtx.size(); ++i) {
|
for (int i = 0; i < info.usesTexMtx.size(); ++i) {
|
||||||
if (!info.usesTexMtx.test(i)) {
|
if (!info.usesTexMtx.test(i)) {
|
||||||
@ -698,7 +753,8 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||||||
if (config.fogType != GX::FOG_NONE) {
|
if (config.fogType != GX::FOG_NONE) {
|
||||||
info.usesFog = true;
|
info.usesFog = true;
|
||||||
|
|
||||||
uniformPre += "\n"
|
uniformPre +=
|
||||||
|
"\n"
|
||||||
"struct Fog {\n"
|
"struct Fog {\n"
|
||||||
" color: vec4<f32>;\n"
|
" color: vec4<f32>;\n"
|
||||||
" a: f32;\n"
|
" a: f32;\n"
|
||||||
@ -729,7 +785,8 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||||||
break;
|
break;
|
||||||
case GX::FOG_PERSP_REVEXP2:
|
case GX::FOG_PERSP_REVEXP2:
|
||||||
case GX::FOG_ORTHO_REVEXP2:
|
case GX::FOG_ORTHO_REVEXP2:
|
||||||
fragmentFn += "\n fogF = 1.0 - fogF;"
|
fragmentFn +=
|
||||||
|
"\n fogF = 1.0 - fogF;"
|
||||||
"\n var fogZ = exp2(-8.0 * fogF * fogF);";
|
"\n var fogZ = exp2(-8.0 * fogF * fogF);";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -767,7 +824,8 @@ struct Uniform {{
|
|||||||
@group(0) @binding(0)
|
@group(0) @binding(0)
|
||||||
var<uniform> ubuf: Uniform;{uniformBindings}{sampBindings}{texBindings}
|
var<uniform> ubuf: Uniform;{uniformBindings}{sampBindings}{texBindings}
|
||||||
|
|
||||||
struct VertexOutput {{{vtxOutAttrs}
|
struct VertexOutput {{
|
||||||
|
@builtin(position) pos: vec4<f32>;{vtxOutAttrs}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@stage(vertex)
|
@stage(vertex)
|
||||||
|
@ -5,47 +5,6 @@
|
|||||||
|
|
||||||
#include <absl/container/flat_hash_map.h>
|
#include <absl/container/flat_hash_map.h>
|
||||||
#include <aurora/model.hpp>
|
#include <aurora/model.hpp>
|
||||||
#include <magic_enum.hpp>
|
|
||||||
|
|
||||||
enum class VtxDescAttr : u8 {
|
|
||||||
Position = 0,
|
|
||||||
Normal = 2,
|
|
||||||
Color0 = 4,
|
|
||||||
Color1 = 6,
|
|
||||||
Tex0 = 8,
|
|
||||||
Tex1 = 10,
|
|
||||||
Tex2 = 12,
|
|
||||||
Tex3 = 14,
|
|
||||||
Tex4 = 16,
|
|
||||||
Tex5 = 18,
|
|
||||||
Tex6 = 20,
|
|
||||||
PnMatIdx = 24,
|
|
||||||
Tex0MatIdx = 25,
|
|
||||||
Tex1MatIdx = 26,
|
|
||||||
Tex2MatIdx = 27,
|
|
||||||
Tex3MatIdx = 28,
|
|
||||||
Tex4MatIdx = 29,
|
|
||||||
Tex5MatIdx = 30,
|
|
||||||
Tex6MatIdx = 31,
|
|
||||||
};
|
|
||||||
enum class VtxDescAttrType : u8 { None = 0, Direct = 1, Index8 = 2, Index16 = 3 };
|
|
||||||
class VtxDescFlags {
|
|
||||||
u32 m_flags = 0;
|
|
||||||
|
|
||||||
public:
|
|
||||||
constexpr VtxDescFlags() noexcept = default;
|
|
||||||
constexpr VtxDescFlags(u32 flags) noexcept : m_flags(flags){};
|
|
||||||
[[nodiscard]] constexpr VtxDescAttrType GetAttributeType(VtxDescAttr attribute) const noexcept {
|
|
||||||
return VtxDescAttrType((m_flags >> u32(attribute)) & 0x3);
|
|
||||||
}
|
|
||||||
[[nodiscard]] constexpr VtxDescAttrType GetDirectAttributeType(VtxDescAttr attribute) const noexcept {
|
|
||||||
return VtxDescAttrType((m_flags >> u32(attribute)) & 0x1);
|
|
||||||
}
|
|
||||||
constexpr void SetAttributeType(VtxDescAttr attribute, VtxDescAttrType type) noexcept {
|
|
||||||
m_flags &= ~(u32(0x3) << u32(attribute));
|
|
||||||
m_flags |= u32(type) << u32(attribute);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace aurora::gfx::model {
|
namespace aurora::gfx::model {
|
||||||
static logvisor::Module Log("aurora::gfx::model");
|
static logvisor::Module Log("aurora::gfx::model");
|
||||||
@ -59,53 +18,52 @@ static std::optional<Range> staticNrmRange;
|
|||||||
static std::optional<Range> staticPackedTcRange;
|
static std::optional<Range> staticPackedTcRange;
|
||||||
static std::optional<Range> staticTcRange;
|
static std::optional<Range> staticTcRange;
|
||||||
|
|
||||||
enum class VertexFormat : u8 {
|
|
||||||
F32F32,
|
|
||||||
S16F32,
|
|
||||||
S16S16,
|
|
||||||
};
|
|
||||||
static VtxDescFlags sVtxDescFlags;
|
|
||||||
void set_vtx_desc_compressed(u32 vtxDesc) noexcept { sVtxDescFlags = vtxDesc; }
|
|
||||||
|
|
||||||
static inline std::pair<gx::DlVert, size_t> readVert(const u8* data) noexcept {
|
static inline std::pair<gx::DlVert, size_t> readVert(const u8* data) noexcept {
|
||||||
gx::DlVert out{};
|
gx::DlVert out{};
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
const auto read8 = [data, &offset](VtxDescAttrType type) -> s8 {
|
const auto vtxTypes = gx::g_gxState.vtxDesc;
|
||||||
if (type == VtxDescAttrType::Direct) {
|
const auto read8 = [/*data, &offset*/](GX::AttrType type) -> s8 {
|
||||||
s8 v = static_cast<s8>(data[offset]);
|
// if (type == GX::INDEX8) {
|
||||||
++offset;
|
// s8 v = static_cast<s8>(data[offset]);
|
||||||
return v;
|
// ++offset;
|
||||||
|
// return v;
|
||||||
|
// }
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (type != GX::NONE) {
|
||||||
|
Log.report(logvisor::Fatal, FMT_STRING("unsupported vtx attr"));
|
||||||
|
unreachable();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
const auto read16 = [data, &offset](VtxDescAttrType type) -> s16 {
|
const auto read16 = [data, &offset](GX::AttrType type) -> s16 {
|
||||||
if (type == VtxDescAttrType::Index16) {
|
if (type == GX::INDEX16) {
|
||||||
s16 v = metaforce::SBig(*reinterpret_cast<const u16*>(data + offset));
|
s16 v = metaforce::SBig(*reinterpret_cast<const u16*>(data + offset));
|
||||||
offset += 2;
|
offset += 2;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::PnMatIdx));
|
read8(vtxTypes[GX::VA_PNMTXIDX]);
|
||||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex0MatIdx));
|
read8(vtxTypes[GX::VA_TEX0MTXIDX]);
|
||||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex1MatIdx));
|
read8(vtxTypes[GX::VA_TEX1MTXIDX]);
|
||||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex2MatIdx));
|
read8(vtxTypes[GX::VA_TEX2MTXIDX]);
|
||||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex3MatIdx));
|
read8(vtxTypes[GX::VA_TEX3MTXIDX]);
|
||||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex4MatIdx));
|
read8(vtxTypes[GX::VA_TEX4MTXIDX]);
|
||||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex5MatIdx));
|
read8(vtxTypes[GX::VA_TEX5MTXIDX]);
|
||||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex6MatIdx));
|
read8(vtxTypes[GX::VA_TEX6MTXIDX]);
|
||||||
|
|
||||||
out.pos = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Position));
|
out.pos = read16(vtxTypes[GX::VA_POS]);
|
||||||
out.norm = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Normal));
|
out.norm = read16(vtxTypes[GX::VA_NRM]);
|
||||||
read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Color0));
|
read16(vtxTypes[GX::VA_CLR0]);
|
||||||
read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Color1));
|
read16(vtxTypes[GX::VA_CLR1]);
|
||||||
out.uvs[0] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex0));
|
out.uvs[0] = read16(vtxTypes[GX::VA_TEX0]);
|
||||||
out.uvs[1] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex1));
|
out.uvs[1] = read16(vtxTypes[GX::VA_TEX1]);
|
||||||
out.uvs[2] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex2));
|
out.uvs[2] = read16(vtxTypes[GX::VA_TEX2]);
|
||||||
out.uvs[3] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex3));
|
out.uvs[3] = read16(vtxTypes[GX::VA_TEX3]);
|
||||||
out.uvs[4] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex4));
|
out.uvs[4] = read16(vtxTypes[GX::VA_TEX4]);
|
||||||
out.uvs[5] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex5));
|
out.uvs[5] = read16(vtxTypes[GX::VA_TEX5]);
|
||||||
out.uvs[6] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex6));
|
out.uvs[6] = read16(vtxTypes[GX::VA_TEX6]);
|
||||||
|
|
||||||
return {out, offset};
|
return {out, offset};
|
||||||
}
|
}
|
||||||
@ -130,7 +88,6 @@ void queue_surface(const u8* dlStart, u32 dlSize) noexcept {
|
|||||||
while (offset < dlSize - 6) {
|
while (offset < dlSize - 6) {
|
||||||
const auto header = dlStart[offset];
|
const auto header = dlStart[offset];
|
||||||
const auto primitive = static_cast<GX::Primitive>(header & 0xF8);
|
const auto primitive = static_cast<GX::Primitive>(header & 0xF8);
|
||||||
const auto vtxFmt = static_cast<VertexFormat>(header & 0x3);
|
|
||||||
const auto vtxCount = metaforce::SBig(*reinterpret_cast<const u16*>(dlStart + offset + 1));
|
const auto vtxCount = metaforce::SBig(*reinterpret_cast<const u16*>(dlStart + offset + 1));
|
||||||
offset += 3;
|
offset += 3;
|
||||||
|
|
||||||
|
@ -4,71 +4,138 @@
|
|||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
#include "gx.hpp"
|
#include "gx.hpp"
|
||||||
|
|
||||||
namespace aurora::gfx {
|
|
||||||
static logvisor::Module Log("aurora::gfx::stream");
|
static logvisor::Module Log("aurora::gfx::stream");
|
||||||
|
|
||||||
|
using aurora::gfx::gx::g_gxState;
|
||||||
|
|
||||||
struct SStreamState {
|
struct SStreamState {
|
||||||
GX::Primitive primitive;
|
GX::Primitive primitive;
|
||||||
metaforce::EStreamFlags flags;
|
u16 vertexCount = 0;
|
||||||
uint32_t vertexCount = 0;
|
aurora::ByteBuffer vertexBuffer;
|
||||||
ByteBuffer vertexBuffer;
|
std::vector<u16> indices;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
GX::Attr currentAttr{};
|
||||||
|
#endif
|
||||||
|
|
||||||
explicit SStreamState(GX::Primitive primitive) noexcept : primitive(primitive) {}
|
explicit SStreamState(GX::Primitive primitive, u16 numVerts, u16 vertexSize) noexcept : primitive(primitive) {
|
||||||
|
vertexBuffer.reserve_extra(size_t(numVerts) * vertexSize);
|
||||||
|
if (numVerts > 3 && (primitive == GX::TRIANGLEFAN || primitive == GX::TRIANGLESTRIP)) {
|
||||||
|
indices.reserve((u32(numVerts) - 3) * 3 + 3);
|
||||||
|
} else if (numVerts > 4 && primitive == GX::QUADS) {
|
||||||
|
indices.reserve(u32(numVerts) / 4 * 6);
|
||||||
|
} else {
|
||||||
|
indices.reserve(numVerts);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
static std::optional<SStreamState> sStreamState;
|
static std::optional<SStreamState> sStreamState;
|
||||||
|
|
||||||
void stream_begin(GX::Primitive primitive) noexcept {
|
void GXBegin(GX::Primitive primitive, GX::VtxFmt vtxFmt, u16 nVerts) noexcept {
|
||||||
|
#ifndef NDEBUG
|
||||||
if (sStreamState) {
|
if (sStreamState) {
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("Stream began twice!"));
|
Log.report(logvisor::Fatal, FMT_STRING("Stream began twice!"));
|
||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
sStreamState.emplace(primitive);
|
#endif
|
||||||
|
uint16_t vertexSize = 0;
|
||||||
|
for (GX::Attr attr{}; const auto type : g_gxState.vtxDesc) {
|
||||||
|
if (type == GX::DIRECT) {
|
||||||
|
if (attr == GX::VA_POS || attr == GX::VA_NRM) {
|
||||||
|
vertexSize += 12;
|
||||||
|
} else if (attr == GX::VA_CLR0 || attr == GX::VA_CLR1) {
|
||||||
|
vertexSize += 16;
|
||||||
|
} else if (attr >= GX::VA_TEX0 && attr <= GX::VA_TEX7) {
|
||||||
|
vertexSize += 8;
|
||||||
|
} else {
|
||||||
|
Log.report(logvisor::Fatal, FMT_STRING("don't know how to handle attr {}"), attr);
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
} else if (type != GX::NONE) {
|
||||||
|
Log.report(logvisor::Fatal, FMT_STRING("invalid vtx type {} for attr {}"), type, attr);
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
attr = GX::Attr(attr + 1);
|
||||||
|
}
|
||||||
|
if (vertexSize == 0) {
|
||||||
|
Log.report(logvisor::Fatal, FMT_STRING("no vtx attributes enabled?"));
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
sStreamState.emplace(primitive, nVerts, vertexSize);
|
||||||
}
|
}
|
||||||
|
static inline void check_attr_order(GX::Attr attr) noexcept {
|
||||||
void stream_vertex(metaforce::EStreamFlags flags, const zeus::CVector3f& pos, const zeus::CVector3f& nrm,
|
#ifndef NDEBUG
|
||||||
const zeus::CColor& color, const zeus::CVector2f& uv) noexcept {
|
|
||||||
if (!sStreamState) {
|
if (!sStreamState) {
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("Stream not started!"));
|
Log.report(logvisor::Fatal, FMT_STRING("Stream not started!"));
|
||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
if (sStreamState->flags) {
|
if (sStreamState->currentAttr >= attr) {
|
||||||
if (sStreamState->flags != flags) {
|
Log.report(logvisor::Fatal, FMT_STRING("bad attribute order: {}, last {}"), attr, sStreamState->currentAttr);
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("Stream changed flags?"));
|
|
||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
} else {
|
sStreamState->currentAttr = attr;
|
||||||
sStreamState->flags = flags;
|
#endif
|
||||||
}
|
|
||||||
sStreamState->vertexBuffer.append(&pos, 12);
|
|
||||||
if (flags & metaforce::EStreamFlagBits::fHasNormal) {
|
|
||||||
sStreamState->vertexBuffer.append(&nrm, 12);
|
|
||||||
}
|
|
||||||
if (flags & metaforce::EStreamFlagBits::fHasColor) {
|
|
||||||
sStreamState->vertexBuffer.append(&color, 16);
|
|
||||||
}
|
|
||||||
if (flags & metaforce::EStreamFlagBits::fHasTexture) {
|
|
||||||
sStreamState->vertexBuffer.append(&uv, 8);
|
|
||||||
}
|
|
||||||
sStreamState->vertexCount++;
|
|
||||||
}
|
}
|
||||||
|
void GXPosition3f32(const zeus::CVector3f& pos) noexcept {
|
||||||
void stream_end() noexcept {
|
#ifndef NDEBUG
|
||||||
const auto vertRange = push_verts(sStreamState->vertexBuffer.data(), sStreamState->vertexBuffer.size());
|
if (!sStreamState) {
|
||||||
|
Log.report(logvisor::Fatal, FMT_STRING("Stream not started!"));
|
||||||
stream::PipelineConfig config{};
|
unreachable();
|
||||||
config.shaderConfig.denormalizedVertexAttributes = true;
|
}
|
||||||
config.shaderConfig.denormalizedHasNrm = sStreamState->flags.IsSet(metaforce::EStreamFlagBits::fHasNormal);
|
sStreamState->currentAttr = GX::VA_POS;
|
||||||
const auto info = populate_pipeline_config(config, sStreamState->primitive, {});
|
#endif
|
||||||
const auto pipeline = pipeline_ref(config);
|
auto& state = *sStreamState;
|
||||||
|
state.vertexBuffer.append(&pos, 12);
|
||||||
push_draw_command(stream::DrawData{
|
if (state.primitive == GX::TRIANGLES || state.vertexCount < 3) {
|
||||||
|
state.indices.push_back(state.vertexCount);
|
||||||
|
} else if (state.primitive == GX::TRIANGLEFAN) {
|
||||||
|
state.indices.push_back(0);
|
||||||
|
state.indices.push_back(state.vertexCount - 1);
|
||||||
|
state.indices.push_back(state.vertexCount);
|
||||||
|
} else if (state.primitive == GX::TRIANGLESTRIP) {
|
||||||
|
if ((state.vertexCount & 1) == 0) {
|
||||||
|
state.indices.push_back(state.vertexCount - 2);
|
||||||
|
state.indices.push_back(state.vertexCount - 1);
|
||||||
|
} else {
|
||||||
|
state.indices.push_back(state.vertexCount - 1);
|
||||||
|
state.indices.push_back(state.vertexCount - 2);
|
||||||
|
}
|
||||||
|
state.indices.push_back(state.vertexCount);
|
||||||
|
} else if (state.primitive == GX::QUADS) {
|
||||||
|
if ((state.vertexCount & 3) == 3) {
|
||||||
|
state.indices.push_back(state.vertexCount - 1);
|
||||||
|
state.indices.push_back(state.vertexCount);
|
||||||
|
state.indices.push_back(state.vertexCount - 3);
|
||||||
|
} else {
|
||||||
|
state.indices.push_back(state.vertexCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++state.vertexCount;
|
||||||
|
}
|
||||||
|
void GXNormal3f32(const zeus::CVector3f& nrm) noexcept {
|
||||||
|
check_attr_order(GX::VA_NRM);
|
||||||
|
sStreamState->vertexBuffer.append(&nrm, 12);
|
||||||
|
}
|
||||||
|
void GXColor4f32(const zeus::CColor& color) noexcept {
|
||||||
|
check_attr_order(GX::VA_CLR0);
|
||||||
|
sStreamState->vertexBuffer.append(&color, 16);
|
||||||
|
}
|
||||||
|
void GXTexCoord2f32(const zeus::CVector2f& uv) noexcept {
|
||||||
|
check_attr_order(GX::VA_TEX0);
|
||||||
|
sStreamState->vertexBuffer.append(&uv, 8);
|
||||||
|
}
|
||||||
|
void GXEnd() noexcept {
|
||||||
|
const auto vertRange = aurora::gfx::push_verts(sStreamState->vertexBuffer.data(), sStreamState->vertexBuffer.size());
|
||||||
|
const auto indexRange = aurora::gfx::push_indices(aurora::ArrayRef{sStreamState->indices});
|
||||||
|
aurora::gfx::stream::PipelineConfig config{};
|
||||||
|
const auto info = populate_pipeline_config(config, GX::TRIANGLES, {});
|
||||||
|
const auto pipeline = aurora::gfx::pipeline_ref(config);
|
||||||
|
aurora::gfx::push_draw_command(aurora::gfx::stream::DrawData{
|
||||||
.pipeline = pipeline,
|
.pipeline = pipeline,
|
||||||
.vertRange = vertRange,
|
.vertRange = vertRange,
|
||||||
.uniformRange = build_uniform(info),
|
.uniformRange = build_uniform(info),
|
||||||
.vertexCount = sStreamState->vertexCount,
|
.indexRange = indexRange,
|
||||||
|
.indexCount = static_cast<uint32_t>(sStreamState->indices.size()),
|
||||||
.bindGroups = info.bindGroups,
|
.bindGroups = info.bindGroups,
|
||||||
});
|
});
|
||||||
|
|
||||||
sStreamState.reset();
|
sStreamState.reset();
|
||||||
}
|
}
|
||||||
} // namespace aurora::gfx
|
|
||||||
|
@ -22,7 +22,7 @@ wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] Pipeli
|
|||||||
};
|
};
|
||||||
uint64_t offset = 12;
|
uint64_t offset = 12;
|
||||||
uint32_t shaderLocation = 1;
|
uint32_t shaderLocation = 1;
|
||||||
if (info.usesNormal) {
|
if (config.shaderConfig.vtxAttrs[GX::VA_NRM] == GX::DIRECT) {
|
||||||
attributes[shaderLocation] = wgpu::VertexAttribute{
|
attributes[shaderLocation] = wgpu::VertexAttribute{
|
||||||
.format = wgpu::VertexFormat::Float32x3,
|
.format = wgpu::VertexFormat::Float32x3,
|
||||||
.offset = offset,
|
.offset = offset,
|
||||||
@ -31,7 +31,7 @@ wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] Pipeli
|
|||||||
offset += 12;
|
offset += 12;
|
||||||
shaderLocation++;
|
shaderLocation++;
|
||||||
}
|
}
|
||||||
if (info.usesVtxColor) {
|
if (config.shaderConfig.vtxAttrs[GX::VA_CLR0] == GX::DIRECT) {
|
||||||
attributes[shaderLocation] = wgpu::VertexAttribute{
|
attributes[shaderLocation] = wgpu::VertexAttribute{
|
||||||
.format = wgpu::VertexFormat::Float32x4,
|
.format = wgpu::VertexFormat::Float32x4,
|
||||||
.offset = offset,
|
.offset = offset,
|
||||||
@ -40,9 +40,8 @@ wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] Pipeli
|
|||||||
offset += 16;
|
offset += 16;
|
||||||
shaderLocation++;
|
shaderLocation++;
|
||||||
}
|
}
|
||||||
// TODO only sample 1?
|
for (int i = GX::VA_TEX0; i < GX::VA_TEX7; ++i) {
|
||||||
for (int i = 0; i < info.sampledTextures.size(); ++i) {
|
if (config.shaderConfig.vtxAttrs[i] != GX::DIRECT) {
|
||||||
if (!info.sampledTextures.test(i)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
attributes[shaderLocation] = wgpu::VertexAttribute{
|
attributes[shaderLocation] = wgpu::VertexAttribute{
|
||||||
@ -76,6 +75,7 @@ void render(const State& state, const DrawData& data, const wgpu::RenderPassEnco
|
|||||||
pass.SetBindGroup(2, find_bind_group(data.bindGroups.textureBindGroup));
|
pass.SetBindGroup(2, find_bind_group(data.bindGroups.textureBindGroup));
|
||||||
}
|
}
|
||||||
pass.SetVertexBuffer(0, g_vertexBuffer, data.vertRange.offset, data.vertRange.size);
|
pass.SetVertexBuffer(0, g_vertexBuffer, data.vertRange.offset, data.vertRange.size);
|
||||||
pass.Draw(data.vertexCount);
|
pass.SetIndexBuffer(g_indexBuffer, wgpu::IndexFormat::Uint16, data.indexRange.offset, data.indexRange.size);
|
||||||
|
pass.DrawIndexed(data.indexCount);
|
||||||
}
|
}
|
||||||
} // namespace aurora::gfx::stream
|
} // namespace aurora::gfx::stream
|
||||||
|
@ -8,7 +8,8 @@ struct DrawData {
|
|||||||
PipelineRef pipeline;
|
PipelineRef pipeline;
|
||||||
Range vertRange;
|
Range vertRange;
|
||||||
Range uniformRange;
|
Range uniformRange;
|
||||||
uint32_t vertexCount;
|
Range indexRange;
|
||||||
|
uint32_t indexCount;
|
||||||
gx::GXBindGroups bindGroups;
|
gx::GXBindGroups bindGroups;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user