mirror of
https://gitlab.com/GaryOderNichts/re3-wiiu.git
synced 2024-11-25 10:36:53 +01:00
added CPointLights
This commit is contained in:
parent
92434f01f1
commit
c40c7acb96
@ -360,9 +360,11 @@ CTheZones::GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info)
|
||||
else{
|
||||
if(CClock::GetIsTimeInRange(19, 22)){
|
||||
n = (CClock::GetHours() - 19) / 3.0f;
|
||||
assert(n >= 0.0f && n <= 1.0f);
|
||||
d = n - 1.0f;
|
||||
}else{
|
||||
d = (CClock::GetHours() - 5) / 3.0f;
|
||||
assert(d >= 0.0f && d <= 1.0f);
|
||||
n = d - 1.0f;
|
||||
}
|
||||
info->carDensity = day->carDensity * d + night->carDensity * n;
|
||||
@ -399,6 +401,24 @@ CTheZones::GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info)
|
||||
info->pedGroup = day->pedGroup;
|
||||
else
|
||||
info->pedGroup = night->pedGroup;
|
||||
|
||||
assert(info->carDensity >= 0);
|
||||
assert(info->carThreshold[0] >= 0);
|
||||
assert(info->carThreshold[1] >= 0);
|
||||
assert(info->carThreshold[2] >= 0);
|
||||
assert(info->carThreshold[3] >= 0);
|
||||
assert(info->carThreshold[4] >= 0);
|
||||
assert(info->carThreshold[5] >= 0);
|
||||
assert(info->copThreshold >= 0);
|
||||
assert(info->gangThreshold[0] >= 0);
|
||||
assert(info->gangThreshold[1] >= 0);
|
||||
assert(info->gangThreshold[2] >= 0);
|
||||
assert(info->gangThreshold[3] >= 0);
|
||||
assert(info->gangThreshold[4] >= 0);
|
||||
assert(info->gangThreshold[5] >= 0);
|
||||
assert(info->gangThreshold[6] >= 0);
|
||||
assert(info->gangThreshold[7] >= 0);
|
||||
assert(info->gangThreshold[8] >= 0);
|
||||
}
|
||||
|
||||
// BUG: there might be a bug somewhere in there that causes
|
||||
|
@ -53,7 +53,8 @@ enum Config {
|
||||
|
||||
NUMEXTRADIRECTIONALS = 4,
|
||||
NUMANTENNAS = 8,
|
||||
NUMCORONAS = 56
|
||||
NUMCORONAS = 56,
|
||||
NUMPOINTLIGHTS = 32
|
||||
};
|
||||
|
||||
#define GTA3_1_1_PATCH FALSE
|
||||
|
27
src/re3.cpp
27
src/re3.cpp
@ -111,6 +111,29 @@ delayedPatches10(int a, int b)
|
||||
return RsEventHandler_orig(a, b);
|
||||
}
|
||||
|
||||
void __declspec(naked) HeadlightsFix()
|
||||
{
|
||||
static const float fMinusOne = -1.0f;
|
||||
_asm
|
||||
{
|
||||
fld [esp+708h-690h]
|
||||
fcomp fMinusOne
|
||||
fnstsw ax
|
||||
and ah, 5
|
||||
cmp ah, 1
|
||||
jnz HeadlightsFix_DontLimit
|
||||
fld fMinusOne
|
||||
fstp [esp+708h-690h]
|
||||
|
||||
HeadlightsFix_DontLimit:
|
||||
fld [esp+708h-690h]
|
||||
fabs
|
||||
fld st
|
||||
push 0x5382F2
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
patch()
|
||||
@ -120,6 +143,10 @@ patch()
|
||||
Patch<float>(0x46BC61+6, 1.0f); // car distance
|
||||
InjectHook(0x59E460, printf, PATCH_JUMP);
|
||||
|
||||
// stolen from silentpatch (sorry)
|
||||
Patch<WORD>(0x5382BF, 0x0EEB);
|
||||
InjectHook(0x5382EC, HeadlightsFix, PATCH_JUMP);
|
||||
|
||||
InterceptCall(&open_script_orig, open_script, 0x438869);
|
||||
|
||||
InterceptCall(&RsEventHandler_orig, delayedPatches10, 0x58275E);
|
||||
|
@ -1,13 +1,294 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Lights.h"
|
||||
#include "Camera.h"
|
||||
#include "Weather.h"
|
||||
#include "World.h"
|
||||
#include "Collision.h"
|
||||
#include "Sprite.h"
|
||||
#include "Timer.h"
|
||||
#include "PointLights.h"
|
||||
|
||||
int16 &CPointLights::NumLights = *(int16*)0x95CC3E;
|
||||
CRegisteredPointLight *CPointLights::aLights = (CRegisteredPointLight*)0x7096D0;
|
||||
|
||||
WRAPPER void CPointLights::RenderFogEffect(void) { EAXJMP(0x510C30); }
|
||||
//WRAPPER void CPointLights::RenderFogEffect(void) { EAXJMP(0x510C30); }
|
||||
|
||||
void
|
||||
CPointLights::InitPerFrame(void)
|
||||
{
|
||||
NumLights = 0;
|
||||
}
|
||||
|
||||
#define MAX_DIST 22.0f
|
||||
|
||||
void
|
||||
CPointLights::AddLight(uint8 type, CVector coors, CVector dir, float radius, float red, float green, float blue, uint8 fogType, bool castExtraShadows)
|
||||
{
|
||||
CVector dist;
|
||||
float distance;
|
||||
|
||||
// The check is done in some weird way in the game
|
||||
// we're doing it a bit better here
|
||||
if(NumLights >= NUMPOINTLIGHTS)
|
||||
return;
|
||||
|
||||
dist = coors - TheCamera.GetPosition();
|
||||
if(fabs(dist.x) < MAX_DIST && fabs(dist.y) < MAX_DIST){
|
||||
distance = dist.Magnitude();
|
||||
if(distance < MAX_DIST){
|
||||
aLights[NumLights].type = type;
|
||||
aLights[NumLights].fogType = fogType;
|
||||
aLights[NumLights].coors = coors;
|
||||
aLights[NumLights].dir = dir;
|
||||
aLights[NumLights].radius = radius;
|
||||
aLights[NumLights].castExtraShadows = castExtraShadows;
|
||||
if(distance < MAX_DIST*0.75f){
|
||||
aLights[NumLights].red = red;
|
||||
aLights[NumLights].green = green;
|
||||
aLights[NumLights].blue = blue;
|
||||
}else{
|
||||
float fade = 1.0f - (distance/MAX_DIST - 0.75f)*4.0f;
|
||||
aLights[NumLights].red = red * fade;
|
||||
aLights[NumLights].green = green * fade;
|
||||
aLights[NumLights].blue = blue * fade;
|
||||
}
|
||||
NumLights++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
CPointLights::GenerateLightsAffectingObject(CVector *objCoors)
|
||||
{
|
||||
int i;
|
||||
float ret;
|
||||
CVector dist;
|
||||
float radius, distance;
|
||||
|
||||
ret = 1.0f;
|
||||
for(i = 0; i < NumLights; i++){
|
||||
if(aLights[i].type == LIGHT_FOGONLY_3 || aLights[i].type == LIGHT_FOGONLY_4)
|
||||
continue;
|
||||
|
||||
// same weird distance calculation. simplified here
|
||||
dist = aLights[i].coors - *objCoors;
|
||||
radius = aLights[i].radius;
|
||||
if(fabs(dist.x) < radius &&
|
||||
fabs(dist.y) < radius &&
|
||||
fabs(dist.z) < radius){
|
||||
|
||||
distance = dist.Magnitude();
|
||||
if(distance < radius){
|
||||
|
||||
float distNorm = distance/radius;
|
||||
if(aLights[i].type == LIGHT_DARKEN){
|
||||
// darken the object the closer it is
|
||||
ret *= distNorm;
|
||||
}else{
|
||||
float intensity;
|
||||
if(distNorm < 0.5f)
|
||||
// near enough
|
||||
intensity = 1.0f;
|
||||
else
|
||||
// attenuate
|
||||
intensity = 1.0f - (distNorm - 0.5f)*2.0f;
|
||||
|
||||
if(distance != 0.0f){
|
||||
CVector dir = dist / distance;
|
||||
|
||||
if(aLights[i].type == LIGHT_DIRECTIONAL){
|
||||
float dot = -DotProduct(dir, aLights[i].dir);
|
||||
intensity *= max((dot-0.5f)*2.0f, 0.0f);
|
||||
}
|
||||
|
||||
if(intensity > 0.0f)
|
||||
AddAnExtraDirectionalLight(Scene.world,
|
||||
dir.x, dir.y, dir.z,
|
||||
aLights[i].red*intensity, aLights[i].green*intensity, aLights[i].blue*intensity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern RwRaster *&gpPointlightRaster;
|
||||
|
||||
void
|
||||
CPointLights::RemoveLightsAffectingObject(void)
|
||||
{
|
||||
RemoveExtraDirectionalLights(Scene.world);
|
||||
}
|
||||
|
||||
// for directional fog
|
||||
#define FOG_AREA_LENGTH 12.0f
|
||||
#define FOG_AREA_WIDTH 5.0f
|
||||
// for pointlight fog
|
||||
#define FOG_AREA_RADIUS 9.0f
|
||||
|
||||
float FogSizes[8] = { 1.3f, 2.0f, 1.7f, 2.0f, 1.4f, 2.1f, 1.5f, 2.3f };
|
||||
|
||||
void
|
||||
CPointLights::RenderFogEffect(void)
|
||||
{
|
||||
int i;
|
||||
float fogginess;
|
||||
CColPoint point;
|
||||
CEntity *entity;
|
||||
float xmin, ymin;
|
||||
float xmax, ymax;
|
||||
int16 xi, yi;
|
||||
CVector spriteCoors;
|
||||
float spritew, spriteh;
|
||||
|
||||
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
|
||||
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
|
||||
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
|
||||
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
|
||||
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpPointlightRaster);
|
||||
|
||||
for(i = 0; i < NumLights; i++){
|
||||
if(aLights[i].fogType != FOG_NORMAL && aLights[i].fogType != FOG_ALWAYS)
|
||||
continue;
|
||||
|
||||
fogginess = aLights[i].fogType == FOG_ALWAYS ? 1.0f : CWeather::Foggyness;
|
||||
if(fogginess == 0.0f)
|
||||
continue;
|
||||
|
||||
if(aLights[i].type == LIGHT_DIRECTIONAL){
|
||||
|
||||
// TODO: test this. haven't found directional fog so far
|
||||
|
||||
float coors2X = aLights[i].coors.x + FOG_AREA_LENGTH*aLights[i].dir.x;
|
||||
float coors2Y = aLights[i].coors.y + FOG_AREA_LENGTH*aLights[i].dir.y;
|
||||
|
||||
if(coors2X < aLights[i].coors.x){
|
||||
xmin = coors2X;
|
||||
xmax = aLights[i].coors.x;
|
||||
}else{
|
||||
xmax = coors2X;
|
||||
xmin = aLights[i].coors.x;
|
||||
}
|
||||
if(coors2Y < aLights[i].coors.y){
|
||||
ymin = coors2Y;
|
||||
ymax = aLights[i].coors.y;
|
||||
}else{
|
||||
ymax = coors2Y;
|
||||
ymin = aLights[i].coors.y;
|
||||
}
|
||||
|
||||
xmin -= 5.0f;
|
||||
ymin -= 5.0f;
|
||||
xmax += 5.0f;
|
||||
ymax += 5.0f;
|
||||
|
||||
for(xi = (int16)xmin - (int16)xmin % 4; xi <= (int16)xmax + 4; xi += 4){
|
||||
for(yi = (int16)ymin - (int16)ymin % 4; yi <= (int16)ymax + 4; yi += 4){
|
||||
// Some kind of pseudo random number?
|
||||
int r = (xi ^ yi)>>2 & 0xF;
|
||||
if((r & 1) == 0)
|
||||
continue;
|
||||
|
||||
// Check if fog effect is close enough to directional line in x and y
|
||||
float dx = xi - aLights[i].coors.x;
|
||||
float dy = yi - aLights[i].coors.y;
|
||||
float dot = dx*aLights[i].dir.x + dy*aLights[i].dir.y;
|
||||
float distsq = sq(dx) + sq(dy);
|
||||
float linedistsq = distsq - sq(dot);
|
||||
if(dot > 0.0f && dot < FOG_AREA_LENGTH && linedistsq < sq(FOG_AREA_WIDTH)){
|
||||
CVector fogcoors(xi, yi, aLights[i].coors.z + 1.0f);
|
||||
if(CWorld::ProcessVerticalLine(fogcoors, fogcoors.z - 20.0f,
|
||||
point, entity, true, false, false, false, true, false, nil)){
|
||||
// Now same check again in xyz
|
||||
fogcoors.z = point.point.z + 1.3f;
|
||||
// actually we don't have to recalculate x and y, but the game does it that way
|
||||
dx = xi - aLights[i].coors.x;
|
||||
dy = yi - aLights[i].coors.y;
|
||||
float dz = fogcoors.z - aLights[i].coors.z;
|
||||
dot = dx*aLights[i].dir.x + dy*aLights[i].dir.y + dz*aLights[i].dir.z;
|
||||
distsq = sq(dx) + sq(dy) + sq(dz);
|
||||
linedistsq = distsq - sq(dot);
|
||||
if(dot > 0.0f && dot < FOG_AREA_LENGTH && linedistsq < sq(FOG_AREA_WIDTH)){
|
||||
float intensity = 158.0f * fogginess;
|
||||
// more intensity the smaller the angle
|
||||
intensity *= dot/sqrt(distsq);
|
||||
// more intensity the closer to light source
|
||||
intensity *= 1.0f - sq(dot/FOG_AREA_LENGTH);
|
||||
// more intensity the closer to line
|
||||
intensity *= 1.0f - sq(sqrt(linedistsq) / FOG_AREA_WIDTH);
|
||||
|
||||
if(CSprite::CalcScreenCoors(fogcoors, spriteCoors, &spritew, &spriteh, true)){
|
||||
float rotation = (CTimer::GetTimeInMilliseconds()&0x1FFF) * 2*3.14f / 0x1FFF;
|
||||
float size = FogSizes[r>>1];
|
||||
CSprite::RenderOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z,
|
||||
spritew * size, spriteh * size,
|
||||
aLights[i].red * intensity, aLights[i].green * intensity, aLights[i].blue * intensity,
|
||||
intensity, 1/spriteCoors.z, rotation, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}else if(aLights[i].type == LIGHT_POINT || aLights[i].type == LIGHT_FOGONLY_3 || aLights[i].type == LIGHT_FOGONLY_4){
|
||||
if(CWorld::ProcessVerticalLine(aLights[i].coors, aLights[i].coors.z - 20.0f,
|
||||
point, entity, true, false, false, false, true, false, nil)){
|
||||
|
||||
xmin = aLights[i].coors.x - FOG_AREA_RADIUS;
|
||||
ymin = aLights[i].coors.y - FOG_AREA_RADIUS;
|
||||
xmax = aLights[i].coors.x + FOG_AREA_RADIUS;
|
||||
ymax = aLights[i].coors.y + FOG_AREA_RADIUS;
|
||||
|
||||
for(xi = (int16)xmin - (int16)xmin % 2; xi <= (int16)xmax + 2; xi += 2){
|
||||
for(yi = (int16)ymin - (int16)ymin % 2; yi <= (int16)ymax + 2; yi += 2){
|
||||
// Some kind of pseudo random number?
|
||||
int r = (xi ^ yi)>>1 & 0xF;
|
||||
if((r & 1) == 0)
|
||||
continue;
|
||||
|
||||
float dx = xi - aLights[i].coors.x;
|
||||
float dy = yi - aLights[i].coors.y;
|
||||
float lightdist = sqrt(sq(dx) + sq(dy));
|
||||
if(lightdist < FOG_AREA_RADIUS){
|
||||
dx = xi - TheCamera.GetPosition().x;
|
||||
dy = yi - TheCamera.GetPosition().y;
|
||||
float camdist = sqrt(sq(dx) + sq(dy));
|
||||
if(camdist < MAX_DIST){
|
||||
float intensity;
|
||||
// distance fade
|
||||
if(camdist < MAX_DIST/2)
|
||||
intensity = 1.0f;
|
||||
else
|
||||
intensity = 1.0f - (camdist - MAX_DIST/2) / (MAX_DIST/2);
|
||||
intensity *= 132.0f * fogginess;
|
||||
// more intensity the closer to light source
|
||||
intensity *= 1.0f - sq(lightdist / FOG_AREA_RADIUS);
|
||||
|
||||
CVector fogcoors(xi, yi, point.point.z + 1.6f);
|
||||
if(CSprite::CalcScreenCoors(fogcoors, spriteCoors, &spritew, &spriteh, true)){
|
||||
float rotation = (CTimer::GetTimeInMilliseconds()&0x3FFF) * 2*3.14f / 0x3FFF;
|
||||
float size = FogSizes[r>>1];
|
||||
CSprite::RenderOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z,
|
||||
spritew * size, spriteh * size,
|
||||
aLights[i].red * intensity, aLights[i].green * intensity, aLights[i].blue * intensity,
|
||||
intensity, 1/spriteCoors.z, rotation, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x510790, CPointLights::AddLight, PATCH_JUMP);
|
||||
InjectHook(0x510960, CPointLights::GenerateLightsAffectingObject, PATCH_JUMP);
|
||||
InjectHook(0x510C20, CPointLights::RemoveLightsAffectingObject, PATCH_JUMP);
|
||||
InjectHook(0x510C30, CPointLights::RenderFogEffect, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
|
@ -1,9 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
class CRegisteredPointLight
|
||||
{
|
||||
public:
|
||||
CVector coors;
|
||||
CVector dir;
|
||||
float radius;
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
int8 type;
|
||||
int8 fogType;
|
||||
bool castExtraShadows;
|
||||
};
|
||||
static_assert(sizeof(CRegisteredPointLight) == 0x2C, "CRegisteredPointLight: error");
|
||||
|
||||
class CPointLights
|
||||
{
|
||||
// Probably have to make this public for shadows later
|
||||
static int16 &NumLights;
|
||||
static CRegisteredPointLight *aLights; //[NUMPOINTLIGHTS]
|
||||
public:
|
||||
enum {
|
||||
LIGHT_POINT,
|
||||
LIGHT_DIRECTIONAL,
|
||||
LIGHT_DARKEN, // no effects at all
|
||||
// these have only fog, otherwise no difference?
|
||||
LIGHT_FOGONLY_3,
|
||||
LIGHT_FOGONLY_4,
|
||||
};
|
||||
enum {
|
||||
FOG_NONE,
|
||||
FOG_NORMAL, // taken from Foggyness
|
||||
FOG_ALWAYS
|
||||
};
|
||||
|
||||
static void InitPerFrame(void);
|
||||
static void AddLight(uint8 type, CVector coors, CVector dir, float radius, float red, float green, float blue, uint8 fogType, bool castExtraShadows);
|
||||
static float GenerateLightsAffectingObject(CVector *objCoors);
|
||||
static void RemoveLightsAffectingObject(void);
|
||||
static void RenderFogEffect(void);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user