neo screen droplets

This commit is contained in:
aap 2020-11-19 19:07:32 +01:00
parent 8963cbcb7c
commit 07fe099b4e
21 changed files with 1034 additions and 8 deletions

View File

@ -309,7 +309,10 @@ project "reVC"
linkoptions "/SAFESEH:NO"
characterset ("MBCS")
targetextension ".exe"
staticruntime "on"
if(_OPTIONS["with-librw"]) then
-- external librw is dynamic
staticruntime "on"
end
filter "platforms:win*glfw*"
staticruntime "off"

View File

@ -29,6 +29,7 @@
#include "ColStore.h"
#include "Automobile.h"
#include "MBlur.h"
#include "screendroplets.h"
uint8 CGameLogic::ActivePlayers;
uint8 CGameLogic::ShortCutState;
@ -153,6 +154,9 @@ CGameLogic::Update()
}
}
CEventList::Initialise();
#ifdef SCREEN_DROPLETS
ScreenDroplets::Initialise();
#endif
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
@ -259,6 +263,9 @@ CGameLogic::Update()
}
}
CEventList::Initialise();
#ifdef SCREEN_DROPLETS
ScreenDroplets::Initialise();
#endif
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
@ -311,6 +318,9 @@ CGameLogic::Update()
}
}
CEventList::Initialise();
#ifdef SCREEN_DROPLETS
ScreenDroplets::Initialise();
#endif
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);

View File

@ -93,6 +93,7 @@
#include "WaterCreatures.h"
#include "postfx.h"
#include "custompipes.h"
#include "screendroplets.h"
eLevelName CGame::currLevel;
int32 CGame::currArea;
@ -401,6 +402,9 @@ bool CGame::Initialise(const char* datFile)
CPed::Initialise();
CRouteNode::Initialise();
CEventList::Initialise();
#ifdef SCREEN_DROPLETS
ScreenDroplets::Initialise();
#endif
LoadingScreen("Loading the Game", "Find big buildings", nil);
CRenderer::Init();
LoadingScreen("Loading the Game", "Setup game variables", nil);
@ -568,6 +572,9 @@ void CGame::ReInitGameObjectVariables(void)
currArea = AREA_MAIN_MAP;
CPed::Initialise();
CEventList::Initialise();
#ifdef SCREEN_DROPLETS
ScreenDroplets::Initialise();
#endif
CWeapon::InitialiseWeapons();
CPopulation::Initialise();

View File

@ -246,10 +246,18 @@ enum Config {
#ifdef LIBRW
//#define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur)
//#define EXTENDED_PIPELINES // custom render pipelines (includes Neo)
//#define SCREEN_DROPLETS // neo water droplets
//#define NEW_RENDERER // leeds-like world rendering, needs librw
#endif
//#define MULTISAMPLING // adds MSAA option TODO
#ifndef EXTENDED_COLOURFILTER
#undef SCREEN_DROPLETS // we need the front- (or back-)buffer for this effect
#endif
#ifndef EXTENDED_PIPELINES
#undef SCREEN_DROPLETS // we need neo.txd
#endif
#ifdef LIBRW
// these are not supported with librw yet
# undef MULTISAMPLING

View File

@ -68,7 +68,9 @@
#include "Clock.h"
#include "Occlusion.h"
#include "Ropes.h"
#include "postfx.h"
#include "custompipes.h"
#include "screendroplets.h"
GlobalScene Scene;
@ -401,6 +403,9 @@ Initialise3D(void *param)
bool ret = CGame::InitialiseRenderWare();
#ifdef EXTENDED_PIPELINES
CustomPipes::CustomPipeInit(); // need Scene.world for this
#endif
#ifdef SCREEN_DROPLETS
ScreenDroplets::InitDraw();
#endif
return ret;
}
@ -411,6 +416,9 @@ Initialise3D(void *param)
static void
Terminate3D(void)
{
#ifdef SCREEN_DROPLETS
ScreenDroplets::Shutdown();
#endif
#ifdef EXTENDED_PIPELINES
CustomPipes::CustomPipeShutdown();
#endif
@ -1246,10 +1254,17 @@ Idle(void *arg)
RenderDebugShit();
RenderEffects();
tbStartTimer(0, "RenderMotionBlur");
if((TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE) &&
TheCamera.m_ScreenReductionPercentage > 0.0f)
TheCamera.SetMotionBlurAlpha(150);
#ifdef SCREEN_DROPLETS
CPostFX::GetBackBuffer(Scene.camera);
ScreenDroplets::Process();
ScreenDroplets::Render();
#endif
tbStartTimer(0, "RenderMotionBlur");
TheCamera.RenderMotionBlur();
tbEndTimer("RenderMotionBlur");

View File

@ -44,7 +44,7 @@ CustomMatCopy(void *dst, void *src, int32, int32)
static rw::TexDictionary *neoTxd;
rw::TexDictionary *neoTxd;
bool bRenderingEnvMap;
int32 EnvMapSize = 128;

View File

@ -6,6 +6,7 @@
namespace CustomPipes {
extern rw::TexDictionary *neoTxd;
struct CustomMatExt
{

View File

@ -132,6 +132,8 @@ vehicleRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)
inst++;
}
d3d::setTexture(1, nil);
SetRenderState(SRCBLEND, BLENDSRCALPHA);
}

View File

@ -133,6 +133,8 @@ vehicleRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
inst++;
}
setTexture(1, nil);
SetRenderState(SRCBLEND, BLENDSRCALPHA);
#ifndef RW_GL_USE_VAOS

View File

@ -375,6 +375,14 @@ CPostFX::NeedFrontBuffer(int32 type)
return false;
}
void
CPostFX::GetBackBuffer(RwCamera *cam)
{
RwRasterPushContext(pBackBuffer);
RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);
RwRasterPopContext();
}
void
CPostFX::Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha)
{
@ -391,11 +399,8 @@ CPostFX::Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blu
blur = AvgAlpha;
}
if(NeedBackBuffer()){
RwRasterPushContext(pBackBuffer);
RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);
RwRasterPopContext();
}
if(NeedBackBuffer())
GetBackBuffer(cam);
DefinedState();

View File

@ -39,6 +39,7 @@ public:
static void SmoothColor(uint32 red, uint32 green, uint32 blue, uint32 alpha);
static bool NeedBackBuffer(void);
static bool NeedFrontBuffer(int32 type);
static void GetBackBuffer(RwCamera *cam);
static bool UseBlurColours(void) { return EffectSwitch != POSTFX_SIMPLE; }
};

View File

@ -0,0 +1,791 @@
#define WITH_D3D
#include "common.h"
#ifdef SCREEN_DROPLETS
#ifndef LIBRW
#error "Need librw for SCREEN_DROPLETS"
#endif
#include "General.h"
#include "Main.h"
#include "RwHelper.h"
#include "Main.h"
#include "Timer.h"
#include "Camera.h"
#include "ZoneCull.h"
#include "Weather.h"
#include "ParticleObject.h"
#include "Pad.h"
#include "RenderBuffer.h"
#include "custompipes.h"
#include "postfx.h"
#include "screendroplets.h"
// for 640
#define MAXSIZE 15
#define MINSIZE 4
int ScreenDroplets::ms_initialised;
RwTexture *ScreenDroplets::ms_maskTex;
RwTexture *ScreenDroplets::ms_screenTex;
bool ScreenDroplets::ms_enabled = true;
bool ScreenDroplets::ms_movingEnabled = true;
ScreenDroplets::ScreenDrop ScreenDroplets::ms_drops[ScreenDroplets::MAXDROPS];
int ScreenDroplets::ms_numDrops;
ScreenDroplets::ScreenDropMoving ScreenDroplets::ms_dropsMoving[ScreenDroplets::MAXDROPSMOVING];
int ScreenDroplets::ms_numDropsMoving;
CVector ScreenDroplets::ms_prevCamUp;
CVector ScreenDroplets::ms_prevCamPos;
CVector ScreenDroplets::ms_camMoveDelta;
float ScreenDroplets::ms_camMoveDist;
CVector ScreenDroplets::ms_screenMoveDelta;
float ScreenDroplets::ms_screenMoveDist;
float ScreenDroplets::ms_camUpAngle;
int ScreenDroplets::ms_splashDuration;
CParticleObject *ScreenDroplets::ms_splashObject;
struct Im2DVertexUV2 : rw::RWDEVICE::Im2DVertex
{
rw::float32 u2, v2;
};
#ifdef RW_D3D9
static void *screenDroplet_PS;
#endif
#ifdef RW_GL3
static rw::gl3::Shader *screenDroplet;
#endif
// platform specific
static void openim2d_uv2(void);
static void closeim2d_uv2(void);
static void RenderIndexedPrimitive_UV2(RwPrimitiveType primType, Im2DVertexUV2 *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices);
static Im2DVertexUV2 VertexBuffer[TEMPBUFFERVERTSIZE];
void
ScreenDroplets::Initialise(void)
{
Clear();
ms_splashDuration = -1;
ms_splashObject = nil;
}
void
ScreenDroplets::InitDraw(void)
{
if(CustomPipes::neoTxd)
ms_maskTex = CustomPipes::neoTxd->find("dropmask");
ms_screenTex = RwTextureCreate(nil);
RwTextureSetFilterMode(ms_screenTex, rwFILTERLINEAR);
openim2d_uv2();
#ifdef RW_D3D9
#include "shaders/screenDroplet_PS.inc"
screenDroplet_PS = rw::d3d::createPixelShader(screenDroplet_PS_cso);
#endif
#ifdef RW_GL3
using namespace rw::gl3;
{
#include "shaders/im2d_UV2_gl.inc"
#include "shaders/screenDroplet_fs_gl.inc"
const char *vs[] = { shaderDecl, header_vert_src, im2d_UV2_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, screenDroplet_frag_src, nil };
screenDroplet = Shader::create(vs, fs);
assert(screenDroplet);
}
#endif
ms_initialised = 1;
}
void
ScreenDroplets::Shutdown(void)
{
if(ms_maskTex){
RwTextureDestroy(ms_maskTex);
ms_maskTex = nil;
}
if(ms_screenTex){
RwTextureSetRaster(ms_screenTex, nil);
RwTextureDestroy(ms_screenTex);
ms_screenTex = nil;
}
#ifdef RW_D3D9
if(screenDroplet_PS){
rw::d3d::destroyPixelShader(screenDroplet_PS);
screenDroplet_PS = nil;
}
#endif
#ifdef RW_GL3
if(screenDroplet){
screenDroplet->destroy();
screenDroplet = nil;
}
#endif
closeim2d_uv2();
}
void
ScreenDroplets::Process(void)
{
ProcessCameraMovement();
SprayDrops();
ProcessMoving();
Fade();
}
static void
FlushBuffer(void)
{
if(TempBufferIndicesStored){
RenderIndexedPrimitive_UV2(rwPRIMTYPETRILIST,
VertexBuffer, TempBufferVerticesStored,
TempBufferRenderIndexList, TempBufferIndicesStored);
TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0;
}
}
static int
StartStoring(int numIndices, int numVertices, RwImVertexIndex **indexStart, Im2DVertexUV2 **vertexStart)
{
if(TempBufferIndicesStored + numIndices >= TEMPBUFFERINDEXSIZE ||
TempBufferVerticesStored + numVertices >= TEMPBUFFERVERTSIZE)
FlushBuffer();
*indexStart = &TempBufferRenderIndexList[TempBufferIndicesStored];
*vertexStart = &VertexBuffer[TempBufferVerticesStored];
int vertOffset = TempBufferVerticesStored;
TempBufferIndicesStored += numIndices;
TempBufferVerticesStored += numVertices;
return vertOffset;
}
void
ScreenDroplets::Render(void)
{
ScreenDrop *drop;
DefinedState();
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(ms_maskTex));
RwRenderStateSet(rwRENDERSTATEFOGENABLE, FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwTextureSetRaster(ms_screenTex, CPostFX::pBackBuffer);
#ifdef RW_D3D9
rw::d3d::im2dOverridePS = screenDroplet_PS;
rw::d3d::setTexture(1, ms_screenTex);
#endif
#ifdef RW_GL3
rw::gl3::im2dOverrideShader = screenDroplet;
rw::gl3::setTexture(1, ms_screenTex);
#endif
RenderBuffer::ClearRenderBuffer();
for(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++)
if(drop->active)
AddToRenderList(drop);
FlushBuffer();
#ifdef RW_D3D9
rw::d3d::im2dOverridePS = nil;
rw::d3d::setTexture(1, nil);
#endif
#ifdef RW_GL3
rw::gl3::im2dOverrideShader = nil;
rw::gl3::setTexture(1, nil);
#endif
RwRenderStateSet(rwRENDERSTATEFOGENABLE, FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, FALSE);
}
void
ScreenDroplets::AddToRenderList(ScreenDroplets::ScreenDrop *drop)
{
static float xy[] = {
-1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
1.0f, -1.0f
};
static float uv[] = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
int i;
RwImVertexIndex *indices;
Im2DVertexUV2 *verts;
int first = StartStoring(6, 4, &indices, &verts);
float scale = 0.5f*SCREEN_SCALE_X(drop->size);
float screenz = RwIm2DGetNearScreenZ();
float z = RwCameraGetNearClipPlane(Scene.camera);
float recipz = 1.0f/z;
float magSize = SCREEN_SCALE_Y(drop->magnification*(300.0f-40.0f) + 40.0f);
float ul = drop->x - magSize;
float vt = drop->y - magSize;
float ur = drop->x + magSize;
float vb = drop->y + magSize;
ul = Max(ul, 0.0f)/RwRasterGetWidth(CPostFX::pBackBuffer);
vt = Max(vt, 0.0f)/RwRasterGetHeight(CPostFX::pBackBuffer);
ur = Min(ur, SCREEN_WIDTH)/RwRasterGetWidth(CPostFX::pBackBuffer);
vb = Min(vb, SCREEN_HEIGHT)/RwRasterGetHeight(CPostFX::pBackBuffer);
for(i = 0; i < 4; i++){
RwIm2DVertexSetScreenX(&verts[i], drop->x + xy[i*2]*scale);
RwIm2DVertexSetScreenY(&verts[i], drop->y + xy[i*2+1]*scale);
RwIm2DVertexSetScreenZ(&verts[i], screenz);
RwIm2DVertexSetCameraZ(&verts[i], z);
RwIm2DVertexSetRecipCameraZ(&verts[i], recipz);
RwIm2DVertexSetIntRGBA(&verts[i], drop->color.r, drop->color.g, drop->color.b, drop->color.a);
RwIm2DVertexSetU(&verts[i], uv[i*2], recipz);
RwIm2DVertexSetV(&verts[i], uv[i*2+1], recipz);
verts[i].u2 = i < 2 ? ul : ur;
verts[i].v2 = i % 3 ? vt : vb;
}
indices[0] = first + 0;
indices[1] = first + 1;
indices[2] = first + 2;
indices[3] = first + 2;
indices[4] = first + 3;
indices[5] = first + 0;
}
void
ScreenDroplets::Clear(void)
{
ScreenDrop *drop;
for(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++)
drop->active = false;
ms_numDrops = 0;
}
ScreenDroplets::ScreenDrop*
ScreenDroplets::NewDrop(float x, float y, float size, float lifetime, bool fades, int r, int g, int b)
{
ScreenDrop *drop;
int i;
for(i = 0, drop = ms_drops; i < MAXDROPS; i++, drop++)
if(!ms_drops[i].active)
goto found;
return nil;
found:
ms_numDrops++;
drop->x = x;
drop->y = y;
drop->size = size;
drop->magnification = (MAXSIZE - size + 1.0f) / (MAXSIZE - MINSIZE + 1.0f);
drop->fades = fades;
drop->active = true;
drop->color.r = r;
drop->color.g = g;
drop->color.b = b;
drop->color.a = 255;
drop->time = 0.0f;
drop->lifetime = lifetime;
return drop;
}
void
ScreenDroplets::SetMoving(ScreenDroplets::ScreenDrop *drop)
{
ScreenDropMoving *moving;
for(moving = ms_dropsMoving; moving < &ms_dropsMoving[MAXDROPSMOVING]; moving++)
if(moving->drop == nil)
goto found;
return;
found:
ms_numDropsMoving++;
moving->drop = drop;
moving->dist = 0.0f;
}
void
ScreenDroplets::FillScreen(int n)
{
float x, y, size;
ScreenDrop *drop;
if(!ms_initialised)
return;
ms_numDrops = 0;
for(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++){
drop->active = false;
if(drop < &ms_drops[n]){
x = CGeneral::GetRandomNumber() % (int)SCREEN_WIDTH;
y = CGeneral::GetRandomNumber() % (int)SCREEN_HEIGHT;
size = CGeneral::GetRandomNumberInRange(MINSIZE, MAXSIZE);
NewDrop(x, y, size, 2000.0f, true);
}
}
}
void
ScreenDroplets::FillScreenMoving(float amount, bool isBlood)
{
int n = (ms_screenMoveDelta.z > 5.0f ? 1.5f : 1.0f)*amount*20.0f;
float x, y, size;
ScreenDrop *drop;
while(n--)
if(ms_numDrops < MAXDROPS && ms_numDropsMoving < MAXDROPSMOVING){
x = CGeneral::GetRandomNumber() % (int)SCREEN_WIDTH;
y = CGeneral::GetRandomNumber() % (int)SCREEN_HEIGHT;
size = CGeneral::GetRandomNumberInRange(MINSIZE, MAXSIZE);
drop = nil;
if(isBlood)
drop = NewDrop(x, y, size, 2000.0f, true, 255, 0, 0);
else
drop = NewDrop(x, y, size, 2000.0f, true);
if(drop)
SetMoving(drop);
}
}
void
ScreenDroplets::RegisterSplash(CParticleObject *pobj)
{
CVector dist = pobj->GetPosition() - ms_prevCamPos;
if(dist.MagnitudeSqr() < 20.0f){
ms_splashDuration = 14;
ms_splashObject = pobj;
}
}
void
ScreenDroplets::ProcessCameraMovement(void)
{
RwMatrix *camMat = RwFrameGetMatrix(RwCameraGetFrame(Scene.camera));
CVector camPos = camMat->pos;
CVector camUp = camMat->at;
ms_camMoveDelta = camPos - ms_prevCamPos;
ms_camMoveDist = ms_camMoveDelta.Magnitude();
ms_prevCamUp = camUp;
ms_prevCamPos = camPos;
ms_screenMoveDelta.x = -RwV3dDotProduct(&camMat->right, (RwV3d*)&ms_camMoveDelta);
ms_screenMoveDelta.y = RwV3dDotProduct(&camMat->up, (RwV3d*)&ms_camMoveDelta);
ms_screenMoveDelta.z = RwV3dDotProduct(&camMat->at, (RwV3d*)&ms_camMoveDelta);
ms_screenMoveDelta *= 10.0f;
ms_screenMoveDist = ms_screenMoveDelta.Magnitude2D();
uint16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;
bool isTopDown = mode == CCam::MODE_TOPDOWN || mode == CCam::MODE_GTACLASSIC || mode == CCam::MODE_TOP_DOWN_PED;
bool isLookingInDirection = CPad::GetPad(0)->GetLookBehindForCar() || CPad::GetPad(0)->GetLookLeft() || CPad::GetPad(0)->GetLookRight();
ms_enabled = !isTopDown && !isLookingInDirection;
ms_movingEnabled = !isTopDown && !isLookingInDirection;
// 0 when looking stright up, 180 when looking up or down
ms_camUpAngle = RADTODEG(Acos(clamp(camUp.z, -1.0f, 1.0f)));
}
void
ScreenDroplets::SprayDrops(void)
{
bool noRain = CCullZones::PlayerNoRain() || CCullZones::CamNoRain();
if(!noRain && CWeather::Rain > 0.0f && ms_enabled){
// 180 when looking stright up, 0 when looking up or down
float angle = 180.0f - ms_camUpAngle;
angle = Max(angle, 40.0f); // want at least some rain
FillScreenMoving((angle - 40.0f) / 150.0f * CWeather::Rain * 0.5f);
}
int i;
for(i = 0; i < MAX_AUDIOHYDRANTS; i++){
CAudioHydrant *hyd = CAudioHydrant::Get(i);
if (hyd->pParticleObject){
CVector dist = hyd->pParticleObject->GetPosition() - ms_prevCamPos;
if(dist.MagnitudeSqr() > 40.0f ||
DotProduct(dist, ms_prevCamUp) < 0.0f) continue;
FillScreenMoving(1.0f);
}
}
static int ndrops[] = {
125, 250, 500, 1000, 1000,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if(ms_splashDuration >= 0){
if(ms_numDrops < MAXDROPS) {
float numDropMult = 1.0f;
if(ms_splashObject){
float dist = (ms_splashObject->GetPosition() - ms_prevCamPos).Magnitude();
numDropMult = 1.0f - (dist - 5.0f)/15.0f;
if(numDropMult < 0) numDropMult = 0.0f; // fix
}
int n = ndrops[ms_splashDuration] * numDropMult;
while(n--)
if(ms_numDrops < MAXDROPS){
float x = CGeneral::GetRandomNumber() % (int)SCREEN_WIDTH;
float y = CGeneral::GetRandomNumber() % (int)SCREEN_HEIGHT;
float size = CGeneral::GetRandomNumberInRange(MINSIZE, MAXSIZE);
NewDrop(x, y, size, 10000.0f, false);
}
}
ms_splashDuration--;
}
}
void
ScreenDroplets::NewTrace(ScreenDroplets::ScreenDropMoving *moving)
{
if(ms_numDrops < MAXDROPS){
moving->dist = 0.0f;
NewDrop(moving->drop->x, moving->drop->y, MINSIZE, 500.0f, true,
moving->drop->color.r, moving->drop->color.g, moving->drop->color.b);
}
}
void
ScreenDroplets::MoveDrop(ScreenDroplets::ScreenDropMoving *moving)
{
ScreenDrop *drop = moving->drop;
if(!ms_movingEnabled)
return;
if(!drop->active){
moving->drop = nil;
ms_numDropsMoving--;
return;
}
if(ms_screenMoveDelta.z > 0.0f && ms_camMoveDist > 0.3f){
if(ms_screenMoveDist > 0.5f && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON){
// movement when camera turns
moving->dist += ms_screenMoveDist;
if(moving->dist > 20.0f && drop->color.a > 100)
NewTrace(moving);
drop->x -= ms_screenMoveDelta.x;
drop->y += ms_screenMoveDelta.y;
}else{
// movement out of center
float d = ms_screenMoveDelta.z*0.2f;
float dx, dy, sum;
dx = drop->x - SCREEN_WIDTH*0.5f + ms_screenMoveDelta.x;
if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON)
dy = drop->y - SCREEN_HEIGHT*1.2f - ms_screenMoveDelta.y;
else
dy = drop->y - SCREEN_HEIGHT*0.5f - ms_screenMoveDelta.y;
sum = fabs(dx) + fabs(dy);
if(sum > 0.001f){
dx /= sum;
dy /= sum;
}
moving->dist += d;
if(moving->dist > 20.0f && drop->color.a > 100)
NewTrace(moving);
drop->x += dx * d;
drop->y += dy * d;
}
if(drop->x < 0.0f || drop->y < 0.0f ||
drop->x > SCREEN_WIDTH || drop->y > SCREEN_HEIGHT){
moving->drop = nil;
ms_numDropsMoving--;
}
}
}
void
ScreenDroplets::ProcessMoving(void)
{
ScreenDropMoving *moving;
if(!ms_movingEnabled)
return;
for(moving = ms_dropsMoving; moving < &ms_dropsMoving[MAXDROPSMOVING]; moving++)
if(moving->drop)
MoveDrop(moving);
}
void
ScreenDroplets::Fade(void)
{
ScreenDrop *drop;
for(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++)
if(drop->active)
drop->Fade();
}
void
ScreenDroplets::ScreenDrop::Fade(void)
{
int delta = CTimer::GetTimeStepInMilliseconds();
time += delta;
if(time < lifetime){
color.a = 255 - time/lifetime*255;
}else if(fades){
ScreenDroplets::ms_numDrops--;
active = false;
}
}
/*
* Im2D with two uv coors
*/
#ifdef RW_D3D9
// stolen from RW, not in a public header
namespace rw {
namespace d3d {
void addDynamicVB(uint32 length, uint32 fvf, IDirect3DVertexBuffer9 **buf); // NB: don't share this pointer
void removeDynamicVB(IDirect3DVertexBuffer9 **buf);
void addDynamicIB(uint32 length, IDirect3DIndexBuffer9 **buf); // NB: don't share this pointer
void removeDynamicIB(IDirect3DIndexBuffer9 **buf);
}
}
// different than im2d
#define NUMINDICES 1024
#define NUMVERTICES 1024
static int primTypeMap[] = {
D3DPT_POINTLIST, // invalid
D3DPT_LINELIST,
D3DPT_LINESTRIP,
D3DPT_TRIANGLELIST,
D3DPT_TRIANGLESTRIP,
D3DPT_TRIANGLEFAN,
D3DPT_POINTLIST, // actually not supported!
};
// end of stolen stuff
static IDirect3DVertexDeclaration9 *im2ddecl_uv2;
static IDirect3DVertexBuffer9 *im2dvertbuf_uv2;
static IDirect3DIndexBuffer9 *im2dindbuf_uv2;
void
openim2d_uv2(void)
{
using namespace rw;
using namespace d3d;
D3DVERTEXELEMENT9 elements[5] = {
{ 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0 },
{ 0, offsetof(Im2DVertexUV2, color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
{ 0, offsetof(Im2DVertexUV2, u), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
{ 0, offsetof(Im2DVertexUV2, u2), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
D3DDECL_END()
};
assert(im2ddecl_uv2 == nil);
im2ddecl_uv2 = (IDirect3DVertexDeclaration9*)d3d9::createVertexDeclaration((d3d9::VertexElement*)elements);
assert(im2ddecl_uv2);
assert(im2dvertbuf_uv2 == nil);
im2dvertbuf_uv2 = (IDirect3DVertexBuffer9*)createVertexBuffer(NUMVERTICES*sizeof(Im2DVertexUV2), 0, true);
assert(im2dvertbuf_uv2);
addDynamicVB(NUMVERTICES*sizeof(Im2DVertexUV2), 0, &im2dvertbuf_uv2);
assert(im2dindbuf_uv2 == nil);
im2dindbuf_uv2 = (IDirect3DIndexBuffer9*)createIndexBuffer(NUMINDICES*sizeof(rw::uint16), true);
assert(im2dindbuf_uv2);
addDynamicIB(NUMINDICES*sizeof(rw::uint16), &im2dindbuf_uv2);
}
void
closeim2d_uv2(void)
{
using namespace rw;
using namespace d3d;
d3d9::destroyVertexDeclaration(im2ddecl_uv2);
im2ddecl_uv2 = nil;
removeDynamicVB(&im2dvertbuf_uv2);
destroyVertexBuffer(im2dvertbuf_uv2);
im2dvertbuf_uv2 = nil;
removeDynamicIB(&im2dindbuf_uv2);
destroyIndexBuffer(im2dindbuf_uv2);
im2dindbuf_uv2 = nil;
}
void
RenderIndexedPrimitive_UV2(RwPrimitiveType primType, Im2DVertexUV2 *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices)
{
using namespace rw;
using namespace d3d;
if(numVertices > NUMVERTICES ||
numIndices > NUMINDICES){
// TODO: error
return;
}
rw::uint16 *lockedindices = lockIndices(im2dindbuf_uv2, 0, numIndices*sizeof(rw::uint16), D3DLOCK_DISCARD);
memcpy(lockedindices, indices, numIndices*sizeof(rw::uint16));
unlockIndices(im2dindbuf_uv2);
rw::uint8 *lockedvertices = lockVertices(im2dvertbuf_uv2, 0, numVertices*sizeof(Im2DVertexUV2), D3DLOCK_DISCARD);
memcpy(lockedvertices, vertices, numVertices*sizeof(Im2DVertexUV2));
unlockVertices(im2dvertbuf_uv2);
setStreamSource(0, im2dvertbuf_uv2, 0, sizeof(Im2DVertexUV2));
setIndices(im2dindbuf_uv2);
setVertexDeclaration(im2ddecl_uv2);
if(im2dOverridePS)
setPixelShader(im2dOverridePS);
else if(engine->device.getRenderState(TEXTURERASTER))
setPixelShader(im2d_tex_PS);
else
setPixelShader(im2d_PS);
d3d::flushCache();
rw::uint32 primCount = 0;
switch(primType){
case PRIMTYPELINELIST:
primCount = numIndices/2;
break;
case PRIMTYPEPOLYLINE:
primCount = numIndices-1;
break;
case PRIMTYPETRILIST:
primCount = numIndices/3;
break;
case PRIMTYPETRISTRIP:
primCount = numIndices-2;
break;
case PRIMTYPETRIFAN:
primCount = numIndices-2;
break;
case PRIMTYPEPOINTLIST:
primCount = numIndices;
break;
}
d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0,
0, numVertices,
0, primCount);
}
#endif
#ifdef RW_GL3
// different than im2d
#define NUMINDICES 1024
#define NUMVERTICES 1024
static rw::gl3::AttribDesc im2d_UV2_attribDesc[4] = {
{ rw::gl3::ATTRIB_POS, GL_FLOAT, GL_FALSE, 4,
sizeof(Im2DVertexUV2), 0 },
{ rw::gl3::ATTRIB_COLOR, GL_UNSIGNED_BYTE, GL_TRUE, 4,
sizeof(Im2DVertexUV2), offsetof(Im2DVertexUV2, r) },
{ rw::gl3::ATTRIB_TEXCOORDS0, GL_FLOAT, GL_FALSE, 2,
sizeof(Im2DVertexUV2), offsetof(Im2DVertexUV2, u) },
{ rw::gl3::ATTRIB_TEXCOORDS1, GL_FLOAT, GL_FALSE, 2,
sizeof(Im2DVertexUV2), offsetof(Im2DVertexUV2, u2) }
};
static int primTypeMap[] = {
GL_POINTS, // invalid
GL_LINES,
GL_LINE_STRIP,
GL_TRIANGLES,
GL_TRIANGLE_STRIP,
GL_TRIANGLE_FAN,
GL_POINTS
};
static int32 u_xform;
uint32 im2D_UV2_Vbo, im2D_UV2_Ibo;
#ifdef RW_GL_USE_VAOS
uint32 im2D_UV2_Vao;
#endif
void
openim2d_uv2(void)
{
u_xform = rw::gl3::registerUniform("u_xform"); // this doesn't add a new one, so it's safe
glGenBuffers(1, &im2D_UV2_Ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2D_UV2_Ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, NUMINDICES*2, nil, GL_STREAM_DRAW);
glGenBuffers(1, &im2D_UV2_Vbo);
glBindBuffer(GL_ARRAY_BUFFER, im2D_UV2_Vbo);
glBufferData(GL_ARRAY_BUFFER, NUMVERTICES*sizeof(Im2DVertexUV2), nil, GL_STREAM_DRAW);
#ifdef RW_GL_USE_VAOS
glGenVertexArrays(1, &im2D_UV2_Vao);
glBindVertexArray(im2D_UV2_Vao);
setAttribPointers(im2d_UV2_attribDesc, 4);
#endif
}
void
closeim2d_uv2(void)
{
glDeleteBuffers(1, &im2D_UV2_Ibo);
glDeleteBuffers(1, &im2D_UV2_Vbo);
#ifdef RW_GL_USE_VAOS
glDeleteVertexArrays(1, &im2D_UV2_Vao);
#endif
}
void
RenderIndexedPrimitive_UV2(RwPrimitiveType primType, Im2DVertexUV2 *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices)
{
using namespace rw;
using namespace gl3;
GLfloat xform[4];
Camera *cam;
cam = (Camera*)engine->currentCamera;
#ifdef RW_GL_USE_VAOS
glBindVertexArray(im2D_UV2_Vao);
#endif
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2D_UV2_Ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, NUMINDICES*2, nil, GL_STREAM_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, numIndices*2, indices);
glBindBuffer(GL_ARRAY_BUFFER, im2D_UV2_Vbo);
glBufferData(GL_ARRAY_BUFFER, NUMVERTICES*sizeof(Im2DVertexUV2), nil, GL_STREAM_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*sizeof(Im2DVertexUV2), vertices);
xform[0] = 2.0f/cam->frameBuffer->width;
xform[1] = -2.0f/cam->frameBuffer->height;
xform[2] = -1.0f;
xform[3] = 1.0f;
if(im2dOverrideShader)
im2dOverrideShader->use();
else
assert(0);//im2dShader->use();
#ifndef RW_GL_USE_VAOS
setAttribPointers(im2d_UV2_attribDesc, 4);
#endif
glUniform4fv(currentShader->uniformLocations[u_xform], 1, xform);
flushCache();
glDrawElements(primTypeMap[primType], numIndices,
GL_UNSIGNED_SHORT, nil);
#ifndef RW_GL_USE_VAOS
disableAttribPointers(im2d_UV2_attribDesc, 4);
#endif
}
#endif
#endif

View File

@ -0,0 +1,78 @@
#pragma once
#ifdef SCREEN_DROPLETS
class CParticleObject;
class ScreenDroplets
{
public:
enum {
MAXDROPS = 2000,
MAXDROPSMOVING = 700
};
class ScreenDrop
{
public:
float x, y, time; // shorts on xbox (short float?)
float size, magnification, lifetime; // "
CRGBA color;
bool active;
bool fades;
void Fade(void);
};
struct ScreenDropMoving
{
ScreenDrop *drop;
float dist;
};
static int ms_initialised;
static RwTexture *ms_maskTex;
static RwTexture *ms_screenTex;
static bool ms_enabled;
static bool ms_movingEnabled;
static ScreenDrop ms_drops[MAXDROPS];
static int ms_numDrops;
static ScreenDropMoving ms_dropsMoving[MAXDROPSMOVING];
static int ms_numDropsMoving;
static CVector ms_prevCamUp;
static CVector ms_prevCamPos;
static CVector ms_camMoveDelta;
static float ms_camMoveDist;
static CVector ms_screenMoveDelta;
static float ms_screenMoveDist;
static float ms_camUpAngle;
static int ms_splashDuration;
static CParticleObject *ms_splashObject;
static void Initialise(void);
static void InitDraw(void);
static void Shutdown(void);
static void Process(void);
static void Render(void);
static void AddToRenderList(ScreenDrop *drop);
static void Clear(void);
static ScreenDrop *NewDrop(float x, float y, float size, float lifetime, bool fades, int r = 255, int g = 255, int b = 255);
static void SetMoving(ScreenDroplets::ScreenDrop *drop);
static void FillScreen(int n);
static void FillScreenMoving(float amount, bool isBlood = false);
static void RegisterSplash(CParticleObject *pobj);
static void ProcessCameraMovement(void);
static void SprayDrops(void);
static void NewTrace(ScreenDroplets::ScreenDropMoving *moving);
static void MoveDrop(ScreenDropMoving *moving);
static void ProcessMoving(void);
static void Fade(void);
};
#endif

View File

@ -65,3 +65,13 @@ neoVehicle_fs_gl.inc: neoVehicle.frag
(echo 'const char *neoVehicle_frag_src =';\
sed 's/..*/"&\\n"/' neoVehicle.frag;\
echo ';') >neoVehicle_fs_gl.inc
im2d_UV2_gl.inc: im2d_UV2.vert
(echo 'const char *im2d_UV2_vert_src =';\
sed 's/..*/"&\\n"/' im2d_UV2.vert;\
echo ';') >im2d_UV2_gl.inc
screenDroplet_fs_gl.inc: screenDroplet.frag
(echo 'const char *screenDroplet_frag_src =';\
sed 's/..*/"&\\n"/' screenDroplet.frag;\
echo ';') >screenDroplet_fs_gl.inc

View File

@ -0,0 +1,21 @@
uniform vec4 u_xform;
VSIN(ATTRIB_POS) vec4 in_pos;
VSOUT vec4 v_color;
VSOUT vec2 v_tex0;
VSOUT vec2 v_tex1;
VSOUT float v_fog;
void
main(void)
{
gl_Position = in_pos;
gl_Position.w = 1.0;
gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;
v_fog = DoFog(gl_Position.z);
gl_Position.xyz *= gl_Position.w;
v_color = in_color;
v_tex0 = in_tex0;
v_tex1 = in_tex1;
}

View File

@ -0,0 +1,18 @@
uniform sampler2D tex0;
uniform sampler2D tex1;
FSIN vec4 v_color;
FSIN vec2 v_tex0;
FSIN vec2 v_tex1;
FSIN float v_fog;
void
main(void)
{
vec4 color;
color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));
color *= texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y));
FRAGCOLOR(color);
}

Binary file not shown.

View File

@ -0,0 +1,17 @@
struct VS_out {
float4 Position : POSITION;
float2 TexCoord0 : TEXCOORD0;
float2 TexCoord1 : TEXCOORD1;
float4 Color : COLOR0;
};
sampler2D tex0 : register(s0);
sampler2D tex1 : register(s1);
float4 main(VS_out input) : COLOR
{
float4 color = input.Color;
color *= tex2D(tex0, input.TexCoord0.xy);
color *= tex2D(tex1, input.TexCoord1.xy);
return color;
}

View File

@ -0,0 +1,29 @@
static unsigned char screenDroplet_PS_cso[] = {
0x00, 0x02, 0xff, 0xff, 0xfe, 0xff, 0x2c, 0x00, 0x43, 0x54, 0x41, 0x42,
0x1c, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff,
0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x74, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x01, 0x00, 0x02, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x5c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x06, 0x00,
0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x30,
0x00, 0xab, 0xab, 0xab, 0x04, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x31,
0x00, 0xab, 0xab, 0xab, 0x04, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5f, 0x32,
0x5f, 0x30, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68,
0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33,
0x31, 0x31, 0x31, 0x00, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80,
0x00, 0x00, 0x03, 0xb0, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80,
0x01, 0x00, 0x03, 0xb0, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80,
0x00, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90,
0x00, 0x08, 0x0f, 0xa0, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90,
0x01, 0x08, 0x0f, 0xa0, 0x42, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80,
0x00, 0x00, 0xe4, 0xb0, 0x00, 0x08, 0xe4, 0xa0, 0x42, 0x00, 0x00, 0x03,
0x01, 0x00, 0x0f, 0x80, 0x01, 0x00, 0xe4, 0xb0, 0x01, 0x08, 0xe4, 0xa0,
0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0xe4, 0x80,
0x00, 0x00, 0xe4, 0x90, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80,
0x01, 0x00, 0xe4, 0x80, 0x00, 0x00, 0xe4, 0x80, 0x01, 0x00, 0x00, 0x02,
0x00, 0x08, 0x0f, 0x80, 0x00, 0x00, 0xe4, 0x80, 0xff, 0xff, 0x00, 0x00
};

View File

@ -8,6 +8,7 @@
#include "Camera.h"
#include "Game.h"
#include "DMAudio.h"
#include "screendroplets.h"
CParticleObject gPObjectArray[MAX_PARTICLEOBJECTS];
@ -18,6 +19,8 @@ CParticleObject *CParticleObject::pUnusedListHead;
CAudioHydrant List[MAX_AUDIOHYDRANTS];
CAudioHydrant *CAudioHydrant::Get(int n) { return &List[n]; }
bool
CAudioHydrant::Add(CParticleObject *particleobject)
{
@ -246,6 +249,9 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe
pobj->m_nNumEffectCycles = 0;
pobj->m_nSkipFrames = 1;
pobj->m_nCreationChance = 0;
#ifdef SCREEN_DROPLETS
ScreenDroplets::RegisterSplash(pobj);
#endif
break;
}

View File

@ -107,4 +107,6 @@ public:
static bool Add (CParticleObject *particleobject);
static void Remove(CParticleObject *particleobject);
static CAudioHydrant *Get(int n); // for neo screen droplets
};