From 847962910f0bff071f3bf07c9abb87764fb6cac3 Mon Sep 17 00:00:00 2001 From: claude-bot Date: Mon, 13 Jul 2026 12:40:03 +0000 Subject: Import aap/librw @ master Snapshot for re3/reVC vendoring, per @lzcnt. Source: https://github.com/aap/librw (master). --- src/d3d/d3drender.cpp | 424 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 424 insertions(+) create mode 100644 src/d3d/d3drender.cpp (limited to 'src/d3d/d3drender.cpp') diff --git a/src/d3d/d3drender.cpp b/src/d3d/d3drender.cpp new file mode 100644 index 0000000..d135d87 --- /dev/null +++ b/src/d3d/d3drender.cpp @@ -0,0 +1,424 @@ +#include +#include +#include +#include + +#define WITH_D3D +#include "../rwbase.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "rwd3d.h" + +namespace rw { +namespace d3d { + +#ifdef RW_D3D9 +IDirect3DDevice9 *d3ddevice = nil; + +#define MAX_LIGHTS 8 + + +#define VS_NAME g_vs20_main +#define PS_NAME g_ps20_main +void *default_amb_VS; +void *default_amb_dir_VS; +void *default_all_VS; +void *default_PS; +void *default_tex_PS; +void *im2d_VS; +void *im2d_PS; +void *im2d_tex_PS; + + +void +createDefaultShaders(void) +{ + { + static +#include "shaders/default_amb_VS.h" + default_amb_VS = createVertexShader((void*)VS_NAME); + assert(default_amb_VS); + } + { + static +#include "shaders/default_amb_dir_VS.h" + default_amb_dir_VS = createVertexShader((void*)VS_NAME); + assert(default_amb_dir_VS); + } + { + static +#include "shaders/default_all_VS.h" + default_all_VS = createVertexShader((void*)VS_NAME); + assert(default_all_VS); + } + + { + static +#include "shaders/default_PS.h" + default_PS = createPixelShader((void*)PS_NAME); + assert(default_PS); + } + { + static +#include "shaders/default_tex_PS.h" + default_tex_PS = createPixelShader((void*)PS_NAME); + assert(default_tex_PS); + } + + { + static +#include "shaders/im2d_VS.h" + im2d_VS = createVertexShader((void*)VS_NAME); + assert(im2d_VS); + } + { + static +#include "shaders/im2d_PS.h" + im2d_PS = createPixelShader((void*)PS_NAME); + assert(im2d_PS); + } + { + static +#include "shaders/im2d_tex_PS.h" + im2d_tex_PS = createPixelShader((void*)PS_NAME); + assert(im2d_tex_PS); + } +} + +void +destroyDefaultShaders(void) +{ + destroyVertexShader(default_amb_VS); + default_amb_VS = nil; + destroyVertexShader(default_amb_dir_VS); + default_amb_dir_VS = nil; + destroyVertexShader(default_all_VS); + default_all_VS = nil; + + destroyPixelShader(default_PS); + default_PS = nil; + destroyPixelShader(default_tex_PS); + default_tex_PS = nil; + + destroyVertexShader(im2d_VS); + im2d_VS = nil; + destroyPixelShader(im2d_PS); + im2d_PS = nil; + destroyPixelShader(im2d_tex_PS); + im2d_tex_PS = nil; +} + + +void +lightingCB_Fix(Atomic *atomic) +{ + WorldLights lightData; + Light *directionals[8]; + Light *locals[8]; + lightData.directionals = directionals; + lightData.numDirectionals = 8; + lightData.locals = locals; + lightData.numLocals = 8; + + ((World*)engine->currentWorld)->enumerateLights(atomic, &lightData); + + int i, n; + RGBA amb; + D3DLIGHT9 light; + light.Type = D3DLIGHT_DIRECTIONAL; + //light.Diffuse = { 0.8f, 0.8f, 0.8f, 1.0f }; + light.Specular = { 0.0f, 0.0f, 0.0f, 0.0f }; + light.Ambient = { 0.0f, 0.0f, 0.0f, 0.0f }; + light.Position = { 0.0f, 0.0f, 0.0f }; + //light.Direction = { 0.0f, 0.0f, -1.0f }; + light.Range = 0.0f; + light.Falloff = 0.0f; + light.Attenuation0 = 0.0f; + light.Attenuation1 = 0.0f; + light.Attenuation2 = 0.0f; + light.Theta = 0.0f; + light.Phi = 0.0f; + + convColor(&amb, &lightData.ambient); + d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_RGBA(amb.red, amb.green, amb.blue, amb.alpha)); + + n = 0; + for(i = 0; i < lightData.numDirectionals; i++){ + if(n >= MAX_LIGHTS) + return; + Light *l = lightData.directionals[i]; + light.Type = D3DLIGHT_DIRECTIONAL; + light.Diffuse = *(D3DCOLORVALUE*)&l->color; + light.Direction = *(D3DVECTOR*)&l->getFrame()->getLTM()->at; + d3ddevice->SetLight(n, &light); + d3ddevice->LightEnable(n, TRUE); + n++; + } + + for(i = 0; i < lightData.numLocals; i++){ + if(n >= MAX_LIGHTS) + return; + Light *l = lightData.locals[i]; + switch(l->getType()){ + case Light::POINT: + light.Type = D3DLIGHT_POINT; + light.Diffuse = *(D3DCOLORVALUE*)&l->color; + light.Position = *(D3DVECTOR*)&l->getFrame()->getLTM()->pos; + light.Direction.x = 0.0f; + light.Direction.y = 0.0f; + light.Direction.z = 0.0f; + light.Range = l->radius; + light.Falloff = 1.0f; + light.Attenuation0 = 1.0f; + light.Attenuation1 = 0.0f/l->radius; + light.Attenuation2 = 5.0f/(l->radius*l->radius); + d3ddevice->SetLight(n, &light); + d3ddevice->LightEnable(n, TRUE); + n++; + break; + + case Light::SPOT: + light.Type = D3DLIGHT_SPOT; + light.Diffuse = *(D3DCOLORVALUE*)&l->color; + light.Position = *(D3DVECTOR*)&l->getFrame()->getLTM()->pos; + light.Direction = *(D3DVECTOR*)&l->getFrame()->getLTM()->at; + light.Range = l->radius; + light.Falloff = 1.0f; + light.Attenuation0 = 1.0f; + light.Attenuation1 = 0.0f/l->radius; + light.Attenuation2 = 5.0f/(l->radius*l->radius); + light.Theta = l->getAngle()*2.0f; + light.Phi = light.Theta; + d3ddevice->SetLight(n, &light); + d3ddevice->LightEnable(n, TRUE); + n++; + break; + + case Light::SOFTSPOT: + light.Type = D3DLIGHT_SPOT; + light.Diffuse = *(D3DCOLORVALUE*)&l->color; + light.Position = *(D3DVECTOR*)&l->getFrame()->getLTM()->pos; + light.Direction = *(D3DVECTOR*)&l->getFrame()->getLTM()->at; + light.Range = l->radius; + light.Falloff = 1.0f; + light.Attenuation0 = 1.0f; + light.Attenuation1 = 0.0f/l->radius; + light.Attenuation2 = 5.0f/(l->radius*l->radius); + light.Theta = 0.0f; + light.Phi = l->getAngle()*2.0f; + d3ddevice->SetLight(n, &light); + d3ddevice->LightEnable(n, TRUE); + n++; + break; + } + } + + for(; n < MAX_LIGHTS; n++) + d3ddevice->LightEnable(n, FALSE); +} + + +struct LightVS +{ + V3d color; float param0; + V3d position; float param1; + V3d direction; float param2; +}; + +void +setAmbient(const RGBAf &color) +{ + if(!equal(d3dShaderState.ambient, color)){ + d3dShaderState.ambient = color; + d3ddevice->SetVertexShaderConstantF(VSLOC_ambLight, (float*)&color, 1); + } +} + +void +setNumLights(int numDir, int numPoint, int numSpot) +{ + static int32 numLights[4*3]; + if(d3dShaderState.numDir != numDir || + d3dShaderState.numPoint != numPoint || + d3dShaderState.numSpot != numSpot){ + numLights[0] = d3dShaderState.numDir = numDir; + numLights[4] = d3dShaderState.numPoint = numPoint; + numLights[8] = d3dShaderState.numSpot = numSpot; + d3ddevice->SetVertexShaderConstantI(VSLOC_numLights, numLights, 3); + } +} + +int32 +uploadLights(WorldLights *lightData) +{ + int i; + int bits = 0; + float32 firstLight[4]; + firstLight[0] = 0; // directional + firstLight[1] = 0; // point + firstLight[2] = 0; // spot + firstLight[3] = 0; + + if(lightData->numAmbients) + bits |= VSLIGHT_AMBIENT; + + LightVS directionals[8]; + LightVS points[8]; + LightVS spots[8]; + for(i = 0; i < lightData->numDirectionals; i++){ + Light *l = lightData->directionals[i]; + directionals[i].color.x = l->color.red; + directionals[i].color.y = l->color.green; + directionals[i].color.z = l->color.blue; + directionals[i].direction = l->getFrame()->getLTM()->at; + bits |= VSLIGHT_DIRECT; + } + + int np = 0; + int ns = 0; + for(i = 0; i < lightData->numLocals; i++){ + Light *l = lightData->locals[i]; + + switch(l->getType()){ + case Light::POINT: + points[np].color.x = l->color.red; + points[np].color.y = l->color.green; + points[np].color.z = l->color.blue; + points[np].param0 = l->radius; + points[np].position = l->getFrame()->getLTM()->pos; + np++; + bits |= VSLIGHT_POINT; + break; + case Light::SPOT: + case Light::SOFTSPOT: + spots[ns].color.x = l->color.red; + spots[ns].color.y = l->color.green; + spots[ns].color.z = l->color.blue; + spots[ns].param0 = l->radius; + spots[ns].position = l->getFrame()->getLTM()->pos; + spots[ns].direction = l->getFrame()->getLTM()->at; + spots[ns].param1 = l->minusCosAngle; + // lower bound of falloff + if(l->getType() == Light::SOFTSPOT) + spots[ns].param2 = 0.0f; + else + spots[ns].param2 = 1.0f; + bits |= VSLIGHT_SPOT; + ns++; + break; + } + } + + firstLight[0] = 0; + int numDir = lightData->numDirectionals; + firstLight[1] = numDir + firstLight[0]; + int numPoint = np; + firstLight[2] = numPoint + firstLight[1]; + int numSpot = ns; + + setNumLights(numDir, numPoint, numSpot); + if(d3dShaderState.lightOffset[0] != firstLight[0] || + d3dShaderState.lightOffset[1] != firstLight[1] || + d3dShaderState.lightOffset[2] != firstLight[2]){ + d3dShaderState.lightOffset[0] = firstLight[0]; + d3dShaderState.lightOffset[1] = firstLight[1]; + d3dShaderState.lightOffset[2] = firstLight[2]; + d3ddevice->SetVertexShaderConstantF(VSLOC_lightOffset, firstLight, 1); + } + + int32 off = VSLOC_lights; + if(numDir) + d3ddevice->SetVertexShaderConstantF(off, (float*)&directionals, numDir*3); + off += numDir*3; + + if(numPoint) + d3ddevice->SetVertexShaderConstantF(off, (float*)&points, numPoint*3); + off += numPoint*3; + + if(numSpot) + d3ddevice->SetVertexShaderConstantF(off, (float*)&spots, numSpot*3); + + return bits; +} + +int32 +lightingCB_Shader(Atomic *atomic) +{ + WorldLights lightData; + Light *directionals[8]; + Light *locals[8]; + lightData.directionals = directionals; + lightData.numDirectionals = 8; + lightData.locals = locals; + lightData.numLocals = 8; + + if(atomic->geometry->flags & rw::Geometry::LIGHT){ + ((World*)engine->currentWorld)->enumerateLights(atomic, &lightData); + setAmbient(lightData.ambient); + return uploadLights(&lightData); + }else{ + static const RGBAf black = { 0.0f, 0.0f, 0.0f, 0.0f }; + setAmbient(black); + setNumLights(0, 0, 0); + return 0; + } +} + +int32 +lightingCB_Shader(void) +{ + WorldLights lightData; + Light *directionals[8]; + Light *locals[8]; + lightData.directionals = directionals; + lightData.numDirectionals = 8; + lightData.locals = locals; + lightData.numLocals = 8; + + ((World*)engine->currentWorld)->enumerateLights(&lightData); + setAmbient(lightData.ambient); + return uploadLights(&lightData); +} + +static RawMatrix identityXform = { + { 1.0f, 0.0f, 0.0f }, 0.0f, + { 0.0f, 1.0f, 0.0f }, 0.0f, + { 0.0f, 0.0f, 1.0f }, 0.0f, + { 0.0f, 0.0f, 0.0f }, 1.0f +}; + +void +uploadMatrices(void) +{ + RawMatrix combined; + Camera *cam = engine->currentCamera; + d3ddevice->SetVertexShaderConstantF(VSLOC_world, (float*)&identityXform, 4); + d3ddevice->SetVertexShaderConstantF(VSLOC_normal, (float*)&identityXform, 4); + + RawMatrix::mult(&combined, &cam->devView, &cam->devProj); + d3ddevice->SetVertexShaderConstantF(VSLOC_combined, (float*)&combined, 4); +} + +void +uploadMatrices(Matrix *worldMat) +{ + RawMatrix combined, world, worldview; + Camera *cam = engine->currentCamera; + convMatrix(&world, worldMat); + d3ddevice->SetVertexShaderConstantF(VSLOC_world, (float*)&world, 4); + // TODO: inverse transpose + d3ddevice->SetVertexShaderConstantF(VSLOC_normal, (float*)&world, 4); + + RawMatrix::mult(&worldview, &world, &cam->devView); + RawMatrix::mult(&combined, &worldview, &cam->devProj); + d3ddevice->SetVertexShaderConstantF(VSLOC_combined, (float*)&combined, 4); +} + + + +#endif + +} +} -- cgit v1.2.3