Finish up portal trail effect

This commit is contained in:
James Lambert 2023-09-18 21:08:52 -06:00
parent 65eebe53d3
commit 55fa62c57e
11 changed files with 144 additions and 36 deletions

View file

@ -1146,7 +1146,7 @@ materials:
gDPSetCombineMode:
color: ["1", "PRIMITIVE", "TEXEL0", "PRIMITIVE"]
alpha: ["TEXEL0", "0", "SHADE", "0"]
alpha: ["TEXEL0", "PRIMITIVE", "SHADE", "0"]
gSPGeometryMode:
clear: [G_CULL_BACK, G_CULL_FRONT, G_ZBUFFER]
set: [G_FOG]

View file

@ -1 +1 @@
-m assets/materials/static.skm.yaml --rotate 0,0,0 --sort-dir 0,1,0 --default-material brightglow_y
-m assets/materials/static.skm.yaml --default-material portal_trail

View file

@ -1,41 +1,81 @@
#include "portal_trail.h"
#include "../math/vector2.h"
#include "../math/mathf.h"
#include "../defs.h"
#include "../build/assets/models/portal_gun/ball_trail.h"
#include "../build/assets/materials/static.h"
#include "../graphics/color.h"
#include "../util/time.h"
#define TRAIL_LENGTH 8.0f
#define FADE_IN_LENGTH 4.0f
#define SEGMENT_LENGTH 2.0f
#define SEGMENT_ROTATION (152 * M_PI / 180.0f)
struct Transform gTrailSectionOffset = {
{0.0f, 0.0f, -8.0f},
{0.0f, 0.0f, -SEGMENT_LENGTH},
{0.0f, 0.0f, 0.0f, 1.0f},
{1.0f, 1.0f, 1.0f},
};
void portalTrailInit(struct PortalTrail* trail) {
quatAxisAngle(&gForward, SEGMENT_ROTATION, &gTrailSectionOffset.rotation);
transformToMatrixL(&gTrailSectionOffset, &trail->sectionOffset, SCENE_SCALE);
guMtxIdent(&trail->baseTransform[0]);
guMtxIdent(&trail->baseTransform[1]);
trail->currentBaseTransform = 0;
trail->lastDistance = 0.0f;
trail->maxDistance = -TRAIL_LENGTH;
}
void portalTrailUpdateBaseTransform(struct PortalTrail* trail) {
trail->currentBaseTransform ^= 1;
transformToMatrixL(&trail->trailTransform, &trail->baseTransform[trail->currentBaseTransform], SCENE_SCALE);
osWritebackDCache(&trail->baseTransform[trail->currentBaseTransform], sizeof(Mtx));
}
void portalTrailPlay(struct PortalTrail* trail, struct Vector3* from, struct Vector3* to) {
trail->trailTransform.position = *from;
struct Vector3 dir;
vector3Sub(to, from, &dir);
quatLook(&dir, &gUp, &trail->trailTransform.rotation);
struct Vector3 randomUp;
randomUp.x = randomInRangef(-1.0f, 1.0f);
randomUp.y = randomInRangef(-1.0f, 1.0f);
randomUp.z = randomInRangef(-1.0f, 1.0f);
quatLook(&dir, &randomUp, &trail->trailTransform.rotation);
vector3Normalize(&dir, &trail->direction);
trail->trailTransform.scale = gOneVec;
trail->currentBaseTransform ^= 1;
portalTrailUpdateBaseTransform(trail);
transformToMatrixL(&trail->trailTransform, &trail->baseTransform[trail->currentBaseTransform], SCENE_SCALE);
osWritebackDCache(&trail->baseTransform[trail->currentBaseTransform], sizeof(Mtx));
trail->lastDistance = 0.0f;
trail->maxDistance = vector3Dot(&dir, &trail->direction);
if (trail->maxDistance < SEGMENT_LENGTH) {
trail->maxDistance = -TRAIL_LENGTH;
}
}
void portalTrailUpdate(struct PortalTrail* trail, float distance) {
void portalTrailUpdate(struct PortalTrail* trail) {
if (trail->lastDistance >= trail->maxDistance + TRAIL_LENGTH) {
return;
}
trail->lastDistance += FIXED_DELTA_TIME * PORTAL_PROJECTILE_SPEED;
if (trail->lastDistance > TRAIL_LENGTH + SEGMENT_LENGTH) {
trail->lastDistance -= SEGMENT_LENGTH;
trail->maxDistance -= SEGMENT_LENGTH;
struct Transform tmp;
transformConcat(&trail->trailTransform, &gTrailSectionOffset, &tmp);
trail->trailTransform = tmp;
portalTrailUpdateBaseTransform(trail);
}
}
struct Coloru8 gTrailColor[] = {
@ -43,16 +83,73 @@ struct Coloru8 gTrailColor[] = {
{50, 70, 200, 255},
};
void portalTrailRender(struct PortalTrail* trail, struct RenderState* renderState, struct MaterialState* materialState) {
void portalTrailRender(struct PortalTrail* trail, struct RenderState* renderState, struct MaterialState* materialState, struct Camera* fromCamera, int portalIndex) {
if (trail->lastDistance >= trail->maxDistance + TRAIL_LENGTH) {
return;
}
materialStateSet(materialState, PORTAL_TRAIL_INDEX, renderState);
struct Coloru8* color = &gTrailColor[0];
gSPFogPosition(renderState->dl++, 800, 999);
gDPSetPrimColor(renderState->dl++, 255, 255, color->r, color->g, color->b, color->a);
struct Coloru8* color = &gTrailColor[portalIndex];
struct Ray cameraRay;
cameraRay.origin = fromCamera->transform.position;
quatMultVector(&fromCamera->transform.rotation, &gForward, &cameraRay.dir);
vector3Negate(&cameraRay.dir, &cameraRay.dir);
struct Vector3 pointAlongTrail;
vector3AddScaled(&trail->trailTransform.position, &trail->direction, trail->lastDistance - TRAIL_LENGTH, &pointAlongTrail);
int minDistance = fogIntValue(cameraClipDistance(fromCamera, rayDetermineDistance(&cameraRay, &pointAlongTrail)));
vector3AddScaled(&trail->trailTransform.position, &trail->direction, trail->lastDistance, &pointAlongTrail);
int maxDistance = fogIntValue(cameraClipDistance(fromCamera, rayDetermineDistance(&cameraRay, &pointAlongTrail)));
if (maxDistance <= minDistance) {
maxDistance = minDistance + 1;
if (maxDistance > 1000) {
maxDistance = 1000;
minDistance = 999;
}
}
float currentDistance = trail->lastDistance - TRAIL_LENGTH;
int alpha = 0;
if (currentDistance < -(TRAIL_LENGTH - FADE_IN_LENGTH)) {
alpha = (int)(((TRAIL_LENGTH - FADE_IN_LENGTH) + currentDistance) * (-255.0f / TRAIL_LENGTH));
if (alpha < 0) {
alpha = 0;
}
if (alpha > 255) {
alpha = 255;
}
}
gSPFogPosition(renderState->dl++, minDistance, maxDistance);
gDPSetPrimColor(renderState->dl++, 255, 255, color->r, color->g, color->b, alpha);
gSPMatrix(renderState->dl++, &trail->baseTransform[trail->currentBaseTransform], G_MTX_MODELVIEW | G_MTX_PUSH | G_MTX_MUL);
gSPDisplayList(renderState->dl++, portal_gun_ball_trail_model_gfx);
int hasMore = 1;
while (hasMore) {
currentDistance += SEGMENT_LENGTH;
hasMore = currentDistance < trail->lastDistance && currentDistance < trail->maxDistance;
if (currentDistance <= 0.0f) {
continue;
}
gSPDisplayList(renderState->dl++, portal_gun_ball_trail_model_gfx);
if (hasMore) {
gSPMatrix(renderState->dl++, &trail->sectionOffset, G_MTX_MODELVIEW | G_MTX_NOPUSH | G_MTX_MUL);
}
}
gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW);
}

View file

@ -8,18 +8,23 @@
#include "../math/transform.h"
#include "../graphics/renderstate.h"
#include "../levels/material_state.h"
#include "../scene/camera.h"
#define PORTAL_PROJECTILE_SPEED 50.0f
struct PortalTrail {
struct Transform trailTransform;
Mtx sectionOffset;
Mtx baseTransform[2];
struct Vector3 chunkOffset;
struct Vector3 direction;
short currentBaseTransform;
float lastDistance;
float maxDistance;
};
void portalTrailInit(struct PortalTrail* trail);
void portalTrailPlay(struct PortalTrail* trail, struct Vector3* from, struct Vector3* to);
void portalTrailUpdate(struct PortalTrail* trail, float distance);
void portalTrailRender(struct PortalTrail* trail, struct RenderState* renderState, struct MaterialState* materialState);
void portalTrailUpdate(struct PortalTrail* trail);
void portalTrailRender(struct PortalTrail* trail, struct RenderState* renderState, struct MaterialState* materialState, struct Camera* fromCamera, int portalIndex);
#endif

View file

@ -194,4 +194,16 @@ float cameraClipDistance(struct Camera* camera, float distance) {
}
return -((camera->nearPlane + camera->farPlane) * modifiedDistance + 2.0f * camera->nearPlane * camera->farPlane) / denom;
}
int fogIntValue(float floatValue) {
if (floatValue < -1.0) {
return 0;
}
if (floatValue > 1.0) {
return 1000;
}
return (int)((floatValue + 1.0f) * 500.0f);
}

View file

@ -47,4 +47,6 @@ int cameraApplyMatrices(struct RenderState* renderState, struct CameraMatrixInfo
float cameraClipDistance(struct Camera* camera, float distance);
int fogIntValue(float floatValue);
#endif

View file

@ -14,6 +14,8 @@
#define PORTAL_GUN_RECOIL_TIME (0.18f)
#define PORTAL_GUN_NEAR_PLANE 0.05f
struct Vector2 gGunColliderEdgeVectors[] = {
{0.0f, 1.0f},
{0.707f, 0.707f},
@ -108,20 +110,20 @@ void portalBallRender(struct PortalGunProjectile* projectile, struct RenderState
gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW);
}
void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState, struct Transform* fromView) {
void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState, struct Camera* fromCamera) {
struct MaterialState materialState;
materialStateInit(&materialState, DEFAULT_INDEX);
for (int i = 0; i < 2; ++i) {
struct PortalGunProjectile* projectile = &portalGun->projectiles[i];
portalTrailRender(&projectile->trail, renderState, &materialState);
portalTrailRender(&projectile->trail, renderState, &materialState, fromCamera, i);
if (projectile->roomIndex == -1) {
continue;
}
portalBallRender(projectile, renderState, &materialState, fromView, i);
portalBallRender(projectile, renderState, &materialState, &fromCamera->transform, i);
}
portalGun->rigidBody.transform.scale = gOneVec;
@ -131,6 +133,8 @@ void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* render
return;
}
cameraModifyProjectionViewForPortalGun(fromCamera, renderState, PORTAL_GUN_NEAR_PLANE * SCENE_SCALE, (float)SCREEN_WD / (float)SCREEN_HT);
transformToMatrixL(&portalGun->rigidBody.transform, matrix, SCENE_SCALE);
gSPMatrix(renderState->dl++, matrix, G_MTX_MODELVIEW | G_MTX_PUSH | G_MTX_MUL);
gSPDisplayList(renderState->dl++, portal_gun_v_portalgun_model_gfx);
@ -138,7 +142,6 @@ void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* render
}
#define NO_HIT_DISTANCE 20.0f
#define PORTAL_PROJECTILE_SPEED 50.0f
#define MAX_PROJECTILE_DISTANCE 100.0f
void portalGunUpdate(struct PortalGun* portalGun, struct Player* player) {
@ -163,6 +166,8 @@ void portalGunUpdate(struct PortalGun* portalGun, struct Player* player) {
for (int i = 0; i < 2; ++i) {
struct PortalGunProjectile* projectile = &portalGun->projectiles[i];
portalTrailUpdate(&projectile->trail);
if (projectile->roomIndex == -1) {
continue;
}

View file

@ -10,6 +10,7 @@
#include "../player/player.h"
#include "../util/time.h"
#include "../effects/portal_trail.h"
#include "../scene/camera.h"
struct PortalGunProjectile {
struct Ray positionDirection;
@ -38,7 +39,7 @@ struct PortalGun {
void portalGunInit(struct PortalGun* portalGun, struct Transform* at);
// void portalGunDummyRender(void* data, struct DynamicRenderDataList* renderList, struct RenderState* renderState);
void portalGunUpdate(struct PortalGun* portalGun, struct Player* player);
void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState, struct Transform* fromView);
void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState, struct Camera* fromCamera);
void portalGunFire(struct PortalGun* portalGun, int portalIndex, struct Ray* ray, struct Vector3* playerUp, int roomIndex);

View file

@ -471,18 +471,6 @@ void renderPlanBuild(struct RenderPlan* renderPlan, struct Scene* scene, struct
#define MIN_FOG_DISTANCE 1.0f
#define MAX_FOG_DISTANCE 2.5f
int fogIntValue(float floatValue) {
if (floatValue < -1.0) {
return 0;
}
if (floatValue > 1.0) {
return 1000;
}
return (int)((floatValue + 1.0f) * 500.0f);
}
void renderPlanExecute(struct RenderPlan* renderPlan, struct Scene* scene, Mtx* staticTransforms, struct RenderState* renderState) {
struct DynamicRenderDataList* dynamicList = dynamicRenderListNew(renderState, MAX_DYNAMIC_SCENE_OBJECTS);

View file

@ -6,7 +6,6 @@
#define DEFAULT_FAR_PLANE 30.0f
#define DEFAULT_NEAR_PLANE 0.125f
#define PORTAL_GUN_NEAR_PLANE 0.05f
#define MAX_PORTAL_STEPS 6

View file

@ -306,8 +306,7 @@ void sceneRender(struct Scene* scene, struct RenderState* renderState, struct Gr
renderPlanExecute(&renderPlan, scene, staticMatrices, renderState);
if (scene->portalGun.portalGunVisible){
cameraModifyProjectionViewForPortalGun(&scene->camera, renderState, PORTAL_GUN_NEAR_PLANE * SCENE_SCALE, renderPlan.stageProps[0].aspectRatio);
portalGunRenderReal(&scene->portalGun, renderState, &scene->camera.transform);
portalGunRenderReal(&scene->portalGun, renderState, &scene->camera);
}
gDPPipeSync(renderState->dl++);