forked from Ports/goldeneye-pc-port
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e767334f7 | ||
|
|
6c183d9434 | ||
|
|
fd7800cf80 | ||
|
|
06856ed973 | ||
|
|
fbc8911238 | ||
|
|
3154efa79f | ||
|
|
af9a3c19e6 |
No files matched your search
@@ -42,6 +42,8 @@ struct ShaderProgram {
|
|||||||
GLint decal_scale_location;
|
GLint decal_scale_location;
|
||||||
int decal_mode;
|
int decal_mode;
|
||||||
float decal_scale;
|
float decal_scale;
|
||||||
|
GLint depth_prepass_location;
|
||||||
|
int depth_prepass;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Framebuffer {
|
struct Framebuffer {
|
||||||
@@ -83,6 +85,14 @@ static uint32_t depth_copy_width, depth_copy_height;
|
|||||||
static bool current_depth_test;
|
static bool current_depth_test;
|
||||||
static bool current_depth_decal;
|
static bool current_depth_decal;
|
||||||
|
|
||||||
|
// Translucent surfaces write no depth and are only drawn in rough back-to-front order, so a farther
|
||||||
|
// railing drawn later blended over a nearer one. Their nearly opaque texels (railing bars) first get
|
||||||
|
// a depth-only pass, then the surface is drawn as usual: semi-transparent texels are unchanged.
|
||||||
|
#define XLU_DEPTH_PREPASS_ALPHA "0.98"
|
||||||
|
static bool current_depth_compare;
|
||||||
|
static GLenum current_depth_func = GL_LESS;
|
||||||
|
static bool current_blend;
|
||||||
|
|
||||||
static int gl_glsl_version = 130;
|
static int gl_glsl_version = 130;
|
||||||
static char gl_glsl_version_str[16] = "130";
|
static char gl_glsl_version_str[16] = "130";
|
||||||
static GLenum gl_mirror_clamp = GL_MIRROR_CLAMP_TO_EDGE;
|
static GLenum gl_mirror_clamp = GL_MIRROR_CLAMP_TO_EDGE;
|
||||||
@@ -417,6 +427,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
|
|||||||
append_line(fs_buf, &fs_len, "uniform int frame_count;");
|
append_line(fs_buf, &fs_len, "uniform int frame_count;");
|
||||||
append_line(fs_buf, &fs_len, "uniform float noise_scale;");
|
append_line(fs_buf, &fs_len, "uniform float noise_scale;");
|
||||||
append_line(fs_buf, &fs_len, "uniform int uDecalMode;");
|
append_line(fs_buf, &fs_len, "uniform int uDecalMode;");
|
||||||
|
append_line(fs_buf, &fs_len, "uniform int uDepthPrepass;");
|
||||||
append_line(fs_buf, &fs_len, "uniform highp float uDecalPixelScale;");
|
append_line(fs_buf, &fs_len, "uniform highp float uDecalPixelScale;");
|
||||||
append_line(fs_buf, &fs_len, "uniform highp sampler2D uDepthTex;");
|
append_line(fs_buf, &fs_len, "uniform highp sampler2D uDepthTex;");
|
||||||
|
|
||||||
@@ -617,6 +628,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
|
|||||||
if (cc_features.opt_invisible) {
|
if (cc_features.opt_invisible) {
|
||||||
append_line(fs_buf, &fs_len, " texel.a = 0.0;");
|
append_line(fs_buf, &fs_len, " texel.a = 0.0;");
|
||||||
}
|
}
|
||||||
|
append_line(fs_buf, &fs_len, " if (uDepthPrepass != 0 && texel.a < " XLU_DEPTH_PREPASS_ALPHA ") discard;");
|
||||||
|
|
||||||
append_line(fs_buf, &fs_len, " OUTPUT_COLOR = texel;");
|
append_line(fs_buf, &fs_len, " OUTPUT_COLOR = texel;");
|
||||||
} else {
|
} else {
|
||||||
@@ -740,6 +752,11 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
|
|||||||
prg->decal_scale_location = glGetUniformLocation(shader_program, "uDecalPixelScale");
|
prg->decal_scale_location = glGetUniformLocation(shader_program, "uDecalPixelScale");
|
||||||
prg->decal_mode = 0;
|
prg->decal_mode = 0;
|
||||||
prg->decal_scale = 0.0f;
|
prg->decal_scale = 0.0f;
|
||||||
|
prg->depth_prepass_location = glGetUniformLocation(shader_program, "uDepthPrepass");
|
||||||
|
prg->depth_prepass = 0;
|
||||||
|
if (prg->depth_prepass_location >= 0) {
|
||||||
|
glUniform1i(prg->depth_prepass_location, 0);
|
||||||
|
}
|
||||||
if (prg->decal_mode_location >= 0) {
|
if (prg->decal_mode_location >= 0) {
|
||||||
glUniform1i(prg->decal_mode_location, 0);
|
glUniform1i(prg->decal_mode_location, 0);
|
||||||
glUniform1i(glGetUniformLocation(shader_program, "uDepthTex"), DECAL_DEPTH_TEXTURE_UNIT);
|
glUniform1i(glGetUniformLocation(shader_program, "uDepthTex"), DECAL_DEPTH_TEXTURE_UNIT);
|
||||||
@@ -902,6 +919,7 @@ static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint
|
|||||||
|
|
||||||
static void gfx_opengl_set_depth_mode(bool depth_test, bool depth_update, bool depth_compare, bool depth_source_prim, uint16_t zmode) {
|
static void gfx_opengl_set_depth_mode(bool depth_test, bool depth_update, bool depth_compare, bool depth_source_prim, uint16_t zmode) {
|
||||||
current_depth_test = depth_test;
|
current_depth_test = depth_test;
|
||||||
|
current_depth_compare = depth_compare;
|
||||||
current_depth_decal = depth_test && depth_compare && zmode == ZMODE_DEC;
|
current_depth_decal = depth_test && depth_compare && zmode == ZMODE_DEC;
|
||||||
|
|
||||||
if (depth_test) {
|
if (depth_test) {
|
||||||
@@ -912,7 +930,7 @@ static void gfx_opengl_set_depth_mode(bool depth_test, bool depth_update, bool d
|
|||||||
if (depth_compare) {
|
if (depth_compare) {
|
||||||
switch (zmode) {
|
switch (zmode) {
|
||||||
case ZMODE_INTER:
|
case ZMODE_INTER:
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(current_depth_func = GL_LEQUAL);
|
||||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
glPolygonOffset(0, 0);
|
glPolygonOffset(0, 0);
|
||||||
break;
|
break;
|
||||||
@@ -920,22 +938,22 @@ static void gfx_opengl_set_depth_mode(bool depth_test, bool depth_update, bool d
|
|||||||
case ZMODE_OPA:
|
case ZMODE_OPA:
|
||||||
case ZMODE_XLU:
|
case ZMODE_XLU:
|
||||||
if (depth_source_prim) {
|
if (depth_source_prim) {
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(current_depth_func = GL_LEQUAL);
|
||||||
} else {
|
} else {
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(current_depth_func = GL_LESS);
|
||||||
}
|
}
|
||||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
glPolygonOffset(0, 0);
|
glPolygonOffset(0, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZMODE_DEC:
|
case ZMODE_DEC:
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(current_depth_func = GL_LEQUAL);
|
||||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||||
glPolygonOffset(-2, -2);
|
glPolygonOffset(-2, -2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
glDepthFunc(GL_ALWAYS);
|
glDepthFunc(current_depth_func = GL_ALWAYS);
|
||||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
glPolygonOffset(0, 0);
|
glPolygonOffset(0, 0);
|
||||||
}
|
}
|
||||||
@@ -961,6 +979,7 @@ static void gfx_opengl_set_scissor(int x, int y, int width, int height) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void gfx_opengl_set_use_alpha(bool use_alpha, bool modulate) {
|
static void gfx_opengl_set_use_alpha(bool use_alpha, bool modulate) {
|
||||||
|
current_blend = use_alpha && !modulate;
|
||||||
if (use_alpha) {
|
if (use_alpha) {
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
} else {
|
} else {
|
||||||
@@ -1084,6 +1103,26 @@ static void gfx_opengl_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_
|
|||||||
}
|
}
|
||||||
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * buf_vbo_len, buf_vbo, GL_STREAM_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * buf_vbo_len, buf_vbo, GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
struct ShaderProgram* prg = current_shader_program;
|
||||||
|
if (!current_depth_decal && current_depth_test && current_depth_compare && !current_depth_mask && current_blend &&
|
||||||
|
prg != nullptr && prg->depth_prepass_location >= 0) {
|
||||||
|
glUniform1i(prg->depth_prepass_location, 1);
|
||||||
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3 * buf_vbo_num_tris);
|
||||||
|
glUniform1i(prg->depth_prepass_location, 0);
|
||||||
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
|
||||||
|
// The colour pass must pass where the prepass just stored this surface's own depth
|
||||||
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3 * buf_vbo_num_tris);
|
||||||
|
glDepthFunc(current_depth_func);
|
||||||
|
depth_copy_dirty = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 3 * buf_vbo_num_tris);
|
glDrawArrays(GL_TRIANGLES, 0, 3 * buf_vbo_num_tris);
|
||||||
|
|
||||||
if (current_depth_test && current_depth_mask) {
|
if (current_depth_test && current_depth_mask) {
|
||||||
|
|||||||
@@ -764,6 +764,22 @@ Gfx *sub_GAME_7F0B3C8C(Gfx *gdl)
|
|||||||
{
|
{
|
||||||
if (i == dword_CODE_bss_8007FFA0[j].unk1)
|
if (i == dword_CODE_bss_8007FFA0[j].unk1)
|
||||||
{
|
{
|
||||||
|
#ifdef PORT
|
||||||
|
/* Tinted glass stands in a window opening at the far side of
|
||||||
|
* the room, yet it is a prop and so was drawn after the room's
|
||||||
|
* translucent geometry. Railing balusters in front of it are
|
||||||
|
* such geometry (an XLU quad that writes no depth), so the
|
||||||
|
* glass painted over them (Facility main hall). Draw the room's
|
||||||
|
* tinted glass before its translucent geometry instead. */
|
||||||
|
if (get_debug_do_draw_obj() && sub_GAME_7F0BD8F0())
|
||||||
|
{
|
||||||
|
gSPMatrix(gdl++, osVirtualToPhysical((void*)currentPlayerGetProjectionMatrix()), (G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION));
|
||||||
|
gdl = fogRenderClearFogMode(gdl);
|
||||||
|
g_PortXluGlassPhase = 1;
|
||||||
|
gdl = chrpropsRenderPass(gdl, dword_CODE_bss_8007FFA0[j].roomid, 1);
|
||||||
|
}
|
||||||
|
g_PortXluGlassPhase = 2;
|
||||||
|
#endif
|
||||||
gSPMatrix(gdl++, osVirtualToPhysical((void*)get_BONDdata_field_10E0()), (G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION));
|
gSPMatrix(gdl++, osVirtualToPhysical((void*)get_BONDdata_field_10E0()), (G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION));
|
||||||
gdl = fogSetRenderFogColor(
|
gdl = fogSetRenderFogColor(
|
||||||
bgScissorCurrentPlayerViewF(
|
bgScissorCurrentPlayerViewF(
|
||||||
@@ -792,6 +808,9 @@ Gfx *sub_GAME_7F0B3C8C(Gfx *gdl)
|
|||||||
gdl = chrpropsRenderPass(gdl, dword_CODE_bss_8007FFA0[j].roomid, 1);
|
gdl = chrpropsRenderPass(gdl, dword_CODE_bss_8007FFA0[j].roomid, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef PORT
|
||||||
|
g_PortXluGlassPhase = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (1);
|
if (1);
|
||||||
}
|
}
|
||||||
@@ -3358,6 +3377,38 @@ bool bgTestRayIntersectsBbox(coord3d *origin, coord3d *dir, s32 *bbox_min, s32 *
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PORT
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
/* The image id of a room triangle's texture, read like the N64 does: texLoad
|
||||||
|
* stores the id in the 8 bytes before the texture data, and the room's
|
||||||
|
* G_SETTIMG points at that data (a full host pointer in w1 on PC). Room GDLs
|
||||||
|
* load into the default pool, so anything outside it is not a texture.
|
||||||
|
* The id selects the impact decal, sound and dust puff (HIT_WATER: no decal,
|
||||||
|
* no puff, splash sound). */
|
||||||
|
static s32 bgTexnumFromSetTimg(Gfx *settimg)
|
||||||
|
{
|
||||||
|
struct texpool *pool = &ptr_texture_alloc_start;
|
||||||
|
u8 *data = (u8 *)settimg->words.w1;
|
||||||
|
s32 texnum;
|
||||||
|
|
||||||
|
if (data < pool->start + 8 || data >= (u8 *)pool->end)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
texnum = *(s16 *)(data - 8);
|
||||||
|
|
||||||
|
if (texnum < 0 || texnum >= MAX_TEXTURES)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return texnum;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
bool bgTestRayIntersectionInRoom(coord3d *from, coord3d *to, coord3d *dir, RoomVtxBatchBounds *point, s32 roomnum, struct HitThing *hitthing)
|
bool bgTestRayIntersectionInRoom(coord3d *from, coord3d *to, coord3d *dir, RoomVtxBatchBounds *point, s32 roomnum, struct HitThing *hitthing)
|
||||||
{
|
{
|
||||||
Vertex *vtxbase;
|
Vertex *vtxbase;
|
||||||
@@ -3555,6 +3606,11 @@ bool bgTestRayIntersectionInRoom(coord3d *from, coord3d *to, coord3d *dir, RoomV
|
|||||||
#ifdef PORT
|
#ifdef PORT
|
||||||
/* D154: KSEG0 texnum deref invalid for converted GDLs (cf. D135). D431 (#119): light fixtures are the one texture class the game acts on, so recover their image id from the fixture table. */
|
/* D154: KSEG0 texnum deref invalid for converted GDLs (cf. D135). D431 (#119): light fixtures are the one texture class the game acts on, so recover their image id from the fixture table. */
|
||||||
texnum = lightFixtureTexnumForGfx(gdl, roomnum);
|
texnum = lightFixtureTexnumForGfx(gdl, roomnum);
|
||||||
|
|
||||||
|
if (texnum < 0)
|
||||||
|
{
|
||||||
|
texnum = bgTexnumFromSetTimg(tcmd);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
temp.word = ((u32 *) tcmd)[1] - 8;
|
temp.word = ((u32 *) tcmd)[1] - 8;
|
||||||
texnum = *((u16 *) (temp.word | 0x80000000));
|
texnum = *((u16 *) (temp.word | 0x80000000));
|
||||||
@@ -3737,6 +3793,11 @@ bool bgTestRayIntersectionInRoom(coord3d *from, coord3d *to, coord3d *dir, RoomV
|
|||||||
#ifdef PORT
|
#ifdef PORT
|
||||||
/* D154: KSEG0 texnum deref invalid for converted GDLs (cf. D135). D431 (#119): light fixtures are the one texture class the game acts on, so recover their image id from the fixture table. */
|
/* D154: KSEG0 texnum deref invalid for converted GDLs (cf. D135). D431 (#119): light fixtures are the one texture class the game acts on, so recover their image id from the fixture table. */
|
||||||
texnum = lightFixtureTexnumForGfx(gdl, roomnum);
|
texnum = lightFixtureTexnumForGfx(gdl, roomnum);
|
||||||
|
|
||||||
|
if (texnum < 0)
|
||||||
|
{
|
||||||
|
texnum = bgTexnumFromSetTimg(tcmd);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
temp.word = ((u32 *) tcmd)[1] - 8;
|
temp.word = ((u32 *) tcmd)[1] - 8;
|
||||||
texnum = *((u16 *) (temp.word | 0x80000000));
|
texnum = *((u16 *) (temp.word | 0x80000000));
|
||||||
|
|||||||
@@ -334,6 +334,11 @@ s32 chrpropTestPointInPolygon(coord3d *point, struct rect4f *poly
|
|||||||
void roomGetProps(s32 *roomids);
|
void roomGetProps(s32 *roomids);
|
||||||
ObjectRecord *scan_position_data_table_for_normal_object_at_preset(s32 arg0);
|
ObjectRecord *scan_position_data_table_for_normal_object_at_preset(s32 arg0);
|
||||||
Gfx *chrpropsRenderPass(Gfx *arg0, s32 roomid, s32 arg2);
|
Gfx *chrpropsRenderPass(Gfx *arg0, s32 roomid, s32 arg2);
|
||||||
|
#ifdef PORT
|
||||||
|
/* Translucent prop pass filter: 0 = all props, 1 = tinted glass only,
|
||||||
|
* 2 = all but tinted glass (see bg.c). */
|
||||||
|
extern s32 g_PortXluGlassPhase;
|
||||||
|
#endif
|
||||||
PropRecord *chrpropGetActiveTail(void);
|
PropRecord *chrpropGetActiveTail(void);
|
||||||
void propsDefragRoomProps(void);
|
void propsDefragRoomProps(void);
|
||||||
void chraiGetPropRoomIds(PropRecord *self, s32 *roomids);
|
void chraiGetPropRoomIds(PropRecord *self, s32 *roomids);
|
||||||
|
|||||||
@@ -466,6 +466,15 @@ Gfx *chrpropRender(Gfx * gdl, PropRecord *prop, s32 withalpha)
|
|||||||
/**
|
/**
|
||||||
* Address: 7F03A6F4
|
* Address: 7F03A6F4
|
||||||
*/
|
*/
|
||||||
|
#ifdef PORT
|
||||||
|
s32 g_PortXluGlassPhase = 0;
|
||||||
|
|
||||||
|
static bool chrpropIsTintedGlass(PropRecord *prop)
|
||||||
|
{
|
||||||
|
return prop->type == PROP_TYPE_OBJ && prop->obj != NULL && prop->obj->type == PROPDEF_TINTED_GLASS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Gfx *chrpropsRenderPass(Gfx *gdl, s32 roomid, s32 renderpass)
|
Gfx *chrpropsRenderPass(Gfx *gdl, s32 roomid, s32 renderpass)
|
||||||
{
|
{
|
||||||
s32 flag;
|
s32 flag;
|
||||||
@@ -542,6 +551,14 @@ Gfx *chrpropsRenderPass(Gfx *gdl, s32 roomid, s32 renderpass)
|
|||||||
{
|
{
|
||||||
prop = *pp;
|
prop = *pp;
|
||||||
|
|
||||||
|
#ifdef PORT
|
||||||
|
if (prop != NULL && g_PortXluGlassPhase != 0
|
||||||
|
&& chrpropIsTintedGlass(prop) != (g_PortXluGlassPhase == 1))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (prop != NULL)
|
if (prop != NULL)
|
||||||
{
|
{
|
||||||
flag = 0;
|
flag = 0;
|
||||||
@@ -1176,6 +1193,14 @@ void chraiDefaultWeaponFireHandler(s32 hand)
|
|||||||
rooms[1] = 255;
|
rooms[1] = 255;
|
||||||
explosionCreate(0, finalpos, hittile, 1, 0, get_cur_playernum(), rooms, 0);
|
explosionCreate(0, finalpos, hittile, 1, 0, get_cur_playernum(), rooms, 0);
|
||||||
}
|
}
|
||||||
|
#ifdef PORT
|
||||||
|
else if (gotbghit && besttexture >= 0 && g_Textures[besttexture].hitTexture == HIT_WATER)
|
||||||
|
{
|
||||||
|
/* a splash instead of the yellow impact flash below */
|
||||||
|
explosionCreateWaterSplash(finalpos, bestroom);
|
||||||
|
createSpark = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
finalpos->x -= 26.0f * shotdata.dir.x;
|
finalpos->x -= 26.0f * shotdata.dir.x;
|
||||||
|
|||||||
@@ -1590,6 +1590,9 @@ void explosionInitFlyingParticles(coord3d *spawnpos, f32 spawn_rand_scale, f32 s
|
|||||||
rand3 = (2.0f * (((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX))) - 1.0f;
|
rand3 = (2.0f * (((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX))) - 1.0f;
|
||||||
|
|
||||||
g_FlyingParticlesBuffer[g_NumParticleEntries].unk00 = 1;
|
g_FlyingParticlesBuffer[g_NumParticleEntries].unk00 = 1;
|
||||||
|
#ifdef PORT
|
||||||
|
g_FlyingParticlesBuffer[g_NumParticleEntries].is_splash = FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
g_FlyingParticlesBuffer[g_NumParticleEntries].position.f[0] = spawnpos->f[0] + (spawn_rand_scale * rand1);
|
g_FlyingParticlesBuffer[g_NumParticleEntries].position.f[0] = spawnpos->f[0] + (spawn_rand_scale * rand1);
|
||||||
g_FlyingParticlesBuffer[g_NumParticleEntries].position.f[1] = spawnpos->f[1] + (spawn_rand_scale * rand2);
|
g_FlyingParticlesBuffer[g_NumParticleEntries].position.f[1] = spawnpos->f[1] + (spawn_rand_scale * rand2);
|
||||||
@@ -1739,6 +1742,15 @@ void explosionUpdateFlyingParticles(void)
|
|||||||
g_FlyingParticlesBuffer[i].unk00 = 0;
|
g_FlyingParticlesBuffer[i].unk00 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PORT
|
||||||
|
if (g_FlyingParticlesBuffer[i].is_splash
|
||||||
|
&& g_FlyingParticlesBuffer[i].position_drift.f[1] < 0.0f
|
||||||
|
&& g_FlyingParticlesBuffer[i].position.f[1] < g_FlyingParticlesBuffer[i].splash_y)
|
||||||
|
{
|
||||||
|
g_FlyingParticlesBuffer[i].unk00 = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// position-related. deletes particles that are too low or too high.
|
// position-related. deletes particles that are too low or too high.
|
||||||
if ((g_FlyingParticlesBuffer[i].position.f[1] < -30000.0f) || (g_FlyingParticlesBuffer[i].position.f[1] > 30000.0f))
|
if ((g_FlyingParticlesBuffer[i].position.f[1] < -30000.0f) || (g_FlyingParticlesBuffer[i].position.f[1] > 30000.0f))
|
||||||
{
|
{
|
||||||
@@ -1749,6 +1761,62 @@ void explosionUpdateFlyingParticles(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PORT
|
||||||
|
#include "glass.h"
|
||||||
|
|
||||||
|
/* Bullet hitting water (PC): the N64 only drew the yellow impact flash there.
|
||||||
|
* Use the chr hit puffs instead (chrCreateHitPuffs: the small impact puff and
|
||||||
|
* the larger burst), tinted to the water colour, plus droplets (the wall-hit
|
||||||
|
* dust particles, recoloured) thrown up and removed when they fall back
|
||||||
|
* through the surface. */
|
||||||
|
#define WATER_SPLASH_R 0xA0
|
||||||
|
#define WATER_SPLASH_G 0xC8
|
||||||
|
#define WATER_SPLASH_B 0xF0
|
||||||
|
#define WATER_SPLASH_DROPLETS 12
|
||||||
|
|
||||||
|
static void explosionTintSpark(s_bullet_spark *spark)
|
||||||
|
{
|
||||||
|
if (spark != NULL)
|
||||||
|
{
|
||||||
|
spark->unk28 = WATER_SPLASH_R;
|
||||||
|
spark->unk29 = WATER_SPLASH_G;
|
||||||
|
spark->unk2A = WATER_SPLASH_B;
|
||||||
|
spark->unk2B = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void explosionCreateWaterSplash(coord3d *pos, s16 room)
|
||||||
|
{
|
||||||
|
s32 i;
|
||||||
|
s32 j;
|
||||||
|
|
||||||
|
explosionTintSpark(bullet_spark_create(pos, 3, 43.0f, room));
|
||||||
|
explosionTintSpark(bullet_spark_create(pos, 1, 21.0f, room));
|
||||||
|
|
||||||
|
for (i = 0; i < WATER_SPLASH_DROPLETS; i++)
|
||||||
|
{
|
||||||
|
struct FlyingParticles *drop = &g_FlyingParticlesBuffer[g_NumParticleEntries];
|
||||||
|
|
||||||
|
explosionInitFlyingParticles(pos, 2.0f, 1.0f, 6.0f, 3.0f);
|
||||||
|
|
||||||
|
drop->is_splash = TRUE;
|
||||||
|
drop->splash_y = pos->f[1];
|
||||||
|
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
|
/* vary the brightness per vertex, keep the water hue */
|
||||||
|
s32 shade = 0xC0 + (randomGetNext() & 0x3F);
|
||||||
|
|
||||||
|
drop->vertex_list[j].v.cn[0] = (WATER_SPLASH_R * shade) / 0xFF;
|
||||||
|
drop->vertex_list[j].v.cn[1] = (WATER_SPLASH_G * shade) / 0xFF;
|
||||||
|
drop->vertex_list[j].v.cn[2] = (WATER_SPLASH_B * shade) / 0xFF;
|
||||||
|
drop->vertex_list[j].v.cn[3] = 0xB0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern Gfx globalDL_0xa50;
|
extern Gfx globalDL_0xa50;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@@ -2065,6 +2133,21 @@ void explosionCreateBulletImpact(struct coord3d *pos, struct coord3d *arg1, s16
|
|||||||
impact_type = 0x10;
|
impact_type = 0x10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PORT
|
||||||
|
/* Glass objects: the bulletproof/unbreakable ones take the texture-based
|
||||||
|
* hole, a decal drawn in the opaque pass. Transparent glass writes no
|
||||||
|
* depth there, so the decal depth test (RDP ZMODE_DEC, emulated exactly)
|
||||||
|
* rejects every pixel. Use the window crack the breakable glass gets: it
|
||||||
|
* is drawn after the glass in the translucent pass, without the decal
|
||||||
|
* test. */
|
||||||
|
if ((prop != NULL) && (impact_type != 0x10)
|
||||||
|
&& ((prop->obj->type == PROPDEF_GLASS) || (prop->obj->type == PROPDEF_TINTED_GLASS))
|
||||||
|
&& ((g_ImpactTypes[impact_type].unk2 >= 2) || (g_ImpactTypes[impact_type].unk1 != 2)))
|
||||||
|
{
|
||||||
|
impact_type = (randomGetNext() % 3) + 0x11;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
spA0.f[0] = pos->f[0];
|
spA0.f[0] = pos->f[0];
|
||||||
spA0.f[1] = pos->f[1];
|
spA0.f[1] = pos->f[1];
|
||||||
spA0.f[2] = pos->f[2];
|
spA0.f[2] = pos->f[2];
|
||||||
|
|||||||
@@ -148,6 +148,11 @@ struct FlyingParticles {
|
|||||||
s32 unk34;
|
s32 unk34;
|
||||||
|
|
||||||
Vtx vertex_list[4];
|
Vtx vertex_list[4];
|
||||||
|
#ifdef PORT
|
||||||
|
/* water splash droplet: removed once it falls back below splash_y */
|
||||||
|
s32 is_splash;
|
||||||
|
f32 splash_y;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern f32 g_SpExplosionDamageMult;
|
extern f32 g_SpExplosionDamageMult;
|
||||||
@@ -178,6 +183,9 @@ Gfx *explosionRenderPropSmoke(PropRecord *arg0, Gfx *arg1, s32 withalpha);
|
|||||||
Gfx *explosionRenderBulletImpactOnProp(Gfx *arg0, PropRecord *arg1, s32 arg2);
|
Gfx *explosionRenderBulletImpactOnProp(Gfx *arg0, PropRecord *arg1, s32 arg2);
|
||||||
|
|
||||||
void explosionCreateSmoke(coord3d *pos, StandTile *stan, s16 smoke_type, u8 *rooms, s32 flags);
|
void explosionCreateSmoke(coord3d *pos, StandTile *stan, s16 smoke_type, u8 *rooms, s32 flags);
|
||||||
|
#ifdef PORT
|
||||||
|
void explosionCreateWaterSplash(coord3d *pos, s16 room);
|
||||||
|
#endif
|
||||||
void explosionUpdateFlyingParticles(void);
|
void explosionUpdateFlyingParticles(void);
|
||||||
u8 explosionChrpropSmokeTick(PropRecord* prop);
|
u8 explosionChrpropSmokeTick(PropRecord* prop);
|
||||||
u8 explosionChrpropExplosionTick(PropRecord* prop);
|
u8 explosionChrpropExplosionTick(PropRecord* prop);
|
||||||
|
|||||||
Reference in new issue
Block a user