worked on platform drivers

This commit is contained in:
aap 2016-07-05 11:36:43 +02:00
parent ad1ea4ca53
commit abe0bba5af
17 changed files with 611 additions and 384 deletions

View File

@ -1,5 +1,29 @@
librw librw
===== =====
This work in progress. This library is supposed to be a re-implementation of RenderWare graphics,
The basics of DFFs and many plugins are implemented (at least read&write). 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'

View File

@ -29,6 +29,16 @@ defaultEndUpdateCB(Camera *cam)
static void static void
cameraSync(ObjectWithFrame*) 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 void
@ -169,73 +179,6 @@ Camera::streamGetSize(void)
s_plglist.streamGetSize(this); 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 void
Camera::setFOV(float32 fov, float32 ratio) Camera::setFOV(float32 fov, float32 ratio)
{ {

View File

@ -23,7 +23,6 @@ using namespace d3d;
void* void*
driverOpen(void *o, int32, int32) driverOpen(void *o, int32, int32)
{ {
printf("d3d8 open\n");
driver[PLATFORM_D3D8]->defaultPipeline = makeDefaultPipeline(); driver[PLATFORM_D3D8]->defaultPipeline = makeDefaultPipeline();
driver[PLATFORM_D3D8]->rasterNativeOffset = nativeRasterOffset; driver[PLATFORM_D3D8]->rasterNativeOffset = nativeRasterOffset;

View File

@ -30,7 +30,6 @@ using namespace d3d;
void* void*
driverOpen(void *o, int32, int32) driverOpen(void *o, int32, int32)
{ {
printf("d3d9 open\n");
driver[PLATFORM_D3D9]->defaultPipeline = makeDefaultPipeline(); driver[PLATFORM_D3D9]->defaultPipeline = makeDefaultPipeline();
driver[PLATFORM_D3D9]->rasterNativeOffset = nativeRasterOffset; driver[PLATFORM_D3D9]->rasterNativeOffset = nativeRasterOffset;

View File

@ -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 #endif
} }
} }

View File

@ -5,6 +5,8 @@
namespace rw { namespace rw {
namespace d3d { namespace d3d {
void initializeRender(void);
extern bool32 isP8supported; extern bool32 isP8supported;
#ifdef RW_D3D9 #ifdef RW_D3D9

View File

@ -22,7 +22,6 @@ namespace xbox {
void* void*
driverOpen(void *o, int32, int32) driverOpen(void *o, int32, int32)
{ {
printf("xbox open\n");
driver[PLATFORM_XBOX]->defaultPipeline = makeDefaultPipeline(); driver[PLATFORM_XBOX]->defaultPipeline = makeDefaultPipeline();
driver[PLATFORM_XBOX]->rasterNativeOffset = nativeRasterOffset; driver[PLATFORM_XBOX]->rasterNativeOffset = nativeRasterOffset;

View File

@ -53,6 +53,9 @@ Driver::open(void)
driver[i]->beginUpdate = null::beginUpdate; driver[i]->beginUpdate = null::beginUpdate;
driver[i]->endUpdate = null::endUpdate; driver[i]->endUpdate = null::endUpdate;
driver[i]->setRenderState = null::setRenderState;
driver[i]->getRenderState = null::getRenderState;
driver[i]->rasterCreate = null::rasterCreate; driver[i]->rasterCreate = null::rasterCreate;
driver[i]->rasterLock = null::rasterLock; driver[i]->rasterLock = null::rasterLock;
driver[i]->rasterUnlock = null::rasterUnlock; driver[i]->rasterUnlock = null::rasterUnlock;
@ -69,6 +72,8 @@ void beginUpdate(Camera*) { }
void endUpdate(Camera*) { } void endUpdate(Camera*) { }
void setRenderState(int32, uint32) { }
uint32 getRenderState(int32) { return 0; }
void void
rasterCreate(Raster*) rasterCreate(Raster*)

View File

@ -26,7 +26,6 @@ namespace gl3 {
void* void*
driverOpen(void *o, int32, int32) driverOpen(void *o, int32, int32)
{ {
printf("gl3 open\n");
#ifdef RW_OPENGL #ifdef RW_OPENGL
driver[PLATFORM_GL3]->defaultPipeline = makeDefaultPipeline(); driver[PLATFORM_GL3]->defaultPipeline = makeDefaultPipeline();
#endif #endif
@ -37,8 +36,6 @@ driverOpen(void *o, int32, int32)
driver[PLATFORM_GL3]->rasterNumLevels = rasterNumLevels; driver[PLATFORM_GL3]->rasterNumLevels = rasterNumLevels;
driver[PLATFORM_GL3]->rasterFromImage = rasterFromImage; driver[PLATFORM_GL3]->rasterFromImage = rasterFromImage;
initializeRender();
return o; return o;
} }

409
src/gl/gl3driver.cpp Normal file
View File

@ -0,0 +1,409 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#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 <GL/glew.h>
#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

View File

@ -74,7 +74,7 @@ matfxDefaultRender(InstanceDataHeader *header, InstanceData *inst)
setTexture(0, m->texture); setTexture(0, m->texture);
setVertexAlpha(inst->vertexAlpha || m->color.alpha != 0xFF); rw::setRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
flushCache(); flushCache();
glDrawElements(header->primType, inst->numIndex, glDrawElements(header->primType, inst->numIndex,
@ -173,15 +173,16 @@ matfxEnvRender(InstanceDataHeader *header, InstanceData *inst)
setTexture(0, env->tex); setTexture(0, env->tex);
setVertexAlpha(1); rw::setRenderState(VERTEXALPHA, 1);
rw::setRenderState(SRCBLEND, BLENDONE);
glBlendFunc(GL_ONE, GL_ONE); rw::setRenderState(DESTBLEND, BLENDONE);
flushCache(); flushCache();
glDrawElements(header->primType, inst->numIndex, glDrawElements(header->primType, inst->numIndex,
GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset); 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 void
@ -197,8 +198,8 @@ matfxRenderCB(Atomic *atomic, InstanceDataHeader *header)
InstanceData *inst = header->inst; InstanceData *inst = header->inst;
int32 n = header->numMeshes; int32 n = header->numMeshes;
setAlphaTestFunc(1); rw::setRenderState(ALPHATESTFUNC, 1);
setAlphaRef(0.2); rw::setRenderState(ALPHATESTREF, 50);
int32 fx; int32 fx;
while(n--){ while(n--){
@ -260,6 +261,11 @@ makeSkinPipeline(void)
return pipe; return pipe;
} }
#else
void initMatFX(void) { }
void initSkin(void) { }
#endif #endif
} }

View File

@ -14,161 +14,13 @@
#include "rwgl3.h" #include "rwgl3.h"
#include "rwgl3shader.h" #include "rwgl3shader.h"
#include "rwgl3impl.h"
namespace rw { namespace rw {
namespace gl3 { 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 #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 void
setAttribPointers(InstanceDataHeader *header) 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 void
lightingCB(void) lightingCB(void)
{ {
@ -346,9 +59,16 @@ lightingCB(void)
setAmbientLight(&ambLight); setAmbientLight(&ambLight);
} }
#define U(s) currentShader->uniformLocations[findUniform(s)]
void void
defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
{ {
Material *m;
RGBAf col;
GLfloat surfProps[4];
int id;
setWorldMatrix(atomic->getFrame()->getLTM()); setWorldMatrix(atomic->getFrame()->getLTM());
lightingCB(); lightingCB();
@ -356,15 +76,11 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo);
setAttribPointers(header); setAttribPointers(header);
Material *m;
RGBAf col;
GLfloat surfProps[4];
int id;
InstanceData *inst = header->inst; InstanceData *inst = header->inst;
int32 n = header->numMeshes; int32 n = header->numMeshes;
setAlphaTestFunc(1); rw::setRenderState(ALPHATESTFUNC, 1);
setAlphaRef(0.2); rw::setRenderState(ALPHATESTREF, 50);
simpleShader->use(); simpleShader->use();
@ -382,7 +98,7 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
setTexture(0, m->texture); setTexture(0, m->texture);
setVertexAlpha(inst->vertexAlpha || m->color.alpha != 0xFF); rw::setRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
flushCache(); flushCache();
glDrawElements(header->primType, inst->numIndex, glDrawElements(header->primType, inst->numIndex,

View File

@ -61,8 +61,6 @@ struct InstanceDataHeader : rw::InstanceDataHeader
void setAttribPointers(InstanceDataHeader *header); void setAttribPointers(InstanceDataHeader *header);
// Render state // Render state
void setAlphaTestFunc(int32 f);
void setAlphaRef(float32 f);
// per Scene // per Scene
void setProjectionMatrix(float32*); void setProjectionMatrix(float32*);
@ -76,7 +74,6 @@ void setLight(int32 n, Light*);
// per Mesh // per Mesh
void setTexture(int32 n, Texture *tex); void setTexture(int32 n, Texture *tex);
void setVertexAlpha(bool32 enable);
void flushCache(void); void flushCache(void);

View File

@ -24,7 +24,6 @@ namespace wdgl {
void* void*
driverOpen(void *o, int32, int32) driverOpen(void *o, int32, int32)
{ {
printf("wdgl open\n");
driver[PLATFORM_WDGL]->defaultPipeline = makeDefaultPipeline(); driver[PLATFORM_WDGL]->defaultPipeline = makeDefaultPipeline();
return o; return o;
} }

View File

@ -23,7 +23,6 @@ namespace ps2 {
void* void*
driverOpen(void *o, int32, int32) driverOpen(void *o, int32, int32)
{ {
printf("ps2 open\n");
driver[PLATFORM_PS2]->defaultPipeline = makeDefaultPipeline(); driver[PLATFORM_PS2]->defaultPipeline = makeDefaultPipeline();
driver[PLATFORM_PS2]->rasterNativeOffset = nativeRasterOffset; driver[PLATFORM_PS2]->rasterNativeOffset = nativeRasterOffset;

View File

@ -1,5 +1,51 @@
namespace rw { 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 // This is for platform independent things
// TODO: move more stuff into this // TODO: move more stuff into this
struct Engine struct Engine
@ -21,6 +67,9 @@ struct Driver
void (*beginUpdate)(Camera*); void (*beginUpdate)(Camera*);
void (*endUpdate)(Camera*); void (*endUpdate)(Camera*);
void (*setRenderState)(int32 state, uint32 value);
uint32 (*getRenderState)(int32 state);
void (*rasterCreate)(Raster*); void (*rasterCreate)(Raster*);
uint8 *(*rasterLock)(Raster*, int32 level); uint8 *(*rasterLock)(Raster*, int32 level);
void (*rasterUnlock)(Raster*, int32 level); void (*rasterUnlock)(Raster*, int32 level);
@ -39,10 +88,19 @@ struct Driver
extern Driver *driver[NUM_PLATFORMS]; extern Driver *driver[NUM_PLATFORMS];
#define DRIVER driver[rw::platform] #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 { namespace null {
void beginUpdate(Camera*); void beginUpdate(Camera*);
void endUpdate(Camera*); void endUpdate(Camera*);
void setRenderState(int32 state, uint32 value);
uint32 getRenderState(int32 state);
void rasterCreate(Raster*); void rasterCreate(Raster*);
uint8 *rasterLock(Raster*, int32 level); uint8 *rasterLock(Raster*, int32 level);
void rasterUnlock(Raster*, int32 level); void rasterUnlock(Raster*, int32 level);

View File

@ -560,7 +560,6 @@ struct Camera : PluginBase<Camera>
bool streamWrite(Stream *stream); bool streamWrite(Stream *stream);
uint32 streamGetSize(void); uint32 streamGetSize(void);
void updateProjectionMatrix(void);
// fov in degrees // fov in degrees
void setFOV(float32 fov, float32 ratio); void setFOV(float32 fov, float32 ratio);
}; };