implemented im2d for d3d, fun little software T&L renderer

This commit is contained in:
aap 2017-08-27 17:13:10 +02:00
parent ea48c140c1
commit c53d29b1cf
24 changed files with 618 additions and 142 deletions

View File

@ -17,10 +17,8 @@ InitRW(void)
return false;
if(!rw::Engine::start(&engineStartParams))
return false;
rw::engine->loadTextures = 1;
rw::TexDictionary::setCurrent(rw::TexDictionary::create());
rw::Image::setSearchPath(".");
rw::Image::setSearchPath("./");
return true;
}

View File

@ -127,11 +127,20 @@ MakeWindow(HINSTANCE instance, int width, int height, const char *title)
return 0;
}
int offx = 100;
int offy = 100;
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = width;
rect.bottom = height;
DWORD style = WS_OVERLAPPEDWINDOW;
AdjustWindowRect(&rect, style, FALSE);
rect.right += -rect.left;
rect.bottom += -rect.top;
HWND win;
win = CreateWindow("librwD3D9", title,
WS_BORDER | WS_CAPTION | WS_SYSMENU |
WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
0, 0, width, height, 0, 0, instance, 0);
win = CreateWindow("librwD3D9", title, style,
offx, offy, rect.right, rect.bottom, 0, 0, instance, 0);
if(!win){
MessageBox(0, "CreateWindow() - FAILED", 0, 0);
return 0;

View File

@ -284,6 +284,9 @@ Camera::create(void)
cam->fogPlane = 5.0f;
cam->projection = Camera::PERSPECTIVE;
cam->frameBuffer = nil;
cam->zBuffer = nil;
// clump extension
cam->clump = nil;
cam->inClump.init();
@ -315,6 +318,10 @@ Camera::clone(void)
cam->farPlane = this->farPlane;
cam->fogPlane = this->fogPlane;
cam->projection = this->projection;
cam->frameBuffer = this->frameBuffer;
cam->zBuffer = this->zBuffer;
s_plglist.copy(cam, this);
return cam;
}

View File

@ -10,6 +10,7 @@
#include "../rwobjects.h"
#include "../rwengine.h"
#include "rwd3d.h"
#include "rwd3dimpl.h"
#define PLUGIN_ID 0
@ -275,6 +276,7 @@ setRasterStage(uint32 stage, Raster *raster)
void
setTexture(uint32 stage, Texture *tex)
{
// TODO: support mipmaps
static DWORD filternomip[] = {
0, D3DTEXF_POINT, D3DTEXF_LINEAR,
D3DTEXF_POINT, D3DTEXF_LINEAR,
@ -289,10 +291,10 @@ setTexture(uint32 stage, Texture *tex)
return;
}
if(tex->raster){
setSamplerState(stage, D3DSAMP_MAGFILTER, filternomip[tex->filterAddressing & 0xFF]);
setSamplerState(stage, D3DSAMP_MINFILTER, filternomip[tex->filterAddressing & 0xFF]);
setSamplerState(stage, D3DSAMP_ADDRESSU, wrap[(tex->filterAddressing >> 8) & 0xF]);
setSamplerState(stage, D3DSAMP_ADDRESSV, wrap[(tex->filterAddressing >> 12) & 0xF]);
setSamplerState(stage, D3DSAMP_MAGFILTER, filternomip[tex->getFilter()]);
setSamplerState(stage, D3DSAMP_MINFILTER, filternomip[tex->getFilter()]);
setSamplerState(stage, D3DSAMP_ADDRESSU, wrap[tex->getAddressU()]);
setSamplerState(stage, D3DSAMP_ADDRESSV, wrap[tex->getAddressV()]);
}
setRasterStage(stage, tex->raster);
}
@ -528,6 +530,14 @@ initD3D(void)
// setTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CONSTANT);
// setTextureStageState(0, D3DTSS_COLOROP, D3DTA_CONSTANT);
openIm2D();
return 1;
}
static int
finalizeD3D(void)
{
return 1;
}
@ -539,6 +549,8 @@ deviceSystem(DeviceReq req, void *arg0)
return startD3D((EngineStartParams*)arg0);
case DEVICEINIT:
return initD3D();
case DEVICEFINALIZE:
return finalizeD3D();
case DEVICESTOP:
return stopD3D();
}
@ -553,7 +565,7 @@ Device renderdevice = {
d3d::showRaster,
d3d::setRwRenderState,
d3d::getRwRenderState,
null::im2DRenderIndexedPrimitive,
d3d::im2DRenderIndexedPrimitive,
d3d::deviceSystem,
};

102
src/d3d/d3dim2d.cpp Normal file
View File

@ -0,0 +1,102 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "../rwbase.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#include "rwd3d.h"
#include "rwd3d9.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
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()
};
d3ddevice->CreateVertexDeclaration((D3DVERTEXELEMENT9*)elements, &im2ddecl);
im2dvertbuf = (IDirect3DVertexBuffer9*)createVertexBuffer(NUMVERTICES*sizeof(Im2DVertex), 0, D3DPOOL_MANAGED);
im2dindbuf = (IDirect3DIndexBuffer9*)createIndexBuffer(NUMINDICES*sizeof(uint16));
}
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), 0);
memcpy(lockedindices, indices, numIndices*sizeof(uint16));
unlockIndices(im2dindbuf);
uint8 *lockedvertices = lockVertices(im2dvertbuf, 0, numVertices*sizeof(Im2DVertex), D3DLOCK_NOSYSLOCK);
memcpy(lockedvertices, vertices, numVertices*sizeof(Im2DVertex));
unlockVertices(im2dvertbuf);
d3ddevice->SetStreamSource(0, im2dvertbuf, 0, sizeof(Im2DVertex));
d3ddevice->SetIndices(im2dindbuf);
d3ddevice->SetVertexDeclaration(im2ddecl);
d3d::setTexture(0, engine->imtexture);
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);
}
#endif
}
}

View File

@ -21,6 +21,24 @@ extern IDirect3DDevice9 *d3ddevice;
extern Device renderdevice;
void lightingCB(void);
struct Im2DVertex
{
float32 x, y, z;
float32 w;
D3DCOLOR color;
float32 u, v;
void setScreenX(float32 x) { this->x = x; }
void setScreenY(float32 y) { this->y = y; }
void setScreenZ(float32 z) { this->z = z; }
void setCameraZ(float32 z) { }
void setRecipCameraZ(float32 recipz) { this->w = recipz; }
void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->color = D3DCOLOR_ARGB(a, r, g, b); }
void setU(float32 u) { this->u = u; }
void setV(float32 v) { this->v = v; }
};
#else
enum {
D3DLOCK_NOSYSLOCK = 0, // ignored

View File

@ -1,6 +1,12 @@
namespace rw {
namespace d3d {
#ifdef RW_D3D9
void openIm2D(void);
void im2DRenderIndexedPrimitive(PrimitiveType primType,
void *vertices, int32 numVertices, void *indices, int32 numIndices);
#endif
void rasterCreate(Raster *raster);
uint8 *rasterLock(Raster *raster, int32 level);
void rasterUnlock(Raster *raster, int32 level);

View File

@ -41,7 +41,7 @@ void *mustmalloc_h(size_t sz, uint32 hint)
{
void *ret;
ret = rwMalloc(sz, hint);
if(ret)
if(ret || sz == 0)
return ret;
fprintf(stderr, "Error: out of memory\n");
exit(1);
@ -51,7 +51,7 @@ void *mustrealloc_h(void *p, size_t sz, uint32 hint)
{
void *ret;
ret = rwRealloc(p, sz, hint);
if(ret)
if(ret || sz == 0)
return ret;
fprintf(stderr, "Error: out of memory\n");
exit(1);
@ -83,7 +83,8 @@ Engine::init(void)
Engine::s_plglist.last = nil;
// core plugin attach here
Engine::registerPlugin(0, ID_FRAMEMODULE, Frame::_open, Frame::_close);
Frame::registerModule();
Texture::registerModule();
// driver plugin attach
ps2::registerPlatformPlugins();
@ -111,10 +112,7 @@ Engine::open(void)
engine = (Engine*)rwNew(Engine::s_plglist.size, MEMDUR_GLOBAL);
engine->currentCamera = nil;
engine->currentWorld = nil;
engine->currentTexDictionary = nil;
engine->imtexture = nil;
engine->loadTextures = 1;
engine->makeDummies = 1;
// Initialize device
// Device and possibly OS specific!
@ -177,10 +175,7 @@ void
Engine::term(void)
{
// TODO
for(uint i = 0; i < NUM_PLATFORMS; i++)
Driver::s_plglist[i].destruct(rw::engine->driver[i]);
Engine::s_plglist.destruct(engine);
Engine::state = Opened;
Engine::state = Dead;
}
void
@ -197,7 +192,10 @@ void
Engine::stop(void)
{
engine->device.system(DEVICESTOP, nil);
Engine::state = Dead;
for(uint i = 0; i < NUM_PLATFORMS; i++)
Driver::s_plglist[i].destruct(rw::engine->driver[i]);
Engine::s_plglist.destruct(engine);
Engine::state = Opened;
}
namespace null {

View File

@ -13,10 +13,14 @@
namespace rw {
PluginList Frame::s_plglist = { sizeof(Frame), sizeof(Frame), nil, nil };
void *Frame::_open(void *object, int32 offset, int32 size) { engine->frameDirtyList.init(); return object; }
void *Frame::_close(void *object, int32 offset, int32 size) { return object; }
static void *frameOpen(void *object, int32 offset, int32 size) { engine->frameDirtyList.init(); return object; }
static void *frameClose(void *object, int32 offset, int32 size) { return object; }
void
Frame::registerModule(void)
{
Engine::registerPlugin(0, ID_FRAMEMODULE, frameOpen, frameClose);
}
Frame*
Frame::create(void)

View File

@ -70,7 +70,6 @@ static UniformObject uniformObject;
int32 u_matColor;
int32 u_surfaceProps;
Shader *simpleShader;
static bool32 stateDirty = 1;
@ -304,6 +303,17 @@ setActiveTexture(int32 n)
void
setTexture(int32 n, Texture *tex)
{
// TODO: support mipmaps
static GLint filternomip[] = {
0, GL_NEAREST, GL_LINEAR,
GL_NEAREST, GL_LINEAR,
GL_NEAREST, GL_LINEAR
};
static GLint wrap[] = {
0, GL_REPEAT, GL_MIRRORED_REPEAT,
GL_CLAMP, GL_CLAMP_TO_BORDER
};
bool32 alpha;
setActiveTexture(GL_TEXTURE0+n);
if(tex == nil || tex->raster->platform != PLATFORM_GL3 ||
@ -315,6 +325,13 @@ setTexture(int32 n, Texture *tex)
nativeRasterOffset);
glBindTexture(GL_TEXTURE_2D, natras->texid);
alpha = natras->hasAlpha;
if(tex->filterAddressing != natras->filterAddressing){
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filternomip[tex->getFilter()]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filternomip[tex->getFilter()]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap[tex->getAddressU()]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap[tex->getAddressV()]);
natras->filterAddressing = tex->filterAddressing;
}
}
if(n == 0){
@ -518,25 +535,6 @@ initOpenGL(void)
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
byte whitepixel[4] = {0xFF, 0xFF, 0xFF, 0xFF};
glGenTextures(1, &whitetex);
glBindTexture(GL_TEXTURE_2D, whitetex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1,
0, GL_RGBA, GL_UNSIGNED_BYTE, &whitepixel);
im2DInit();
return 1;
}
static int
finalizeOpenGL(void)
{
#include "shaders/simple_gl3.inc"
simpleShader = Shader::fromStrings(simple_vert_src, simple_frag_src);
glGenBuffers(1, &ubo_state);
glBindBuffer(GL_UNIFORM_BUFFER, ubo_state);
glBindBufferBase(GL_UNIFORM_BUFFER, gl3::findBlock("State"), ubo_state);
@ -558,6 +556,25 @@ finalizeOpenGL(void)
GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
byte whitepixel[4] = {0xFF, 0xFF, 0xFF, 0xFF};
glGenTextures(1, &whitetex);
glBindTexture(GL_TEXTURE_2D, whitetex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1,
0, GL_RGBA, GL_UNSIGNED_BYTE, &whitepixel);
#include "shaders/simple_gl3.inc"
simpleShader = Shader::fromStrings(simple_vert_src, simple_frag_src);
openIm2D();
return 1;
}
static int
finalizeOpenGL(void)
{
return 1;
}

View File

@ -16,19 +16,20 @@
namespace rw {
namespace gl3 {
uint32 im2DVbo, im2DIbo;
static uint32 im2DVbo, im2DIbo;
static int32 u_xform;
#define STARTINDICES 1024
#define STARTVERTICES 1024
#define STARTINDICES 10000
#define STARTVERTICES 10000
static Shader *im2dShader;
static AttribDesc attribDesc[3] = {
{ ATTRIB_POS, GL_FLOAT, GL_FALSE, 3,
{ ATTRIB_POS, GL_FLOAT, GL_FALSE, 4,
sizeof(Im2DVertex), 0 },
{ ATTRIB_COLOR, GL_UNSIGNED_BYTE, GL_TRUE, 4,
sizeof(Im2DVertex), offsetof(Im2DVertex, r) },
{ ATTRIB_TEXCOORDS0, GL_FLOAT, GL_FALSE, 2,
sizeof(Im2DVertex), offsetof(Im2DVertex, r) },
sizeof(Im2DVertex), offsetof(Im2DVertex, u) },
};
static int primTypeMap[] = {
@ -42,8 +43,10 @@ static int primTypeMap[] = {
};
void
im2DInit(void)
openIm2D(void)
{
u_xform = registerUniform("u_xform");
#include "shaders/im2d_gl3.inc"
im2dShader = Shader::fromStrings(im2d_vert_src, im2d_frag_src);
@ -65,6 +68,11 @@ im2DRenderIndexedPrimitive(PrimitiveType primType,
void *vertices, int32 numVertices,
void *indices, int32 numIndices)
{
GLfloat xform[4];
Camera *cam;
cam = (Camera*)engine->currentCamera;
// TODO: fixed size
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2DIbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*2,
indices, GL_DYNAMIC_DRAW);
@ -73,9 +81,15 @@ im2DRenderIndexedPrimitive(PrimitiveType primType,
glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Im2DVertex),
vertices, GL_DYNAMIC_DRAW);
setAttribPointers(attribDesc, 3);
im2dShader->use();
xform[0] = 2.0f/cam->frameBuffer->width;
xform[1] = -2.0f/cam->frameBuffer->height;
xform[2] = -1.0f;
xform[3] = 1.0f;
im2dShader->use();
setAttribPointers(attribDesc, 3);
glUniform4fv(currentShader->uniformLocations[u_xform], 1, xform);
setTexture(0, engine->imtexture);
flushCache();

View File

@ -23,9 +23,27 @@ int32 nativeRasterOffset;
void
rasterCreate(Raster *raster)
{
switch(raster->type){
case Raster::CAMERA:
// TODO: set/check width, height, depth, format?
raster->flags |= Raster::DONTALLOCATE;
break;
case Raster::ZBUFFER:
// TODO: set/check width, height, depth, format?
raster->flags |= Raster::DONTALLOCATE;
break;
case Raster::TEXTURE:
// continue below
break;
default:
assert(0 && "unsupported format");
}
if(raster->flags & Raster::DONTALLOCATE)
return;
assert(raster->type == Raster::TEXTURE);
#ifdef RW_OPENGL
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset);
switch(raster->format & 0xF00){
@ -54,11 +72,10 @@ rasterCreate(Raster *raster)
glGenTextures(1, &natras->texid);
glBindTexture(GL_TEXTURE_2D, natras->texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
raster->width, raster->height,
0, natras->format, natras->type, nil);
natras->filterAddressing = ~0;
glBindTexture(GL_TEXTURE_2D, 0);
#endif

View File

@ -78,11 +78,23 @@ struct InstanceDataHeader : rw::InstanceDataHeader
InstanceData *inst;
};
#ifdef RW_GL3
struct Im2DVertex
{
float32 x, y, z;
float32 x, y, z, w;
uint8 r, g, b, a;
float32 u, v;
void setScreenX(float32 x) { this->x = x; }
void setScreenY(float32 y) { this->y = y; }
void setScreenZ(float32 z) { this->z = z; }
void setCameraZ(float32 z) { this->w = z; }
void setRecipCameraZ(float32 recipz) { }
void setColor(uint8 r, uint8 g, uint8 b, uint8 a) {
this->r = r; this->g = g; this->b = b; this->a = a; }
void setU(float32 u) { this->u = u; }
void setV(float32 v) { this->v = v; }
};
void setAttribPointers(AttribDesc *attribDescs, int32 numAttribs);
@ -105,6 +117,8 @@ void setTexture(int32 n, Texture *tex);
void flushCache(void);
#endif
class ObjPipeline : public rw::ObjPipeline
{
public:
@ -136,6 +150,8 @@ struct Gl3Raster
uint32 texid;
bool32 hasAlpha;
// cached filtermode and addressing
uint32 filterAddressing;
};
void registerNativeRaster(void);

View File

@ -5,7 +5,7 @@ namespace gl3 {
extern Shader *simpleShader;
extern uint32 im2DVbo, im2DIbo;
void im2DInit(void);
void openIm2D(void);
void im2DRenderIndexedPrimitive(PrimitiveType primType,
void *vertices, int32 numVertices, void *indices, int32 numIndices);

View File

@ -1,13 +1,15 @@
#version 330
layout(std140) uniform Im2DState
{
int u_alphaTest;
float u_alphaRef;
mat4 u_xform;
};
//layout(std140) uniform Im2DState
//{
// int u_alphaTest;
// float u_alphaRef;
// mat4 u_xform;
//};
layout(location = 0) in vec3 in_pos;
uniform vec4 u_xform;
layout(location = 0) in vec4 in_pos;
layout(location = 2) in vec4 in_color;
layout(location = 3) in vec2 in_tex0;
@ -17,7 +19,9 @@ out vec2 v_tex0;
void
main(void)
{
gl_Position = vec4(in_pos, 1.0);
gl_Position = in_pos;
gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;
gl_Position.xyz *= gl_Position.w;
v_color = in_color;
v_tex0 = in_tex0;
}

View File

@ -1,14 +1,16 @@
const char *im2d_vert_src =
"#version 330\n"
"layout(std140) uniform Im2DState\n"
"{\n"
" int u_alphaTest;\n"
" float u_alphaRef;\n"
" mat4 u_xform;\n"
"};\n"
"//layout(std140) uniform Im2DState\n"
"//{\n"
"// int u_alphaTest;\n"
"// float u_alphaRef;\n"
"// mat4 u_xform;\n"
"//};\n"
"layout(location = 0) in vec3 in_pos;\n"
"uniform vec4 u_xform;\n"
"layout(location = 0) in vec4 in_pos;\n"
"layout(location = 2) in vec4 in_color;\n"
"layout(location = 3) in vec2 in_tex0;\n"
@ -18,7 +20,9 @@ const char *im2d_vert_src =
"void\n"
"main(void)\n"
"{\n"
" gl_Position = vec4(in_pos, 1.0);\n"
" gl_Position = in_pos;\n"
" gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;\n"
" gl_Position.xyz *= gl_Position.w;\n"
" v_color = in_color;\n"
" v_tex0 = in_tex0;\n"
"}\n"

View File

@ -8,6 +8,19 @@
#ifdef RW_GL3
#define RW_OPENGL
#define RWDEVICE gl3
#endif
#ifdef RW_D3D9
#define RWDEVICE d3d
#endif
#ifdef RW_D3D8
#define RWDEVICE d3d
#endif
#ifdef RW_PS2
#define RWDEVICE ps2
#endif
#ifdef RW_WDGL
@ -64,7 +77,21 @@ struct RGBAf
float32 blue;
float32 alpha;
};
inline RGBAf makeRGBAf(float32 r, float32 g, float32 b, float32 a) { RGBAf c = { r, g, b, a }; return c; }
inline bool32 equal(const RGBAf &c1, const RGBAf &c2) { return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue && c1.alpha == c2.alpha; }
inline RGBAf add(const RGBAf &a, const RGBAf &b) { return makeRGBAf(a.red+b.red, a.green+b.green, a.blue+b.blue, a.alpha+b.alpha); }
inline RGBAf modulate(const RGBAf &a, const RGBAf &b) { return makeRGBAf(a.red*b.red, a.green*b.green, a.blue*b.blue, a.alpha*b.alpha); }
inline RGBAf scale(const RGBAf &a, float32 f) { return makeRGBAf(a.red*f, a.green*f, a.blue*f, a.alpha*f); }
inline void clamp(RGBAf *a) {
if(a->red > 1.0f) a->red = 1.0f;
if(a->red < 0.0f) a->red = 0.0f;
if(a->green > 1.0f) a->green = 1.0f;
if(a->green < 0.0f) a->green = 0.0f;
if(a->blue > 1.0f) a->blue = 1.0f;
if(a->blue < 0.0f) a->blue = 0.0f;
if(a->alpha > 1.0f) a->alpha = 1.0f;
if(a->alpha < 0.0f) a->alpha = 0.0f;
}
inline void convColor(RGBA *i, RGBAf *f){
int32 c;
@ -467,6 +494,7 @@ enum CoreModuleID
{
ID_NAMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x00),
ID_FRAMEMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x03),
ID_TEXTUREMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x08),
};
#define ECODE(c, s) c,

View File

@ -135,11 +135,6 @@ struct Engine
Texture *imtexture;
LinkList frameDirtyList;
TexDictionary *currentTexDictionary;
// load textures from files
bool32 loadTextures;
// create dummy textures to store just names
bool32 makeDummies;
// Dynamically allocated because of plugins
Driver *driver[NUM_PLATFORMS];
Device device;
@ -170,6 +165,9 @@ inline void SetRenderState(int32 state, uint32 value){
inline uint32 GetRenderState(int32 state){
return engine->device.getRenderState(state); }
inline float32 GetNearZ(void) { return engine->device.zNear; }
inline float32 GetFarZ(void) { return engine->device.zNear; }
// These must be macros because we might want to pass __FILE__ and __LINE__ later
#define rwMalloc(s, h) rw::Engine::memfuncs.rwmalloc(s,h)
#define rwMallocT(t, s, h) (t*)rw::Engine::memfuncs.rwmalloc((s)*sizeof(t),h)

View File

@ -137,8 +137,7 @@ struct Frame
void purgeClone(void);
#ifndef RWPUBLIC
static void *_open(void*, int32, int32);
static void *_close(void*, int32, int32);
static void registerModule(void);
#endif
static void syncDirty(void);
};
@ -282,30 +281,6 @@ struct TexDictionary;
struct Texture
{
PLUGINBASE
Raster *raster;
TexDictionary *dict;
LLLink inDict;
char name[32];
char mask[32];
uint32 filterAddressing; // VVVVUUUU FFFFFFFF
int32 refCount;
static Texture *create(Raster *raster);
void destroy(void);
static Texture *fromDict(LLLink *lnk){
return LLLinkGetData(lnk, Texture, inDict); }
static Texture *streamRead(Stream *stream);
bool streamWrite(Stream *stream);
uint32 streamGetSize(void);
static Texture *read(const char *name, const char *mask);
static Texture *streamReadNative(Stream *stream);
void streamWriteNative(Stream *stream);
uint32 streamGetSizeNative(void);
static Texture *(*findCB)(const char *name);
static Texture *(*readCB)(const char *name, const char *mask);
enum FilterMode {
NEAREST = 1,
LINEAR,
@ -320,6 +295,40 @@ struct Texture
CLAMP,
BORDER
};
PLUGINBASE
Raster *raster;
TexDictionary *dict;
LLLink inDict;
char name[32];
char mask[32];
uint32 filterAddressing; // VVVVUUUU FFFFFFFF
int32 refCount;
static Texture *create(Raster *raster);
void destroy(void);
static Texture *fromDict(LLLink *lnk){
return LLLinkGetData(lnk, Texture, inDict); }
FilterMode getFilter(void) { return (FilterMode)(filterAddressing & 0xFF); }
void setFilter(FilterMode f) { filterAddressing = filterAddressing & ~0xFF | f; }
Addressing getAddressU(void) { return (Addressing)((filterAddressing >> 8) & 0xF); }
Addressing getAddressV(void) { return (Addressing)((filterAddressing >> 12) & 0xF); }
void setAddressU(Addressing u) { filterAddressing = filterAddressing & ~0xF00 | u<<8; }
void setAddressV(Addressing v) { filterAddressing = filterAddressing & ~0xF000 | v<<12; }
static Texture *streamRead(Stream *stream);
bool streamWrite(Stream *stream);
uint32 streamGetSize(void);
static Texture *read(const char *name, const char *mask);
static Texture *streamReadNative(Stream *stream);
void streamWriteNative(Stream *stream);
uint32 streamGetSizeNative(void);
static Texture *(*findCB)(const char *name);
static Texture *(*readCB)(const char *name, const char *mask);
#ifndef RWPUBLIC
static void registerModule(void);
#endif
};
@ -624,12 +633,15 @@ struct Camera
V3d frustumCorners[8];
BBox frustumBoundBox;
Raster *frameBuffer;
Raster *zBuffer;
// clump link handled by plugin in RW
Clump *clump;
LLLink inClump;
// world extension
/* 3 unknowns */
/* RW: frustum sectors, space, position */
World *world;
ObjectWithFrame::Sync originalSync;
void (*originalBeginUpdate)(Camera*);

View File

@ -15,19 +15,54 @@
#include "d3d/rwd3d8.h"
#include "d3d/rwd3d9.h"
#ifdef _WIN32
/* srsly? */
#define strdup _strdup
#endif
#define PLUGIN_ID 0
// TODO: maintain a global list of all texdicts
namespace rw {
PluginList TexDictionary::s_plglist = { sizeof(TexDictionary), sizeof(TexDictionary), nil, nil };
PluginList Texture::s_plglist = { sizeof(Texture), sizeof(Texture), nil, nil };
PluginList Raster::s_plglist = { sizeof(Raster), sizeof(Raster), nil, nil };
struct TextureGlobals
{
TexDictionary *initialTexDict;
TexDictionary *currentTexDict;
// load textures from files
bool32 loadTextures;
// create dummy textures to store just names
bool32 makeDummies;
};
int32 textureModuleOffset;
#define TEXTUREGLOBAL(v) (PLUGINOFFSET(TextureGlobals, engine, textureModuleOffset)->v)
static void*
textureOpen(void *object, int32 offset, int32 size)
{
TexDictionary *texdict;
textureModuleOffset = offset;
texdict = TexDictionary::create();
TEXTUREGLOBAL(initialTexDict) = texdict;
TexDictionary::setCurrent(texdict);
TEXTUREGLOBAL(loadTextures) = 1;
TEXTUREGLOBAL(makeDummies) = 0;
return object;
}
static void*
textureClose(void *object, int32 offset, int32 size)
{
TEXTUREGLOBAL(initialTexDict)->destroy();
return object;
}
void
Texture::registerModule(void)
{
Engine::registerPlugin(sizeof(TextureGlobals), ID_TEXTUREMODULE, textureOpen, textureClose);
}
//
// TexDictionary
//
@ -49,8 +84,8 @@ TexDictionary::create(void)
void
TexDictionary::destroy(void)
{
if(engine->currentTexDictionary == this)
engine->currentTexDictionary = nil;
if(TEXTUREGLOBAL(currentTexDict) == this)
TEXTUREGLOBAL(currentTexDict) = nil;
FORLIST(lnk, this->textures)
Texture::fromDict(lnk)->destroy();
s_plglist.destruct(this);
@ -145,13 +180,13 @@ TexDictionary::streamGetSize(void)
void
TexDictionary::setCurrent(TexDictionary *txd)
{
engine->currentTexDictionary = txd;
PLUGINOFFSET(TextureGlobals, engine, textureModuleOffset)->currentTexDict = txd;
}
TexDictionary*
TexDictionary::getCurrent(void)
{
return engine->currentTexDictionary;
return PLUGINOFFSET(TextureGlobals, engine, textureModuleOffset)->currentTexDict;
}
//
@ -200,8 +235,8 @@ Texture::destroy(void)
static Texture*
defaultFindCB(const char *name)
{
if(engine->currentTexDictionary)
return engine->currentTexDictionary->find(name);
if(TEXTUREGLOBAL(currentTexDict))
return TEXTUREGLOBAL(currentTexDict)->find(name);
// TODO: RW searches *all* TXDs otherwise
return nil;
}
@ -238,11 +273,11 @@ Texture::read(const char *name, const char *mask)
tex->refCount++;
return tex;
}
if(engine->loadTextures){
if(TEXTUREGLOBAL(loadTextures)){
tex = Texture::readCB(name, mask);
if(tex == nil)
goto dummytex;
}else dummytex: if(engine->makeDummies){
}else dummytex: if(TEXTUREGLOBAL(makeDummies)){
tex = Texture::create(nil);
if(tex == nil)
return nil;
@ -252,10 +287,10 @@ Texture::read(const char *name, const char *mask)
raster = Raster::create(0, 0, 0, Raster::DONTALLOCATE);
tex->raster = raster;
}
if(tex && engine->currentTexDictionary){
if(tex && TEXTUREGLOBAL(currentTexDict)){
if(tex->dict)
tex->inDict.remove();
engine->currentTexDictionary->add(tex);
TEXTUREGLOBAL(currentTexDict)->add(tex);
}
return tex;
}

View File

@ -13,8 +13,8 @@ void
Camera::update(void)
{
if(m_rwcam){
m_rwcam->nearPlane = m_near;
m_rwcam->farPlane = m_far;
m_rwcam->setNearPlane(m_near);
m_rwcam->setFarPlane(m_far);
m_rwcam->setFOV(m_fov, m_aspectRatio);
rw::Frame *f = m_rwcam->getFrame();

View File

@ -5,10 +5,16 @@
rw::V3d zero = { 0.0f, 0.0f, 0.0f };
Camera *camera;
rw::Clump *clump;
rw::World *world;
struct SceneGlobals {
rw::World *world;
rw::Camera *camera;
rw::Clump *clump;
} Scene;
rw::Texture *tex;
rw::EngineStartParams engineStartParams;
void tlTest(rw::Clump *clump);
void
Init(void)
{
@ -152,6 +158,8 @@ InitRW(void)
if(!sk::InitRW())
return false;
tex = rw::Texture::read("maze", nil);
char *filename = "teapot.dff";
if(sk::args.argc > 1)
filename = sk::args.argv[1];
@ -161,31 +169,43 @@ InitRW(void)
return false;
}
rw::findChunk(&in, rw::ID_CLUMP, NULL, NULL);
clump = rw::Clump::streamRead(&in);
assert(clump);
Scene.clump = rw::Clump::streamRead(&in);
assert(Scene.clump);
in.close();
clump->getFrame()->translate(&zero, rw::COMBINEREPLACE);
// TEST - Set texture to the all materials of the clump
FORLIST(lnk, Scene.clump->atomics){
rw::Atomic *a = rw::Atomic::fromClump(lnk);
for(int i = 0; i < a->geometry->matList.numMaterials; i++)
a->geometry->matList.materials[i]->setTexture(tex);
}
dumpUserData(clump);
setupClump(clump);
Scene.clump->getFrame()->translate(&zero, rw::COMBINEREPLACE);
world = rw::World::create();
dumpUserData(Scene.clump);
setupClump(Scene.clump);
Scene.world = rw::World::create();
rw::Light *ambient = rw::Light::create(rw::Light::AMBIENT);
ambient->setColor(0.2f, 0.2f, 0.2f);
world->addLight(ambient);
Scene.world->addLight(ambient);
rw::V3d xaxis = { 1.0f, 0.0f, 0.0f };
rw::Light *direct = rw::Light::create(rw::Light::DIRECTIONAL);
direct->setColor(0.8f, 0.8f, 0.8f);
direct->setFrame(rw::Frame::create());
direct->getFrame()->rotate(&xaxis, 180.0f, rw::COMBINEREPLACE);
world->addLight(direct);
Scene.world->addLight(direct);
camera = new Camera;
camera->m_rwcam = rw::Camera::create();
camera->m_rwcam->setFrame(rw::Frame::create());
Scene.camera = rw::Camera::create();
camera->m_rwcam = Scene.camera;
Scene.camera->frameBuffer =
rw::Raster::create(sk::globals.width, sk::globals.height, 0, rw::Raster::CAMERA);
Scene.camera->zBuffer =
rw::Raster::create(sk::globals.width, sk::globals.height, 0, rw::Raster::ZBUFFER);
Scene.camera->setFrame(rw::Frame::create());
camera->m_aspectRatio = 640.0f/480.0f;
camera->m_near = 0.1f;
camera->m_far = 450.0f;
@ -196,7 +216,7 @@ InitRW(void)
// camera->setPosition(Vec3(0.0f, -1.0f, 3.0f));
camera->update();
world->addCamera(camera->m_rwcam);
Scene.world->addCamera(camera->m_rwcam);
return true;
}
@ -204,15 +224,37 @@ InitRW(void)
void
im2dtest(void)
{
static rw::gl3::Im2DVertex verts[] = {
{ -0.5, -0.5, 0.0, 255, 0, 0, 255, 0.0, 0.0 },
{ 0.5, -0.5, 0.0, 0, 255, 0, 255, 0.0, 0.0 },
{ -0.5, 0.5, 0.0, 0, 0, 255, 255, 0.0, 0.0 },
{ 0.5, 0.5, 0.0, 0, 255, 255, 255, 0.0, 0.0 },
using namespace rw::RWDEVICE;
int i;
static struct
{
float x, y;
rw::uint8 r, g, b, a;
float u, v;
} vs[4] = {
{ 0.0f, 0.0f, 255, 0, 0, 128, 0.0f, 0.0f },
{ 640.0f, 0.0f, 0, 255, 0, 128, 1.0f, 0.0f },
{ 0.0f, 480.0f, 0, 0, 255, 128, 0.0f, 1.0f },
{ 640.0f, 480.0f, 0, 255, 255, 128, 1.0f, 1.0f },
};
static Im2DVertex verts[4];
static short indices[] = {
0, 1, 2, 3
};
for(i = 0; i < 4; i++){
verts[i].setScreenX(vs[i].x);
verts[i].setScreenY(vs[i].y);
verts[i].setScreenZ(rw::GetNearZ());
verts[i].setCameraZ(Scene.camera->nearPlane);
verts[i].setRecipCameraZ(1.0f/Scene.camera->nearPlane);
verts[i].setColor(vs[i].r, vs[i].g, vs[i].b, vs[i].a);
verts[i].setU(vs[i].u);
verts[i].setV(vs[i].v);
}
rw::engine->imtexture = tex;
rw::SetRenderState(rw::VERTEXALPHA, 1);
rw::engine->device.im2DRenderIndexedPrimitive(rw::PRIMTYPETRISTRIP,
&verts, 4, &indices, 4);
}
@ -225,8 +267,9 @@ Draw(float timeDelta)
camera->update();
camera->m_rwcam->beginUpdate();
clump->render();
Scene.clump->render();
im2dtest();
// tlTest(Scene.clump);
camera->m_rwcam->endUpdate();
camera->m_rwcam->showRaster();

BIN
tools/clumpview/maze.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

134
tools/clumpview/tests.cpp Normal file
View File

@ -0,0 +1,134 @@
#include <rw.h>
#include <skeleton.h>
using namespace rw;
//
// This is a test to implement T&L in software and render with Im2D
#define MAX_LIGHTS 8
struct Directional {
V3d at;
RGBAf color;
};
static Directional directionals[MAX_LIGHTS];
static int32 numDirectionals;
static RGBAf ambLight;
static void
enumLights(Matrix *lightmat)
{
int32 n;
World *world;
world = (World*)engine->currentWorld;
ambLight.red = 0.0;
ambLight.green = 0.0;
ambLight.blue = 0.0;
ambLight.alpha = 0.0;
numDirectionals = 0;
// only unpositioned lights right now
FORLIST(lnk, world->directionalLights){
Light *l = Light::fromWorld(lnk);
if(l->getType() == Light::DIRECTIONAL){
if(numDirectionals >= MAX_LIGHTS)
continue;
n = numDirectionals++;
V3d::transformVectors(&directionals[n].at, &l->getFrame()->getLTM()->at, 1, lightmat);
directionals[n].color = l->color;
directionals[n].color.alpha = 0.0f;
}else if(l->getType() == Light::AMBIENT){
ambLight.red += l->color.red;
ambLight.green += l->color.green;
ambLight.blue += l->color.blue;
}
}
}
static void
drawAtomic(Atomic *a)
{
using namespace RWDEVICE;
Im2DVertex *im2dverts;
V3d *xvert;
Matrix xform;
Matrix lightmat;
Camera *cam = (Camera*)engine->currentCamera;
Geometry *g = a->geometry;
MeshHeader *mh = g->meshHeader;
Mesh *m = mh->getMeshes();
int32 width = cam->frameBuffer->width;
int32 height = cam->frameBuffer->height;
RGBA *prelight;
V3d *normals;
TexCoords *texcoords;
Matrix::mult(&xform, a->getFrame()->getLTM(), &cam->viewMatrix);
Matrix::invert(&lightmat, a->getFrame()->getLTM());
enumLights(&lightmat);
xvert = rwNewT(V3d, g->numVertices, MEMDUR_FUNCTION);
im2dverts = rwNewT(Im2DVertex, g->numVertices, MEMDUR_FUNCTION);
prelight = g->colors;
normals = g->morphTargets[0].normals;
texcoords = g->texCoords[0];
V3d::transformPoints(xvert, g->morphTargets[0].vertices, g->numVertices, &xform);
for(int32 i = 0; i < g->numVertices; i++){
float32 recipZ = 1.0f/xvert[i].z;
im2dverts[i].setScreenX(xvert[i].x * recipZ * width);
im2dverts[i].setScreenY((xvert[i].y * recipZ * height));
im2dverts[i].setScreenZ(recipZ * cam->zScale + cam->zShift);
im2dverts[i].setCameraZ(xvert[i].z);
im2dverts[i].setRecipCameraZ(recipZ);
im2dverts[i].setColor(255, 0, 0, 255);
im2dverts[i].setU(texcoords[i].u);
im2dverts[i].setV(texcoords[i].v);
}
for(int32 i = 0; i < mh->numMeshes; i++){
for(int32 j = 0; j < m[i].numIndices; j++){
int32 idx = m[i].indices[j];
RGBA col;
RGBAf colf, color;
if(prelight)
convColor(&color, &prelight[idx]);
else{
color.red = color.green = color.blue = 0.0f;
color.alpha = 1.0f;
}
color = add(color, ambLight);
if(normals)
for(int32 k = 0; k < numDirectionals; k++){
float32 f = dot(normals[idx], neg(directionals[k].at));
if(f <= 0.0f) continue;
colf = scale(directionals[k].color, f);
color = add(color, colf);
}
convColor(&colf, &m[i].material->color);
color = modulate(color, colf);
clamp(&color);
convColor(&col, &color);
im2dverts[idx].setColor(col.red, col.green, col.blue, col.alpha);
}
engine->imtexture = m[i].material->texture;
rw::engine->device.im2DRenderIndexedPrimitive(rw::PRIMTYPETRILIST,
im2dverts, g->numVertices, m[i].indices, m[i].numIndices);
}
rwFree(xvert);
rwFree(im2dverts);
}
void
tlTest(Clump *clump)
{
FORLIST(lnk, clump->atomics){
Atomic *a = Atomic::fromClump(lnk);
drawAtomic(a);
}
}