2016-06-27 21:59:35 +02:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
#include "../rwbase.h"
|
|
|
|
#include "../rwerror.h"
|
|
|
|
#include "../rwplg.h"
|
|
|
|
#include "../rwpipeline.h"
|
|
|
|
#include "../rwobjects.h"
|
2016-07-11 20:27:21 +02:00
|
|
|
#include "../rwanim.h"
|
2016-06-27 21:59:35 +02:00
|
|
|
#include "../rwengine.h"
|
|
|
|
#include "../rwplugins.h"
|
|
|
|
#ifdef RW_OPENGL
|
|
|
|
#include <GL/glew.h>
|
|
|
|
#endif
|
|
|
|
#include "rwgl3.h"
|
|
|
|
#include "rwgl3shader.h"
|
2016-06-29 12:53:02 +02:00
|
|
|
#include "rwgl3plg.h"
|
|
|
|
|
|
|
|
#include "rwgl3impl.h"
|
2016-06-27 21:59:35 +02:00
|
|
|
|
|
|
|
namespace rw {
|
|
|
|
namespace gl3 {
|
|
|
|
|
|
|
|
#ifdef RW_OPENGL
|
|
|
|
|
|
|
|
// MatFX
|
|
|
|
|
2016-06-29 12:53:02 +02:00
|
|
|
Shader *envShader;
|
|
|
|
|
2016-06-27 21:59:35 +02:00
|
|
|
static void*
|
|
|
|
matfxOpen(void *o, int32, int32)
|
|
|
|
{
|
2016-07-19 18:40:10 +02:00
|
|
|
#include "shaders/matfx_gl3.inc"
|
2016-06-27 21:59:35 +02:00
|
|
|
matFXGlobals.pipelines[PLATFORM_GL3] = makeMatFXPipeline();
|
2016-07-19 18:40:10 +02:00
|
|
|
envShader = Shader::fromStrings(matfx_env_vert_src, matfx_env_frag_src);
|
2016-06-27 21:59:35 +02:00
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
matfxClose(void *o, int32, int32)
|
|
|
|
{
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
initMatFX(void)
|
|
|
|
{
|
|
|
|
Driver::registerPlugin(PLATFORM_GL3, 0, ID_MATFX,
|
|
|
|
matfxOpen, matfxClose);
|
2016-06-29 12:53:02 +02:00
|
|
|
registerUniform("u_texMatrix");
|
|
|
|
registerUniform("u_coefficient");
|
|
|
|
}
|
|
|
|
|
|
|
|
#define U(s) currentShader->uniformLocations[findUniform(s)]
|
|
|
|
|
|
|
|
void
|
|
|
|
matfxDefaultRender(InstanceDataHeader *header, InstanceData *inst)
|
|
|
|
{
|
|
|
|
Material *m;
|
|
|
|
RGBAf col;
|
|
|
|
GLfloat surfProps[4];
|
|
|
|
m = inst->material;
|
|
|
|
|
|
|
|
simpleShader->use();
|
|
|
|
|
|
|
|
convColor(&col, &m->color);
|
|
|
|
glUniform4fv(U("u_matColor"), 1, (GLfloat*)&col);
|
|
|
|
|
|
|
|
surfProps[0] = m->surfaceProps.ambient;
|
|
|
|
surfProps[1] = m->surfaceProps.specular;
|
|
|
|
surfProps[2] = m->surfaceProps.diffuse;
|
|
|
|
surfProps[3] = 0.0f;
|
|
|
|
glUniform4fv(U("u_surfaceProps"), 1, surfProps);
|
|
|
|
|
|
|
|
setTexture(0, m->texture);
|
|
|
|
|
2016-07-05 11:36:43 +02:00
|
|
|
rw::setRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
|
2016-06-29 12:53:02 +02:00
|
|
|
|
|
|
|
flushCache();
|
|
|
|
glDrawElements(header->primType, inst->numIndex,
|
|
|
|
GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
calcEnvTexMatrix(Frame *f, float32 *mat)
|
|
|
|
{
|
|
|
|
Matrix cam;
|
|
|
|
if(f){
|
|
|
|
// PS2 style - could be simplified by the shader
|
|
|
|
cam = *((Camera*)engine->currentCamera)->getFrame()->getLTM();
|
|
|
|
cam.pos = { 0.0, 0.0, 0.0 };
|
|
|
|
cam.right.x = -cam.right.x;
|
|
|
|
cam.right.y = -cam.right.y;
|
|
|
|
cam.right.z = -cam.right.z;
|
|
|
|
|
|
|
|
Matrix inv;
|
|
|
|
Matrix::invert(&inv, f->getLTM());
|
|
|
|
inv.pos = { -1.0, -1.0, -1.0 };
|
|
|
|
inv.right.x *= -0.5f;
|
|
|
|
inv.right.y *= -0.5f;
|
|
|
|
inv.right.z *= -0.5f;
|
|
|
|
inv.up.x *= -0.5f;
|
|
|
|
inv.up.y *= -0.5f;
|
|
|
|
inv.up.z *= -0.5f;
|
|
|
|
inv.at.x *= -0.5f;
|
|
|
|
inv.at.y *= -0.5f;
|
|
|
|
inv.at.z *= -0.5f;
|
|
|
|
inv.pos.x *= -0.5f;
|
|
|
|
inv.pos.y *= -0.5f;
|
|
|
|
inv.pos.z *= -0.5f;
|
|
|
|
|
|
|
|
Matrix m;
|
|
|
|
Matrix::mult(&m, &inv, &cam);
|
|
|
|
|
|
|
|
memcpy(mat, &m, 64);
|
|
|
|
mat[3] = mat[7] = mat[11] = 0.0f;
|
|
|
|
mat[15] = 1.0f;
|
|
|
|
|
|
|
|
}else{
|
|
|
|
// D3D - TODO: find out what PS2 does
|
|
|
|
mat[0] = 0.5f;
|
|
|
|
mat[1] = 0.0f;
|
|
|
|
mat[2] = 0.0f;
|
|
|
|
mat[3] = 0.0f;
|
|
|
|
|
|
|
|
mat[4] = 0.0f;
|
|
|
|
mat[5] = -0.5f;
|
|
|
|
mat[6] = 0.0f;
|
|
|
|
mat[7] = 0.0f;
|
|
|
|
|
|
|
|
mat[8] = 0.0f;
|
|
|
|
mat[9] = 0.0f;
|
|
|
|
mat[10] = 1.0f;
|
|
|
|
mat[11] = 0.0f;
|
|
|
|
|
|
|
|
mat[12] = 0.5f;
|
|
|
|
mat[13] = 0.5f;
|
|
|
|
mat[14] = 0.0f;
|
|
|
|
mat[15] = 0.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
matfxEnvRender(InstanceDataHeader *header, InstanceData *inst)
|
|
|
|
{
|
|
|
|
Material *m;
|
|
|
|
RGBAf col;
|
|
|
|
GLfloat surfProps[4];
|
|
|
|
float32 texMat[16];
|
|
|
|
m = inst->material;
|
|
|
|
|
|
|
|
matfxDefaultRender(header, inst);
|
|
|
|
|
|
|
|
MatFX *fx = MatFX::get(m);
|
|
|
|
int32 idx = fx->getEffectIndex(MatFX::ENVMAP);
|
|
|
|
MatFX::Env *env = &fx->fx[idx].env;
|
|
|
|
|
|
|
|
envShader->use();
|
|
|
|
|
|
|
|
convColor(&col, &m->color);
|
|
|
|
glUniform4fv(U("u_matColor"), 1, (GLfloat*)&col);
|
|
|
|
|
|
|
|
surfProps[0] = m->surfaceProps.ambient;
|
|
|
|
surfProps[1] = m->surfaceProps.specular;
|
|
|
|
surfProps[2] = m->surfaceProps.diffuse;
|
|
|
|
surfProps[3] = 0.0f;
|
|
|
|
glUniform4fv(U("u_surfaceProps"), 1, surfProps);
|
|
|
|
|
|
|
|
glUniform1fv(U("u_coefficient"), 1, &env->coefficient);
|
|
|
|
|
|
|
|
calcEnvTexMatrix(env->frame, texMat);
|
|
|
|
glUniformMatrix4fv(U("u_texMatrix"), 1, GL_FALSE, texMat);
|
|
|
|
|
|
|
|
setTexture(0, env->tex);
|
|
|
|
|
2016-07-05 11:36:43 +02:00
|
|
|
rw::setRenderState(VERTEXALPHA, 1);
|
|
|
|
rw::setRenderState(SRCBLEND, BLENDONE);
|
|
|
|
rw::setRenderState(DESTBLEND, BLENDONE);
|
2016-06-29 12:53:02 +02:00
|
|
|
|
|
|
|
flushCache();
|
|
|
|
glDrawElements(header->primType, inst->numIndex,
|
|
|
|
GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset);
|
|
|
|
|
2016-07-05 11:36:43 +02:00
|
|
|
rw::setRenderState(SRCBLEND, BLENDSRCALPHA);
|
|
|
|
rw::setRenderState(DESTBLEND, BLENDINVSRCALPHA);
|
2016-06-29 12:53:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
matfxRenderCB(Atomic *atomic, InstanceDataHeader *header)
|
|
|
|
{
|
|
|
|
setWorldMatrix(atomic->getFrame()->getLTM());
|
|
|
|
lightingCB();
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, header->vbo);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo);
|
|
|
|
setAttribPointers(header);
|
|
|
|
|
|
|
|
InstanceData *inst = header->inst;
|
|
|
|
int32 n = header->numMeshes;
|
|
|
|
|
2016-07-05 11:36:43 +02:00
|
|
|
rw::setRenderState(ALPHATESTFUNC, 1);
|
|
|
|
rw::setRenderState(ALPHATESTREF, 50);
|
2016-06-29 12:53:02 +02:00
|
|
|
|
|
|
|
int32 fx;
|
|
|
|
while(n--){
|
|
|
|
fx = MatFX::getEffects(inst->material);
|
|
|
|
switch(fx){
|
|
|
|
case MatFX::ENVMAP:
|
|
|
|
matfxEnvRender(header, inst);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
matfxDefaultRender(header, inst);
|
|
|
|
}
|
|
|
|
inst++;
|
|
|
|
}
|
2016-06-27 21:59:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjPipeline*
|
|
|
|
makeMatFXPipeline(void)
|
|
|
|
{
|
|
|
|
ObjPipeline *pipe = new ObjPipeline(PLATFORM_GL3);
|
|
|
|
pipe->instanceCB = defaultInstanceCB;
|
|
|
|
pipe->uninstanceCB = defaultUninstanceCB;
|
|
|
|
pipe->renderCB = matfxRenderCB;
|
|
|
|
pipe->pluginID = ID_MATFX;
|
|
|
|
pipe->pluginData = 0;
|
|
|
|
return pipe;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skin
|
|
|
|
|
2016-07-11 20:27:21 +02:00
|
|
|
Shader *skinShader;
|
|
|
|
|
2016-06-27 21:59:35 +02:00
|
|
|
static void*
|
|
|
|
skinOpen(void *o, int32, int32)
|
|
|
|
{
|
2016-07-19 18:40:10 +02:00
|
|
|
#include "shaders/simple_gl3.inc"
|
|
|
|
#include "shaders/skin_gl3.inc"
|
2016-06-27 21:59:35 +02:00
|
|
|
skinGlobals.pipelines[PLATFORM_GL3] = makeSkinPipeline();
|
2016-07-19 18:40:10 +02:00
|
|
|
skinShader = Shader::fromStrings(skin_vert_src, simple_frag_src);
|
2016-06-27 21:59:35 +02:00
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
skinClose(void *o, int32, int32)
|
|
|
|
{
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
initSkin(void)
|
|
|
|
{
|
|
|
|
Driver::registerPlugin(PLATFORM_GL3, 0, ID_SKIN,
|
|
|
|
skinOpen, skinClose);
|
2016-07-11 20:27:21 +02:00
|
|
|
registerUniform("u_boneMatrices");
|
|
|
|
}
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
ATTRIB_WEIGHTS = ATTRIB_TEXCOORDS7+1,
|
|
|
|
ATTRIB_INDICES
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
skinInstanceCB(Geometry *geo, InstanceDataHeader *header)
|
|
|
|
{
|
|
|
|
AttribDesc attribs[14], *a;
|
|
|
|
uint32 stride;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Create attribute descriptions
|
|
|
|
//
|
|
|
|
a = attribs;
|
|
|
|
stride = 0;
|
|
|
|
|
|
|
|
// Positions
|
|
|
|
a->index = ATTRIB_POS;
|
|
|
|
a->size = 3;
|
|
|
|
a->type = GL_FLOAT;
|
|
|
|
a->normalized = GL_FALSE;
|
|
|
|
a->offset = stride;
|
|
|
|
stride += 12;
|
|
|
|
a++;
|
|
|
|
|
|
|
|
// Normals
|
|
|
|
// TODO: compress
|
|
|
|
bool hasNormals = !!(geo->geoflags & Geometry::NORMALS);
|
|
|
|
if(hasNormals){
|
|
|
|
a->index = ATTRIB_NORMAL;
|
|
|
|
a->size = 3;
|
|
|
|
a->type = GL_FLOAT;
|
|
|
|
a->normalized = GL_FALSE;
|
|
|
|
a->offset = stride;
|
|
|
|
stride += 12;
|
|
|
|
a++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prelighting
|
|
|
|
bool isPrelit = !!(geo->geoflags & Geometry::PRELIT);
|
|
|
|
if(isPrelit){
|
|
|
|
a->index = ATTRIB_COLOR;
|
|
|
|
a->size = 4;
|
|
|
|
a->type = GL_UNSIGNED_BYTE;
|
|
|
|
a->normalized = GL_TRUE;
|
|
|
|
a->offset = stride;
|
|
|
|
stride += 4;
|
|
|
|
a++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Texture coordinates
|
|
|
|
for(int32 n = 0; n < geo->numTexCoordSets; n++){
|
|
|
|
a->index = ATTRIB_TEXCOORDS0+n;
|
|
|
|
a->size = 2;
|
|
|
|
a->type = GL_FLOAT;
|
|
|
|
a->normalized = GL_FALSE;
|
|
|
|
a->offset = stride;
|
|
|
|
stride += 8;
|
|
|
|
a++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 - attribs;
|
|
|
|
for(a = attribs; a != &attribs[header->numAttribs]; a++)
|
|
|
|
a->stride = stride;
|
|
|
|
header->attribDesc = new AttribDesc[header->numAttribs];
|
|
|
|
memcpy(header->attribDesc, attribs,
|
|
|
|
header->numAttribs*sizeof(AttribDesc));
|
|
|
|
|
|
|
|
//
|
|
|
|
// Allocate and fill vertex buffer
|
|
|
|
//
|
|
|
|
Skin *skin = Skin::get(geo);
|
|
|
|
uint8 *verts = new uint8[header->totalNumVertex*stride];
|
|
|
|
header->vertexBuffer = verts;
|
|
|
|
|
|
|
|
// Positions
|
|
|
|
for(a = attribs; a->index != ATTRIB_POS; a++)
|
|
|
|
;
|
|
|
|
instV3d(VERT_FLOAT3, verts + a->offset,
|
|
|
|
geo->morphTargets[0].vertices,
|
|
|
|
header->totalNumVertex, a->stride);
|
|
|
|
|
|
|
|
// Normals
|
|
|
|
if(hasNormals){
|
|
|
|
for(a = attribs; a->index != ATTRIB_NORMAL; a++)
|
|
|
|
;
|
|
|
|
instV3d(VERT_FLOAT3, verts + a->offset,
|
|
|
|
geo->morphTargets[0].normals,
|
|
|
|
header->totalNumVertex, a->stride);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prelighting
|
|
|
|
if(isPrelit){
|
|
|
|
for(a = attribs; a->index != ATTRIB_COLOR; a++)
|
|
|
|
;
|
|
|
|
instColor(VERT_RGBA, verts + a->offset,
|
|
|
|
geo->colors,
|
|
|
|
header->totalNumVertex, a->stride);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Texture coordinates
|
|
|
|
for(int32 n = 0; n < geo->numTexCoordSets; n++){
|
|
|
|
for(a = attribs; a->index != ATTRIB_TEXCOORDS0+n; a++)
|
|
|
|
;
|
|
|
|
instV2d(VERT_FLOAT2, verts + a->offset,
|
|
|
|
geo->texCoords[n],
|
|
|
|
header->totalNumVertex, a->stride);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Weights
|
|
|
|
for(a = attribs; a->index != ATTRIB_WEIGHTS; a++)
|
|
|
|
;
|
|
|
|
instV4d(VERT_FLOAT4, verts + a->offset,
|
|
|
|
skin->weights,
|
|
|
|
header->totalNumVertex, a->stride);
|
|
|
|
|
|
|
|
// Indices
|
|
|
|
for(a = attribs; a->index != ATTRIB_INDICES; a++)
|
|
|
|
;
|
|
|
|
// not really colors of course but what the heck
|
|
|
|
instColor(VERT_RGBA, verts + a->offset,
|
|
|
|
skin->indices,
|
|
|
|
header->totalNumVertex, a->stride);
|
|
|
|
|
|
|
|
glGenBuffers(1, &header->vbo);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, header->vbo);
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, header->totalNumVertex*stride,
|
|
|
|
header->vertexBuffer, GL_STATIC_DRAW);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
skinUninstanceCB(Geometry *geo, InstanceDataHeader *header)
|
|
|
|
{
|
|
|
|
assert(0 && "can't uninstance");
|
|
|
|
}
|
|
|
|
|
|
|
|
#define U(s) currentShader->uniformLocations[findUniform(s)]
|
|
|
|
|
|
|
|
static float skinMatrices[64*16];
|
|
|
|
|
|
|
|
void
|
|
|
|
updateSkinMatrices(Atomic *a)
|
|
|
|
{
|
|
|
|
Skin *skin = Skin::get(a->geometry);
|
|
|
|
HAnimHierarchy *hier = Skin::getHierarchy(a);
|
|
|
|
Matrix *invMats = (Matrix*)skin->inverseMatrices;
|
|
|
|
|
|
|
|
float *m;
|
|
|
|
m = (float*)skinMatrices;
|
|
|
|
for(int i = 0; i < hier->numNodes; i++){
|
|
|
|
invMats[i].rightw = 0.0f;
|
|
|
|
invMats[i].upw = 0.0f;
|
|
|
|
invMats[i].atw = 0.0f;
|
|
|
|
invMats[i].posw = 1.0f;
|
|
|
|
Matrix::mult((Matrix*)m, &hier->matrices[i], &invMats[i]);
|
|
|
|
m[3] = 0.0f;
|
|
|
|
m[7] = 0.0f;
|
|
|
|
m[11] = 0.0f;
|
|
|
|
m[15] = 1.0f;
|
|
|
|
m += 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
skinRenderCB(Atomic *atomic, InstanceDataHeader *header)
|
|
|
|
{
|
|
|
|
Material *m;
|
|
|
|
RGBAf col;
|
|
|
|
GLfloat surfProps[4];
|
|
|
|
int id;
|
|
|
|
|
|
|
|
setWorldMatrix(atomic->getFrame()->getLTM());
|
|
|
|
lightingCB();
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, header->vbo);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo);
|
|
|
|
setAttribPointers(header);
|
|
|
|
|
|
|
|
InstanceData *inst = header->inst;
|
|
|
|
int32 n = header->numMeshes;
|
|
|
|
|
|
|
|
rw::setRenderState(ALPHATESTFUNC, 1);
|
|
|
|
rw::setRenderState(ALPHATESTREF, 50);
|
|
|
|
|
|
|
|
skinShader->use();
|
|
|
|
|
|
|
|
updateSkinMatrices(atomic);
|
|
|
|
glUniformMatrix4fv(U("u_boneMatrices"), 64, GL_FALSE,
|
|
|
|
(GLfloat*)skinMatrices);
|
|
|
|
|
|
|
|
while(n--){
|
|
|
|
m = inst->material;
|
|
|
|
|
|
|
|
convColor(&col, &m->color);
|
|
|
|
glUniform4fv(U("u_matColor"), 1, (GLfloat*)&col);
|
|
|
|
|
|
|
|
surfProps[0] = m->surfaceProps.ambient;
|
|
|
|
surfProps[1] = m->surfaceProps.specular;
|
|
|
|
surfProps[2] = m->surfaceProps.diffuse;
|
|
|
|
surfProps[3] = 0.0f;
|
|
|
|
glUniform4fv(U("u_surfaceProps"), 1, surfProps);
|
|
|
|
|
|
|
|
setTexture(0, m->texture);
|
|
|
|
|
|
|
|
rw::setRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
|
|
|
|
|
|
|
|
flushCache();
|
|
|
|
glDrawElements(header->primType, inst->numIndex,
|
|
|
|
GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset);
|
|
|
|
inst++;
|
|
|
|
}
|
2016-06-27 21:59:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjPipeline*
|
|
|
|
makeSkinPipeline(void)
|
|
|
|
{
|
|
|
|
ObjPipeline *pipe = new ObjPipeline(PLATFORM_GL3);
|
2016-07-11 20:27:21 +02:00
|
|
|
pipe->instanceCB = skinInstanceCB;
|
|
|
|
pipe->uninstanceCB = skinUninstanceCB;
|
|
|
|
pipe->renderCB = skinRenderCB;
|
2016-06-27 21:59:35 +02:00
|
|
|
pipe->pluginID = ID_SKIN;
|
|
|
|
pipe->pluginData = 1;
|
|
|
|
return pipe;
|
|
|
|
}
|
|
|
|
|
2016-07-05 11:36:43 +02:00
|
|
|
#else
|
|
|
|
|
|
|
|
void initMatFX(void) { }
|
|
|
|
void initSkin(void) { }
|
|
|
|
|
2016-06-27 21:59:35 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|