Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wind Waker: Particle system improvements #739

Merged
merged 25 commits into from
Jan 4, 2025
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
68f7dc7
Wind Waker: Split dPa_control_c init into common and scene
themikelester Jan 1, 2025
3c32a75
Wind Waker: Replace Particle.ts EffectDrawGroup with ParticleGroup
themikelester Jan 1, 2025
c166533
JPA: Fix misplaced `workData.volumeEmitCount = this.emitCount`
themikelester Jan 1, 2025
ee2103d
Wind Waker: Introducing "simple" emitters
themikelester Jan 1, 2025
8b055af
Wind Waker: "Simple" particles can now access the framebuffer
themikelester Jan 1, 2025
0571751
Wind Waker: Fix common particles spawning once on scene creation
themikelester Jan 1, 2025
2f74099
Formatting improvements
themikelester Jan 1, 2025
ab74ba4
Wind Waker: d_a_ep now uses simple particles
themikelester Jan 1, 2025
03ccde5
Wind Waker: Small note regarding simple particles ignoring emitter tr…
themikelester Jan 3, 2025
a70ff02
Wind Waker: Remove indirect particle hack
themikelester Jan 3, 2025
2f587b1
Wind Waker: Simple particle emitters are cleared every frame
themikelester Jan 3, 2025
ccc5706
Wind Waker: Fixup d_a_ep (torch) actor. The default state now matches…
themikelester Jan 3, 2025
eb9f410
Wind Waker: Allow type 2 d_a_ep to render flames
themikelester Jan 3, 2025
aa99a35
Wind Waker: Explicit return types for d_particle functions
themikelester Jan 3, 2025
2c1e8f7
Wind Waker: Fixed TODO - d_a_obj_flame now uses simple particle emitters
themikelester Jan 3, 2025
8c65343
Wind Waker: Remove old `patchResData` indirect particles hack
themikelester Jan 3, 2025
07df049
Wind Waker: Add frustum culling for simple emitters
themikelester Jan 3, 2025
d830542
Wind Waker: Don't distance cull 2D/UI particle emitters
themikelester Jan 3, 2025
b09e553
J2D: Add `J2DGrafContext.getFrustumForView()`
themikelester Jan 3, 2025
ca3419e
Wind Waker: Draw 2D/UI particle groups with ortho view/proj matrices
themikelester Jan 3, 2025
8740623
Wind Waker: Implement first 2D emitter for d_a_title
themikelester Jan 3, 2025
fe73bef
Wind Waker: Add sparkle emitter to d_a_title
themikelester Jan 3, 2025
a88d2c1
Wind Waker: Add new drawlists for fore/background 2D particles
themikelester Jan 3, 2025
d39b97a
Wind Waker: Don't frustum cull 2D particles
themikelester Jan 4, 2025
b1099c1
Wind Waker: Use computeModelMatrixT to avoid list creation
themikelester Jan 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion src/Common/JSYSTEM/J2Dv1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { BTIData } from "./JUTTexture.js";
import { GXMaterialBuilder } from "../../gx/GXMaterialBuilder.js";
import { mat4, vec2, vec4 } from "gl-matrix";
import { GfxRenderCache } from "../../gfx/render/GfxRenderCache.js";
import { Frustum } from "../../Geometry.js";

const materialParams = new MaterialParams();
const drawParams = new DrawParams();
Expand Down Expand Up @@ -80,10 +81,11 @@ const enum J2DUVBinding {

export class J2DGrafContext {
private clipSpaceNearZ: GfxClipSpaceNearZ;
private frustum = new Frustum();

public sceneParams = new SceneParams();
public viewport = vec4.create();
public ortho = vec4.create();

public near: number;
public far: number;

Expand Down Expand Up @@ -118,6 +120,18 @@ export class J2DGrafContext {

projectionMatrixForCuboid(this.sceneParams.u_Projection, left, right, bottom, top, this.near, this.far);
projectionMatrixConvertClipSpaceNearZ(this.sceneParams.u_Projection, this.clipSpaceNearZ, GfxClipSpaceNearZ.NegativeOne);

}

/**
* noclip modification:
* Given a view matrix, return a Frustum which can be used for culling.
* In the original game, frustums are generated from proj matrices alone. But noclip expects viewProj frustums.
*/
public getFrustumForView(viewFromWorldMatrix: mat4): Frustum {
const clipFromWorldMatrix = mat4.mul(scratchMat, this.sceneParams.u_Projection, viewFromWorldMatrix);
this.frustum.updateClipFrustum(clipFromWorldMatrix, this.clipSpaceNearZ);
themikelester marked this conversation as resolved.
Show resolved Hide resolved
return this.frustum;
}

public setOnRenderInst(renderInst: GfxRenderInst): void {
Expand Down
5 changes: 3 additions & 2 deletions src/Common/JSYSTEM/JPA.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1711,7 +1711,7 @@ export class JPABaseEmitter {
throw "whoops";
}

private createParticle(): JPABaseParticle | null {
public createParticle(): JPABaseParticle | null {
if (this.emitterManager.deadParticlePool.length === 0)
return null;

Expand All @@ -1736,7 +1736,6 @@ export class JPABaseEmitter {
this.emitCount = bem1.divNumber * bem1.divNumber * 4 + 2;
else
this.emitCount = bem1.divNumber;
workData.volumeEmitCount = this.emitCount;
workData.volumeEmitIdx = 0;
} else {
// Rate
Expand All @@ -1748,6 +1747,8 @@ export class JPABaseEmitter {
this.emitCount = 1;
}

workData.volumeEmitCount = this.emitCount;

if (!!(this.status & JPAEmitterStatus.STOP_CREATE_PARTICLE))
this.emitCount = 0;

Expand Down
40 changes: 29 additions & 11 deletions src/ZeldaWindWaker/Main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { EDemoMode, dDemo_manager_c } from './d_demo.js';
import { dDlst_list_Set, dDlst_list_c } from './d_drawlist.js';
import { dKankyo_create, dKy__RegisterConstructors, dKy_setLight, dScnKy_env_light_c } from './d_kankyo.js';
import { dKyw__RegisterConstructors } from './d_kankyo_wether.js';
import { dPa_control_c } from './d_particle.js';
import { dPa_control_c, ParticleGroup } from './d_particle.js';
import { Placename, PlacenameState, dPn__update, d_pn__RegisterConstructors } from './d_place_name.js';
import { dProcName_e } from './d_procname.js';
import { ResType, dRes_control_c } from './d_resorce.js';
Expand Down Expand Up @@ -403,18 +403,37 @@ export class WindWakerRenderer implements Viewer.SceneGfx {
{
globals.particleCtrl.calc(globals, viewerInput);

for (let group = EffectDrawGroup.Main; group <= EffectDrawGroup.Indirect; group++) {
for (let group = ParticleGroup.Normal; group <= ParticleGroup.Wind; group++) {
let texPrjMtx: mat4 | null = null;

if (group === EffectDrawGroup.Indirect) {
if (group === ParticleGroup.Projection) {
texPrjMtx = scratchMatrix;
texProjCameraSceneTex(texPrjMtx, globals.camera.clipFromViewMatrix, 1);
}

globals.particleCtrl.setDrawInfo(globals.camera.viewFromWorldMatrix, globals.camera.clipFromViewMatrix, texPrjMtx, globals.camera.frustum);
renderInstManager.setCurrentList(dlst.effect[group]);
renderInstManager.setCurrentList(dlst.effect[group == ParticleGroup.Projection ? EffectDrawGroup.Indirect : EffectDrawGroup.Main]);
globals.particleCtrl.draw(device, this.renderHelper.renderInstManager, group);
}

// From mDoGph_Painter(). Draw the 2D particle groups with different view/proj matrices.
{
const orthoCtx = this.globals.scnPlay.currentGrafPort;
const viewMtx = mat4.fromTranslation(scratchMatrix, [orthoCtx.aspectRatioCorrection * 320, 240, 0]);
themikelester marked this conversation as resolved.
Show resolved Hide resolved
const frustum = orthoCtx.getFrustumForView(viewMtx);
const template = renderInstManager.pushTemplate();
orthoCtx.setOnRenderInst(template);

globals.particleCtrl.setDrawInfo(viewMtx, orthoCtx.sceneParams.u_Projection, null, frustum);

renderInstManager.setCurrentList(dlst.particle2DBack);
globals.particleCtrl.draw(device, this.renderHelper.renderInstManager, ParticleGroup.TwoDback);
globals.particleCtrl.draw(device, this.renderHelper.renderInstManager, ParticleGroup.TwoDmenuBack);

renderInstManager.setCurrentList(dlst.particle2DFore);
globals.particleCtrl.draw(device, this.renderHelper.renderInstManager, ParticleGroup.TwoDfore);
globals.particleCtrl.draw(device, this.renderHelper.renderInstManager, ParticleGroup.TwoDmenuFore);
}
}

this.renderHelper.renderInstManager.popTemplate();
Expand Down Expand Up @@ -481,9 +500,11 @@ export class WindWakerRenderer implements Viewer.SceneGfx {

this.executeList(passRenderer, dlst.effect[EffectDrawGroup.Main]);
this.executeList(passRenderer, dlst.wetherEffect);
this.executeListSet(passRenderer, dlst.ui);

this.executeList(passRenderer, dlst.particle2DBack);
this.executeListSet(passRenderer, dlst.ui);
this.executeListSet(passRenderer, dlst.ui2D);
this.executeList(passRenderer, dlst.particle2DFore);
});
});

Expand Down Expand Up @@ -823,12 +844,9 @@ class SceneDesc {

renderer.extraTextures = new ZWWExtraTextures(device, ZAtoon, ZBtoonEX);

const jpac: JPA.JPAC[] = [];
for (let i = 0; i < particleArchives.length; i++) {
const jpacData = modelCache.getFileData(particleArchives[i]);
jpac.push(JPA.parse(jpacData));
}
globals.particleCtrl = new dPa_control_c(renderer.renderCache, jpac);
globals.particleCtrl = new dPa_control_c(renderer.renderCache);
globals.particleCtrl.createCommon(globals, JPA.parse(modelCache.getFileData(particleArchives[0])));
globals.particleCtrl.createRoomScene(globals, JPA.parse(modelCache.getFileData(particleArchives[1])));

// dStage_Create
dKankyo_create(globals);
Expand Down
Loading
Loading