diff options
Diffstat (limited to 'src/gl/gl3render.cpp')
| -rw-r--r-- | src/gl/gl3render.cpp | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/src/gl/gl3render.cpp b/src/gl/gl3render.cpp new file mode 100644 index 0000000..a02c5c0 --- /dev/null +++ b/src/gl/gl3render.cpp @@ -0,0 +1,193 @@ +#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); + else + memset(&lightData, 0, sizeof(lightData)); + return setLights(&lightData); +} + +int32 +lightingCB(void) +{ + WorldLights lightData; + Light *directionals[8]; + Light *locals[8]; + lightData.directionals = directionals; + lightData.numDirectionals = 8; + lightData.locals = locals; + lightData.numLocals = 8; + + ((World*)engine->currentWorld)->enumerateLights(&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 + |
