diff --git a/premake5.lua b/premake5.lua index 591ab10..b1934e6 100755 --- a/premake5.lua +++ b/premake5.lua @@ -1,3 +1,6 @@ +GLEWdir = "C:/Users/aap/src/glew-2.1.0" +GLFW64dir = "C:/Users/aap/src/glfw-3.2.1.bin.WIN64" + workspace "librw" location "build" language "C++" @@ -41,8 +44,13 @@ workspace "librw" filter { "platforms:linux*" } system "linux" + filter { "platforms:win*gl3" } + defines { "GLEW_STATIC" } + includedirs { path.join(GLEWdir, "include") } + includedirs { path.join(GLFW64dir, "include") } + filter "action:vs*" - buildoptions { "/wd4996" } + buildoptions { "/wd4996", "/wd4244" } filter {} diff --git a/src/base.err b/src/base.err index 52df5b2..a02a9c0 100644 --- a/src/base.err +++ b/src/base.err @@ -10,3 +10,9 @@ ECODE(ERR_VERSION, "Unsupported version %X") ECODE(ERR_PLATFORM, "Unsupported platform %d") +ECODE(ERR_ENGINEINIT, + "Engine could not be initialized") +ECODE(ERR_ENGINEOPEN, + "Engine could not be opened") +ECODE(ERR_ENGINESTART, + "Engine could not be started") diff --git a/src/camera.cpp b/src/camera.cpp index 1477596..76e68a3 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -17,13 +17,13 @@ defaultBeginUpdateCB(Camera *cam) { engine->currentCamera = cam; Frame::syncDirty(); - engine->beginUpdate(cam); + engine->device.beginUpdate(cam); } void defaultEndUpdateCB(Camera *cam) { - engine->endUpdate(cam); + engine->device.endUpdate(cam); } static void @@ -315,7 +315,14 @@ Camera::destroy(void) void Camera::clear(RGBA *col, uint32 mode) { - engine->clearCamera(this, col, mode); + engine->device.clearCamera(this, col, mode); +} + +void +Camera::showRaster(void) +{ + // TODO: camera raster + engine->device.showRaster(nil); } void @@ -323,8 +330,8 @@ calczShiftScale(Camera *cam) { float32 n = cam->nearPlane; float32 f = cam->farPlane; - float32 N = engine->zNear; - float32 F = engine->zFar; + float32 N = engine->device.zNear; + float32 F = engine->device.zFar; // RW does this N += (F - N)/10000.0f; F -= (F - N)/10000.0f; diff --git a/src/clump.cpp b/src/clump.cpp index 2c33f79..17efa3d 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -523,7 +523,7 @@ Atomic::getPipeline(void) { return this->pipeline ? this->pipeline : - driver[platform]->defaultPipeline; + engine->driver[platform]->defaultPipeline; } void diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp index 8e8e6ae..49d7b5e 100644 --- a/src/d3d/d3d.cpp +++ b/src/d3d/d3d.cpp @@ -15,9 +15,7 @@ namespace d3d { bool32 isP8supported = 1; -#ifdef RW_D3D9 -IDirect3DDevice9 *device = nil; -#else +#ifndef RW_D3D9 #define MAKEFOURCC(ch0, ch1, ch2, ch3) \ ((uint32)(uint8)(ch0) | ((uint32)(uint8)(ch1) << 8) | \ ((uint32)(uint8)(ch2) << 16) | ((uint32)(uint8)(ch3) << 24 )) @@ -186,7 +184,7 @@ createIndexBuffer(uint32 length) { #ifdef RW_D3D9 IDirect3DIndexBuffer9 *ibuf; - device->CreateIndexBuffer(length, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ibuf, 0); + d3ddevice->CreateIndexBuffer(length, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ibuf, 0); return ibuf; #else return new uint8[length]; @@ -227,7 +225,7 @@ createVertexBuffer(uint32 length, uint32 fvf, int32 pool) { #ifdef RW_D3D9 IDirect3DVertexBuffer9 *vbuf; - device->CreateVertexBuffer(length, D3DUSAGE_WRITEONLY, fvf, (D3DPOOL)pool, &vbuf, 0); + d3ddevice->CreateVertexBuffer(length, D3DUSAGE_WRITEONLY, fvf, (D3DPOOL)pool, &vbuf, 0); return vbuf; #else (void)fvf; @@ -270,7 +268,7 @@ createTexture(int32 width, int32 height, int32 numlevels, uint32 format) { #ifdef RW_D3D9 IDirect3DTexture9 *tex; - device->CreateTexture(width, height, numlevels, 0, + d3ddevice->CreateTexture(width, height, numlevels, 0, (D3DFORMAT)format, D3DPOOL_MANAGED, &tex, nil); return tex; #else diff --git a/src/d3d/d3d8.cpp b/src/d3d/d3d8.cpp index cccf81f..454ff90 100644 --- a/src/d3d/d3d8.cpp +++ b/src/d3d/d3d8.cpp @@ -23,15 +23,15 @@ using namespace d3d; void* driverOpen(void *o, int32, int32) { - driver[PLATFORM_D3D8]->defaultPipeline = makeDefaultPipeline(); + engine->driver[PLATFORM_D3D8]->defaultPipeline = makeDefaultPipeline(); - driver[PLATFORM_D3D8]->rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_D3D8]->rasterCreate = rasterCreate; - driver[PLATFORM_D3D8]->rasterLock = rasterLock; - driver[PLATFORM_D3D8]->rasterUnlock = rasterUnlock; - driver[PLATFORM_D3D8]->rasterNumLevels = rasterNumLevels; - driver[PLATFORM_D3D8]->rasterFromImage = rasterFromImage; - driver[PLATFORM_D3D8]->rasterToImage = rasterToImage; + engine->driver[PLATFORM_D3D8]->rasterNativeOffset = nativeRasterOffset; + engine->driver[PLATFORM_D3D8]->rasterCreate = rasterCreate; + engine->driver[PLATFORM_D3D8]->rasterLock = rasterLock; + engine->driver[PLATFORM_D3D8]->rasterUnlock = rasterUnlock; + engine->driver[PLATFORM_D3D8]->rasterNumLevels = rasterNumLevels; + engine->driver[PLATFORM_D3D8]->rasterFromImage = rasterFromImage; + engine->driver[PLATFORM_D3D8]->rasterToImage = rasterToImage; return o; } @@ -102,7 +102,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) Geometry *geometry = (Geometry*)object; uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); @@ -359,26 +359,26 @@ defaultInstanceCB(Geometry *geo, InstanceData *inst) uint8 *dst = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK); instV3d(VERT_FLOAT3, dst, - &geo->morphTargets[0].vertices[3*inst->minVert], + &geo->morphTargets[0].vertices[inst->minVert], inst->numVertices, inst->stride); dst += 12; if(geo->flags & Geometry::NORMALS){ instV3d(VERT_FLOAT3, dst, - &geo->morphTargets[0].normals[3*inst->minVert], + &geo->morphTargets[0].normals[inst->minVert], inst->numVertices, inst->stride); dst += 12; } inst->vertexAlpha = 0; if(geo->flags & Geometry::PRELIT){ - inst->vertexAlpha = instColor(VERT_ARGB, dst, &geo->colors[4*inst->minVert], + inst->vertexAlpha = instColor(VERT_ARGB, dst, &geo->colors[inst->minVert], inst->numVertices, inst->stride); dst += 4; } for(int32 i = 0; i < geo->numTexCoordSets; i++){ - instTexCoords(VERT_FLOAT2, dst, &geo->texCoords[i][2*inst->minVert], + instTexCoords(VERT_FLOAT2, dst, &geo->texCoords[i][inst->minVert], inst->numVertices, inst->stride); dst += 8; } @@ -390,26 +390,26 @@ defaultUninstanceCB(Geometry *geo, InstanceData *inst) { uint8 *src = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK); uninstV3d(VERT_FLOAT3, - &geo->morphTargets[0].vertices[3*inst->minVert], + &geo->morphTargets[0].vertices[inst->minVert], src, inst->numVertices, inst->stride); src += 12; if(geo->flags & Geometry::NORMALS){ uninstV3d(VERT_FLOAT3, - &geo->morphTargets[0].normals[3*inst->minVert], + &geo->morphTargets[0].normals[inst->minVert], src, inst->numVertices, inst->stride); src += 12; } inst->vertexAlpha = 0; if(geo->flags & Geometry::PRELIT){ - uninstColor(VERT_ARGB, &geo->colors[4*inst->minVert], src, + uninstColor(VERT_ARGB, &geo->colors[inst->minVert], src, inst->numVertices, inst->stride); src += 4; } for(int32 i = 0; i < geo->numTexCoordSets; i++){ - uninstTexCoords(VERT_FLOAT2, &geo->texCoords[i][2*inst->minVert], src, + uninstTexCoords(VERT_FLOAT2, &geo->texCoords[i][inst->minVert], src, inst->numVertices, inst->stride); src += 8; } @@ -481,7 +481,7 @@ readNativeTexture(Stream *stream) { uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); diff --git a/src/d3d/d3d8render.cpp b/src/d3d/d3d8render.cpp index 8330529..c5aed73 100644 --- a/src/d3d/d3d8render.cpp +++ b/src/d3d/d3d8render.cpp @@ -7,6 +7,7 @@ #include "../rwplg.h" #include "../rwpipeline.h" #include "../rwobjects.h" +#include "../rwengine.h" #include "rwd3d.h" #include "rwd3d8.h" @@ -23,28 +24,31 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) { RawMatrix world; + d3d::lightingCB(); + Geometry *geo = atomic->geometry; + d3d::setRenderState(D3DRS_LIGHTING, !!(geo->flags & rw::Geometry::LIGHT)); + Frame *f = atomic->getFrame(); convMatrix(&world, f->getLTM()); - device->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&world); + d3ddevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&world); InstanceData *inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ d3d::setTexture(0, inst->material->texture); d3d::setMaterial(inst->material); - d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40)); d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL); d3d::setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL); if(geo->flags & Geometry::PRELIT) d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1); - device->SetFVF(inst->vertexShader); - device->SetStreamSource(0, (IDirect3DVertexBuffer9*)inst->vertexBuffer, 0, inst->stride); - device->SetIndices((IDirect3DIndexBuffer9*)inst->indexBuffer); + d3ddevice->SetFVF(inst->vertexShader); + d3ddevice->SetStreamSource(0, (IDirect3DVertexBuffer9*)inst->vertexBuffer, 0, inst->stride); + d3ddevice->SetIndices((IDirect3DIndexBuffer9*)inst->indexBuffer); uint32 numPrim = inst->primType == D3DPT_TRIANGLESTRIP ? inst->numIndices-2 : inst->numIndices/3; d3d::flushCache(); - device->DrawIndexedPrimitive((D3DPRIMITIVETYPE)inst->primType, inst->baseIndex, - 0, inst->numVertices, 0, numPrim); + d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)inst->primType, inst->baseIndex, + 0, inst->numVertices, 0, numPrim); inst++; } } diff --git a/src/d3d/d3d9.cpp b/src/d3d/d3d9.cpp index 8ce74ee..a772b0c 100644 --- a/src/d3d/d3d9.cpp +++ b/src/d3d/d3d9.cpp @@ -31,15 +31,15 @@ static VertexElement _d3ddec_end = {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0}; void* driverOpen(void *o, int32, int32) { - driver[PLATFORM_D3D9]->defaultPipeline = makeDefaultPipeline(); + engine->driver[PLATFORM_D3D9]->defaultPipeline = makeDefaultPipeline(); - driver[PLATFORM_D3D9]->rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_D3D9]->rasterCreate = rasterCreate; - driver[PLATFORM_D3D9]->rasterLock = rasterLock; - driver[PLATFORM_D3D9]->rasterUnlock = rasterUnlock; - driver[PLATFORM_D3D9]->rasterNumLevels = rasterNumLevels; - driver[PLATFORM_D3D9]->rasterFromImage = rasterFromImage; - driver[PLATFORM_D3D9]->rasterToImage = rasterToImage; + engine->driver[PLATFORM_D3D9]->rasterNativeOffset = nativeRasterOffset; + engine->driver[PLATFORM_D3D9]->rasterCreate = rasterCreate; + engine->driver[PLATFORM_D3D9]->rasterLock = rasterLock; + engine->driver[PLATFORM_D3D9]->rasterUnlock = rasterUnlock; + engine->driver[PLATFORM_D3D9]->rasterNumLevels = rasterNumLevels; + engine->driver[PLATFORM_D3D9]->rasterFromImage = rasterFromImage; + engine->driver[PLATFORM_D3D9]->rasterToImage = rasterToImage; return o; } @@ -64,7 +64,7 @@ createVertexDeclaration(VertexElement *elements) { #ifdef RW_D3D9 IDirect3DVertexDeclaration9 *decl = 0; - device->CreateVertexDeclaration((D3DVERTEXELEMENT9*)elements, &decl); + d3ddevice->CreateVertexDeclaration((D3DVERTEXELEMENT9*)elements, &decl); return decl; #else int n = 0; @@ -122,7 +122,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) Geometry *geometry = (Geometry*)object; uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); @@ -592,7 +592,7 @@ readNativeTexture(Stream *stream) { uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); diff --git a/src/d3d/d3d9render.cpp b/src/d3d/d3d9render.cpp index 44672a5..96dc440 100644 --- a/src/d3d/d3d9render.cpp +++ b/src/d3d/d3d9render.cpp @@ -7,6 +7,7 @@ #include "../rwplg.h" #include "../rwpipeline.h" #include "../rwobjects.h" +#include "../rwengine.h" #include "rwd3d.h" #include "rwd3d9.h" @@ -23,29 +24,32 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) { RawMatrix world; + d3d::lightingCB(); + Geometry *geo = atomic->geometry; + d3d::setRenderState(D3DRS_LIGHTING, !!(geo->flags & rw::Geometry::LIGHT)); + Frame *f = atomic->getFrame(); convMatrix(&world, f->getLTM()); - device->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&world); + d3ddevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&world); - device->SetStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer, - 0, header->vertexStream[0].stride); - device->SetIndices((IDirect3DIndexBuffer9*)header->indexBuffer); - device->SetVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration); + d3ddevice->SetStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer, + 0, header->vertexStream[0].stride); + d3ddevice->SetIndices((IDirect3DIndexBuffer9*)header->indexBuffer); + d3ddevice->SetVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration); InstanceData *inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ d3d::setTexture(0, inst->material->texture); d3d::setMaterial(inst->material); - d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40)); d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL); d3d::setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL); if(geo->flags & Geometry::PRELIT) d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1); d3d::flushCache(); - device->DrawIndexedPrimitive((D3DPRIMITIVETYPE)header->primType, inst->baseIndex, - 0, inst->numVertices, - inst->startIndex, inst->numPrimitives); + d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)header->primType, inst->baseIndex, + 0, inst->numVertices, + inst->startIndex, inst->numPrimitives); inst++; } } diff --git a/src/d3d/d3ddriver.cpp b/src/d3d/d3ddriver.cpp index 12cf481..d420914 100644 --- a/src/d3d/d3ddriver.cpp +++ b/src/d3d/d3ddriver.cpp @@ -5,16 +5,31 @@ #include "../rwbase.h" #include "../rwplg.h" +#include "../rwerror.h" #include "../rwpipeline.h" #include "../rwobjects.h" #include "../rwengine.h" #include "rwd3d.h" +#define PLUGIN_ID 0 + namespace rw { namespace d3d { #ifdef RW_D3D9 +// cached RW render states +static bool32 vertexAlpha; +static bool32 textureAlpha; +static uint32 srcblend, destblend; +static uint32 zwrite; +static uint32 ztest; +static uint32 fogenable; +static RGBA fogcolor; +static uint32 alphafunc; +static uint32 alpharef; + + #define MAXNUMSTATES D3DRS_BLENDOPALPHA #define MAXNUMSTAGES 8 #define MAXNUMTEXSTATES D3DTSS_CONSTANT @@ -41,10 +56,13 @@ static uint32 d3dTextureStageStates[MAXNUMSTATES][MAXNUMSTAGES]; static uint32 d3dSamplerStates[MAXNUMSAMPLERSTATES][MAXNUMSTAGES]; +// TODO: not only rasters, make a struct static Raster *d3dRaster[MAXNUMSTAGES]; static D3DMATERIAL9 d3dmaterial; +// D3D render state + void setRenderState(uint32 state, uint32 value) { @@ -81,7 +99,7 @@ flushCache(void) v = stateCache[s].value; stateCache[s].dirty = 0; if(d3dStates[s] != v){ - device->SetRenderState((D3DRENDERSTATETYPE)s, v); + d3ddevice->SetRenderState((D3DRENDERSTATETYPE)s, v); d3dStates[s] = v; } } @@ -92,7 +110,7 @@ flushCache(void) v = textureStageStateCache[t][s].value; textureStageStateCache[t][s].dirty = 0; if(d3dTextureStageStates[t][s] != v){ - device->SetTextureStageState(s, (D3DTEXTURESTAGESTATETYPE)t, v); + d3ddevice->SetTextureStageState(s, (D3DTEXTURESTAGESTATETYPE)t, v); d3dTextureStageStates[t][s] = v; } } @@ -103,22 +121,154 @@ void setSamplerState(uint32 stage, uint32 type, uint32 value) { if(d3dSamplerStates[type][stage] != value){ - device->SetSamplerState(stage, (D3DSAMPLERSTATETYPE)type, value); + d3ddevice->SetSamplerState(stage, (D3DSAMPLERSTATETYPE)type, value); d3dSamplerStates[type][stage] = value; } } +// RW render state + +static void +setVertexAlpha(bool32 enable) +{ + if(vertexAlpha != enable){ + if(!textureAlpha){ + setRenderState(D3DRS_ALPHABLENDENABLE, enable); + setRenderState(D3DRS_ALPHATESTENABLE, enable); + } + vertexAlpha = enable; + } +} + +static uint32 blendMap[] = { + D3DBLEND_ZERO, + D3DBLEND_ONE, + D3DBLEND_SRCCOLOR, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_SRCALPHA, + D3DBLEND_INVSRCALPHA, + D3DBLEND_DESTALPHA, + D3DBLEND_INVDESTALPHA, + D3DBLEND_DESTCOLOR, + D3DBLEND_INVDESTCOLOR, + D3DBLEND_SRCALPHASAT +}; + +uint32 alphafuncMap[] = { + D3DCMP_ALWAYS, + D3DCMP_GREATEREQUAL, + D3DCMP_LESS +}; + +static void +setRwRenderState(int32 state, uint32 value) +{ + uint32 bval = value ? TRUE : FALSE; + switch(state){ + case VERTEXALPHA: + setVertexAlpha(bval); + break; + case SRCBLEND: + if(srcblend != value){ + srcblend = value; + setRenderState(D3DRS_SRCBLEND, blendMap[value]); + } + break; + case DESTBLEND: + if(destblend != value){ + destblend = value; + setRenderState(D3DRS_DESTBLEND, blendMap[value]); + } + break; + case ZTESTENABLE: + if(ztest != bval){ + ztest = bval; + setRenderState(D3DRS_ZENABLE, ztest); + } + break; + case ZWRITEENABLE: + if(zwrite != bval){ + zwrite = bval; + setRenderState(D3DRS_ZWRITEENABLE, zwrite); + } + break; + case FOGENABLE: + if(fogenable != bval){ + fogenable = bval; + setRenderState(D3DRS_FOGENABLE, fogenable); + }; + break; + case FOGCOLOR:{ + RGBA c = *(RGBA*)&value; + if(!equal(fogcolor, c)){ + fogcolor = c; + setRenderState(D3DRS_FOGCOLOR, D3DCOLOR_RGBA(c.red, c.green, c.blue, c.alpha)); + }} break; + case ALPHATESTFUNC: + if(alphafunc != value){ + alphafunc = value; + setRenderState(D3DRS_ALPHAFUNC, alphafuncMap[alphafunc]); + } + break; + case ALPHATESTREF: + if(alpharef != value){ + alpharef = value; + setRenderState(D3DRS_ALPHAREF, alpharef); + } + break; + } +} + +static uint32 +getRwRenderState(int32 state) +{ + switch(state){ + case VERTEXALPHA: + return vertexAlpha; + case SRCBLEND: + return srcblend; + case DESTBLEND: + return destblend; + case ZTESTENABLE: + return ztest; + case ZWRITEENABLE: + return zwrite; + case FOGENABLE: + return fogenable; + case FOGCOLOR: + return *(uint32*)&fogcolor; + case ALPHATESTFUNC: + return alphafunc; + case ALPHATESTREF: + return alpharef; + } + return 0; +} + void setRasterStage(uint32 stage, Raster *raster) { + bool32 alpha; D3dRaster *d3draster = nil; if(raster != d3dRaster[stage]){ d3dRaster[stage] = raster; if(raster){ d3draster = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); - device->SetTexture(stage, (IDirect3DTexture9*)d3draster->texture); - }else - device->SetTexture(stage, nil); + d3ddevice->SetTexture(stage, (IDirect3DTexture9*)d3draster->texture); + alpha = d3draster->hasAlpha; + }else{ + d3ddevice->SetTexture(stage, nil); + alpha = 0; + } + if(stage == 0){ + if(textureAlpha != alpha){ + textureAlpha = alpha; + if(!vertexAlpha){ + setRenderState(D3DRS_ALPHABLENDENABLE, alpha); + setRenderState(D3DRS_ALPHATESTENABLE, alpha); + } + } + } } } @@ -173,19 +323,19 @@ setMaterial(Material *mat) d3dmaterial.Ambient.g != mat9.Ambient.g || d3dmaterial.Ambient.b != mat9.Ambient.b || d3dmaterial.Ambient.a != mat9.Ambient.a){ - device->SetMaterial(&mat9); + d3ddevice->SetMaterial(&mat9); d3dmaterial = mat9; } } -void +static void beginUpdate(Camera *cam) { float view[16], proj[16]; // View Matrix Matrix inv; - Matrix::invertOrthonormal(&inv, cam->getFrame()->getLTM()); + Matrix::invert(&inv, cam->getFrame()->getLTM()); // Since we're looking into positive Z, // flip X to ge a left handed view space. view[0] = -inv.right.x; @@ -204,7 +354,7 @@ beginUpdate(Camera *cam) view[13] = inv.pos.y; view[14] = inv.pos.z; view[15] = 1.0f; - device->SetTransform(D3DTS_VIEW, (D3DMATRIX*)view); + d3ddevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)view); // Projection Matrix float32 invwx = 1.0f/cam->viewWindow.x; @@ -237,15 +387,176 @@ beginUpdate(Camera *cam) proj[15] = 1.0f; } proj[14] = -cam->nearPlane*proj[10]; - device->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)proj); + d3ddevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)proj); + + // TODO: figure out where this is really done + setRenderState(D3DRS_FOGSTART, *(uint32*)&cam->fogPlane); + setRenderState(D3DRS_FOGEND, *(uint32*)&cam->farPlane); + + // TODO: figure out when to call this + d3ddevice->BeginScene(); } -void -initializeRender(void) +static void +endUpdate(Camera *cam) { - engine->beginUpdate = beginUpdate; + // TODO: figure out when to call this + d3ddevice->EndScene(); } +static void +clearCamera(Camera *cam, RGBA *col, uint32 mode) +{ + int flags = 0; + if(mode & Camera::CLEARIMAGE) + mode |= D3DCLEAR_TARGET; + if(mode & Camera::CLEARZ) + mode |= D3DCLEAR_ZBUFFER; + D3DCOLOR c = D3DCOLOR_RGBA(col->red, col->green, col->blue, col->alpha); + d3ddevice->Clear(0, 0, mode, c, 1.0f, 0); +} + +static void +showRaster(Raster *raster) +{ + // TODO: do this properly! + d3ddevice->Present(nil, nil, 0, nil); +} + +// taken from Frank Luna's d3d9 book +static int +startD3D(EngineStartParams *params) +{ + HWND win = params->window; + bool windowed = true; + + HRESULT hr = 0; + IDirect3D9 *d3d9 = 0; + d3d9 = Direct3DCreate9(D3D_SDK_VERSION); + if(!d3d9){ + RWERROR((ERR_GENERAL, "Direct3DCreate9() failed")); + return 0; + } + + D3DCAPS9 caps; + d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); + int vp = 0; + if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) + vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; + else + vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; + + RECT rect; + GetClientRect(win, &rect); + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + + D3DPRESENT_PARAMETERS d3dpp; + d3dpp.BackBufferWidth = width; + d3dpp.BackBufferHeight = height; + d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; + d3dpp.BackBufferCount = 1; + d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; + d3dpp.MultiSampleQuality = 0; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.hDeviceWindow = win; + d3dpp.Windowed = windowed; + d3dpp.EnableAutoDepthStencil = true; + d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; + d3dpp.Flags = 0; + d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + + IDirect3DDevice9 *dev; + hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, win, + vp, &d3dpp, &dev); + if(FAILED(hr)){ + // try again using a 16-bit depth buffer + d3dpp.AutoDepthStencilFormat = D3DFMT_D16; + + hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + win, vp, &d3dpp, &dev); + + if(FAILED(hr)){ + RWERROR((ERR_GENERAL, "CreateDevice() failed")); + d3d9->Release(); + return 0; + } + } + d3d9->Release(); + d3d::d3ddevice = dev; + return 1; +} + +static int +stopD3D(void) +{ + d3d::d3ddevice->Release(); + d3d::d3ddevice = nil; + return 1; +} + +static int +initD3D(void) +{ + // TODO: do some real stuff here + + d3ddevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); + alphafunc = ALPHAGREATEREQUAL; + d3ddevice->SetRenderState(D3DRS_ALPHAREF, 10); + alpharef = 10; + + d3ddevice->SetRenderState(D3DRS_FOGENABLE, FALSE); + fogenable = 0; + d3ddevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_LINEAR); + // TODO: more fog stuff + + d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + + d3ddevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + srcblend = BLENDSRCALPHA; + d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + destblend = BLENDINVSRCALPHA; + d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 0); + vertexAlpha = 0; + textureAlpha = 0; + + setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); +// setTextureStageState(0, D3DTSS_CONSTANT, 0xFFFFFFFF); +// setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); +// setTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CONSTANT); +// setTextureStageState(0, D3DTSS_COLOROP, D3DTA_CONSTANT); + + return 1; +} + +static int +deviceSystem(DeviceReq req, void *arg0) +{ + switch(req){ + case DEVICESTART: + return startD3D((EngineStartParams*)arg0); + case DEVICEINIT: + return initD3D(); + case DEVICESTOP: + return stopD3D(); + } + return 1; +} + +Device renderdevice = { + 0.0f, 1.0f, + d3d::beginUpdate, + d3d::endUpdate, + d3d::clearCamera, + d3d::showRaster, + d3d::setRwRenderState, + d3d::getRwRenderState, + null::im2DRenderIndexedPrimitive, + d3d::deviceSystem, +}; + #endif } } diff --git a/src/d3d/d3drender.cpp b/src/d3d/d3drender.cpp new file mode 100644 index 0000000..828b4ce --- /dev/null +++ b/src/d3d/d3drender.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include + +#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 + +void +lightingCB(void) +{ + World *world; + RGBAf ambLight = { 0.0, 0.0, 0.0, 1.0 }; + 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; + int n = 0; + + world = (World*)engine->currentWorld; + // only unpositioned lights right now + FORLIST(lnk, world->directionalLights){ + Light *l = Light::fromWorld(lnk); + if(l->getType() == Light::DIRECTIONAL){ + if(n >= MAX_LIGHTS) + continue; + light.Diffuse = *(D3DCOLORVALUE*)&l->color; + light.Direction = *(D3DVECTOR*)&l->getFrame()->getLTM()->at; + d3ddevice->SetLight(n, &light); + d3ddevice->LightEnable(n, TRUE); + n++; + }else if(l->getType() == Light::AMBIENT){ + ambLight.red += l->color.red; + ambLight.green += l->color.green; + ambLight.blue += l->color.blue; + } + } + for(; n < MAX_LIGHTS; n++) + d3ddevice->LightEnable(n, FALSE); + convColor(&amb, &ambLight); + d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_RGBA(amb.red, amb.green, amb.blue, amb.alpha)); +} + +#endif + +} +} diff --git a/src/d3d/rwd3d.h b/src/d3d/rwd3d.h index bc0014b..836d8d3 100644 --- a/src/d3d/rwd3d.h +++ b/src/d3d/rwd3d.h @@ -4,14 +4,23 @@ #endif namespace rw { -namespace d3d { -void initializeRender(void); +#ifdef RW_D3D9 +struct EngineStartParams +{ + HWND window; +}; +#endif + +namespace d3d { extern bool32 isP8supported; #ifdef RW_D3D9 -extern IDirect3DDevice9 *device; +extern IDirect3DDevice9 *d3ddevice; +extern Device renderdevice; + +void lightingCB(void); #else enum { D3DLOCK_NOSYSLOCK = 0, // ignored diff --git a/src/d3d/xbox.cpp b/src/d3d/xbox.cpp index 406c40f..5adb2c9 100644 --- a/src/d3d/xbox.cpp +++ b/src/d3d/xbox.cpp @@ -21,13 +21,13 @@ namespace xbox { void* driverOpen(void *o, int32, int32) { - driver[PLATFORM_XBOX]->defaultPipeline = makeDefaultPipeline(); + engine->driver[PLATFORM_XBOX]->defaultPipeline = makeDefaultPipeline(); - driver[PLATFORM_XBOX]->rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_XBOX]->rasterCreate = rasterCreate; - driver[PLATFORM_XBOX]->rasterLock = rasterLock; - driver[PLATFORM_XBOX]->rasterUnlock = rasterUnlock; - driver[PLATFORM_XBOX]->rasterNumLevels = rasterNumLevels; + engine->driver[PLATFORM_XBOX]->rasterNativeOffset = nativeRasterOffset; + engine->driver[PLATFORM_XBOX]->rasterCreate = rasterCreate; + engine->driver[PLATFORM_XBOX]->rasterLock = rasterLock; + engine->driver[PLATFORM_XBOX]->rasterUnlock = rasterUnlock; + engine->driver[PLATFORM_XBOX]->rasterNumLevels = rasterNumLevels; // TODO: from image return o; @@ -71,7 +71,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) uint32 vers; uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, &vers)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); @@ -622,7 +622,7 @@ readNativeTexture(Stream *stream) { uint32 vers, platform; if(!findChunk(stream, ID_STRUCT, nil, &vers)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); diff --git a/src/d3d/xboxplugins.cpp b/src/d3d/xboxplugins.cpp index 2561b8f..8dc6eca 100644 --- a/src/d3d/xboxplugins.cpp +++ b/src/d3d/xboxplugins.cpp @@ -35,7 +35,7 @@ readNativeSkin(Stream *stream, int32, void *object, int32 offset) Geometry *geometry = (Geometry*)object; uint32 vers, platform; if(!findChunk(stream, ID_STRUCT, nil, &vers)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); diff --git a/src/engine.cpp b/src/engine.cpp index 833277e..5b78309 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -3,6 +3,7 @@ #include #include "rwbase.h" +#include "rwerror.h" #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" @@ -15,22 +16,55 @@ #include "gl/rwgl3.h" #include "gl/rwwdgl.h" +#define PLUGIN_ID 0 + namespace rw { Engine *engine; -Driver *driver[NUM_PLATFORMS]; +PluginList Driver::s_plglist[NUM_PLATFORMS]; +Engine::State Engine::state = Dead; -void +// This function mainly registers engine plugins +// RW initializes memory related things here too and +// uses more plugins +// TODO: do this^ ? +bool32 Engine::init(void) { - engine = new Engine; - PluginList init = { sizeof(Driver), sizeof(Driver), nil, nil }; + if(engine || Engine::state != Dead){ + RWERROR((ERR_ENGINEINIT)); + return 0; + } + PluginList init = { sizeof(Driver), sizeof(Driver), nil, nil }; for(uint i = 0; i < NUM_PLATFORMS; i++) Driver::s_plglist[i] = init; - Frame::dirtyList.init(); + // Register plugins + // TODO: these are wrong + ps2::initializePlatform(); + xbox::initializePlatform(); + d3d8::initializePlatform(); + d3d9::initializePlatform(); + wdgl::initializePlatform(); + gl3::initializePlatform(); + Engine::state = Initialized; + return 1; +} + +// This is where RW allocates the engine and e.g. opens d3d +// TODO: this will take an argument with device specific data (HWND &c.) +bool32 +Engine::open(void) +{ + if(engine || Engine::state != Initialized){ + RWERROR((ERR_ENGINEOPEN)); + return 0; + } + + // Allocate engine + engine = (Engine*)malloc(sizeof(Engine)); engine->currentCamera = nil; engine->currentWorld = nil; engine->currentTexDictionary = nil; @@ -38,45 +72,66 @@ Engine::init(void) engine->loadTextures = 1; engine->makeDummies = 1; - engine->beginUpdate = null::beginUpdate; - engine->endUpdate = null::endUpdate; - engine->clearCamera = null::clearCamera; - engine->setRenderState = null::setRenderState; - engine->getRenderState = null::getRenderState; - engine->im2DRenderIndexedPrimitive = null::im2DRenderIndexedPrimitive; - engine->zNear = 0.0f; // random values - engine->zFar = 1.0f; + // Initialize device + // Device and possibly OS specific! +#ifdef RW_GL3 + engine->device = gl3::renderdevice; +#elif RW_D3D9 + engine->device = d3d::renderdevice; +#else + engine->device = null::renderdevice; +#endif - ps2::initializePlatform(); - xbox::initializePlatform(); - d3d8::initializePlatform(); - d3d9::initializePlatform(); - wdgl::initializePlatform(); - gl3::initializePlatform(); + // TODO: open device; create d3d object/get video mode + + // TODO: init driver functions + ObjPipeline *defpipe = new ObjPipeline(PLATFORM_NULL); + for(uint i = 0; i < NUM_PLATFORMS; i++){ + rw::engine->driver[i] = (Driver*)malloc(Driver::s_plglist[i].size); + + engine->driver[i]->defaultPipeline = defpipe; + + engine->driver[i]->rasterCreate = null::rasterCreate; + engine->driver[i]->rasterLock = null::rasterLock; + engine->driver[i]->rasterUnlock = null::rasterUnlock; + engine->driver[i]->rasterNumLevels = null::rasterNumLevels; + engine->driver[i]->rasterFromImage = null::rasterFromImage; + engine->driver[i]->rasterToImage = null::rasterToImage; + } + + Engine::state = Opened; + return 1; } -PluginList Driver::s_plglist[NUM_PLATFORMS]; +// This is where RW creates the actual rendering device +// ans calls the engine plugin ctors +bool32 +Engine::start(EngineStartParams *p) +{ + if(engine == nil || Engine::state != Opened){ + RWERROR((ERR_ENGINESTART)); + return 0; + } + + // Start device + engine->device.system(DEVICESTART, (void*)p); + engine->device.system(DEVICEINIT, nil); + + // TODO: construct engine plugins + Frame::dirtyList.init(); + for(uint i = 0; i < NUM_PLATFORMS; i++) + Driver::s_plglist[i].construct(rw::engine->driver[i]); + + // TODO: finalize device start + + Engine::state = Started; + return 1; +} void -Driver::open(void) +Engine::stop(void) { - ObjPipeline *defpipe = new ObjPipeline(PLATFORM_NULL); - - for(uint i = 0; i < NUM_PLATFORMS; i++){ - rw::driver[i] = (Driver*)malloc(s_plglist[i].size); - - driver[i]->defaultPipeline = defpipe; - - driver[i]->rasterCreate = null::rasterCreate; - driver[i]->rasterLock = null::rasterLock; - driver[i]->rasterUnlock = null::rasterUnlock; - driver[i]->rasterNumLevels = null::rasterNumLevels; - driver[i]->rasterFromImage = null::rasterFromImage; - driver[i]->rasterToImage = null::rasterToImage; - - - s_plglist[i].construct(rw::driver[i]); - } + engine->device.system(DEVICESTOP, nil); } namespace null { @@ -84,6 +139,7 @@ namespace null { void beginUpdate(Camera*) { } void endUpdate(Camera*) { } void clearCamera(Camera*,RGBA*,uint32) { } +void showRaster(Raster*) { } void setRenderState(int32, uint32) { } uint32 getRenderState(int32) { return 0; } @@ -129,5 +185,23 @@ rasterToImage(Raster*) return nil; } +int +devicesystem(DeviceReq req, void *arg0) +{ + return 1; +} + +Device renderdevice = { + 0.0f, 1.0f, + null::beginUpdate, + null::endUpdate, + null::clearCamera, + null::showRaster, + null::setRenderState, + null::getRenderState, + null::im2DRenderIndexedPrimitive, + null::devicesystem +}; + } } diff --git a/src/geoplg.cpp b/src/geoplg.cpp index 36a164b..821735f 100644 --- a/src/geoplg.cpp +++ b/src/geoplg.cpp @@ -8,6 +8,7 @@ #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" +#include "rwengine.h" #include "rwanim.h" #include "rwplugins.h" #include "ps2/rwps2.h" diff --git a/src/gl/gl3.cpp b/src/gl/gl3.cpp index eaf7b5d..d4d8f1f 100644 --- a/src/gl/gl3.cpp +++ b/src/gl/gl3.cpp @@ -26,14 +26,14 @@ void* driverOpen(void *o, int32, int32) { #ifdef RW_OPENGL - driver[PLATFORM_GL3]->defaultPipeline = makeDefaultPipeline(); + engine->driver[PLATFORM_GL3]->defaultPipeline = makeDefaultPipeline(); #endif - driver[PLATFORM_GL3]->rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_GL3]->rasterCreate = rasterCreate; - driver[PLATFORM_GL3]->rasterLock = rasterLock; - driver[PLATFORM_GL3]->rasterUnlock = rasterUnlock; - driver[PLATFORM_GL3]->rasterNumLevels = rasterNumLevels; - driver[PLATFORM_GL3]->rasterFromImage = rasterFromImage; + engine->driver[PLATFORM_GL3]->rasterNativeOffset = nativeRasterOffset; + engine->driver[PLATFORM_GL3]->rasterCreate = rasterCreate; + engine->driver[PLATFORM_GL3]->rasterLock = rasterLock; + engine->driver[PLATFORM_GL3]->rasterUnlock = rasterUnlock; + engine->driver[PLATFORM_GL3]->rasterNumLevels = rasterNumLevels; + engine->driver[PLATFORM_GL3]->rasterFromImage = rasterFromImage; return o; } diff --git a/src/gl/gl3driver.cpp b/src/gl/gl3driver.cpp index d3695db..4060eee 100644 --- a/src/gl/gl3driver.cpp +++ b/src/gl/gl3driver.cpp @@ -10,10 +10,13 @@ #include "../rwengine.h" #ifdef RW_OPENGL #include +#include #include "rwgl3.h" #include "rwgl3shader.h" #include "rwgl3impl.h" +#define PLUGIN_ID 0 + namespace rw { namespace gl3 { @@ -77,7 +80,9 @@ static uint32 srcblend, destblend; static uint32 zwrite; static uint32 ztest; -uint32 blendMap[] = { +static int32 activeTexture; + +static uint32 blendMap[] = { GL_ZERO, GL_ONE, GL_SRC_COLOR, @@ -91,18 +96,26 @@ uint32 blendMap[] = { GL_SRC_ALPHA_SATURATE, }; -void +static void +setVertexAlpha(bool32 enable) +{ + if(vertexAlpha != enable){ + vertexAlpha = enable; + if(!textureAlpha){ + if(enable) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + } + } +} + +static void setRenderState(int32 state, uint32 value) { switch(state){ case VERTEXALPHA: - if(vertexAlpha != value){ - vertexAlpha = value; - if(vertexAlpha) - glEnable(GL_BLEND); - else if(!textureAlpha) - glDisable(GL_BLEND); - } + setVertexAlpha(value); break; case SRCBLEND: if(srcblend != value){ @@ -158,7 +171,7 @@ setRenderState(int32 state, uint32 value) } } -uint32 +static uint32 getRenderState(int32 state) { RGBA rgba; @@ -182,15 +195,15 @@ getRenderState(int32 state) case ALPHATESTFUNC: return uniformState.alphaFunc; case ALPHATESTREF: - return uniformState.alphaRef*255.0f; + return (uint32)(uniformState.alphaRef*255.0f); } return 0; } -void +static void resetRenderState(void) { - uniformState.alphaFunc = ALPHAGREATERTHAN; + uniformState.alphaFunc = ALPHAGREATEREQUAL; uniformState.alphaRef = 10.0f/255.0f; uniformState.fogEnable = 0; uniformState.fogStart = 0.0f; @@ -254,7 +267,7 @@ setLight(int32 n, Light *light) l->direction = m->at; } // light has position - l->w = light->getType() >= Light::POINT ? 1.0f : 0.0; + l->w = light->getType() >= Light::POINT ? 1.0f : 0.0f; l->color = light->color; l->radius = light->radius; l->minusCosAngle = light->minusCosAngle; @@ -275,11 +288,20 @@ setViewMatrix(float32 *mat) sceneDirty = 1; } +static void +setActiveTexture(int32 n) +{ + if(activeTexture != n){ + activeTexture = n; + glActiveTexture(n); + } +} + void setTexture(int32 n, Texture *tex) { bool32 alpha; - glActiveTexture(GL_TEXTURE0+n); + setActiveTexture(GL_TEXTURE0+n); if(tex == nil || tex->raster->platform != PLATFORM_GL3 || tex->raster->width == 0){ glBindTexture(GL_TEXTURE_2D, whitetex); @@ -291,12 +313,16 @@ setTexture(int32 n, Texture *tex) alpha = natras->hasAlpha; } - if(textureAlpha != alpha){ - textureAlpha = alpha; - if(textureAlpha) - glEnable(GL_BLEND); - else if(!vertexAlpha) - glDisable(GL_BLEND); + if(n == 0){ + if(alpha != textureAlpha){ + textureAlpha = alpha; + if(!vertexAlpha){ + if(alpha) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + } + } } } @@ -323,7 +349,7 @@ flushCache(void) } } -void +static void clearCamera(Camera *cam, RGBA *col, uint32 mode) { RGBAf colf; @@ -339,7 +365,16 @@ clearCamera(Camera *cam, RGBA *col, uint32 mode) glClear(mask); } -void +static GLFWwindow *glfwwindow; + +static void +showRaster(Raster *raster) +{ + // TODO: do this properly! + glfwSwapBuffers(glfwwindow); +} + +static void beginUpdate(Camera *cam) { float view[16], proj[16]; @@ -410,17 +445,62 @@ beginUpdate(Camera *cam) } } -void -initializeRender(void) +static int +startGLFW(EngineStartParams *startparams) { - engine->beginUpdate = beginUpdate; - engine->clearCamera = clearCamera; - engine->setRenderState = setRenderState; - engine->getRenderState = getRenderState; - engine->im2DRenderIndexedPrimitive = im2DRenderIndexedPrimitive; - engine->zNear = -1.0f; - engine->zFar = 1.0f; + GLenum status; + GLFWwindow *win; + /* Init GLFW */ + if(!glfwInit()){ + RWERROR((ERR_GENERAL, "glfwInit() failed")); + return 0; + } + glfwWindowHint(GLFW_SAMPLES, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + win = glfwCreateWindow(startparams->width, startparams->height, startparams->windowtitle, 0, 0); + if(win == nil){ + RWERROR((ERR_GENERAL, "glfwCreateWindow() failed")); + glfwTerminate(); + return 0; + } + glfwMakeContextCurrent(win); + + /* Init GLEW */ + glewExperimental = GL_TRUE; + status = glewInit(); + if(status != GLEW_OK){ + RWERROR((ERR_GENERAL, glewGetErrorString(status))); + glfwDestroyWindow(win); + glfwTerminate(); + return 0; + } + if(!GLEW_VERSION_3_3){ + RWERROR((ERR_GENERAL, "OpenGL 3.3 needed")); + glfwDestroyWindow(win); + glfwTerminate(); + return 0; + } + glfwwindow = win; + *startparams->window = win; + return 1; +} + +static int +stopGLFW(void) +{ + glfwDestroyWindow(glfwwindow); + glfwTerminate(); + return 1; +} + +static int +initOpenGL(void) +{ #include "shaders/simple_gl3.inc" simpleShader = Shader::fromStrings(simple_vert_src, simple_frag_src); @@ -438,7 +518,6 @@ initializeRender(void) GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); - glGenBuffers(1, &ubo_scene); glBindBuffer(GL_UNIFORM_BUFFER, ubo_scene); glBindBufferBase(GL_UNIFORM_BUFFER, gl3::findBlock("Scene"), ubo_scene); @@ -446,7 +525,6 @@ initializeRender(void) GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); - glGenBuffers(1, &ubo_object); glBindBuffer(GL_UNIFORM_BUFFER, ubo_object); glBindBufferBase(GL_UNIFORM_BUFFER, gl3::findBlock("Object"), ubo_object); @@ -454,7 +532,6 @@ initializeRender(void) GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); - byte whitepixel[4] = {0xFF, 0xFF, 0xFF, 0xFF}; glGenTextures(1, &whitetex); glBindTexture(GL_TEXTURE_2D, whitetex); @@ -464,7 +541,35 @@ initializeRender(void) 0, GL_RGBA, GL_UNSIGNED_BYTE, &whitepixel); im2DInit(); + return 1; } + +static int +deviceSystem(DeviceReq req, void *arg0) +{ + switch(req){ + case DEVICESTART: + return startGLFW((EngineStartParams*)arg0); + case DEVICEINIT: + return initOpenGL(); + case DEVICESTOP: + return stopGLFW(); + } + return 1; +} + +Device renderdevice = { + -1.0f, 1.0f, + gl3::beginUpdate, + null::endUpdate, + gl3::clearCamera, + gl3::showRaster, + gl3::setRenderState, + gl3::getRenderState, + gl3::im2DRenderIndexedPrimitive, + gl3::deviceSystem +}; + } } diff --git a/src/gl/gl3render.cpp b/src/gl/gl3render.cpp index 90783b7..fd345a7 100644 --- a/src/gl/gl3render.cpp +++ b/src/gl/gl3render.cpp @@ -43,7 +43,7 @@ void lightingCB(void) { World *world; - RGBAf ambLight = (RGBAf){0.0, 0.0, 0.0, 1.0}; + RGBAf ambLight = { 0.0, 0.0, 0.0, 1.0 }; int n = 0; world = (World*)engine->currentWorld; @@ -84,9 +84,6 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) InstanceData *inst = header->inst; int32 n = header->numMeshes; -// rw::setRenderState(ALPHATESTFUNC, 1); -// rw::setRenderState(ALPHATESTREF, 50); - simpleShader->use(); while(n--){ diff --git a/src/gl/gl3shader.cpp b/src/gl/gl3shader.cpp index be879a0..fa16bb8 100644 --- a/src/gl/gl3shader.cpp +++ b/src/gl/gl3shader.cpp @@ -189,8 +189,10 @@ Shader::fromFiles(const char *vspath, const char *fspath) void Shader::use(void) { - glUseProgram(this->program); - currentShader = this; + if(currentShader != this){ + glUseProgram(this->program); + currentShader = this; + } } } diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index 0a51e9a..313ea6d 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -1,8 +1,24 @@ +#ifdef RW_GL3 +#include +#include +#endif + namespace rw { + +#ifdef RW_GL3 +struct EngineStartParams +{ + GLFWwindow **window; + int width, height; + const char *windowtitle; +}; +#endif + namespace gl3 { void initializePlatform(void); -void initializeRender(void); + +extern Device renderdevice; // arguments to glVertexAttribPointer basically struct AttribDesc diff --git a/src/gl/shaders/im2d.frag b/src/gl/shaders/im2d.frag index b40c2f9..91bfc3e 100644 --- a/src/gl/shaders/im2d.frag +++ b/src/gl/shaders/im2d.frag @@ -10,6 +10,6 @@ out vec4 color; void main(void) { - color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y)); + color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y)); } diff --git a/src/gl/shaders/im2d_gl3.inc b/src/gl/shaders/im2d_gl3.inc index 23af07c..6230350 100644 --- a/src/gl/shaders/im2d_gl3.inc +++ b/src/gl/shaders/im2d_gl3.inc @@ -36,7 +36,7 @@ const char *im2d_frag_src = "void\n" "main(void)\n" "{\n" -" color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y));\n" +" color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y));\n" "}\n" ; diff --git a/src/gl/shaders/matfx_env.frag b/src/gl/shaders/matfx_env.frag index 5c9522d..ed90362 100644 --- a/src/gl/shaders/matfx_env.frag +++ b/src/gl/shaders/matfx_env.frag @@ -17,7 +17,7 @@ out vec4 color; void main(void) { - color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y)); + color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y)); switch(u_alphaTest){ default: case 0: break; diff --git a/src/gl/shaders/matfx_gl3.inc b/src/gl/shaders/matfx_gl3.inc index 3a8f5f5..8b65b64 100644 --- a/src/gl/shaders/matfx_gl3.inc +++ b/src/gl/shaders/matfx_gl3.inc @@ -78,7 +78,7 @@ const char *matfx_env_frag_src = "void\n" "main(void)\n" "{\n" -" color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y));\n" +" color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y));\n" " switch(u_alphaTest){\n" " default:\n" " case 0: break;\n" diff --git a/src/gl/shaders/simple.frag b/src/gl/shaders/simple.frag index 11b2939..770d62b 100644 --- a/src/gl/shaders/simple.frag +++ b/src/gl/shaders/simple.frag @@ -22,7 +22,7 @@ out vec4 color; void main(void) { - color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y)); + color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y)); if(u_fogEnable != 0) color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog); switch(u_alphaTest){ diff --git a/src/gl/shaders/simple_gl3.inc b/src/gl/shaders/simple_gl3.inc index 6d0e614..76a21f8 100644 --- a/src/gl/shaders/simple_gl3.inc +++ b/src/gl/shaders/simple_gl3.inc @@ -95,7 +95,7 @@ const char *simple_frag_src = "void\n" "main(void)\n" "{\n" -" color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y));\n" +" color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y));\n" " if(u_fogEnable != 0)\n" " color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n" " switch(u_alphaTest){\n" diff --git a/src/gl/wdgl.cpp b/src/gl/wdgl.cpp index 60029ef..123c7d5 100644 --- a/src/gl/wdgl.cpp +++ b/src/gl/wdgl.cpp @@ -25,7 +25,7 @@ namespace wdgl { void* driverOpen(void *o, int32, int32) { - driver[PLATFORM_WDGL]->defaultPipeline = makeDefaultPipeline(); + engine->driver[PLATFORM_WDGL]->defaultPipeline = makeDefaultPipeline(); return o; } diff --git a/src/hanim.cpp b/src/hanim.cpp index 32b824c..d2daf6e 100644 --- a/src/hanim.cpp +++ b/src/hanim.cpp @@ -8,6 +8,7 @@ #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" +#include "rwengine.h" #include "rwanim.h" #include "rwplugins.h" #include "ps2/rwps2.h" diff --git a/src/image.cpp b/src/image.cpp index fd97f49..06a7ef3 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -917,7 +917,7 @@ Raster::create(int32 width, int32 height, int32 depth, int32 format, int32 platf s_plglist.construct(raster); // printf("%d %d %d %d\n", raster->type, raster->width, raster->height, raster->depth); - driver[raster->platform]->rasterCreate(raster); + engine->driver[raster->platform]->rasterCreate(raster); return raster; } @@ -933,19 +933,19 @@ Raster::destroy(void) uint8* Raster::lock(int32 level) { - return driver[this->platform]->rasterLock(this, level); + return engine->driver[this->platform]->rasterLock(this, level); } void Raster::unlock(int32 level) { - driver[this->platform]->rasterUnlock(this, level); + engine->driver[this->platform]->rasterUnlock(this, level); } int32 Raster::getNumLevels(void) { - return driver[this->platform]->rasterNumLevels(this); + return engine->driver[this->platform]->rasterNumLevels(this); } int32 @@ -964,14 +964,14 @@ Raster::createFromImage(Image *image, int32 platform) Raster *raster = Raster::create(image->width, image->height, image->depth, TEXTURE | DONTALLOCATE, platform); - driver[raster->platform]->rasterFromImage(raster, image); + engine->driver[raster->platform]->rasterFromImage(raster, image); return raster; } Image* Raster::toImage(void) { - return driver[this->platform]->rasterToImage(this); + return engine->driver[this->platform]->rasterToImage(this); } } diff --git a/src/ps2/ps2.cpp b/src/ps2/ps2.cpp index ec29a1c..b4a22f6 100644 --- a/src/ps2/ps2.cpp +++ b/src/ps2/ps2.cpp @@ -24,13 +24,13 @@ namespace ps2 { void* driverOpen(void *o, int32, int32) { - driver[PLATFORM_PS2]->defaultPipeline = makeDefaultPipeline(); + engine->driver[PLATFORM_PS2]->defaultPipeline = makeDefaultPipeline(); - driver[PLATFORM_PS2]->rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_PS2]->rasterCreate = rasterCreate; - driver[PLATFORM_PS2]->rasterLock = rasterLock; - driver[PLATFORM_PS2]->rasterUnlock = rasterUnlock; - driver[PLATFORM_PS2]->rasterNumLevels = rasterNumLevels; + engine->driver[PLATFORM_PS2]->rasterNativeOffset = nativeRasterOffset; + engine->driver[PLATFORM_PS2]->rasterCreate = rasterCreate; + engine->driver[PLATFORM_PS2]->rasterLock = rasterLock; + engine->driver[PLATFORM_PS2]->rasterUnlock = rasterUnlock; + engine->driver[PLATFORM_PS2]->rasterNumLevels = rasterNumLevels; return o; } @@ -73,7 +73,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) Geometry *geometry = (Geometry*)object; uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); diff --git a/src/ps2/ps2raster.cpp b/src/ps2/ps2raster.cpp index 363e45b..e69c057 100644 --- a/src/ps2/ps2raster.cpp +++ b/src/ps2/ps2raster.cpp @@ -559,7 +559,7 @@ registerNativeRaster(void) void printTEX0(uint64 tex0) { - printf("%016lX ", tex0); + printf("%016llX ", tex0); uint32 tbp0 = tex0 & 0x3FFF; tex0 >>= 14; uint32 tbw = tex0 & 0x3F; tex0 >>= 6; uint32 psm = tex0 & 0x3F; tex0 >>= 6; @@ -579,7 +579,7 @@ printTEX0(uint64 tex0) void printTEX1(uint64 tex1) { - printf("%016lX ", tex1); + printf("%016llX ", tex1); uint32 lcm = tex1 & 0x1; tex1 >>= 2; uint32 mxl = tex1 & 0x7; tex1 >>= 3; uint32 mmag = tex1 & 0x1; tex1 >>= 1; diff --git a/src/ps2/ps2skin.cpp b/src/ps2/ps2skin.cpp index f605fa3..36609b4 100644 --- a/src/ps2/ps2skin.cpp +++ b/src/ps2/ps2skin.cpp @@ -74,7 +74,7 @@ readNativeSkin(Stream *stream, int32, void *object, int32 offset) Geometry *geometry = (Geometry*)object; uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); diff --git a/src/rwengine.h b/src/rwengine.h index aa88f9a..1428c1e 100644 --- a/src/rwengine.h +++ b/src/rwengine.h @@ -22,9 +22,9 @@ enum RenderState enum AlphaTestFunc { - ALPHANEVER = 0, - ALPHALESS, - ALPHAGREATERTHAN + ALPHAALWAYS = 0, + ALPHAGREATEREQUAL, + ALPHALESS }; enum BlendFunction @@ -43,37 +43,35 @@ enum BlendFunction // TODO: add more perhaps }; -// This is for platform independent things and the render device (of which -// there can only ever be one). -// TODO: move more stuff into this -struct Engine +enum DeviceReq { - void *currentCamera; - void *currentWorld; - Texture *imtexture; + // Device/Context creation + DEVICESTART, + // Device initialization before Engine/Driver plugins are opened + DEVICEINIT, + // Device/Context shutdown + DEVICESTOP, +}; - TexDictionary *currentTexDictionary; - bool32 loadTextures; // load textures from files - bool32 makeDummies; // create dummy textures to store just names +typedef int DeviceSystem(DeviceReq req, void *arg0); - - // Device +// This is for the render device, we only have one +struct Device +{ float32 zNear, zFar; void (*beginUpdate)(Camera*); void (*endUpdate)(Camera*); void (*clearCamera)(Camera*, RGBA *col, uint32 mode); + void (*showRaster)(Raster *raster); void (*setRenderState)(int32 state, uint32 value); uint32 (*getRenderState)(int32 state); void (*im2DRenderIndexedPrimitive)(PrimitiveType, void*, int32, void*, int32); - - static void init(void); + DeviceSystem *system; }; -extern Engine *engine; - -// This is for platform driver implementations which have to be available -// regardless of the render device. +// This is for platform-dependent but portable things +// so the engine has one for every platform struct Driver { ObjPipeline *defaultPipeline; @@ -87,7 +85,6 @@ struct Driver Image *(*rasterToImage)(Raster*); static PluginList s_plglist[NUM_PLATFORMS]; - static void open(void); static int32 registerPlugin(int32 platform, int32 size, uint32 id, Constructor ctor, Destructor dtor){ return s_plglist[platform].registerPlugin(size, id, @@ -95,14 +92,47 @@ struct Driver } }; -extern Driver *driver[NUM_PLATFORMS]; -#define DRIVER driver[rw::platform] +struct EngineStartParams; + +// This is for platform independent things +// TODO: move more stuff into this +// TODO: make this have plugins and allocate in Engine::open +struct Engine +{ + enum State { + Dead = 0, + Initialized, + Opened, + Started + }; + void *currentCamera; + void *currentWorld; + Texture *imtexture; + + 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; + + static State state; + + static bool32 init(void); + static bool32 open(void); + static bool32 start(EngineStartParams*); + static void stop(void); +}; + +extern Engine *engine; inline void SetRenderState(int32 state, uint32 value){ - engine->setRenderState(state, value); } + engine->device.setRenderState(state, value); } inline uint32 GetRenderState(int32 state){ - return engine->getRenderState(state); } + return engine->device.getRenderState(state); } namespace null { void beginUpdate(Camera*); @@ -121,6 +151,10 @@ namespace null { void im2DRenderIndexedPrimitive(PrimitiveType, void*, int32, void*, int32); + + int deviceSystem(DeviceReq req); + + extern Device renderdevice; } } diff --git a/src/rwerror.h b/src/rwerror.h index e382e89..937cc0e 100644 --- a/src/rwerror.h +++ b/src/rwerror.h @@ -20,6 +20,6 @@ char *dbgsprint(int32 code, ...); fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); \ fprintf(stderr, "%s\n", rw::dbgsprint ecode); \ rw::setError(&_e); \ -}while(0); +}while(0) } diff --git a/src/rwobjects.h b/src/rwobjects.h index 19f2dd1..5bbf75b 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -612,6 +612,7 @@ struct Camera : PluginBase void beginUpdate(void) { this->beginUpdateCB(this); } void endUpdate(void) { this->endUpdateCB(this); } void clear(RGBA *col, uint32 mode); + void showRaster(void); void setNearPlane(float32); void setFarPlane(float32); int32 frustumTestSphere(Sphere *s);