summaryrefslogtreecommitdiffstats
path: root/src/extras/custompipes_gl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/extras/custompipes_gl.cpp')
-rw-r--r--src/extras/custompipes_gl.cpp623
1 files changed, 623 insertions, 0 deletions
diff --git a/src/extras/custompipes_gl.cpp b/src/extras/custompipes_gl.cpp
new file mode 100644
index 00000000..cb434ea1
--- /dev/null
+++ b/src/extras/custompipes_gl.cpp
@@ -0,0 +1,623 @@
+#include "common.h"
+
+#ifdef RW_OPENGL
+#ifdef EXTENDED_PIPELINES
+
+#include "main.h"
+#include "RwHelper.h"
+#include "Lights.h"
+#include "Timecycle.h"
+#include "FileMgr.h"
+#include "Clock.h"
+#include "Weather.h"
+#include "TxdStore.h"
+#include "Renderer.h"
+#include "World.h"
+#include "custompipes.h"
+
+#ifndef LIBRW
+#error "Need librw for EXTENDED_PIPELINES"
+#endif
+
+namespace CustomPipes {
+
+static int32 u_viewVec;
+static int32 u_rampStart;
+static int32 u_rampEnd;
+static int32 u_rimData;
+
+static int32 u_lightMap;
+
+static int32 u_eye;
+static int32 u_reflProps;
+static int32 u_specDir;
+static int32 u_specColor;
+
+#define U(i) currentShader->uniformLocations[i]
+
+/*
+ * Neo Vehicle pipe
+ */
+
+rw::gl3::Shader *neoVehicleShader;
+
+static void
+uploadSpecLights(void)
+{
+ using namespace rw::gl3;
+
+ rw::RGBAf colors[1 + NUMEXTRADIRECTIONALS];
+ struct {
+ rw::V3d dir;
+ float power;
+ } dirs[1 + NUMEXTRADIRECTIONALS];
+ memset(colors, 0, sizeof(colors));
+ memset(dirs, 0, sizeof(dirs));
+ for(int i = 0; i < 1+NUMEXTRADIRECTIONALS; i++)
+ dirs[i].power = 1.0f;
+ float power = Power.Get();
+ Color speccol = SpecColor.Get();
+ colors[0].red = speccol.r;
+ colors[0].green = speccol.g;
+ colors[0].blue = speccol.b;
+ dirs[0].dir = pDirect->getFrame()->getLTM()->at;
+ dirs[0].power = power;
+ for(int i = 0; i < NUMEXTRADIRECTIONALS; i++){
+ if(pExtraDirectionals[i]->getFlags() & rw::Light::LIGHTATOMICS){
+ colors[1+i] = pExtraDirectionals[i]->color;
+ dirs[1+i].dir = pExtraDirectionals[i]->getFrame()->getLTM()->at;
+ dirs[1+i].power = power*2.0f;
+ }
+ }
+ glUniform4fv(U(u_specDir), 1 + NUMEXTRADIRECTIONALS, (float*)&dirs);
+ glUniform4fv(U(u_specColor), 1 + NUMEXTRADIRECTIONALS, (float*)&colors);
+}
+
+static void
+vehicleRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
+{
+ using namespace rw;
+ using namespace rw::gl3;
+
+ // TODO: make this less of a kludge
+ if(VehiclePipeSwitch == VEHICLEPIPE_MATFX){
+ matFXGlobals.pipelines[rw::platform]->render(atomic);
+ return;
+ }
+
+ Material *m;
+
+ setWorldMatrix(atomic->getFrame()->getLTM());
+ lightingCB(atomic);
+
+#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
+
+ InstanceData *inst = header->inst;
+ rw::int32 n = header->numMeshes;
+
+ neoVehicleShader->use();
+
+ V3d eyePos = rw::engine->currentCamera->getFrame()->getLTM()->pos;
+ glUniform3fv(U(u_eye), 1, (float*)&eyePos);
+
+ uploadSpecLights();
+
+ float reflProps[4];
+ reflProps[0] = Fresnel.Get();
+ reflProps[1] = SpecColor.Get().a;
+
+ setTexture(1, EnvMapTex);
+
+ SetRenderState(SRCBLEND, BLENDONE);
+
+ while(n--){
+ m = inst->material;
+
+ setMaterial(m->color, m->surfaceProps);
+
+ setTexture(0, m->texture);
+
+ rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
+
+ reflProps[2] = m->surfaceProps.specular * VehicleShininess;
+ reflProps[3] = m->surfaceProps.specular == 0.0f ? 0.0f : VehicleSpecularity;
+ glUniform4fv(U(u_reflProps), 1, reflProps);
+
+ drawInst(header, inst);
+ inst++;
+ }
+
+ SetRenderState(SRCBLEND, BLENDSRCALPHA);
+
+#ifndef RW_GL_USE_VAOS
+ disableAttribPointers(header->attribDesc, header->numAttribs);
+#endif
+}
+
+void
+CreateVehiclePipe(void)
+{
+ using namespace rw;
+ using namespace rw::gl3;
+
+ if(CFileMgr::LoadFile("neo/carTweakingTable.dat", work_buff, sizeof(work_buff), "r") == 0)
+ printf("Error: couldn't open 'neo/carTweakingTable.dat'\n");
+ else{
+ char *fp = (char*)work_buff;
+ fp = ReadTweakValueTable(fp, Fresnel);
+ fp = ReadTweakValueTable(fp, Power);
+ fp = ReadTweakValueTable(fp, DiffColor);
+ fp = ReadTweakValueTable(fp, SpecColor);
+ }
+
+
+ {
+#ifdef RW_GLES2
+#include "gl2_shaders/neoVehicle_fs_gl2.inc"
+#include "gl2_shaders/neoVehicle_vs_gl2.inc"
+#else
+#include "shaders/neoVehicle_fs_gl3.inc"
+#include "shaders/neoVehicle_vs_gl3.inc"
+#endif
+ const char *vs[] = { shaderDecl, header_vert_src, neoVehicle_vert_src, nil };
+ const char *fs[] = { shaderDecl, header_frag_src, neoVehicle_frag_src, nil };
+ neoVehicleShader = Shader::create(vs, fs);
+ assert(neoVehicleShader);
+ }
+
+
+ rw::gl3::ObjPipeline *pipe = rw::gl3::ObjPipeline::create();
+ pipe->instanceCB = rw::gl3::defaultInstanceCB;
+ pipe->uninstanceCB = nil;
+ pipe->renderCB = vehicleRenderCB;
+ vehiclePipe = pipe;
+}
+
+void
+DestroyVehiclePipe(void)
+{
+ neoVehicleShader->destroy();
+ neoVehicleShader = nil;
+
+ ((rw::gl3::ObjPipeline*)vehiclePipe)->destroy();
+ vehiclePipe = nil;
+}
+
+
+
+/*
+ * Neo World pipe
+ */
+
+rw::gl3::Shader *neoWorldShader;
+
+static void
+worldRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
+{
+ using namespace rw;
+ using namespace rw::gl3;
+
+ Material *m;
+
+ setWorldMatrix(atomic->getFrame()->getLTM());
+ lightingCB(atomic);
+
+#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
+
+ InstanceData *inst = header->inst;
+ rw::int32 n = header->numMeshes;
+
+ neoWorldShader->use();
+
+ float lightfactor[4];
+
+ while(n--){
+ m = inst->material;
+
+ if(MatFX::getEffects(m) == MatFX::DUAL){
+ MatFX *matfx = MatFX::get(m);
+ Texture *dualtex = matfx->getDualTexture();
+ if(dualtex == nil)
+ goto notex;
+ setTexture(1, dualtex);
+ lightfactor[0] = lightfactor[1] = lightfactor[2] = WorldLightmapBlend.Get()*LightmapMult;
+ }else{
+ notex:
+ setTexture(1, nil);
+ lightfactor[0] = lightfactor[1] = lightfactor[2] = 0.0f;
+ }
+ lightfactor[3] = m->color.alpha/255.0f;
+ glUniform4fv(U(u_lightMap), 1, lightfactor);
+
+ RGBA color = { 255, 255, 255, m->color.alpha };
+ setMaterial(color, m->surfaceProps);
+
+ setTexture(0, m->texture);
+
+ rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
+
+ drawInst(header, inst);
+ inst++;
+ }
+#ifndef RW_GL_USE_VAOS
+ disableAttribPointers(header->attribDesc, header->numAttribs);
+#endif
+}
+
+void
+CreateWorldPipe(void)
+{
+ using namespace rw;
+ using namespace rw::gl3;
+
+ if(CFileMgr::LoadFile("neo/worldTweakingTable.dat", work_buff, sizeof(work_buff), "r") == 0)
+ printf("Error: couldn't open 'neo/worldTweakingTable.dat'\n");
+ else
+ ReadTweakValueTable((char*)work_buff, WorldLightmapBlend);
+
+ {
+#ifdef RW_GLES2
+#include "gl2_shaders/neoWorldIII_fs_gl2.inc"
+#include "gl2_shaders/default_UV2_gl2.inc"
+#else
+#include "shaders/neoWorldVC_fs_gl3.inc"
+#include "shaders/default_UV2_gl3.inc"
+#endif
+ const char *vs[] = { shaderDecl, header_vert_src, default_UV2_vert_src, nil };
+ const char *fs[] = { shaderDecl, header_frag_src, neoWorldVC_frag_src, nil };
+ neoWorldShader = Shader::create(vs, fs);
+ assert(neoWorldShader);
+ }
+
+
+ rw::gl3::ObjPipeline *pipe = rw::gl3::ObjPipeline::create();
+ pipe->instanceCB = rw::gl3::defaultInstanceCB;
+ pipe->uninstanceCB = nil;
+ pipe->renderCB = worldRenderCB;
+ worldPipe = pipe;
+}
+
+void
+DestroyWorldPipe(void)
+{
+ neoWorldShader->destroy();
+ neoWorldShader = nil;
+
+ ((rw::gl3::ObjPipeline*)worldPipe)->destroy();
+ worldPipe = nil;
+}
+
+
+
+
+/*
+ * Neo Gloss pipe
+ */
+
+rw::gl3::Shader *neoGlossShader;
+
+static void
+glossRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
+{
+ using namespace rw;
+ using namespace rw::gl3;
+
+ worldRenderCB(atomic, header);
+
+ Material *m;
+
+#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
+
+ InstanceData *inst = header->inst;
+ rw::int32 n = header->numMeshes;
+
+ neoGlossShader->use();
+
+ V3d eyePos = rw::engine->currentCamera->getFrame()->getLTM()->pos;
+ glUniform3fv(U(u_eye), 1, (float*)&eyePos);
+ glUniform4fv(U(u_reflProps), 1, (float*)&GlossMult);
+
+ SetRenderState(VERTEXALPHA, TRUE);
+ SetRenderState(SRCBLEND, BLENDONE);
+ SetRenderState(DESTBLEND, BLENDONE);
+ SetRenderState(ZWRITEENABLE, FALSE);
+ SetRenderState(ALPHATESTFUNC, ALPHAALWAYS);
+
+ while(n--){
+ m = inst->material;
+
+ RGBA color = { 255, 255, 255, m->color.alpha };
+ setMaterial(color, m->surfaceProps);
+
+ if(m->texture){
+ Texture *tex = GetGlossTex(m);
+ if(tex){
+ setTexture(0, tex);
+ drawInst(header, inst);
+ }
+ }
+ inst++;
+ }
+
+ SetRenderState(ZWRITEENABLE, TRUE);
+ SetRenderState(ALPHATESTFUNC, ALPHAGREATEREQUAL);
+ SetRenderState(SRCBLEND, BLENDSRCALPHA);
+ SetRenderState(DESTBLEND, BLENDINVSRCALPHA);
+
+#ifndef RW_GL_USE_VAOS
+ disableAttribPointers(header->attribDesc, header->numAttribs);
+#endif
+}
+
+void
+CreateGlossPipe(void)
+{
+ using namespace rw;
+ using namespace rw::gl3;
+
+ {
+#ifdef RW_GLES2
+#include "gl2_shaders/neoGloss_fs_gl2.inc"
+#include "gl2_shaders/neoGloss_vs_gl2.inc"
+#else
+#include "shaders/neoGloss_fs_gl3.inc"
+#include "shaders/neoGloss_vs_gl3.inc"
+#endif
+ const char *vs[] = { shaderDecl, header_vert_src, neoGloss_vert_src, nil };
+ const char *fs[] = { shaderDecl, header_frag_src, neoGloss_frag_src, nil };
+ neoGlossShader = Shader::create(vs, fs);
+ assert(neoGlossShader);
+ }
+
+ rw::gl3::ObjPipeline *pipe = rw::gl3::ObjPipeline::create();
+ pipe->instanceCB = rw::gl3::defaultInstanceCB;
+ pipe->uninstanceCB = nil;
+ pipe->renderCB = glossRenderCB;
+ glossPipe = pipe;
+}
+
+void
+DestroyGlossPipe(void)
+{
+ neoGlossShader->destroy();
+ neoGlossShader = nil;
+
+ ((rw::gl3::ObjPipeline*)glossPipe)->destroy();
+ glossPipe = nil;
+}
+
+
+
+/*
+ * Neo Rim pipes
+ */
+
+rw::gl3::Shader *neoRimShader;
+rw::gl3::Shader *neoRimSkinShader;
+
+static void
+uploadRimData(bool enable)
+{
+ using namespace rw;
+ using namespace rw::gl3;
+
+ V3d viewVec = rw::engine->currentCamera->getFrame()->getLTM()->at;
+ glUniform3fv(U(u_viewVec), 1, (float*)&viewVec);
+ float rimData[4];
+ rimData[0] = Offset.Get();
+ rimData[1] = Scale.Get();
+ if(enable)
+ rimData[2] = Scaling.Get()*RimlightMult;
+ else
+ rimData[2] = 0.0f;
+ rimData[3] = 0.0f;
+ glUniform3fv(U(u_rimData), 1, rimData);
+ Color col = RampStart.Get();
+ glUniform4fv(U(u_rampStart), 1, (float*)&col);
+ col = RampEnd.Get();
+ glUniform4fv(U(u_rampEnd), 1, (float*)&col);
+}
+
+static void
+rimSkinRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
+{
+ using namespace rw;
+ using namespace rw::gl3;
+
+ Material *m;
+
+ setWorldMatrix(atomic->getFrame()->getLTM());
+ lightingCB(atomic);
+
+#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
+
+ InstanceData *inst = header->inst;
+ rw::int32 n = header->numMeshes;
+
+ neoRimSkinShader->use();
+
+ uploadRimData(atomic->geometry->flags & Geometry::LIGHT);
+
+ uploadSkinMatrices(atomic);
+
+ while(n--){
+ m = inst->material;
+
+ setMaterial(m->color, m->surfaceProps);
+
+ setTexture(0, m->texture);
+
+ rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
+
+ drawInst(header, inst);
+ inst++;
+ }
+#ifndef RW_GL_USE_VAOS
+ disableAttribPointers(header->attribDesc, header->numAttribs);
+#endif
+}
+
+static void
+rimRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
+{
+ using namespace rw;
+ using namespace rw::gl3;
+
+ Material *m;
+
+ setWorldMatrix(atomic->getFrame()->getLTM());
+ lightingCB(atomic);
+
+#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
+
+ InstanceData *inst = header->inst;
+ rw::int32 n = header->numMeshes;
+
+ neoRimShader->use();
+
+ uploadRimData(atomic->geometry->flags & Geometry::LIGHT);
+
+ while(n--){
+ m = inst->material;
+
+ setMaterial(m->color, m->surfaceProps);
+
+ setTexture(0, m->texture);
+
+ rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
+
+ drawInst(header, inst);
+ inst++;
+ }
+#ifndef RW_GL_USE_VAOS
+ disableAttribPointers(header->attribDesc, header->numAttribs);
+#endif
+}
+
+void
+CreateRimLightPipes(void)
+{
+ using namespace rw::gl3;
+
+ if(CFileMgr::LoadFile("neo/rimTweakingTable.dat", work_buff, sizeof(work_buff), "r") == 0)
+ printf("Error: couldn't open 'neo/rimTweakingTable.dat'\n");
+ else{
+ char *fp = (char*)work_buff;
+ fp = ReadTweakValueTable(fp, RampStart);
+ fp = ReadTweakValueTable(fp, RampEnd);
+ fp = ReadTweakValueTable(fp, Offset);
+ fp = ReadTweakValueTable(fp, Scale);
+ fp = ReadTweakValueTable(fp, Scaling);
+ }
+
+ {
+#ifdef RW_GLES2
+#include "gl2_shaders/simple_fs_gl2.inc"
+#include "gl2_shaders/neoRimSkin_gl2.inc"
+#else
+#include "shaders/simple_fs_gl3.inc"
+#include "shaders/neoRimSkin_gl3.inc"
+#endif
+ const char *vs[] = { shaderDecl, header_vert_src, neoRimSkin_vert_src, nil };
+ const char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil };
+ neoRimSkinShader = Shader::create(vs, fs);
+ assert(neoRimSkinShader);
+ }
+
+ {
+#ifdef RW_GLES2
+#include "gl2_shaders/simple_fs_gl2.inc"
+#include "gl2_shaders/neoRim_gl2.inc"
+#else
+#include "shaders/simple_fs_gl3.inc"
+#include "shaders/neoRim_gl3.inc"
+#endif
+ const char *vs[] = { shaderDecl, header_vert_src, neoRim_vert_src, nil };
+ const char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil };
+ neoRimShader = Shader::create(vs, fs);
+ assert(neoRimShader);
+ }
+
+
+ rw::gl3::ObjPipeline *pipe = rw::gl3::ObjPipeline::create();
+ pipe->instanceCB = rw::gl3::defaultInstanceCB;
+ pipe->uninstanceCB = nil;
+ pipe->renderCB = rimRenderCB;
+ rimPipe = pipe;
+
+ pipe = rw::gl3::ObjPipeline::create();
+ pipe->instanceCB = rw::gl3::skinInstanceCB;
+ pipe->uninstanceCB = nil;
+ pipe->renderCB = rimSkinRenderCB;
+ rimSkinPipe = pipe;
+}
+
+void
+DestroyRimLightPipes(void)
+{
+ neoRimShader->destroy();
+ neoRimShader = nil;
+
+ neoRimSkinShader->destroy();
+ neoRimSkinShader = nil;
+
+ ((rw::gl3::ObjPipeline*)rimPipe)->destroy();
+ rimPipe = nil;
+
+ ((rw::gl3::ObjPipeline*)rimSkinPipe)->destroy();
+ rimSkinPipe = nil;
+}
+
+
+
+void
+CustomPipeRegisterGL(void)
+{
+ u_viewVec = rw::gl3::registerUniform("u_viewVec");
+ u_rampStart = rw::gl3::registerUniform("u_rampStart");
+ u_rampEnd = rw::gl3::registerUniform("u_rampEnd");
+ u_rimData = rw::gl3::registerUniform("u_rimData");
+
+ u_lightMap = rw::gl3::registerUniform("u_lightMap");
+
+ u_eye = rw::gl3::registerUniform("u_eye");
+ u_reflProps = rw::gl3::registerUniform("u_reflProps");
+ u_specDir = rw::gl3::registerUniform("u_specDir");
+ u_specColor = rw::gl3::registerUniform("u_specColor");
+}
+
+
+}
+
+#endif
+#endif