2019-06-28 23:39:32 +02:00
|
|
|
#define WITHD3D
|
|
|
|
#include "common.h"
|
|
|
|
#include "patcher.h"
|
|
|
|
|
|
|
|
struct MatFXNothing { int pad[5]; int effect; };
|
|
|
|
|
|
|
|
struct MatFXBump
|
|
|
|
{
|
|
|
|
RwFrame *bumpFrame;
|
|
|
|
RwTexture *bumpedTex;
|
|
|
|
RwTexture *bumpTex;
|
|
|
|
float negBumpCoefficient;
|
|
|
|
int pad;
|
|
|
|
int effect;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct MatFXEnv
|
|
|
|
{
|
|
|
|
RwFrame *envFrame;
|
|
|
|
RwTexture *envTex;
|
|
|
|
float envCoeff;
|
|
|
|
int envFBalpha;
|
|
|
|
int pad;
|
|
|
|
int effect;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct MatFXDual
|
|
|
|
{
|
|
|
|
RwTexture *dualTex;
|
|
|
|
RwInt32 srcBlend;
|
|
|
|
RwInt32 dstBlend;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct MatFX
|
|
|
|
{
|
|
|
|
union {
|
|
|
|
MatFXNothing n;
|
|
|
|
MatFXBump b;
|
|
|
|
MatFXEnv e;
|
|
|
|
MatFXDual d;
|
|
|
|
} fx[2];
|
|
|
|
int effects;
|
|
|
|
};
|
|
|
|
|
|
|
|
int &MatFXMaterialDataOffset = *(int*)0x66188C;
|
|
|
|
int &MatFXAtomicDataOffset = *(int*)0x66189C;
|
|
|
|
|
|
|
|
#ifdef PS2_MATFX
|
|
|
|
|
|
|
|
void
|
|
|
|
_rpMatFXD3D8AtomicMatFXDefaultRender(RxD3D8InstanceData *inst, int flags, RwTexture *texture)
|
|
|
|
{
|
|
|
|
if(flags & (rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2) && texture)
|
|
|
|
RwD3D8SetTexture(texture, 0);
|
|
|
|
else
|
2019-06-30 12:53:39 +02:00
|
|
|
RwD3D8SetTexture(nil, 0);
|
2019-06-28 23:39:32 +02:00
|
|
|
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(inst->vertexAlpha || inst->material->color.alpha != 0xFF));
|
|
|
|
RwD3D8SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, inst->vertexAlpha != 0);
|
|
|
|
RwD3D8SetPixelShader(0);
|
|
|
|
RwD3D8SetVertexShader(inst->vertexShader);
|
|
|
|
RwD3D8SetStreamSource(0, inst->vertexBuffer, inst->stride);
|
|
|
|
|
|
|
|
if(inst->indexBuffer){
|
|
|
|
RwD3D8SetIndices(inst->indexBuffer, inst->baseIndex);
|
|
|
|
RwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices);
|
|
|
|
}else
|
|
|
|
RwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices);
|
|
|
|
}
|
|
|
|
|
|
|
|
// map [-1; -1] -> [0; 1], flip V
|
|
|
|
static RwMatrix scalenormal = {
|
|
|
|
{ 0.5f, 0.0f, 0.0f }, 0,
|
|
|
|
{ 0.0f, -0.5f, 0.0f }, 0,
|
|
|
|
{ 0.0f, 0.0f, 1.0f }, 0,
|
|
|
|
{ 0.5f, 0.5f, 0.0f }, 0,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
// flipped U for PS2
|
|
|
|
static RwMatrix scalenormal_flipU = {
|
|
|
|
{ -0.5f, 0.0f, 0.0f }, 0,
|
|
|
|
{ 0.0f, -0.5f, 0.0f }, 0,
|
|
|
|
{ 0.0f, 0.0f, 1.0f }, 0,
|
|
|
|
{ 0.5f, 0.5f, 0.0f }, 0,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
ApplyEnvMapTextureMatrix(RwTexture *tex, int n, RwFrame *frame)
|
|
|
|
{
|
|
|
|
RwD3D8SetTexture(tex, n);
|
|
|
|
RwD3D8SetTextureStageState(n, D3DRS_ALPHAREF, 2);
|
|
|
|
RwD3D8SetTextureStageState(n, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL);
|
|
|
|
if(frame){
|
|
|
|
RwMatrix *envframemat = RwMatrixCreate();
|
|
|
|
RwMatrix *tmpmat = RwMatrixCreate();
|
|
|
|
RwMatrix *envmat = RwMatrixCreate();
|
|
|
|
|
|
|
|
RwMatrixInvert(envframemat, RwFrameGetLTM(frame));
|
|
|
|
// PS2
|
|
|
|
// can this be simplified?
|
|
|
|
*tmpmat = *RwFrameGetLTM(RwCameraGetFrame((RwCamera*)RWSRCGLOBAL(curCamera)));
|
|
|
|
RwV3dNegate(&tmpmat->right, &tmpmat->right);
|
|
|
|
tmpmat->flags = 0;
|
|
|
|
tmpmat->pos.x = 0.0f;
|
|
|
|
tmpmat->pos.y = 0.0f;
|
|
|
|
tmpmat->pos.z = 0.0f;
|
|
|
|
RwMatrixMultiply(envmat, tmpmat, envframemat);
|
|
|
|
*tmpmat = *envmat;
|
|
|
|
// important because envframemat can have a translation that we don't like
|
|
|
|
tmpmat->pos.x = 0.0f;
|
|
|
|
tmpmat->pos.y = 0.0f;
|
|
|
|
tmpmat->pos.z = 0.0f;
|
|
|
|
// for some reason we flip in U as well
|
|
|
|
RwMatrixMultiply(envmat, tmpmat, &scalenormal_flipU);
|
|
|
|
|
|
|
|
RwD3D8SetTransform(D3DTS_TEXTURE0+n, envmat);
|
|
|
|
|
|
|
|
RwMatrixDestroy(envmat);
|
|
|
|
RwMatrixDestroy(tmpmat);
|
|
|
|
RwMatrixDestroy(envframemat);
|
|
|
|
}else
|
|
|
|
RwD3D8SetTransform(D3DTS_TEXTURE0+n, &scalenormal);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_rpMatFXD3D8AtomicMatFXEnvRender_ps2(RxD3D8InstanceData *inst, int flags, int sel, RwTexture *texture, RwTexture *envMap)
|
|
|
|
{
|
|
|
|
MatFX *matfx = *RWPLUGINOFFSET(MatFX*, inst->material, MatFXMaterialDataOffset);
|
|
|
|
MatFXEnv *env = &matfx->fx[sel].e;
|
|
|
|
|
|
|
|
uint8 intens = (uint8)(env->envCoeff*255.0f);
|
|
|
|
|
|
|
|
if(intens == 0 || envMap == nil){
|
|
|
|
if(sel == 0)
|
|
|
|
_rpMatFXD3D8AtomicMatFXDefaultRender(inst, flags, texture);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(inst->vertexAlpha || inst->material->color.alpha != 0xFF));
|
|
|
|
if(flags & (rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2) && texture)
|
|
|
|
RwD3D8SetTexture(texture, 0);
|
|
|
|
else
|
|
|
|
RwD3D8SetTexture(nil, 0);
|
2020-03-22 11:40:18 +01:00
|
|
|
RwD3D8SetPixelShader(0);
|
2019-06-28 23:39:32 +02:00
|
|
|
RwD3D8SetVertexShader(inst->vertexShader);
|
|
|
|
RwD3D8SetStreamSource(0, inst->vertexBuffer, inst->stride);
|
|
|
|
RwD3D8SetIndices(inst->indexBuffer, inst->baseIndex);
|
|
|
|
if(inst->indexBuffer)
|
|
|
|
RwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices);
|
|
|
|
else
|
|
|
|
RwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices);
|
|
|
|
|
|
|
|
// Effect pass
|
|
|
|
|
|
|
|
ApplyEnvMapTextureMatrix(envMap, 0, env->envFrame);
|
|
|
|
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
|
|
|
|
RwUInt32 src, dst, lighting, zwrite, fog, fogcol;
|
|
|
|
RwRenderStateGet(rwRENDERSTATESRCBLEND, &src);
|
|
|
|
RwRenderStateGet(rwRENDERSTATEDESTBLEND, &dst);
|
|
|
|
|
|
|
|
// This is of course not using framebuffer alpha,
|
|
|
|
// but if the diffuse texture had no alpha, the result should actually be rather the same
|
|
|
|
if(env->envFBalpha)
|
|
|
|
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
|
|
|
|
else
|
|
|
|
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
|
|
|
|
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
|
|
|
|
RwD3D8GetRenderState(D3DRS_LIGHTING, &lighting);
|
|
|
|
RwD3D8GetRenderState(D3DRS_ZWRITEENABLE, &zwrite);
|
|
|
|
RwD3D8GetRenderState(D3DRS_FOGENABLE, &fog);
|
|
|
|
RwD3D8SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
|
|
|
if(fog){
|
|
|
|
RwD3D8GetRenderState(D3DRS_FOGCOLOR, &fogcol);
|
|
|
|
RwD3D8SetRenderState(D3DRS_FOGCOLOR, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
D3DCOLOR texfactor = D3DCOLOR_RGBA(intens, intens, intens, intens);
|
|
|
|
RwD3D8SetRenderState(D3DRS_TEXTUREFACTOR, texfactor);
|
|
|
|
RwD3D8SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
|
|
|
RwD3D8SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
|
|
|
|
RwD3D8SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TFACTOR);
|
|
|
|
// alpha unused
|
|
|
|
//RwD3D8SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
|
|
|
//RwD3D8SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
|
|
|
|
//RwD3D8SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
|
|
|
|
|
|
|
|
if(inst->indexBuffer)
|
|
|
|
RwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices);
|
|
|
|
else
|
|
|
|
RwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices);
|
|
|
|
|
|
|
|
// Reset states
|
|
|
|
|
|
|
|
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
|
|
|
|
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)src);
|
|
|
|
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)dst);
|
|
|
|
RwD3D8SetRenderState(D3DRS_LIGHTING, lighting);
|
|
|
|
RwD3D8SetRenderState(D3DRS_ZWRITEENABLE, zwrite);
|
|
|
|
if(fog)
|
|
|
|
RwD3D8SetRenderState(D3DRS_FOGCOLOR, fogcol);
|
|
|
|
RwD3D8SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
|
|
|
RwD3D8SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
|
|
|
RwD3D8SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, 0);
|
|
|
|
RwD3D8SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
STARTPATCHES
|
|
|
|
InjectHook(0x5CF6C0, _rpMatFXD3D8AtomicMatFXEnvRender_ps2, PATCH_JUMP);
|
|
|
|
ENDPATCHES
|
|
|
|
|
|
|
|
#endif
|