diff --git a/README.md b/README.md index 27c3a33..78ed8c5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,29 @@ librw ===== -This work in progress. -The basics of DFFs and many plugins are implemented (at least read&write). +This library is supposed to be a re-implementation of RenderWare graphics, +or a good part of it anyway. + +It is intended to be cross-platform in two senses eventually: +support rendering on different platforms similar to RW; +supporting all file formats for all platforms at all times and provide +way to convert to all other platforms. + +File formats are already supported rather well, although rasters +as used by TXD files still need some work, especially for PS2. + +As for rendering, D3D9 and OpenGL 3 work somewhat well but both still need +work. Rendering some things on the PS2 worked in the past but the code +is not maintained, it was only a test. + +# Roadmap + +* Work on platform independent rendering functions (setting render states etc.) + +* Get a solid GL3 driver working + +* Make building everything a bit easier + +# Building + +Edit the makefile(s) and type 'make BUILD=gl3' diff --git a/src/camera.cpp b/src/camera.cpp index be366cd..f8a5e48 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -29,6 +29,16 @@ defaultEndUpdateCB(Camera *cam) static void cameraSync(ObjectWithFrame*) { + // TODO: calculate view matrix here (i.e. projection * inverseLTM) + // RW projection matrix looks like this: + // (cf. Camera View Matrix white paper) + // w = viewWindow width + // h = viewWindow height + // o = view offset + // + // 1/2w 0 ox/2w + 1/2 -ox/2w + // 0 -1/2h -oy/2h + 1/2 oy/2h + // 0 0 1 0 } void @@ -169,73 +179,6 @@ Camera::streamGetSize(void) s_plglist.streamGetSize(this); } -// TODO: remove -void -Camera::updateProjectionMatrix(void) -{ - float32 invwx = 1.0f/this->viewWindow.x; - float32 invwy = 1.0f/this->viewWindow.y; - float32 invz = 1.0f/(this->farPlane-this->nearPlane); - if(rw::platform == PLATFORM_D3D8 || rw::platform == PLATFORM_D3D9 || - rw::platform == PLATFORM_XBOX){ - // is this all really correct? - this->projMat[0] = invwx; - this->projMat[1] = 0.0f; - this->projMat[2] = 0.0f; - this->projMat[3] = 0.0f; - - this->projMat[4] = 0.0f; - this->projMat[5] = invwy; - this->projMat[6] = 0.0f; - this->projMat[7] = 0.0f; - - if(this->projection == PERSPECTIVE){ - this->projMat[8] = this->viewOffset.x*invwx; - this->projMat[9] = this->viewOffset.y*invwy; - this->projMat[10] = this->farPlane*invz; - this->projMat[11] = 1.0f; - - this->projMat[12] = 0.0f; - this->projMat[13] = 0.0f; - this->projMat[14] = -this->nearPlane*this->projMat[10]; - this->projMat[15] = 0.0f; - }else{ - this->projMat[8] = 0.0f; - this->projMat[9] = 0.0f; - this->projMat[10] = invz; - this->projMat[11] = 0.0f; - - this->projMat[12] = this->viewOffset.x*invwx; - this->projMat[13] = this->viewOffset.y*invwy; - this->projMat[14] = -this->nearPlane*this->projMat[10]; - this->projMat[15] = 1.0f; - } - }else if(rw::platform == PLATFORM_WDGL || rw::platform == PLATFORM_GL3){ - this->projMat[0] = invwx; - this->projMat[1] = 0.0f; - this->projMat[2] = 0.0f; - this->projMat[3] = 0.0f; - - this->projMat[4] = 0.0f; - this->projMat[5] = invwy; - this->projMat[6] = 0.0f; - this->projMat[7] = 0.0f; - - if(this->projection == PERSPECTIVE){ - this->projMat[8] = this->viewOffset.x*invwx; - this->projMat[9] = this->viewOffset.y*invwy; - this->projMat[10] = (this->farPlane+this->nearPlane)*invz; - this->projMat[11] = 1.0f; - - this->projMat[12] = 0.0f; - this->projMat[13] = 0.0f; - this->projMat[14] = -2.0f*this->nearPlane*this->farPlane*invz; - this->projMat[15] = 0.0f; - }else{ - } - } -} - void Camera::setFOV(float32 fov, float32 ratio) { diff --git a/src/d3d/d3d8.cpp b/src/d3d/d3d8.cpp index 1637993..9195873 100644 --- a/src/d3d/d3d8.cpp +++ b/src/d3d/d3d8.cpp @@ -23,7 +23,6 @@ using namespace d3d; void* driverOpen(void *o, int32, int32) { - printf("d3d8 open\n"); driver[PLATFORM_D3D8]->defaultPipeline = makeDefaultPipeline(); driver[PLATFORM_D3D8]->rasterNativeOffset = nativeRasterOffset; diff --git a/src/d3d/d3d9.cpp b/src/d3d/d3d9.cpp index fb91b2f..4c41077 100644 --- a/src/d3d/d3d9.cpp +++ b/src/d3d/d3d9.cpp @@ -30,7 +30,6 @@ using namespace d3d; void* driverOpen(void *o, int32, int32) { - printf("d3d9 open\n"); driver[PLATFORM_D3D9]->defaultPipeline = makeDefaultPipeline(); driver[PLATFORM_D3D9]->rasterNativeOffset = nativeRasterOffset; diff --git a/src/d3d/d3ddriver.cpp b/src/d3d/d3ddriver.cpp index 37ea7c6..8644b6e 100644 --- a/src/d3d/d3ddriver.cpp +++ b/src/d3d/d3ddriver.cpp @@ -177,6 +177,82 @@ setMaterial(Material *mat) } } +void +beginUpdate(Camera *cam) +{ + float view[16], proj[16]; + + // View Matrix + Matrix inv; + // TODO: this can be simplified, or we use matrix flags.... + 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; + view[1] = inv.right.y; + view[2] = inv.right.z; + view[3] = 0.0f; + view[4] = -inv.up.x; + view[5] = inv.up.y; + view[6] = inv.up.z; + view[7] = 0.0f; + view[8] = -inv.at.x; + view[9] = inv.at.y; + view[10] = inv.at.z; + view[11] = 0.0f; + view[12] = -inv.pos.x; + view[13] = inv.pos.y; + view[14] = inv.pos.z; + view[15] = 1.0f; + device->SetTransform(D3DTS_VIEW, (D3DMATRIX*)view); + + // Projection Matrix + float32 invwx = 1.0f/this->viewWindow.x; + float32 invwy = 1.0f/this->viewWindow.y; + float32 invz = 1.0f/(this->farPlane-this->nearPlane); + + // is this all really correct? RW code looks a bit different... + proj[0] = invwx; + proj[1] = 0.0f; + proj[2] = 0.0f; + proj[3] = 0.0f; + + proj[4] = 0.0f; + proj[5] = invwy; + proj[6] = 0.0f; + proj[7] = 0.0f; + + if(this->projection == PERSPECTIVE){ + proj[8] = this->viewOffset.x*invwx; + proj[9] = this->viewOffset.y*invwy; + proj[10] = this->farPlane*invz; + proj[11] = 1.0f; + + proj[12] = 0.0f; + proj[13] = 0.0f; + proj[14] = -this->nearPlane*this->projMat[10]; + proj[15] = 0.0f; + }else{ + proj[8] = 0.0f; + proj[9] = 0.0f; + proj[10] = invz; + proj[11] = 0.0f; + + proj[12] = this->viewOffset.x*invwx; + proj[13] = this->viewOffset.y*invwy; + proj[14] = -this->nearPlane*this->projMat[10]; + proj[15] = 1.0f; + } + device->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)proj); +} + +void +initializeRender(void) +{ + driver[PLATFORM_D3D8]->beginUpdate = beginUpdate; + driver[PLATFORM_D3D9]->beginUpdate = beginUpdate; +} + #endif } } diff --git a/src/d3d/rwd3d.h b/src/d3d/rwd3d.h index 04ebde0..babaeda 100644 --- a/src/d3d/rwd3d.h +++ b/src/d3d/rwd3d.h @@ -5,6 +5,8 @@ namespace rw { namespace d3d { +void initializeRender(void); + extern bool32 isP8supported; #ifdef RW_D3D9 diff --git a/src/d3d/xbox.cpp b/src/d3d/xbox.cpp index c9a9049..58c3064 100644 --- a/src/d3d/xbox.cpp +++ b/src/d3d/xbox.cpp @@ -22,7 +22,6 @@ namespace xbox { void* driverOpen(void *o, int32, int32) { - printf("xbox open\n"); driver[PLATFORM_XBOX]->defaultPipeline = makeDefaultPipeline(); driver[PLATFORM_XBOX]->rasterNativeOffset = nativeRasterOffset; diff --git a/src/engine.cpp b/src/engine.cpp index a2a6f9b..edacdfd 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -53,6 +53,9 @@ Driver::open(void) driver[i]->beginUpdate = null::beginUpdate; driver[i]->endUpdate = null::endUpdate; + driver[i]->setRenderState = null::setRenderState; + driver[i]->getRenderState = null::getRenderState; + driver[i]->rasterCreate = null::rasterCreate; driver[i]->rasterLock = null::rasterLock; driver[i]->rasterUnlock = null::rasterUnlock; @@ -69,6 +72,8 @@ void beginUpdate(Camera*) { } void endUpdate(Camera*) { } +void setRenderState(int32, uint32) { } +uint32 getRenderState(int32) { return 0; } void rasterCreate(Raster*) diff --git a/src/gl/gl3.cpp b/src/gl/gl3.cpp index 83baa17..a63acda 100644 --- a/src/gl/gl3.cpp +++ b/src/gl/gl3.cpp @@ -26,7 +26,6 @@ namespace gl3 { void* driverOpen(void *o, int32, int32) { - printf("gl3 open\n"); #ifdef RW_OPENGL driver[PLATFORM_GL3]->defaultPipeline = makeDefaultPipeline(); #endif @@ -37,8 +36,6 @@ driverOpen(void *o, int32, int32) driver[PLATFORM_GL3]->rasterNumLevels = rasterNumLevels; driver[PLATFORM_GL3]->rasterFromImage = rasterFromImage; - initializeRender(); - return o; } diff --git a/src/gl/gl3driver.cpp b/src/gl/gl3driver.cpp new file mode 100644 index 0000000..62bc2b7 --- /dev/null +++ b/src/gl/gl3driver.cpp @@ -0,0 +1,409 @@ +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "../rwplugins.h" +#ifdef RW_OPENGL +#include +#include "rwgl3.h" +#include "rwgl3shader.h" + +namespace rw { +namespace gl3 { + +struct UniformState +{ + int alphaFunc; + float32 alphaRef; +}; + +struct UniformScene +{ + float32 proj[16]; + float32 view[16]; +}; + +struct UniformLight +{ + V3d position; + float32 w; + V3d direction; + int32 pad1; + RGBAf color; + float32 radius; + float32 minusCosAngle; + int32 pad2[2]; +}; + +#define MAX_LIGHTS 8 + +struct UniformObject +{ + Matrix world; + RGBAf ambLight; + int32 numLights; + int32 pad[3]; + UniformLight lights[MAX_LIGHTS]; +}; + +GLuint vao; +GLuint ubo_state, ubo_scene, ubo_object; +GLuint whitetex; +UniformState uniformState; +UniformScene uniformScene; +UniformObject uniformObject; + +Shader *simpleShader; + +static bool32 stateDirty = 1; +static bool32 sceneDirty = 1; +static bool32 objectDirty = 1; + +// cached render states +static bool32 vertexAlpha; +static bool32 textureAlpha; +static uint32 srcblend, destblend; +static uint32 zwrite; +static uint32 ztest; + +uint32 blendMap[] = { + GL_ZERO, + GL_ONE, + GL_SRC_COLOR, + GL_ONE_MINUS_SRC_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, + GL_ONE_MINUS_DST_ALPHA, + GL_DST_COLOR, + GL_ONE_MINUS_DST_COLOR, + GL_SRC_ALPHA_SATURATE, +}; + +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); + } + break; + case SRCBLEND: + if(srcblend != value){ + srcblend = value; + glBlendFunc(blendMap[srcblend], blendMap[destblend]); + } + break; + case DESTBLEND: + if(destblend != value){ + destblend = value; + glBlendFunc(blendMap[srcblend], blendMap[destblend]); + } + break; + case ZTESTENABLE: + if(ztest != value){ + ztest = value; + if(ztest) + glEnable(GL_DEPTH_TEST); + else + glDisable(GL_DEPTH_TEST); + } + break; + case ZWRITEENABLE: + if(zwrite != (value ? GL_TRUE : GL_FALSE)){ + zwrite = value ? GL_TRUE : GL_FALSE; + glDepthMask(zwrite); + } + break; + + case ALPHATESTFUNC: + uniformState.alphaFunc = value; + stateDirty = 1; + break; + case ALPHATESTREF: + uniformState.alphaRef = value/255.0f; + stateDirty = 1; + break; + case ZTESTFUNC: + break; + } +} + +uint32 +getRenderState(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 ALPHATESTFUNC: + return uniformState.alphaFunc; + case ALPHATESTREF: + return uniformState.alphaRef*255.0f; + case ZTESTFUNC: + break; + } +} + +void +resetRenderState(void) +{ + uniformState.alphaFunc = ALPHAGREATERTHAN; + uniformState.alphaRef = 10.0f/255.0f; + stateDirty = 1; + + vertexAlpha = 0; + textureAlpha = 0; + glDisable(GL_BLEND); + + srcblend = BLENDSRCALPHA; + destblend = BLENDINVSRCALPHA; + glBlendFunc(blendMap[srcblend], blendMap[destblend]); + + zwrite = GL_TRUE; + glDepthMask(zwrite); + + ztest = 1; + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + for(int i = 0; i < 8; i++){ + glActiveTexture(GL_TEXTURE0+i); + glBindTexture(GL_TEXTURE_2D, 0); + } +} + +void +setWorldMatrix(Matrix *mat) +{ + uniformObject.world = *mat; + objectDirty = 1; +} + +void +setAmbientLight(RGBAf *amb) +{ + uniformObject.ambLight = *amb; + objectDirty = 1; +} + +void +setNumLights(int32 n) +{ + uniformObject.numLights = n; + objectDirty = 1; +} + +void +setLight(int32 n, Light *light) +{ + UniformLight *l; + Frame *f; + Matrix *m; + + l = &uniformObject.lights[n]; + f = light->getFrame(); + if(f){ + m = f->getLTM(); + l->position = m->pos; + l->direction = m->at; + } + // light has position + l->w = light->getType() >= Light::POINT ? 1.0f : 0.0; + l->color = light->color; + l->radius = light->radius; + l->minusCosAngle = light->minusCosAngle; + objectDirty = 1; +} + +void +setProjectionMatrix(float32 *mat) +{ + memcpy(&uniformScene.proj, mat, 64); + sceneDirty = 1; +} + +void +setViewMatrix(float32 *mat) +{ + memcpy(&uniformScene.view, mat, 64); + sceneDirty = 1; +} + +void +setTexture(int32 n, Texture *tex) +{ + bool32 alpha; + glActiveTexture(GL_TEXTURE0+n); + if(tex == nil){ + glBindTexture(GL_TEXTURE_2D, whitetex); + alpha = 0; + }else{ + Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, tex->raster, + nativeRasterOffset); + glBindTexture(GL_TEXTURE_2D, natras->texid); + alpha = natras->hasAlpha; + } + + if(textureAlpha != alpha){ + textureAlpha = alpha; + if(textureAlpha) + glEnable(GL_BLEND); + else if(!vertexAlpha) + glDisable(GL_BLEND); + } +} + +void +flushCache(void) +{ + if(objectDirty){ + glBindBuffer(GL_UNIFORM_BUFFER, ubo_object); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformObject), + &uniformObject); + objectDirty = 0; + } + if(sceneDirty){ + glBindBuffer(GL_UNIFORM_BUFFER, ubo_scene); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformScene), + &uniformScene); + sceneDirty = 0; + } + if(stateDirty){ + glBindBuffer(GL_UNIFORM_BUFFER, ubo_state); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformState), + &uniformState); + stateDirty = 0; + } +} + +void +beginUpdate(Camera *cam) +{ + float view[16], proj[16]; + // View Matrix + Matrix inv; + // TODO: this can be simplified, or we use matrix flags.... + 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; + view[1] = inv.right.y; + view[2] = inv.right.z; + view[3] = 0.0f; + view[4] = -inv.up.x; + view[5] = inv.up.y; + view[6] = inv.up.z; + view[7] = 0.0f; + view[8] = -inv.at.x; + view[9] = inv.at.y; + view[10] = inv.at.z; + view[11] = 0.0f; + view[12] = -inv.pos.x; + view[13] = inv.pos.y; + view[14] = inv.pos.z; + view[15] = 1.0f; + setViewMatrix(view); + + // Projection Matrix + float32 invwx = 1.0f/cam->viewWindow.x; + float32 invwy = 1.0f/cam->viewWindow.y; + float32 invz = 1.0f/(cam->farPlane-cam->nearPlane); + + proj[0] = invwx; + proj[1] = 0.0f; + proj[2] = 0.0f; + proj[3] = 0.0f; + + proj[4] = 0.0f; + proj[5] = invwy; + proj[6] = 0.0f; + proj[7] = 0.0f; + + if(cam->projection == Camera::PERSPECTIVE){ + proj[8] = cam->viewOffset.x*invwx; + proj[9] = cam->viewOffset.y*invwy; + proj[10] = (cam->farPlane+cam->nearPlane)*invz; + proj[11] = 1.0f; + + proj[12] = 0.0f; + proj[13] = 0.0f; + proj[14] = -2.0f*cam->nearPlane*cam->farPlane*invz; + proj[15] = 0.0f; + }else{ + // TODO + } + setProjectionMatrix(proj); +} + +void +initializeRender(void) +{ + driver[PLATFORM_GL3]->beginUpdate = beginUpdate; + driver[PLATFORM_GL3]->setRenderState = setRenderState; + driver[PLATFORM_GL3]->getRenderState = getRenderState; + + simpleShader = Shader::fromFiles("simple.vert", "simple.frag"); + + glClearColor(0.25, 0.25, 0.25, 1.0); + + resetRenderState(); + + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + glGenBuffers(1, &ubo_state); + glBindBuffer(GL_UNIFORM_BUFFER, ubo_state); + glBindBufferBase(GL_UNIFORM_BUFFER, gl3::findBlock("State"), ubo_state); + glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformState), &uniformState, + 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); + glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformScene), &uniformScene, + 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); + glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformObject), &uniformObject, + 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); +} +} +} + +#endif diff --git a/src/gl/gl3plugins.cpp b/src/gl/gl3plugins.cpp index 72633c1..0326905 100644 --- a/src/gl/gl3plugins.cpp +++ b/src/gl/gl3plugins.cpp @@ -74,7 +74,7 @@ matfxDefaultRender(InstanceDataHeader *header, InstanceData *inst) setTexture(0, m->texture); - setVertexAlpha(inst->vertexAlpha || m->color.alpha != 0xFF); + rw::setRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF); flushCache(); glDrawElements(header->primType, inst->numIndex, @@ -173,15 +173,16 @@ matfxEnvRender(InstanceDataHeader *header, InstanceData *inst) setTexture(0, env->tex); - setVertexAlpha(1); - - glBlendFunc(GL_ONE, GL_ONE); + rw::setRenderState(VERTEXALPHA, 1); + rw::setRenderState(SRCBLEND, BLENDONE); + rw::setRenderState(DESTBLEND, BLENDONE); flushCache(); glDrawElements(header->primType, inst->numIndex, GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + rw::setRenderState(SRCBLEND, BLENDSRCALPHA); + rw::setRenderState(DESTBLEND, BLENDINVSRCALPHA); } void @@ -197,8 +198,8 @@ matfxRenderCB(Atomic *atomic, InstanceDataHeader *header) InstanceData *inst = header->inst; int32 n = header->numMeshes; - setAlphaTestFunc(1); - setAlphaRef(0.2); + rw::setRenderState(ALPHATESTFUNC, 1); + rw::setRenderState(ALPHATESTREF, 50); int32 fx; while(n--){ @@ -260,6 +261,11 @@ makeSkinPipeline(void) return pipe; } +#else + +void initMatFX(void) { } +void initSkin(void) { } + #endif } diff --git a/src/gl/gl3render.cpp b/src/gl/gl3render.cpp index 2e086a7..b5048b8 100644 --- a/src/gl/gl3render.cpp +++ b/src/gl/gl3render.cpp @@ -14,161 +14,13 @@ #include "rwgl3.h" #include "rwgl3shader.h" +#include "rwgl3impl.h" + namespace rw { namespace gl3 { -struct UniformState -{ - int alphaFunc; - float32 alphaRef; -}; - -struct UniformScene -{ - float32 proj[16]; - float32 view[16]; -}; - -struct UniformLight -{ - V3d position; - float32 w; - V3d direction; - int32 pad1; - RGBAf color; - float32 radius; - float32 minusCosAngle; - int32 pad2[2]; -}; - #define MAX_LIGHTS 8 -struct UniformObject -{ - Matrix world; - RGBAf ambLight; - int32 numLights; - int32 pad[3]; - UniformLight lights[MAX_LIGHTS]; -}; - -GLuint vao; -GLuint ubo_state, ubo_scene, ubo_object; -GLuint whitetex; -UniformState uniformState; -UniformScene uniformScene; -UniformObject uniformObject; - -Shader *simpleShader; - -void -beginUpdate(Camera *cam) -{ - float view[16], proj[16]; - // View Matrix - Matrix inv; - 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; - view[1] = inv.right.y; - view[2] = inv.right.z; - view[3] = 0.0f; - view[4] = -inv.up.x; - view[5] = inv.up.y; - view[6] = inv.up.z; - view[7] = 0.0f; - view[8] = -inv.at.x; - view[9] = inv.at.y; - view[10] = inv.at.z; - view[11] = 0.0f; - view[12] = -inv.pos.x; - view[13] = inv.pos.y; - view[14] = inv.pos.z; - view[15] = 1.0f; - setViewMatrix(view); - - // Projection Matrix - float32 invwx = 1.0f/cam->viewWindow.x; - float32 invwy = 1.0f/cam->viewWindow.y; - float32 invz = 1.0f/(cam->farPlane-cam->nearPlane); - - proj[0] = invwx; - proj[1] = 0.0f; - proj[2] = 0.0f; - proj[3] = 0.0f; - - proj[4] = 0.0f; - proj[5] = invwy; - proj[6] = 0.0f; - proj[7] = 0.0f; - - if(cam->projection == Camera::PERSPECTIVE){ - proj[8] = cam->viewOffset.x*invwx; - proj[9] = cam->viewOffset.y*invwy; - proj[10] = (cam->farPlane+cam->nearPlane)*invz; - proj[11] = 1.0f; - - proj[12] = 0.0f; - proj[13] = 0.0f; - proj[14] = -2.0f*cam->nearPlane*cam->farPlane*invz; - proj[15] = 0.0f; - }else{ - // TODO - } - setProjectionMatrix(proj); -} - -void -initializeRender(void) -{ - driver[PLATFORM_GL3]->beginUpdate = beginUpdate; - - simpleShader = Shader::fromFiles("simple.vert", "simple.frag"); - - glClearColor(0.25, 0.25, 0.25, 1.0); - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - - glGenBuffers(1, &ubo_state); - glBindBuffer(GL_UNIFORM_BUFFER, ubo_state); - glBindBufferBase(GL_UNIFORM_BUFFER, gl3::findBlock("State"), ubo_state); - glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformState), &uniformState, - 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); - glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformScene), &uniformScene, - 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); - glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformObject), &uniformObject, - 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); -} - void setAttribPointers(InstanceDataHeader *header) { @@ -182,145 +34,6 @@ setAttribPointers(InstanceDataHeader *header) } } -static bool32 stateDirty = 1; -static bool32 sceneDirty = 1; -static bool32 objectDirty = 1; - -void -setWorldMatrix(Matrix *mat) -{ - uniformObject.world = *mat; - objectDirty = 1; -} - -void -setAmbientLight(RGBAf *amb) -{ - uniformObject.ambLight = *amb; - objectDirty = 1; -} - -void -setNumLights(int32 n) -{ - uniformObject.numLights = n; - objectDirty = 1; -} - -void -setLight(int32 n, Light *light) -{ - UniformLight *l; - Frame *f; - Matrix *m; - - l = &uniformObject.lights[n]; - f = light->getFrame(); - if(f){ - m = f->getLTM(); - l->position = m->pos; - l->direction = m->at; - } - // light has position - l->w = light->getType() >= Light::POINT ? 1.0f : 0.0; - l->color = light->color; - l->radius = light->radius; - l->minusCosAngle = light->minusCosAngle; - objectDirty = 1; -} - -void -setProjectionMatrix(float32 *mat) -{ - memcpy(&uniformScene.proj, mat, 64); - sceneDirty = 1; -} - -void -setViewMatrix(float32 *mat) -{ - memcpy(&uniformScene.view, mat, 64); - sceneDirty = 1; -} - -static bool32 vertexAlpha; -static bool32 textureAlpha; - -void -setTexture(int32 n, Texture *tex) -{ - bool32 alpha; - glActiveTexture(GL_TEXTURE0+n); - if(tex == nil){ - glBindTexture(GL_TEXTURE_2D, whitetex); - alpha = 0; - }else{ - Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, tex->raster, - nativeRasterOffset); - glBindTexture(GL_TEXTURE_2D, natras->texid); - alpha = natras->hasAlpha; - } - - if(textureAlpha == alpha) - return; - if(alpha) - /*printf("enable\n"),*/ glEnable(GL_BLEND); - else if(!vertexAlpha) - /*printf("disable\n"),*/ glDisable(GL_BLEND); - textureAlpha = alpha; -} - -void -setVertexAlpha(bool32 alpha) -{ - if(vertexAlpha == alpha) - return; - if(alpha) - /*printf("enable\n"),*/ glEnable(GL_BLEND); - else if(!textureAlpha) - /*printf("disable\n"),*/ glDisable(GL_BLEND); - vertexAlpha = alpha; -} - -void -setAlphaTestFunc(int32 f) -{ - uniformState.alphaFunc = f; - stateDirty = 1; -} - -void -setAlphaRef(float32 f) -{ - uniformState.alphaRef = f; - stateDirty = 1; -} - -#define U(s) currentShader->uniformLocations[findUniform(s)] - -void -flushCache(void) -{ - if(objectDirty){ - glBindBuffer(GL_UNIFORM_BUFFER, ubo_object); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformObject), - &uniformObject); - objectDirty = 0; - } - if(sceneDirty){ - glBindBuffer(GL_UNIFORM_BUFFER, ubo_scene); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformScene), - &uniformScene); - sceneDirty = 0; - } - if(stateDirty){ - glBindBuffer(GL_UNIFORM_BUFFER, ubo_state); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformState), - &uniformState); - stateDirty = 0; - } -} - void lightingCB(void) { @@ -346,9 +59,16 @@ lightingCB(void) setAmbientLight(&ambLight); } +#define U(s) currentShader->uniformLocations[findUniform(s)] + void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) { + Material *m; + RGBAf col; + GLfloat surfProps[4]; + int id; + setWorldMatrix(atomic->getFrame()->getLTM()); lightingCB(); @@ -356,15 +76,11 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo); setAttribPointers(header); - Material *m; - RGBAf col; - GLfloat surfProps[4]; - int id; InstanceData *inst = header->inst; int32 n = header->numMeshes; - setAlphaTestFunc(1); - setAlphaRef(0.2); + rw::setRenderState(ALPHATESTFUNC, 1); + rw::setRenderState(ALPHATESTREF, 50); simpleShader->use(); @@ -382,7 +98,7 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) setTexture(0, m->texture); - setVertexAlpha(inst->vertexAlpha || m->color.alpha != 0xFF); + rw::setRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF); flushCache(); glDrawElements(header->primType, inst->numIndex, diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index 74c0ea7..a1c9040 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -61,8 +61,6 @@ struct InstanceDataHeader : rw::InstanceDataHeader void setAttribPointers(InstanceDataHeader *header); // Render state -void setAlphaTestFunc(int32 f); -void setAlphaRef(float32 f); // per Scene void setProjectionMatrix(float32*); @@ -76,7 +74,6 @@ void setLight(int32 n, Light*); // per Mesh void setTexture(int32 n, Texture *tex); -void setVertexAlpha(bool32 enable); void flushCache(void); diff --git a/src/gl/wdgl.cpp b/src/gl/wdgl.cpp index 786805a..c4a1d74 100644 --- a/src/gl/wdgl.cpp +++ b/src/gl/wdgl.cpp @@ -24,7 +24,6 @@ namespace wdgl { void* driverOpen(void *o, int32, int32) { - printf("wdgl open\n"); driver[PLATFORM_WDGL]->defaultPipeline = makeDefaultPipeline(); return o; } diff --git a/src/ps2/ps2.cpp b/src/ps2/ps2.cpp index a400757..889a4de 100644 --- a/src/ps2/ps2.cpp +++ b/src/ps2/ps2.cpp @@ -23,7 +23,6 @@ namespace ps2 { void* driverOpen(void *o, int32, int32) { - printf("ps2 open\n"); driver[PLATFORM_PS2]->defaultPipeline = makeDefaultPipeline(); driver[PLATFORM_PS2]->rasterNativeOffset = nativeRasterOffset; diff --git a/src/rwengine.h b/src/rwengine.h index 8d469b5..cd03007 100644 --- a/src/rwengine.h +++ b/src/rwengine.h @@ -1,5 +1,51 @@ namespace rw { +enum RenderState +{ + VERTEXALPHA = 0, + SRCBLEND, + DESTBLEND, + ZTESTENABLE, + ZWRITEENABLE, + // TODO: + // fog enable, color, type, density + // ? cullmode + // ? shademode + // ???? stencil + + // platform specific or opaque? + ALPHATESTFUNC, + ALPHATESTREF, + ZTESTFUNC, +}; + +enum AlphaTestFunc +{ + ALPHANEVER = 0, + ALPHALESS, + ALPHAGREATERTHAN +}; + +enum BlendFunction +{ + BLENDZERO = 0, + BLENDONE, + BLENDSRCCOLOR, + BLENDINVSRCCOLOR, + BLENDSRCALPHA, + BLENDINVSRCALPHA, + BLENDDESTALPHA, + BLENDINVDESTALPHA, + BLENDDESTCOLOR, + BLENDINVDESTCOLOR, + BLENDSRCALPHASAT, + // TODO: add more perhaps +}; + +enum ZTestFunc +{ +}; + // This is for platform independent things // TODO: move more stuff into this struct Engine @@ -21,6 +67,9 @@ struct Driver void (*beginUpdate)(Camera*); void (*endUpdate)(Camera*); + void (*setRenderState)(int32 state, uint32 value); + uint32 (*getRenderState)(int32 state); + void (*rasterCreate)(Raster*); uint8 *(*rasterLock)(Raster*, int32 level); void (*rasterUnlock)(Raster*, int32 level); @@ -39,10 +88,19 @@ struct Driver extern Driver *driver[NUM_PLATFORMS]; #define DRIVER driver[rw::platform] +inline void setRenderState(int32 state, uint32 value){ + DRIVER->setRenderState(state, value); } + +inline uint32 getRenderState(int32 state){ + return DRIVER->getRenderState(state); } + namespace null { void beginUpdate(Camera*); void endUpdate(Camera*); + void setRenderState(int32 state, uint32 value); + uint32 getRenderState(int32 state); + void rasterCreate(Raster*); uint8 *rasterLock(Raster*, int32 level); void rasterUnlock(Raster*, int32 level); diff --git a/src/rwobjects.h b/src/rwobjects.h index 9f4d96d..7695f24 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -560,7 +560,6 @@ struct Camera : PluginBase bool streamWrite(Stream *stream); uint32 streamGetSize(void); - void updateProjectionMatrix(void); // fov in degrees void setFOV(float32 fov, float32 ratio); };