Initial commit

This commit is contained in:
Shinovon 2026-04-22 07:30:27 +05:00
commit 77cdaaf97e
827 changed files with 418745 additions and 0 deletions

56
vendor/librw/src/gl/gl3.cpp vendored Normal file
View file

@ -0,0 +1,56 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#include "rwgl3.h"
#include "rwgl3shader.h"
#include "rwgl3impl.h"
namespace rw {
namespace gl3 {
// TODO: make some of these things platform-independent
static void*
driverOpen(void *o, int32, int32)
{
#ifdef RW_OPENGL
engine->driver[PLATFORM_GL3]->defaultPipeline = makeDefaultPipeline();
#endif
engine->driver[PLATFORM_GL3]->rasterNativeOffset = nativeRasterOffset;
engine->driver[PLATFORM_GL3]->rasterCreate = rasterCreate;
engine->driver[PLATFORM_GL3]->rasterLock = rasterLock;
engine->driver[PLATFORM_GL3]->rasterUnlock = rasterUnlock;
engine->driver[PLATFORM_GL3]->rasterNumLevels = rasterNumLevels;
engine->driver[PLATFORM_GL3]->imageFindRasterFormat = imageFindRasterFormat;
engine->driver[PLATFORM_GL3]->rasterFromImage = rasterFromImage;
engine->driver[PLATFORM_GL3]->rasterToImage = rasterToImage;
return o;
}
static void*
driverClose(void *o, int32, int32)
{
return o;
}
void
registerPlatformPlugins(void)
{
Driver::registerPlugin(PLATFORM_GL3, 0, PLATFORM_GL3,
driverOpen, driverClose);
registerNativeRaster();
}
}
}

2111
vendor/librw/src/gl/gl3device.cpp vendored Normal file

File diff suppressed because it is too large Load diff

306
vendor/librw/src/gl/gl3immed.cpp vendored Normal file
View file

@ -0,0 +1,306 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwrender.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#ifdef RW_OPENGL
#include "rwgl3.h"
#include "rwgl3impl.h"
#include "rwgl3shader.h"
namespace rw {
namespace gl3 {
uint32 im2DVbo, im2DIbo;
#ifdef RW_GL_USE_VAOS
uint32 im2DVao;
#endif
Shader *im2dOverrideShader;
static int32 u_xform;
#define STARTINDICES 10000
#define STARTVERTICES 10000
static Shader *im2dShader;
static AttribDesc im2dattribDesc[3] = {
{ ATTRIB_POS, GL_FLOAT, GL_FALSE, 4,
sizeof(Im2DVertex), 0 },
{ ATTRIB_COLOR, GL_UNSIGNED_BYTE, GL_TRUE, 4,
sizeof(Im2DVertex), offsetof(Im2DVertex, r) },
{ ATTRIB_TEXCOORDS0, GL_FLOAT, GL_FALSE, 2,
sizeof(Im2DVertex), offsetof(Im2DVertex, u) },
};
static int primTypeMap[] = {
GL_POINTS, // invalid
GL_LINES,
GL_LINE_STRIP,
GL_TRIANGLES,
GL_TRIANGLE_STRIP,
GL_TRIANGLE_FAN,
GL_POINTS
};
void
openIm2D(void)
{
// must already be registered by device. we just need the value
u_xform = registerUniform("u_xform", UNIFORM_VEC4);
#include "shaders/im2d_gl.inc"
#include "shaders/simple_fs_gl.inc"
const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil };
im2dShader = Shader::create(vs, fs);
assert(im2dShader);
glGenBuffers(1, &im2DIbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2DIbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, STARTINDICES*2, nil, GL_STREAM_DRAW);
glGenBuffers(1, &im2DVbo);
glBindBuffer(GL_ARRAY_BUFFER, im2DVbo);
glBufferData(GL_ARRAY_BUFFER, STARTVERTICES*sizeof(Im2DVertex), nil, GL_STREAM_DRAW);
#ifdef RW_GL_USE_VAOS
glGenVertexArrays(1, &im2DVao);
glBindVertexArray(im2DVao);
setAttribPointers(im2dattribDesc, 3);
#endif
}
void
closeIm2D(void)
{
glDeleteBuffers(1, &im2DIbo);
glDeleteBuffers(1, &im2DVbo);
#ifdef RW_GL_USE_VAOS
glDeleteVertexArrays(1, &im2DVao);
#endif
im2dShader->destroy();
im2dShader = nil;
}
static Im2DVertex tmpprimbuf[3];
void
im2DRenderLine(void *vertices, int32 numVertices, int32 vert1, int32 vert2)
{
Im2DVertex *verts = (Im2DVertex*)vertices;
tmpprimbuf[0] = verts[vert1];
tmpprimbuf[1] = verts[vert2];
im2DRenderPrimitive(PRIMTYPELINELIST, tmpprimbuf, 2);
}
void
im2DRenderTriangle(void *vertices, int32 numVertices, int32 vert1, int32 vert2, int32 vert3)
{
Im2DVertex *verts = (Im2DVertex*)vertices;
tmpprimbuf[0] = verts[vert1];
tmpprimbuf[1] = verts[vert2];
tmpprimbuf[2] = verts[vert3];
im2DRenderPrimitive(PRIMTYPETRILIST, tmpprimbuf, 3);
}
void
im2DSetXform(void)
{
GLfloat xform[4];
Camera *cam;
cam = (Camera*)engine->currentCamera;
xform[0] = 2.0f/cam->frameBuffer->width;
xform[1] = -2.0f/cam->frameBuffer->height;
xform[2] = -1.0f;
xform[3] = 1.0f;
setUniform(u_xform, xform);
// glUniform4fv(currentShader->uniformLocations[u_xform], 1, xform);
}
void
im2DRenderPrimitive(PrimitiveType primType, void *vertices, int32 numVertices)
{
#ifdef RW_GL_USE_VAOS
glBindVertexArray(im2DVao);
#endif
glBindBuffer(GL_ARRAY_BUFFER, im2DVbo);
glBufferData(GL_ARRAY_BUFFER, STARTVERTICES*sizeof(Im2DVertex), nil, GL_STREAM_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*sizeof(Im2DVertex), vertices);
if(im2dOverrideShader)
im2dOverrideShader->use();
else
im2dShader->use();
#ifndef RW_GL_USE_VAOS
setAttribPointers(im2dattribDesc, 3);
#endif
im2DSetXform();
flushCache();
glDrawArrays(primTypeMap[primType], 0, numVertices);
#ifndef RW_GL_USE_VAOS
disableAttribPointers(im2dattribDesc, 3);
#endif
}
void
im2DRenderIndexedPrimitive(PrimitiveType primType,
void *vertices, int32 numVertices,
void *indices, int32 numIndices)
{
#ifdef RW_GL_USE_VAOS
glBindVertexArray(im2DVao);
#endif
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2DIbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, STARTINDICES*2, nil, GL_STREAM_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, numIndices*2, indices);
glBindBuffer(GL_ARRAY_BUFFER, im2DVbo);
glBufferData(GL_ARRAY_BUFFER, STARTVERTICES*sizeof(Im2DVertex), nil, GL_STREAM_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*sizeof(Im2DVertex), vertices);
if(im2dOverrideShader)
im2dOverrideShader->use();
else
im2dShader->use();
#ifndef RW_GL_USE_VAOS
setAttribPointers(im2dattribDesc, 3);
#endif
im2DSetXform();
flushCache();
glDrawElements(primTypeMap[primType], numIndices,
GL_UNSIGNED_SHORT, nil);
#ifndef RW_GL_USE_VAOS
disableAttribPointers(im2dattribDesc, 3);
#endif
}
// Im3D
static Shader *im3dShader;
static AttribDesc im3dattribDesc[3] = {
{ ATTRIB_POS, GL_FLOAT, GL_FALSE, 3,
sizeof(Im3DVertex), 0 },
{ ATTRIB_COLOR, GL_UNSIGNED_BYTE, GL_TRUE, 4,
sizeof(Im3DVertex), offsetof(Im3DVertex, r) },
{ ATTRIB_TEXCOORDS0, GL_FLOAT, GL_FALSE, 2,
sizeof(Im3DVertex), offsetof(Im3DVertex, u) },
};
static uint32 im3DVbo, im3DIbo;
#ifdef RW_GL_USE_VAOS
static uint32 im3DVao;
#endif
static int32 num3DVertices; // not actually needed here
void
openIm3D(void)
{
#include "shaders/im3d_gl.inc"
#include "shaders/simple_fs_gl.inc"
const char *vs[] = { shaderDecl, header_vert_src, im3d_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil };
im3dShader = Shader::create(vs, fs);
assert(im3dShader);
glGenBuffers(1, &im3DIbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im3DIbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, STARTINDICES*2, nil, GL_STREAM_DRAW);
glGenBuffers(1, &im3DVbo);
glBindBuffer(GL_ARRAY_BUFFER, im3DVbo);
glBufferData(GL_ARRAY_BUFFER, STARTVERTICES*sizeof(Im3DVertex), nil, GL_STREAM_DRAW);
#ifdef RW_GL_USE_VAOS
glGenVertexArrays(1, &im3DVao);
glBindVertexArray(im3DVao);
setAttribPointers(im3dattribDesc, 3);
#endif
}
void
closeIm3D(void)
{
glDeleteBuffers(1, &im3DIbo);
glDeleteBuffers(1, &im3DVbo);
#ifdef RW_GL_USE_VAOS
glDeleteVertexArrays(1, &im3DVao);
#endif
im3dShader->destroy();
im3dShader = nil;
}
void
im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags)
{
if(world == nil){
static Matrix ident;
ident.setIdentity();
world = &ident;
}
setWorldMatrix(world);
im3dShader->use();
if((flags & im3d::VERTEXUV) == 0)
SetRenderStatePtr(TEXTURERASTER, nil);
#ifdef RW_GL_USE_VAOS
glBindVertexArray(im2DVao);
#endif
glBindBuffer(GL_ARRAY_BUFFER, im3DVbo);
glBufferData(GL_ARRAY_BUFFER, STARTVERTICES*sizeof(Im3DVertex), nil, GL_STREAM_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*sizeof(Im3DVertex), vertices);
#ifndef RW_GL_USE_VAOS
setAttribPointers(im3dattribDesc, 3);
#endif
num3DVertices = numVertices;
}
void
im3DRenderPrimitive(PrimitiveType primType)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im3DIbo);
flushCache();
glDrawArrays(primTypeMap[primType], 0, num3DVertices);
}
void
im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im3DIbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, STARTINDICES*2, nil, GL_STREAM_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, numIndices*2, indices);
flushCache();
glDrawElements(primTypeMap[primType], numIndices,
GL_UNSIGNED_SHORT, nil);
}
void
im3DEnd(void)
{
#ifndef RW_GL_USE_VAOS
disableAttribPointers(im3dattribDesc, 3);
#endif
}
}
}
#endif

258
vendor/librw/src/gl/gl3matfx.cpp vendored Normal file
View file

@ -0,0 +1,258 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwrender.h"
#include "../rwengine.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwanim.h"
#include "../rwplugins.h"
#include "rwgl3.h"
#include "rwgl3shader.h"
#include "rwgl3plg.h"
#include "rwgl3impl.h"
namespace rw {
namespace gl3 {
#ifdef RW_OPENGL
static Shader *envShader, *envShader_noAT;
static Shader *envShader_fullLight, *envShader_fullLight_noAT;
static int32 u_texMatrix;
static int32 u_fxparams;
static int32 u_colorClamp;
static int32 u_envColor;
void
matfxDefaultRender(InstanceDataHeader *header, InstanceData *inst, int32 vsBits, uint32 flags)
{
Material *m;
m = inst->material;
setMaterial(flags, m->color, m->surfaceProps);
setTexture(0, m->texture);
rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
if((vsBits & VSLIGHT_MASK) == 0){
if(getAlphaTest())
defaultShader->use();
else
defaultShader_noAT->use();
}else{
if(getAlphaTest())
defaultShader_fullLight->use();
else
defaultShader_fullLight_noAT->use();
}
drawInst(header, inst);
}
static Frame *lastEnvFrame;
static RawMatrix normal2texcoord = {
{ 0.5f, 0.0f, 0.0f }, 0.0f,
{ 0.0f, -0.5f, 0.0f }, 0.0f,
{ 0.0f, 0.0f, 1.0f }, 0.0f,
{ 0.5f, 0.5f, 0.0f }, 1.0f
};
void
uploadEnvMatrix(Frame *frame)
{
Matrix invMat;
if(frame == nil)
frame = engine->currentCamera->getFrame();
// cache the matrix across multiple meshes
static RawMatrix envMtx;
// can't do it, frame matrix may change
// if(frame != lastEnvFrame){
// lastEnvFrame = frame;
{
RawMatrix invMtx;
Matrix::invert(&invMat, frame->getLTM());
convMatrix(&invMtx, &invMat);
invMtx.pos.set(0.0f, 0.0f, 0.0f);
float uscale = fabs(normal2texcoord.right.x);
normal2texcoord.right.x = MatFX::envMapFlipU ? -uscale : uscale;
RawMatrix::mult(&envMtx, &invMtx, &normal2texcoord);
}
setUniform(u_texMatrix, &envMtx);
}
void
matfxEnvRender(InstanceDataHeader *header, InstanceData *inst, int32 vsBits, uint32 flags, MatFX::Env *env)
{
Material *m;
m = inst->material;
if(env->tex == nil || env->coefficient == 0.0f){
matfxDefaultRender(header, inst, vsBits, flags);
return;
}
setTexture(0, m->texture);
setTexture(1, env->tex);
uploadEnvMatrix(env->frame);
setMaterial(flags, m->color, m->surfaceProps);
float fxparams[4];
fxparams[0] = env->coefficient;
fxparams[1] = env->fbAlpha ? 0.0f : 1.0f;
fxparams[2] = fxparams[3] = 0.0f;
setUniform(u_fxparams, fxparams);
static float zero[4];
static float one[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
// This clamps the vertex color below. With it we can achieve both PC and PS2 style matfx
if(MatFX::envMapApplyLight)
setUniform(u_colorClamp, zero);
else
setUniform(u_colorClamp, one);
RGBAf envcol[4];
if(MatFX::envMapUseMatColor)
convColor(envcol, &m->color);
else
convColor(envcol, &MatFX::envMapColor);
setUniform(u_envColor, envcol);
rw::SetRenderState(VERTEXALPHA, 1);
rw::SetRenderState(SRCBLEND, BLENDONE);
if((vsBits & VSLIGHT_MASK) == 0){
if(getAlphaTest())
envShader->use();
else
envShader_noAT->use();
}else{
if(getAlphaTest())
envShader_fullLight->use();
else
envShader_fullLight_noAT->use();
}
drawInst(header, inst);
rw::SetRenderState(SRCBLEND, BLENDSRCALPHA);
}
void
matfxRenderCB(Atomic *atomic, InstanceDataHeader *header)
{
uint32 flags = atomic->geometry->flags;
setWorldMatrix(atomic->getFrame()->getLTM());
int32 vsBits = lightingCB(atomic);
setupVertexInput(header);
lastEnvFrame = nil;
InstanceData *inst = header->inst;
int32 n = header->numMeshes;
while(n--){
MatFX *matfx = MatFX::get(inst->material);
if(matfx == nil)
matfxDefaultRender(header, inst, vsBits, flags);
else switch(matfx->type){
case MatFX::ENVMAP:
matfxEnvRender(header, inst, vsBits, flags, &matfx->fx[0].env);
break;
default:
matfxDefaultRender(header, inst, vsBits, flags);
break;
}
inst++;
}
teardownVertexInput(header);
}
ObjPipeline*
makeMatFXPipeline(void)
{
ObjPipeline *pipe = ObjPipeline::create();
pipe->instanceCB = defaultInstanceCB;
pipe->uninstanceCB = defaultUninstanceCB;
pipe->renderCB = matfxRenderCB;
pipe->pluginID = ID_MATFX;
pipe->pluginData = 0;
return pipe;
}
static void*
matfxOpen(void *o, int32, int32)
{
matFXGlobals.pipelines[PLATFORM_GL3] = makeMatFXPipeline();
#include "shaders/matfx_gl.inc"
const char *vs[] = { shaderDecl, header_vert_src, matfx_env_vert_src, nil };
const char *vs_fullLight[] = { shaderDecl, "#define DIRECTIONALS\n#define POINTLIGHTS\n#define SPOTLIGHTS\n", header_vert_src, matfx_env_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, matfx_env_frag_src, nil };
const char *fs_noAT[] = { shaderDecl, "#define NO_ALPHATEST\n", header_frag_src, matfx_env_frag_src, nil };
envShader = Shader::create(vs, fs);
assert(envShader);
envShader_noAT = Shader::create(vs, fs_noAT);
assert(envShader_noAT);
envShader_fullLight = Shader::create(vs_fullLight, fs);
assert(envShader_fullLight);
envShader_fullLight_noAT = Shader::create(vs_fullLight, fs_noAT);
assert(envShader_fullLight_noAT);
return o;
}
static void*
matfxClose(void *o, int32, int32)
{
((ObjPipeline*)matFXGlobals.pipelines[PLATFORM_GL3])->destroy();
matFXGlobals.pipelines[PLATFORM_GL3] = nil;
envShader->destroy();
envShader = nil;
envShader_noAT->destroy();
envShader_noAT = nil;
envShader_fullLight->destroy();
envShader_fullLight = nil;
envShader_fullLight_noAT->destroy();
envShader_fullLight_noAT = nil;
return o;
}
void
initMatFX(void)
{
u_texMatrix = registerUniform("u_texMatrix", UNIFORM_MAT4);
u_fxparams = registerUniform("u_fxparams", UNIFORM_VEC4);
u_colorClamp = registerUniform("u_colorClamp", UNIFORM_VEC4);
u_envColor = registerUniform("u_envColor", UNIFORM_VEC4);
Driver::registerPlugin(PLATFORM_GL3, 0, ID_MATFX,
matfxOpen, matfxClose);
}
#else
void initMatFX(void) { }
#endif
}
}

333
vendor/librw/src/gl/gl3pipe.cpp vendored Normal file
View file

@ -0,0 +1,333 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#include "rwgl3.h"
#include "rwgl3shader.h"
namespace rw {
namespace gl3 {
// TODO: make some of these things platform-independent
#ifdef RW_OPENGL
void
freeInstanceData(Geometry *geometry)
{
if(geometry->instData == nil ||
geometry->instData->platform != PLATFORM_GL3)
return;
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
geometry->instData = nil;
glDeleteBuffers(1, &header->ibo);
glDeleteBuffers(1, &header->vbo);
#ifdef RW_GL_USE_VAOS
glDeleteBuffers(1, &header->vao);
#endif
rwFree(header->indexBuffer);
rwFree(header->vertexBuffer);
rwFree(header->attribDesc);
rwFree(header->inst);
rwFree(header);
}
void*
destroyNativeData(void *object, int32, int32)
{
freeInstanceData((Geometry*)object);
return object;
}
static InstanceDataHeader*
instanceMesh(rw::ObjPipeline *rwpipe, Geometry *geo)
{
InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY);
MeshHeader *meshh = geo->meshHeader;
geo->instData = header;
header->platform = PLATFORM_GL3;
header->serialNumber = meshh->serialNum;
header->numMeshes = meshh->numMeshes;
header->primType = meshh->flags == 1 ? GL_TRIANGLE_STRIP : GL_TRIANGLES;
header->totalNumVertex = geo->numVertices;
header->totalNumIndex = meshh->totalIndices;
header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY);
header->indexBuffer = rwNewT(uint16, header->totalNumIndex, MEMDUR_EVENT | ID_GEOMETRY);
InstanceData *inst = header->inst;
Mesh *mesh = meshh->getMeshes();
uint32 offset = 0;
for(uint32 i = 0; i < header->numMeshes; i++){
findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
&inst->minVert, &inst->numVertices);
assert(inst->minVert != 0xFFFFFFFF);
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;
#ifdef RW_GL_USE_VAOS
glGenVertexArrays(1, &header->vao);
glBindVertexArray(header->vao);
#endif
glGenBuffers(1, &header->ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, header->totalNumIndex*2,
header->indexBuffer, GL_STATIC_DRAW);
return header;
}
static void
instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
// don't try to (re)instance native data
if(geo->flags & Geometry::NATIVE)
return;
InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
if(geo->instData){
// Already have instanced data, so check if we have to reinstance
assert(header->platform == PLATFORM_GL3);
if(header->serialNumber != geo->meshHeader->serialNum){
// Mesh changed, so reinstance everything
freeInstanceData(geo);
}
}
// no instance or complete reinstance
if(geo->instData == nil){
geo->instData = instanceMesh(rwpipe, geo);
pipe->instanceCB(geo, (InstanceDataHeader*)geo->instData, 0);
}else if(geo->lockedSinceInst)
pipe->instanceCB(geo, (InstanceDataHeader*)geo->instData, 1);
geo->lockedSinceInst = 0;
}
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;
pipe->instance(atomic);
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_GL3);
if(pipe->renderCB)
pipe->renderCB(atomic, (InstanceDataHeader*)geo->instData);
}
void
ObjPipeline::init(void)
{
this->rw::ObjPipeline::init(PLATFORM_GL3);
this->impl.instance = gl3::instance;
this->impl.uninstance = gl3::uninstance;
this->impl.render = gl3::render;
this->instanceCB = nil;
this->uninstanceCB = nil;
this->renderCB = nil;
}
ObjPipeline*
ObjPipeline::create(void)
{
ObjPipeline *pipe = rwNewT(ObjPipeline, 1, MEMDUR_GLOBAL);
pipe->init();
return pipe;
}
void
defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance)
{
AttribDesc *attribs, *a;
bool isPrelit = !!(geo->flags & Geometry::PRELIT);
bool hasNormals = !!(geo->flags & Geometry::NORMALS);
if(!reinstance){
AttribDesc tmpAttribs[12];
uint32 stride;
//
// Create attribute descriptions
//
a = tmpAttribs;
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
if(hasNormals){
a->index = ATTRIB_NORMAL;
a->size = 3;
a->type = GL_FLOAT;
a->normalized = GL_FALSE;
a->offset = stride;
stride += 12;
a++;
}
// Prelighting
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 - tmpAttribs;
for(a = tmpAttribs; a != &tmpAttribs[header->numAttribs]; a++)
a->stride = stride;
header->attribDesc = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY);
memcpy(header->attribDesc, tmpAttribs,
header->numAttribs*sizeof(AttribDesc));
//
// Allocate vertex buffer
//
header->vertexBuffer = rwNewT(uint8, header->totalNumVertex*stride, MEMDUR_EVENT | ID_GEOMETRY);
assert(header->vbo == 0);
glGenBuffers(1, &header->vbo);
}
attribs = header->attribDesc;
//
// Fill vertex buffer
//
uint8 *verts = header->vertexBuffer;
// Positions
if(!reinstance || geo->lockedSinceInst&Geometry::LOCKVERTICES){
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 && (!reinstance || geo->lockedSinceInst&Geometry::LOCKNORMALS)){
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 && (!reinstance || geo->lockedSinceInst&Geometry::LOCKPRELIGHT)){
for(a = attribs; a->index != ATTRIB_COLOR; a++)
;
int n = header->numMeshes;
InstanceData *inst = header->inst;
while(n--){
assert(inst->minVert != 0xFFFFFFFF);
inst->vertexAlpha = instColor(VERT_RGBA,
verts + a->offset + a->stride*inst->minVert,
geo->colors + inst->minVert,
inst->numVertices, a->stride);
inst++;
}
}
// Texture coordinates
for(int32 n = 0; n < geo->numTexCoordSets; n++){
if(!reinstance || geo->lockedSinceInst&(Geometry::LOCKTEXCOORDS<<n)){
for(a = attribs; a->index != ATTRIB_TEXCOORDS0+n; a++)
;
instTexCoords(VERT_FLOAT2, verts + a->offset,
geo->texCoords[n],
header->totalNumVertex, a->stride);
}
}
#ifdef RW_GL_USE_VAOS
glBindVertexArray(header->vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo);
#endif
glBindBuffer(GL_ARRAY_BUFFER, header->vbo);
glBufferData(GL_ARRAY_BUFFER, header->totalNumVertex*attribs[0].stride,
header->vertexBuffer, GL_STATIC_DRAW);
#ifdef RW_GL_USE_VAOS
setAttribPointers(header->attribDesc, header->numAttribs);
glBindVertexArray(0);
#endif
}
void
defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header)
{
assert(0 && "can't uninstance");
}
ObjPipeline*
makeDefaultPipeline(void)
{
ObjPipeline *pipe = ObjPipeline::create();
pipe->instanceCB = defaultInstanceCB;
pipe->uninstanceCB = defaultUninstanceCB;
pipe->renderCB = defaultRenderCB;
return pipe;
}
#else
void *destroyNativeData(void *object, int32, int32) { return object; }
#endif
}
}

1045
vendor/librw/src/gl/gl3raster.cpp vendored Normal file

File diff suppressed because it is too large Load diff

184
vendor/librw/src/gl/gl3render.cpp vendored Normal file
View file

@ -0,0 +1,184 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwrender.h"
#include "../rwengine.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#ifdef RW_OPENGL
#include "rwgl3.h"
#include "rwgl3shader.h"
#include "rwgl3impl.h"
namespace rw {
namespace gl3 {
#define MAX_LIGHTS
void
drawInst_simple(InstanceDataHeader *header, InstanceData *inst)
{
flushCache();
glDrawElements(header->primType, inst->numIndex,
GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset);
}
// Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer
void
drawInst_GSemu(InstanceDataHeader *header, InstanceData *inst)
{
uint32 hasAlpha;
int alphafunc, alpharef, gsalpharef;
int zwrite;
hasAlpha = getAlphaBlend();
if(hasAlpha){
zwrite = rw::GetRenderState(rw::ZWRITEENABLE);
alphafunc = rw::GetRenderState(rw::ALPHATESTFUNC);
if(zwrite){
alpharef = rw::GetRenderState(rw::ALPHATESTREF);
gsalpharef = rw::GetRenderState(rw::GSALPHATESTREF);
SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL);
SetRenderState(rw::ALPHATESTREF, gsalpharef);
drawInst_simple(header, inst);
SetRenderState(rw::ALPHATESTFUNC, rw::ALPHALESS);
SetRenderState(rw::ZWRITEENABLE, 0);
drawInst_simple(header, inst);
SetRenderState(rw::ZWRITEENABLE, 1);
SetRenderState(rw::ALPHATESTFUNC, alphafunc);
SetRenderState(rw::ALPHATESTREF, alpharef);
}else{
SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAALWAYS);
drawInst_simple(header, inst);
SetRenderState(rw::ALPHATESTFUNC, alphafunc);
}
}else
drawInst_simple(header, inst);
}
void
drawInst(InstanceDataHeader *header, InstanceData *inst)
{
if(rw::GetRenderState(rw::GSALPHATEST))
drawInst_GSemu(header, inst);
else
drawInst_simple(header, inst);
}
void
setAttribPointers(AttribDesc *attribDescs, int32 numAttribs)
{
AttribDesc *a;
for(a = attribDescs; a != &attribDescs[numAttribs]; a++){
glEnableVertexAttribArray(a->index);
glVertexAttribPointer(a->index, a->size, a->type, a->normalized,
a->stride, (void*)(uint64)a->offset);
}
}
void
disableAttribPointers(AttribDesc *attribDescs, int32 numAttribs)
{
AttribDesc *a;
for(a = attribDescs; a != &attribDescs[numAttribs]; a++)
glDisableVertexAttribArray(a->index);
}
void
setupVertexInput(InstanceDataHeader *header)
{
#ifdef RW_GL_USE_VAOS
glBindVertexArray(header->vao);
#else
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo);
glBindBuffer(GL_ARRAY_BUFFER, header->vbo);
setAttribPointers(header->attribDesc, header->numAttribs);
#endif
}
void
teardownVertexInput(InstanceDataHeader *header)
{
#ifndef RW_GL_USE_VAOS
disableAttribPointers(header->attribDesc, header->numAttribs);
#endif
}
int32
lightingCB(Atomic *atomic)
{
WorldLights lightData;
Light *directionals[8];
Light *locals[8];
lightData.directionals = directionals;
lightData.numDirectionals = 8;
lightData.locals = locals;
lightData.numLocals = 8;
if(atomic->geometry->flags & rw::Geometry::LIGHT){
((World*)engine->currentWorld)->enumerateLights(atomic, &lightData);
if((atomic->geometry->flags & rw::Geometry::NORMALS) == 0){
// Get rid of lights that need normals when we don't have any
lightData.numDirectionals = 0;
lightData.numLocals = 0;
}
return setLights(&lightData);
}else{
memset(&lightData, 0, sizeof(lightData));
return setLights(&lightData);
}
}
void
defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
{
Material *m;
uint32 flags = atomic->geometry->flags;
setWorldMatrix(atomic->getFrame()->getLTM());
int32 vsBits = lightingCB(atomic);
setupVertexInput(header);
InstanceData *inst = header->inst;
int32 n = header->numMeshes;
while(n--){
m = inst->material;
setMaterial(flags, m->color, m->surfaceProps);
setTexture(0, m->texture);
rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
if((vsBits & VSLIGHT_MASK) == 0){
if(getAlphaTest())
defaultShader->use();
else
defaultShader_noAT->use();
}else{
if(getAlphaTest())
defaultShader_fullLight->use();
else
defaultShader_fullLight_noAT->use();
}
drawInst(header, inst);
inst++;
}
teardownVertexInput(header);
}
}
}
#endif

355
vendor/librw/src/gl/gl3shader.cpp vendored Normal file
View file

@ -0,0 +1,355 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#ifdef RW_OPENGL
#include "rwgl3.h"
#include "rwgl3shader.h"
namespace rw {
namespace gl3 {
#include "shaders/header_vs.inc"
#include "shaders/header_fs.inc"
UniformRegistry uniformRegistry;
static char nameBuffer[(MAX_UNIFORMS + MAX_BLOCKS)*32]; // static because memory system isn't up yet when we register
static uint32 nameBufPtr;
static float uniformData[512*4]; // seems enough
static uint32 dataPtr;
static int uniformTypesize[] = {
0, 4, 4, 16
};
static char*
shader_strdup(const char *name)
{
size_t len = strlen(name)+1;
char *s = &nameBuffer[nameBufPtr];
nameBufPtr += len;
assert(nameBufPtr <= nelem(nameBuffer));
memcpy(s, name, len);
return s;
}
int32
registerUniform(const char *name, UniformType type, int32 num)
{
int i;
i = findUniform(name);
if(i >= 0){
Uniform *u = &uniformRegistry.uniforms[i];
assert(u->type == type);
assert(u->num == num);
return i;
}
// TODO: print error
if(uniformRegistry.numUniforms+1 >= MAX_UNIFORMS){
assert(0 && "no space for uniform");
return -1;
}
Uniform *u = &uniformRegistry.uniforms[uniformRegistry.numUniforms];
u->name = shader_strdup(name);
u->type = type;
u->serialNum = 0;
if(type == UNIFORM_NA){
u->num = 0;
u->data = nil;
}else{
u->num = num;
u->data = &uniformData[dataPtr];
dataPtr += uniformTypesize[type]*num;
assert(dataPtr <= nelem(uniformData));
}
return uniformRegistry.numUniforms++;
}
int32
findUniform(const char *name)
{
int i;
for(i = 0; i < uniformRegistry.numUniforms; i++)
if(strcmp(name, uniformRegistry.uniforms[i].name) == 0)
return i;
return -1;
}
int32
registerBlock(const char *name)
{
int i;
i = findBlock(name);
if(i >= 0) return i;
// TODO: print error
if(uniformRegistry.numBlocks+1 >= MAX_BLOCKS)
return -1;
uniformRegistry.blockNames[uniformRegistry.numBlocks] = shader_strdup(name);
return uniformRegistry.numBlocks++;
}
int32
findBlock(const char *name)
{
int i;
for(i = 0; i < uniformRegistry.numBlocks; i++)
if(strcmp(name, uniformRegistry.blockNames[i]) == 0)
return i;
return -1;
}
void
setUniform(int32 id, void *data)
{
Uniform *u = &uniformRegistry.uniforms[id];
assert(u->type != UNIFORM_NA);
if(memcmp(u->data, data, uniformTypesize[u->type]*u->num * sizeof(float)) != 0){
memcpy(u->data, data, uniformTypesize[u->type]*u->num * sizeof(float));
//u->dirty = true;
u->serialNum++;
}
}
void
flushUniforms(void)
{
for(int i = 0; i < uniformRegistry.numUniforms; i++){
// this is bad!
if(i >= currentShader->numUniforms){
printf("trying to set uniform %d %s that doesn't exist!\n", i, uniformRegistry.uniforms[i].name);
continue;
}
int32 loc = currentShader->uniformLocations[i];
if(loc == -1)
continue;
Uniform *u = &uniformRegistry.uniforms[i];
if(currentShader->serialNums[i] != u->serialNum)
switch(u->type){
case UNIFORM_NA:
break;
case UNIFORM_VEC4:
glUniform4fv(loc, u->num, (GLfloat*)u->data);
break;
case UNIFORM_IVEC4:
glUniform4iv(loc, u->num, (GLint*)u->data);
break;
case UNIFORM_MAT4:
glUniformMatrix4fv(loc, u->num, GL_FALSE, (GLfloat*)u->data);
break;
}
currentShader->serialNums[i] = u->serialNum;
}
}
Shader *currentShader;
static void
printShaderSource(const char **src)
{
int f;
const char *file;
bool printline;
int line = 1;
for(f = 0; src[f]; f++){
int fileline = 1;
char c;
file = src[f];
printline = true;
while(c = *file++, c != '\0'){
if(printline)
printf("%.4d/%d:%.4d: ", line++, f, fileline++);
putchar(c);
printline = c == '\n';
}
putchar('\n');
}
}
static int
compileshader(GLenum type, const char **src, GLuint *shader)
{
GLint n;
GLint shdr, success;
GLint len;
char *log;
for(n = 0; src[n]; n++);
shdr = glCreateShader(type);
glShaderSource(shdr, n, src, nil);
glCompileShader(shdr);
glGetShaderiv(shdr, GL_COMPILE_STATUS, &success);
if(!success){
printShaderSource(src);
fprintf(stderr, "Error in %s shader\n",
type == GL_VERTEX_SHADER ? "vertex" : "fragment");
glGetShaderiv(shdr, GL_INFO_LOG_LENGTH, &len);
log = (char*)rwMalloc(len, MEMDUR_FUNCTION);
glGetShaderInfoLog(shdr, len, nil, log);
fprintf(stderr, "%s\n", log);
rwFree(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();
if(gl3Caps.glversion < 30){
// TODO: perhaps just do this always and get rid of the layout stuff?
glBindAttribLocation(prog, ATTRIB_POS, "in_pos");
glBindAttribLocation(prog, ATTRIB_NORMAL, "in_normal");
glBindAttribLocation(prog, ATTRIB_COLOR, "in_color");
glBindAttribLocation(prog, ATTRIB_WEIGHTS, "in_weights");
glBindAttribLocation(prog, ATTRIB_INDICES, "in_indices");
glBindAttribLocation(prog, ATTRIB_TEXCOORDS0, "in_tex0");
glBindAttribLocation(prog, ATTRIB_TEXCOORDS1, "in_tex1");
}
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*)rwMalloc(len, MEMDUR_FUNCTION);
glGetProgramInfoLog(prog, len, nil, log);
fprintf(stderr, "%s\n", log);
rwFree(log);
return 1;
}
*program = prog;
return 0;
}
Shader*
Shader::create(const char **vsrc, const char **fsrc)
{
GLuint vs, fs, program;
int i;
int fail;
fail = compileshader(GL_VERTEX_SHADER, vsrc, &vs);
if(fail)
return nil;
fail = compileshader(GL_FRAGMENT_SHADER, fsrc, &fs);
if(fail){
glDeleteShader(vs);
return nil;
}
fail = linkprogram(vs, fs, &program);
glDeleteShader(vs);
glDeleteShader(fs);
if(fail){
return nil;
}
Shader *sh = rwNewT(Shader, 1, MEMDUR_EVENT | ID_DRIVER); // or global?
#ifdef xxxRW_GLES2
int numUniforms;
glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numUniforms);
for(i = 0; i < numUniforms; i++){
GLint size;
GLenum type;
char name[100];
glGetActiveUniform(program, i, 100, nil, &size, &type, name);
printf("%d %d %s\n", size, type, name);
}
printf("\n");
#endif
#ifdef xxxRW_GLES2
int numAttribs;
glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &numAttribs);
for(i = 0; i < numAttribs; i++){
GLint size;
GLenum type;
char name[100];
glGetActiveAttrib(program, i, 100, nil, &size, &type, name);
GLint bind = glGetAttribLocation(program, name);
printf("%d %d %s. %d\n", size, type, name, bind);
}
printf("\n");
#endif
// 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->numUniforms = uniformRegistry.numUniforms;
sh->uniformLocations = rwNewT(GLint, uniformRegistry.numUniforms, MEMDUR_EVENT | ID_DRIVER);
sh->serialNums = rwNewT(uint32, uniformRegistry.numUniforms, MEMDUR_EVENT | ID_DRIVER);
for(i = 0; i < uniformRegistry.numUniforms; i++){
sh->uniformLocations[i] = glGetUniformLocation(program,
uniformRegistry.uniforms[i].name);
sh->serialNums[i] = ~0; // let's hope this means dirty
}
// set samplers
glUseProgram(program);
char name[64];
GLint loc;
for(i = 0; i < 4; i++){
sprintf(name, "tex%d", i);
loc = glGetUniformLocation(program, name);
glUniform1i(loc, i);
}
// reset program
if(currentShader)
glUseProgram(currentShader->program);
return sh;
}
void
Shader::use(void)
{
if(currentShader != this){
glUseProgram(this->program);
currentShader = this;
}
}
void
Shader::destroy(void)
{
glDeleteProgram(this->program);
rwFree(this->uniformLocations);
rwFree(this->serialNums);
rwFree(this);
}
}
}
#endif

366
vendor/librw/src/gl/gl3skin.cpp vendored Normal file
View file

@ -0,0 +1,366 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwrender.h"
#include "../rwengine.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwanim.h"
#include "../rwplugins.h"
#include "rwgl3.h"
#include "rwgl3shader.h"
#include "rwgl3plg.h"
#include "rwgl3impl.h"
namespace rw {
namespace gl3 {
#ifdef RW_OPENGL
static Shader *skinShader, *skinShader_noAT;
static Shader *skinShader_fullLight, *skinShader_fullLight_noAT;
static int32 u_boneMatrices;
void
skinInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance)
{
AttribDesc *attribs, *a;
bool isPrelit = !!(geo->flags & Geometry::PRELIT);
bool hasNormals = !!(geo->flags & Geometry::NORMALS);
if(!reinstance){
AttribDesc tmpAttribs[14];
uint32 stride;
//
// Create attribute descriptions
//
a = tmpAttribs;
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
if(hasNormals){
a->index = ATTRIB_NORMAL;
a->size = 3;
a->type = GL_FLOAT;
a->normalized = GL_FALSE;
a->offset = stride;
stride += 12;
a++;
}
// Prelighting
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++;
}
// Weights
a->index = ATTRIB_WEIGHTS;
a->size = 4;
a->type = GL_FLOAT;
a->normalized = GL_FALSE;
a->offset = stride;
stride += 16;
a++;
// Indices
a->index = ATTRIB_INDICES;
a->size = 4;
a->type = GL_UNSIGNED_BYTE;
a->normalized = GL_FALSE;
a->offset = stride;
stride += 4;
a++;
header->numAttribs = a - tmpAttribs;
for(a = tmpAttribs; a != &tmpAttribs[header->numAttribs]; a++)
a->stride = stride;
header->attribDesc = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY);
memcpy(header->attribDesc, tmpAttribs,
header->numAttribs*sizeof(AttribDesc));
//
// Allocate vertex buffer
//
header->vertexBuffer = rwNewT(uint8, header->totalNumVertex*stride, MEMDUR_EVENT | ID_GEOMETRY);
assert(header->vbo == 0);
glGenBuffers(1, &header->vbo);
}
Skin *skin = Skin::get(geo);
attribs = header->attribDesc;
//
// Fill vertex buffer
//
uint8 *verts = header->vertexBuffer;
// Positions
if(!reinstance || geo->lockedSinceInst&Geometry::LOCKVERTICES){
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 && (!reinstance || geo->lockedSinceInst&Geometry::LOCKNORMALS)){
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 && (!reinstance || geo->lockedSinceInst&Geometry::LOCKPRELIGHT)){
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++){
if(!reinstance || geo->lockedSinceInst&(Geometry::LOCKTEXCOORDS<<n)){
for(a = attribs; a->index != ATTRIB_TEXCOORDS0+n; a++)
;
instTexCoords(VERT_FLOAT2, verts + a->offset,
geo->texCoords[n],
header->totalNumVertex, a->stride);
}
}
// Weights
if(!reinstance){
for(a = attribs; a->index != ATTRIB_WEIGHTS; a++)
;
float *w = skin->weights;
instV4d(VERT_FLOAT4, verts + a->offset,
(V4d*)w,
header->totalNumVertex, a->stride);
}
// Indices
if(!reinstance){
for(a = attribs; a->index != ATTRIB_INDICES; a++)
;
// not really colors of course but what the heck
instColor(VERT_RGBA, verts + a->offset,
(RGBA*)skin->indices,
header->totalNumVertex, a->stride);
}
#ifdef RW_GL_USE_VAOS
glBindVertexArray(header->vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo);
#endif
glBindBuffer(GL_ARRAY_BUFFER, header->vbo);
glBufferData(GL_ARRAY_BUFFER, header->totalNumVertex*attribs[0].stride,
header->vertexBuffer, GL_STATIC_DRAW);
#ifdef RW_GL_USE_VAOS
setAttribPointers(header->attribDesc, header->numAttribs);
glBindVertexArray(0);
#endif
}
void
skinUninstanceCB(Geometry *geo, InstanceDataHeader *header)
{
assert(0 && "can't uninstance");
}
static float skinMatrices[64*16];
void
uploadSkinMatrices(Atomic *a)
{
int i;
Skin *skin = Skin::get(a->geometry);
Matrix *m = (Matrix*)skinMatrices;
HAnimHierarchy *hier = Skin::getHierarchy(a);
if(hier){
Matrix *invMats = (Matrix*)skin->inverseMatrices;
Matrix tmp;
assert(skin->numBones == hier->numNodes);
if(hier->flags & HAnimHierarchy::LOCALSPACEMATRICES){
for(i = 0; i < hier->numNodes; i++){
invMats[i].flags = 0;
Matrix::mult(m, &invMats[i], &hier->matrices[i]);
m++;
}
}else{
Matrix invAtmMat;
Matrix::invert(&invAtmMat, a->getFrame()->getLTM());
for(i = 0; i < hier->numNodes; i++){
invMats[i].flags = 0;
Matrix::mult(&tmp, &hier->matrices[i], &invAtmMat);
Matrix::mult(m, &invMats[i], &tmp);
m++;
}
}
}else{
for(i = 0; i < skin->numBones; i++){
m->setIdentity();
m++;
}
}
setUniform(u_boneMatrices, skinMatrices);
}
void
skinRenderCB(Atomic *atomic, InstanceDataHeader *header)
{
Material *m;
uint32 flags = atomic->geometry->flags;
setWorldMatrix(atomic->getFrame()->getLTM());
int32 vsBits = lightingCB(atomic);
setupVertexInput(header);
InstanceData *inst = header->inst;
int32 n = header->numMeshes;
uploadSkinMatrices(atomic);
while(n--){
m = inst->material;
setMaterial(flags, m->color, m->surfaceProps);
setTexture(0, m->texture);
rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
if((vsBits & VSLIGHT_MASK) == 0){
if(getAlphaTest())
skinShader->use();
else
skinShader_noAT->use();
}else{
if(getAlphaTest())
skinShader_fullLight->use();
else
skinShader_fullLight_noAT->use();
}
drawInst(header, inst);
inst++;
}
teardownVertexInput(header);
}
static void*
skinOpen(void *o, int32, int32)
{
skinGlobals.pipelines[PLATFORM_GL3] = makeSkinPipeline();
#include "shaders/simple_fs_gl.inc"
#include "shaders/skin_gl.inc"
const char *vs[] = { shaderDecl, header_vert_src, skin_vert_src, nil };
const char *vs_fullLight[] = { shaderDecl, "#define DIRECTIONALS\n#define POINTLIGHTS\n#define SPOTLIGHTS\n", header_vert_src, skin_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil };
const char *fs_noAT[] = { shaderDecl, "#define NO_ALPHATEST\n", header_frag_src, simple_frag_src, nil };
skinShader = Shader::create(vs, fs);
assert(skinShader);
skinShader_noAT = Shader::create(vs, fs_noAT);
assert(skinShader_noAT);
skinShader_fullLight = Shader::create(vs_fullLight, fs);
assert(skinShader_fullLight);
skinShader_fullLight_noAT = Shader::create(vs_fullLight, fs_noAT);
assert(skinShader_fullLight_noAT);
return o;
}
static void*
skinClose(void *o, int32, int32)
{
((ObjPipeline*)skinGlobals.pipelines[PLATFORM_GL3])->destroy();
skinGlobals.pipelines[PLATFORM_GL3] = nil;
skinShader->destroy();
skinShader = nil;
skinShader_noAT->destroy();
skinShader_noAT = nil;
skinShader_fullLight->destroy();
skinShader_fullLight = nil;
skinShader_fullLight_noAT->destroy();
skinShader_fullLight_noAT = nil;
return o;
}
void
initSkin(void)
{
u_boneMatrices = registerUniform("u_boneMatrices", UNIFORM_MAT4, 64);
Driver::registerPlugin(PLATFORM_GL3, 0, ID_SKIN,
skinOpen, skinClose);
}
ObjPipeline*
makeSkinPipeline(void)
{
ObjPipeline *pipe = ObjPipeline::create();
pipe->instanceCB = skinInstanceCB;
pipe->uninstanceCB = skinUninstanceCB;
pipe->renderCB = skinRenderCB;
pipe->pluginID = ID_SKIN;
pipe->pluginData = 1;
return pipe;
}
#else
void initSkin(void) { }
#endif
}
}

1590
vendor/librw/src/gl/glad/glad.c vendored Normal file

File diff suppressed because it is too large Load diff

2808
vendor/librw/src/gl/glad/glad.h vendored Normal file

File diff suppressed because it is too large Load diff

290
vendor/librw/src/gl/glad/khrplatform.h vendored Normal file
View file

@ -0,0 +1,290 @@
#ifndef __khrplatform_h_
#define __khrplatform_h_
/*
** Copyright (c) 2008-2018 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/* Khronos platform-specific types and definitions.
*
* The master copy of khrplatform.h is maintained in the Khronos EGL
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
* The last semantic modification to khrplatform.h was at commit ID:
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
*
* Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file.
* Please submit changes by filing pull requests or issues on
* the EGL Registry repository linked above.
*
*
* See the Implementer's Guidelines for information about where this file
* should be located on your system and for more details of its use:
* http://www.khronos.org/registry/implementers_guide.pdf
*
* This file should be included as
* #include <KHR/khrplatform.h>
* by Khronos client API header files that use its types and defines.
*
* The types in khrplatform.h should only be used to define API-specific types.
*
* Types defined in khrplatform.h:
* khronos_int8_t signed 8 bit
* khronos_uint8_t unsigned 8 bit
* khronos_int16_t signed 16 bit
* khronos_uint16_t unsigned 16 bit
* khronos_int32_t signed 32 bit
* khronos_uint32_t unsigned 32 bit
* khronos_int64_t signed 64 bit
* khronos_uint64_t unsigned 64 bit
* khronos_intptr_t signed same number of bits as a pointer
* khronos_uintptr_t unsigned same number of bits as a pointer
* khronos_ssize_t signed size
* khronos_usize_t unsigned size
* khronos_float_t signed 32 bit floating point
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
* nanoseconds
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
* khronos_boolean_enum_t enumerated boolean type. This should
* only be used as a base type when a client API's boolean type is
* an enum. Client APIs which use an integer or other type for
* booleans cannot use this as the base type for their boolean.
*
* Tokens defined in khrplatform.h:
*
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
*
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
*
* Calling convention macros defined in this file:
* KHRONOS_APICALL
* KHRONOS_APIENTRY
* KHRONOS_APIATTRIBUTES
*
* These may be used in function prototypes as:
*
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
* int arg1,
* int arg2) KHRONOS_APIATTRIBUTES;
*/
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
# define KHRONOS_STATIC 1
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APICALL
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(KHRONOS_STATIC)
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
* header compatible with static linking. */
# define KHRONOS_APICALL
#elif defined(_WIN32)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
#elif defined(__ANDROID__)
# define KHRONOS_APICALL __attribute__((visibility("default")))
#else
# define KHRONOS_APICALL
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIENTRY
*-------------------------------------------------------------------------
* This follows the return type of the function and precedes the function
* name in the function prototype.
*/
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
/* Win32 but not WinCE */
# define KHRONOS_APIENTRY __stdcall
#else
# define KHRONOS_APIENTRY
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIATTRIBUTES
*-------------------------------------------------------------------------
* This follows the closing parenthesis of the function prototype arguments.
*/
#if defined (__ARMCC_2__)
#define KHRONOS_APIATTRIBUTES __softfp
#else
#define KHRONOS_APIATTRIBUTES
#endif
/*-------------------------------------------------------------------------
* basic type definitions
*-----------------------------------------------------------------------*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
/*
* Using <stdint.h>
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__VMS ) || defined(__sgi)
/*
* Using <inttypes.h>
*/
#include <inttypes.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
/*
* Win32
*/
typedef __int32 khronos_int32_t;
typedef unsigned __int32 khronos_uint32_t;
typedef __int64 khronos_int64_t;
typedef unsigned __int64 khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__sun__) || defined(__digital__)
/*
* Sun or Digital
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#if defined(__arch64__) || defined(_LP64)
typedef long int khronos_int64_t;
typedef unsigned long int khronos_uint64_t;
#else
typedef long long int khronos_int64_t;
typedef unsigned long long int khronos_uint64_t;
#endif /* __arch64__ */
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif 0
/*
* Hypothetical platform with no float or int64 support
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#define KHRONOS_SUPPORT_INT64 0
#define KHRONOS_SUPPORT_FLOAT 0
#else
/*
* Generic fallback
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#endif
/*
* Types that are (so far) the same on all platforms
*/
typedef signed char khronos_int8_t;
typedef unsigned char khronos_uint8_t;
typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
/*
* Types that differ between LLP64 and LP64 architectures - in LLP64,
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef _WIN64
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
#if KHRONOS_SUPPORT_FLOAT
/*
* Float type
*/
typedef float khronos_float_t;
#endif
#if KHRONOS_SUPPORT_INT64
/* Time types
*
* These types can be used to represent a time interval in nanoseconds or
* an absolute Unadjusted System Time. Unadjusted System Time is the number
* of nanoseconds since some arbitrary system event (e.g. since the last
* time the system booted). The Unadjusted System Time is an unsigned
* 64 bit value that wraps back to 0 every 584 years. Time intervals
* may be either signed or unsigned.
*/
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
typedef khronos_int64_t khronos_stime_nanoseconds_t;
#endif
/*
* Dummy value used to pad enum types to 32 bits.
*/
#ifndef KHRONOS_MAX_ENUM
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
#endif
/*
* Enumerated boolean type
*
* Values other than zero should be considered to be true. Therefore
* comparisons should not be made against KHRONOS_TRUE.
*/
typedef enum {
KHRONOS_FALSE = 0,
KHRONOS_TRUE = 1,
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */

288
vendor/librw/src/gl/rwgl3.h vendored Normal file
View file

@ -0,0 +1,288 @@
#ifdef RW_GL3
#include "glad/glad.h"
#ifdef LIBRW_SDL2
#include <SDL.h>
#else
#include <GLFW/glfw3.h>
#endif
#endif
namespace rw {
#ifdef RW_GL3
struct EngineOpenParams
{
#ifdef LIBRW_SDL2
SDL_Window **window;
bool32 fullscreen;
#else
GLFWwindow **window;
#endif
int width, height;
const char *windowtitle;
};
#endif
namespace gl3 {
void registerPlatformPlugins(void);
extern Device renderdevice;
// 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_WEIGHTS,
ATTRIB_INDICES,
ATTRIB_TEXCOORDS0,
ATTRIB_TEXCOORDS1,
ATTRIB_TEXCOORDS2,
ATTRIB_TEXCOORDS3,
ATTRIB_TEXCOORDS4,
ATTRIB_TEXCOORDS5,
ATTRIB_TEXCOORDS6,
ATTRIB_TEXCOORDS7,
};
// default uniform indices
extern int32 u_matColor;
extern int32 u_surfProps;
struct InstanceData
{
uint32 numIndex;
uint32 minVert; // not used for rendering
int32 numVertices; //
Material *material;
bool32 vertexAlpha;
uint32 program;
uint32 offset;
};
struct InstanceDataHeader : rw::InstanceDataHeader
{
uint32 serialNumber;
uint32 numMeshes;
uint16 *indexBuffer;
uint32 primType;
uint8 *vertexBuffer;
int32 numAttribs;
AttribDesc *attribDesc;
uint32 totalNumIndex;
uint32 totalNumVertex;
uint32 ibo;
uint32 vbo; // or 2?
#ifdef RW_GL_USE_VAOS
uint32 vao;
#endif
InstanceData *inst;
};
#ifdef RW_GL3
struct Shader;
extern Shader *defaultShader, *defaultShader_noAT;
extern Shader *defaultShader_fullLight, *defaultShader_fullLight_noAT;
struct Im3DVertex
{
V3d position;
uint8 r, g, b, a;
float32 u, v;
void setX(float32 x) { this->position.x = x; }
void setY(float32 y) { this->position.y = y; }
void setZ(float32 z) { this->position.z = z; }
void setColor(uint8 r, uint8 g, uint8 b, uint8 a) {
this->r = r; this->g = g; this->b = b; this->a = a; }
void setU(float32 u) { this->u = u; }
void setV(float32 v) { this->v = v; }
float getX(void) { return this->position.x; }
float getY(void) { return this->position.y; }
float getZ(void) { return this->position.z; }
RGBA getColor(void) { return makeRGBA(this->r, this->g, this->b, this->a); }
float getU(void) { return this->u; }
float getV(void) { return this->v; }
};
struct Im2DVertex
{
float32 x, y, z, w;
uint8 r, g, b, a;
float32 u, v;
void setScreenX(float32 x) { this->x = x; }
void setScreenY(float32 y) { this->y = y; }
void setScreenZ(float32 z) { this->z = z; }
// This is a bit unefficient but we have to counteract GL's divide, so multiply
void setCameraZ(float32 z) { this->w = z; }
void setRecipCameraZ(float32 recipz) { this->w = 1.0f/recipz; }
void setColor(uint8 r, uint8 g, uint8 b, uint8 a) {
this->r = r; this->g = g; this->b = b; this->a = a; }
void setU(float32 u, float recipz) { this->u = u; }
void setV(float32 v, float recipz) { this->v = v; }
float getScreenX(void) { return this->x; }
float getScreenY(void) { return this->y; }
float getScreenZ(void) { return this->z; }
float getCameraZ(void) { return this->w; }
float getRecipCameraZ(void) { return 1.0f/this->w; }
RGBA getColor(void) { return makeRGBA(this->r, this->g, this->b, this->a); }
float getU(void) { return this->u; }
float getV(void) { return this->v; }
};
void setAttribPointers(AttribDesc *attribDescs, int32 numAttribs);
void disableAttribPointers(AttribDesc *attribDescs, int32 numAttribs);
void setupVertexInput(InstanceDataHeader *header);
void teardownVertexInput(InstanceDataHeader *header);
// Render state
// Vertex shader bits
enum
{
// These should be low so they could be used as indices
VSLIGHT_DIRECT = 1,
VSLIGHT_POINT = 2,
VSLIGHT_SPOT = 4,
VSLIGHT_MASK = 7, // all the above
// less critical
VSLIGHT_AMBIENT = 8,
};
extern const char *shaderDecl; // #version stuff
extern const char *header_vert_src;
extern const char *header_frag_src;
extern Shader *im2dOverrideShader;
// per Scene
void setProjectionMatrix(float32*);
void setViewMatrix(float32*);
// per Object
void setWorldMatrix(Matrix*);
int32 setLights(WorldLights *lightData);
// per Mesh
void setTexture(int32 n, Texture *tex);
void setMaterial(const RGBA &color, const SurfaceProperties &surfaceprops, float extraSurfProp = 0.0f);
inline void setMaterial(uint32 flags, const RGBA &color, const SurfaceProperties &surfaceprops, float extraSurfProp = 0.0f)
{
static RGBA white = { 255, 255, 255, 255 };
if(flags & Geometry::MODULATE)
setMaterial(color, surfaceprops, extraSurfProp);
else
setMaterial(white, surfaceprops, extraSurfProp);
}
void setAlphaBlend(bool32 enable);
bool32 getAlphaBlend(void);
bool32 getAlphaTest(void);
void bindFramebuffer(uint32 fbo);
uint32 bindTexture(uint32 texid);
void flushCache(void);
#endif
class ObjPipeline : public rw::ObjPipeline
{
public:
void init(void);
static ObjPipeline *create(void);
void (*instanceCB)(Geometry *geo, InstanceDataHeader *header, bool32 reinstance);
void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header);
void (*renderCB)(Atomic *atomic, InstanceDataHeader *header);
};
void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance);
void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header);
void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header);
int32 lightingCB(Atomic *atomic);
void drawInst_simple(InstanceDataHeader *header, InstanceData *inst);
// Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer
void drawInst_GSemu(InstanceDataHeader *header, InstanceData *inst);
// This one switches between the above two depending on render state;
void drawInst(InstanceDataHeader *header, InstanceData *inst);
void *destroyNativeData(void *object, int32, int32);
ObjPipeline *makeDefaultPipeline(void);
// Native Texture and Raster
struct Gl3Raster
{
// arguments to glTexImage2D
int32 internalFormat;
int32 type;
int32 format;
int32 bpp; // bytes per pixel
// texture object
uint32 texid;
bool isCompressed;
bool hasAlpha;
bool autogenMipmap;
int8 numLevels;
// cached filtermode and addressing
uint8 filterMode;
uint8 addressU;
uint8 addressV;
int32 maxAnisotropy;
uint32 fbo; // used for camera texture only!
Raster *fboMate; // color or zbuffer raster mate of this one
RasterLevels *backingStore; // if we can't read back GPU memory but have to
};
struct Gl3Caps
{
int gles;
int glversion;
bool dxtSupported;
bool astcSupported; // not used yet
float maxAnisotropy;
};
extern Gl3Caps gl3Caps;
// GLES can't read back textures very nicely.
// In most cases that's not an issue, but when it is,
// this has to be set before the texture is filled:
extern bool32 needToReadBackTextures;
void allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha);
Texture *readNativeTexture(Stream *stream);
void writeNativeTexture(Texture *tex, Stream *stream);
uint32 getSizeNativeTexture(Texture *tex);
extern int32 nativeRasterOffset;
void registerNativeRaster(void);
#define GETGL3RASTEREXT(raster) PLUGINOFFSET(Gl3Raster, raster, rw::gl3::nativeRasterOffset)
}
}

76
vendor/librw/src/gl/rwgl3impl.h vendored Normal file
View file

@ -0,0 +1,76 @@
namespace rw {
namespace gl3 {
#ifdef RW_OPENGL
extern uint32 im2DVbo, im2DIbo;
void openIm2D(void);
void closeIm2D(void);
void im2DRenderLine(void *vertices, int32 numVertices,
int32 vert1, int32 vert2);
void im2DRenderTriangle(void *vertices, int32 numVertices,
int32 vert1, int32 vert2, int32 vert3);
void im2DRenderPrimitive(PrimitiveType primType,
void *vertices, int32 numVertices);
void im2DRenderIndexedPrimitive(PrimitiveType primType,
void *vertices, int32 numVertices, void *indices, int32 numIndices);
void openIm3D(void);
void closeIm3D(void);
void im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags);
void im3DRenderPrimitive(PrimitiveType primType);
void im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices);
void im3DEnd(void);
struct DisplayMode
{
#ifdef LIBRW_SDL2
SDL_DisplayMode mode;
#else
GLFWvidmode mode;
#endif
int32 depth;
uint32 flags;
};
struct GlGlobals
{
#ifdef LIBRW_SDL2
SDL_Window **pWindow;
SDL_Window *window;
SDL_GLContext glcontext;
#else
GLFWwindow **pWindow;
GLFWwindow *window;
GLFWmonitor *monitor;
int numMonitors;
int currentMonitor;
#endif
DisplayMode *modes;
int numModes;
int currentMode;
int presentWidth, presentHeight;
int presentOffX, presentOffY;
// for opening the window
int winWidth, winHeight;
const char *winTitle;
uint32 numSamples;
};
extern GlGlobals glGlobals;
#endif
Raster *rasterCreate(Raster *raster);
uint8 *rasterLock(Raster*, int32 level, int32 lockMode);
void rasterUnlock(Raster*, int32);
int32 rasterNumLevels(Raster*);
bool32 imageFindRasterFormat(Image *img, int32 type,
int32 *width, int32 *height, int32 *depth, int32 *format);
bool32 rasterFromImage(Raster *raster, Image *image);
Image *rasterToImage(Raster *raster);
}
}

16
vendor/librw/src/gl/rwgl3plg.h vendored Normal file
View file

@ -0,0 +1,16 @@
namespace rw {
namespace gl3 {
void initMatFX(void);
ObjPipeline *makeMatFXPipeline(void);
void matfxRenderCB(Atomic *atomic, InstanceDataHeader *header);
void initSkin(void);
ObjPipeline *makeSkinPipeline(void);
void skinInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance);
void skinRenderCB(Atomic *atomic, InstanceDataHeader *header);
void uploadSkinMatrices(Atomic *atomic);
}
}

69
vendor/librw/src/gl/rwgl3shader.h vendored Normal file
View file

@ -0,0 +1,69 @@
#ifdef RW_OPENGL
namespace rw {
namespace gl3 {
// TODO: make this dynamic
enum {
MAX_UNIFORMS = 40,
MAX_BLOCKS = 20
};
enum UniformType
{
UNIFORM_NA, // managed by the user
UNIFORM_VEC4,
UNIFORM_IVEC4,
UNIFORM_MAT4
};
struct Uniform
{
char *name;
UniformType type;
//bool dirty;
uint32 serialNum;
int32 num;
void *data;
};
struct UniformRegistry
{
int32 numUniforms;
Uniform uniforms[MAX_UNIFORMS];
int32 numBlocks;
char *blockNames[MAX_BLOCKS];
};
int32 registerUniform(const char *name, UniformType type = UNIFORM_NA, int32 num = 1);
int32 findUniform(const char *name);
int32 registerBlock(const char *name);
int32 findBlock(const char *name);
void setUniform(int32 id, void *data);
void flushUniforms(void);
extern UniformRegistry uniformRegistry;
struct Shader
{
GLuint program;
// same number of elements as UniformRegistry::numUniforms
GLint *uniformLocations;
uint32 *serialNums;
int32 numUniforms; // just to be sure!
static Shader *create(const char **vsrc, const char **fsrc);
// static Shader *fromFiles(const char *vs, const char *fs);
// static Shader *fromStrings(const char *vsrc, const char *fsrc);
void use(void);
void destroy(void);
};
extern Shader *currentShader;
}
}
#endif

88
vendor/librw/src/gl/rwwdgl.h vendored Normal file
View file

@ -0,0 +1,88 @@
namespace rw {
namespace wdgl {
// NOTE: This is not really RW OpenGL! It's specific to WarDrum's GTA ports
void registerPlatformPlugins(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:
void init(void);
static ObjPipeline *create(void);
uint32 numCustomAttribs;
uint32 (*instanceCB)(Geometry *g, int32 i, uint32 offset);
void (*uninstanceCB)(Geometry *g);
};
ObjPipeline *makeDefaultPipeline(void);
// Skin plugin
void initSkin(void);
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);
// MatFX plugin
void initMatFX(void);
ObjPipeline *makeMatFXPipeline(void);
// Raster
struct Texture : rw::Texture
{
void upload(void);
void bind(int n);
};
extern int32 nativeRasterOffset;
void registerNativeRaster(void);
}
}

45
vendor/librw/src/gl/shaders/Makefile vendored Normal file
View file

@ -0,0 +1,45 @@
all: header_vs.inc header_fs.inc im2d_gl.inc im3d_gl.inc default_vs_gl.inc simple_fs_gl.inc matfx_gl.inc skin_gl.inc
header_vs.inc: header.vert
(echo 'const char *header_vert_src =';\
sed 's/..*/"&\\n"/' header.vert;\
echo ';') >header_vs.inc
header_fs.inc: header.frag
(echo 'const char *header_frag_src =';\
sed 's/..*/"&\\n"/' header.frag;\
echo ';') >header_fs.inc
im2d_gl.inc: im2d.vert
(echo 'const char *im2d_vert_src =';\
sed 's/..*/"&\\n"/' im2d.vert;\
echo ';') >im2d_gl.inc
im3d_gl.inc: im3d.vert
(echo 'const char *im3d_vert_src =';\
sed 's/..*/"&\\n"/' im3d.vert;\
echo ';') >im3d_gl.inc
default_vs_gl.inc: default.vert
(echo 'const char *default_vert_src =';\
sed 's/..*/"&\\n"/' default.vert;\
echo ';') >default_vs_gl.inc
simple_fs_gl.inc: simple.frag
(echo 'const char *simple_frag_src =';\
sed 's/..*/"&\\n"/' simple.frag;\
echo ';') >simple_fs_gl.inc
matfx_gl.inc: matfx_env.frag matfx_env.vert
(echo 'const char *matfx_env_vert_src =';\
sed 's/..*/"&\\n"/' matfx_env.vert;\
echo ';';\
echo 'const char *matfx_env_frag_src =';\
sed 's/..*/"&\\n"/' matfx_env.frag;\
echo ';') >matfx_gl.inc
skin_gl.inc: skin.vert
(echo 'const char *skin_vert_src =';\
sed 's/..*/"&\\n"/' skin.vert;\
echo ';') >skin_gl.inc

View file

@ -0,0 +1,23 @@
VSIN(ATTRIB_POS) vec3 in_pos;
VSOUT vec4 v_color;
VSOUT vec2 v_tex0;
VSOUT float v_fog;
void
main(void)
{
vec4 Vertex = u_world * vec4(in_pos, 1.0);
gl_Position = u_proj * u_view * Vertex;
vec3 Normal = mat3(u_world) * in_normal;
v_tex0 = in_tex0;
v_color = in_color;
v_color.rgb += u_ambLight.rgb*surfAmbient;
v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;
v_color = clamp(v_color, 0.0, 1.0);
v_color *= u_matColor;
v_fog = DoFog(gl_Position.w);
}

View file

@ -0,0 +1,25 @@
const char *default_vert_src =
"VSIN(ATTRIB_POS) vec3 in_pos;\n"
"VSOUT vec4 v_color;\n"
"VSOUT vec2 v_tex0;\n"
"VSOUT float v_fog;\n"
"void\n"
"main(void)\n"
"{\n"
" vec4 Vertex = u_world * vec4(in_pos, 1.0);\n"
" gl_Position = u_proj * u_view * Vertex;\n"
" vec3 Normal = mat3(u_world) * in_normal;\n"
" v_tex0 = in_tex0;\n"
" v_color = in_color;\n"
" v_color.rgb += u_ambLight.rgb*surfAmbient;\n"
" v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;\n"
" v_color = clamp(v_color, 0.0, 1.0);\n"
" v_color *= u_matColor;\n"
" v_fog = DoFog(gl_Position.w);\n"
"}\n"
;

30
vendor/librw/src/gl/shaders/header.frag vendored Normal file
View file

@ -0,0 +1,30 @@
#ifdef USE_UBOS
layout(std140) uniform State
{
vec2 u_alphaRef;
vec4 u_fogData;
vec4 u_fogColor;
};
#else
uniform vec4 u_alphaRef;
uniform vec4 u_fogData;
uniform vec4 u_fogColor;
#endif
#define u_fogStart (u_fogData.x)
#define u_fogEnd (u_fogData.y)
#define u_fogRange (u_fogData.z)
#define u_fogDisable (u_fogData.w)
#ifndef GL2
out vec4 fragColor;
#endif
void DoAlphaTest(float a)
{
#ifndef NO_ALPHATEST
if(a < u_alphaRef.x || a >= u_alphaRef.y)
discard;
#endif
}

128
vendor/librw/src/gl/shaders/header.vert vendored Normal file
View file

@ -0,0 +1,128 @@
//#define DIRECTIONALS
//#define POINTLIGHTS
//#define SPOTLIGHTS
#define ATTRIB_POS 0
#define ATTRIB_NORMAL 1
#define ATTRIB_COLOR 2
#define ATTRIB_WEIGHTS 3
#define ATTRIB_INDICES 4
#define ATTRIB_TEXCOORDS0 5
#define ATTRIB_TEXCOORDS1 6
VSIN(ATTRIB_NORMAL) vec3 in_normal;
VSIN(ATTRIB_COLOR) vec4 in_color;
VSIN(ATTRIB_WEIGHTS) vec4 in_weights;
VSIN(ATTRIB_INDICES) vec4 in_indices;
VSIN(ATTRIB_TEXCOORDS0) vec2 in_tex0;
VSIN(ATTRIB_TEXCOORDS1) vec2 in_tex1;
#ifdef USE_UBOS
layout(std140) uniform State
{
vec2 u_alphaRef;
vec4 u_fogData;
vec4 u_fogColor;
};
#else
uniform vec4 u_alphaRef;
uniform vec4 u_fogData;
uniform vec4 u_fogColor;
#endif
#define u_fogStart (u_fogData.x)
#define u_fogEnd (u_fogData.y)
#define u_fogRange (u_fogData.z)
#define u_fogDisable (u_fogData.w)
#ifdef USE_UBOS
layout(std140) uniform Scene
{
mat4 u_proj;
mat4 u_view;
};
#else
uniform mat4 u_proj;
uniform mat4 u_view;
#endif
#define MAX_LIGHTS 8
#ifdef USE_UBOS
layout(std140) uniform Object
{
mat4 u_world;
vec4 u_ambLight;
vec4 u_lightParams[MAX_LIGHTS]; // type, radius, minusCosAngle, hardSpot
vec4 u_lightPosition[MAX_LIGHTS];
vec4 u_lightDirection[MAX_LIGHTS];
vec4 u_lightColor[MAX_LIGHTS];
};
#else
uniform mat4 u_world;
uniform vec4 u_ambLight;
uniform vec4 u_lightParams[MAX_LIGHTS]; // type, radius, minusCosAngle, hardSpot
uniform vec4 u_lightPosition[MAX_LIGHTS];
uniform vec4 u_lightDirection[MAX_LIGHTS];
uniform vec4 u_lightColor[MAX_LIGHTS];
#endif
uniform vec4 u_matColor;
uniform vec4 u_surfProps; // amb, spec, diff, extra
#define surfAmbient (u_surfProps.x)
#define surfSpecular (u_surfProps.y)
#define surfDiffuse (u_surfProps.z)
vec3 DoDynamicLight(vec3 V, vec3 N)
{
vec3 color = vec3(0.0, 0.0, 0.0);
for(int i = 0; i < MAX_LIGHTS; i++){
if(u_lightParams[i].x == 0.0)
break;
#ifdef DIRECTIONALS
if(u_lightParams[i].x == 1.0){
// direct
float l = max(0.0, dot(N, -u_lightDirection[i].xyz));
color += l*u_lightColor[i].rgb;
}else
#endif
#ifdef POINTLIGHTS
if(u_lightParams[i].x == 2.0){
// point
vec3 dir = V - u_lightPosition[i].xyz;
float dist = length(dir);
float atten = max(0.0, (1.0 - dist/u_lightParams[i].y));
float l = max(0.0, dot(N, -normalize(dir)));
color += l*u_lightColor[i].rgb*atten;
}else
#endif
#ifdef SPOTLIGHTS
if(u_lightParams[i].x == 3.0){
// spot
vec3 dir = V - u_lightPosition[i].xyz;
float dist = length(dir);
float atten = max(0.0, (1.0 - dist/u_lightParams[i].y));
dir /= dist;
float l = max(0.0, dot(N, -dir));
float pcos = dot(dir, u_lightDirection[i].xyz); // cos to point
float ccos = -u_lightParams[i].z;
float falloff = (pcos-ccos)/(1.0-ccos);
if(falloff < 0.0) // outside of cone
l = 0.0;
l *= max(falloff, u_lightParams[i].w);
return l*u_lightColor[i].rgb*atten;
}else
#endif
;
}
return color;
}
float DoFog(float w)
{
return clamp((w - u_fogEnd)*u_fogRange, u_fogDisable, 1.0);
}

View file

@ -0,0 +1,32 @@
const char *header_frag_src =
"#ifdef USE_UBOS\n"
"layout(std140) uniform State\n"
"{\n"
" vec2 u_alphaRef;\n"
" vec4 u_fogData;\n"
" vec4 u_fogColor;\n"
"};\n"
"#else\n"
"uniform vec4 u_alphaRef;\n"
"uniform vec4 u_fogData;\n"
"uniform vec4 u_fogColor;\n"
"#endif\n"
"#define u_fogStart (u_fogData.x)\n"
"#define u_fogEnd (u_fogData.y)\n"
"#define u_fogRange (u_fogData.z)\n"
"#define u_fogDisable (u_fogData.w)\n"
"#ifndef GL2\n"
"out vec4 fragColor;\n"
"#endif\n"
"void DoAlphaTest(float a)\n"
"{\n"
"#ifndef NO_ALPHATEST\n"
" if(a < u_alphaRef.x || a >= u_alphaRef.y)\n"
" discard;\n"
"#endif\n"
"}\n"
;

View file

@ -0,0 +1,130 @@
const char *header_vert_src =
"//#define DIRECTIONALS\n"
"//#define POINTLIGHTS\n"
"//#define SPOTLIGHTS\n"
"#define ATTRIB_POS 0\n"
"#define ATTRIB_NORMAL 1\n"
"#define ATTRIB_COLOR 2\n"
"#define ATTRIB_WEIGHTS 3\n"
"#define ATTRIB_INDICES 4\n"
"#define ATTRIB_TEXCOORDS0 5\n"
"#define ATTRIB_TEXCOORDS1 6\n"
"VSIN(ATTRIB_NORMAL) vec3 in_normal;\n"
"VSIN(ATTRIB_COLOR) vec4 in_color;\n"
"VSIN(ATTRIB_WEIGHTS) vec4 in_weights;\n"
"VSIN(ATTRIB_INDICES) vec4 in_indices;\n"
"VSIN(ATTRIB_TEXCOORDS0) vec2 in_tex0;\n"
"VSIN(ATTRIB_TEXCOORDS1) vec2 in_tex1;\n"
"#ifdef USE_UBOS\n"
"layout(std140) uniform State\n"
"{\n"
" vec2 u_alphaRef;\n"
" vec4 u_fogData;\n"
" vec4 u_fogColor;\n"
"};\n"
"#else\n"
"uniform vec4 u_alphaRef;\n"
"uniform vec4 u_fogData;\n"
"uniform vec4 u_fogColor;\n"
"#endif\n"
"#define u_fogStart (u_fogData.x)\n"
"#define u_fogEnd (u_fogData.y)\n"
"#define u_fogRange (u_fogData.z)\n"
"#define u_fogDisable (u_fogData.w)\n"
"#ifdef USE_UBOS\n"
"layout(std140) uniform Scene\n"
"{\n"
" mat4 u_proj;\n"
" mat4 u_view;\n"
"};\n"
"#else\n"
"uniform mat4 u_proj;\n"
"uniform mat4 u_view;\n"
"#endif\n"
"#define MAX_LIGHTS 8\n"
"#ifdef USE_UBOS\n"
"layout(std140) uniform Object\n"
"{\n"
" mat4 u_world;\n"
" vec4 u_ambLight;\n"
" vec4 u_lightParams[MAX_LIGHTS]; // type, radius, minusCosAngle, hardSpot\n"
" vec4 u_lightPosition[MAX_LIGHTS];\n"
" vec4 u_lightDirection[MAX_LIGHTS];\n"
" vec4 u_lightColor[MAX_LIGHTS];\n"
"};\n"
"#else\n"
"uniform mat4 u_world;\n"
"uniform vec4 u_ambLight;\n"
"uniform vec4 u_lightParams[MAX_LIGHTS]; // type, radius, minusCosAngle, hardSpot\n"
"uniform vec4 u_lightPosition[MAX_LIGHTS];\n"
"uniform vec4 u_lightDirection[MAX_LIGHTS];\n"
"uniform vec4 u_lightColor[MAX_LIGHTS];\n"
"#endif\n"
"uniform vec4 u_matColor;\n"
"uniform vec4 u_surfProps; // amb, spec, diff, extra\n"
"#define surfAmbient (u_surfProps.x)\n"
"#define surfSpecular (u_surfProps.y)\n"
"#define surfDiffuse (u_surfProps.z)\n"
"vec3 DoDynamicLight(vec3 V, vec3 N)\n"
"{\n"
" vec3 color = vec3(0.0, 0.0, 0.0);\n"
" for(int i = 0; i < MAX_LIGHTS; i++){\n"
" if(u_lightParams[i].x == 0.0)\n"
" break;\n"
"#ifdef DIRECTIONALS\n"
" if(u_lightParams[i].x == 1.0){\n"
" // direct\n"
" float l = max(0.0, dot(N, -u_lightDirection[i].xyz));\n"
" color += l*u_lightColor[i].rgb;\n"
" }else\n"
"#endif\n"
"#ifdef POINTLIGHTS\n"
" if(u_lightParams[i].x == 2.0){\n"
" // point\n"
" vec3 dir = V - u_lightPosition[i].xyz;\n"
" float dist = length(dir);\n"
" float atten = max(0.0, (1.0 - dist/u_lightParams[i].y));\n"
" float l = max(0.0, dot(N, -normalize(dir)));\n"
" color += l*u_lightColor[i].rgb*atten;\n"
" }else\n"
"#endif\n"
"#ifdef SPOTLIGHTS\n"
" if(u_lightParams[i].x == 3.0){\n"
" // spot\n"
" vec3 dir = V - u_lightPosition[i].xyz;\n"
" float dist = length(dir);\n"
" float atten = max(0.0, (1.0 - dist/u_lightParams[i].y));\n"
" dir /= dist;\n"
" float l = max(0.0, dot(N, -dir));\n"
" float pcos = dot(dir, u_lightDirection[i].xyz); // cos to point\n"
" float ccos = -u_lightParams[i].z;\n"
" float falloff = (pcos-ccos)/(1.0-ccos);\n"
" if(falloff < 0.0) // outside of cone\n"
" l = 0.0;\n"
" l *= max(falloff, u_lightParams[i].w);\n"
" return l*u_lightColor[i].rgb*atten;\n"
" }else\n"
"#endif\n"
" ;\n"
" }\n"
" return color;\n"
"}\n"
"float DoFog(float w)\n"
"{\n"
" return clamp((w - u_fogEnd)*u_fogRange, u_fogDisable, 1.0);\n"
"}\n"
;

18
vendor/librw/src/gl/shaders/im2d.vert vendored Normal file
View file

@ -0,0 +1,18 @@
uniform vec4 u_xform;
VSIN(ATTRIB_POS) vec4 in_pos;
VSOUT vec4 v_color;
VSOUT vec2 v_tex0;
VSOUT float v_fog;
void
main(void)
{
gl_Position = in_pos;
gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;
v_fog = DoFog(gl_Position.w);
gl_Position.xyz *= gl_Position.w;
v_color = in_color;
v_tex0 = in_tex0;
}

20
vendor/librw/src/gl/shaders/im2d_gl.inc vendored Normal file
View file

@ -0,0 +1,20 @@
const char *im2d_vert_src =
"uniform vec4 u_xform;\n"
"VSIN(ATTRIB_POS) vec4 in_pos;\n"
"VSOUT vec4 v_color;\n"
"VSOUT vec2 v_tex0;\n"
"VSOUT float v_fog;\n"
"void\n"
"main(void)\n"
"{\n"
" gl_Position = in_pos;\n"
" gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;\n"
" v_fog = DoFog(gl_Position.w);\n"
" gl_Position.xyz *= gl_Position.w;\n"
" v_color = in_color;\n"
" v_tex0 = in_tex0;\n"
"}\n"
;

16
vendor/librw/src/gl/shaders/im3d.vert vendored Normal file
View file

@ -0,0 +1,16 @@
VSIN(ATTRIB_POS) vec3 in_pos;
VSOUT vec4 v_color;
VSOUT vec2 v_tex0;
VSOUT float v_fog;
void
main(void)
{
vec4 Vertex = u_world * vec4(in_pos, 1.0);
vec4 CamVertex = u_view * Vertex;
gl_Position = u_proj * CamVertex;
v_color = in_color;
v_tex0 = in_tex0;
v_fog = DoFog(gl_Position.w);
}

18
vendor/librw/src/gl/shaders/im3d_gl.inc vendored Normal file
View file

@ -0,0 +1,18 @@
const char *im3d_vert_src =
"VSIN(ATTRIB_POS) vec3 in_pos;\n"
"VSOUT vec4 v_color;\n"
"VSOUT vec2 v_tex0;\n"
"VSOUT float v_fog;\n"
"void\n"
"main(void)\n"
"{\n"
" vec4 Vertex = u_world * vec4(in_pos, 1.0);\n"
" vec4 CamVertex = u_view * Vertex;\n"
" gl_Position = u_proj * CamVertex;\n"
" v_color = in_color;\n"
" v_tex0 = in_tex0;\n"
" v_fog = DoFog(gl_Position.w);\n"
"}\n"
;

View file

@ -0,0 +1,34 @@
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform vec4 u_fxparams;
#define shininess (u_fxparams.x)
#define disableFBA (u_fxparams.y)
FSIN vec4 v_color;
FSIN vec4 v_envColor;
FSIN vec2 v_tex0;
FSIN vec2 v_tex1;
FSIN float v_fog;
void
main(void)
{
vec4 pass1 = v_color;
pass1 *= texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));
vec4 pass2 = v_envColor*shininess*texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y));
pass1.rgb = mix(u_fogColor.rgb, pass1.rgb, v_fog);
pass2.rgb = mix(vec3(0.0, 0.0, 0.0), pass2.rgb, v_fog);
float fba = max(pass1.a, disableFBA);
vec4 color;
color.rgb = pass1.rgb*pass1.a + pass2.rgb*fba;
color.a = pass1.a;
DoAlphaTest(color.a);
FRAGCOLOR(color);
}

View file

@ -0,0 +1,31 @@
uniform mat4 u_texMatrix;
uniform vec4 u_colorClamp;
uniform vec4 u_envColor;
VSIN(ATTRIB_POS) vec3 in_pos;
VSOUT vec4 v_color;
VSOUT vec4 v_envColor;
VSOUT vec2 v_tex0;
VSOUT vec2 v_tex1;
VSOUT float v_fog;
void
main(void)
{
vec4 Vertex = u_world * vec4(in_pos, 1.0);
gl_Position = u_proj * u_view * Vertex;
vec3 Normal = mat3(u_world) * in_normal;
v_tex0 = in_tex0;
v_tex1 = (u_texMatrix * vec4(Normal, 1.0)).xy;
v_color = in_color;
v_color.rgb += u_ambLight.rgb*surfAmbient;
v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;
v_color = clamp(v_color, 0.0, 1.0);
v_envColor = max(v_color, u_colorClamp) * u_envColor;
v_color *= u_matColor;
v_fog = DoFog(gl_Position.w);
}

View file

@ -0,0 +1,69 @@
const char *matfx_env_vert_src =
"uniform mat4 u_texMatrix;\n"
"uniform vec4 u_colorClamp;\n"
"uniform vec4 u_envColor;\n"
"VSIN(ATTRIB_POS) vec3 in_pos;\n"
"VSOUT vec4 v_color;\n"
"VSOUT vec4 v_envColor;\n"
"VSOUT vec2 v_tex0;\n"
"VSOUT vec2 v_tex1;\n"
"VSOUT float v_fog;\n"
"void\n"
"main(void)\n"
"{\n"
" vec4 Vertex = u_world * vec4(in_pos, 1.0);\n"
" gl_Position = u_proj * u_view * Vertex;\n"
" vec3 Normal = mat3(u_world) * in_normal;\n"
" v_tex0 = in_tex0;\n"
" v_tex1 = (u_texMatrix * vec4(Normal, 1.0)).xy;\n"
" v_color = in_color;\n"
" v_color.rgb += u_ambLight.rgb*surfAmbient;\n"
" v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;\n"
" v_color = clamp(v_color, 0.0, 1.0);\n"
" v_envColor = max(v_color, u_colorClamp) * u_envColor;\n"
" v_color *= u_matColor;\n"
" v_fog = DoFog(gl_Position.w);\n"
"}\n"
;
const char *matfx_env_frag_src =
"uniform sampler2D tex0;\n"
"uniform sampler2D tex1;\n"
"uniform vec4 u_fxparams;\n"
"#define shininess (u_fxparams.x)\n"
"#define disableFBA (u_fxparams.y)\n"
"FSIN vec4 v_color;\n"
"FSIN vec4 v_envColor;\n"
"FSIN vec2 v_tex0;\n"
"FSIN vec2 v_tex1;\n"
"FSIN float v_fog;\n"
"void\n"
"main(void)\n"
"{\n"
" vec4 pass1 = v_color;\n"
" pass1 *= texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n"
" vec4 pass2 = v_envColor*shininess*texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y));\n"
" pass1.rgb = mix(u_fogColor.rgb, pass1.rgb, v_fog);\n"
" pass2.rgb = mix(vec3(0.0, 0.0, 0.0), pass2.rgb, v_fog);\n"
" float fba = max(pass1.a, disableFBA);\n"
" vec4 color;\n"
" color.rgb = pass1.rgb*pass1.a + pass2.rgb*fba;\n"
" color.a = pass1.a;\n"
" DoAlphaTest(color.a);\n"
" FRAGCOLOR(color);\n"
"}\n"
;

15
vendor/librw/src/gl/shaders/simple.frag vendored Normal file
View file

@ -0,0 +1,15 @@
uniform sampler2D tex0;
FSIN vec4 v_color;
FSIN vec2 v_tex0;
FSIN float v_fog;
void
main(void)
{
vec4 color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));
color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);
DoAlphaTest(color.a);
FRAGCOLOR(color);
}

View file

@ -0,0 +1,17 @@
const char *simple_frag_src =
"uniform sampler2D tex0;\n"
"FSIN vec4 v_color;\n"
"FSIN vec2 v_tex0;\n"
"FSIN float v_fog;\n"
"void\n"
"main(void)\n"
"{\n"
" vec4 color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n"
" color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n"
" DoAlphaTest(color.a);\n"
" FRAGCOLOR(color);\n"
"}\n"
;

32
vendor/librw/src/gl/shaders/skin.vert vendored Normal file
View file

@ -0,0 +1,32 @@
uniform mat4 u_boneMatrices[64];
VSIN(ATTRIB_POS) vec3 in_pos;
VSOUT vec4 v_color;
VSOUT vec2 v_tex0;
VSOUT float v_fog;
void
main(void)
{
vec3 SkinVertex = vec3(0.0, 0.0, 0.0);
vec3 SkinNormal = vec3(0.0, 0.0, 0.0);
for(int i = 0; i < 4; i++){
SkinVertex += (u_boneMatrices[int(in_indices[i])] * vec4(in_pos, 1.0)).xyz * in_weights[i];
SkinNormal += (mat3(u_boneMatrices[int(in_indices[i])]) * in_normal) * in_weights[i];
}
vec4 Vertex = u_world * vec4(SkinVertex, 1.0);
gl_Position = u_proj * u_view * Vertex;
vec3 Normal = mat3(u_world) * SkinNormal;
v_tex0 = in_tex0;
v_color = in_color;
v_color.rgb += u_ambLight.rgb*surfAmbient;
v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;
v_color = clamp(v_color, 0.0, 1.0);
v_color *= u_matColor;
v_fog = DoFog(gl_Position.z);
}

34
vendor/librw/src/gl/shaders/skin_gl.inc vendored Normal file
View file

@ -0,0 +1,34 @@
const char *skin_vert_src =
"uniform mat4 u_boneMatrices[64];\n"
"VSIN(ATTRIB_POS) vec3 in_pos;\n"
"VSOUT vec4 v_color;\n"
"VSOUT vec2 v_tex0;\n"
"VSOUT float v_fog;\n"
"void\n"
"main(void)\n"
"{\n"
" vec3 SkinVertex = vec3(0.0, 0.0, 0.0);\n"
" vec3 SkinNormal = vec3(0.0, 0.0, 0.0);\n"
" for(int i = 0; i < 4; i++){\n"
" SkinVertex += (u_boneMatrices[int(in_indices[i])] * vec4(in_pos, 1.0)).xyz * in_weights[i];\n"
" SkinNormal += (mat3(u_boneMatrices[int(in_indices[i])]) * in_normal) * in_weights[i];\n"
" }\n"
" vec4 Vertex = u_world * vec4(SkinVertex, 1.0);\n"
" gl_Position = u_proj * u_view * Vertex;\n"
" vec3 Normal = mat3(u_world) * SkinNormal;\n"
" v_tex0 = in_tex0;\n"
" v_color = in_color;\n"
" v_color.rgb += u_ambLight.rgb*surfAmbient;\n"
" v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;\n"
" v_color = clamp(v_color, 0.0, 1.0);\n"
" v_color *= u_matColor;\n"
" v_fog = DoFog(gl_Position.z);\n"
"}\n"
;

875
vendor/librw/src/gl/wdgl.cpp vendored Normal file
View file

@ -0,0 +1,875 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwanim.h"
#include "../rwengine.h"
#include "../rwplugins.h"
#include "rwwdgl.h"
#ifdef RW_OPENGL
#include "glad/glad.h"
#endif
#define PLUGIN_ID 2
namespace rw {
namespace wdgl {
static void*
driverOpen(void *o, int32, int32)
{
engine->driver[PLATFORM_WDGL]->defaultPipeline = makeDefaultPipeline();
return o;
}
static void*
driverClose(void *o, int32, int32)
{
return o;
}
void
registerPlatformPlugins(void)
{
Driver::registerPlugin(PLATFORM_WDGL, 0, PLATFORM_WDGL,
driverOpen, driverClose);
}
// 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->getMeshes()[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
rwFree(header->attribs);
rwFree(header->data);
rwFree(header);
return object;
}
Stream*
readNativeData(Stream *stream, int32, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY);
geometry->instData = header;
header->platform = PLATFORM_WDGL;
header->vbo = 0;
header->ibo = 0;
header->numAttribs = stream->readU32();
header->attribs = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY);
stream->read32(header->attribs,
header->numAttribs*sizeof(AttribDesc));
header->dataSize = header->attribs[0].stride*geometry->numVertices;
header->data = rwNewT(uint8, header->dataSize, MEMDUR_EVENT | ID_GEOMETRY);
ASSERTLITTLE;
stream->read8(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->write32(header->attribs, header->numAttribs*sizeof(AttribDesc));
ASSERTLITTLE;
stream->write8(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;
// TODO: allow for REINSTANCE (or not, wdgl can't render)
if(geo->instData)
return;
InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY);
geo->instData = header;
header->platform = PLATFORM_WDGL;
header->vbo = 0;
header->ibo = 0;
header->numAttribs =
pipe->numCustomAttribs + 1 + (geo->numTexCoordSets > 0);
if(geo->flags & Geometry::PRELIT)
header->numAttribs++;
if(geo->flags & Geometry::NORMALS)
header->numAttribs++;
int32 offset = 0;
header->attribs = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY);
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->flags & Geometry::NORMALS){
a->index = 2;
a->type = 1;
a->normalized = 1;
a->size = 3;
a->offset = offset;
offset += 4;
a++;
firstCustom++;
}
if(geo->flags & 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 = rwNewT(uint8, header->dataSize, MEMDUR_EVENT | ID_GEOMETRY);
}
a = header->attribs;
for(int32 i = 0; i < header->numAttribs; i++)
a[i].stride = offset;
uint8 *p = header->data + a->offset;
V3d *vert = geo->morphTargets->vertices;
for(int32 i = 0; i < geo->numVertices; i++){
packattrib(p, (float32*)vert, a);
vert++;
p += a->stride;
}
a++;
if(geo->numTexCoordSets){
p = header->data + a->offset;
TexCoords *texcoord = geo->texCoords[0];
for(int32 i = 0; i < geo->numVertices; i++){
packattrib(p, (float32*)texcoord, a, 512.0f);
texcoord++;
p += a->stride;
}
a++;
}
if(geo->flags & Geometry::NORMALS){
p = header->data + a->offset;
V3d *norm = geo->morphTargets->normals;
for(int32 i = 0; i < geo->numVertices; i++){
packattrib(p, (float32*)norm, a);
norm++;
p += a->stride;
}
a++;
}
if(geo->flags & Geometry::PRELIT){
// TODO: this seems too complicated
p = header->data + a->offset;
RGBA *color = geo->colors;
float32 f[4];
for(int32 i = 0; i < geo->numVertices; i++){
f[0] = color->red/255.0f;
f[1] = color->green/255.0f;
f[2] = color->blue/255.0f;
f[3] = color->alpha/255.0f;
packattrib(p, (float32*)f, a);
color++;
p += a->stride;
}
a++;
}
}
static void
uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->flags & Geometry::NATIVE) == 0)
return;
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_WDGL);
geo->numTriangles = geo->meshHeader->guessNumTriangles();
geo->allocateData();
uint8 *p;
TexCoords *texcoord = geo->texCoords[0];
RGBA *color = geo->colors;
V3d *vert = geo->morphTargets->vertices;
V3d *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((float32*)vert, p, a);
vert++;
p += a->stride;
}
break;
case 1: // texCoords
for(int32 i = 0; i < geo->numVertices; i++){
unpackattrib((float32*)texcoord, p, a, 512.0f);
texcoord++;
p += a->stride;
}
break;
case 2: // normals
for(int32 i = 0; i < geo->numVertices; i++){
unpackattrib((float32*)norm, p, a);
norm++;
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->red = f[0]*255.0f;
color->green = f[1]*255.0f;
color->blue = f[2]*255.0f;
color->alpha = f[3]*255.0f;
color++;
p += a->stride;
}
break;
}
}
if(pipe->uninstanceCB)
pipe->uninstanceCB(geo);
geo->generateTriangles();
geo->flags &= ~Geometry::NATIVE;
destroyNativeData(geo, 0, 0);
}
void
ObjPipeline::init(void)
{
this->rw::ObjPipeline::init(PLATFORM_GL3);
this->numCustomAttribs = 0;
this->impl.instance = wdgl::instance;
this->impl.uninstance = wdgl::uninstance;
this->instanceCB = nil;
this->uninstanceCB = nil;
}
ObjPipeline*
ObjPipeline::create(void)
{
ObjPipeline *pipe = rwNewT(ObjPipeline, 1, MEMDUR_GLOBAL);
pipe->init();
return pipe;
}
ObjPipeline*
makeDefaultPipeline(void)
{
ObjPipeline *pipe = ObjPipeline::create();
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 = rwNewT(Skin, 1, MEMDUR_EVENT | ID_SKIN);
*PLUGINOFFSET(Skin*, geometry, offset) = skin;
int32 numBones = stream->readI32();
skin->init(numBones, 0, 0);
stream->read32(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_GL);
Skin *skin = *PLUGINOFFSET(Skin*, object, offset);
stream->writeI32(skin->numBones);
stream->write32(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 = rwNewT(uint8, header->dataSize, MEMDUR_EVENT | ID_GEOMETRY);
Skin *skin = Skin::get(g);
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 = Skin::get(geo);
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);
rwFree(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);
float sum = weights[0] + weights[1] + weights[2] + weights[3];
if(sum){
weights[0] /= sum;
weights[1] /= sum;
weights[2] /= sum;
weights[3] /= sum;
}
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);
}
// Skin
static void*
skinOpen(void *o, int32, int32)
{
skinGlobals.pipelines[PLATFORM_WDGL] = makeSkinPipeline();
return o;
}
static void*
skinClose(void *o, int32, int32)
{
((ObjPipeline*)skinGlobals.pipelines[PLATFORM_WDGL])->destroy();
skinGlobals.pipelines[PLATFORM_WDGL] = nil;
return o;
}
void
initSkin(void)
{
Driver::registerPlugin(PLATFORM_WDGL, 0, ID_SKIN,
skinOpen, skinClose);
}
ObjPipeline*
makeSkinPipeline(void)
{
ObjPipeline *pipe = ObjPipeline::create();
pipe->pluginID = ID_SKIN;
pipe->pluginData = 1;
pipe->numCustomAttribs = 2;
pipe->instanceCB = skinInstanceCB;
pipe->uninstanceCB = skinUninstanceCB;
return pipe;
}
// MatFX
static void*
matfxOpen(void *o, int32, int32)
{
matFXGlobals.pipelines[PLATFORM_WDGL] = makeMatFXPipeline();
return o;
}
static void*
matfxClose(void *o, int32, int32)
{
((ObjPipeline*)matFXGlobals.pipelines[PLATFORM_WDGL])->destroy();
matFXGlobals.pipelines[PLATFORM_WDGL] = nil;
return o;
}
void
initMatFX(void)
{
Driver::registerPlugin(PLATFORM_WDGL, 0, ID_MATFX,
matfxOpen, matfxClose);
}
ObjPipeline*
makeMatFXPipeline(void)
{
ObjPipeline *pipe = ObjPipeline::create();
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),
ID_RASTERWDGL,
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->pixels);
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
}
}