mirror of https://github.com/AxioDL/metaforce.git
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
|
||||
}
|
||||
|
||||
void CCubeRenderer::SetThermalColdScale(float scale) {
|
||||
// TODO
|
||||
}
|
||||
void CCubeRenderer::SetThermalColdScale(float scale) { x2f8_thermColdScale = zeus::clamp(0.f, scale, 1.f); }
|
||||
|
||||
void CCubeRenderer::DoThermalBlendCold() {
|
||||
// TODO
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
#include "Graphics/CTexture.hpp"
|
||||
|
||||
namespace metaforce::CGX {
|
||||
SGXState sGXState;
|
||||
SGXState sGXState{};
|
||||
std::array<GX::VtxDescList, 11> sVtxDescList{};
|
||||
|
||||
void ResetGXStates() noexcept {
|
||||
sGXState.x48_descList = nullptr;
|
||||
// GXClearVtxDesc();
|
||||
sGXState.x48_descList = 0;
|
||||
GXClearVtxDesc();
|
||||
sGXState.x0_arrayPtrs.fill(nullptr);
|
||||
for (GX::TexMapID id = GX::TEXMAP0; id < GX::MAX_TEXMAP; id = static_cast<GX::TexMapID>(id + 1)) {
|
||||
CTexture::InvalidateTexMap(id);
|
||||
|
@ -16,7 +17,9 @@ void ResetGXStates() noexcept {
|
|||
GXSetTevKColor(id, item);
|
||||
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);
|
||||
// GXSetCurrentMtx(0);
|
||||
SetNumIndStages(0);
|
||||
|
|
|
@ -31,7 +31,7 @@ struct SGXState {
|
|||
std::array<u16, 2> x34_chanCtrls{0x4000, 0x4000};
|
||||
std::array<GXColor, 2> x38_chanAmbColors;
|
||||
std::array<GXColor, 2> x40_chanMatColors;
|
||||
GX::VtxDescList* x48_descList = nullptr;
|
||||
u32 x48_descList = 0;
|
||||
u8 x4c_dirtyChans = 0;
|
||||
u8 x4d_prevNumChans = 0;
|
||||
u8 x4e_numChans = 0;
|
||||
|
@ -53,6 +53,7 @@ struct SGXState {
|
|||
GXColor x25c_fogColor;
|
||||
};
|
||||
extern SGXState sGXState;
|
||||
extern std::array<GX::VtxDescList, 11> sVtxDescList;
|
||||
|
||||
static inline void update_fog(u32 value) noexcept {
|
||||
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) {
|
||||
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 {
|
||||
if (sGXState.x4c_dirtyChans != 0) {
|
||||
FlushState();
|
||||
|
@ -102,10 +105,6 @@ static inline void CallDisplayList(const void* data, u32 nbytes) noexcept {
|
|||
GXCallDisplayList(data, nbytes);
|
||||
}
|
||||
|
||||
static inline void End() noexcept {
|
||||
// no-op
|
||||
}
|
||||
|
||||
static inline const GXColor& GetChanAmbColor(EChannelId id) noexcept {
|
||||
const auto idx = std::underlying_type_t<EChannelId>(id);
|
||||
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 {
|
||||
// TODO convert to GX::VtxDescList
|
||||
aurora::gfx::model::set_vtx_desc_compressed(descList);
|
||||
u32 currentDescList = sGXState.x48_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 {
|
||||
|
|
|
@ -59,9 +59,16 @@ const std::array<zeus::CMatrix3f, 6> CGraphics::skCubeBasisMats{{
|
|||
|
||||
// Stream API
|
||||
static EStreamFlags sStreamFlags;
|
||||
static zeus::CColor sQueuedColor;
|
||||
static zeus::CVector2f sQueuedTexCoord;
|
||||
static zeus::CVector3f sQueuedNormal;
|
||||
static GX::Primitive sStreamPrimitive;
|
||||
static u32 sVerticesCount;
|
||||
// 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() {
|
||||
g_LightActive.reset();
|
||||
|
@ -518,55 +525,102 @@ void CGraphics::SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass
|
|||
}
|
||||
|
||||
void CGraphics::StreamBegin(GX::Primitive primitive) {
|
||||
sStreamFlags = {};
|
||||
aurora::gfx::stream_begin(primitive);
|
||||
// Originally ResetVertexDataStream(true);
|
||||
sQueuedVertices.clear();
|
||||
sQueuedVertices.emplace_back();
|
||||
sVerticesCount = 0;
|
||||
// End
|
||||
sStreamFlags = EStreamFlagBits::fHasColor;
|
||||
sStreamPrimitive = primitive;
|
||||
}
|
||||
|
||||
void CGraphics::StreamNormal(const zeus::CVector3f& nrm) {
|
||||
sQueuedNormal = nrm;
|
||||
sQueuedVertices.back().normal = nrm;
|
||||
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) {
|
||||
sQueuedColor = color;
|
||||
sQueuedVertices.back().color = color;
|
||||
sStreamFlags |= EStreamFlagBits::fHasColor;
|
||||
}
|
||||
|
||||
void CGraphics::StreamTexcoord(float x, float y) {
|
||||
sQueuedTexCoord = {x, y};
|
||||
sStreamFlags |= EStreamFlagBits::fHasTexture;
|
||||
}
|
||||
|
||||
void CGraphics::StreamTexcoord(const zeus::CVector2f& uv) {
|
||||
sQueuedTexCoord = uv;
|
||||
sQueuedVertices.back().texCoord = uv;
|
||||
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) {
|
||||
aurora::gfx::stream_vertex(sStreamFlags, pos, sQueuedNormal, sQueuedColor, sQueuedTexCoord);
|
||||
sQueuedVertices.back().vertex = pos;
|
||||
UpdateVertexDataStream();
|
||||
}
|
||||
|
||||
void CGraphics::StreamEnd() {
|
||||
SetTevStates(sStreamFlags);
|
||||
aurora::gfx::stream_end();
|
||||
if (sVerticesCount != 0) {
|
||||
FlushStream();
|
||||
}
|
||||
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,
|
||||
const zeus::CColor& col, s32 numVerts) {
|
||||
StreamBegin(primitive);
|
||||
|
@ -580,12 +634,12 @@ void CGraphics::DrawPrimitive(GX::Primitive primitive, const zeus::CVector3f* po
|
|||
|
||||
void CGraphics::SetTevStates(EStreamFlags flags) noexcept {
|
||||
if (flags & EStreamFlagBits::fHasTexture) {
|
||||
CGX::SetNumTexGens(0);
|
||||
CGX::SetNumTevStages(1);
|
||||
CGX::SetNumTexGens(1); // sTextureUsed & 3?
|
||||
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR0A0);
|
||||
CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD1, GX::TEXMAP1, GX::COLOR0A0);
|
||||
} else /* if (flags < 8) ? */ {
|
||||
CGX::SetNumTexGens(2); // sTextureUsed & 3?
|
||||
} else {
|
||||
CGX::SetNumTexGens(0);
|
||||
CGX::SetNumTevStages(1);
|
||||
CGX::SetTevOrder(GX::TEVSTAGE0, 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);
|
||||
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
|
||||
|
|
|
@ -205,6 +205,10 @@ public:
|
|||
static ERglEnum g_depthFunc;
|
||||
static ERglCullMode g_cullMode;
|
||||
|
||||
static void Startup();
|
||||
static void InitGraphicsVariables();
|
||||
static void InitGraphicsDefaults();
|
||||
static void SetDefaultVtxAttrFmt();
|
||||
static void DisableAllLights();
|
||||
static void LoadLight(ERglLight light, const CLight& info);
|
||||
static void EnableLight(ERglLight light);
|
||||
|
@ -353,14 +357,18 @@ public:
|
|||
static void SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass);
|
||||
static void StreamBegin(GX::Primitive primitive);
|
||||
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 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 StreamVertex(float xyz);
|
||||
static void StreamVertex(float x, float y, float z);
|
||||
static inline void StreamTexcoord(float x, float y) { StreamTexcoord({x, y}); }
|
||||
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 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,
|
||||
const zeus::CColor& col, s32 numVerts);
|
||||
};
|
||||
|
|
|
@ -49,8 +49,9 @@ enum AttrType {
|
|||
};
|
||||
|
||||
struct VtxDescList {
|
||||
Attr attr;
|
||||
AttrType type;
|
||||
Attr attr = GX::VA_NULL;
|
||||
AttrType type = GX::NONE;
|
||||
operator bool() const { return attr != GX::VA_NULL; }
|
||||
};
|
||||
|
||||
enum VtxFmt {
|
||||
|
@ -665,6 +666,32 @@ enum ProjectionType {
|
|||
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
|
||||
|
||||
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;
|
||||
// Originally u8 instead of floats
|
||||
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 GXClearVtxDesc() 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 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;
|
||||
// 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;
|
||||
CGraphics::SetModelMatrix(modXf);
|
||||
|
||||
SParticleUniforms uniformData = {
|
||||
CGraphics::GetPerspectiveProjectionMatrix(/*true*/) * CGraphics::g_GXModelView.toMatrix4f(), {1.f, 1.f, 1.f, 1.f}};
|
||||
// SParticleUniforms uniformData = {
|
||||
// CGraphics::GetPerspectiveProjectionMatrix(/*true*/) * CGraphics::g_GXModelView.toMatrix4f(), {1.f, 1.f, 1.f, 1.f}};
|
||||
// decal.m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
|
||||
|
||||
bool redToAlpha = sMoveRedToAlphaBuffer && desc.x18_ADD && desc.x14_TEX;
|
||||
|
@ -104,52 +104,52 @@ void CDecal::RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) const {
|
|||
// else
|
||||
// CGraphics::SetShaderDataBinding(decal.m_normalDataBind);
|
||||
|
||||
g_instTexData.clear();
|
||||
g_instTexData.reserve(1);
|
||||
// g_instTexData.clear();
|
||||
// g_instTexData.reserve(1);
|
||||
|
||||
SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||
if (decal.x8_rotation == 0.f) {
|
||||
inst.pos[0] = 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[3] = zeus::CVector3f(size, 0.001f, -size);
|
||||
} else {
|
||||
float ang = zeus::degToRad(decal.x8_rotation);
|
||||
float sinSize = std::sin(ang) * size;
|
||||
float cosSize = std::cos(ang) * size;
|
||||
inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 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[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize);
|
||||
}
|
||||
inst.color = color;
|
||||
inst.uvs[0] = zeus::CVector2f(uvSet.xMin, uvSet.yMin);
|
||||
inst.uvs[1] = zeus::CVector2f(uvSet.xMax, uvSet.yMin);
|
||||
inst.uvs[2] = zeus::CVector2f(uvSet.xMin, uvSet.yMax);
|
||||
inst.uvs[3] = zeus::CVector2f(uvSet.xMax, uvSet.yMax);
|
||||
// SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||
// if (decal.x8_rotation == 0.f) {
|
||||
// inst.pos[0] = 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[3] = zeus::CVector3f(size, 0.001f, -size);
|
||||
// } else {
|
||||
// float ang = zeus::degToRad(decal.x8_rotation);
|
||||
// float sinSize = std::sin(ang) * size;
|
||||
// float cosSize = std::cos(ang) * size;
|
||||
// inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 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[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize);
|
||||
// }
|
||||
// inst.color = color;
|
||||
// inst.uvs[0] = zeus::CVector2f(uvSet.xMin, uvSet.yMin);
|
||||
// inst.uvs[1] = zeus::CVector2f(uvSet.xMax, uvSet.yMin);
|
||||
// inst.uvs[2] = zeus::CVector2f(uvSet.xMin, uvSet.yMax);
|
||||
// inst.uvs[3] = zeus::CVector2f(uvSet.xMax, uvSet.yMax);
|
||||
|
||||
// decal.m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
|
||||
// CGraphics::DrawInstances(0, 4, g_instTexData.size());
|
||||
} else {
|
||||
g_instNoTexData.clear();
|
||||
g_instNoTexData.reserve(1);
|
||||
// g_instNoTexData.clear();
|
||||
// g_instNoTexData.reserve(1);
|
||||
|
||||
SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||
if (decal.x8_rotation == 0.f) {
|
||||
inst.pos[0] = 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[3] = zeus::CVector3f(size, 0.001f, -size);
|
||||
} else {
|
||||
float ang = zeus::degToRad(decal.x8_rotation);
|
||||
float sinSize = std::sin(ang) * size;
|
||||
float cosSize = std::cos(ang) * size;
|
||||
inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 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[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize);
|
||||
}
|
||||
inst.color = color;
|
||||
// SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||
// if (decal.x8_rotation == 0.f) {
|
||||
// inst.pos[0] = 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[3] = zeus::CVector3f(size, 0.001f, -size);
|
||||
// } else {
|
||||
// float ang = zeus::degToRad(decal.x8_rotation);
|
||||
// float sinSize = std::sin(ang) * size;
|
||||
// float cosSize = std::cos(ang) * size;
|
||||
// inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 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[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize);
|
||||
// }
|
||||
// inst.color = color;
|
||||
|
||||
// decal.m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
|
||||
// CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "Runtime/GameGlobalObjects.hpp"
|
||||
#include "Runtime/Character/CActorLights.hpp"
|
||||
#include "Runtime/Graphics/CCubeRenderer.hpp"
|
||||
#include "Runtime/Graphics/CGX.hpp"
|
||||
#include "Runtime/Graphics/CModel.hpp"
|
||||
#include "Runtime/Graphics/Shaders/CElementGenShaders.hpp"
|
||||
#include "Runtime/Particle/CElectricDescription.hpp"
|
||||
|
@ -19,11 +20,11 @@ namespace metaforce {
|
|||
namespace {
|
||||
logvisor::Module Log("metaforce::CElementGen");
|
||||
|
||||
constexpr std::array ShadClsSizes{
|
||||
sizeof(SParticleInstanceTex),
|
||||
sizeof(SParticleInstanceIndTex),
|
||||
sizeof(SParticleInstanceNoTex),
|
||||
};
|
||||
// constexpr std::array ShadClsSizes{
|
||||
// sizeof(SParticleInstanceTex),
|
||||
// sizeof(SParticleInstanceIndTex),
|
||||
// sizeof(SParticleInstanceNoTex),
|
||||
// };
|
||||
} // Anonymous namespace
|
||||
|
||||
u16 CElementGen::g_GlobalSeed = 99;
|
||||
|
@ -35,9 +36,9 @@ bool CElementGen::g_ParticleSystemInitialized = false;
|
|||
bool CElementGen::sMoveRedToAlphaBuffer = false;
|
||||
CParticle* CElementGen::g_currentParticle = nullptr;
|
||||
|
||||
std::vector<SParticleInstanceTex> g_instTexData;
|
||||
std::vector<SParticleInstanceIndTex> g_instIndTexData;
|
||||
std::vector<SParticleInstanceNoTex> g_instNoTexData;
|
||||
// std::vector<SParticleInstanceTex> g_instTexData;
|
||||
// std::vector<SParticleInstanceIndTex> g_instIndTexData;
|
||||
// std::vector<SParticleInstanceNoTex> g_instNoTexData;
|
||||
|
||||
void CElementGen::Initialize() {
|
||||
if (g_ParticleSystemInitialized)
|
||||
|
@ -210,21 +211,21 @@ CElementGen::CElementGen(TToken<CGenDescription> gen, EModelOrientationType orie
|
|||
if (x26c_31_LINE) {
|
||||
CUVElement* texr = desc->x54_x40_TEXR.get();
|
||||
// TODO
|
||||
// aurora::gfx::TextureHandle tex;
|
||||
// if (texr)
|
||||
// tex = texr->GetValueTexture(0).GetObj()->GetTexture();
|
||||
// aurora::gfx::TextureHandle tex;
|
||||
// if (texr)
|
||||
// tex = texr->GetValueTexture(0).GetObj()->GetTexture();
|
||||
int maxVerts = x90_MAXP;
|
||||
// m_lineRenderer.reset(
|
||||
// new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, maxVerts * 2, tex, x26c_26_AAPH, x26c_28_zTest));
|
||||
// m_lineRenderer.reset(
|
||||
// new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, maxVerts * 2, tex, x26c_26_AAPH, x26c_28_zTest));
|
||||
} else {
|
||||
m_shaderClass = CElementGenShaders::GetShaderClass(*this);
|
||||
}
|
||||
|
||||
_RecreatePipelines();
|
||||
// CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
|
||||
// CElementGenShaders::BuildShaderDataBinding(ctx, *this);
|
||||
// return true;
|
||||
// } BooTrace);
|
||||
// CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
|
||||
// CElementGenShaders::BuildShaderDataBinding(ctx, *this);
|
||||
// return true;
|
||||
// } BooTrace);
|
||||
}
|
||||
|
||||
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;
|
||||
maxInsts = (maxInsts == 0 ? 256 : maxInsts);
|
||||
|
||||
// CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
|
||||
// if (!x26c_31_LINE) {
|
||||
// m_instBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, ShadClsSizes[size_t(m_shaderClass)], maxInsts);
|
||||
// m_uniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1);
|
||||
// }
|
||||
// if (x28_loadedGenDesc->x45_24_x31_26_PMUS) {
|
||||
// m_instBufPmus = ctx.newDynamicBuffer(boo::BufferUse::Vertex, ShadClsSizes[size_t(m_shaderClass)], maxInsts);
|
||||
// m_uniformBufPmus = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1);
|
||||
// }
|
||||
// return true;
|
||||
// } BooTrace);
|
||||
// CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
|
||||
// if (!x26c_31_LINE) {
|
||||
// m_instBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, ShadClsSizes[size_t(m_shaderClass)], maxInsts);
|
||||
// m_uniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1);
|
||||
// }
|
||||
// if (x28_loadedGenDesc->x45_24_x31_26_PMUS) {
|
||||
// m_instBufPmus = ctx.newDynamicBuffer(boo::BufferUse::Vertex, ShadClsSizes[size_t(m_shaderClass)], maxInsts);
|
||||
// m_uniformBufPmus = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1);
|
||||
// }
|
||||
// return true;
|
||||
// } BooTrace);
|
||||
}
|
||||
|
||||
bool CElementGen::InternalUpdate(double dt) {
|
||||
|
@ -838,12 +839,12 @@ u32 CElementGen::GetSystemCount() const {
|
|||
|
||||
void CElementGen::Render(const CActorLights* actorLights) {
|
||||
// Check to make sure our buffers are ready to render
|
||||
if (!x26c_31_LINE) { // && (!m_instBuf || !m_uniformBuf)
|
||||
return;
|
||||
}
|
||||
if (x28_loadedGenDesc->x45_24_x31_26_PMUS) { // && (!m_instBufPmus || !m_uniformBufPmus)
|
||||
return;
|
||||
}
|
||||
// if (!x26c_31_LINE) {
|
||||
// return;
|
||||
// }
|
||||
// if (x28_loadedGenDesc->x45_24_x31_26_PMUS) { // && (!m_instBufPmus || !m_uniformBufPmus)
|
||||
// return;
|
||||
// }
|
||||
|
||||
SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CElementGen::Render {}"), *x1c_genDesc.GetObjectTag()).c_str(),
|
||||
zeus::skYellow);
|
||||
|
@ -876,16 +877,19 @@ void CElementGen::Render(const CActorLights* actorLights) {
|
|||
|
||||
void CElementGen::RenderModels(const CActorLights* actorLights) {
|
||||
// Check to make sure our buffers are ready to render
|
||||
if (!x26c_31_LINE) { // && (!m_instBuf || !m_uniformBuf)
|
||||
return;
|
||||
}
|
||||
if (x28_loadedGenDesc->x45_24_x31_26_PMUS) { // && (!m_instBufPmus || !m_uniformBufPmus)
|
||||
return;
|
||||
}
|
||||
// if (!x26c_31_LINE) { // && (!m_instBuf || !m_uniformBuf)
|
||||
// return;
|
||||
// }
|
||||
// if (x28_loadedGenDesc->x45_24_x31_26_PMUS) { // && (!m_instBufPmus || !m_uniformBufPmus)
|
||||
// return;
|
||||
// }
|
||||
|
||||
CParticleGlobals::instance()->m_particleAccessParameters = nullptr;
|
||||
if (x26d_26_modelsUseLights)
|
||||
if (x26d_26_modelsUseLights) {
|
||||
CGraphics::SetLightState(x274_backupLightActive);
|
||||
} else {
|
||||
CGraphics::SetAmbientColor(zeus::skWhite);
|
||||
}
|
||||
CGlobalRandom gr(x27c_randState);
|
||||
|
||||
CGenDescription* desc = x1c_genDesc.GetObj();
|
||||
|
@ -897,20 +901,24 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
|
|||
bool moveRedToAlphaBuffer = false;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (desc->x44_31_x31_25_PMAB) {
|
||||
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false);
|
||||
if (moveRedToAlphaBuffer)
|
||||
if (moveRedToAlphaBuffer) {
|
||||
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear);
|
||||
else
|
||||
} else {
|
||||
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One,
|
||||
ERglLogicOp::Clear);
|
||||
CGraphics::SetAlphaCompare(ERglAlphaFunc::Greater, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
|
||||
}
|
||||
} else {
|
||||
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true);
|
||||
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha,
|
||||
ERglLogicOp::Clear);
|
||||
CGraphics::SetAlphaCompare(ERglAlphaFunc::Greater, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
|
||||
}
|
||||
|
||||
CGraphics::SetCullMode(ERglCullMode::None);
|
||||
|
@ -920,37 +928,60 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
|
|||
int partFrame = x74_curFrame - target.x28_startFrame;
|
||||
cachedTex = texr->GetValueTexture(partFrame).GetObj();
|
||||
cachedTex->Load(GX::TEXMAP0, EClampMode::Repeat);
|
||||
/* Shade as TEXC * RASC and TEXA * RASA */
|
||||
|
||||
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc);
|
||||
if (moveRedToAlphaBuffer) {
|
||||
/* Color = Prev.rgb * Prev.a */
|
||||
/* Alpha = Tex.r * Prev.a */
|
||||
CGX::SetTevColorIn(GX::TEVSTAGE1, GX::CC_ZERO, GX::CC_CPREV, GX::CC_APREV, GX::CC_ZERO);
|
||||
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();
|
||||
texr->GetValueUV(partFrame, uvs);
|
||||
} else {
|
||||
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::skPassThru);
|
||||
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
|
||||
}
|
||||
|
||||
switch (m_shaderClass) {
|
||||
case CElementGenShaders::EShaderClass::Tex:
|
||||
g_instTexData.clear();
|
||||
g_instTexData.reserve(x30_particles.size());
|
||||
break;
|
||||
case CElementGenShaders::EShaderClass::NoTex:
|
||||
g_instNoTexData.clear();
|
||||
g_instNoTexData.reserve(x30_particles.size());
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
||||
break;
|
||||
}
|
||||
// switch (m_shaderClass) {
|
||||
// case CElementGenShaders::EShaderClass::Tex:
|
||||
// g_instTexData.clear();
|
||||
// g_instTexData.reserve(x30_particles.size());
|
||||
// break;
|
||||
// case CElementGenShaders::EShaderClass::NoTex:
|
||||
// g_instNoTexData.clear();
|
||||
// g_instNoTexData.reserve(x30_particles.size());
|
||||
// break;
|
||||
// default:
|
||||
// Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
||||
// 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));
|
||||
//
|
||||
// if (moveRedToAlphaBuffer)
|
||||
// CGraphics::SetShaderDataBinding(m_redToAlphaDataBindPmus[g_Renderer->IsThermalVisorHotPass()]);
|
||||
// else
|
||||
// CGraphics::SetShaderDataBinding(m_normalDataBindPmus[g_Renderer->IsThermalVisorHotPass()]);
|
||||
// m_uniformBufPmus->load(&uniformData, sizeof(SParticleUniforms));
|
||||
//
|
||||
// if (moveRedToAlphaBuffer)
|
||||
// CGraphics::SetShaderDataBinding(m_redToAlphaDataBindPmus[g_Renderer->IsThermalVisorHotPass()]);
|
||||
// else
|
||||
// CGraphics::SetShaderDataBinding(m_normalDataBindPmus[g_Renderer->IsThermalVisorHotPass()]);
|
||||
}
|
||||
|
||||
zeus::CTransform orient = zeus::CTransform();
|
||||
|
@ -1041,54 +1072,44 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
|
|||
CGraphics::SetModelMatrix((x10c_globalScaleTransform * partTrans) * x178_localScaleTransform);
|
||||
|
||||
if (desc->x45_24_x31_26_PMUS) {
|
||||
if (!texConst) {
|
||||
CTexture* tex = texr->GetValueTexture(x74_curFrame - particle.x28_startFrame).GetObj();
|
||||
if (tex != cachedTex) {
|
||||
tex->Load(GX::TEXMAP0, EClampMode::Repeat);
|
||||
cachedTex = tex;
|
||||
}
|
||||
}
|
||||
|
||||
switch (m_shaderClass) {
|
||||
case CElementGenShaders::EShaderClass::Tex: {
|
||||
SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||
inst.pos[0] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, 0.5f};
|
||||
inst.pos[1] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, 0.5f};
|
||||
inst.pos[2] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, -0.5f};
|
||||
inst.pos[3] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, -0.5f};
|
||||
inst.color = col;
|
||||
inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||
inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||
inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||
inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||
break;
|
||||
}
|
||||
case CElementGenShaders::EShaderClass::NoTex: {
|
||||
SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||
inst.pos[0] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, 0.5f};
|
||||
inst.pos[1] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, 0.5f};
|
||||
inst.pos[2] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, -0.5f};
|
||||
inst.pos[3] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, -0.5f};
|
||||
inst.color = col;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
if (moveRedToAlphaBuffer) {
|
||||
CGX::Begin(GX::QUADS, GX::VTXFMT0, 4);
|
||||
GXPosition3f32(0.5f, 0.f, 0.5f);
|
||||
GXColor4f32(col);
|
||||
GXTexCoord2f32(uvs.xMax, uvs.yMax);
|
||||
GXPosition3f32(-0.5f, 0.f, 0.5f);
|
||||
GXColor4f32(col);
|
||||
GXTexCoord2f32(uvs.xMin, uvs.yMax);
|
||||
GXPosition3f32(-0.5f, 0.f, -0.5f);
|
||||
GXColor4f32(col);
|
||||
GXTexCoord2f32(uvs.xMin, uvs.yMin);
|
||||
GXPosition3f32(0.5f, 0.f, -0.5f);
|
||||
GXColor4f32(col);
|
||||
GXTexCoord2f32(uvs.xMax, uvs.yMin);
|
||||
CGX::End();
|
||||
} else {
|
||||
CGraphics::StreamBegin(GX::QUADS);
|
||||
CGraphics::StreamColor(col);
|
||||
CGraphics::StreamTexcoord(uvs.xMax, uvs.yMax);
|
||||
CGraphics::StreamVertex(0.5f, 0.f, 0.5f);
|
||||
CGraphics::StreamTexcoord(uvs.xMin, uvs.yMax);
|
||||
CGraphics::StreamVertex(-0.5f, 0.f, 0.5f);
|
||||
CGraphics::StreamTexcoord(uvs.xMin, uvs.yMin);
|
||||
CGraphics::StreamVertex(-0.5f, 0.f, -0.5f);
|
||||
CGraphics::StreamTexcoord(uvs.xMax, uvs.yMin);
|
||||
CGraphics::StreamVertex(0.5f, 0.f, -0.5f);
|
||||
CGraphics::StreamEnd();
|
||||
}
|
||||
} else {
|
||||
CModel* model = desc->x5c_x48_PMDL.GetObj();
|
||||
if (actorLights)
|
||||
actorLights->ActivateLights();
|
||||
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) {
|
||||
CModelFlags flags{7, 0, 1, col};
|
||||
// flags.m_extendedShader = EExtendedShader::ForcedAdditiveNoZWrite;
|
||||
model->Draw(flags);
|
||||
model->Draw({7, 0, 1, col});
|
||||
} else if (1.f == col.a()) {
|
||||
model->Draw({0, 0, 3, zeus::skWhite});
|
||||
} 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;
|
||||
}
|
||||
|
||||
if (desc->x45_24_x31_26_PMUS) {
|
||||
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)
|
||||
if (x26d_26_modelsUseLights) {
|
||||
CGraphics::DisableAllLights();
|
||||
}
|
||||
|
||||
CGraphics::SetCullMode(ERglCullMode::Front);
|
||||
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() {
|
||||
|
@ -1258,8 +1266,9 @@ void CElementGen::RenderParticles() {
|
|||
bool constUVs = true;
|
||||
CTexture* cachedTex = nullptr;
|
||||
|
||||
SParticleUniforms uniformData = {
|
||||
CGraphics::GetPerspectiveProjectionMatrix(/*true*/) * CGraphics::g_GXModelView.toMatrix4f(), {1.f, 1.f, 1.f, 1.f}};
|
||||
// SParticleUniforms uniformData = {CGraphics::GetPerspectiveProjectionMatrix(/*true*/) *
|
||||
// CGraphics::g_GXModelView.toMatrix4f(),
|
||||
// {1.f, 1.f, 1.f, 1.f}};
|
||||
|
||||
if (texr) {
|
||||
CParticle& target = x30_particles[0];
|
||||
|
@ -1269,14 +1278,14 @@ void CElementGen::RenderParticles() {
|
|||
|
||||
if (x338_moduColor != zeus::skBlack) {
|
||||
/* Add RASC * PREVC pass for MODU color loaded into channel mat-color */
|
||||
uniformData.moduColor = x338_moduColor;
|
||||
// uniformData.moduColor = x338_moduColor;
|
||||
}
|
||||
|
||||
texr->GetValueUV(partFrame, uvs);
|
||||
constUVs = texr->HasConstantUV();
|
||||
}
|
||||
|
||||
// m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
|
||||
// m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
|
||||
|
||||
std::vector<CParticleListItem> sortItems;
|
||||
if (desc->x44_28_x30_28_SORT) {
|
||||
|
@ -1301,15 +1310,15 @@ void CElementGen::RenderParticles() {
|
|||
|
||||
if (g_subtractBlend) {
|
||||
// FIXME should there be NoTex specializations for RedToAlpha?
|
||||
// if (moveRedToAlphaBuffer && desc->x54_x40_TEXR)
|
||||
// CGraphics::SetShaderDataBinding(m_redToAlphaSubDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||
// else
|
||||
// CGraphics::SetShaderDataBinding(m_normalSubDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||
// if (moveRedToAlphaBuffer && desc->x54_x40_TEXR)
|
||||
// CGraphics::SetShaderDataBinding(m_redToAlphaSubDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||
// else
|
||||
// CGraphics::SetShaderDataBinding(m_normalSubDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||
} else {
|
||||
// if (moveRedToAlphaBuffer && desc->x54_x40_TEXR)
|
||||
// CGraphics::SetShaderDataBinding(m_redToAlphaDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||
// else
|
||||
// CGraphics::SetShaderDataBinding(m_normalDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||
// if (moveRedToAlphaBuffer && desc->x54_x40_TEXR)
|
||||
// CGraphics::SetShaderDataBinding(m_redToAlphaDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||
// else
|
||||
// CGraphics::SetShaderDataBinding(m_normalDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||
}
|
||||
|
||||
int mbspVal = std::max(1, x270_MBSP);
|
||||
|
@ -1344,19 +1353,19 @@ void CElementGen::RenderParticles() {
|
|||
}
|
||||
#endif
|
||||
|
||||
switch (m_shaderClass) {
|
||||
case CElementGenShaders::EShaderClass::Tex:
|
||||
g_instTexData.clear();
|
||||
g_instTexData.reserve(x30_particles.size());
|
||||
break;
|
||||
case CElementGenShaders::EShaderClass::NoTex:
|
||||
g_instNoTexData.clear();
|
||||
g_instNoTexData.reserve(x30_particles.size());
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
||||
break;
|
||||
}
|
||||
// switch (m_shaderClass) {
|
||||
// case CElementGenShaders::EShaderClass::Tex:
|
||||
// g_instTexData.clear();
|
||||
// g_instTexData.reserve(x30_particles.size());
|
||||
// break;
|
||||
// case CElementGenShaders::EShaderClass::NoTex:
|
||||
// g_instNoTexData.clear();
|
||||
// g_instNoTexData.reserve(x30_particles.size());
|
||||
// break;
|
||||
// default:
|
||||
// Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
||||
// break;
|
||||
// }
|
||||
|
||||
if (!x26c_29_ORNT) {
|
||||
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;
|
||||
if (0.f == particle.x30_lineWidthOrRota) {
|
||||
switch (m_shaderClass) {
|
||||
case CElementGenShaders::EShaderClass::Tex: {
|
||||
SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||
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[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.color = particle.x34_color;
|
||||
inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||
inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||
inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||
inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||
break;
|
||||
}
|
||||
case CElementGenShaders::EShaderClass::NoTex: {
|
||||
SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||
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[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.color = particle.x34_color;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// switch (m_shaderClass) {
|
||||
// case CElementGenShaders::EShaderClass::Tex: {
|
||||
// SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||
// 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[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.color = particle.x34_color;
|
||||
// inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||
// inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||
// inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||
// inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||
// break;
|
||||
// }
|
||||
// case CElementGenShaders::EShaderClass::NoTex: {
|
||||
// SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||
// 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[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.color = particle.x34_color;
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
} else {
|
||||
float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
|
||||
float sinT = std::sin(theta) * size;
|
||||
float cosT = std::cos(theta) * size;
|
||||
|
||||
switch (m_shaderClass) {
|
||||
case CElementGenShaders::EShaderClass::Tex: {
|
||||
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[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f};
|
||||
inst.pos[2] =
|
||||
zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), 1.f};
|
||||
inst.pos[3] =
|
||||
zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), 1.f};
|
||||
inst.color = particle.x34_color;
|
||||
inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||
inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||
inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||
inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||
break;
|
||||
}
|
||||
case CElementGenShaders::EShaderClass::NoTex: {
|
||||
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[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f};
|
||||
inst.pos[2] =
|
||||
zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), 1.f};
|
||||
inst.pos[3] =
|
||||
zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), 1.f};
|
||||
inst.color = particle.x34_color;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// switch (m_shaderClass) {
|
||||
// case CElementGenShaders::EShaderClass::Tex: {
|
||||
// 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[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f};
|
||||
// inst.pos[2] =
|
||||
// zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), 1.f};
|
||||
// inst.pos[3] =
|
||||
// zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), 1.f};
|
||||
// inst.color = particle.x34_color;
|
||||
// inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||
// inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||
// inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||
// inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||
// break;
|
||||
// }
|
||||
// case CElementGenShaders::EShaderClass::NoTex: {
|
||||
// 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[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f};
|
||||
// inst.pos[2] =
|
||||
// zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), 1.f};
|
||||
// inst.pos[3] =
|
||||
// zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), 1.f};
|
||||
// inst.color = particle.x34_color;
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1487,65 +1496,65 @@ void CElementGen::RenderParticles() {
|
|||
texr->GetValueUV(partFrame, uvs);
|
||||
}
|
||||
|
||||
switch (m_shaderClass) {
|
||||
case CElementGenShaders::EShaderClass::Tex: {
|
||||
SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||
viewPoint += rightVec * 0.5f;
|
||||
inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
||||
inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
||||
viewPoint -= rightVec;
|
||||
inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
||||
inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
||||
inst.color = particle.x34_color;
|
||||
inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||
inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||
inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||
inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||
break;
|
||||
}
|
||||
case CElementGenShaders::EShaderClass::NoTex: {
|
||||
SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||
viewPoint += rightVec * 0.5f;
|
||||
inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
||||
inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
||||
viewPoint -= rightVec;
|
||||
inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
||||
inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
||||
inst.color = particle.x34_color;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// switch (m_shaderClass) {
|
||||
// case CElementGenShaders::EShaderClass::Tex: {
|
||||
// SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||
// viewPoint += rightVec * 0.5f;
|
||||
// inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
||||
// inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
||||
// viewPoint -= rightVec;
|
||||
// inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
||||
// inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
||||
// inst.color = particle.x34_color;
|
||||
// inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||
// inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||
// inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||
// inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||
// break;
|
||||
// }
|
||||
// case CElementGenShaders::EShaderClass::NoTex: {
|
||||
// SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||
// viewPoint += rightVec * 0.5f;
|
||||
// inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
||||
// inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
||||
// viewPoint -= rightVec;
|
||||
// inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
|
||||
// inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
|
||||
// inst.color = particle.x34_color;
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
switch (m_shaderClass) {
|
||||
case CElementGenShaders::EShaderClass::Tex:
|
||||
// m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
|
||||
// CGraphics::DrawInstances(0, 4, g_instTexData.size());
|
||||
// m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
|
||||
// CGraphics::DrawInstances(0, 4, g_instTexData.size());
|
||||
break;
|
||||
case CElementGenShaders::EShaderClass::NoTex:
|
||||
// m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
|
||||
// CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
|
||||
// m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
|
||||
// CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (m_shaderClass) {
|
||||
case CElementGenShaders::EShaderClass::Tex:
|
||||
g_instTexData.clear();
|
||||
g_instTexData.reserve(x30_particles.size() * mbspVal);
|
||||
break;
|
||||
case CElementGenShaders::EShaderClass::NoTex:
|
||||
g_instNoTexData.clear();
|
||||
g_instNoTexData.reserve(x30_particles.size() * mbspVal);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
||||
break;
|
||||
}
|
||||
// switch (m_shaderClass) {
|
||||
// case CElementGenShaders::EShaderClass::Tex:
|
||||
// g_instTexData.clear();
|
||||
// g_instTexData.reserve(x30_particles.size() * mbspVal);
|
||||
// break;
|
||||
// case CElementGenShaders::EShaderClass::NoTex:
|
||||
// g_instNoTexData.clear();
|
||||
// g_instNoTexData.reserve(x30_particles.size() * mbspVal);
|
||||
// break;
|
||||
// default:
|
||||
// Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
||||
// break;
|
||||
// }
|
||||
const float mbspFac = 1.f / float(mbspVal);
|
||||
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);
|
||||
|
@ -1569,32 +1578,32 @@ void CElementGen::RenderParticles() {
|
|||
vec += mbspVec;
|
||||
zeus::CVector3f vec2 = systemCameraMatrix * vec;
|
||||
|
||||
switch (m_shaderClass) {
|
||||
case CElementGenShaders::EShaderClass::Tex: {
|
||||
SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||
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[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.color = particle.x34_color;
|
||||
inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||
inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||
inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||
inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||
break;
|
||||
}
|
||||
case CElementGenShaders::EShaderClass::NoTex: {
|
||||
SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||
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[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.color = particle.x34_color;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// switch (m_shaderClass) {
|
||||
// case CElementGenShaders::EShaderClass::Tex: {
|
||||
// SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||
// 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[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.color = particle.x34_color;
|
||||
// inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||
// inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||
// inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||
// inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||
// break;
|
||||
// }
|
||||
// case CElementGenShaders::EShaderClass::NoTex: {
|
||||
// SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||
// 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[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.color = particle.x34_color;
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
|
||||
|
@ -1605,43 +1614,43 @@ void CElementGen::RenderParticles() {
|
|||
vec += mbspVec;
|
||||
zeus::CVector3f vec2 = systemCameraMatrix * vec;
|
||||
|
||||
switch (m_shaderClass) {
|
||||
case CElementGenShaders::EShaderClass::Tex: {
|
||||
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[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[3] = zeus::CVector4f{vec2.x() - (sinT + cosT), vec2.y(), vec2.z() - (cosT - sinT), 1.f};
|
||||
inst.color = particle.x34_color;
|
||||
inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||
inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||
inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||
inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||
break;
|
||||
}
|
||||
case CElementGenShaders::EShaderClass::NoTex: {
|
||||
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[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[3] = zeus::CVector4f{vec2.x() - (sinT + cosT), vec2.y(), vec2.z() - (cosT - sinT), 1.f};
|
||||
inst.color = particle.x34_color;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// switch (m_shaderClass) {
|
||||
// case CElementGenShaders::EShaderClass::Tex: {
|
||||
// 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[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[3] = zeus::CVector4f{vec2.x() - (sinT + cosT), vec2.y(), vec2.z() - (cosT - sinT), 1.f};
|
||||
// inst.color = particle.x34_color;
|
||||
// inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
||||
// inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
||||
// inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
||||
// inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
||||
// break;
|
||||
// }
|
||||
// case CElementGenShaders::EShaderClass::NoTex: {
|
||||
// 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[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[3] = zeus::CVector4f{vec2.x() - (sinT + cosT), vec2.y(), vec2.z() - (cosT - sinT), 1.f};
|
||||
// inst.color = particle.x34_color;
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (m_shaderClass) {
|
||||
case CElementGenShaders::EShaderClass::Tex:
|
||||
// m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
|
||||
// CGraphics::DrawInstances(0, 4, g_instTexData.size());
|
||||
// m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
|
||||
// CGraphics::DrawInstances(0, 4, g_instTexData.size());
|
||||
break;
|
||||
case CElementGenShaders::EShaderClass::NoTex:
|
||||
// m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
|
||||
// CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
|
||||
// m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
|
||||
// CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1660,9 +1669,10 @@ void CElementGen::RenderParticlesIndirectTexture() {
|
|||
x178_localScaleTransform;
|
||||
CGraphics::SetModelMatrix(systemViewPointMatrix);
|
||||
|
||||
SParticleUniforms uniformData = {
|
||||
CGraphics::GetPerspectiveProjectionMatrix(/*true*/) * CGraphics::g_GXModelView.toMatrix4f(), {1.f, 1.f, 1.f, 1.f}};
|
||||
// m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
|
||||
// SParticleUniforms uniformData = {CGraphics::GetPerspectiveProjectionMatrix(/*true*/) *
|
||||
// CGraphics::g_GXModelView.toMatrix4f(),
|
||||
// {1.f, 1.f, 1.f, 1.f}};
|
||||
// m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
|
||||
|
||||
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
|
||||
|
||||
|
@ -1712,11 +1722,11 @@ void CElementGen::RenderParticlesIndirectTexture() {
|
|||
});
|
||||
}
|
||||
|
||||
g_instIndTexData.clear();
|
||||
g_instIndTexData.reserve(x30_particles.size());
|
||||
// g_instIndTexData.clear();
|
||||
// g_instIndTexData.reserve(x30_particles.size());
|
||||
|
||||
// if (!x30_particles.empty())
|
||||
// CGraphics::SetShaderDataBinding(m_normalDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||
// if (!x30_particles.empty())
|
||||
// CGraphics::SetShaderDataBinding(m_normalDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||
|
||||
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);
|
||||
|
@ -1764,35 +1774,35 @@ void CElementGen::RenderParticlesIndirectTexture() {
|
|||
|
||||
CGraphics::ResolveSpareTexture(clipRect);
|
||||
|
||||
SParticleInstanceIndTex& inst = g_instIndTexData.emplace_back();
|
||||
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[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.color = particle.x34_color;
|
||||
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[2] = zeus::CVector4f{uvs.xMax, uvs.yMin, uvsInd.xMax, uvsInd.yMin};
|
||||
inst.texrTindUVs[3] = zeus::CVector4f{uvs.xMin, uvs.yMin, uvsInd.xMin, uvsInd.yMin};
|
||||
// switch (CGraphics::g_BooPlatform) {
|
||||
// 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 = zeus::CVector4f{clipRect.x18_uvXMin, 1.f - clipRect.x24_uvYMax, clipRect.x1c_uvXMax,
|
||||
1.f - clipRect.x20_uvYMin};
|
||||
// break;
|
||||
// }
|
||||
// CGraphics::DrawInstances(0, 4, 1, g_instIndTexData.size() - 1);
|
||||
// SParticleInstanceIndTex& inst = g_instIndTexData.emplace_back();
|
||||
// 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[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.color = particle.x34_color;
|
||||
// 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[2] = zeus::CVector4f{uvs.xMax, uvs.yMin, uvsInd.xMax, uvsInd.yMin};
|
||||
// inst.texrTindUVs[3] = zeus::CVector4f{uvs.xMin, uvs.yMin, uvsInd.xMin, uvsInd.yMin};
|
||||
// switch (CGraphics::g_BooPlatform) {
|
||||
// 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 =
|
||||
// zeus::CVector4f{clipRect.x18_uvXMin, 1.f - clipRect.x24_uvYMax, clipRect.x1c_uvXMax, 1.f - clipRect.x20_uvYMin};
|
||||
// break;
|
||||
// }
|
||||
// CGraphics::DrawInstances(0, 4, 1, g_instIndTexData.size() - 1);
|
||||
}
|
||||
|
||||
if (g_instIndTexData.size()) {
|
||||
// m_instBuf->load(g_instIndTexData.data(), g_instIndTexData.size() * sizeof(SParticleInstanceIndTex));
|
||||
// TODO! this looks like a bug
|
||||
// if (g_instIndTexData.size()) {
|
||||
// m_instBuf->load(g_instIndTexData.data(), g_instIndTexData.size() * sizeof(SParticleInstanceIndTex));
|
||||
// TODO! this looks like a bug
|
||||
// CGraphics::SetShaderDataBinding(m_normalDataBind);
|
||||
// CGraphics::DrawInstances(0, 4, g_instIndTexData.size());
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
void CElementGen::SetOrientation(const zeus::CTransform& orientation) {
|
||||
|
|
|
@ -59,30 +59,30 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct SParticleInstanceTex {
|
||||
std::array<zeus::CVector4f, 4> pos;
|
||||
zeus::CColor color;
|
||||
std::array<zeus::CVector2f, 4> uvs;
|
||||
};
|
||||
extern std::vector<SParticleInstanceTex> g_instTexData;
|
||||
|
||||
struct SParticleInstanceIndTex {
|
||||
std::array<zeus::CVector4f, 4> pos;
|
||||
zeus::CColor color;
|
||||
std::array<zeus::CVector4f, 4> texrTindUVs;
|
||||
zeus::CVector4f sceneUVs;
|
||||
};
|
||||
extern std::vector<SParticleInstanceIndTex> g_instIndTexData;
|
||||
|
||||
struct SParticleInstanceNoTex {
|
||||
std::array<zeus::CVector4f, 4> pos;
|
||||
zeus::CColor color;
|
||||
};
|
||||
extern std::vector<SParticleInstanceNoTex> g_instNoTexData;
|
||||
|
||||
struct SParticleUniforms {
|
||||
zeus::CMatrix4f mvp;
|
||||
zeus::CColor moduColor;
|
||||
};
|
||||
//struct SParticleInstanceTex {
|
||||
// std::array<zeus::CVector4f, 4> pos;
|
||||
// zeus::CColor color;
|
||||
// std::array<zeus::CVector2f, 4> uvs;
|
||||
//};
|
||||
//extern std::vector<SParticleInstanceTex> g_instTexData;
|
||||
//
|
||||
//struct SParticleInstanceIndTex {
|
||||
// std::array<zeus::CVector4f, 4> pos;
|
||||
// zeus::CColor color;
|
||||
// std::array<zeus::CVector4f, 4> texrTindUVs;
|
||||
// zeus::CVector4f sceneUVs;
|
||||
//};
|
||||
//extern std::vector<SParticleInstanceIndTex> g_instIndTexData;
|
||||
//
|
||||
//struct SParticleInstanceNoTex {
|
||||
// std::array<zeus::CVector4f, 4> pos;
|
||||
// zeus::CColor color;
|
||||
//};
|
||||
//extern std::vector<SParticleInstanceNoTex> g_instNoTexData;
|
||||
//
|
||||
//struct SParticleUniforms {
|
||||
// zeus::CMatrix4f mvp;
|
||||
// zeus::CColor moduColor;
|
||||
//};
|
||||
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -132,11 +132,6 @@ struct Light {
|
|||
|
||||
[[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
|
||||
void bind_texture(GX::TexMapID id, metaforce::EClampMode clamp, const TextureHandle& tex, float lod) noexcept;
|
||||
void unbind_texture(GX::TexMapID id) noexcept;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "gx.hpp"
|
||||
|
||||
#include "../gpu.hpp"
|
||||
#include "Runtime/Graphics/GX.hpp"
|
||||
#include "common.hpp"
|
||||
|
||||
#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};
|
||||
}
|
||||
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 {
|
||||
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,
|
||||
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) {
|
||||
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.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 = {
|
||||
.shaderConfig = config.shaderConfig,
|
||||
.primitive = primitive,
|
||||
|
@ -601,7 +630,7 @@ GXBindGroups build_bind_groups(const ShaderInfo& info, const ShaderConfig& confi
|
|||
.uniformBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{
|
||||
.label = "GX Uniform Bind Group",
|
||||
.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(),
|
||||
}),
|
||||
.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 out;
|
||||
u32 uniformSizeKey = info.uniformSize + (config.denormalizedVertexAttributes ? 0 : 1);
|
||||
u32 uniformSizeKey = info.uniformSize + (config.hasIndexedAttributes ? 1 : 0);
|
||||
const auto uniformIt = sUniformBindGroupLayouts.find(uniformSizeKey);
|
||||
if (uniformIt != sUniformBindGroupLayouts.end()) {
|
||||
out.uniformLayout = uniformIt->second;
|
||||
|
@ -676,7 +705,7 @@ GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info, const Shader
|
|||
};
|
||||
const auto uniformLayoutDescriptor = wgpu::BindGroupLayoutDescriptor{
|
||||
.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(),
|
||||
};
|
||||
out.uniformLayout = g_device.CreateBindGroupLayout(&uniformLayoutDescriptor);
|
||||
|
|
|
@ -13,6 +13,8 @@ constexpr u32 MaxKColors = GX::MAX_KCOLOR;
|
|||
constexpr u32 MaxTexMtx = 10;
|
||||
constexpr u32 MaxPTTexMtx = 20;
|
||||
constexpr u32 MaxTexCoord = GX::MAX_TEXCOORD;
|
||||
constexpr u32 MaxVtxAttr = GX::VA_MAX_ATTR;
|
||||
constexpr u32 MaxTevSwap = GX::MAX_TEVSWAP;
|
||||
|
||||
template <typename Arg, Arg Default>
|
||||
struct TevPass {
|
||||
|
@ -40,6 +42,8 @@ struct TevStage {
|
|||
GX::TexCoordID texCoordId = GX::TEXCOORD_NULL;
|
||||
GX::TexMapID texMapId = GX::TEXMAP_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;
|
||||
};
|
||||
struct TextureBind {
|
||||
|
@ -86,6 +90,14 @@ struct FogState {
|
|||
float farZ = 0.f;
|
||||
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 {
|
||||
zeus::CMatrix4f mv;
|
||||
|
@ -111,6 +123,13 @@ struct GXState {
|
|||
std::array<TexMtxVariant, MaxTexMtx> texMtxs;
|
||||
std::array<Mat4x4<float>, MaxPTTexMtx> ptTexMtxs;
|
||||
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 depthUpdate = true;
|
||||
bool alphaUpdate = true;
|
||||
|
@ -128,12 +147,13 @@ const TextureBind& get_texture(GX::TexMapID id) noexcept;
|
|||
|
||||
struct ShaderConfig {
|
||||
GX::FogType fogType;
|
||||
std::array<GX::AttrType, MaxVtxAttr> vtxAttrs;
|
||||
std::array<TevSwap, MaxTevSwap> tevSwapTable;
|
||||
std::array<std::optional<TevStage>, MaxTevStages> tevStages;
|
||||
std::array<ColorChannelConfig, MaxColorChannels> colorChannels;
|
||||
std::array<TcgConfig, MaxTexCoord> tcgs;
|
||||
std::optional<float> alphaDiscard;
|
||||
bool denormalizedVertexAttributes = false;
|
||||
bool denormalizedHasNrm = false; // TODO this is a hack
|
||||
bool hasIndexedAttributes = false;
|
||||
bool operator==(const ShaderConfig&) const = default;
|
||||
};
|
||||
struct PipelineConfig {
|
||||
|
@ -168,8 +188,6 @@ struct ShaderInfo {
|
|||
std::bitset<MaxPTTexMtx> usesPTTexMtx;
|
||||
std::array<GX::TexGenType, MaxTexMtx> texMtxTypes;
|
||||
u32 uniformSize = 0;
|
||||
bool usesVtxColor : 1 = false;
|
||||
bool usesNormal : 1 = false;
|
||||
bool usesFog : 1 = false;
|
||||
};
|
||||
struct BindGroupRanges {
|
||||
|
@ -248,6 +266,9 @@ inline void xxh3_update(XXH3_state_t& state, const gfx::gx::TcgConfig& input) {
|
|||
}
|
||||
template <>
|
||||
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) {
|
||||
if (!item) {
|
||||
break;
|
||||
|
@ -263,9 +284,6 @@ inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input)
|
|||
if (input.alphaDiscard) {
|
||||
XXH3_64bits_update(&state, &*input.alphaDiscard, sizeof(float));
|
||||
}
|
||||
XXH3_64bits_update(&state, &input.denormalizedVertexAttributes,
|
||||
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));
|
||||
XXH3_64bits_update(&state, &input.hasIndexedAttributes, sizeof(gfx::gx::ShaderConfig::hasIndexedAttributes));
|
||||
}
|
||||
} // 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;
|
||||
#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) {
|
||||
case GX::CC_CPREV:
|
||||
return "prev.rgb";
|
||||
|
@ -48,7 +62,9 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const Tev
|
|||
unreachable();
|
||||
}
|
||||
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: {
|
||||
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();
|
||||
}
|
||||
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: {
|
||||
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;
|
||||
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: {
|
||||
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;
|
||||
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:
|
||||
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) {
|
||||
case GX::CA_APREV:
|
||||
return "prev.a";
|
||||
|
@ -202,7 +223,8 @@ static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const Tev
|
|||
unreachable();
|
||||
}
|
||||
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: {
|
||||
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;
|
||||
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: {
|
||||
switch (stage.kaSel) {
|
||||
|
@ -337,14 +360,51 @@ static std::string_view tev_scale(GX::TevScale scale) {
|
|||
}
|
||||
}
|
||||
|
||||
static std::string in_uv(u32 idx) {
|
||||
if (idx == 0) {
|
||||
return "v_packed_uvs.data[in_uv_0_4_idx[0]]";
|
||||
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 (idx < 4) {
|
||||
return fmt::format(FMT_STRING("v_uvs.data[in_uv_0_4_idx[{}]]"), idx);
|
||||
if (attr == GX::VA_POS) {
|
||||
if (type == GX::DIRECT) {
|
||||
return "in_pos";
|
||||
}
|
||||
return "v_verts.data[in_pos_nrm_idx[0]].xyz";
|
||||
}
|
||||
return fmt::format(FMT_STRING("v_uvs.data[in_uv_5_7_idx[{}]]"), idx - 4);
|
||||
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) {
|
||||
return "v_packed_uvs.data[in_uv_0_4_idx[0]]";
|
||||
}
|
||||
if (idx < 4) {
|
||||
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);
|
||||
}
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled attr {}"), attr);
|
||||
unreachable();
|
||||
}
|
||||
|
||||
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(" denormalizedVertexAttributes: {}"), config.denormalizedVertexAttributes);
|
||||
Log.report(logvisor::Info, FMT_STRING(" hasIndexedAttributes: {}"), config.hasIndexedAttributes);
|
||||
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 vtxXfrAttrs;
|
||||
size_t locIdx = 0;
|
||||
if (config.denormalizedVertexAttributes) {
|
||||
vtxInAttrs += "\n @location(0) in_pos: vec3<f32>";
|
||||
vtxOutAttrs += "\n @builtin(position) pos: vec4<f32>;";
|
||||
vtxXfrAttrsPre +=
|
||||
"\n var obj_pos = vec4<f32>(in_pos, 1.0);"
|
||||
"\n var mv_pos = ubuf.mv * obj_pos;"
|
||||
"\n out.pos = ubuf.proj * mv_pos;";
|
||||
if (config.denormalizedHasNrm) {
|
||||
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 {
|
||||
size_t vtxOutIdx = 0;
|
||||
if (config.hasIndexedAttributes) {
|
||||
// Display list attributes
|
||||
vtxInAttrs +=
|
||||
"\n @location(0) in_pos_nrm_idx: vec2<i32>"
|
||||
"\n , @location(1) in_uv_0_4_idx: vec4<i32>"
|
||||
"\n , @location(2) in_uv_5_7_idx: vec4<i32>";
|
||||
locIdx += 3;
|
||||
uniformBindings += R"""(
|
||||
struct Vec3Block {
|
||||
data: array<vec4<f32>>;
|
||||
|
@ -456,18 +507,33 @@ var<storage, read> v_uvs: Vec2Block;
|
|||
@group(0) @binding(4)
|
||||
var<storage, read> v_packed_uvs: Vec2Block;
|
||||
)""";
|
||||
vtxInAttrs +=
|
||||
"\n @location(0) in_pos_nrm_idx: vec2<i32>"
|
||||
"\n , @location(1) in_uv_0_4_idx: vec4<i32>"
|
||||
"\n , @location(2) in_uv_5_7_idx: vec4<i32>";
|
||||
vtxOutAttrs += "\n @builtin(position) pos: vec4<f32>;";
|
||||
vtxXfrAttrsPre +=
|
||||
"\n var obj_pos = vec4<f32>(v_verts.data[in_pos_nrm_idx[0]].xyz, 1.0);"
|
||||
"\n var obj_norm = vec4<f32>(v_norms.data[in_pos_nrm_idx[1]].xyz, 0.0);"
|
||||
"\n var mv_pos = ubuf.mv * obj_pos;"
|
||||
"\n var mv_norm = ubuf.mv_inv * obj_norm;"
|
||||
"\n out.pos = ubuf.proj * mv_pos;";
|
||||
}
|
||||
for (GX::Attr attr{}; attr < MaxVtxAttr; attr = GX::Attr(attr + 1)) {
|
||||
// Direct attributes
|
||||
if (config.vtxAttrs[attr] != GX::DIRECT) {
|
||||
continue;
|
||||
}
|
||||
if (locIdx > 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_norm = ubuf.mv_inv * obj_norm;"
|
||||
"\n out.pos = ubuf.proj * mv_pos;"),
|
||||
vtx_attr(config, GX::VA_POS), vtx_attr(config, GX::VA_NRM));
|
||||
|
||||
std::string fragmentFnPre;
|
||||
std::string fragmentFn;
|
||||
|
@ -478,7 +544,7 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
{
|
||||
std::string outReg;
|
||||
switch (stage->colorOp.outReg) {
|
||||
case GX::TevRegID::TEVPREV:
|
||||
case GX::TEVPREV:
|
||||
outReg = "prev";
|
||||
break;
|
||||
case GX::TEVREG0:
|
||||
|
@ -496,11 +562,13 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid colorOp outReg {}"), stage->colorOp.outReg);
|
||||
}
|
||||
std::string op = 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.c, idx, *stage, info), color_arg_reg(stage->colorPass.d, idx, *stage, info),
|
||||
tev_op(stage->colorOp.op), tev_bias(stage->colorOp.bias), tev_scale(stage->colorOp.scale));
|
||||
std::string op =
|
||||
fmt::format(FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
||||
color_arg_reg(stage->colorPass.a, idx, config, *stage, info),
|
||||
color_arg_reg(stage->colorPass.b, idx, config, *stage, info),
|
||||
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) {
|
||||
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;
|
||||
switch (stage->alphaOp.outReg) {
|
||||
case GX::TevRegID::TEVPREV:
|
||||
case GX::TEVPREV:
|
||||
outReg = "prev.a";
|
||||
break;
|
||||
case GX::TEVREG0:
|
||||
|
@ -527,11 +595,13 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid alphaOp outReg {}"), stage->alphaOp.outReg);
|
||||
}
|
||||
std::string op = 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.c, idx, *stage, info), alpha_arg_reg(stage->alphaPass.d, idx, *stage, info),
|
||||
tev_op(stage->alphaOp.op), tev_bias(stage->alphaOp.bias), tev_scale(stage->alphaOp.scale));
|
||||
std::string op =
|
||||
fmt::format(FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
||||
alpha_arg_reg(stage->alphaPass.a, idx, config, *stage, info),
|
||||
alpha_arg_reg(stage->alphaPass.b, idx, config, *stage, info),
|
||||
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) {
|
||||
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);
|
||||
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 (!addedLightStruct) {
|
||||
uniformPre +=
|
||||
|
@ -580,7 +645,7 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
uniBufAttrs += fmt::format(FMT_STRING("\n lighting_ambient{}: vec4<f32>;"), i);
|
||||
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"""(
|
||||
{{
|
||||
var lighting = ubuf.lighting_ambient{0} + ubuf.cc{0}_amb;
|
||||
|
@ -604,13 +669,9 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
i, GX::MaxLights);
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
||||
} else if (config.colorChannels[i].matSrc == GX::SRC_VTX) {
|
||||
if (config.denormalizedVertexAttributes) {
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), locIdx - 1, 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);
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("SRC_VTX unsupported with normalized vertex attributes"));
|
||||
}
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), vtxOutIdx++, i);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.cc{} = {};"), i, vtx_attr(config, GX::Attr(GX::VA_CLR0 + i)));
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
||||
} else {
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = ubuf.cc{0}_mat;"), i);
|
||||
}
|
||||
|
@ -628,23 +689,17 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
continue;
|
||||
}
|
||||
const auto& tcg = config.tcgs[i];
|
||||
if (config.denormalizedVertexAttributes) {
|
||||
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);
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2<f32>;"), vtxOutIdx++, i);
|
||||
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,
|
||||
vtx_attr(config, GX::Attr(GX::VA_TEX0 + (tcg.src - GX::TG_TEX0))));
|
||||
} else if (tcg.src == GX::TG_POS) {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4<f32>(obj_pos.xyz, 1.0);"), i);
|
||||
} else if (tcg.src == GX::TG_NRM) {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4<f32>(obj_norm.xyz, 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) {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4<f32>({}, 0.0, 1.0);"), i, in_uv(tcg.src - GX::TG_TEX0));
|
||||
} else if (tcg.src == GX::TG_POS) {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4<f32>(obj_pos.xyz, 1.0);"), i);
|
||||
} else if (tcg.src == GX::TG_NRM) {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4<f32>(obj_norm.xyz, 1.0);"), i);
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled tcg src {}"), tcg.src);
|
||||
unreachable();
|
||||
}
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled tcg src {}"), tcg.src);
|
||||
unreachable();
|
||||
}
|
||||
// TODO this all assumes MTX3x4 currently
|
||||
if (tcg.mtx == GX::IDENTITY) {
|
||||
|
@ -663,12 +718,12 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
} else {
|
||||
u32 postMtxIdx = (tcg.postMtx - GX::PTTEXMTX0) / 3;
|
||||
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);
|
||||
fragmentFnPre += fmt::format(
|
||||
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) {
|
||||
if (!info.usesTexMtx.test(i)) {
|
||||
|
@ -698,7 +753,8 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
if (config.fogType != GX::FOG_NONE) {
|
||||
info.usesFog = true;
|
||||
|
||||
uniformPre += "\n"
|
||||
uniformPre +=
|
||||
"\n"
|
||||
"struct Fog {\n"
|
||||
" color: vec4<f32>;\n"
|
||||
" a: f32;\n"
|
||||
|
@ -729,7 +785,8 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
break;
|
||||
case GX::FOG_PERSP_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);";
|
||||
break;
|
||||
default:
|
||||
|
@ -767,7 +824,8 @@ struct Uniform {{
|
|||
@group(0) @binding(0)
|
||||
var<uniform> ubuf: Uniform;{uniformBindings}{sampBindings}{texBindings}
|
||||
|
||||
struct VertexOutput {{{vtxOutAttrs}
|
||||
struct VertexOutput {{
|
||||
@builtin(position) pos: vec4<f32>;{vtxOutAttrs}
|
||||
}};
|
||||
|
||||
@stage(vertex)
|
||||
|
|
|
@ -5,47 +5,6 @@
|
|||
|
||||
#include <absl/container/flat_hash_map.h>
|
||||
#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 {
|
||||
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> 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 {
|
||||
gx::DlVert out{};
|
||||
size_t offset = 0;
|
||||
const auto read8 = [data, &offset](VtxDescAttrType type) -> s8 {
|
||||
if (type == VtxDescAttrType::Direct) {
|
||||
s8 v = static_cast<s8>(data[offset]);
|
||||
++offset;
|
||||
return v;
|
||||
const auto vtxTypes = gx::g_gxState.vtxDesc;
|
||||
const auto read8 = [/*data, &offset*/](GX::AttrType type) -> s8 {
|
||||
// if (type == GX::INDEX8) {
|
||||
// s8 v = static_cast<s8>(data[offset]);
|
||||
// ++offset;
|
||||
// return v;
|
||||
// }
|
||||
#ifndef NDEBUG
|
||||
if (type != GX::NONE) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unsupported vtx attr"));
|
||||
unreachable();
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
};
|
||||
const auto read16 = [data, &offset](VtxDescAttrType type) -> s16 {
|
||||
if (type == VtxDescAttrType::Index16) {
|
||||
const auto read16 = [data, &offset](GX::AttrType type) -> s16 {
|
||||
if (type == GX::INDEX16) {
|
||||
s16 v = metaforce::SBig(*reinterpret_cast<const u16*>(data + offset));
|
||||
offset += 2;
|
||||
return v;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::PnMatIdx));
|
||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex0MatIdx));
|
||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex1MatIdx));
|
||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex2MatIdx));
|
||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex3MatIdx));
|
||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex4MatIdx));
|
||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex5MatIdx));
|
||||
read8(sVtxDescFlags.GetDirectAttributeType(VtxDescAttr::Tex6MatIdx));
|
||||
read8(vtxTypes[GX::VA_PNMTXIDX]);
|
||||
read8(vtxTypes[GX::VA_TEX0MTXIDX]);
|
||||
read8(vtxTypes[GX::VA_TEX1MTXIDX]);
|
||||
read8(vtxTypes[GX::VA_TEX2MTXIDX]);
|
||||
read8(vtxTypes[GX::VA_TEX3MTXIDX]);
|
||||
read8(vtxTypes[GX::VA_TEX4MTXIDX]);
|
||||
read8(vtxTypes[GX::VA_TEX5MTXIDX]);
|
||||
read8(vtxTypes[GX::VA_TEX6MTXIDX]);
|
||||
|
||||
out.pos = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Position));
|
||||
out.norm = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Normal));
|
||||
read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Color0));
|
||||
read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Color1));
|
||||
out.uvs[0] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex0));
|
||||
out.uvs[1] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex1));
|
||||
out.uvs[2] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex2));
|
||||
out.uvs[3] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex3));
|
||||
out.uvs[4] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex4));
|
||||
out.uvs[5] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex5));
|
||||
out.uvs[6] = read16(sVtxDescFlags.GetAttributeType(VtxDescAttr::Tex6));
|
||||
out.pos = read16(vtxTypes[GX::VA_POS]);
|
||||
out.norm = read16(vtxTypes[GX::VA_NRM]);
|
||||
read16(vtxTypes[GX::VA_CLR0]);
|
||||
read16(vtxTypes[GX::VA_CLR1]);
|
||||
out.uvs[0] = read16(vtxTypes[GX::VA_TEX0]);
|
||||
out.uvs[1] = read16(vtxTypes[GX::VA_TEX1]);
|
||||
out.uvs[2] = read16(vtxTypes[GX::VA_TEX2]);
|
||||
out.uvs[3] = read16(vtxTypes[GX::VA_TEX3]);
|
||||
out.uvs[4] = read16(vtxTypes[GX::VA_TEX4]);
|
||||
out.uvs[5] = read16(vtxTypes[GX::VA_TEX5]);
|
||||
out.uvs[6] = read16(vtxTypes[GX::VA_TEX6]);
|
||||
|
||||
return {out, offset};
|
||||
}
|
||||
|
@ -130,7 +88,6 @@ void queue_surface(const u8* dlStart, u32 dlSize) noexcept {
|
|||
while (offset < dlSize - 6) {
|
||||
const auto header = dlStart[offset];
|
||||
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));
|
||||
offset += 3;
|
||||
|
||||
|
|
|
@ -4,71 +4,138 @@
|
|||
#include "common.hpp"
|
||||
#include "gx.hpp"
|
||||
|
||||
namespace aurora::gfx {
|
||||
static logvisor::Module Log("aurora::gfx::stream");
|
||||
|
||||
using aurora::gfx::gx::g_gxState;
|
||||
|
||||
struct SStreamState {
|
||||
GX::Primitive primitive;
|
||||
metaforce::EStreamFlags flags;
|
||||
uint32_t vertexCount = 0;
|
||||
ByteBuffer vertexBuffer;
|
||||
u16 vertexCount = 0;
|
||||
aurora::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;
|
||||
|
||||
void stream_begin(GX::Primitive primitive) noexcept {
|
||||
void GXBegin(GX::Primitive primitive, GX::VtxFmt vtxFmt, u16 nVerts) noexcept {
|
||||
#ifndef NDEBUG
|
||||
if (sStreamState) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Stream began twice!"));
|
||||
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);
|
||||
}
|
||||
|
||||
void stream_vertex(metaforce::EStreamFlags flags, const zeus::CVector3f& pos, const zeus::CVector3f& nrm,
|
||||
const zeus::CColor& color, const zeus::CVector2f& uv) noexcept {
|
||||
static inline void check_attr_order(GX::Attr attr) noexcept {
|
||||
#ifndef NDEBUG
|
||||
if (!sStreamState) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Stream not started!"));
|
||||
unreachable();
|
||||
}
|
||||
if (sStreamState->flags) {
|
||||
if (sStreamState->flags != flags) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Stream changed flags?"));
|
||||
unreachable();
|
||||
}
|
||||
} else {
|
||||
sStreamState->flags = flags;
|
||||
if (sStreamState->currentAttr >= attr) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("bad attribute order: {}, last {}"), attr, sStreamState->currentAttr);
|
||||
unreachable();
|
||||
}
|
||||
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++;
|
||||
sStreamState->currentAttr = attr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void stream_end() noexcept {
|
||||
const auto vertRange = push_verts(sStreamState->vertexBuffer.data(), sStreamState->vertexBuffer.size());
|
||||
|
||||
stream::PipelineConfig config{};
|
||||
config.shaderConfig.denormalizedVertexAttributes = true;
|
||||
config.shaderConfig.denormalizedHasNrm = sStreamState->flags.IsSet(metaforce::EStreamFlagBits::fHasNormal);
|
||||
const auto info = populate_pipeline_config(config, sStreamState->primitive, {});
|
||||
const auto pipeline = pipeline_ref(config);
|
||||
|
||||
push_draw_command(stream::DrawData{
|
||||
void GXPosition3f32(const zeus::CVector3f& pos) noexcept {
|
||||
#ifndef NDEBUG
|
||||
if (!sStreamState) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Stream not started!"));
|
||||
unreachable();
|
||||
}
|
||||
sStreamState->currentAttr = GX::VA_POS;
|
||||
#endif
|
||||
auto& state = *sStreamState;
|
||||
state.vertexBuffer.append(&pos, 12);
|
||||
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,
|
||||
.vertRange = vertRange,
|
||||
.uniformRange = build_uniform(info),
|
||||
.vertexCount = sStreamState->vertexCount,
|
||||
.indexRange = indexRange,
|
||||
.indexCount = static_cast<uint32_t>(sStreamState->indices.size()),
|
||||
.bindGroups = info.bindGroups,
|
||||
});
|
||||
|
||||
sStreamState.reset();
|
||||
}
|
||||
} // namespace aurora::gfx
|
||||
|
|
|
@ -22,7 +22,7 @@ wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] Pipeli
|
|||
};
|
||||
uint64_t offset = 12;
|
||||
uint32_t shaderLocation = 1;
|
||||
if (info.usesNormal) {
|
||||
if (config.shaderConfig.vtxAttrs[GX::VA_NRM] == GX::DIRECT) {
|
||||
attributes[shaderLocation] = wgpu::VertexAttribute{
|
||||
.format = wgpu::VertexFormat::Float32x3,
|
||||
.offset = offset,
|
||||
|
@ -31,7 +31,7 @@ wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] Pipeli
|
|||
offset += 12;
|
||||
shaderLocation++;
|
||||
}
|
||||
if (info.usesVtxColor) {
|
||||
if (config.shaderConfig.vtxAttrs[GX::VA_CLR0] == GX::DIRECT) {
|
||||
attributes[shaderLocation] = wgpu::VertexAttribute{
|
||||
.format = wgpu::VertexFormat::Float32x4,
|
||||
.offset = offset,
|
||||
|
@ -40,9 +40,8 @@ wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] Pipeli
|
|||
offset += 16;
|
||||
shaderLocation++;
|
||||
}
|
||||
// TODO only sample 1?
|
||||
for (int i = 0; i < info.sampledTextures.size(); ++i) {
|
||||
if (!info.sampledTextures.test(i)) {
|
||||
for (int i = GX::VA_TEX0; i < GX::VA_TEX7; ++i) {
|
||||
if (config.shaderConfig.vtxAttrs[i] != GX::DIRECT) {
|
||||
continue;
|
||||
}
|
||||
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.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
|
||||
|
|
|
@ -8,7 +8,8 @@ struct DrawData {
|
|||
PipelineRef pipeline;
|
||||
Range vertRange;
|
||||
Range uniformRange;
|
||||
uint32_t vertexCount;
|
||||
Range indexRange;
|
||||
uint32_t indexCount;
|
||||
gx::GXBindGroups bindGroups;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue