mirror of
https://github.com/rrika/cdcEngineDXHR.git
synced 2024-11-23 05:29:57 +00:00
749 lines
24 KiB
C++
749 lines
24 KiB
C++
#include "PCDX11DeviceManager.h"
|
|
#include "PCDX11Material.h"
|
|
#include "PCDX11RenderDevice.h"
|
|
#include "PCDX11StateManager.h"
|
|
#include "PCDX11StreamDecl.h" // for CommonStreamDecl to PCDX11StreamDecl cast
|
|
#include "MaterialData.h"
|
|
#include "RenderMesh.h"
|
|
#include "surfaces/PCDX11Texture.h"
|
|
#include "buffers/PCDX11UberConstantBuffer.h"
|
|
|
|
namespace cdc {
|
|
|
|
|
|
uint32_t PCDX11Material::mg_state = 0;
|
|
uint32_t PCDX11Material::mg_vsSelectAndFlags;
|
|
PCDX11StreamDecl *PCDX11Material::mg_streamDecl;
|
|
VertexDecl *PCDX11Material::mg_layoutA;
|
|
PCDX11Material *PCDX11Material::mg_material;
|
|
void *PCDX11Material::mg_cbdata;
|
|
MaterialInstanceData *PCDX11Material::mg_matInstance;
|
|
bool PCDX11Material::mg_tesselate;
|
|
|
|
void PCDX11Material::FreeData() {
|
|
// if (materialBlob != ...)
|
|
// renderDevice->Free124(materialBlob);
|
|
delete[] materialBlob; // allocation happens in MaterialSection
|
|
|
|
for (uint32_t i = 0; i < 16; i++) {
|
|
delete constantBuffersPs[i];
|
|
delete constantBuffersVs[i];
|
|
}
|
|
}
|
|
|
|
void PCDX11Material::load(MaterialBlob *newBlob) {
|
|
auto deviceContext = renderDevice->getD3DDeviceContext(); // HACK
|
|
// TODO
|
|
materialBlob = newBlob;
|
|
// TODO
|
|
SetRenderPasses();
|
|
// TODO
|
|
for (uint32_t i = 0; i < 16; i++) {
|
|
MaterialBlobSub *sub = materialBlob->subMat4C[i];
|
|
|
|
if (!sub) continue;
|
|
if (!sub->shaderPixel && !sub->shaderVertex) continue;
|
|
|
|
// TODO: textures
|
|
if (sub->psBufferSize) {
|
|
auto buffer = new PCDX11UberConstantBuffer(32);
|
|
buffer->assignRow(0, sub->psBufferData, sub->psBufferSize);
|
|
buffer->syncBuffer(deviceContext); // HACK
|
|
constantBuffersPs[i] = buffer;
|
|
}
|
|
|
|
if (sub->vsBufferSize) {
|
|
auto buffer = new PCDX11UberConstantBuffer(32);
|
|
buffer->assignRow(0, sub->vsBufferData, sub->vsBufferSize);
|
|
buffer->syncBuffer(deviceContext); // HACK
|
|
constantBuffersVs[i] = buffer;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PCDX11Material::Release() {
|
|
renderDevice->DeferredRelease(this);
|
|
}
|
|
|
|
PCDX11Material::~PCDX11Material() {
|
|
FreeData();
|
|
}
|
|
|
|
void PCDX11Material::method_18() {
|
|
// TODO
|
|
}
|
|
|
|
static char s_dummyModifierParams[16 * 8] = {0};
|
|
|
|
void PCDX11Material::setupVertexResources(
|
|
uint32_t subMaterialIndex,
|
|
MaterialBlobSub* subMat,
|
|
MaterialInstanceData *matInstance,
|
|
char *cbData,
|
|
bool doEverything)
|
|
{
|
|
auto *stateManager = deviceManager->getStateManager();
|
|
auto *texref = subMat->vsTextureRef;
|
|
|
|
if (doEverything) {
|
|
|
|
if (subMat->vsBufferSize)
|
|
stateManager->setVsConstantBuffer(4, constantBuffersVs[subMaterialIndex]);
|
|
|
|
// assign 0..refIndexEndA from submaterial
|
|
for (uint32_t i = 0; i < subMat->vsRefIndexEndA; i++)
|
|
renderDevice->setTexture(
|
|
texref[i].slotIndex + 257,
|
|
static_cast<PCDX11Texture*>(texref[i].tex),
|
|
texref[i].filter,
|
|
texref[i].unknown4);
|
|
|
|
// assign refIndexEndA..refIndexBeginB from submaterial or RenderGlobalState
|
|
CommonScene *scene = renderDevice->scene78;
|
|
for (uint32_t i = subMat->vsRefIndexEndA; i < subMat->vsRefIndexBeginB; i++) {
|
|
auto fi = texref[i].fallbackIndex & 0x1F;
|
|
PCDX11Texture* tex = static_cast<PCDX11Texture*>(scene->globalState.tex14[fi]);
|
|
if (!tex) tex = static_cast<PCDX11Texture*>(texref[i].tex);
|
|
renderDevice->setTexture(
|
|
texref[i].slotIndex + 257,
|
|
tex,
|
|
fi == 10 ? 0 : texref[i].filter,
|
|
texref[i].unknown4);
|
|
}
|
|
}
|
|
|
|
// assign refIndexBeginB..+refIndexCountB from submaterial or MaterialInstanceData
|
|
for (uint32_t i = subMat->vsRefIndexBeginB; i < subMat->vsRefIndexBeginB + subMat->vsRefIndexCountB; i++) {
|
|
auto extTextures = (PCDX11Texture**)matInstance;
|
|
auto fi = texref[i].fallbackIndex & 0x1F;
|
|
PCDX11Texture* tex = extTextures[fi - 1];
|
|
if (!tex) tex = static_cast<PCDX11Texture*>(texref[i].tex);
|
|
renderDevice->setTexture(
|
|
texref[i].slotIndex + 257,
|
|
tex,
|
|
texref[i].filter,
|
|
texref[i].unknown4);
|
|
}
|
|
|
|
if (subMat->vsBufferNumRows) {
|
|
if (!cbData)
|
|
cbData = s_dummyModifierParams;
|
|
PCDX11UberConstantBuffer& cb = stateManager->accessCommonCB(4);
|
|
auto firstRow = subMat->vsBufferFirstRow;
|
|
auto numRows = subMat->vsBufferNumRows;
|
|
cb.assignRow(firstRow, &cbData[16 * firstRow], numRows);
|
|
}
|
|
}
|
|
|
|
void PCDX11Material::setupPixelResources(
|
|
uint32_t subMaterialIndex,
|
|
MaterialBlobSub *subMat,
|
|
MaterialInstanceData *subExt,
|
|
char *cbData,
|
|
bool doEverything)
|
|
{
|
|
auto *stateManager = deviceManager->getStateManager();
|
|
MaterialTexRef *texref = subMat->psTextureRef;
|
|
|
|
if (doEverything) {
|
|
|
|
if (subMat->psBufferSize)
|
|
if (constantBuffersPs[subMaterialIndex]) // HACK
|
|
stateManager->setPsConstantBuffer(3, constantBuffersPs[subMaterialIndex]);
|
|
|
|
// assign 0..refIndexEndA from submaterial
|
|
for (uint32_t i = 0; i < subMat->psRefIndexEndA; i++) {
|
|
PCDX11Texture* tex = static_cast<PCDX11Texture*>(texref[i].tex);
|
|
renderDevice->setTexture(
|
|
texref[i].slotIndex,
|
|
tex,
|
|
texref[i].filter,
|
|
texref[i].unknown4);
|
|
}
|
|
|
|
// assign refIndexEndA..refIndexBeginB from submaterial or RenderGlobalState
|
|
CommonScene *scene = renderDevice->scene78;
|
|
for (uint32_t i = subMat->psRefIndexEndA; i < subMat->psRefIndexBeginB; i++) {
|
|
auto fi = texref[i].fallbackIndex & 0x1F;
|
|
PCDX11Texture* tex = static_cast<PCDX11Texture*>(scene->globalState.tex14[fi]);
|
|
if (!tex) tex = static_cast<PCDX11Texture*>(texref[i].tex);
|
|
renderDevice->setTexture(
|
|
texref[i].slotIndex,
|
|
tex,
|
|
fi == 10 ? 0 : texref[i].filter,
|
|
texref[i].unknown4);
|
|
}
|
|
}
|
|
|
|
// assign refIndexBeginB..+refIndexCountB from submaterial or MaterialInstanceData
|
|
for (uint32_t i = subMat->psRefIndexBeginB; i < subMat->psRefIndexBeginB + subMat->psRefIndexCountB; i++) {
|
|
auto extTextures = subExt->pInstanceTextures;
|
|
auto fi = texref[i].fallbackIndex & 0x1F;
|
|
PCDX11Texture *tex = static_cast<PCDX11Texture*>(extTextures[fi - 1]);
|
|
if (!tex) tex = static_cast<PCDX11Texture*>(texref[i].tex);
|
|
renderDevice->setTexture(
|
|
texref[i].slotIndex,
|
|
tex,
|
|
texref[i].filter,
|
|
texref[i].unknown4);
|
|
}
|
|
|
|
if (subMat->psBufferNumRows) {
|
|
if (!cbData)
|
|
cbData = s_dummyModifierParams;
|
|
PCDX11UberConstantBuffer& cb = stateManager->accessCommonCB(4);
|
|
auto firstRow = subMat->psBufferFirstRow;
|
|
auto numRows = subMat->psBufferNumRows;
|
|
cb.assignRow(firstRow, &cbData[16 * firstRow], numRows);
|
|
}
|
|
}
|
|
|
|
void PCDX11Material::setupDepthBias(MaterialInstanceData *matInstance) {
|
|
float depthBias = 0.0f;
|
|
float slopeScaledDepthBias = 0.0f;
|
|
|
|
if (materialBlob->negDepthBias) {
|
|
depthBias = -materialBlob->negDepthBias;
|
|
slopeScaledDepthBias = -materialBlob->negSlopeScaledDepthBias;
|
|
} else if (matInstance->polyFlags & 0x20000000) {
|
|
depthBias = -1.0f;
|
|
slopeScaledDepthBias = -10.0f;
|
|
}
|
|
|
|
auto *stateManager = deviceManager->getStateManager();
|
|
stateManager->setDepthBias(int32_t(depthBias));
|
|
stateManager->setDepthBiasClamp(0.0f);
|
|
stateManager->setSlopeScaledDepthBias(slopeScaledDepthBias);
|
|
}
|
|
|
|
void PCDX11Material::setupStencil(
|
|
MaterialInstanceData *matInstance,
|
|
bool isColorPass_honorRenderTwice,
|
|
uint32_t flags)
|
|
{
|
|
auto *stateManager = deviceManager->getStateManager();
|
|
StencilParams *stencilSettings = matInstance->stencilSettings64
|
|
? matInstance->stencilSettings64
|
|
: &materialBlob->stencilSettings34;
|
|
|
|
uint32_t matDword18 = materialBlob->dword18;
|
|
bool frontCounterClockwise = bool(flags & 2);
|
|
bool stencilDoubleSided = bool(stencilSettings->m_backParams & 1);
|
|
bool matInstanceDoubleSided = bool(matInstance->polyFlags & 0x40);
|
|
bool materialDoubleSided = bool(matDword18 & 0x80);
|
|
bool materialRenderTwice = bool(matDword18 & 0x800);
|
|
bool materialCullFront = bool(matDword18 & 0x2000);
|
|
|
|
if (stencilDoubleSided || (
|
|
(materialDoubleSided || matInstanceDoubleSided) &&
|
|
!(materialRenderTwice && isColorPass_honorRenderTwice)
|
|
)) // double-check this
|
|
stateManager->setCullMode(CullMode::none, frontCounterClockwise);
|
|
else if (materialCullFront)
|
|
stateManager->setCullMode(CullMode::front, frontCounterClockwise);
|
|
else
|
|
stateManager->setCullMode(CullMode::back, frontCounterClockwise);
|
|
|
|
stateManager->setStencil(stencilSettings);
|
|
}
|
|
|
|
void PCDX11Material::setupSinglePassOpaque(
|
|
PCDX11RenderDevice *renderDevice,
|
|
MaterialInstanceData *matInstance,
|
|
uint32_t flags)
|
|
{
|
|
auto *stateManager = deviceManager->getStateManager();
|
|
setupStencil(matInstance, true, flags);
|
|
stateManager->setDepthRange(matInstance->minDepth, matInstance->maxDepth);
|
|
if (mg_state != 4) {
|
|
invalidate();
|
|
stateManager->setBlendStateAndBlendFactors(0x7010010, 128, 0); // 128 instead of materialBlob->alphaThreshold
|
|
stateManager->setOpacity(1.0);
|
|
stateManager->setDepthState(D3D11_COMPARISON_EQUAL, 0);
|
|
stateManager->setFogColor(renderDevice->scene78->fogColor);
|
|
mg_state = 4;
|
|
}
|
|
|
|
// redo some of what setupStencil did earlier
|
|
uint32_t matDword18 = materialBlob->dword18;
|
|
bool frontCounterClockwise = bool(flags & 2);
|
|
bool matInstanceDoubleSided = bool(matInstance->polyFlags & 0x40);
|
|
bool materialDoubleSided = bool(matDword18 & 0x80);
|
|
bool materialRenderTwice = bool(matDword18 & 0x800);
|
|
bool materialCullFront = bool(matDword18 & 0x2000);
|
|
|
|
if ((materialDoubleSided || matInstanceDoubleSided) && !materialRenderTwice)
|
|
stateManager->setCullMode(CullMode::none, frontCounterClockwise);
|
|
else if (materialCullFront)
|
|
stateManager->setCullMode(CullMode::front, frontCounterClockwise);
|
|
else
|
|
stateManager->setCullMode(CullMode::back, frontCounterClockwise);
|
|
}
|
|
|
|
void PCDX11Material::setupSinglePassTranslucent(
|
|
PCDX11RenderDevice *renderDevice,
|
|
MaterialInstanceData *matInstance,
|
|
uint32_t flags,
|
|
float opacityMultiplier)
|
|
{
|
|
// lights use this function (eg. deferred_fast_omni_diffuse.drm)
|
|
auto *stateManager = deviceManager->getStateManager();
|
|
if (mg_state != 5) {
|
|
invalidate();
|
|
mg_state = 5;
|
|
}
|
|
|
|
float opacity = matInstance->opacity * opacityMultiplier;
|
|
uint32_t blendState = materialBlob->blendStateC;
|
|
uint32_t alphaThreshold = materialBlob->alphaThreshold;
|
|
if ((blendState & 1) || opacity >= 1.0) {
|
|
// empty
|
|
} else {
|
|
blendState = GetFadeBlendMode();
|
|
if (blendState == 0x6540541)
|
|
alphaThreshold = 1;
|
|
}
|
|
|
|
stateManager->setBlendStateAndBlendFactors(
|
|
blendState,
|
|
alphaThreshold,
|
|
materialBlob->blendFactors);
|
|
|
|
setupStencil(matInstance, true, flags);
|
|
|
|
stateManager->setOpacity(opacity);
|
|
stateManager->setDepthState(
|
|
(matInstance->polyFlags & 0x400) ? D3D11_COMPARISON_ALWAYS : D3D11_COMPARISON_LESS_EQUAL, 0);
|
|
|
|
|
|
// redo some of what setupStencil did earlier
|
|
/*uint32_t matDword18 = materialBlob->dword18;
|
|
bool frontCounterClockwise = bool(flags & 2);
|
|
bool matInstanceDoubleSided = bool(matInstance->polyFlags & 0x40);
|
|
bool materialDoubleSided = bool(matDword18 & 0x80);
|
|
bool materialRenderTwice = bool(matDword18 & 0x800);
|
|
bool materialCullFront = bool(matDword18 & 0x2000);
|
|
|
|
if ((materialDoubleSided || matInstanceDoubleSided) && !materialRenderTwice)
|
|
stateManager->setCullMode(CullMode::none, frontCounterClockwise);
|
|
else if (materialCullFront)
|
|
stateManager->setCullMode(CullMode::front, frontCounterClockwise);
|
|
else
|
|
stateManager->setCullMode(CullMode::back, frontCounterClockwise);*/
|
|
}
|
|
|
|
void PCDX11Material::invalidate() {
|
|
mg_state = 21;
|
|
mg_vsSelectAndFlags = 0xffffffff;
|
|
mg_material = nullptr;
|
|
mg_cbdata = nullptr;
|
|
mg_matInstance = nullptr;
|
|
mg_streamDecl = nullptr;
|
|
mg_layoutA = nullptr;
|
|
}
|
|
|
|
// submaterial 0, 1 and 5
|
|
PCDX11StreamDecl *PCDX11Material::SetupDepthPass(
|
|
MaterialInstanceData* matInstance,
|
|
void *drawableExtDword50,
|
|
uint32_t vsSelect,
|
|
bool arg4,
|
|
VertexDecl *layoutA,
|
|
uint8_t flags,
|
|
float opacityMultiplier,
|
|
float floatY)
|
|
{
|
|
if (mg_state != 1) {
|
|
mg_vsSelectAndFlags = -1;
|
|
mg_material = nullptr;
|
|
mg_cbdata = nullptr;
|
|
mg_matInstance = nullptr;
|
|
mg_streamDecl = nullptr;
|
|
mg_layoutA = nullptr;
|
|
mg_state = 1;
|
|
}
|
|
|
|
float opacity = matInstance->opacity * opacityMultiplier;
|
|
uint32_t blendState = materialBlob->blendStateC;
|
|
bool noPixelShader = true;
|
|
if ((blendState & 1) || (blendState & 0x7000000) != 0x7000000 || opacity < 1.0)
|
|
noPixelShader = false;
|
|
|
|
uint32_t subMaterialIndex;
|
|
if (arg4)
|
|
subMaterialIndex = 5;
|
|
else
|
|
subMaterialIndex = noPixelShader ? 0 : 1;
|
|
|
|
MaterialBlobSub *subMaterial = materialBlob->subMat4C[subMaterialIndex];
|
|
uint32_t vsSelectAndFlags = (vsSelect << 8) | flags;
|
|
bool materialChange = mg_material != this;
|
|
if (materialChange || mg_vsSelectAndFlags != vsSelectAndFlags) {
|
|
|
|
auto *stateManager = deviceManager->getStateManager();
|
|
uint32_t vertexIndex = vsSelect;
|
|
if (flags & 8)
|
|
vertexIndex |= 8;
|
|
|
|
// set pixel shader
|
|
PCDX11PixelShaderTable *pixelTable;
|
|
uint32_t pixelIndex = 0;
|
|
if (materialBlob->blendStateC == 0x7010010) {
|
|
stateManager->setBlendStateAndBlendFactors(0x7010010, 128, 0); // 128 instead of materialBlob->alphaThreshold
|
|
pixelTable = &renderDevice->shtab_ps_white_27;
|
|
if (arg4)
|
|
pixelIndex = 1;
|
|
} else {
|
|
if (arg4) {
|
|
stateManager->setBlendStateAndBlendFactors(0x7010010, 128, 0); // 128 instead of materialBlob->alphaThreshold
|
|
stateManager->setAlphaThreshold(materialBlob->alphaThreshold);
|
|
} else {
|
|
stateManager->setBlendStateAndBlendFactors(0x6010010, materialBlob->alphaThreshold, 0);
|
|
}
|
|
auto pixelLib = static_cast<PCDX11ShaderLib*>(subMaterial->shaderPixel);
|
|
if (!pixelLib)
|
|
return nullptr; // HACK
|
|
pixelTable = static_cast<PCDX11PixelShaderTable*>(pixelLib->table);
|
|
}
|
|
|
|
auto pixelShader = (*pixelTable)[pixelIndex];
|
|
stateManager->setPixelShader(pixelShader);
|
|
|
|
// set vertex shader
|
|
auto vertexLib = static_cast<PCDX11ShaderLib*>(subMaterial->shaderVertex);
|
|
if (!vertexLib)
|
|
return nullptr;
|
|
auto vertexTable = static_cast<PCDX11VertexShaderTable*>(vertexLib->table);
|
|
auto vertexShader = (*vertexTable)[vertexIndex];
|
|
stateManager->setVertexShader(vertexShader);
|
|
|
|
mg_vsSelectAndFlags = vsSelectAndFlags;
|
|
mg_material = this;
|
|
|
|
auto *streamDecl = static_cast<PCDX11StreamDecl*>(matInstance->streamDecls24[subMaterialIndex]);
|
|
if (!streamDecl) {
|
|
ShaderInputSpec *layoutB = subMaterial->vsLayout[vsSelect];
|
|
|
|
streamDecl = renderDevice->streamDeclCache.buildStreamDecl(
|
|
layoutA,
|
|
layoutB,
|
|
(flags >> 3) & 1, // flag 8 added in PCDX11TerrainDrawable constructor for example
|
|
&vertexShader->m_sub);
|
|
}
|
|
|
|
mg_streamDecl = streamDecl;
|
|
|
|
} else {
|
|
if (mg_cbdata == drawableExtDword50 || mg_matInstance == matInstance) // || or && ?
|
|
return mg_streamDecl;
|
|
}
|
|
|
|
if (!noPixelShader)
|
|
setupPixelResources(subMaterialIndex, subMaterial, matInstance, (char*)drawableExtDword50, materialChange);
|
|
setupVertexResources(subMaterialIndex, subMaterial, matInstance, (char*)drawableExtDword50, materialChange);
|
|
|
|
setupDepthBias(matInstance);
|
|
deviceManager->getStateManager()->setDepthRange(matInstance->minDepth, matInstance->maxDepth);
|
|
deviceManager->getStateManager()->setOpacity(opacity);
|
|
mg_matInstance = matInstance;
|
|
mg_cbdata = drawableExtDword50;
|
|
|
|
return mg_streamDecl;
|
|
}
|
|
|
|
// submaterial 0 and 1
|
|
PCDX11StreamDecl *PCDX11Material::SetupShadowPass(
|
|
MaterialInstanceData*,
|
|
void *drawableExtDword50,
|
|
uint8_t lightManager434_114,
|
|
uint32_t vsSelect,
|
|
VertexDecl *layout,
|
|
uint8_t flags,
|
|
float opacityMultiplier,
|
|
float floatY)
|
|
{
|
|
// TODO
|
|
return nullptr;
|
|
}
|
|
|
|
// submaterial 4
|
|
PCDX11StreamDecl *PCDX11Material::SetupBloomPass(
|
|
MaterialInstanceData *matInstance,
|
|
void *drawableExtDword50,
|
|
uint32_t vsSelect,
|
|
VertexDecl *layoutA,
|
|
uint8_t flags,
|
|
float opacityMultiplier)
|
|
{
|
|
auto *stateManager = deviceManager->getStateManager();
|
|
const uint32_t subMaterialIndex = 4;
|
|
MaterialBlobSub *subMaterial = materialBlob->subMat4C[subMaterialIndex];
|
|
|
|
setupDepthBias(matInstance);
|
|
setupStencil(matInstance, true, flags);
|
|
stateManager->setDepthRange(matInstance->minDepth, matInstance->maxDepth);
|
|
stateManager->setBlendStateAndBlendFactors(materialBlob->blendState24, 0, 0);
|
|
|
|
uint32_t vertexIndex = vsSelect;
|
|
if (flags & 8)
|
|
vertexIndex |= 8;
|
|
uint32_t pixelIndex = 0;
|
|
|
|
auto pixelTable = static_cast<PCDX11PixelShaderTable*>(static_cast<PCDX11ShaderLib*>(subMaterial->shaderPixel)->table);
|
|
auto pixelShader = (*pixelTable)[pixelIndex];
|
|
stateManager->setPixelShader(pixelShader);
|
|
|
|
auto vertexTable = static_cast<PCDX11VertexShaderTable*>(static_cast<PCDX11ShaderLib*>(subMaterial->shaderVertex)->table);
|
|
auto vertexShader = (*vertexTable)[vertexIndex];
|
|
stateManager->setVertexShader(vertexShader);
|
|
|
|
setupPixelResources(subMaterialIndex, subMaterial, matInstance, (char*)drawableExtDword50, true);
|
|
setupVertexResources(subMaterialIndex, subMaterial, matInstance, (char*)drawableExtDword50, true);
|
|
|
|
auto *streamDecl = static_cast<PCDX11StreamDecl*>(matInstance->streamDecls24[subMaterialIndex]);
|
|
if (!streamDecl) {
|
|
ShaderInputSpec *layoutB = subMaterial->vsLayout[vsSelect];
|
|
|
|
streamDecl = renderDevice->streamDeclCache.buildStreamDecl(
|
|
layoutA,
|
|
layoutB,
|
|
(flags >> 3) & 1, // flag 8 added in PCDX11TerrainDrawable constructor for example
|
|
&vertexShader->m_sub);
|
|
}
|
|
|
|
return streamDecl;
|
|
}
|
|
|
|
// submaterial 0, 3 and 8
|
|
PCDX11StreamDecl *PCDX11Material::SetupSinglePass(
|
|
MaterialInstanceData *matInstance,
|
|
void *drawableExtDword50,
|
|
void *lightConstantBufferData,
|
|
uint32_t vsSelect,
|
|
VertexDecl *layoutA,
|
|
uint8_t flags,
|
|
bool isTranslucentPass,
|
|
float opacityMultiplier,
|
|
float lodDistance)
|
|
{
|
|
float opacity = matInstance->opacity * opacityMultiplier;
|
|
uint32_t blendState = materialBlob->blendStateC;
|
|
bool x = true;
|
|
if ((materialBlob->dword18 & 1) == 0 ||
|
|
renderDevice->scene78->m_isUseAlphaForBloom ||
|
|
(blendState & 1) ||
|
|
opacity < 1.0
|
|
)
|
|
x = false;
|
|
|
|
uint32_t subMaterialIndex;
|
|
if (isTranslucentPass) {
|
|
subMaterialIndex = 8;
|
|
setupSinglePassTranslucent(renderDevice, /*0,*/ matInstance, flags, opacityMultiplier);
|
|
} else {
|
|
subMaterialIndex = 3;
|
|
setupSinglePassOpaque(renderDevice, /*0,*/ matInstance, flags);
|
|
}
|
|
|
|
bool noPixelShader = flags & 1;
|
|
if (noPixelShader)
|
|
subMaterialIndex = 0;
|
|
|
|
auto *stateManager = deviceManager->getStateManager();
|
|
MaterialBlobSub *subMaterial = materialBlob->subMat4C[subMaterialIndex];
|
|
|
|
if (mg_material != this) {
|
|
setupPixelResources(subMaterialIndex, subMaterial, matInstance, (char*)drawableExtDword50, true);
|
|
setupVertexResources(subMaterialIndex, subMaterial, matInstance, (char*)drawableExtDword50, true);
|
|
setupDepthBias(matInstance);
|
|
|
|
} else if (mg_matInstance != matInstance || mg_cbdata != drawableExtDword50) {
|
|
setupPixelResources(subMaterialIndex, subMaterial, matInstance, (char*)drawableExtDword50, false);
|
|
setupVertexResources(subMaterialIndex, subMaterial, matInstance, (char*)drawableExtDword50, false);
|
|
setupDepthBias(matInstance);
|
|
}
|
|
|
|
bool tesselate = false;
|
|
uint32_t vsSelectAndFlags = (vsSelect << 8) | flags;
|
|
|
|
//setupStencil(matInstance, true, flags);
|
|
//stateManager->setDepthRange(matInstance->minDepth, matInstance->maxDepth);
|
|
//stateManager->setBlendStateAndBlendFactors(materialBlob->blendState24, 0, 0);
|
|
|
|
uint16_t renderTargetWriteMask = materialBlob->renderTargetWriteMask;
|
|
/* if (renderDevice->scene78->m_isUseAlphaForBloom) {
|
|
if (x)
|
|
renderTargetWriteMask = renderTargetWriteMask | 8;
|
|
else
|
|
renderTargetWriteMask = renderTargetWriteMask & 7;
|
|
} */
|
|
stateManager->setRenderTargetWriteMask(renderTargetWriteMask);
|
|
|
|
uint32_t vertexIndex = vsSelect;
|
|
if (flags & 8)
|
|
vertexIndex |= 8;
|
|
uint32_t pixelIndex = 0;
|
|
|
|
auto pixelLib = static_cast<PCDX11ShaderLib*>(subMaterial->shaderPixel);
|
|
if (!pixelLib)
|
|
return nullptr;
|
|
auto pixelTable = static_cast<PCDX11PixelShaderTable*>(pixelLib->table);
|
|
auto pixelShader = (*pixelTable)[pixelIndex];
|
|
stateManager->setPixelShader(pixelShader);
|
|
|
|
auto vertexLib = static_cast<PCDX11ShaderLib*>(subMaterial->shaderVertex);
|
|
if (!vertexLib)
|
|
return nullptr;
|
|
auto vertexTable = static_cast<PCDX11VertexShaderTable*>(vertexLib->table);
|
|
auto vertexShader = (*vertexTable)[vertexIndex];
|
|
stateManager->setVertexShader(vertexShader);
|
|
|
|
auto *streamDecl = static_cast<PCDX11StreamDecl*>(matInstance->streamDecls24[subMaterialIndex]);
|
|
if (!streamDecl) {
|
|
ShaderInputSpec *layoutB = subMaterial->vsLayout[vsSelect];
|
|
|
|
streamDecl = renderDevice->streamDeclCache.buildStreamDecl(
|
|
layoutA,
|
|
layoutB,
|
|
(flags >> 3) & 1, // flag 8 added in PCDX11TerrainDrawable constructor for example
|
|
&vertexShader->m_sub);
|
|
}
|
|
|
|
mg_streamDecl = streamDecl;
|
|
|
|
mg_matInstance = matInstance;
|
|
mg_material = this;
|
|
mg_cbdata = drawableExtDword50;
|
|
mg_vsSelectAndFlags = vsSelectAndFlags;
|
|
mg_tesselate = tesselate;
|
|
|
|
return mg_streamDecl;
|
|
}
|
|
|
|
// submaterial 7
|
|
PCDX11StreamDecl *PCDX11Material::SetupNormalMapPass(
|
|
MaterialInstanceData *matInstance,
|
|
void *drawableExtDword50,
|
|
uint32_t vsSelect,
|
|
VertexDecl *layout,
|
|
uint8_t flags,
|
|
float opacityMultiplier,
|
|
float floatY)
|
|
{
|
|
auto *stateManager = deviceManager->getStateManager();
|
|
|
|
if (mg_state != 10) {
|
|
mg_state = 21;
|
|
mg_vsSelectAndFlags = -1;
|
|
mg_material = nullptr;
|
|
mg_cbdata = nullptr;
|
|
mg_matInstance = nullptr;
|
|
mg_streamDecl = nullptr;
|
|
mg_layoutA = nullptr;
|
|
StencilParams stencilParams {
|
|
0xFF00000E,
|
|
0xFF00000E,
|
|
0x0000FFFF,
|
|
0
|
|
};
|
|
stateManager->setStencil(&stencilParams);
|
|
stateManager->setOpacity(1.0f);
|
|
stateManager->setDepthState(D3D11_COMPARISON_LESS_EQUAL, /*depthWrites=*/ true);
|
|
stateManager->setFogColor(renderDevice->scene78->fogColor);
|
|
mg_state = 10;
|
|
}
|
|
|
|
uint32_t matDword18 = materialBlob->dword18;
|
|
bool frontCounterClockwise = bool(flags & 2);
|
|
bool matInstanceDoubleSided = bool(matInstance->polyFlags & 0x40);
|
|
bool materialDoubleSided = bool(matDword18 & 0x80);
|
|
bool materialRenderTwice = bool(matDword18 & 0x800);
|
|
bool materialCullFront = bool(matDword18 & 0x2000);
|
|
|
|
if ((materialDoubleSided || matInstanceDoubleSided) && !materialRenderTwice)
|
|
stateManager->setCullMode(CullMode::none, frontCounterClockwise);
|
|
else if (materialCullFront)
|
|
stateManager->setCullMode(CullMode::front, frontCounterClockwise);
|
|
else
|
|
stateManager->setCullMode(CullMode::back, frontCounterClockwise);
|
|
|
|
uint32_t subMaterialIndex = 7; // normals
|
|
MaterialBlobSub *subMaterial = materialBlob->subMat4C[subMaterialIndex];
|
|
|
|
bool materialChange = mg_material != this;
|
|
if (materialChange || mg_cbdata != drawableExtDword50 || mg_matInstance != matInstance) {
|
|
setupPixelResources(subMaterialIndex, subMaterial, matInstance, (char*)drawableExtDword50, materialChange);
|
|
setupVertexResources(subMaterialIndex, subMaterial, matInstance, (char*)drawableExtDword50, materialChange);
|
|
setupDepthBias(matInstance);
|
|
deviceManager->getStateManager()->setDepthRange(matInstance->minDepth, matInstance->maxDepth);
|
|
}
|
|
|
|
float opacity = matInstance->opacity * opacityMultiplier;
|
|
uint32_t blendState = materialBlob->blendStateC;
|
|
if ((blendState & 1) || (blendState & 0x7000000) != 0x7000000 || opacity < 1.0)
|
|
blendState = 0x6010010;
|
|
else
|
|
blendState = 0x7010010;
|
|
stateManager->setBlendStateAndBlendFactors(blendState, materialBlob->alphaThreshold, 0);
|
|
|
|
bool tesselate = false; // TODO
|
|
|
|
uint32_t vsSelectAndFlags = (vsSelect << 8) | flags;
|
|
if (materialChange ||
|
|
mg_layoutA != layout ||
|
|
((mg_vsSelectAndFlags ^ vsSelectAndFlags) & 0xFF08) ||
|
|
mg_tesselate != tesselate)
|
|
{
|
|
uint16_t renderTargetWriteMask = materialBlob->renderTargetWriteMask;
|
|
stateManager->setRenderTargetWriteMask(renderTargetWriteMask & 7);
|
|
|
|
// set pixel shader
|
|
uint32_t pixelIndex = 0; // without discard
|
|
if ((materialBlob->blendStateC & 0x07000000) != 0x07000000)
|
|
pixelIndex = 4; // with discard
|
|
|
|
auto pixelLib = static_cast<PCDX11ShaderLib*>(subMaterial->shaderPixel);
|
|
if (!pixelLib)
|
|
return nullptr; // HACK
|
|
auto *pixelTable = static_cast<PCDX11PixelShaderTable*>(pixelLib->table);
|
|
auto pixelShader = (*pixelTable)[pixelIndex];
|
|
stateManager->setPixelShader(pixelShader);
|
|
|
|
// set vertex shader
|
|
uint32_t vertexIndex = vsSelect;
|
|
if (flags & 8)
|
|
vertexIndex |= 8;
|
|
if (tesselate)
|
|
vertexIndex |= 16;
|
|
|
|
auto vertexLib = static_cast<PCDX11ShaderLib*>(subMaterial->shaderVertex);
|
|
auto vertexTable = static_cast<PCDX11VertexShaderTable*>(vertexLib->table);
|
|
auto vertexShader = (*vertexTable)[vertexIndex];
|
|
stateManager->setVertexShader(vertexShader);
|
|
|
|
// TODO: domain and hull shader
|
|
auto *streamDecl = static_cast<PCDX11StreamDecl*>(matInstance->streamDecls24[subMaterialIndex]);
|
|
if (!streamDecl) {
|
|
ShaderInputSpec *layoutB = subMaterial->vsLayout[vsSelect];
|
|
streamDecl = renderDevice->streamDeclCache.buildStreamDecl(
|
|
layout,
|
|
layoutB,
|
|
(flags >> 3) & 1, // flag 8 added in PCDX11TerrainDrawable constructor for example
|
|
&vertexShader->m_sub);
|
|
}
|
|
|
|
mg_streamDecl = streamDecl;
|
|
}
|
|
|
|
mg_material = this;
|
|
mg_tesselate = tesselate;
|
|
mg_matInstance = matInstance;
|
|
mg_layoutA = layout;
|
|
mg_vsSelectAndFlags = vsSelectAndFlags;
|
|
mg_cbdata = drawableExtDword50;
|
|
|
|
return mg_streamDecl;
|
|
}
|
|
|
|
}
|