mirror of
https://github.com/GTAmodding/re3.git
synced 2025-07-16 04:04:08 +00:00
neo pipelines; postfx fix
This commit is contained in:
parent
5ac83e4b4c
commit
827ba62671
61 changed files with 3717 additions and 7 deletions
536
src/extras/custompipes.cpp
Normal file
536
src/extras/custompipes.cpp
Normal file
|
@ -0,0 +1,536 @@
|
|||
#define WITH_D3D
|
||||
#include "common.h"
|
||||
|
||||
#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 {
|
||||
|
||||
rw::int32 CustomMatOffset;
|
||||
|
||||
void*
|
||||
CustomMatCtor(void *object, int32, int32)
|
||||
{
|
||||
CustomMatExt *ext = GetCustomMatExt((rw::Material*)object);
|
||||
ext->glossTex = nil;
|
||||
ext->haveGloss = false;
|
||||
return object;
|
||||
}
|
||||
|
||||
void*
|
||||
CustomMatCopy(void *dst, void *src, int32, int32)
|
||||
{
|
||||
CustomMatExt *srcext = GetCustomMatExt((rw::Material*)src);
|
||||
CustomMatExt *dstext = GetCustomMatExt((rw::Material*)dst);
|
||||
dstext->glossTex = srcext->glossTex;
|
||||
dstext->haveGloss = srcext->haveGloss;
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static rw::TexDictionary *neoTxd;
|
||||
|
||||
bool bRenderingEnvMap;
|
||||
int32 EnvMapSize = 128;
|
||||
rw::Camera *EnvMapCam;
|
||||
rw::Texture *EnvMapTex;
|
||||
rw::Texture *EnvMaskTex;
|
||||
static rw::RWDEVICE::Im2DVertex EnvScreenQuad[4];
|
||||
static int16 QuadIndices[6] = { 0, 1, 2, 0, 2, 3 };
|
||||
|
||||
static rw::Camera*
|
||||
CreateEnvMapCam(rw::World *world)
|
||||
{
|
||||
rw::Raster *fbuf = rw::Raster::create(EnvMapSize, EnvMapSize, 0, rw::Raster::CAMERATEXTURE);
|
||||
if(fbuf){
|
||||
rw::Raster *zbuf = rw::Raster::create(EnvMapSize, EnvMapSize, 0, rw::Raster::ZBUFFER);
|
||||
if(zbuf){
|
||||
rw::Frame *frame = rw::Frame::create();
|
||||
if(frame){
|
||||
rw::Camera *cam = rw::Camera::create();
|
||||
if(cam){
|
||||
cam->frameBuffer = fbuf;
|
||||
cam->zBuffer = zbuf;
|
||||
cam->setFrame(frame);
|
||||
cam->setNearPlane(0.1f);
|
||||
cam->setFarPlane(250.0f);
|
||||
rw::V2d vw = { 2.0f, 2.0f };
|
||||
cam->setViewWindow(&vw);
|
||||
world->addCamera(cam);
|
||||
EnvMapTex = rw::Texture::create(fbuf);
|
||||
EnvMapTex->setFilter(rw::Texture::LINEAR);
|
||||
|
||||
frame->matrix.right.x = -1.0f;
|
||||
frame->matrix.up.y = -1.0f;
|
||||
frame->matrix.update();
|
||||
return cam;
|
||||
}
|
||||
frame->destroy();
|
||||
}
|
||||
zbuf->destroy();
|
||||
}
|
||||
fbuf->destroy();
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
DestroyCam(rw::Camera *cam)
|
||||
{
|
||||
if(cam == nil)
|
||||
return;
|
||||
if(cam->frameBuffer){
|
||||
cam->frameBuffer->destroy();
|
||||
cam->frameBuffer = nil;
|
||||
}
|
||||
if(cam->zBuffer){
|
||||
cam->zBuffer->destroy();
|
||||
cam->zBuffer = nil;
|
||||
}
|
||||
rw::Frame *f = cam->getFrame();
|
||||
if(f){
|
||||
cam->setFrame(nil);
|
||||
f->destroy();
|
||||
}
|
||||
cam->world->removeCamera(cam);
|
||||
cam->destroy();
|
||||
}
|
||||
|
||||
void
|
||||
RenderEnvMapScene(void)
|
||||
{
|
||||
CRenderer::RenderRoads();
|
||||
CRenderer::RenderEverythingBarRoads();
|
||||
CRenderer::RenderFadingInEntities();
|
||||
}
|
||||
|
||||
void
|
||||
EnvMapRender(void)
|
||||
{
|
||||
if(VehiclePipeSwitch != VEHICLEPIPE_NEO)
|
||||
return;
|
||||
|
||||
RwCameraEndUpdate(Scene.camera);
|
||||
|
||||
// Neo does this differently, but i'm not quite convinced it's much better
|
||||
rw::V3d camPos = FindPlayerCoors();
|
||||
EnvMapCam->getFrame()->matrix.pos = camPos;
|
||||
EnvMapCam->getFrame()->transform(&EnvMapCam->getFrame()->matrix, rw::COMBINEREPLACE);
|
||||
|
||||
rw::RGBA skycol = { CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(), 255 };
|
||||
EnvMapCam->clear(&skycol, rwCAMERACLEARZ|rwCAMERACLEARIMAGE);
|
||||
RwCameraBeginUpdate(EnvMapCam);
|
||||
bRenderingEnvMap = true;
|
||||
RenderEnvMapScene();
|
||||
bRenderingEnvMap = false;
|
||||
|
||||
if(EnvMaskTex){
|
||||
rw::SetRenderState(rw::VERTEXALPHA, TRUE);
|
||||
rw::SetRenderState(rw::SRCBLEND, rw::BLENDZERO);
|
||||
rw::SetRenderState(rw::DESTBLEND, rw::BLENDSRCCOLOR);
|
||||
rw::SetRenderStatePtr(rw::TEXTURERASTER, EnvMaskTex->raster);
|
||||
rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, EnvScreenQuad, 4, QuadIndices, 6);
|
||||
rw::SetRenderState(rw::SRCBLEND, rw::BLENDSRCALPHA);
|
||||
rw::SetRenderState(rw::DESTBLEND, rw::BLENDINVSRCALPHA);
|
||||
}
|
||||
RwCameraEndUpdate(EnvMapCam);
|
||||
|
||||
|
||||
RwCameraBeginUpdate(Scene.camera);
|
||||
|
||||
// debug env map
|
||||
// rw::SetRenderStatePtr(rw::TEXTURERASTER, EnvMapTex->raster);
|
||||
// rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, EnvScreenQuad, 4, QuadIndices, 6);
|
||||
}
|
||||
|
||||
static void
|
||||
EnvMapInit(void)
|
||||
{
|
||||
if(neoTxd)
|
||||
EnvMaskTex = neoTxd->find("CarReflectionMask");
|
||||
|
||||
EnvMapCam = CreateEnvMapCam(Scene.world);
|
||||
|
||||
int width = EnvMapCam->frameBuffer->width;
|
||||
int height = EnvMapCam->frameBuffer->height;
|
||||
float screenZ = RwIm2DGetNearScreenZ();
|
||||
float recipZ = 1.0f/EnvMapCam->nearPlane;
|
||||
|
||||
EnvScreenQuad[0].setScreenX(0.0f);
|
||||
EnvScreenQuad[0].setScreenY(0.0f);
|
||||
EnvScreenQuad[0].setScreenZ(screenZ);
|
||||
EnvScreenQuad[0].setCameraZ(EnvMapCam->nearPlane);
|
||||
EnvScreenQuad[0].setRecipCameraZ(recipZ);
|
||||
EnvScreenQuad[0].setColor(255, 255, 255, 255);
|
||||
EnvScreenQuad[0].setU(0.0f, recipZ);
|
||||
EnvScreenQuad[0].setV(0.0f, recipZ);
|
||||
|
||||
EnvScreenQuad[1].setScreenX(0.0f);
|
||||
EnvScreenQuad[1].setScreenY(height);
|
||||
EnvScreenQuad[1].setScreenZ(screenZ);
|
||||
EnvScreenQuad[1].setCameraZ(EnvMapCam->nearPlane);
|
||||
EnvScreenQuad[1].setRecipCameraZ(recipZ);
|
||||
EnvScreenQuad[1].setColor(255, 255, 255, 255);
|
||||
EnvScreenQuad[1].setU(0.0f, recipZ);
|
||||
EnvScreenQuad[1].setV(1.0f, recipZ);
|
||||
|
||||
EnvScreenQuad[2].setScreenX(width);
|
||||
EnvScreenQuad[2].setScreenY(height);
|
||||
EnvScreenQuad[2].setScreenZ(screenZ);
|
||||
EnvScreenQuad[2].setCameraZ(EnvMapCam->nearPlane);
|
||||
EnvScreenQuad[2].setRecipCameraZ(recipZ);
|
||||
EnvScreenQuad[2].setColor(255, 255, 255, 255);
|
||||
EnvScreenQuad[2].setU(1.0f, recipZ);
|
||||
EnvScreenQuad[2].setV(1.0f, recipZ);
|
||||
|
||||
EnvScreenQuad[3].setScreenX(width);
|
||||
EnvScreenQuad[3].setScreenY(0.0f);
|
||||
EnvScreenQuad[3].setScreenZ(screenZ);
|
||||
EnvScreenQuad[3].setCameraZ(EnvMapCam->nearPlane);
|
||||
EnvScreenQuad[3].setRecipCameraZ(recipZ);
|
||||
EnvScreenQuad[3].setColor(255, 255, 255, 255);
|
||||
EnvScreenQuad[3].setU(1.0f, recipZ);
|
||||
EnvScreenQuad[3].setV(0.0f, recipZ);
|
||||
}
|
||||
|
||||
static void
|
||||
EnvMapShutdown(void)
|
||||
{
|
||||
EnvMapTex->raster = nil;
|
||||
EnvMapTex->destroy();
|
||||
EnvMapTex = nil;
|
||||
DestroyCam(EnvMapCam);
|
||||
EnvMapCam = nil;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tweak values
|
||||
*/
|
||||
|
||||
#define INTERP_SETUP \
|
||||
int h1 = CClock::GetHours(); \
|
||||
int h2 = (h1+1)%24; \
|
||||
int w1 = CWeather::OldWeatherType; \
|
||||
int w2 = CWeather::NewWeatherType; \
|
||||
float timeInterp = (CClock::GetSeconds()/60.0f + CClock::GetMinutes())/60.0f; \
|
||||
float c0 = (1.0f-timeInterp)*(1.0f-CWeather::InterpolationValue); \
|
||||
float c1 = timeInterp*(1.0f-CWeather::InterpolationValue); \
|
||||
float c2 = (1.0f-timeInterp)*CWeather::InterpolationValue; \
|
||||
float c3 = timeInterp*CWeather::InterpolationValue;
|
||||
#define INTERP(v) v[h1][w1]*c0 + v[h2][w1]*c1 + v[h1][w2]*c2 + v[h2][w2]*c3;
|
||||
#define INTERPF(v,f) v[h1][w1].f*c0 + v[h2][w1].f*c1 + v[h1][w2].f*c2 + v[h2][w2].f*c3;
|
||||
|
||||
InterpolatedFloat::InterpolatedFloat(float init)
|
||||
{
|
||||
curInterpolator = 61; // compared against second
|
||||
for(int h = 0; h < 24; h++)
|
||||
for(int w = 0; w < NUMWEATHERS; w++)
|
||||
data[h][w] = init;
|
||||
}
|
||||
|
||||
void
|
||||
InterpolatedFloat::Read(char *s, int line, int field)
|
||||
{
|
||||
sscanf(s, "%f", &data[line][field]);
|
||||
}
|
||||
|
||||
float
|
||||
InterpolatedFloat::Get(void)
|
||||
{
|
||||
if(curInterpolator != CClock::GetSeconds()){
|
||||
INTERP_SETUP
|
||||
curVal = INTERP(data);
|
||||
curInterpolator = CClock::GetSeconds();
|
||||
}
|
||||
return curVal;
|
||||
}
|
||||
|
||||
InterpolatedColor::InterpolatedColor(const Color &init)
|
||||
{
|
||||
curInterpolator = 61; // compared against second
|
||||
for(int h = 0; h < 24; h++)
|
||||
for(int w = 0; w < NUMWEATHERS; w++)
|
||||
data[h][w] = init;
|
||||
}
|
||||
|
||||
void
|
||||
InterpolatedColor::Read(char *s, int line, int field)
|
||||
{
|
||||
int r, g, b, a;
|
||||
sscanf(s, "%i, %i, %i, %i", &r, &g, &b, &a);
|
||||
data[line][field] = Color(r/255.0f, g/255.0f, b/255.0f, a/255.0f);
|
||||
}
|
||||
|
||||
Color
|
||||
InterpolatedColor::Get(void)
|
||||
{
|
||||
if(curInterpolator != CClock::GetSeconds()){
|
||||
INTERP_SETUP
|
||||
curVal.r = INTERPF(data, r);
|
||||
curVal.g = INTERPF(data, g);
|
||||
curVal.b = INTERPF(data, b);
|
||||
curVal.a = INTERPF(data, a);
|
||||
curInterpolator = CClock::GetSeconds();
|
||||
}
|
||||
return curVal;
|
||||
}
|
||||
|
||||
void
|
||||
InterpolatedLight::Read(char *s, int line, int field)
|
||||
{
|
||||
int r, g, b, a;
|
||||
sscanf(s, "%i, %i, %i, %i", &r, &g, &b, &a);
|
||||
data[line][field] = Color(r/255.0f, g/255.0f, b/255.0f, a/100.0f);
|
||||
}
|
||||
|
||||
char*
|
||||
ReadTweakValueTable(char *fp, InterpolatedValue &interp)
|
||||
{
|
||||
char buf[24], *p;
|
||||
int c;
|
||||
int line, field;
|
||||
|
||||
line = 0;
|
||||
c = *fp++;
|
||||
while(c != '\0' && line < 24){
|
||||
field = 0;
|
||||
if(c != '\0' && c != '#'){
|
||||
while(c != '\0' && c != '\n' && field < NUMWEATHERS){
|
||||
p = buf;
|
||||
while(c != '\0' && c == '\t')
|
||||
c = *fp++;
|
||||
*p++ = c;
|
||||
while(c = *fp++, c != '\0' && c != '\t' && c != '\n')
|
||||
*p++ = c;
|
||||
*p++ = '\0';
|
||||
interp.Read(buf, line, field);
|
||||
field++;
|
||||
}
|
||||
line++;
|
||||
}
|
||||
while(c != '\0' && c != '\n')
|
||||
c = *fp++;
|
||||
c = *fp++;
|
||||
}
|
||||
return fp-1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Neo Vehicle pipe
|
||||
*/
|
||||
|
||||
int32 VehiclePipeSwitch = VEHICLEPIPE_NEO;
|
||||
float VehicleShininess = 1.0f;
|
||||
float VehicleSpecularity = 1.0f;
|
||||
InterpolatedFloat Fresnel(0.4f);
|
||||
InterpolatedFloat Power(18.0f);
|
||||
InterpolatedLight DiffColor(Color(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
InterpolatedLight SpecColor(Color(0.7f, 0.7f, 0.7f, 1.0f));
|
||||
rw::ObjPipeline *vehiclePipe;
|
||||
|
||||
void
|
||||
AttachVehiclePipe(rw::Atomic *atomic)
|
||||
{
|
||||
atomic->pipeline = vehiclePipe;
|
||||
}
|
||||
|
||||
void
|
||||
AttachVehiclePipe(rw::Clump *clump)
|
||||
{
|
||||
FORLIST(lnk, clump->atomics)
|
||||
AttachVehiclePipe(rw::Atomic::fromClump(lnk));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Neo World pipe
|
||||
*/
|
||||
|
||||
float LightmapMult = 1.0f;
|
||||
InterpolatedFloat WorldLightmapBlend(1.0f);
|
||||
rw::ObjPipeline *worldPipe;
|
||||
|
||||
void
|
||||
AttachWorldPipe(rw::Atomic *atomic)
|
||||
{
|
||||
atomic->pipeline = worldPipe;
|
||||
}
|
||||
|
||||
void
|
||||
AttachWorldPipe(rw::Clump *clump)
|
||||
{
|
||||
FORLIST(lnk, clump->atomics)
|
||||
AttachWorldPipe(rw::Atomic::fromClump(lnk));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Neo Gloss pipe
|
||||
*/
|
||||
|
||||
float GlossMult = 1.0f;
|
||||
rw::ObjPipeline *glossPipe;
|
||||
|
||||
rw::Texture*
|
||||
GetGlossTex(rw::Material *mat)
|
||||
{
|
||||
if(neoTxd == nil)
|
||||
return nil;
|
||||
CustomMatExt *ext = GetCustomMatExt(mat);
|
||||
if(!ext->haveGloss){
|
||||
char glossname[128];
|
||||
strcpy(glossname, mat->texture->name);
|
||||
strcat(glossname, "_gloss");
|
||||
ext->glossTex = neoTxd->find(glossname);
|
||||
ext->haveGloss = true;
|
||||
}
|
||||
return ext->glossTex;
|
||||
}
|
||||
|
||||
void
|
||||
AttachGlossPipe(rw::Atomic *atomic)
|
||||
{
|
||||
atomic->pipeline = glossPipe;
|
||||
}
|
||||
|
||||
void
|
||||
AttachGlossPipe(rw::Clump *clump)
|
||||
{
|
||||
FORLIST(lnk, clump->atomics)
|
||||
AttachWorldPipe(rw::Atomic::fromClump(lnk));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Neo Rim pipes
|
||||
*/
|
||||
|
||||
float RimlightMult = 1.0f;
|
||||
InterpolatedColor RampStart(Color(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
InterpolatedColor RampEnd(Color(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
InterpolatedFloat Offset(0.5f);
|
||||
InterpolatedFloat Scale(1.5f);
|
||||
InterpolatedFloat Scaling(2.0f);
|
||||
rw::ObjPipeline *rimPipe;
|
||||
rw::ObjPipeline *rimSkinPipe;
|
||||
|
||||
void
|
||||
AttachRimPipe(rw::Atomic *atomic)
|
||||
{
|
||||
if(rw::Skin::get(atomic->geometry))
|
||||
atomic->pipeline = rimSkinPipe;
|
||||
else
|
||||
atomic->pipeline = rimPipe;
|
||||
}
|
||||
|
||||
void
|
||||
AttachRimPipe(rw::Clump *clump)
|
||||
{
|
||||
FORLIST(lnk, clump->atomics)
|
||||
AttachRimPipe(rw::Atomic::fromClump(lnk));
|
||||
}
|
||||
|
||||
/*
|
||||
* High level stuff
|
||||
*/
|
||||
|
||||
void
|
||||
CustomPipeInit(void)
|
||||
{
|
||||
RwStream *stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "neo/neo.txd");
|
||||
if(stream == nil)
|
||||
printf("Error: couldn't open 'neo/neo.txd'\n");
|
||||
else{
|
||||
if(RwStreamFindChunk(stream, rwID_TEXDICTIONARY, nil, nil))
|
||||
neoTxd = RwTexDictionaryGtaStreamRead(stream);
|
||||
RwStreamClose(stream, nil);
|
||||
}
|
||||
|
||||
EnvMapInit();
|
||||
|
||||
CreateVehiclePipe();
|
||||
CreateWorldPipe();
|
||||
CreateGlossPipe();
|
||||
CreateRimLightPipes();
|
||||
}
|
||||
|
||||
void
|
||||
CustomPipeShutdown(void)
|
||||
{
|
||||
DestroyVehiclePipe();
|
||||
DestroyWorldPipe();
|
||||
DestroyGlossPipe();
|
||||
DestroyRimLightPipes();
|
||||
|
||||
EnvMapShutdown();
|
||||
|
||||
if(neoTxd){
|
||||
neoTxd->destroy();
|
||||
neoTxd = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CustomPipeRegister(void)
|
||||
{
|
||||
#ifdef RW_OPENGL
|
||||
CustomPipeRegisterGL();
|
||||
#endif
|
||||
|
||||
CustomMatOffset = rw::Material::registerPlugin(sizeof(CustomMatExt), MAKECHUNKID(rwVENDORID_ROCKSTAR, 0x80),
|
||||
CustomMatCtor, nil, CustomMatCopy);
|
||||
}
|
||||
|
||||
|
||||
// Load textures from generic as fallback
|
||||
|
||||
rw::TexDictionary *genericTxd;
|
||||
rw::Texture *(*defaultFindCB)(const char *name);
|
||||
|
||||
static rw::Texture*
|
||||
customFindCB(const char *name)
|
||||
{
|
||||
rw::Texture *res = defaultFindCB(name);
|
||||
if(res == nil)
|
||||
res = genericTxd->find(name);
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
SetTxdFindCallback(void)
|
||||
{
|
||||
int slot = CTxdStore::FindTxdSlot("generic");
|
||||
CTxdStore::AddRef(slot);
|
||||
// TODO: function for this
|
||||
genericTxd = CTxdStore::GetSlot(slot)->texDict;
|
||||
assert(genericTxd);
|
||||
if(defaultFindCB == nil)
|
||||
defaultFindCB = rw::Texture::findCB;
|
||||
rw::Texture::findCB = customFindCB;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue