librw/src/d3d/d3d9render.cpp

197 lines
6.2 KiB
C++
Raw Normal View History

2020-04-30 17:54:38 +02:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define WITH_D3D
#include "../rwbase.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
2017-08-09 10:57:32 +02:00
#include "../rwengine.h"
2018-01-03 18:02:02 +01:00
#include "../rwrender.h"
#include "rwd3d.h"
#include "rwd3d9.h"
namespace rw {
namespace d3d9 {
using namespace d3d;
#ifndef RW_D3D9
void defaultRenderCB(Atomic*, InstanceDataHeader*) {}
2020-04-21 01:26:33 +02:00
void defaultRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header) {}
#else
2018-01-09 23:09:26 +01:00
void
2020-04-25 12:16:04 +02:00
drawInst_simple(d3d9::InstanceDataHeader *header, d3d9::InstanceData *inst)
2018-01-09 23:09:26 +01:00
{
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;
2020-04-25 12:16:04 +02:00
int alphafunc, alpharef, gsalpharef;
2018-01-09 23:09:26 +01:00
int zwrite;
d3d::getRenderState(D3DRS_ALPHABLENDENABLE, &hasAlpha);
if(hasAlpha){
zwrite = rw::GetRenderState(rw::ZWRITEENABLE);
alphafunc = rw::GetRenderState(rw::ALPHATESTFUNC);
if(zwrite){
2020-04-25 12:16:04 +02:00
alpharef = rw::GetRenderState(rw::ALPHATESTREF);
gsalpharef = rw::GetRenderState(rw::GSALPHATESTREF);
2018-01-09 23:09:26 +01:00
SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL);
2020-04-25 12:16:04 +02:00
SetRenderState(rw::ALPHATESTREF, gsalpharef);
drawInst_simple(header, inst);
2018-01-09 23:09:26 +01:00
SetRenderState(rw::ALPHATESTFUNC, rw::ALPHALESS);
SetRenderState(rw::ZWRITEENABLE, 0);
2020-04-25 12:16:04 +02:00
drawInst_simple(header, inst);
2018-01-09 23:09:26 +01:00
SetRenderState(rw::ZWRITEENABLE, 1);
SetRenderState(rw::ALPHATESTFUNC, alphafunc);
2020-04-25 12:16:04 +02:00
SetRenderState(rw::ALPHATESTREF, alpharef);
2018-01-09 23:09:26 +01:00
}else{
SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAALWAYS);
2020-04-25 12:16:04 +02:00
drawInst_simple(header, inst);
2018-01-09 23:09:26 +01:00
SetRenderState(rw::ALPHATESTFUNC, alphafunc);
}
}else
2020-04-25 12:16:04 +02:00
drawInst_simple(header, inst);
}
void
drawInst(d3d9::InstanceDataHeader *header, d3d9::InstanceData *inst)
{
if(rw::GetRenderState(rw::GSALPHATEST))
drawInst_GSemu(header, inst);
else
drawInst_simple(header, inst);
2018-01-09 23:09:26 +01:00
}
void
defaultRenderCB_Fix(Atomic *atomic, InstanceDataHeader *header)
{
2017-08-04 19:54:03 +02:00
RawMatrix world;
2017-11-15 19:23:50 +01:00
Geometry *geo = atomic->geometry;
2017-08-04 19:54:03 +02:00
2017-11-15 19:23:50 +01:00
int lighting = !!(geo->flags & rw::Geometry::LIGHT);
if(lighting)
d3d::lightingCB_Fix(atomic);
2017-08-09 10:57:32 +02:00
2017-11-15 19:23:50 +01:00
d3d::setRenderState(D3DRS_LIGHTING, lighting);
2017-08-09 10:57:32 +02:00
Frame *f = atomic->getFrame();
2017-08-04 19:54:03 +02:00
convMatrix(&world, f->getLTM());
2017-08-09 10:57:32 +02:00
d3ddevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&world);
2020-04-26 19:33:43 +02:00
setStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride);
setIndices(header->indexBuffer);
setVertexDeclaration(header->vertexDeclaration);
InstanceData *inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
2018-01-03 18:02:02 +01:00
SetRenderState(VERTEXALPHA, inst->vertexAlpha || inst->material->color.alpha != 255);
2018-01-13 18:45:35 +01:00
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);
}
2018-01-03 18:02:02 +01:00
// 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);
2018-01-09 23:09:26 +01:00
drawInst(header, inst);
inst++;
}
2018-01-03 18:02:02 +01:00
d3d::setTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
d3d::setTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
}
void
defaultRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header)
{
int vsBits;
2020-04-26 19:33:43 +02:00
setStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride);
setIndices(header->indexBuffer);
setVertexDeclaration(header->vertexDeclaration);
vsBits = lightingCB_Shader(atomic);
uploadMatrices(atomic->getFrame()->getLTM());
2020-04-20 19:18:28 +02:00
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];
2020-04-26 19:33:43 +02:00
surfProps[3] = 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);
2020-04-20 19:18:28 +02:00
setPixelShader(default_tex_PS);
}else
2020-04-20 19:18:28 +02:00
setPixelShader(default_PS);
drawInst(header, inst);
inst++;
}
}
#endif
}
}