summaryrefslogtreecommitdiff
path: root/src/gl/gl3render.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gl/gl3render.cpp')
-rw-r--r--src/gl/gl3render.cpp193
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
+