2020-04-30 17:54:38 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
2016-06-27 21:59:35 +02:00
|
|
|
|
2020-04-20 15:42:07 +02:00
|
|
|
#define WITH_D3D
|
2016-06-27 21:59:35 +02:00
|
|
|
#include "../rwbase.h"
|
|
|
|
#include "../rwerror.h"
|
|
|
|
#include "../rwplg.h"
|
|
|
|
#include "../rwpipeline.h"
|
|
|
|
#include "../rwobjects.h"
|
2016-07-11 20:27:21 +02:00
|
|
|
#include "../rwanim.h"
|
2016-06-27 21:59:35 +02:00
|
|
|
#include "../rwengine.h"
|
2020-04-20 15:42:07 +02:00
|
|
|
#include "../rwrender.h"
|
2016-06-27 21:59:35 +02:00
|
|
|
#include "../rwplugins.h"
|
|
|
|
#include "rwd3d.h"
|
|
|
|
#include "rwd3d9.h"
|
|
|
|
|
|
|
|
namespace rw {
|
|
|
|
namespace d3d9 {
|
|
|
|
using namespace d3d;
|
|
|
|
|
2020-04-21 01:26:33 +02:00
|
|
|
#ifndef RW_D3D9
|
|
|
|
void matfxRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header) {}
|
|
|
|
#else
|
|
|
|
|
2020-04-20 15:42:07 +02:00
|
|
|
static void *matfx_env_amb_VS;
|
|
|
|
static void *matfx_env_amb_dir_VS;
|
|
|
|
static void *matfx_env_all_VS;
|
|
|
|
static void *matfx_env_PS;
|
|
|
|
static void *matfx_env_tex_PS;
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
VSLOC_texMat = VSLOC_afterLights,
|
|
|
|
|
2020-04-20 19:18:28 +02:00
|
|
|
PSLOC_shininess = 1,
|
|
|
|
PSLOC_colorClamp = 2
|
2020-04-20 15:42:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
matfxRender_Default(InstanceDataHeader *header, InstanceData *inst, int32 lightBits)
|
|
|
|
{
|
|
|
|
Material *m = inst->material;
|
|
|
|
|
|
|
|
// Pick a shader
|
|
|
|
if((lightBits & VSLIGHT_MASK) == 0)
|
|
|
|
setVertexShader(default_amb_VS);
|
|
|
|
else if((lightBits & VSLIGHT_MASK) == VSLIGHT_DIRECT)
|
|
|
|
setVertexShader(default_amb_dir_VS);
|
|
|
|
else
|
|
|
|
setVertexShader(default_all_VS);
|
|
|
|
|
|
|
|
SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 255);
|
|
|
|
|
|
|
|
if(inst->material->texture){
|
|
|
|
d3d::setTexture(0, m->texture);
|
2020-04-20 19:18:28 +02:00
|
|
|
setPixelShader(default_tex_PS);
|
2020-04-20 15:42:07 +02:00
|
|
|
}else
|
2020-04-20 19:18:28 +02:00
|
|
|
setPixelShader(default_PS);
|
2020-04-20 15:42:07 +02:00
|
|
|
|
|
|
|
drawInst(header, inst);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Frame *lastEnvFrame;
|
|
|
|
|
|
|
|
static RawMatrix normal2texcoord = {
|
|
|
|
{ 0.5f, 0.0f, 0.0f }, 0.0f,
|
|
|
|
{ 0.0f, -0.5f, 0.0f }, 0.0f,
|
|
|
|
{ 0.0f, 0.0f, 1.0f }, 0.0f,
|
|
|
|
{ 0.5f, 0.5f, 0.0f }, 1.0f
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
uploadEnvMatrix(Frame *frame)
|
|
|
|
{
|
|
|
|
Matrix invMat;
|
|
|
|
if(frame == nil)
|
|
|
|
frame = engine->currentCamera->getFrame();
|
|
|
|
|
|
|
|
// cache the matrix across multiple meshes
|
|
|
|
if(frame == lastEnvFrame)
|
|
|
|
return;
|
|
|
|
lastEnvFrame = frame;
|
|
|
|
|
|
|
|
RawMatrix envMtx, invMtx;
|
|
|
|
Matrix::invert(&invMat, frame->getLTM());
|
|
|
|
convMatrix(&invMtx, &invMat);
|
2020-05-15 13:34:19 +02:00
|
|
|
invMtx.pos.set(0.0f, 0.0f, 0.0f);
|
2020-04-20 15:42:07 +02:00
|
|
|
RawMatrix::mult(&envMtx, &invMtx, &normal2texcoord);
|
|
|
|
d3ddevice->SetVertexShaderConstantF(VSLOC_texMat, (float*)&envMtx, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
matfxRender_EnvMap(InstanceDataHeader *header, InstanceData *inst, int32 lightBits, MatFX::Env *env)
|
|
|
|
{
|
|
|
|
Material *m = inst->material;
|
|
|
|
|
|
|
|
if(env->tex == nil || env->coefficient == 0.0f){
|
|
|
|
matfxRender_Default(header, inst, lightBits);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
d3d::setTexture(1, env->tex);
|
|
|
|
uploadEnvMatrix(env->frame);
|
|
|
|
|
|
|
|
SetRenderState(SRCBLEND, BLENDONE);
|
|
|
|
|
|
|
|
static float zero[4];
|
|
|
|
static float one[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
2020-05-27 10:26:28 +02:00
|
|
|
struct {
|
|
|
|
float shininess;
|
|
|
|
float disableFBA;
|
|
|
|
float unused[2];
|
|
|
|
} fxparams;
|
|
|
|
fxparams.shininess = env->coefficient;
|
|
|
|
fxparams.disableFBA = env->fbAlpha ? 0.0f : 1.0f;
|
|
|
|
d3ddevice->SetPixelShaderConstantF(PSLOC_shininess, (float*)&fxparams, 1);
|
2020-04-20 15:42:07 +02:00
|
|
|
// This clamps the vertex color below. With it we can achieve both PC and PS2 style matfx
|
|
|
|
if(MatFX::modulateEnvMap)
|
|
|
|
d3ddevice->SetPixelShaderConstantF(PSLOC_colorClamp, zero, 1);
|
|
|
|
else
|
|
|
|
d3ddevice->SetPixelShaderConstantF(PSLOC_colorClamp, one, 1);
|
|
|
|
|
|
|
|
// Pick a shader
|
|
|
|
if((lightBits & VSLIGHT_MASK) == 0)
|
|
|
|
setVertexShader(matfx_env_amb_VS);
|
|
|
|
else if((lightBits & VSLIGHT_MASK) == VSLIGHT_DIRECT)
|
|
|
|
setVertexShader(matfx_env_amb_dir_VS);
|
|
|
|
else
|
|
|
|
setVertexShader(matfx_env_all_VS);
|
|
|
|
|
|
|
|
bool32 texAlpha = PLUGINOFFSET(D3dRaster, env->tex->raster, nativeRasterOffset)->hasAlpha;
|
|
|
|
|
|
|
|
if(inst->material->texture){
|
|
|
|
d3d::setTexture(0, m->texture);
|
|
|
|
setPixelShader(matfx_env_tex_PS);
|
|
|
|
}else
|
|
|
|
setPixelShader(matfx_env_PS);
|
|
|
|
|
|
|
|
SetRenderState(VERTEXALPHA, texAlpha || inst->vertexAlpha || m->color.alpha != 255);
|
|
|
|
|
|
|
|
drawInst(header, inst);
|
|
|
|
|
|
|
|
SetRenderState(SRCBLEND, BLENDSRCALPHA);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
matfxRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header)
|
|
|
|
{
|
|
|
|
int vsBits;
|
2020-04-24 19:06:11 +02:00
|
|
|
setStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer,
|
2020-04-20 15:42:07 +02:00
|
|
|
0, header->vertexStream[0].stride);
|
2020-04-24 19:06:11 +02:00
|
|
|
setIndices((IDirect3DIndexBuffer9*)header->indexBuffer);
|
|
|
|
setVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration);
|
2020-04-20 15:42:07 +02:00
|
|
|
|
|
|
|
lastEnvFrame = nil;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2020-04-20 15:42:07 +02:00
|
|
|
bool normals = !!(atomic->geometry->flags & Geometry::NORMALS);
|
|
|
|
|
|
|
|
float surfProps[4];
|
2020-04-26 19:33:43 +02:00
|
|
|
surfProps[3] = 0.0f;
|
2020-04-20 15:42:07 +02:00
|
|
|
|
|
|
|
InstanceData *inst = header->inst;
|
|
|
|
for(uint32 i = 0; i < header->numMeshes; i++){
|
|
|
|
Material *m = inst->material;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
MatFX *matfx = MatFX::get(m);
|
|
|
|
if(matfx == nil)
|
|
|
|
matfxRender_Default(header, inst, vsBits);
|
|
|
|
else switch(matfx->type){
|
|
|
|
case MatFX::ENVMAP:
|
|
|
|
if(normals)
|
|
|
|
matfxRender_EnvMap(header, inst, vsBits, &matfx->fx[0].env);
|
|
|
|
else
|
|
|
|
matfxRender_Default(header, inst, vsBits);
|
|
|
|
break;
|
|
|
|
case MatFX::NOTHING:
|
|
|
|
case MatFX::BUMPMAP:
|
|
|
|
case MatFX::BUMPENVMAP:
|
|
|
|
case MatFX::DUAL:
|
|
|
|
case MatFX::UVTRANSFORM:
|
|
|
|
case MatFX::DUALUVTRANSFORM:
|
|
|
|
// not supported yet
|
|
|
|
matfxRender_Default(header, inst, vsBits);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
inst++;
|
|
|
|
}
|
|
|
|
d3d::setTexture(1, nil);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define VS_NAME g_vs20_main
|
|
|
|
#define PS_NAME g_ps20_main
|
|
|
|
|
|
|
|
void
|
|
|
|
createMatFXShaders(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
static
|
|
|
|
#include "shaders/matfx_env_amb_VS.h"
|
|
|
|
matfx_env_amb_VS = createVertexShader((void*)VS_NAME);
|
|
|
|
assert(matfx_env_amb_VS);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
static
|
|
|
|
#include "shaders/matfx_env_amb_dir_VS.h"
|
|
|
|
matfx_env_amb_dir_VS = createVertexShader((void*)VS_NAME);
|
|
|
|
assert(matfx_env_amb_dir_VS);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
static
|
|
|
|
#include "shaders/matfx_env_all_VS.h"
|
|
|
|
matfx_env_all_VS = createVertexShader((void*)VS_NAME);
|
|
|
|
assert(matfx_env_all_VS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
static
|
|
|
|
#include "shaders/matfx_env_PS.h"
|
|
|
|
matfx_env_PS = createPixelShader((void*)PS_NAME);
|
|
|
|
assert(matfx_env_PS);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
static
|
|
|
|
#include "shaders/matfx_env_tex_PS.h"
|
|
|
|
matfx_env_tex_PS = createPixelShader((void*)PS_NAME);
|
|
|
|
assert(matfx_env_tex_PS);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
destroyMatFXShaders(void)
|
|
|
|
{
|
2020-04-20 20:37:59 +02:00
|
|
|
destroyVertexShader(matfx_env_amb_VS);
|
|
|
|
matfx_env_amb_VS = nil;
|
|
|
|
|
|
|
|
destroyVertexShader(matfx_env_amb_dir_VS);
|
|
|
|
matfx_env_amb_dir_VS = nil;
|
|
|
|
|
|
|
|
destroyVertexShader(matfx_env_all_VS);
|
|
|
|
matfx_env_all_VS = nil;
|
|
|
|
|
|
|
|
|
|
|
|
destroyPixelShader(matfx_env_PS);
|
2020-04-20 15:42:07 +02:00
|
|
|
matfx_env_PS = nil;
|
|
|
|
|
2020-04-20 20:37:59 +02:00
|
|
|
destroyPixelShader(matfx_env_tex_PS);
|
2020-04-20 15:42:07 +02:00
|
|
|
matfx_env_tex_PS = nil;
|
|
|
|
}
|
|
|
|
|
2020-04-21 01:26:33 +02:00
|
|
|
#endif
|
|
|
|
|
2016-06-27 21:59:35 +02:00
|
|
|
static void*
|
|
|
|
matfxOpen(void *o, int32, int32)
|
|
|
|
{
|
2020-04-21 01:26:33 +02:00
|
|
|
#ifdef RW_D3D9
|
2020-04-20 15:42:07 +02:00
|
|
|
createMatFXShaders();
|
2020-04-21 01:26:33 +02:00
|
|
|
#endif
|
2020-04-20 15:42:07 +02:00
|
|
|
|
2016-06-27 21:59:35 +02:00
|
|
|
matFXGlobals.pipelines[PLATFORM_D3D9] = makeMatFXPipeline();
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
matfxClose(void *o, int32, int32)
|
|
|
|
{
|
2020-04-21 01:26:33 +02:00
|
|
|
#ifdef RW_D3D9
|
2020-04-20 15:42:07 +02:00
|
|
|
destroyMatFXShaders();
|
2020-04-21 01:26:33 +02:00
|
|
|
#endif
|
2020-04-20 15:42:07 +02:00
|
|
|
|
2016-06-27 21:59:35 +02:00
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
initMatFX(void)
|
|
|
|
{
|
|
|
|
Driver::registerPlugin(PLATFORM_D3D9, 0, ID_MATFX,
|
|
|
|
matfxOpen, matfxClose);
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjPipeline*
|
|
|
|
makeMatFXPipeline(void)
|
|
|
|
{
|
|
|
|
ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9);
|
|
|
|
pipe->instanceCB = defaultInstanceCB;
|
|
|
|
pipe->uninstanceCB = defaultUninstanceCB;
|
2020-04-20 15:42:07 +02:00
|
|
|
pipe->renderCB = matfxRenderCB_Shader;
|
2016-06-27 21:59:35 +02:00
|
|
|
pipe->pluginID = ID_MATFX;
|
|
|
|
pipe->pluginData = 0;
|
|
|
|
return pipe;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|