moved gl3 code here; added files i forgot last time

This commit is contained in:
aap
2016-06-24 15:24:58 +02:00
parent 9623bdbf11
commit e3fa1fcc7f
29 changed files with 8464 additions and 2 deletions

276
src/gl/gl3pipe.cpp Normal file
View File

@@ -0,0 +1,276 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#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>
#endif
#include "rwgl3.h"
#include "rwgl3shader.h"
namespace rw {
namespace gl3 {
// TODO: make some of these things platform-independent
void
initializePlatform(void)
{
#ifdef RW_OPENGL
driver[PLATFORM_GL3].defaultPipeline = makeDefaultPipeline();
matFXGlobals.pipelines[PLATFORM_GL3] = makeMatFXPipeline();
skinGlobals.pipelines[PLATFORM_GL3] = makeSkinPipeline();
#endif
initializeRender();
}
#ifdef RW_OPENGL
static void
instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if(geo->geoflags & Geometry::NATIVE)
return;
geo->geoflags |= Geometry::NATIVE;
InstanceDataHeader *header = new InstanceDataHeader;
MeshHeader *meshh = geo->meshHeader;
geo->instData = header;
header->platform = PLATFORM_GL3;
header->serialNumber = 0;
header->numMeshes = meshh->numMeshes;
header->primType = meshh->flags == 1 ? GL_TRIANGLE_STRIP : GL_TRIANGLES;
header->totalNumVertex = geo->numVertices;
header->totalNumIndex = meshh->totalIndices;
header->inst = new InstanceData[header->numMeshes];
header->indexBuffer = new uint16[header->totalNumIndex];
InstanceData *inst = header->inst;
Mesh *mesh = meshh->mesh;
uint32 offset = 0;
for(uint32 i = 0; i < header->numMeshes; i++){
findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
&inst->minVert, nil);
inst->numIndex = mesh->numIndices;
inst->material = mesh->material;
inst->vertexAlpha = 0;
inst->program = 0;
inst->offset = offset;
memcpy((uint8*)header->indexBuffer + inst->offset,
mesh->indices, inst->numIndex*2);
offset += inst->numIndex*2;
mesh++;
inst++;
}
header->vertexBuffer = nil;
header->numAttribs = 0;
header->attribDesc = nil;
header->ibo = 0;
header->vbo = 0;
glGenBuffers(1, &header->ibo);
glBindBuffer(GL_ARRAY_BUFFER, header->ibo);
glBufferData(GL_ARRAY_BUFFER, header->totalNumIndex*2,
header->indexBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
pipe->instanceCB(geo, header);
}
static void
uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
assert(0 && "can't uninstance");
}
static void
render(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
pipe->instance(atomic);
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_GL3);
if(pipe->renderCB)
pipe->renderCB(atomic, (InstanceDataHeader*)geo->instData);
}
ObjPipeline::ObjPipeline(uint32 platform)
: rw::ObjPipeline(platform)
{
this->impl.instance = gl3::instance;
this->impl.uninstance = gl3::uninstance;
this->impl.render = gl3::render;
this->instanceCB = nil;
this->uninstanceCB = nil;
this->renderCB = nil;
}
void
defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
{
AttribDesc attribs[12], *a;
uint32 stride;
//
// Create attribute descriptions
//
a = attribs;
stride = 0;
// Positions
a->index = ATTRIB_POS;
a->size = 3;
a->type = GL_FLOAT;
a->normalized = GL_FALSE;
a->offset = stride;
stride += 12;
a++;
// Normals
// TODO: compress
bool hasNormals = !!(geo->geoflags & Geometry::NORMALS);
if(hasNormals){
a->index = ATTRIB_NORMAL;
a->size = 3;
a->type = GL_FLOAT;
a->normalized = GL_FALSE;
a->offset = stride;
stride += 12;
a++;
}
// Prelighting
bool isPrelit = !!(geo->geoflags & Geometry::PRELIT);
if(isPrelit){
a->index = ATTRIB_COLOR;
a->size = 4;
a->type = GL_UNSIGNED_BYTE;
a->normalized = GL_TRUE;
a->offset = stride;
stride += 4;
a++;
}
// Texture coordinates
for(int32 n = 0; n < geo->numTexCoordSets; n++){
a->index = ATTRIB_TEXCOORDS0+n;
a->size = 2;
a->type = GL_FLOAT;
a->normalized = GL_FALSE;
a->offset = stride;
stride += 8;
a++;
}
header->numAttribs = a - attribs;
for(a = attribs; a != &attribs[header->numAttribs]; a++)
a->stride = stride;
header->attribDesc = new AttribDesc[header->numAttribs];
memcpy(header->attribDesc, attribs,
header->numAttribs*sizeof(AttribDesc));
//
// Allocate and fill vertex buffer
//
uint8 *verts = new uint8[header->totalNumVertex*stride];
header->vertexBuffer = verts;
// Positions
for(a = attribs; a->index != ATTRIB_POS; a++)
;
instV3d(VERT_FLOAT3, verts + a->offset,
geo->morphTargets[0].vertices,
header->totalNumVertex, a->stride);
// Normals
if(hasNormals){
for(a = attribs; a->index != ATTRIB_NORMAL; a++)
;
instV3d(VERT_FLOAT3, verts + a->offset,
geo->morphTargets[0].normals,
header->totalNumVertex, a->stride);
}
// Prelighting
if(isPrelit){
for(a = attribs; a->index != ATTRIB_COLOR; a++)
;
instColor(VERT_RGBA, verts + a->offset,
geo->colors,
header->totalNumVertex, a->stride);
}
// Texture coordinates
for(int32 n = 0; n < geo->numTexCoordSets; n++){
for(a = attribs; a->index != ATTRIB_TEXCOORDS0+n; a++)
;
instV2d(VERT_FLOAT2, verts + a->offset,
geo->texCoords[n],
header->totalNumVertex, a->stride);
}
glGenBuffers(1, &header->vbo);
glBindBuffer(GL_ARRAY_BUFFER, header->vbo);
glBufferData(GL_ARRAY_BUFFER, header->totalNumVertex*stride,
header->vertexBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void
defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header)
{
assert(0 && "can't uninstance");
}
ObjPipeline*
makeDefaultPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_GL3);
pipe->instanceCB = defaultInstanceCB;
pipe->uninstanceCB = defaultUninstanceCB;
pipe->renderCB = defaultRenderCB;
return pipe;
}
ObjPipeline*
makeSkinPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_GL3);
pipe->instanceCB = defaultInstanceCB;
pipe->uninstanceCB = defaultUninstanceCB;
pipe->renderCB = defaultRenderCB;
pipe->pluginID = ID_SKIN;
pipe->pluginData = 1;
return pipe;
}
ObjPipeline*
makeMatFXPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_GL3);
pipe->instanceCB = defaultInstanceCB;
pipe->uninstanceCB = defaultUninstanceCB;
pipe->renderCB = defaultRenderCB;
pipe->pluginID = ID_MATFX;
pipe->pluginData = 0;
return pipe;
}
#endif
}
}

132
src/gl/gl3raster.cpp Normal file
View File

@@ -0,0 +1,132 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#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>
#endif
#include "rwgl3.h"
#include "rwgl3shader.h"
namespace rw {
namespace gl3 {
int32 nativeRasterOffset;
static void
rasterCreate(Raster *raster)
{
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset);
if(raster->flags & Raster::DONTALLOCATE)
return;
assert(raster->depth == 32);
#ifdef RW_OPENGL
glGenTextures(1, &natras->texid);
glBindTexture(GL_TEXTURE_2D, natras->texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, raster->width, raster->height,
0, GL_RGBA, GL_UNSIGNED_BYTE, nil);
glBindTexture(GL_TEXTURE_2D, 0);
#endif
}
static uint8*
rasterLock(Raster*, int32 level)
{
printf("locking\n");
return nil;
}
static void
rasterUnlock(Raster*, int32)
{
printf("unlocking\n");
}
static int32
rasterNumLevels(Raster*)
{
printf("numlevels\n");
return 0;
}
static void
rasterFromImage(Raster *raster, Image *image)
{
int32 format;
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset);
format = Raster::C8888;
format |= 4;
raster->type = format & 0x7;
raster->flags = format & 0xF8;
raster->format = format & 0xFF00;
rasterCreate(raster);
assert(image->depth == 32);
natras->hasAlpha = image->hasAlpha();
#ifdef RW_OPENGL
glBindTexture(GL_TEXTURE_2D, natras->texid);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, raster->width, raster->height,
0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
glBindTexture(GL_TEXTURE_2D, 0);
#endif
}
static void*
createNativeRaster(void *object, int32 offset, int32)
{
Gl3Raster *ras = PLUGINOFFSET(Gl3Raster, object, offset);
ras->texid = 0;
return object;
}
static void*
destroyNativeRaster(void *object, int32, int32)
{
//Gl3Raster *ras = PLUGINOFFSET(Gl3Raster, object, offset);
// TODO
return object;
}
static void*
copyNativeRaster(void *dst, void *, int32 offset, int32)
{
Gl3Raster *d = PLUGINOFFSET(Gl3Raster, dst, offset);
d->texid = 0;
return dst;
}
void
registerNativeRaster(void)
{
nativeRasterOffset = Raster::registerPlugin(sizeof(Gl3Raster),
0x12340000 | PLATFORM_GL3,
createNativeRaster,
destroyNativeRaster,
copyNativeRaster);
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;
}
}
}

359
src/gl/gl3render.cpp Normal file
View File

@@ -0,0 +1,359 @@
#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 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_scene, ubo_object;
GLuint whitetex;
UniformScene uniformScene;
UniformObject uniformObject;
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;
glClearColor(0.25, 0.25, 0.25, 1.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
registerBlock("Scene");
registerBlock("Object");
registerUniform("u_matColor");
registerUniform("u_surfaceProps");
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)
{
AttribDesc *a;
for(a = header->attribDesc;
a != &header->attribDesc[header->numAttribs];
a++){
glEnableVertexAttribArray(a->index);
glVertexAttribPointer(a->index, a->size, a->type, a->normalized,
a->stride, (void*)(uint64)a->offset);
}
}
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
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;
}
}
void
lightingCB(void)
{
World *world;
RGBAf ambLight = (RGBAf){0.0, 0.0, 0.0, 1.0};
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;
setLight(n++, l);
}else if(l->getType() == Light::AMBIENT){
ambLight.red += l->color.red;
ambLight.green += l->color.green;
ambLight.blue += l->color.blue;
}
}
setNumLights(n);
setAmbientLight(&ambLight);
}
void
defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
{
setWorldMatrix(atomic->getFrame()->getLTM());
lightingCB();
glBindBuffer(GL_ARRAY_BUFFER, header->vbo);
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;
while(n--){
m = inst->material;
#define U(s) currentShader->uniformLocations[findUniform(s)]
convColor(&col, &m->color);
glUniform4fv(U("u_matColor"), 1, (GLfloat*)&col);
surfProps[0] = m->surfaceProps.ambient;
surfProps[1] = m->surfaceProps.specular;
surfProps[2] = m->surfaceProps.diffuse;
surfProps[3] = 0.0f;
glUniform4fv(U("u_surfaceProps"), 1, surfProps);
setTexture(0, m->texture);
setVertexAlpha(inst->vertexAlpha || m->color.alpha != 0xFF);
flushCache();
glDrawElements(header->primType, inst->numIndex,
GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset);
inst++;
}
}
}
}
#endif

193
src/gl/gl3shader.cpp Normal file
View File

@@ -0,0 +1,193 @@
#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 {
UniformRegistry uniformRegistry;
int
registerUniform(const char *name)
{
int i;
i = findUniform(name);
if(i >= 0) return i;
uniformRegistry.uniformNames[uniformRegistry.numUniforms] = strdup(name);
return uniformRegistry.numUniforms++;
}
int
findUniform(const char *name)
{
int i;
for(i = 0; i < uniformRegistry.numUniforms; i++)
if(strcmp(name, uniformRegistry.uniformNames[i]) == 0)
return i;
return -1;
}
int
registerBlock(const char *name)
{
int i;
i = findBlock(name);
if(i >= 0) return i;
uniformRegistry.blockNames[uniformRegistry.numBlocks] = strdup(name);
return uniformRegistry.numBlocks++;
}
int
findBlock(const char *name)
{
int i;
for(i = 0; i < uniformRegistry.numBlocks; i++)
if(strcmp(name, uniformRegistry.blockNames[i]) == 0)
return i;
return -1;
}
Shader *currentShader;
// TODO: maybe make this public somewhere?
static char*
loadfile(const char *path)
{
FILE *f;
char *buf;
long len;
if(f = fopen(path, "rb"), f == nil){
fprintf(stderr, "Couldn't open file %s\n", path);
exit(1);
}
fseek(f, 0, SEEK_END);
len = ftell(f);
buf = (char*)malloc(len+1);
rewind(f);
fread(buf, 1, len, f);
buf[len] = '\0';
fclose(f);
return buf;
}
static int
compileshader(GLenum type, const char *src, GLuint *shader)
{
GLint shdr, success;
GLint len;
char *log;
shdr = glCreateShader(type);
glShaderSource(shdr, 1, &src, nil);
glCompileShader(shdr);
glGetShaderiv(shdr, GL_COMPILE_STATUS, &success);
if(!success){
fprintf(stderr, "Error in %s shader\n",
type == GL_VERTEX_SHADER ? "vertex" : "fragment");
glGetShaderiv(shdr, GL_INFO_LOG_LENGTH, &len);
log = (char*)malloc(len);
glGetShaderInfoLog(shdr, len, nil, log);
fprintf(stderr, "%s\n", log);
free(log);
return 1;
}
*shader = shdr;
return 0;
}
static int
linkprogram(GLint vs, GLint fs, GLuint *program)
{
GLint prog, success;
GLint len;
char *log;
prog = glCreateProgram();
glAttachShader(prog, vs);
glAttachShader(prog, fs);
glLinkProgram(prog);
glGetProgramiv(prog, GL_LINK_STATUS, &success);
if(!success){
fprintf(stderr, "Error in program\n");
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
log = (char*)malloc(len);
glGetProgramInfoLog(prog, len, nil, log);
fprintf(stderr, "%s\n", log);
free(log);
return 1;
}
*program = prog;
return 0;
}
Shader*
Shader::fromFiles(const char *vspath, const char *fspath)
{
GLuint vs, fs, program;
int i;
char *src;
int fail;
src = loadfile(vspath);
fail = compileshader(GL_VERTEX_SHADER, src, &vs);
free(src);
if(fail)
return nil;
src = loadfile(fspath);
fail = compileshader(GL_FRAGMENT_SHADER, src, &fs);
free(src);
if(fail)
return nil;
fail = linkprogram(vs, fs, &program);
if(fail)
return nil;
glDeleteProgram(vs);
glDeleteProgram(fs);
Shader *sh = new Shader;
// set uniform block binding
for(i = 0; i < uniformRegistry.numBlocks; i++){
int idx = glGetUniformBlockIndex(program,
uniformRegistry.blockNames[i]);
if(idx >= 0)
glUniformBlockBinding(program, idx, i);
}
// query uniform locations
sh->program = program;
sh->uniformLocations = new GLint[uniformRegistry.numUniforms];
for(i = 0; i < uniformRegistry.numUniforms; i++)
sh->uniformLocations[i] = glGetUniformLocation(program,
uniformRegistry.uniformNames[i]);
return sh;
}
void
Shader::use(void)
{
glUseProgram(this->program);
currentShader = this;
}
}
}
#endif

108
src/gl/rwgl3.h Normal file
View File

@@ -0,0 +1,108 @@
namespace rw {
namespace gl3 {
void initializePlatform(void);
void initializeRender(void);
// arguments to glVertexAttribPointer basically
struct AttribDesc
{
uint32 index;
int32 type;
bool32 normalized;
int32 size;
uint32 stride;
uint32 offset;
};
enum AttribIndices
{
ATTRIB_POS = 0,
ATTRIB_NORMAL,
ATTRIB_COLOR,
ATTRIB_TEXCOORDS0,
ATTRIB_TEXCOORDS1,
ATTRIB_TEXCOORDS2,
ATTRIB_TEXCOORDS3,
ATTRIB_TEXCOORDS4,
ATTRIB_TEXCOORDS5,
ATTRIB_TEXCOORDS6,
ATTRIB_TEXCOORDS7,
};
struct InstanceData
{
uint32 numIndex;
uint32 minVert; // not used for rendering
Material *material;
bool32 vertexAlpha;
uint32 program;
uint32 offset;
};
struct InstanceDataHeader : rw::InstanceDataHeader
{
uint32 serialNumber; // not really needed right now
uint32 numMeshes;
uint16 *indexBuffer;
uint32 primType;
uint8 *vertexBuffer;
int32 numAttribs;
AttribDesc *attribDesc;
uint32 totalNumIndex;
uint32 totalNumVertex;
uint32 ibo;
uint32 vbo; // or 2?
InstanceData *inst;
};
void setAttribPointers(InstanceDataHeader *header);
// per Scene
void setProjectionMatrix(float32*);
void setViewMatrix(float32*);
// per Object
void setWorldMatrix(Matrix*);
void setAmbientLight(RGBAf*);
void setNumLights(int32 n);
void setLight(int32 n, Light*);
// per Mesh
void setTexture(int32 n, Texture *tex);
void setVertexAlpha(bool32 enable);
class ObjPipeline : public rw::ObjPipeline
{
public:
void (*instanceCB)(Geometry *geo, InstanceDataHeader *header);
void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header);
void (*renderCB)(Atomic *atomic, InstanceDataHeader *header);
ObjPipeline(uint32 platform);
};
void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header);
void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header);
void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header);
ObjPipeline *makeDefaultPipeline(void);
ObjPipeline *makeSkinPipeline(void);
ObjPipeline *makeMatFXPipeline(void);
// Native Texture and Raster
extern int32 nativeRasterOffset;
struct Gl3Raster
{
uint32 texid;
bool32 hasAlpha;
};
void registerNativeRaster(void);
}
}

44
src/gl/rwgl3shader.h Normal file
View File

@@ -0,0 +1,44 @@
#ifdef RW_OPENGL
namespace rw {
namespace gl3 {
// TODO: make this dynamic
enum {
MAX_UNIFORMS = 20,
MAX_BLOCKS = 20
};
struct UniformRegistry
{
int numUniforms;
char *uniformNames[MAX_UNIFORMS];
int numBlocks;
char *blockNames[MAX_BLOCKS];
};
int registerUniform(const char *name);
int findUniform(const char *name);
int registerBlock(const char *name);
int findBlock(const char *name);
extern UniformRegistry uniformRegistry;
class Shader
{
public:
GLuint program;
// same number of elements as UniformRegistry::numUniforms
GLint *uniformLocations;
static Shader *fromFiles(const char *vs, const char *fs);
void use(void);
};
extern Shader *currentShader;
}
}
#endif

83
src/gl/rwwdgl.h Normal file
View File

@@ -0,0 +1,83 @@
namespace rw {
namespace wdgl {
// NOTE: This is not really RW OpenGL! It's specific to WarDrum's GTA ports
void initializePlatform(void);
struct AttribDesc
{
// arguments to glVertexAttribPointer (should use OpenGL types here)
// Vertex = 0, TexCoord, Normal, Color, Weight, Bone Index, Extra Color
uint32 index;
// float = 0, byte, ubyte, short, ushort
int32 type;
bool32 normalized;
int32 size;
uint32 stride;
uint32 offset;
};
struct InstanceDataHeader : rw::InstanceDataHeader
{
int32 numAttribs;
AttribDesc *attribs;
uint32 dataSize;
uint8 *data;
// needed for rendering
uint32 vbo;
uint32 ibo;
};
// only RW_OPENGL
void uploadGeo(Geometry *geo);
void setAttribPointers(InstanceDataHeader *inst);
void packattrib(uint8 *dst, float32 *src, AttribDesc *a, float32 scale);
void unpackattrib(float *dst, uint8 *src, AttribDesc *a, float32 scale);
void *destroyNativeData(void *object, int32, int32);
Stream *readNativeData(Stream *stream, int32 len, void *object, int32, int32);
Stream *writeNativeData(Stream *stream, int32 len, void *object, int32, int32);
int32 getSizeNativeData(void *object, int32, int32);
void registerNativeDataPlugin(void);
void printPipeinfo(Atomic *a);
class ObjPipeline : public rw::ObjPipeline
{
public:
uint32 numCustomAttribs;
uint32 (*instanceCB)(Geometry *g, int32 i, uint32 offset);
void (*uninstanceCB)(Geometry *g);
ObjPipeline(uint32 platform);
};
ObjPipeline *makeDefaultPipeline(void);
// Skin plugin
Stream *readNativeSkin(Stream *stream, int32, void *object, int32 offset);
Stream *writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset);
int32 getSizeNativeSkin(void *object, int32 offset);
ObjPipeline *makeSkinPipeline(void);
ObjPipeline *makeMatFXPipeline(void);
// Raster
struct Texture : rw::Texture
{
void upload(void);
void bind(int n);
};
extern int32 nativeRasterOffset;
void registerNativeRaster(void);
}
}

793
src/gl/wdgl.cpp Normal file
View File

@@ -0,0 +1,793 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#include "../rwplugins.h"
#include "rwwdgl.h"
#ifdef RW_OPENGL
#include <GL/glew.h>
#endif
#define PLUGIN_ID 2
namespace rw {
namespace wdgl {
void
initializePlatform(void)
{
driver[PLATFORM_WDGL].defaultPipeline = makeDefaultPipeline();
}
// VC
// 8733 0 0 0 3
// 45 1 0 0 2
// 8657 1 3 0 2
// 4610 2 1 1 3
// 4185 3 2 1 4
// 256 4 2 1 4
// 201 4 4 1 4
// 457 5 2 0 4
// SA
// 20303 0 0 0 3 vertices: 3 floats
// 53 1 0 0 2 texCoords: 2 floats
// 20043 1 3 0 2 texCoords: 2 shorts
// 6954 2 1 1 3 normal: 3 bytes normalized
// 13527 3 2 1 4 color: 4 ubytes normalized
// 196 4 2 1 4 weight: 4 ubytes normalized
// 225 4 4 1 4 weight: 4 ushorts normalized
// 421 5 2 0 4 indices: 4 ubytes
// 12887 6 2 1 4 extracolor:4 ubytes normalized
/*
static void
printAttribInfo(AttribDesc *attribs, int n)
{
for(int i = 0; i < n; i++)
printf("%x %x %x %x\n",
attribs[i].index,
attribs[i].type,
attribs[i].normalized,
attribs[i].size);
}
*/
#ifdef RW_OPENGL
void
uploadGeo(Geometry *geo)
{
InstanceDataHeader *inst = (InstanceDataHeader*)geo->instData;
MeshHeader *meshHeader = geo->meshHeader;
glGenBuffers(1, &inst->vbo);
glBindBuffer(GL_ARRAY_BUFFER, inst->vbo);
glBufferData(GL_ARRAY_BUFFER, inst->dataSize,
inst->data, GL_STATIC_DRAW);
glGenBuffers(1, &inst->ibo);
glBindBuffer(GL_ARRAY_BUFFER, inst->ibo);
glBufferData(GL_ARRAY_BUFFER, meshHeader->totalIndices*2,
0, GL_STATIC_DRAW);
GLintptr offset = 0;
for(uint32 i = 0; i < meshHeader->numMeshes; i++){
Mesh *mesh = &meshHeader->mesh[i];
glBufferSubData(GL_ARRAY_BUFFER, offset, mesh->numIndices*2,
mesh->indices);
offset += mesh->numIndices*2;
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void
setAttribPointers(InstanceDataHeader *inst)
{
static GLenum attribType[] = {
GL_FLOAT,
GL_BYTE, GL_UNSIGNED_BYTE,
GL_SHORT, GL_UNSIGNED_SHORT
};
for(int32 i = 0; i < inst->numAttribs; i++){
AttribDesc *a = &inst->attribs[i];
glEnableVertexAttribArray(a->index);
glVertexAttribPointer(a->index, a->size, attribType[a->type],
a->normalized, a->stride,
(void*)(uint64)a->offset);
}
}
#endif
void
packattrib(uint8 *dst, float32 *src, AttribDesc *a, float32 scale=1.0f)
{
int8 *i8dst;
uint16 *u16dst;
int16 *i16dst;
switch(a->type){
case 0: // float
memcpy(dst, src, a->size*4);
break;
// TODO: maybe have loop inside if?
case 1: // byte
i8dst = (int8*)dst;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
i8dst[i] = src[i]*scale;
else
i8dst[i] = src[i]*127.0f;
}
break;
case 2: // ubyte
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = src[i]*scale;
else
dst[i] = src[i]*255.0f;
}
break;
case 3: // short
i16dst = (int16*)dst;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
i16dst[i] = src[i]*scale;
else
i16dst[i] = src[i]*32767.0f;
}
break;
case 4: // ushort
u16dst = (uint16*)dst;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
u16dst[i] = src[i]*scale;
else
u16dst[i] = src[i]*65535.0f;
}
break;
}
}
void
unpackattrib(float *dst, uint8 *src, AttribDesc *a, float32 scale=1.0f)
{
int8 *i8src;
uint16 *u16src;
int16 *i16src;
switch(a->type){
case 0: // float
memcpy(dst, src, a->size*4);
break;
// TODO: maybe have loop inside if?
case 1: // byte
i8src = (int8*)src;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = i8src[i]/scale;
else
dst[i] = i8src[i]/127.0f;
}
break;
case 2: // ubyte
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = src[i]/scale;
else
dst[i] = src[i]/255.0f;
}
break;
case 3: // short
i16src = (int16*)src;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = i16src[i]/scale;
else
dst[i] = i16src[i]/32767.0f;
}
break;
case 4: // ushort
u16src = (uint16*)src;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = u16src[i]/scale;
else
dst[i] = u16src[i]/65435.0f;
}
break;
}
}
void*
destroyNativeData(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
if(geometry->instData == nil ||
geometry->instData->platform != PLATFORM_WDGL)
return object;
InstanceDataHeader *header =
(InstanceDataHeader*)geometry->instData;
geometry->instData = nil;
// TODO: delete ibo and vbo
delete[] header->attribs;
delete[] header->data;
delete header;
return object;
}
Stream*
readNativeData(Stream *stream, int32, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
InstanceDataHeader *header = new InstanceDataHeader;
geometry->instData = header;
header->platform = PLATFORM_WDGL;
header->vbo = 0;
header->ibo = 0;
header->numAttribs = stream->readU32();
header->attribs = new AttribDesc[header->numAttribs];
stream->read(header->attribs,
header->numAttribs*sizeof(AttribDesc));
header->dataSize = header->attribs[0].stride*geometry->numVertices;
header->data = new uint8[header->dataSize];
stream->read(header->data, header->dataSize);
return stream;
}
Stream*
writeNativeData(Stream *stream, int32, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
if(geometry->instData == nil ||
geometry->instData->platform != PLATFORM_WDGL)
return stream;
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
stream->writeU32(header->numAttribs);
stream->write(header->attribs, header->numAttribs*sizeof(AttribDesc));
stream->write(header->data, header->dataSize);
return stream;
}
int32
getSizeNativeData(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
if(geometry->instData == nil ||
geometry->instData->platform != PLATFORM_WDGL)
return 0;
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
return 4 + header->numAttribs*sizeof(AttribDesc) + header->dataSize;
}
void
registerNativeDataPlugin(void)
{
Geometry::registerPlugin(0, ID_NATIVEDATA,
nil, destroyNativeData, nil);
Geometry::registerPluginStream(ID_NATIVEDATA,
readNativeData,
writeNativeData,
getSizeNativeData);
}
void
printPipeinfo(Atomic *a)
{
Geometry *g = a->geometry;
if(g->instData == nil || g->instData->platform != PLATFORM_WDGL)
return;
int32 plgid = 0;
if(a->pipeline)
plgid = a->pipeline->pluginID;
printf("%s %x: ", debugFile, plgid);
InstanceDataHeader *h = (InstanceDataHeader*)g->instData;
for(int i = 0; i < h->numAttribs; i++)
printf("%x(%x) ", h->attribs[i].index, h->attribs[i].type);
printf("\n");
}
static void
instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if(geo->geoflags & Geometry::NATIVE)
return;
InstanceDataHeader *header = new InstanceDataHeader;
geo->instData = header;
header->platform = PLATFORM_WDGL;
header->vbo = 0;
header->ibo = 0;
header->numAttribs =
pipe->numCustomAttribs + 1 + (geo->numTexCoordSets > 0);
if(geo->geoflags & Geometry::PRELIT)
header->numAttribs++;
if(geo->geoflags & Geometry::NORMALS)
header->numAttribs++;
int32 offset = 0;
header->attribs = new AttribDesc[header->numAttribs];
AttribDesc *a = header->attribs;
// Vertices
a->index = 0;
a->type = 0;
a->normalized = 0;
a->size = 3;
a->offset = offset;
offset += 12;
a++;
int32 firstCustom = 1;
// texCoords, only one set here
if(geo->numTexCoordSets){
a->index = 1;
a->type = 3;
a->normalized = 0;
a->size = 2;
a->offset = offset;
offset += 4;
a++;
firstCustom++;
}
if(geo->geoflags & Geometry::NORMALS){
a->index = 2;
a->type = 1;
a->normalized = 1;
a->size = 3;
a->offset = offset;
offset += 4;
a++;
firstCustom++;
}
if(geo->geoflags & Geometry::PRELIT){
a->index = 3;
a->type = 2;
a->normalized = 1;
a->size = 4;
a->offset = offset;
offset += 4;
a++;
firstCustom++;
}
if(pipe->instanceCB)
offset += pipe->instanceCB(geo, firstCustom, offset);
else{
header->dataSize = offset*geo->numVertices;
header->data = new uint8[header->dataSize];
}
a = header->attribs;
for(int32 i = 0; i < header->numAttribs; i++)
a[i].stride = offset;
uint8 *p = header->data + a->offset;
float32 *vert = geo->morphTargets->vertices;
for(int32 i = 0; i < geo->numVertices; i++){
packattrib(p, vert, a);
vert += 3;
p += a->stride;
}
a++;
if(geo->numTexCoordSets){
p = header->data + a->offset;
float32 *texcoord = geo->texCoords[0];
for(int32 i = 0; i < geo->numVertices; i++){
packattrib(p, texcoord, a, 512.0f);
texcoord += 2;
p += a->stride;
}
a++;
}
if(geo->geoflags & Geometry::NORMALS){
p = header->data + a->offset;
float32 *norm = geo->morphTargets->normals;
for(int32 i = 0; i < geo->numVertices; i++){
packattrib(p, norm, a);
norm += 3;
p += a->stride;
}
a++;
}
if(geo->geoflags & Geometry::PRELIT){
// TODO: this seems too complicated
p = header->data + a->offset;
uint8 *color = geo->colors;
float32 f[4];
for(int32 i = 0; i < geo->numVertices; i++){
f[0] = color[0]/255.0f;
f[1] = color[1]/255.0f;
f[2] = color[2]/255.0f;
f[3] = color[3]/255.0f;
packattrib(p, f, a);
color += 4;
p += a->stride;
}
a++;
}
geo->geoflags |= Geometry::NATIVE;
}
static void
uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
return;
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_WDGL);
geo->geoflags &= ~Geometry::NATIVE;
geo->allocateData();
uint8 *p;
float32 *texcoord = geo->texCoords[0];
uint8 *color = geo->colors;
float32 *vert = geo->morphTargets->vertices;
float32 *norm = geo->morphTargets->normals;
float32 f[4];
InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
for(int i = 0; i < header->numAttribs; i++){
AttribDesc *a = &header->attribs[i];
p = header->data + a->offset;
switch(a->index){
case 0: // Vertices
for(int32 i = 0; i < geo->numVertices; i++){
unpackattrib(vert, p, a);
vert += 3;
p += a->stride;
}
break;
case 1: // texCoords
for(int32 i = 0; i < geo->numVertices; i++){
unpackattrib(texcoord, p, a, 512.0f);
texcoord += 2;
p += a->stride;
}
break;
case 2: // normals
for(int32 i = 0; i < geo->numVertices; i++){
unpackattrib(norm, p, a);
norm += 3;
p += a->stride;
}
break;
case 3: // colors
for(int32 i = 0; i < geo->numVertices; i++){
// TODO: this seems too complicated
unpackattrib(f, p, a);
color[0] = f[0]*255.0f;
color[1] = f[1]*255.0f;
color[2] = f[2]*255.0f;
color[3] = f[3]*255.0f;
color += 4;
p += a->stride;
}
break;
}
}
if(pipe->uninstanceCB)
pipe->uninstanceCB(geo);
geo->generateTriangles();
destroyNativeData(geo, 0, 0);
}
ObjPipeline::ObjPipeline(uint32 platform)
: rw::ObjPipeline(platform)
{
this->numCustomAttribs = 0;
this->impl.instance = wdgl::instance;
this->impl.uninstance = wdgl::uninstance;
this->instanceCB = nil;
this->uninstanceCB = nil;
}
ObjPipeline*
makeDefaultPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_WDGL);
return pipe;
}
// Skin
Stream*
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"));
return nil;
}
platform = stream->readU32();
if(platform != PLATFORM_GL){
RWERROR((ERR_PLATFORM, platform));
return nil;
}
Skin *skin = new Skin;
*PLUGINOFFSET(Skin*, geometry, offset) = skin;
int32 numBones = stream->readI32();
skin->init(numBones, 0, 0);
stream->read(skin->inverseMatrices, skin->numBones*64);
return stream;
}
Stream*
writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset)
{
writeChunkHeader(stream, ID_STRUCT, len-12);
stream->writeU32(PLATFORM_WDGL);
Skin *skin = *PLUGINOFFSET(Skin*, object, offset);
stream->writeI32(skin->numBones);
stream->write(skin->inverseMatrices, skin->numBones*64);
return stream;
}
int32
getSizeNativeSkin(void *object, int32 offset)
{
Skin *skin = *PLUGINOFFSET(Skin*, object, offset);
if(skin == nil)
return -1;
int32 size = 12 + 4 + 4 + skin->numBones*64;
return size;
}
uint32
skinInstanceCB(Geometry *g, int32 i, uint32 offset)
{
InstanceDataHeader *header = (InstanceDataHeader*)g->instData;
AttribDesc *a = &header->attribs[i];
// weights
a->index = 4;
a->type = 2; /* but also short o_O */
a->normalized = 1;
a->size = 4;
a->offset = offset;
offset += 4;
a++;
// indices
a->index = 5;
a->type = 2;
a->normalized = 0;
a->size = 4;
a->offset = offset;
offset += 4;
header->dataSize = offset*g->numVertices;
header->data = new uint8[header->dataSize];
Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset);
if(skin == nil)
return 8;
a = &header->attribs[i];
uint8 *wgt = header->data + a[0].offset;
uint8 *idx = header->data + a[1].offset;
uint8 *indices = skin->indices;
float32 *weights = skin->weights;
for(int32 i = 0; i < g->numVertices; i++){
packattrib(wgt, weights, a);
weights += 4;
wgt += offset;
idx[0] = *indices++;
idx[1] = *indices++;
idx[2] = *indices++;
idx[3] = *indices++;
idx += offset;
}
return 8;
}
void
skinUninstanceCB(Geometry *geo)
{
InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset);
if(skin == nil)
return;
uint8 *data = skin->data;
float *invMats = skin->inverseMatrices;
skin->init(skin->numBones, skin->numBones, geo->numVertices);
memcpy(skin->inverseMatrices, invMats, skin->numBones*64);
delete[] data;
uint8 *p;
float *weights = skin->weights;
uint8 *indices = skin->indices;
for(int i = 0; i < header->numAttribs; i++){
AttribDesc *a = &header->attribs[i];
p = header->data + a->offset;
switch(a->index){
case 4: // weights
for(int32 i = 0; i < geo->numVertices; i++){
unpackattrib(weights, p, a);
weights += 4;
p += a->stride;
}
break;
case 5: // indices
for(int32 i = 0; i < geo->numVertices; i++){
*indices++ = p[0];
*indices++ = p[1];
*indices++ = p[2];
*indices++ = p[3];
p += a->stride;
}
break;
}
}
skin->findNumWeights(geo->numVertices);
skin->findUsedBones(geo->numVertices);
}
ObjPipeline*
makeSkinPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_WDGL);
pipe->pluginID = ID_SKIN;
pipe->pluginData = 1;
pipe->numCustomAttribs = 2;
pipe->instanceCB = skinInstanceCB;
pipe->uninstanceCB = skinUninstanceCB;
return pipe;
}
ObjPipeline*
makeMatFXPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_WDGL);
pipe->pluginID = ID_MATFX;
pipe->pluginData = 0;
return pipe;
}
// Raster
int32 nativeRasterOffset;
#ifdef RW_OPENGL
struct GlRaster {
GLuint id;
};
static void*
createNativeRaster(void *object, int32 offset, int32)
{
GlRaster *raster = PLUGINOFFSET(GlRaster, object, offset);
raster->id = 0;
return object;
}
static void*
destroyNativeRaster(void *object, int32 offset, int32)
{
// TODO:
return object;
}
static void*
copyNativeRaster(void *dst, void *, int32 offset, int32)
{
GlRaster *raster = PLUGINOFFSET(GlRaster, dst, offset);
raster->id = 0;
return dst;
}
void
registerNativeRaster(void)
{
nativeRasterOffset = Raster::registerPlugin(sizeof(GlRaster),
0x12340000 | PLATFORM_WDGL,
createNativeRaster,
destroyNativeRaster,
copyNativeRaster);
}
void
Texture::upload(void)
{
GLuint id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
Raster *r = this->raster;
if(r->palette){
printf("can't upload paletted raster\n");
return;
}
static GLenum filter[] = {
0, GL_NEAREST, GL_LINEAR,
GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST,
GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR
};
static GLenum filternomip[] = {
0, GL_NEAREST, GL_LINEAR,
GL_NEAREST, GL_LINEAR,
GL_NEAREST, GL_LINEAR
};
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
filternomip[this->filterAddressing & 0xFF]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
filternomip[this->filterAddressing & 0xFF]);
static GLenum wrap[] = {
0, GL_REPEAT, GL_MIRRORED_REPEAT,
GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
};
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
wrap[(this->filterAddressing >> 8) & 0xF]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
wrap[(this->filterAddressing >> 12) & 0xF]);
switch(r->format & 0xF00){
case Raster::C8888:
glTexImage2D(GL_TEXTURE_2D, 0, 4, r->width, r->height,
0, GL_RGBA, GL_UNSIGNED_BYTE, r->texels);
break;
default:
printf("unsupported raster format: %x\n", r->format);
break;
}
glBindTexture(GL_TEXTURE_2D, 0);
GlRaster *glr = PLUGINOFFSET(GlRaster, r, nativeRasterOffset);
glr->id = id;
}
void
Texture::bind(int n)
{
Raster *r = this->raster;
GlRaster *glr = PLUGINOFFSET(GlRaster, r, nativeRasterOffset);
glActiveTexture(GL_TEXTURE0+n);
if(r){
if(glr->id == 0)
this->upload();
glBindTexture(GL_TEXTURE_2D, glr->id);
}else
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
}
#endif
}
}