librw/src/d3d/d3dimmed.cpp
2020-04-26 20:14:52 +02:00

365 lines
9.0 KiB
C++

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#define WITH_D3D
#include "../rwbase.h"
#include "../rwplg.h"
#include "../rwrender.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#include "rwd3d.h"
#include "rwd3d9.h"
#include "rwd3dimpl.h"
namespace rw {
namespace d3d {
#ifdef RW_D3D9
// might want to tweak this
#define NUMINDICES 10000
#define NUMVERTICES 10000
static int primTypeMap[] = {
D3DPT_POINTLIST, // invalid
D3DPT_LINELIST,
D3DPT_LINESTRIP,
D3DPT_TRIANGLELIST,
D3DPT_TRIANGLESTRIP,
D3DPT_TRIANGLEFAN,
D3DPT_POINTLIST, // actually not supported!
};
static IDirect3DVertexDeclaration9 *im2ddecl;
static IDirect3DVertexBuffer9 *im2dvertbuf;
static IDirect3DIndexBuffer9 *im2dindbuf;
void *im2dOverridePS;
void
openIm2D(void)
{
D3DVERTEXELEMENT9 elements[4] = {
{ 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0 },
{ 0, offsetof(Im2DVertex, color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
{ 0, offsetof(Im2DVertex, u), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
D3DDECL_END()
};
assert(im2ddecl == nil);
im2ddecl = (IDirect3DVertexDeclaration9*)d3d9::createVertexDeclaration((d3d9::VertexElement*)elements);
assert(im2ddecl);
assert(im2dvertbuf == nil);
im2dvertbuf = (IDirect3DVertexBuffer9*)createVertexBuffer(NUMVERTICES*sizeof(Im2DVertex), 0, true);
assert(im2dvertbuf);
addDynamicVB(NUMVERTICES*sizeof(Im2DVertex), 0, &im2dvertbuf);
assert(im2dindbuf == nil);
im2dindbuf = (IDirect3DIndexBuffer9*)createIndexBuffer(NUMINDICES*sizeof(uint16), true);
assert(im2dindbuf);
addDynamicIB(NUMINDICES*sizeof(uint16), &im2dindbuf);
}
void
closeIm2D(void)
{
d3d9::destroyVertexDeclaration(im2ddecl);
im2ddecl = nil;
removeDynamicVB(&im2dvertbuf);
destroyVertexBuffer(im2dvertbuf);
im2dvertbuf = nil;
removeDynamicIB(&im2dindbuf);
destroyIndexBuffer(im2dindbuf);
im2dindbuf = nil;
}
static Im2DVertex tmpprimbuf[3];
void
im2DRenderLine(void *vertices, int32 numVertices, int32 vert1, int32 vert2)
{
Im2DVertex *verts = (Im2DVertex*)vertices;
tmpprimbuf[0] = verts[vert1];
tmpprimbuf[1] = verts[vert2];
im2DRenderPrimitive(PRIMTYPELINELIST, tmpprimbuf, 2);
}
void
im2DRenderTriangle(void *vertices, int32 numVertices, int32 vert1, int32 vert2, int32 vert3)
{
Im2DVertex *verts = (Im2DVertex*)vertices;
tmpprimbuf[0] = verts[vert1];
tmpprimbuf[1] = verts[vert2];
tmpprimbuf[2] = verts[vert3];
im2DRenderPrimitive(PRIMTYPETRILIST, tmpprimbuf, 3);
}
void
im2DRenderPrimitive(PrimitiveType primType, void *vertices, int32 numVertices)
{
if(numVertices > NUMVERTICES){
// TODO: error
return;
}
uint8 *lockedvertices = lockVertices(im2dvertbuf, 0, numVertices*sizeof(Im2DVertex), D3DLOCK_DISCARD);
memcpy(lockedvertices, vertices, numVertices*sizeof(Im2DVertex));
unlockVertices(im2dvertbuf);
setStreamSource(0, im2dvertbuf, 0, sizeof(Im2DVertex));
setVertexDeclaration(im2ddecl);
if(im2dOverridePS)
setPixelShader(im2dOverridePS);
else if(engine->device.getRenderState(TEXTURERASTER))
setPixelShader(im2d_tex_PS);
else
setPixelShader(im2d_PS);
d3d::flushCache();
uint32 primCount = 0;
switch(primType){
case PRIMTYPELINELIST:
primCount = numVertices/2;
break;
case PRIMTYPEPOLYLINE:
primCount = numVertices-1;
break;
case PRIMTYPETRILIST:
primCount = numVertices/3;
break;
case PRIMTYPETRISTRIP:
primCount = numVertices-2;
break;
case PRIMTYPETRIFAN:
primCount = numVertices-2;
break;
case PRIMTYPEPOINTLIST:
primCount = numVertices;
break;
}
d3ddevice->DrawPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0, primCount);
}
void
im2DRenderIndexedPrimitive(PrimitiveType primType,
void *vertices, int32 numVertices, void *indices, int32 numIndices)
{
if(numVertices > NUMVERTICES ||
numIndices > NUMINDICES){
// TODO: error
return;
}
uint16 *lockedindices = lockIndices(im2dindbuf, 0, numIndices*sizeof(uint16), D3DLOCK_DISCARD);
memcpy(lockedindices, indices, numIndices*sizeof(uint16));
unlockIndices(im2dindbuf);
uint8 *lockedvertices = lockVertices(im2dvertbuf, 0, numVertices*sizeof(Im2DVertex), D3DLOCK_DISCARD);
memcpy(lockedvertices, vertices, numVertices*sizeof(Im2DVertex));
unlockVertices(im2dvertbuf);
setStreamSource(0, im2dvertbuf, 0, sizeof(Im2DVertex));
setIndices(im2dindbuf);
setVertexDeclaration(im2ddecl);
if(im2dOverridePS)
setPixelShader(im2dOverridePS);
else if(engine->device.getRenderState(TEXTURERASTER))
setPixelShader(im2d_tex_PS);
else
setPixelShader(im2d_PS);
d3d::flushCache();
uint32 primCount = 0;
switch(primType){
case PRIMTYPELINELIST:
primCount = numIndices/2;
break;
case PRIMTYPEPOLYLINE:
primCount = numIndices-1;
break;
case PRIMTYPETRILIST:
primCount = numIndices/3;
break;
case PRIMTYPETRISTRIP:
primCount = numIndices-2;
break;
case PRIMTYPETRIFAN:
primCount = numIndices-2;
break;
case PRIMTYPEPOINTLIST:
primCount = numIndices;
break;
}
d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0,
0, numVertices,
0, primCount);
}
// Im3D
static IDirect3DVertexDeclaration9 *im3ddecl;
static IDirect3DVertexBuffer9 *im3dvertbuf;
static IDirect3DIndexBuffer9 *im3dindbuf;
static int32 num3DVertices;
void
openIm3D(void)
{
D3DVERTEXELEMENT9 elements[4] = {
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, offsetof(Im3DVertex, color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
{ 0, offsetof(Im3DVertex, u), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
D3DDECL_END()
};
assert(im3ddecl == nil);
im3ddecl = (IDirect3DVertexDeclaration9*)d3d9::createVertexDeclaration((d3d9::VertexElement*)elements);
assert(im3ddecl);
assert(im3dvertbuf == nil);
im3dvertbuf = (IDirect3DVertexBuffer9*)createVertexBuffer(NUMVERTICES*sizeof(Im3DVertex), 0, true);
assert(im3dvertbuf);
addDynamicVB(NUMVERTICES*sizeof(Im3DVertex), 0, &im3dvertbuf);
assert(im3dindbuf == nil);
im3dindbuf = (IDirect3DIndexBuffer9*)createIndexBuffer(NUMINDICES*sizeof(uint16), true);
assert(im3dindbuf);
addDynamicIB(NUMINDICES*sizeof(uint16), &im3dindbuf);
}
void
closeIm3D(void)
{
d3d9::destroyVertexDeclaration(im3ddecl);
im3ddecl = nil;
removeDynamicVB(&im3dvertbuf);
destroyVertexBuffer(im3dvertbuf);
im3dvertbuf = nil;
removeDynamicIB(&im3dindbuf);
destroyIndexBuffer(im3dindbuf);
im3dindbuf = nil;
}
void
im3DTransform(void *vertices, int32 numVertices, Matrix *world)
{
if(world == nil)
uploadMatrices();
else
uploadMatrices(world);
d3ddevice->SetVertexShaderConstantF(VSLOC_fogData, (float*)&d3dShaderState.fogData, 1);
d3ddevice->SetPixelShaderConstantF(PSLOC_fogColor, (float*)&d3dShaderState.fogColor, 1);
static float surfprops[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
static float white[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
d3ddevice->SetVertexShaderConstantF(VSLOC_surfProps, surfprops, 1);
d3ddevice->SetVertexShaderConstantF(VSLOC_matColor, white, 1);
uint8 *lockedvertices = lockVertices(im3dvertbuf, 0, numVertices*sizeof(Im3DVertex), D3DLOCK_DISCARD);
memcpy(lockedvertices, vertices, numVertices*sizeof(Im3DVertex));
unlockVertices(im3dvertbuf);
setStreamSource(0, im3dvertbuf, 0, sizeof(Im3DVertex));
setVertexDeclaration(im3ddecl);
setVertexShader(default_amb_VS);
num3DVertices = numVertices;
}
void
im3DRenderPrimitive(PrimitiveType primType)
{
if(engine->device.getRenderState(TEXTURERASTER))
setPixelShader(default_tex_PS);
else
setPixelShader(default_PS);
d3d::flushCache();
uint32 primCount = 0;
switch(primType){
case PRIMTYPELINELIST:
primCount = num3DVertices/2;
break;
case PRIMTYPEPOLYLINE:
primCount = num3DVertices-1;
break;
case PRIMTYPETRILIST:
primCount = num3DVertices/3;
break;
case PRIMTYPETRISTRIP:
primCount = num3DVertices-2;
break;
case PRIMTYPETRIFAN:
primCount = num3DVertices-2;
break;
case PRIMTYPEPOINTLIST:
primCount = num3DVertices;
break;
}
d3ddevice->DrawPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0, primCount);
}
void
im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices)
{
uint16 *lockedindices = lockIndices(im3dindbuf, 0, numIndices*sizeof(uint16), D3DLOCK_DISCARD);
memcpy(lockedindices, indices, numIndices*sizeof(uint16));
unlockIndices(im3dindbuf);
setIndices(im3dindbuf);
if(engine->device.getRenderState(TEXTURERASTER))
setPixelShader(default_tex_PS);
else
setPixelShader(default_PS);
d3d::flushCache();
uint32 primCount = 0;
switch(primType){
case PRIMTYPELINELIST:
primCount = numIndices/2;
break;
case PRIMTYPEPOLYLINE:
primCount = numIndices-1;
break;
case PRIMTYPETRILIST:
primCount = numIndices/3;
break;
case PRIMTYPETRISTRIP:
primCount = numIndices-2;
break;
case PRIMTYPETRIFAN:
primCount = numIndices-2;
break;
case PRIMTYPEPOINTLIST:
primCount = numIndices;
break;
}
d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0,
0, num3DVertices,
0, primCount);
}
void
im3DEnd(void)
{
}
#endif
}
}