P.S: 此贴只是用来记录SKYGFX里重点的函数,并不是教程,等坑填完了,在放出资源哈
PS2颜色校正管线(PS2 COLOR FILTER)
使用双重渲染管线 (DUAL PASS RENDER)
TO DO
PS2颜色校正管线(PS2 COLOR FILTER)
void
CPostEffects::ColourFilter_switch(RwRGBA rgb1, RwRGBA rgb2)
{
RwRGBA rgb1pc = rgb1;
RwRGBA rgb2pc = rgb2;
if(config->usePCTimecyc){
// Gotta fix alpha for effects that assume PS2 alpha range
rgb1.alpha /= 2;
rgb2.alpha /= 2;
}else{
// Gotta fix alpha for effects that assume PC alpha range
// clamping this is important!
if(rgb1pc.alpha >= 128)
rgb1pc.alpha = 255;
else
rgb1pc.alpha *= 2;
if(rgb2pc.alpha >= 128)
rgb2pc.alpha = 255;
else
rgb2pc.alpha *= 2;
}
case COLORFILTER_PS2:
CPostEffects::ColourFilter_PS2(rgb1, rgb2);
break;
case COLORFILTER_PC:
// this effects expects PC alphas
CPostEffects::ColourFilter(rgb1pc, rgb2pc);
break;
}
void
CPostEffects::ColourFilter_PS2(RwRGBA rgba1, RwRGBA rgba2)
{
RwIm2DVertex *verts;
verts = colorfilterVerts;
// Setup state
// RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)CPostEffects::pRasterFrontBuffer);
// Make Im2D use PS2 color range
overrideColorMod = D3DTOP_MODULATE2X;
overrideAlphaMod = D3DTOP_MODULATE2X;
// First color - replace
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwIm2DVertexSetIntRGBA(&verts[0], rgba1.red, rgba1.green, rgba1.blue, 255);
RwIm2DVertexSetIntRGBA(&verts[1], rgba1.red, rgba1.green, rgba1.blue, 255);
RwIm2DVertexSetIntRGBA(&verts[2], rgba1.red, rgba1.green, rgba1.blue, 255);
RwIm2DVertexSetIntRGBA(&verts[3], rgba1.red, rgba1.green, rgba1.blue, 255);
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, colorfilterIndices, 6);
if(m_bBlurColourFilter){
static RwIm2DVertex blurVerts[4];
float rasterWidth = RwRasterGetWidth(CPostEffects::pRasterFrontBuffer);
float rasterHeight = RwRasterGetHeight(CPostEffects::pRasterFrontBuffer);
float scale = RwRasterGetWidth(RwCameraGetRaster(Scene.camera))/640.0f;
float leftOff = m_colourLeftUOffset*scale / 16.0f / rasterWidth;
float rightOff = m_colourRightUOffset*scale / 16.0f / rasterWidth;
float topOff = m_colourTopVOffset*scale / 16.0f / rasterHeight;
float bottomOff = m_colourBottomVOffset*scale / 16.0f / rasterHeight;
memcpy(blurVerts, verts, sizeof(blurVerts));
/* These are our vertices:
* 0--3
* |\ |
* | \|
* 1--2 */
// We can get away without setting zrecip on D3D
RwIm2DVertexSetU(&blurVerts[0], RwIm2DVertexGetU(&blurVerts[0]) + leftOff, 1.0f);
RwIm2DVertexSetU(&blurVerts[1], RwIm2DVertexGetU(&blurVerts[1]) + leftOff, 1.0f);
RwIm2DVertexSetU(&blurVerts[2], RwIm2DVertexGetU(&blurVerts[2]) + rightOff, 1.0f);
RwIm2DVertexSetU(&blurVerts[3], RwIm2DVertexGetU(&blurVerts[3]) + rightOff, 1.0f);
RwIm2DVertexSetV(&blurVerts[0], RwIm2DVertexGetV(&blurVerts[0]) + topOff, 1.0f);
RwIm2DVertexSetV(&blurVerts[3], RwIm2DVertexGetV(&blurVerts[3]) + topOff, 1.0f);
RwIm2DVertexSetV(&blurVerts[1], RwIm2DVertexGetV(&blurVerts[1]) + bottomOff, 1.0f);
RwIm2DVertexSetV(&blurVerts[2], RwIm2DVertexGetV(&blurVerts[2]) + bottomOff, 1.0f);
verts = blurVerts;
}
// Second color - add
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
RwIm2DVertexSetIntRGBA(&verts[0], rgba2.red, rgba2.green, rgba2.blue, rgba2.alpha);
RwIm2DVertexSetIntRGBA(&verts[1], rgba2.red, rgba2.green, rgba2.blue, rgba2.alpha);
RwIm2DVertexSetIntRGBA(&verts[2], rgba2.red, rgba2.green, rgba2.blue, rgba2.alpha);
RwIm2DVertexSetIntRGBA(&verts[3], rgba2.red, rgba2.green, rgba2.blue, rgba2.alpha);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, colorfilterIndices, 6);
// Restore state
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)NULL);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
overrideColorMod = -1;
overrideAlphaMod = -1;
}
使用双重渲染管线 (DUAL PASS RENDER)
void D3D9RenderDefault_DUAL(RxD3D9ResEntryHeader *resEntryHeader, RxD3D9InstanceData *instanceData, RwUInt8 flags, RwTexture *texture)
{
if(flags & (rxGEOMETRY_TEXTURED2 | rxGEOMETRY_TEXTURED)){
RwD3D9SetTexture(texture, 0);
RwD3D9SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
RwD3D9SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
RwD3D9SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
RwD3D9SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
RwD3D9SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
RwD3D9SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
}else{
RwD3D9SetTexture(NULL, 0);
RwD3D9SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
RwD3D9SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
RwD3D9SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
RwD3D9SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
}
RwD3D9SetPixelShader(NULL);
RwD3D9SetVertexShader(instanceData->vertexShader);
D3D9RenderDual(config->dualPassVehicle, resEntryHeader, instanceData);
}
void D3D9RenderDual(int dual, RxD3D9ResEntryHeader *resEntryHeader, RxD3D9InstanceData *instanceData)
{
RwBool hasAlpha;
int alphafunc, alpharef;
int zwrite;
// this also takes texture alpha into account
RwD3D9GetRenderState(D3DRS_ALPHABLENDENABLE, &hasAlpha);
RwRenderStateGet(rwRENDERSTATEZWRITEENABLE, &zwrite);
RwRenderStateGet(rwRENDERSTATEALPHATESTFUNCTION, &alphafunc);
if(dual && hasAlpha && zwrite){
RwRenderStateGet(rwRENDERSTATEALPHATESTFUNCTIONREF, &alpharef);
RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, (void*)config->zwriteThreshold);
RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTION, (void*)rwALPHATESTFUNCTIONGREATEREQUAL);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
D3D9Render(resEntryHeader, instanceData);
RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTION, (void*)rwALPHATESTFUNCTIONLESS);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
D3D9Render(resEntryHeader, instanceData);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)zwrite);
RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTIONREF, (void*)alpharef);
RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTION, (void*)alphafunc);
}else if(!zwrite){
RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTION, (void*)rwALPHATESTFUNCTIONALWAYS);
D3D9Render(resEntryHeader, instanceData);
RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTION, (void*)alphafunc);
}else
D3D9Render(resEntryHeader, instanceData);
}
TO DO
- 需要找出相关的rwRENDER*状态的常数
- Radiosity Simulation不准确,目前用Shader实现,RW引擎相关函数:
// 0x702080
void CPostEffects::Radiosity(int intensityLimit, int filterPasses, int renderPasses, int intensity) {
plugin::Call<0x702080>();
}
// 0x702F00
void CPostEffects::DarknessFilter(int32 a1) {
plugin::Call<0x702F00, int32>(a1);
}