#include #include #include #include #define WITH_D3D #include "../rwbase.h" #include "../rwplg.h" #include "../rwpipeline.h" #include "../rwobjects.h" #include "../rwengine.h" #include "../rwrender.h" #include "rwd3d.h" #include "rwd3d9.h" namespace rw { namespace d3d9 { using namespace d3d; #ifndef RW_D3D9 void defaultRenderCB(Atomic*, InstanceDataHeader*) {} void defaultRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header) {} #else void drawInst(d3d9::InstanceDataHeader *header, d3d9::InstanceData *inst) { d3d::flushCache(); d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)header->primType, inst->baseIndex, 0, inst->numVertices, inst->startIndex, inst->numPrimitives); } // Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer void drawInst_GSemu(d3d9::InstanceDataHeader *header, InstanceData *inst) { uint32 hasAlpha; int alphafunc; int zwrite; d3d::getRenderState(D3DRS_ALPHABLENDENABLE, &hasAlpha); if(hasAlpha){ zwrite = rw::GetRenderState(rw::ZWRITEENABLE); alphafunc = rw::GetRenderState(rw::ALPHATESTFUNC); if(zwrite){ SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL); drawInst(header, inst); SetRenderState(rw::ALPHATESTFUNC, rw::ALPHALESS); SetRenderState(rw::ZWRITEENABLE, 0); drawInst(header, inst); SetRenderState(rw::ZWRITEENABLE, 1); SetRenderState(rw::ALPHATESTFUNC, alphafunc); }else{ SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAALWAYS); drawInst(header, inst); SetRenderState(rw::ALPHATESTFUNC, alphafunc); } }else drawInst(header, inst); } void defaultRenderCB_Fix(Atomic *atomic, InstanceDataHeader *header) { RawMatrix world; Geometry *geo = atomic->geometry; int lighting = !!(geo->flags & rw::Geometry::LIGHT); if(lighting) d3d::lightingCB_Fix(atomic); d3d::setRenderState(D3DRS_LIGHTING, lighting); Frame *f = atomic->getFrame(); convMatrix(&world, f->getLTM()); d3ddevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&world); setStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride); setIndices((IDirect3DIndexBuffer9*)header->indexBuffer); setVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration); InstanceData *inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ SetRenderState(VERTEXALPHA, inst->vertexAlpha || inst->material->color.alpha != 255); const static rw::RGBA white = { 255, 255, 255, 255 }; d3d::setMaterial(inst->material->surfaceProps, white); d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL); if(geo->flags & Geometry::PRELIT) d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1); else d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL); d3d::setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, inst->vertexAlpha ? D3DMCS_COLOR1 : D3DMCS_MATERIAL); if(inst->material->texture){ // Texture d3d::setTexture(0, inst->material->texture); d3d::setTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); d3d::setTextureStageState(0, D3DTSS_COLORARG1, D3DTA_CURRENT); d3d::setTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); d3d::setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); d3d::setTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CURRENT); d3d::setTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); }else{ d3d::setTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); d3d::setTextureStageState(0, D3DTSS_COLORARG1, D3DTA_CURRENT); d3d::setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); d3d::setTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CURRENT); } // Material colour const rw::RGBA *col = &inst->material->color; d3d::setTextureStageState(1, D3DTSS_CONSTANT, D3DCOLOR_ARGB(col->alpha,col->red,col->green,col->blue)); d3d::setTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); d3d::setTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); d3d::setTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CONSTANT); d3d::setTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE); d3d::setTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT); d3d::setTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CONSTANT); drawInst(header, inst); inst++; } d3d::setTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); d3d::setTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); } void defaultRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header) { int vsBits; setStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride); setIndices((IDirect3DIndexBuffer9*)header->indexBuffer); setVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration); vsBits = lightingCB_Shader(atomic); uploadMatrices(atomic->getFrame()->getLTM()); d3ddevice->SetVertexShaderConstantF(VSLOC_fogData, (float*)&d3dShaderState.fogData, 1); d3ddevice->SetPixelShaderConstantF(PSLOC_fogColor, (float*)&d3dShaderState.fogColor, 1); // Pick a shader if((vsBits & VSLIGHT_MASK) == 0) setVertexShader(default_amb_VS); else if((vsBits & VSLIGHT_MASK) == VSLIGHT_DIRECT) setVertexShader(default_amb_dir_VS); else setVertexShader(default_all_VS); float surfProps[4]; surfProps[3] = atomic->geometry->flags&Geometry::PRELIT ? 1.0f : 0.0f; InstanceData *inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ Material *m = inst->material; SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 255); rw::RGBAf col; convColor(&col, &inst->material->color); d3ddevice->SetVertexShaderConstantF(VSLOC_matColor, (float*)&col, 1); surfProps[0] = m->surfaceProps.ambient; surfProps[1] = m->surfaceProps.specular; surfProps[2] = m->surfaceProps.diffuse; d3ddevice->SetVertexShaderConstantF(VSLOC_surfProps, surfProps, 1); if(inst->material->texture){ d3d::setTexture(0, m->texture); setPixelShader(default_tex_PS); }else setPixelShader(default_PS); drawInst(header, inst); inst++; } } #endif } }