mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-20 10:25:40 +00:00
Accurate MP3 material processing
This commit is contained in:
@@ -79,7 +79,7 @@ void CGameArea::MergeTerrain()
|
||||
for (uint32 iSurf = 0; iSurf < SubmeshCount; iSurf++)
|
||||
{
|
||||
SSurface *pSurf = pMdl->GetSurface(iSurf);
|
||||
CMaterial *pMat = mpMaterialSet->MaterialByIndex(pSurf->MaterialID);
|
||||
CMaterial *pMat = mpMaterialSet->MaterialByIndex(pSurf->MaterialID, false);
|
||||
|
||||
bool NewMat = true;
|
||||
for (std::vector<CStaticModel*>::iterator it = mStaticWorldModels.begin(); it != mStaticWorldModels.end(); it++)
|
||||
|
||||
@@ -17,7 +17,6 @@ CMaterial::CMaterial()
|
||||
: mpShader(nullptr)
|
||||
, mShaderStatus(EShaderStatus::NoShader)
|
||||
, mRecalcHash(true)
|
||||
, mEnableBloom(false)
|
||||
, mVersion(EGame::Invalid)
|
||||
, mOptions(EMaterialOption::None)
|
||||
, mVtxDesc(EVertexAttribute::None)
|
||||
@@ -27,16 +26,16 @@ CMaterial::CMaterial()
|
||||
, mEchoesUnknownA(0)
|
||||
, mEchoesUnknownB(0)
|
||||
, mpIndirectTexture(nullptr)
|
||||
{
|
||||
}
|
||||
, mpNextDrawPassMaterial(nullptr)
|
||||
, mpBloomMaterial(nullptr)
|
||||
{}
|
||||
|
||||
CMaterial::CMaterial(EGame Version, FVertexDescription VtxDesc)
|
||||
: mpShader(nullptr)
|
||||
, mShaderStatus(EShaderStatus::NoShader)
|
||||
, mRecalcHash(true)
|
||||
, mEnableBloom(Version == EGame::Corruption)
|
||||
, mVersion(Version)
|
||||
, mOptions(EMaterialOption::DepthWrite)
|
||||
, mOptions(EMaterialOption::DepthWrite | EMaterialOption::ColorWrite)
|
||||
, mVtxDesc(VtxDesc)
|
||||
, mBlendSrcFac(GL_ONE)
|
||||
, mBlendDstFac(GL_ZERO)
|
||||
@@ -44,27 +43,18 @@ CMaterial::CMaterial(EGame Version, FVertexDescription VtxDesc)
|
||||
, mEchoesUnknownA(0)
|
||||
, mEchoesUnknownB(0)
|
||||
, mpIndirectTexture(nullptr)
|
||||
{
|
||||
mpShader = nullptr;
|
||||
mShaderStatus = EShaderStatus::NoShader;
|
||||
mRecalcHash = true;
|
||||
mEnableBloom = (Version == EGame::Corruption);
|
||||
mVersion = Version;
|
||||
mOptions = EMaterialOption::DepthWrite;
|
||||
mVtxDesc = VtxDesc;
|
||||
mBlendSrcFac = GL_ONE;
|
||||
mBlendDstFac = GL_ZERO;
|
||||
mLightingEnabled = true;
|
||||
mEchoesUnknownA = 0;
|
||||
mEchoesUnknownB = 0;
|
||||
mpIndirectTexture = nullptr;
|
||||
}
|
||||
, mpNextDrawPassMaterial(nullptr)
|
||||
, mpBloomMaterial(nullptr)
|
||||
{}
|
||||
|
||||
CMaterial::~CMaterial()
|
||||
{
|
||||
for (uint32 iPass = 0; iPass < mPasses.size(); iPass++)
|
||||
delete mPasses[iPass];
|
||||
|
||||
delete mpNextDrawPassMaterial;
|
||||
delete mpBloomMaterial;
|
||||
|
||||
ClearShader();
|
||||
}
|
||||
|
||||
@@ -72,12 +62,13 @@ CMaterial* CMaterial::Clone()
|
||||
{
|
||||
CMaterial *pOut = new CMaterial();
|
||||
pOut->mName = mName;
|
||||
pOut->mEnableBloom = mEnableBloom;
|
||||
pOut->mVersion = mVersion;
|
||||
pOut->mOptions = mOptions;
|
||||
pOut->mVtxDesc = mVtxDesc;
|
||||
for (uint32 iKonst = 0; iKonst < 4; iKonst++)
|
||||
pOut->mKonstColors[iKonst] = mKonstColors[iKonst];
|
||||
for (uint32 iTev = 0; iTev < 4; iTev++)
|
||||
pOut->mTevColors[iTev] = mTevColors[iTev];
|
||||
pOut->mBlendSrcFac = mBlendSrcFac;
|
||||
pOut->mBlendDstFac = mBlendDstFac;
|
||||
pOut->mLightingEnabled = mLightingEnabled;
|
||||
@@ -89,6 +80,12 @@ CMaterial* CMaterial::Clone()
|
||||
for (uint32 iPass = 0; iPass < mPasses.size(); iPass++)
|
||||
pOut->mPasses[iPass] = mPasses[iPass]->Clone(pOut);
|
||||
|
||||
if (mpNextDrawPassMaterial)
|
||||
pOut->mpNextDrawPassMaterial = mpNextDrawPassMaterial->Clone();
|
||||
|
||||
if (mpBloomMaterial)
|
||||
pOut->mpBloomMaterial = mpBloomMaterial->Clone();
|
||||
|
||||
return pOut;
|
||||
}
|
||||
|
||||
@@ -179,15 +176,12 @@ bool CMaterial::SetCurrent(FRenderOptions Options)
|
||||
dstRGB = mBlendDstFac;
|
||||
}
|
||||
|
||||
// Set alpha blend equation
|
||||
bool AlphaBlended = ((mBlendSrcFac == GL_SRC_ALPHA) && (mBlendDstFac == GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
if ((mEnableBloom) && (Options & ERenderOption::EnableBloom) && (!AlphaBlended)) {
|
||||
srcAlpha = mBlendSrcFac;
|
||||
dstAlpha = mBlendDstFac;
|
||||
} else {
|
||||
if (mOptions & EMaterialOption::ZeroDestAlpha) {
|
||||
srcAlpha = GL_ZERO;
|
||||
dstAlpha = GL_ZERO;
|
||||
} else {
|
||||
srcAlpha = mBlendSrcFac;
|
||||
dstAlpha = mBlendDstFac;
|
||||
}
|
||||
|
||||
glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
@@ -196,6 +190,11 @@ bool CMaterial::SetCurrent(FRenderOptions Options)
|
||||
for (uint32 iKonst = 0; iKonst < 4; iKonst++)
|
||||
CGraphics::sPixelBlock.Konst[iKonst] = mKonstColors[iKonst];
|
||||
|
||||
// Set TEV registers
|
||||
if (mVersion >= EGame::Corruption)
|
||||
for (uint32 iTev = 0; iTev < 4; iTev++)
|
||||
CGraphics::sPixelBlock.TevColor[iTev] = mTevColors[iTev];
|
||||
|
||||
// Set color channels
|
||||
// COLOR0_Amb is initialized by the node instead of by the material
|
||||
CGraphics::sVertexBlock.COLOR0_Mat = CColor::skWhite;
|
||||
@@ -204,6 +203,11 @@ bool CMaterial::SetCurrent(FRenderOptions Options)
|
||||
if ((mOptions & EMaterialOption::DepthWrite) || (Options & ERenderOption::NoAlpha)) glDepthMask(GL_TRUE);
|
||||
else glDepthMask(GL_FALSE);
|
||||
|
||||
// Set color/alpha write
|
||||
GLboolean bColorWrite = mOptions.HasFlag(EMaterialOption::ColorWrite);
|
||||
GLboolean bAlphaWrite = mOptions.HasFlag(EMaterialOption::AlphaWrite);
|
||||
glColorMask(bColorWrite, bColorWrite, bColorWrite, bAlphaWrite);
|
||||
|
||||
// Load uniforms
|
||||
for (uint32 iPass = 0; iPass < mPasses.size(); iPass++)
|
||||
mPasses[iPass]->SetAnimCurrent(Options, iPass);
|
||||
@@ -249,6 +253,7 @@ uint64 CMaterial::HashParameters()
|
||||
Hash.HashLong(mOptions);
|
||||
Hash.HashLong(mVtxDesc);
|
||||
Hash.HashData(mKonstColors, sizeof(CColor) * 4);
|
||||
Hash.HashData(mTevColors, sizeof(CColor) * 4);
|
||||
Hash.HashLong(mBlendSrcFac);
|
||||
Hash.HashLong(mBlendDstFac);
|
||||
Hash.HashByte(mLightingEnabled);
|
||||
|
||||
@@ -31,10 +31,32 @@ enum class EMaterialOption
|
||||
Lightmap = 0x800,
|
||||
ShortTexCoord = 0x2000,
|
||||
AllMP1Settings = 0x2FF8,
|
||||
ColorWrite = 0x10000,
|
||||
AlphaWrite = 0x20000,
|
||||
ZeroDestAlpha = 0x40000,
|
||||
DrawWhiteAmbientDKCR = 0x80000
|
||||
};
|
||||
DECLARE_FLAGS_ENUMCLASS(EMaterialOption, FMaterialOptions)
|
||||
|
||||
enum class EMP3MaterialOption
|
||||
{
|
||||
None = 0,
|
||||
Bloom = 0x1,
|
||||
ForceLightingStage = 0x4,
|
||||
PreIncandecenceTransparency = 0x8,
|
||||
Masked = 0x10,
|
||||
AdditiveIncandecence = 0x20,
|
||||
Occluder = 0x100,
|
||||
SolidWhiteOnly = 0x200,
|
||||
ReflectionAlphaTarget = 0x400,
|
||||
SolidColorOnly = 0x800,
|
||||
ExcludeFromScanVisor = 0x4000,
|
||||
XRayOpaque = 0x8000,
|
||||
XRayAlphaTarget = 0x10000,
|
||||
DrawWhiteAmbientDKCR = 0x80000,
|
||||
};
|
||||
DECLARE_FLAGS_ENUMCLASS(EMP3MaterialOption, FMP3MaterialOptions)
|
||||
|
||||
class CMaterial
|
||||
{
|
||||
friend class CMaterialLoader;
|
||||
@@ -57,12 +79,12 @@ private:
|
||||
EShaderStatus mShaderStatus; // A status variable so that PWE won't crash if a shader fails to compile.
|
||||
uint64 mParametersHash; // A hash of all the parameters that can identify this TEV setup.
|
||||
bool mRecalcHash; // Indicates the hash needs to be recalculated. Set true when parameters are changed.
|
||||
bool mEnableBloom; // Bool that toggles bloom on or off. On by default on MP3 materials, off by default on MP1 materials.
|
||||
|
||||
EGame mVersion;
|
||||
FMaterialOptions mOptions; // See the EMaterialOptions enum above
|
||||
FMaterialOptions mOptions; // See the EMaterialOption enum above
|
||||
FVertexDescription mVtxDesc; // Descriptor of vertex attributes used by this material
|
||||
CColor mKonstColors[4]; // Konst color values for TEV
|
||||
CColor mTevColors[4]; // Initial TEV color register values (for MP3 materials only)
|
||||
GLenum mBlendSrcFac; // Source blend factor
|
||||
GLenum mBlendDstFac; // Dest blend factor
|
||||
bool mLightingEnabled; // Color channel control flags; indicate whether lighting is enabled
|
||||
@@ -72,6 +94,16 @@ private:
|
||||
|
||||
std::vector<CMaterialPass*> mPasses;
|
||||
|
||||
// Transparent materials in MP3/DKCR may require multiple draw passes to achieve hybrid
|
||||
// blending modes. This serves as a linked list of materials to be drawn successively
|
||||
// for each surface.
|
||||
CMaterial* mpNextDrawPassMaterial;
|
||||
|
||||
// Bloom in MP3 changes the CMaterialPass layout significantly. This is an alternate
|
||||
// material head that may be conditionally used when the user wants to view bloom.
|
||||
// (only set in the head non-bloom CMaterial).
|
||||
CMaterial* mpBloomMaterial;
|
||||
|
||||
// Reuse shaders between materials that have identical TEV setups
|
||||
struct SMaterialShader
|
||||
{
|
||||
@@ -101,18 +133,22 @@ public:
|
||||
inline GLenum BlendSrcFac() const { return mBlendSrcFac; }
|
||||
inline GLenum BlendDstFac() const { return mBlendDstFac; }
|
||||
inline CColor Konst(uint32 KIndex) const { return mKonstColors[KIndex]; }
|
||||
inline CColor TevColor(ETevOutput Out) const { return mTevColors[int(Out)]; }
|
||||
inline CTexture* IndTexture() const { return mpIndirectTexture; }
|
||||
inline bool IsLightingEnabled() const { return mLightingEnabled; }
|
||||
inline uint32 EchoesUnknownA() const { return mEchoesUnknownA; }
|
||||
inline uint32 EchoesUnknownB() const { return mEchoesUnknownB; }
|
||||
inline uint32 PassCount() const { return mPasses.size(); }
|
||||
inline CMaterialPass* Pass(uint32 PassIndex) const { return mPasses[PassIndex]; }
|
||||
inline CMaterial* GetNextDrawPass() const { return mpNextDrawPassMaterial; }
|
||||
inline CMaterial* GetBloomVersion() const { return mpBloomMaterial; }
|
||||
|
||||
inline void SetName(const TString& rkName) { mName = rkName; }
|
||||
inline void SetOptions(FMaterialOptions Options) { mOptions = Options; Update(); }
|
||||
inline void SetVertexDescription(FVertexDescription Desc) { mVtxDesc = Desc; Update(); }
|
||||
inline void SetBlendMode(GLenum SrcFac, GLenum DstFac) { mBlendSrcFac = SrcFac; mBlendDstFac = DstFac; mRecalcHash = true; }
|
||||
inline void SetKonst(const CColor& Konst, uint32 KIndex) { mKonstColors[KIndex] = Konst; Update(); }
|
||||
inline void SetTevColor(const CColor& Color, ETevOutput Out) { mTevColors[int(Out)] = Color; }
|
||||
inline void SetIndTexture(CTexture *pTex) { mpIndirectTexture = pTex; }
|
||||
inline void SetLightingEnabled(bool Enabled) { mLightingEnabled = Enabled; Update(); }
|
||||
|
||||
|
||||
@@ -14,8 +14,11 @@ CMaterialPass::CMaterialPass(CMaterial *pParent)
|
||||
, mKColorSel(kKonstOne)
|
||||
, mKAlphaSel(kKonstOne)
|
||||
, mRasSel(kRasColorNull)
|
||||
, mTevColorScale(1.f)
|
||||
, mTevAlphaScale(1.f)
|
||||
, mTexCoordSource(0xFF)
|
||||
, mAnimMode(EUVAnimMode::NoUVAnim)
|
||||
, mTexSwapComps{'r', 'g', 'b', 'a'}
|
||||
{
|
||||
for (uint32 iParam = 0; iParam < 4; iParam++)
|
||||
{
|
||||
@@ -46,13 +49,18 @@ CMaterialPass* CMaterialPass::Clone(CMaterial *pParent)
|
||||
pOut->mKColorSel = mKColorSel;
|
||||
pOut->mKAlphaSel = mKAlphaSel;
|
||||
pOut->mRasSel = mRasSel;
|
||||
pOut->mTevColorScale = mTevColorScale;
|
||||
pOut->mTevAlphaScale = mTevAlphaScale;
|
||||
pOut->mTexCoordSource = mTexCoordSource;
|
||||
pOut->mpTexture = mpTexture;
|
||||
pOut->mAnimMode = mAnimMode;
|
||||
|
||||
for (uint32 iParam = 0; iParam < 4; iParam++)
|
||||
for (uint32 iParam = 0; iParam < 8; iParam++)
|
||||
pOut->mAnimParams[iParam] = mAnimParams[iParam];
|
||||
|
||||
for (uint32 iComp = 0; iComp < 4; iComp++)
|
||||
pOut->mTexSwapComps[iComp] = mTexSwapComps[iComp];
|
||||
|
||||
pOut->mEnabled = mEnabled;
|
||||
|
||||
return pOut;
|
||||
@@ -71,9 +79,12 @@ void CMaterialPass::HashParameters(CFNV1A& rHash)
|
||||
rHash.HashLong(mKColorSel);
|
||||
rHash.HashLong(mKAlphaSel);
|
||||
rHash.HashLong(mRasSel);
|
||||
rHash.HashLong(mTevColorScale);
|
||||
rHash.HashLong(mTevAlphaScale);
|
||||
rHash.HashLong(mTexCoordSource);
|
||||
rHash.HashLong((uint) mAnimMode);
|
||||
rHash.HashData(mAnimParams, sizeof(float) * 4);
|
||||
rHash.HashData(mAnimParams, sizeof(float) * 8);
|
||||
rHash.HashData(mTexSwapComps, sizeof(char) * 4);
|
||||
rHash.HashByte(mEnabled);
|
||||
}
|
||||
}
|
||||
@@ -295,6 +306,18 @@ void CMaterialPass::SetRasSel(ETevRasSel Sel)
|
||||
mpParentMat->Update();
|
||||
}
|
||||
|
||||
void CMaterialPass::SetTevColorScale(float Scale)
|
||||
{
|
||||
mTevColorScale = Scale;
|
||||
mpParentMat->Update();
|
||||
}
|
||||
|
||||
void CMaterialPass::SetTevAlphaScale(float Scale)
|
||||
{
|
||||
mTevAlphaScale = Scale;
|
||||
mpParentMat->Update();
|
||||
}
|
||||
|
||||
void CMaterialPass::SetTexCoordSource(uint32 Source)
|
||||
{
|
||||
mTexCoordSource = Source;
|
||||
@@ -317,6 +340,11 @@ void CMaterialPass::SetAnimParam(uint32 ParamIndex, float Value)
|
||||
mAnimParams[ParamIndex] = Value;
|
||||
}
|
||||
|
||||
void CMaterialPass::SetTexSwapComp(uint32 Comp, char Value)
|
||||
{
|
||||
mTexSwapComps[Comp] = Value;
|
||||
}
|
||||
|
||||
void CMaterialPass::SetEnabled(bool Enabled)
|
||||
{
|
||||
mEnabled = Enabled;
|
||||
|
||||
@@ -12,9 +12,10 @@ class CMaterial;
|
||||
|
||||
enum class EPassSettings
|
||||
{
|
||||
None = 0x0,
|
||||
EmissiveBloom = 0x4,
|
||||
InvertOpacityMap = 0x10
|
||||
None = 0x0,
|
||||
BloomContribution = 0x4,
|
||||
ModulateIncandecenceMap = 0x8,
|
||||
InvertOpacityMap = 0x10
|
||||
};
|
||||
DECLARE_FLAGS_ENUMCLASS(EPassSettings, FPassSettings)
|
||||
|
||||
@@ -34,11 +35,14 @@ class CMaterialPass
|
||||
ETevKSel mKColorSel;
|
||||
ETevKSel mKAlphaSel;
|
||||
ETevRasSel mRasSel;
|
||||
float mTevColorScale;
|
||||
float mTevAlphaScale;
|
||||
uint32 mTexCoordSource; // Should maybe be an enum but worried about conflicts with EVertexDescriptionn
|
||||
TResPtr<CTexture> mpTexture;
|
||||
EUVAnimMode mAnimMode;
|
||||
EUVConvolutedModeBType mAnimConvolutedModeBType;
|
||||
float mAnimParams[8];
|
||||
char mTexSwapComps[4];
|
||||
bool mEnabled;
|
||||
|
||||
public:
|
||||
@@ -58,10 +62,13 @@ public:
|
||||
void SetKColorSel(ETevKSel Sel);
|
||||
void SetKAlphaSel(ETevKSel Sel);
|
||||
void SetRasSel(ETevRasSel Sel);
|
||||
void SetTevColorScale(float Scale);
|
||||
void SetTevAlphaScale(float Scale);
|
||||
void SetTexCoordSource(uint32 Source);
|
||||
void SetTexture(CTexture *pTex);
|
||||
void SetAnimMode(EUVAnimMode Mode);
|
||||
void SetAnimParam(uint32 ParamIndex, float Value);
|
||||
void SetTexSwapComp(uint32 Comp, char Value);
|
||||
void SetEnabled(bool Enabled);
|
||||
|
||||
// Getters
|
||||
@@ -74,10 +81,13 @@ public:
|
||||
inline ETevKSel KColorSel() const { return mKColorSel; }
|
||||
inline ETevKSel KAlphaSel() const { return mKAlphaSel; }
|
||||
inline ETevRasSel RasSel() const { return mRasSel; }
|
||||
inline float TevColorScale() const { return mTevColorScale; }
|
||||
inline float TevAlphaScale() const { return mTevAlphaScale; }
|
||||
inline uint32 TexCoordSource() const { return mTexCoordSource; }
|
||||
inline CTexture* Texture() const { return mpTexture; }
|
||||
inline EUVAnimMode AnimMode() const { return mAnimMode; }
|
||||
inline float AnimParam(uint32 ParamIndex) const { return mAnimParams[ParamIndex]; }
|
||||
inline char TexSwapComp(uint32 Comp) const { return mTexSwapComps[Comp]; }
|
||||
inline bool IsEnabled() const { return mEnabled; }
|
||||
|
||||
// Static
|
||||
|
||||
@@ -38,10 +38,13 @@ public:
|
||||
return mMaterials.size();
|
||||
}
|
||||
|
||||
CMaterial* MaterialByIndex(uint32 Index)
|
||||
CMaterial* MaterialByIndex(uint32 Index, bool TryBloom)
|
||||
{
|
||||
if (Index >= NumMaterials()) return nullptr;
|
||||
return mMaterials[Index];
|
||||
CMaterial* Ret = mMaterials[Index];
|
||||
if (TryBloom && Ret->GetBloomVersion())
|
||||
return Ret->GetBloomVersion();
|
||||
return Ret;
|
||||
}
|
||||
|
||||
CMaterial* MaterialByName(const TString& rkName)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef ETEVENUMS
|
||||
#define ETEVENUMS
|
||||
|
||||
#include <Common/BasicTypes.h>
|
||||
|
||||
enum ETevColorInput
|
||||
{
|
||||
kPrevRGB = 0x0,
|
||||
@@ -103,6 +105,20 @@ enum class EUVAnimMode
|
||||
NoUVAnim = -1
|
||||
};
|
||||
|
||||
enum class EUVAnimUVSource : uint16
|
||||
{
|
||||
Position,
|
||||
Normal,
|
||||
UV
|
||||
};
|
||||
enum class EUVAnimMatrixConfig : uint16
|
||||
{
|
||||
NoMtxNoPost,
|
||||
MtxNoPost,
|
||||
NoMtxPost,
|
||||
MtxPost
|
||||
};
|
||||
|
||||
enum class EUVConvolutedModeBType {
|
||||
Zero,
|
||||
One,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,105 @@
|
||||
#include <Common/FileIO.h>
|
||||
#include <assimp/scene.h>
|
||||
|
||||
enum class EMP3RenderConfig {
|
||||
NoBloomTransparent,
|
||||
NoBloomAdditiveIncandecence,
|
||||
FullRenderOpaque,
|
||||
OptimizedDiffuseLightingColorOpaque,
|
||||
OptimizedDiffuseBloomLightingColorOpaque,
|
||||
AdditiveIncandecenceOnly,
|
||||
AdditiveBlendPremultiplyModColor,
|
||||
FullRenderTransparent,
|
||||
FullRenderTransparentAdditiveIncandecence,
|
||||
MaterialAlphaCompare,
|
||||
SolidWhite,
|
||||
SolidKColor,
|
||||
StaticAlphaCompare,
|
||||
DynamicAlphaCompare,
|
||||
RandomStaticAlpha,
|
||||
SolidKColorKAlpha,
|
||||
XRayAdditiveIncandecence,
|
||||
XRayTransparent,
|
||||
XRayOpaque
|
||||
};
|
||||
|
||||
enum class EPASS {
|
||||
DIFF,
|
||||
RIML,
|
||||
BLOL,
|
||||
CLR,
|
||||
TRAN,
|
||||
INCA,
|
||||
RFLV,
|
||||
RFLD,
|
||||
LRLD,
|
||||
LURD,
|
||||
BLOD,
|
||||
BLOI,
|
||||
XRAY,
|
||||
TOON
|
||||
};
|
||||
|
||||
enum class EINT {
|
||||
OPAC,
|
||||
BLOD,
|
||||
BLOI,
|
||||
BNIF,
|
||||
XRBR
|
||||
};
|
||||
|
||||
enum class ECLR {
|
||||
CLR,
|
||||
DIFB
|
||||
};
|
||||
|
||||
// Material PASSes do not directly map as individual TEV stages (CMaterialPass).
|
||||
// Therefore, the material data chunks are stored in a random-access-friendly
|
||||
// container for procedural TEV stage generation.
|
||||
struct SMP3IntermediateMaterial
|
||||
{
|
||||
FMP3MaterialOptions mOptions;
|
||||
|
||||
struct PASS
|
||||
{
|
||||
CFourCC mPassType;
|
||||
TResPtr<CTexture> mpTexture = nullptr;
|
||||
FPassSettings mSettings;
|
||||
uint32 mUvSrc;
|
||||
EUVAnimUVSource mUvSource = EUVAnimUVSource::UV;
|
||||
EUVAnimMatrixConfig mMtxConfig = EUVAnimMatrixConfig::NoMtxNoPost;
|
||||
EUVAnimMode mAnimMode = EUVAnimMode::NoUVAnim;
|
||||
EUVConvolutedModeBType mAnimConvolutedModeBType;
|
||||
float mAnimParams[8];
|
||||
|
||||
char GetSwapAlphaComp() const
|
||||
{
|
||||
switch (mSettings.ToInt32() & 0x3)
|
||||
{
|
||||
case 0: return 'r';
|
||||
case 1: return 'g';
|
||||
case 2: return 'b';
|
||||
default: return 'a';
|
||||
}
|
||||
}
|
||||
};
|
||||
std::optional<PASS> mPASSes[14];
|
||||
const std::optional<PASS>& GetPASS(EPASS pass) const { return mPASSes[int(pass)]; }
|
||||
|
||||
uint8 mINTs[5] = {255, 255, 0, 32, 255};
|
||||
uint8 GetINT(EINT eint) const { return mINTs[int(eint)]; }
|
||||
|
||||
CColor mCLRs[2] = {CColor::skWhite, CColor::skWhite};
|
||||
const CColor& GetCLR(ECLR clr) const { return mCLRs[int(clr)]; }
|
||||
};
|
||||
|
||||
struct STevTracker
|
||||
{
|
||||
uint8 mCurKColor = 0;
|
||||
bool mStaticDiffuseLightingAlphaSet = false;
|
||||
bool mStaticLightingAlphaSet = false;
|
||||
};
|
||||
|
||||
class CMaterialLoader
|
||||
{
|
||||
// Material data
|
||||
@@ -15,13 +114,10 @@ class CMaterialLoader
|
||||
IInputStream *mpFile;
|
||||
EGame mVersion;
|
||||
std::vector<TResPtr<CTexture>> mTextures;
|
||||
bool mHasOPAC;
|
||||
bool mHas0x400;
|
||||
|
||||
CColor mCorruptionColors[4];
|
||||
uint8 mCorruptionInts[5];
|
||||
uint32 mCorruptionFlags;
|
||||
std::vector<uint32> mPassOffsets;
|
||||
|
||||
CMaterialLoader();
|
||||
~CMaterialLoader();
|
||||
@@ -33,7 +129,59 @@ class CMaterialLoader
|
||||
|
||||
void ReadCorruptionMatSet();
|
||||
CMaterial* ReadCorruptionMaterial();
|
||||
void CreateCorruptionPasses(CMaterial *pMat);
|
||||
void SetMP3IntermediateIntoMaterialPass(CMaterialPass* pPass, const SMP3IntermediateMaterial::PASS& Intermediate);
|
||||
void SelectBestCombinerConfig(EMP3RenderConfig& OutConfig, uint8& OutAlpha,
|
||||
const SMP3IntermediateMaterial& Material, bool Bloom);
|
||||
|
||||
bool SetupStaticDiffuseLightingStage(STevTracker& Tracker, CMaterial* pMat,
|
||||
const SMP3IntermediateMaterial& Intermediate, bool FullAlpha);
|
||||
void SetupStaticDiffuseLightingNoBloomStage(STevTracker& Tracker, CMaterial* pMat,
|
||||
const SMP3IntermediateMaterial& Intermediate);
|
||||
void SetupStaticDiffuseLightingNoBLOLStage(STevTracker& Tracker, CMaterial* pMat,
|
||||
const SMP3IntermediateMaterial& Intermediate);
|
||||
void SetupColorTextureStage(STevTracker& Tracker, CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate,
|
||||
bool useStageAlpha, uint8 Alpha, bool StaticLighting);
|
||||
void SetupColorTextureAlwaysStaticLightingStage(STevTracker& Tracker, CMaterial* pMat,
|
||||
const SMP3IntermediateMaterial& Intermediate);
|
||||
void SetupColorKColorStage(STevTracker& Tracker, CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate,
|
||||
bool useStageAlpha, uint8 Alpha, bool StaticLighting);
|
||||
bool SetupTransparencyStage(STevTracker& Tracker, CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate);
|
||||
void SetupTransparencyKAlphaMultiplyStage(STevTracker& Tracker, CMaterial* pMat,
|
||||
const SMP3IntermediateMaterial& Intermediate, bool multiplyPrevAlpha,
|
||||
uint8 Alpha);
|
||||
bool SetupReflectionAlphaStage(STevTracker& Tracker, CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate);
|
||||
bool SetupReflectionStages(STevTracker& Tracker, CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate,
|
||||
ETevColorInput argD, bool StaticLighting);
|
||||
bool SetupQuantizedKAlphaAdd(STevTracker& Tracker, CMaterial* pMat, uint8 Value);
|
||||
bool SetupIncandecenceStage(STevTracker& Tracker, CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate);
|
||||
bool SetupIncandecenceStageNoBloom(STevTracker& Tracker, CMaterial* pMat,
|
||||
const SMP3IntermediateMaterial& Intermediate);
|
||||
bool SetupStartingIncandecenceStage(STevTracker& Tracker, CMaterial* pMat,
|
||||
const SMP3IntermediateMaterial& Intermediate);
|
||||
void SetupStartingIncandecenceDynamicKColorStage(STevTracker& Tracker, CMaterial* pMat,
|
||||
const SMP3IntermediateMaterial& Intermediate);
|
||||
bool SetupStaticBloomLightingStage(STevTracker& Tracker, CMaterial* pMat,
|
||||
const SMP3IntermediateMaterial& Intermediate, bool StaticLighting);
|
||||
bool SetupStaticBloomLightingA1Stages(STevTracker& Tracker, CMaterial* pMat,
|
||||
const SMP3IntermediateMaterial& Intermediate);
|
||||
bool SetupStaticBloomDiffuseLightingStages(STevTracker& Tracker, CMaterial* pMat,
|
||||
const SMP3IntermediateMaterial& Intermediate, bool StaticLighting);
|
||||
bool SetupStaticBloomIncandecenceLightingStage(STevTracker& Tracker, CMaterial* pMat,
|
||||
const SMP3IntermediateMaterial& Intermediate);
|
||||
void SetupNoBloomTransparent(CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate, uint8 Alpha);
|
||||
void SetupNoBloomAdditiveIncandecence(CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate, uint8 Alpha);
|
||||
void SetupFullRenderOpaque(CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate);
|
||||
void SetupOptimizedDiffuseLightingColorOpaque(CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate);
|
||||
void SetupOptimizedDiffuseBloomLightingColorOpaque(CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate);
|
||||
void SetupAdditiveIncandecenceOnly(CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate);
|
||||
void SetupFullRenderTransparent(CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate, uint8 Alpha);
|
||||
void SetupFullRenderTransparentAdditiveIncandecence(CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate,
|
||||
uint8 Alpha);
|
||||
void SetupMaterialAlphaCompare(CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate);
|
||||
void SetupSolidWhite(CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate);
|
||||
void SetupSolidKColorKAlpha(CMaterial* pMat, const SMP3IntermediateMaterial& Intermediate);
|
||||
|
||||
void CreateCorruptionPasses(CMaterial *pMat, const SMP3IntermediateMaterial& Intermediate, bool Bloom);
|
||||
|
||||
CMaterial* LoadAssimpMaterial(const aiMaterial *pAiMat);
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ SSurface* CModelLoader::LoadSurface(IInputStream& rModel)
|
||||
LoadSurfaceHeaderDKCR(rModel, pSurf);
|
||||
|
||||
bool HasAABB = (pSurf->AABox != CAABox::skInfinite);
|
||||
CMaterial *pMat = mMaterials[0]->MaterialByIndex(pSurf->MaterialID);
|
||||
CMaterial *pMat = mMaterials[0]->MaterialByIndex(pSurf->MaterialID, false);
|
||||
|
||||
// Primitive table
|
||||
uint8 Flag = rModel.ReadByte();
|
||||
@@ -282,7 +282,7 @@ void CModelLoader::LoadSurfaceHeaderDKCR(IInputStream& rModel, SSurface *pSurf)
|
||||
SSurface* CModelLoader::LoadAssimpMesh(const aiMesh *pkMesh, CMaterialSet *pSet)
|
||||
{
|
||||
// Create vertex description and assign it to material
|
||||
CMaterial *pMat = pSet->MaterialByIndex(pkMesh->mMaterialIndex);
|
||||
CMaterial *pMat = pSet->MaterialByIndex(pkMesh->mMaterialIndex, false);
|
||||
FVertexDescription Desc = pMat->VtxDesc();
|
||||
|
||||
if (Desc == (FVertexDescription) EVertexAttribute::None)
|
||||
|
||||
@@ -108,8 +108,8 @@ void CModel::GenerateMaterialShaders()
|
||||
|
||||
for (uint32 iMat = 0; iMat < pSet->NumMaterials(); iMat++)
|
||||
{
|
||||
CMaterial *pMat = pSet->MaterialByIndex(iMat);
|
||||
pMat->GenerateShader(false);
|
||||
pSet->MaterialByIndex(iMat, false)->GenerateShader(false);
|
||||
pSet->MaterialByIndex(iMat, true)->GenerateShader(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,29 +136,40 @@ void CModel::DrawSurface(FRenderOptions Options, uint32 Surface, uint32 MatSet)
|
||||
if (MatSet >= mMaterialSets.size())
|
||||
MatSet = mMaterialSets.size() - 1;
|
||||
|
||||
auto DoDraw = [this, Surface]()
|
||||
{
|
||||
// Draw IBOs
|
||||
mVBO.Bind();
|
||||
glLineWidth(1.f);
|
||||
|
||||
for (uint32 iIBO = 0; iIBO < mSurfaceIndexBuffers[Surface].size(); iIBO++)
|
||||
{
|
||||
CIndexBuffer *pIBO = &mSurfaceIndexBuffers[Surface][iIBO];
|
||||
pIBO->DrawElements();
|
||||
}
|
||||
|
||||
mVBO.Unbind();
|
||||
};
|
||||
|
||||
// Bind material
|
||||
if ((Options & ERenderOption::NoMaterialSetup) == 0)
|
||||
{
|
||||
SSurface *pSurf = mSurfaces[Surface];
|
||||
CMaterial *pMat = mMaterialSets[MatSet]->MaterialByIndex(pSurf->MaterialID);
|
||||
CMaterial *pMat = mMaterialSets[MatSet]->MaterialByIndex(pSurf->MaterialID, Options.HasFlag(ERenderOption::EnableBloom));
|
||||
|
||||
if (!Options.HasFlag(ERenderOption::EnableOccluders) && pMat->Options().HasFlag(EMaterialOption::Occluder))
|
||||
return;
|
||||
|
||||
pMat->SetCurrent(Options);
|
||||
for (CMaterial* passMat = pMat; passMat; passMat = passMat->GetNextDrawPass())
|
||||
{
|
||||
passMat->SetCurrent(Options);
|
||||
DoDraw();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw IBOs
|
||||
mVBO.Bind();
|
||||
glLineWidth(1.f);
|
||||
|
||||
for (uint32 iIBO = 0; iIBO < mSurfaceIndexBuffers[Surface].size(); iIBO++)
|
||||
else
|
||||
{
|
||||
CIndexBuffer *pIBO = &mSurfaceIndexBuffers[Surface][iIBO];
|
||||
pIBO->DrawElements();
|
||||
DoDraw();
|
||||
}
|
||||
|
||||
mVBO.Unbind();
|
||||
}
|
||||
|
||||
void CModel::DrawWireframe(FRenderOptions Options, CColor WireColor /*= CColor::skWhite*/)
|
||||
@@ -206,19 +217,22 @@ void CModel::SetSkin(CSkin *pSkin)
|
||||
|
||||
for (uint32 iMat = 0; iMat < pSet->NumMaterials(); iMat++)
|
||||
{
|
||||
CMaterial *pMat = pSet->MaterialByIndex(iMat);
|
||||
FVertexDescription VtxDesc = pMat->VtxDesc();
|
||||
|
||||
if (pSkin && !VtxDesc.HasAllFlags(kBoneFlags))
|
||||
for (bool iBloom = false; !iBloom; iBloom = true)
|
||||
{
|
||||
VtxDesc |= kBoneFlags;
|
||||
pMat->SetVertexDescription(VtxDesc);
|
||||
}
|
||||
CMaterial *pMat = pSet->MaterialByIndex(iMat, iBloom);
|
||||
FVertexDescription VtxDesc = pMat->VtxDesc();
|
||||
|
||||
else if (!pSkin && VtxDesc.HasAnyFlags(kBoneFlags))
|
||||
{
|
||||
VtxDesc &= ~kBoneFlags;
|
||||
pMat->SetVertexDescription(VtxDesc);
|
||||
if (pSkin && !VtxDesc.HasAllFlags(kBoneFlags))
|
||||
{
|
||||
VtxDesc |= kBoneFlags;
|
||||
pMat->SetVertexDescription(VtxDesc);
|
||||
}
|
||||
|
||||
else if (!pSkin && VtxDesc.HasAnyFlags(kBoneFlags))
|
||||
{
|
||||
VtxDesc &= ~kBoneFlags;
|
||||
pMat->SetVertexDescription(VtxDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,7 +263,7 @@ CMaterial* CModel::GetMaterialByIndex(uint32 MatSet, uint32 Index)
|
||||
if (GetMatCount() == 0)
|
||||
return nullptr;
|
||||
|
||||
return mMaterialSets[MatSet]->MaterialByIndex(Index);
|
||||
return mMaterialSets[MatSet]->MaterialByIndex(Index, false);
|
||||
}
|
||||
|
||||
CMaterial* CModel::GetMaterialBySurface(uint32 MatSet, uint32 Surface)
|
||||
@@ -263,7 +277,7 @@ bool CModel::HasTransparency(uint32 MatSet)
|
||||
MatSet = mMaterialSets.size() - 1;
|
||||
|
||||
for (uint32 iMat = 0; iMat < mMaterialSets[MatSet]->NumMaterials(); iMat++)
|
||||
if (mMaterialSets[MatSet]->MaterialByIndex(iMat)->Options() & EMaterialOption::Transparent ) return true;
|
||||
if (mMaterialSets[MatSet]->MaterialByIndex(iMat, true)->Options() & EMaterialOption::Transparent ) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -274,7 +288,7 @@ bool CModel::IsSurfaceTransparent(uint32 Surface, uint32 MatSet)
|
||||
MatSet = mMaterialSets.size() - 1;
|
||||
|
||||
uint32 matID = mSurfaces[Surface]->MaterialID;
|
||||
return (mMaterialSets[MatSet]->MaterialByIndex(matID)->Options() & EMaterialOption::Transparent) != 0;
|
||||
return (mMaterialSets[MatSet]->MaterialByIndex(matID, true)->Options() & EMaterialOption::Transparent) != 0;
|
||||
}
|
||||
|
||||
bool CModel::IsLightmapped() const
|
||||
@@ -285,7 +299,7 @@ bool CModel::IsLightmapped() const
|
||||
|
||||
for (uint32 iMat = 0; iMat < pSet->NumMaterials(); iMat++)
|
||||
{
|
||||
CMaterial *pMat = pSet->MaterialByIndex(iMat);
|
||||
CMaterial *pMat = pSet->MaterialByIndex(iMat, true);
|
||||
if (pMat->Options().HasFlag(EMaterialOption::Lightmap))
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user