This repository has been archived by the owner. It is now read-only.
Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
There are no files selected for viewing
| @@ -0,0 +1,212 @@ | ||
| #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 | ||
| RwD3D8SetTexture(NULL, 0); | ||
| 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); | ||
| 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 |