diff --git a/src/Camera.ts b/src/Camera.ts index 3e38cdfa2..5d93cfe4f 100644 --- a/src/Camera.ts +++ b/src/Camera.ts @@ -1021,8 +1021,8 @@ export function deserializeCamera(camera: Camera, view: DataView, byteOffs: numb return 0x04*4*3; } -function texProjCamera(dst: mat4, camera: Camera, scaleS: number, scaleT: number, transS: number, transT: number): void { - const projMtx = camera.projectionMatrix; +function texProjCamera(dst: mat4, clipFromViewMatrix: ReadonlyMat4, scaleS: number, scaleT: number, transS: number, transT: number): void { + const projMtx = clipFromViewMatrix; // Avoid multiplications where we know the result will be 0. dst[0] = projMtx[0] * scaleS; @@ -1049,8 +1049,8 @@ function texProjCamera(dst: mat4, camera: Camera, scaleS: number, scaleT: number dst[15] = 9999.0; } -export function texProjCameraSceneTex(dst: mat4, camera: Camera, flipYScale: number): void { +export function texProjCameraSceneTex(dst: mat4, clipFromViewMatrix: ReadonlyMat4, flipYScale: number): void { // Map from -1 to 1 to 0 to 1. let scaleS = 0.5, scaleT = -0.5 * flipYScale, transS = 0.5, transT = 0.5; - texProjCamera(dst, camera, scaleS, scaleT, transS, transT); + texProjCamera(dst, clipFromViewMatrix, scaleS, scaleT, transS, transT); } diff --git a/src/Common/JSYSTEM/J3D/J3DGraphBase.ts b/src/Common/JSYSTEM/J3D/J3DGraphBase.ts index 46b306652..77d25b2be 100644 --- a/src/Common/JSYSTEM/J3D/J3DGraphBase.ts +++ b/src/Common/JSYSTEM/J3D/J3DGraphBase.ts @@ -5,12 +5,12 @@ import { BMD, MaterialEntry, Shape, ShapeMtxType, DRW1MatrixKind, TEX1, INF1, Hi import * as GX_Material from '../../../gx/gx_material.js'; import { DrawParams, ColorKind, loadTextureFromMipChain, loadedDataCoalescerComboGfx, MaterialParams, fillIndTexMtx, setChanWriteEnabled, createInputLayout } from '../../../gx/gx_render.js'; -import { GXShapeHelperGfx, GXMaterialHelperGfx } from '../../../gx/gx_render.js'; +import { GXMaterialHelperGfx } from '../../../gx/gx_render.js'; import { Camera, computeViewSpaceDepthFromWorldSpaceAABB, texProjCameraSceneTex } from '../../../Camera.js'; import { TextureMapping } from '../../../TextureHolder.js'; import { nArray, assert, assertExists } from '../../../util.js'; -import { AABB } from '../../../Geometry.js'; +import { AABB, Frustum } from '../../../Geometry.js'; import { GfxDevice, GfxSampler, GfxTexture, GfxChannelWriteMask, GfxFormat, GfxInputLayout, GfxVertexBufferDescriptor, GfxIndexBufferDescriptor } from '../../../gfx/platform/GfxPlatform.js'; import { GfxCoalescedBuffersCombo, GfxBufferCoalescerCombo } from '../../../gfx/helpers/BufferHelpers.js'; import { Texture } from '../../../viewer.js'; @@ -38,7 +38,7 @@ export class ShapeInstanceState { public drawViewMatrixVisibility: boolean[] = []; // The camera's view matrix. - public worldToViewMatrix = mat4.create(); + public viewFromWorldMatrix = mat4.create(); // Used while calculating joint matrices. // public currentScale = vec3.create(); @@ -88,7 +88,7 @@ export class ShapeData { } export class MaterialData { - public fillMaterialParamsCallback: ((materialParams: MaterialParams, materialInstance: MaterialInstance, viewMatrix: ReadonlyMat4, modelMatrix: ReadonlyMat4, camera: Camera, drawParams: DrawParams) => void) | null = null; + public fillMaterialParamsCallback: ((materialParams: MaterialParams, materialInstance: MaterialInstance, clipFromViewMatrix: ReadonlyMat4, viewFromWorldMatrix: ReadonlyMat4, modelMatrix: ReadonlyMat4, drawParams: DrawParams) => void) | null = null; constructor(public material: MaterialEntry) { } @@ -134,7 +134,7 @@ export class ShapeInstance { constructor(public shapeData: ShapeData) { } - public prepareToRender(device: GfxDevice, renderInstManager: GfxRenderInstManager, depth: number, camera: Camera, materialInstance: MaterialInstance, modelData: J3DModelData, materialInstanceState: MaterialInstanceState, shapeInstanceState: ShapeInstanceState): void { + public prepareToRender(renderInstManager: GfxRenderInstManager, viewDepth: number, clipFromViewMatrix: ReadonlyMat4, materialInstance: MaterialInstance, modelData: J3DModelData, materialInstanceState: MaterialInstanceState, shapeInstanceState: ShapeInstanceState): void { if (!this.visible) return; @@ -147,14 +147,14 @@ export class ShapeInstance { const template = renderInstManager.pushTemplate(); template.sortKey = materialInstance.sortKey; - template.sortKey = setSortKeyDepth(template.sortKey, depth); + template.sortKey = setSortKeyDepth(template.sortKey, viewDepth); template.sortKey = setSortKeyBias(template.sortKey, this.shapeData.sortKeyBias); materialInstance.setOnRenderInst(renderInstManager.gfxRenderCache, template); const multi = shape.shapeMtxType === ShapeMtxType.Multi; if (!multi) - materialInstance.fillMaterialParams(template, materialInstanceState, shapeInstanceState.worldToViewMatrix, materialJointMatrix, camera, drawParams); + materialInstance.fillMaterialParams(template, materialInstanceState, clipFromViewMatrix, shapeInstanceState.viewFromWorldMatrix, materialJointMatrix, drawParams); for (let i = 0; i < shape.mtxGroups.length; i++) { if (!prepareShapeMtxGroup(drawParams, shapeInstanceState, shape, shape.mtxGroups[i])) @@ -165,7 +165,7 @@ export class ShapeInstance { materialInstance.materialHelper.allocateDrawParamsDataOnInst(renderInst, drawParams); if (multi) - materialInstance.fillMaterialParams(renderInst, materialInstanceState, shapeInstanceState.worldToViewMatrix, materialJointMatrix, camera, drawParams); + materialInstance.fillMaterialParams(renderInst, materialInstanceState, clipFromViewMatrix, shapeInstanceState.viewFromWorldMatrix, materialJointMatrix, drawParams); renderInstManager.submitRenderInst(renderInst); } @@ -373,7 +373,7 @@ export class MaterialInstance { const matrixMode: TexMtxMapMode = texMtx.info & 0x3F; // ref. J3DTexGenBlockPatched::calc() - switch (matrixMode as number) { + switch (matrixMode) { case TexMtxMapMode.EnvmapBasic: case TexMtxMapMode.EnvmapOld: case TexMtxMapMode.Envmap: @@ -390,7 +390,7 @@ export class MaterialInstance { mat4.copy(dst, modelViewMatrix); break; - case 0x05: + case TexMtxMapMode.Unk0x05: case TexMtxMapMode.EnvmapOldEffectMtx: case TexMtxMapMode.EnvmapEffectMtx: computeMatrixWithoutTranslation(dst, modelMatrix); @@ -407,7 +407,7 @@ export class MaterialInstance { const matrixMode: TexMtxMapMode = texMtx.info & 0x3F; // ref. J3DTexGenBlockPatched::calcPostTexMtx() - switch (matrixMode as number) { + switch (matrixMode) { case TexMtxMapMode.EnvmapBasic: case TexMtxMapMode.EnvmapOld: case TexMtxMapMode.Envmap: @@ -424,7 +424,7 @@ export class MaterialInstance { mat4.identity(dst); break; - case 0x05: + case TexMtxMapMode.Unk0x05: case TexMtxMapMode.EnvmapOldEffectMtx: case TexMtxMapMode.EnvmapEffectMtx: mat4.invert(dst, viewMatrix); @@ -448,7 +448,7 @@ export class MaterialInstance { } } - public calcTexMtx(dst: mat4, texMtx: TexMtx, texSRT: ReadonlyMat4, modelMatrix: ReadonlyMat4, camera: Camera, flipY: boolean): void { + public calcTexMtx(dst: mat4, texMtx: TexMtx, texSRT: ReadonlyMat4, modelMatrix: ReadonlyMat4, clipFromViewMatrix: ReadonlyMat4, flipY: boolean): void { // The input matrix is passed in in dst. const matrixMode: TexMtxMapMode = texMtx.info & 0x3F; @@ -457,145 +457,117 @@ export class MaterialInstance { // ref. J3DTexMtx::calc() const tmp1 = scratchMat4a; const tmp2 = scratchMat4b; - switch (matrixMode as number) { + switch (matrixMode) { case TexMtxMapMode.EnvmapBasic: - { - // J3DGetTextureMtxOld(tmp1) - J3DGetTextureMtxOld(tmp1, texSRT); - - // PSMTXConcat(tmp1, inputMatrix, this->finalMatrix) - mat43Concat(dst, tmp1, dst); - } + // J3DGetTextureMtxOld(tmp1) + // PSMTXConcat(tmp1, inputMatrix, this->finalMatrix) + mat43Concat(dst, texSRT, dst); break; case TexMtxMapMode.ProjmapBasic: case TexMtxMapMode.ViewProjmapBasic: - case 0x05: - { - // J3DGetTextureMtxOld(tmp2) - J3DGetTextureMtxOld(tmp2, texSRT); - - mtxFlipY(dst, flipY); - - // J3DMtxProjConcat(tmp2, this->effectMtx, tmp1) - J3DMtxProjConcat(tmp1, tmp2, texMtx.effectMatrix); - // PSMTXConcat(tmp1, inputMatrix, this->finalMatrix) - mat43Concat(dst, tmp1, dst); - } + case TexMtxMapMode.Unk0x05: + mtxFlipY(dst, flipY); + + // J3DGetTextureMtxOld(tmp2) + // J3DMtxProjConcat(tmp2, this->effectMtx, tmp1) + J3DMtxProjConcat(tmp1, texSRT, texMtx.effectMatrix); + // PSMTXConcat(tmp1, inputMatrix, this->finalMatrix) + mat43Concat(dst, tmp1, dst); break; - case 0x04: - { - // J3DGetTextureMtxOld(tmp2) - J3DGetTextureMtxOld(tmp2, texSRT); + case TexMtxMapMode.Unk0x04: + mtxFlipY(dst, flipY); - mtxFlipY(dst, flipY); - - // J3DMtxProjConcat(tmp2, this->effectMtx, this->finalMatrix); - J3DMtxProjConcat(dst, tmp2, texMtx.effectMatrix); - } + // J3DGetTextureMtxOld(tmp2) + // J3DMtxProjConcat(tmp2, this->effectMtx, this->finalMatrix); + J3DMtxProjConcat(dst, texSRT, texMtx.effectMatrix); break; case TexMtxMapMode.EnvmapOld: - { - // J3DGetTextureMtxOld(tmp1) - J3DGetTextureMtxOld(tmp1, texSRT); - - // PSMTXConcat(tmp1, EnvMtxOld, tmp1) - buildEnvMtxOld(tmp2, flipYScale); - mat43Concat(tmp1, tmp1, tmp2); + // J3DGetTextureMtxOld(tmp1) + // PSMTXConcat(tmp1, EnvMtxOld, tmp1) + buildEnvMtxOld(tmp2, flipYScale); + mat43Concat(tmp1, texSRT, tmp2); - // PSMTXConcat(tmp1, inputMatrix, this->finalMatrix) - mat43Concat(dst, tmp1, dst); - } + // PSMTXConcat(tmp1, inputMatrix, this->finalMatrix) + mat43Concat(dst, tmp1, dst); break; case TexMtxMapMode.Envmap: - { - // J3DGetTextureMtx(tmp1) - J3DGetTextureMtx(tmp1, texSRT); + // J3DGetTextureMtx(tmp1) + J3DGetTextureMtx(tmp1, texSRT); - // PSMTXConcat(tmp1, EnvMtx, tmp1) - buildEnvMtx(tmp2, flipYScale); - mat43Concat(tmp1, tmp1, tmp2); + // PSMTXConcat(tmp1, EnvMtx, tmp1) + buildEnvMtx(tmp2, flipYScale); + mat43Concat(tmp1, tmp1, tmp2); - // PSMTXConcat(tmp1, inputMatrix, this->finalMatrix) - mat43Concat(dst, tmp1, dst); - } + // PSMTXConcat(tmp1, inputMatrix, this->finalMatrix) + mat43Concat(dst, tmp1, dst); break; case TexMtxMapMode.Projmap: case TexMtxMapMode.ViewProjmap: case TexMtxMapMode.EnvmapEffectMtx: - { - // J3DGetTextureMtx(tmp2) - J3DGetTextureMtx(tmp2, texSRT); - - if (matrixMode === TexMtxMapMode.ViewProjmap) { - // The effect matrix here is a GameCube projection matrix. Swap it out with out own. - // In Galaxy, this is done in ViewProjmapEffectMtxSetter. - - // Replaces the effectMatrix. EnvMtx is built into this call, as well. - texProjCameraSceneTex(tmp1, camera, flipYScale); - - // J3DMtxProjConcat(tmp2, this->effectMtx, tmp1) - J3DMtxProjConcat(tmp1, tmp2, tmp1); - } else if (matrixMode === TexMtxMapMode.Projmap) { - // PSMTXConcat(tmp2, EnvMtx, tmp2) - buildEnvMtx(tmp1, flipYScale); - mat43Concat(tmp2, tmp2, tmp1); - - if (this.effectMtx !== null) { - mat4.mul(tmp1, this.effectMtx, tmp1); - } else { - // Multiply the effect matrix by the inverse of the model matrix. - // In Galaxy, this is done in ProjmapEffectMtxSetter. - mat4.invert(tmp1, modelMatrix); - mat4.mul(tmp1, texMtx.effectMatrix, tmp1); - } + // J3DGetTextureMtx(tmp2) + J3DGetTextureMtx(tmp2, texSRT); - // J3DMtxProjConcat(tmp2, this->effectMtx, tmp1) - J3DMtxProjConcat(tmp1, tmp2, tmp1); - } else { - // PSMTXConcat(tmp2, EnvMtx, tmp2) - buildEnvMtx(tmp1, flipYScale); - mat43Concat(tmp2, tmp2, tmp1); + if (matrixMode === TexMtxMapMode.ViewProjmap) { + // The effect matrix here is a GameCube projection matrix. Swap it out with out own. + // In Galaxy, this is done in ViewProjmapEffectMtxSetter. - // J3DMtxProjConcat(tmp2, this->effectMtx, tmp1) - const effectMtx = this.effectMtx !== null ? this.effectMtx : texMtx.effectMatrix; - J3DMtxProjConcat(tmp1, tmp2, effectMtx); - } + // Replaces the effectMatrix. EnvMtx is built into this call, as well. + texProjCameraSceneTex(tmp1, clipFromViewMatrix, flipYScale); - // PSMTXConcat(tmp1, inputMatrix, this->finalMatrix) - mat43Concat(dst, tmp1, dst); - } - break; + // J3DMtxProjConcat(tmp2, this->effectMtx, tmp1) + J3DMtxProjConcat(tmp1, tmp2, tmp1); + } else if (matrixMode === TexMtxMapMode.Projmap) { + // PSMTXConcat(tmp2, EnvMtx, tmp2) + buildEnvMtx(tmp1, flipYScale); + mat43Concat(tmp2, tmp2, tmp1); - case TexMtxMapMode.EnvmapOldEffectMtx: - { - // J3DGetTextureMtxOld(tmp2) - J3DGetTextureMtxOld(tmp2, texSRT); + if (this.effectMtx !== null) { + mat4.mul(tmp1, this.effectMtx, tmp1); + } else { + // Multiply the effect matrix by the inverse of the model matrix. + // In Galaxy, this is done in ProjmapEffectMtxSetter. + mat4.invert(tmp1, modelMatrix); + mat4.mul(tmp1, texMtx.effectMatrix, tmp1); + } - // PSMTXConcat(tmp2, EnvMtxOld, tmp2) - buildEnvMtxOld(tmp1, flipYScale); + // J3DMtxProjConcat(tmp2, this->effectMtx, tmp1) + J3DMtxProjConcat(tmp1, tmp2, tmp1); + } else { + // PSMTXConcat(tmp2, EnvMtx, tmp2) + buildEnvMtx(tmp1, flipYScale); mat43Concat(tmp2, tmp2, tmp1); // J3DMtxProjConcat(tmp2, this->effectMtx, tmp1) const effectMtx = this.effectMtx !== null ? this.effectMtx : texMtx.effectMatrix; J3DMtxProjConcat(tmp1, tmp2, effectMtx); - - // PSMTXConcat(tmp1, inputMatrix, this->finalMatrix) - mat43Concat(dst, tmp1, dst); } + + // PSMTXConcat(tmp1, inputMatrix, this->finalMatrix) + mat43Concat(dst, tmp1, dst); break; - case TexMtxMapMode.None: - { - // J3DGetTextureMtxOld(this->finalMatrix) - J3DGetTextureMtxOld(dst, texSRT); + case TexMtxMapMode.EnvmapOldEffectMtx: + // J3DGetTextureMtxOld(tmp2) + // PSMTXConcat(tmp2, EnvMtxOld, tmp2) + buildEnvMtxOld(tmp1, flipYScale); + mat43Concat(tmp2, texSRT, tmp1); - mtxFlipY(dst, flipY); - } + // J3DMtxProjConcat(tmp2, this->effectMtx, tmp1) + const effectMtx = this.effectMtx !== null ? this.effectMtx : texMtx.effectMatrix; + J3DMtxProjConcat(tmp1, tmp2, effectMtx); + + // PSMTXConcat(tmp1, inputMatrix, this->finalMatrix) + mat43Concat(dst, tmp1, dst); + break; + + case TexMtxMapMode.None: + mat4.copy(dst, texSRT); + mtxFlipY(dst, flipY); break; default: @@ -603,7 +575,7 @@ export class MaterialInstance { } } - public fillOnMaterialParams(materialParams: MaterialParams, materialInstanceState: MaterialInstanceState, camera: Camera, modelMatrix: ReadonlyMat4, drawParams: DrawParams, viewMatrix: ReadonlyMat4 = camera.viewMatrix): void { + public fillOnMaterialParams(materialParams: MaterialParams, materialInstanceState: MaterialInstanceState, clipFromViewMatrix: ReadonlyMat4, viewFromWorldMatrix: ReadonlyMat4, modelMatrix: ReadonlyMat4, drawParams: DrawParams): void { const material = this.materialData.material; this.calcColor(materialParams.u_Color[ColorKind.MAT0], ColorKind.MAT0, material.colorMatRegs[0], ColorRegType.S10); @@ -635,7 +607,7 @@ export class MaterialInstance { m.copy(materialInstanceState.textureMappings[samplerIndex]); } - mat4.mul(scratchModelViewMatrix, viewMatrix, modelMatrix); + mat4.mul(scratchModelViewMatrix, viewFromWorldMatrix, modelMatrix); // Texture matrices. for (let i = 0; i < material.texMatrices.length; i++) { @@ -649,7 +621,7 @@ export class MaterialInstance { this.calcTexMtxInput(dst, texMtx, scratchModelViewMatrix, modelMatrix); const texSRT = scratchMat4c; this.calcTexSRT(texSRT, i); - this.calcTexMtx(dst, texMtx, texSRT, modelMatrix, camera, flipY); + this.calcTexMtx(dst, texMtx, texSRT, modelMatrix, clipFromViewMatrix, flipY); } for (let i = 0; i < material.indTexMatrices.length; i++) { @@ -666,21 +638,21 @@ export class MaterialInstance { materialParams.u_FogBlock.copy(this.fogBlock); if (this.materialData.fillMaterialParamsCallback !== null) - this.materialData.fillMaterialParamsCallback(materialParams, this, viewMatrix, modelMatrix, camera, drawParams); + this.materialData.fillMaterialParamsCallback(materialParams, this, clipFromViewMatrix, viewFromWorldMatrix, modelMatrix, drawParams); } - public fillMaterialParams(renderInst: GfxRenderInst, materialInstanceState: MaterialInstanceState, viewMatrix: ReadonlyMat4, modelMatrix: ReadonlyMat4, camera: Camera, drawParams: DrawParams): void { - this.fillOnMaterialParams(materialParams, materialInstanceState, camera, modelMatrix, drawParams, viewMatrix); + public fillMaterialParams(renderInst: GfxRenderInst, materialInstanceState: MaterialInstanceState, clipFromViewMatrix: ReadonlyMat4, viewFromWorldMatrix: ReadonlyMat4, modelMatrix: ReadonlyMat4, drawParams: DrawParams): void { + this.fillOnMaterialParams(materialParams, materialInstanceState, clipFromViewMatrix, viewFromWorldMatrix, modelMatrix, drawParams); this.materialHelper.allocateMaterialParamsDataOnInst(renderInst, materialParams); renderInst.setSamplerBindingsFromTextureMappings(materialParams.m_TextureMapping); } - public prepareToRenderShapes(device: GfxDevice, renderInstManager: GfxRenderInstManager, depth: number, camera: Camera, modelData: J3DModelData, materialInstanceState: MaterialInstanceState, shapeInstanceState: ShapeInstanceState): void { + public prepareToRenderShapes(renderInstManager: GfxRenderInstManager, viewDepth: number, clipFromViewMatrix: ReadonlyMat4, modelData: J3DModelData, materialInstanceState: MaterialInstanceState, shapeInstanceState: ShapeInstanceState): void { if (!this.visible) return; for (let i = 0; i < this.shapeInstances.length; i++) - this.shapeInstances[i].prepareToRender(device, renderInstManager, depth, camera, this, modelData, materialInstanceState, shapeInstanceState); + this.shapeInstances[i].prepareToRender(renderInstManager, viewDepth, clipFromViewMatrix, this, modelData, materialInstanceState, shapeInstanceState); } } @@ -1104,7 +1076,17 @@ export class J3DModelInstance { return false; } - public calcView(camera: Camera | null, viewMatrix: mat4 | null): void { + public computeDepth(): number { + // Use the root joint to calculate depth. + const worldFromViewMatrix = this.shapeInstanceState.viewFromWorldMatrix; + + const rootJoint = this.modelData.bmd.jnt1.joints[0]; + bboxScratch.transform(rootJoint.bbox, this.modelMatrix); + const depth = Math.max(computeViewSpaceDepthFromWorldSpaceAABB(worldFromViewMatrix, bboxScratch), 0); + return depth; + } + + public calcView(viewMatrix: ReadonlyMat4, cullFrustum: Frustum | null): void { // Billboards have their model matrix modified to face the camera, so their world space position doesn't // quite match what they kind of do. // @@ -1112,55 +1094,48 @@ export class J3DModelInstance { // In theory, we could cull using the bounding sphere instead. const disableCulling = this.modelData.hasBillboard; - if (viewMatrix !== null) - mat4.copy(this.shapeInstanceState.worldToViewMatrix, viewMatrix); + mat4.copy(this.shapeInstanceState.viewFromWorldMatrix, viewMatrix); + + // TODO(jstpierre): Move the frustum culling code to either the game or J3DGraphSimple? const jnt1 = this.modelData.bmd.jnt1; for (let i = 0; i < this.modelData.bmd.jnt1.joints.length; i++) { const jointToWorldMatrix = this.shapeInstanceState.jointToWorldMatrixArray[i]; - // TODO(jstpierre): Use shape visibility if the bbox is empty (?). - if (camera === null || disableCulling || jnt1.joints[i].bbox.isEmpty()) { + if (cullFrustum === null || disableCulling || jnt1.joints[i].bbox.isEmpty()) { this.jointVisibility[i] = true; } else { // Frustum cull. // Note to future self: joint bboxes do *not* contain their child joints (see: trees in Super Mario Sunshine). // You *cannot* use PARTIAL_INTERSECTION to optimize frustum culling. bboxScratch.transform(jnt1.joints[i].bbox, jointToWorldMatrix); - this.jointVisibility[i] = camera.frustum.contains(bboxScratch); + this.jointVisibility[i] = cullFrustum.contains(bboxScratch); } } - this.calcDrawMatrixArray(this.shapeInstanceState.worldToViewMatrix); + this.calcDrawMatrixArray(this.shapeInstanceState.viewFromWorldMatrix); } - public computeDepth(camera: Camera): number { - // Use the root joint to calculate depth. - const rootJoint = this.modelData.bmd.jnt1.joints[0]; - bboxScratch.transform(rootJoint.bbox, this.modelMatrix); - const depth = Math.max(computeViewSpaceDepthFromWorldSpaceAABB(camera.viewMatrix, bboxScratch), 0); - return depth; - } - - private draw(device: GfxDevice, renderInstManager: GfxRenderInstManager, camera: Camera, translucent: boolean): void { + private draw(renderInstManager: GfxRenderInstManager, clipFromViewMatrix: ReadonlyMat4, translucent: boolean): void { if (!this.isAnyShapeVisible()) return; - const depth = translucent ? this.computeDepth(camera) : -1; + const viewDepth = translucent ? this.computeDepth() : -1; for (let i = 0; i < this.materialInstances.length; i++) { const materialInstance = this.materialInstances[i]; if (materialInstance.materialData.material.translucent !== translucent) continue; - materialInstance.prepareToRenderShapes(device, renderInstManager, depth, camera, this.modelData, this.materialInstanceState, this.shapeInstanceState); + + materialInstance.prepareToRenderShapes(renderInstManager, viewDepth, clipFromViewMatrix, this.modelData, this.materialInstanceState, this.shapeInstanceState); } } - public drawOpa(device: GfxDevice, renderInstManager: GfxRenderInstManager, camera: Camera): void { - this.draw(device, renderInstManager, camera, false); + public drawOpa(renderInstManager: GfxRenderInstManager, clipFromViewMatrix: ReadonlyMat4): void { + this.draw(renderInstManager, clipFromViewMatrix, false); } - public drawXlu(device: GfxDevice, renderInstManager: GfxRenderInstManager, camera: Camera): void { - this.draw(device, renderInstManager, camera, true); + public drawXlu(renderInstManager: GfxRenderInstManager, clipFromViewMatrix: ReadonlyMat4): void { + this.draw(renderInstManager, clipFromViewMatrix, true); } private calcJointAnimRecurse(node: JointTreeNode, parentNode: JointTreeNode | null): void { diff --git a/src/Common/JSYSTEM/J3D/J3DGraphSimple.ts b/src/Common/JSYSTEM/J3D/J3DGraphSimple.ts index 129f6182b..0019544a5 100644 --- a/src/Common/JSYSTEM/J3D/J3DGraphSimple.ts +++ b/src/Common/JSYSTEM/J3D/J3DGraphSimple.ts @@ -284,18 +284,20 @@ export class J3DModelInstanceSimple extends J3DModelInstance { if (!this.visible) return; + const camera = viewerInput.camera; + this.animationController.setTimeInMilliseconds(viewerInput.time); - this.calcSkybox(viewerInput.camera); + this.calcSkybox(camera); this.calcAnim(); - this.calcView(viewerInput.camera, viewerInput.camera.viewMatrix); + this.calcView(camera.viewMatrix, camera.frustum); // If entire model is culled away, then we don't need to render anything. if (!this.isAnyShapeVisible()) return; - const depth = this.computeDepth(viewerInput.camera); + const viewDepth = this.computeDepth(); for (let i = 0; i < this.materialInstances.length; i++) - this.materialInstances[i].prepareToRenderShapes(device, renderInstManager, depth, viewerInput.camera, this.modelData, this.materialInstanceState, this.shapeInstanceState); + this.materialInstances[i].prepareToRenderShapes(renderInstManager, viewDepth, camera.projectionMatrix, this.modelData, this.materialInstanceState, this.shapeInstanceState); } public override destroy(device: GfxDevice): void { diff --git a/src/Common/JSYSTEM/J3D/J3DLoader.ts b/src/Common/JSYSTEM/J3D/J3DLoader.ts index 2483a05dc..e69e9c6ff 100644 --- a/src/Common/JSYSTEM/J3D/J3DLoader.ts +++ b/src/Common/JSYSTEM/J3D/J3DLoader.ts @@ -549,8 +549,9 @@ export const enum TexMtxMapMode { ProjmapBasic = 0x02, ViewProjmapBasic = 0x03, // Unknown: 0x04, 0x05. No known uses. + Unk0x04 = 0x04, + Unk0x05 = 0x05, // Uses "Old" conventions, remaps translation in fourth component - // TODO(jstpierre): Figure out the geometric interpretation of old vs. new EnvmapOld = 0x06, // Uses "New" conventions, remaps translation in third component Envmap = 0x07, diff --git a/src/InteractiveExamples/JPAExplorer.ts b/src/InteractiveExamples/JPAExplorer.ts index 831dfe787..aaa0ad6f7 100644 --- a/src/InteractiveExamples/JPAExplorer.ts +++ b/src/InteractiveExamples/JPAExplorer.ts @@ -463,7 +463,7 @@ export class Explorer implements SceneGfx { { renderInstManager.setCurrentList(this.indirectList); const texPrjMtx = scratchMatrix; - texProjCameraSceneTex(texPrjMtx, viewerInput.camera, 1); + texProjCameraSceneTex(texPrjMtx, viewerInput.camera.projectionMatrix, 1); this.effectSystem.setDrawInfo(viewerInput.camera.viewMatrix, viewerInput.camera.projectionMatrix, texPrjMtx); this.effectSystem.draw(device, this.renderHelper.renderInstManager, EfGroup.Indirect); } diff --git a/src/InteractiveExamples/SlimySpringWater.ts b/src/InteractiveExamples/SlimySpringWater.ts index 6fe5d8fd2..db16c436c 100644 --- a/src/InteractiveExamples/SlimySpringWater.ts +++ b/src/InteractiveExamples/SlimySpringWater.ts @@ -235,9 +235,10 @@ class FakeWaterModelInstance { if (!this.visible) return; + const camera = viewerInput.camera; this.modelInstance.animationController.setTimeInMilliseconds(viewerInput.time); this.modelInstance.calcAnim(); - this.modelInstance.calcView(viewerInput.camera, viewerInput.camera.viewMatrix); + this.modelInstance.calcView(camera.viewMatrix, camera.frustum); const template = renderInstManager.pushTemplate(); @@ -247,7 +248,7 @@ class FakeWaterModelInstance { // Push our material instance. this.materialInstance.setOnRenderInst(renderInstManager.gfxRenderCache, template); - this.materialInstance.fillMaterialParams(template, this.modelInstance.materialInstanceState, this.modelInstance.shapeInstanceState.worldToViewMatrix, this.modelInstance.modelMatrix, viewerInput.camera, drawParams); + this.materialInstance.fillMaterialParams(template, this.modelInstance.materialInstanceState, this.modelInstance.shapeInstanceState.viewFromWorldMatrix, this.modelInstance.modelMatrix, viewerInput.camera.projectionMatrix, drawParams); this.plane.prepareToRender(renderInstManager); renderInstManager.popTemplate(); diff --git a/src/InteractiveExamples/SunshineWater.ts b/src/InteractiveExamples/SunshineWater.ts index 8875e5486..2b52c8927 100644 --- a/src/InteractiveExamples/SunshineWater.ts +++ b/src/InteractiveExamples/SunshineWater.ts @@ -141,7 +141,7 @@ class SunshineWaterModel { bindTTK1MaterialInstance(this.seaMaterialInstance, this.animationController, btk); this.plane = new PlaneShape(device, cache); - this.shapeInstanceState.worldToViewMatrix = scratchViewMatrix; + this.shapeInstanceState.viewFromWorldMatrix = scratchViewMatrix; } public mangleMaterial(material: MaterialEntry, configName: string): void { @@ -192,11 +192,11 @@ class SunshineWaterModel { fillSceneParamsDataOnTemplate(template, viewerInput); this.seaMaterialInstance.setOnRenderInst(renderHelper.renderInstManager.gfxRenderCache, template); - computeViewMatrix(this.shapeInstanceState.worldToViewMatrix, viewerInput.camera); - mat4.mul(drawParams.u_PosMtx[0], this.shapeInstanceState.worldToViewMatrix, this.modelMatrix); + computeViewMatrix(this.shapeInstanceState.viewFromWorldMatrix, viewerInput.camera); + mat4.mul(drawParams.u_PosMtx[0], this.shapeInstanceState.viewFromWorldMatrix, this.modelMatrix); this.seaMaterialInstance.materialHelper.allocateDrawParamsDataOnInst(template, drawParams); - this.seaMaterialInstance.fillMaterialParams(template, this.materialInstanceState, this.shapeInstanceState.worldToViewMatrix, this.modelMatrix, viewerInput.camera, drawParams); + this.seaMaterialInstance.fillMaterialParams(template, this.materialInstanceState, this.shapeInstanceState.viewFromWorldMatrix, viewerInput.camera.projectionMatrix, this.modelMatrix, drawParams); this.plane.prepareToRender(renderHelper); diff --git a/src/MetroidPrime/render.ts b/src/MetroidPrime/render.ts index 64e4e23c9..6153e615c 100644 --- a/src/MetroidPrime/render.ts +++ b/src/MetroidPrime/render.ts @@ -16,7 +16,7 @@ import { GfxRendererLayer, GfxRenderInst, makeSortKey, setSortKeyBias, setSortKe import { computeViewMatrix, computeViewMatrixSkybox } from '../Camera.js'; import { LoadedVertexData, LoadedVertexDraw, LoadedVertexLayout } from '../gx/gx_displaylist.js'; import * as GX_Material from '../gx/gx_material.js'; -import { GX_Program, GXMaterialHacks, lightSetWorldDirectionNormalMatrix, lightSetWorldPositionViewMatrix } from '../gx/gx_material.js'; +import { GX_Program, GXMaterialHacks, lightSetWorldDirection, lightSetWorldPosition } from '../gx/gx_material.js'; import { AreaAttributes, Effect, Entity, LightParameters, MP1EntityType, WorldLightingOptions } from './script.js'; import { Color, colorAdd, colorCopy, colorMult, colorNewCopy, OpaqueBlack, TransparentBlack, White } from '../Color.js'; import { computeNormalMatrix, getMatrixTranslation, setMatrixTranslation, texEnvMtx, transformVec3Mat4w0, transformVec3Mat4w1, Vec3One } from '../MathHelpers.js'; @@ -290,8 +290,8 @@ class MaterialGroupInstance { if (actorLights !== null && i < actorLights.lights.length) { const light = actorLights.lights[i].gxLight; materialParams.u_Lights[i].copy(light); - lightSetWorldPositionViewMatrix(materialParams.u_Lights[i], viewMatrix, light.Position); - lightSetWorldDirectionNormalMatrix(materialParams.u_Lights[i], viewMatrix, light.Direction); + lightSetWorldPosition(materialParams.u_Lights[i], viewMatrix, light.Position); + lightSetWorldDirection(materialParams.u_Lights[i], viewMatrix, light.Direction); } else { materialParams.u_Lights[i].reset(); } diff --git a/src/NeedForSpeedMostWanted/render.ts b/src/NeedForSpeedMostWanted/render.ts index 8fc7841ad..7d062c6fe 100644 --- a/src/NeedForSpeedMostWanted/render.ts +++ b/src/NeedForSpeedMostWanted/render.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "gl-matrix"; -import { CameraController, computeViewMatrix, computeViewSpaceDepthFromWorldSpacePoint } from "../Camera.js"; +import { CameraController, computeViewSpaceDepthFromWorldSpacePoint } from "../Camera.js"; import { GfxShaderLibrary } from "../gfx/helpers/GfxShaderLibrary.js"; import { makeBackbufferDescSimple, standardFullClearRenderPassDescriptor } from "../gfx/helpers/RenderGraphHelpers.js"; import { fillMatrix4x3, fillMatrix4x4, fillVec4v } from "../gfx/helpers/UniformBufferHelpers.js"; @@ -91,8 +91,7 @@ export class NfsRenderer implements SceneGfx { let offs = template.allocateUniformBuffer(NfsProgram.ub_SceneParams, 24); const sceneParamsMapped = template.mapUniformBufferF32(NfsProgram.ub_SceneParams); const worldProjMatrix = mat4.create(); - computeViewMatrix(worldProjMatrix, viewerInput.camera); - mat4.mul(worldProjMatrix, viewerInput.camera.projectionMatrix, worldProjMatrix); + mat4.mul(worldProjMatrix, viewerInput.camera.projectionMatrix, viewerInput.camera.viewMatrix); offs += fillMatrix4x4(sceneParamsMapped, offs, worldProjMatrix); offs += fillVec4v(sceneParamsMapped, offs, [cameraPos[0], cameraPos[1], cameraPos[2], 0]); offs += fillVec4v(sceneParamsMapped, offs, [viewerInput.backbufferWidth, viewerInput.backbufferHeight, 0, 0]); diff --git a/src/PokemonSnap/particles.ts b/src/PokemonSnap/particles.ts index 65b23c742..0f04fe859 100644 --- a/src/PokemonSnap/particles.ts +++ b/src/PokemonSnap/particles.ts @@ -1,21 +1,21 @@ + import * as RDP from "../Common/N64/RDP.js"; import { mat4, vec3, vec4 } from "gl-matrix"; import ArrayBufferSlice from "../ArrayBufferSlice.js"; import { TexCM } from "../Common/N64/Image.js"; import { makeStaticDataBuffer } from "../gfx/helpers/BufferHelpers.js"; -import { GfxBuffer, GfxBufferUsage, GfxDevice, GfxFormat, GfxInputLayout, GfxInputLayoutBufferDescriptor, GfxSampler, GfxTexture, GfxVertexAttributeDescriptor, GfxVertexBufferFrequency, GfxBindingLayoutDescriptor, GfxProgram, GfxMegaStateDescriptor, GfxCompareMode, GfxBlendMode, GfxBlendFactor, GfxCullMode, GfxVertexBufferDescriptor, GfxIndexBufferDescriptor } from "../gfx/platform/GfxPlatform.js"; +import { setAttachmentStateSimple } from "../gfx/helpers/GfxMegaStateDescriptorHelpers.js"; +import { fillMatrix4x3, fillMatrix4x4, fillVec4v } from "../gfx/helpers/UniformBufferHelpers.js"; +import { GfxBindingLayoutDescriptor, GfxBlendFactor, GfxBlendMode, GfxBuffer, GfxBufferUsage, GfxCompareMode, GfxCullMode, GfxDevice, GfxFormat, GfxIndexBufferDescriptor, GfxInputLayout, GfxMegaStateDescriptor, GfxProgram, GfxSampler, GfxTexture, GfxVertexAttributeDescriptor, GfxVertexBufferDescriptor, GfxVertexBufferFrequency } from "../gfx/platform/GfxPlatform.js"; import { GfxRenderCache } from "../gfx/render/GfxRenderCache.js"; -import { GfxRenderInstManager, makeSortKey, GfxRendererLayer } from "../gfx/render/GfxRenderInstManager.js"; -import { clamp, lerp, MathConstants, normToLength, normToLengthAndAdd, transformVec3Mat4w0, Vec3Zero, Vec3UnitX, calcBillboardMatrix, CalcBillboardFlags } from "../MathHelpers.js"; +import { GfxRendererLayer, GfxRenderInstManager, makeSortKey } from "../gfx/render/GfxRenderInstManager.js"; +import { CalcBillboardFlags, calcBillboardMatrix, clamp, lerp, MathConstants, normToLength, normToLengthAndAdd, transformVec3Mat4w0, Vec3UnitX, Vec3Zero } from "../MathHelpers.js"; import { DeviceProgram } from "../Program.js"; +import { TextureMapping } from "../TextureHolder.js"; import { align, assert, hexzero, nArray } from "../util.js"; import { ViewerRenderInput } from "../viewer.js"; import { getColor, getVec3 } from "./room.js"; -import { fillMatrix4x4, fillMatrix4x3, fillVec4v } from "../gfx/helpers/UniformBufferHelpers.js"; -import { TextureMapping } from "../TextureHolder.js"; -import { computeViewMatrix } from "../Camera.js"; -import { setAttachmentStateSimple } from "../gfx/helpers/GfxMegaStateDescriptorHelpers.js"; export interface EmitterData { isCommon: boolean; @@ -968,8 +968,7 @@ class Particle { let offs = renderInst.allocateUniformBuffer(ParticleProgram.ub_DrawParams, 12 + 4 * 2); const draw = renderInst.mapUniformBufferF32(ParticleProgram.ub_DrawParams); - computeViewMatrix(particleMtx, viewerInput.camera); - mat4.mul(particleMtx, particleMtx, this.modelMatrix); + mat4.mul(particleMtx, viewerInput.camera.viewMatrix, this.modelMatrix); calcBillboardMatrix(particleMtx, particleMtx, CalcBillboardFlags.UseRollLocal | CalcBillboardFlags.PriorityZ | CalcBillboardFlags.UseZPlane); offs += fillMatrix4x3(draw, offs, particleMtx); diff --git a/src/StarFoxAdventures/SphereMaps.ts b/src/StarFoxAdventures/SphereMaps.ts index a7bce364c..29db71156 100644 --- a/src/StarFoxAdventures/SphereMaps.ts +++ b/src/StarFoxAdventures/SphereMaps.ts @@ -1,15 +1,15 @@ import { mat4, vec3 } from 'gl-matrix'; -import { computeViewMatrix } from '../Camera.js'; import { Blue, Color, colorCopy, colorNewFromRGBA, Red, TransparentBlack, White } from '../Color.js'; +import { projectionMatrixConvertClipSpaceNearZ } from '../gfx/helpers/ProjectionHelpers.js'; import { GfxClipSpaceNearZ, GfxDevice, GfxFormat, GfxMipFilterMode, GfxSampler, GfxTexFilterMode, GfxWrapMode } from '../gfx/platform/GfxPlatform.js'; import { GfxRenderCache } from '../gfx/render/GfxRenderCache.js'; import { GfxrAttachmentSlot, GfxrGraphBuilder, GfxrPass, GfxrPassScope, GfxrRenderTargetDescription, GfxrRenderTargetID, GfxrResolveTextureID } from '../gfx/render/GfxRenderGraph.js'; import { GfxRenderInstList, GfxRenderInstManager } from '../gfx/render/GfxRenderInstManager.js'; import * as GX from '../gx/gx_enum.js'; import * as GX_Material from '../gx/gx_material.js'; -import { ColorKind, fillSceneParams, fillSceneParamsData, GXRenderHelperGfx, MaterialParams, DrawParams, SceneParams } from '../gx/gx_render.js'; +import { ColorKind, DrawParams, fillSceneParams, fillSceneParamsData, gxBindingLayouts, GXRenderHelperGfx, MaterialParams, SceneParams, ub_SceneParamsBufferSize } from '../gx/gx_render.js'; import { projectionMatrixForCuboid } from '../MathHelpers.js'; -import { TDDraw, TSDraw } from "../SuperMarioGalaxy/DDraw.js"; +import { TSDraw } from "../SuperMarioGalaxy/DDraw.js"; import { TextureMapping } from '../TextureHolder.js'; import { nArray } from '../util.js'; import { SFAMaterialBuilder } from './MaterialBuilder.js'; @@ -19,15 +19,11 @@ import { TextureFetcher } from './textures.js'; import { mat4SetTranslation } from './util.js'; import { World } from './world.js'; import { LightType } from './WorldLights.js'; -import { ub_SceneParamsBufferSize } from '../gx/gx_render.js'; -import { gxBindingLayouts } from '../gx/gx_render.js'; -import { projectionMatrixConvertClipSpaceNearZ } from '../gfx/helpers/ProjectionHelpers.js'; const scratchMaterialParams = new MaterialParams(); const scratchDrawParams = new DrawParams(); const scratchSceneParams = new SceneParams(); const scratchMtx0 = mat4.create(); -const scratchMtx1 = mat4.create(); const scratchVec0 = vec3.create(); const scratchVec1 = vec3.create(); @@ -231,10 +227,8 @@ export class SphereMapManager { const skyLight = this.world.envfxMan.skyLight; const groundLight = this.world.envfxMan.groundLight; - const worldView = scratchMtx0; - computeViewMatrix(worldView, sceneCtx.viewerInput.camera); - const worldViewSR = scratchMtx1; - mat4.copy(worldViewSR, worldView); + const worldViewSR = scratchMtx0; + mat4.copy(worldViewSR, sceneCtx.viewToWorldMtx); mat4SetTranslation(worldViewSR, 0, 0, 0); const skyLightVec = scratchVec0; diff --git a/src/StarFoxAdventures/envfx.ts b/src/StarFoxAdventures/envfx.ts index 7e2c612ba..84520aa95 100644 --- a/src/StarFoxAdventures/envfx.ts +++ b/src/StarFoxAdventures/envfx.ts @@ -1,17 +1,15 @@ import { mat4, vec3 } from 'gl-matrix'; +import { Color, colorCopy, colorNewFromRGBA, colorScale, White } from '../Color.js'; import { DataFetcher } from '../DataFetcher.js'; -import { Color, colorNewFromRGBA, colorCopy, colorNewCopy, colorFromRGBA, White, colorScale } from '../Color.js'; import { nArray } from '../util.js'; +import { GfxDevice } from '../gfx/platform/GfxPlatform.js'; +import { ObjectInstance } from './objects.js'; +import { SceneUpdateContext } from './render.js'; import { SFATexture } from './textures.js'; import { dataSubarray, readUint16 } from './util.js'; -import { ObjectInstance } from './objects.js'; import { World } from './world.js'; -import { GfxDevice } from '../gfx/platform/GfxPlatform.js'; import { createDirectionalLight, Light } from './WorldLights.js'; -import { SceneUpdateContext } from './render.js'; -import { computeViewMatrix } from '../Camera.js'; -import { GfxRenderCache } from '../gfx/render/GfxRenderCache.js'; enum EnvfxType { Atmosphere = 5, @@ -75,22 +73,9 @@ export class EnvfxManager { public update(device: GfxDevice, sceneCtx: SceneUpdateContext) { this.updateAmbience(); - - const viewToWorldMtx = scratchMtx0; - computeViewMatrix(viewToWorldMtx, sceneCtx.viewerInput.camera); - mat4.invert(viewToWorldMtx, viewToWorldMtx); - - const viewToWorldTY = viewToWorldMtx[4*3+1]; - - // XXX: This code causes the mist to "overwhelm" the camera when the camera is immersed. - // This doesn't work well with noclip, so I have disabled it. - // let mistParam; - // if (viewToWorldTY >= this.mistTop) - // mistParam = 0; - // else if (viewToWorldTY <= this.mistBottom) - // mistParam = 64; - // else - // mistParam = 64 * (this.mistTop - viewToWorldTY) / (this.mistTop - this.mistBottom); + // const viewToWorldTY = sceneCtx.viewerInput.camera.worldMatrix[13]; + // const mistPercent = 1.0 - saturate(invlerp(this.mistBottom, this.mistTop, viewToWorldTY)); + // let mistParam = mistPercent * 64.0; let mistParam = 0; // Behave as if the camera is always above the mist this.updateMistTexture(device, mistParam); } diff --git a/src/StarFoxAdventures/materials.ts b/src/StarFoxAdventures/materials.ts index 3e4e2e7ab..2b5d286e1 100644 --- a/src/StarFoxAdventures/materials.ts +++ b/src/StarFoxAdventures/materials.ts @@ -793,8 +793,9 @@ export class StandardMapMaterial extends StandardMaterial { this.aprevIsValid = false; this.mb.setTexMtx(2, (dst: mat4, matCtx: MaterialRenderContext) => { + // Flipped - texProjCameraSceneTex(dst, matCtx.sceneCtx.viewerInput.camera, -matCtx.sceneCtx.flipYScale); + texProjCameraSceneTex(dst, matCtx.sceneCtx.viewerInput.camera.projectionMatrix, -matCtx.sceneCtx.flipYScale); mat4.mul(dst, dst, matCtx.modelToViewMtx); return dst; }); @@ -1381,13 +1382,13 @@ class WaterMaterial extends MaterialBase { protected rebuildInternal() { this.mb.setTexMtx(0, (dst: mat4, ctx: MaterialRenderContext) => { // Flipped - texProjCameraSceneTex(dst, ctx.sceneCtx.viewerInput.camera, -ctx.sceneCtx.flipYScale); + texProjCameraSceneTex(dst, ctx.sceneCtx.viewerInput.camera.projectionMatrix, -ctx.sceneCtx.flipYScale); mat4.mul(dst, dst, ctx.modelToViewMtx); }); this.mb.setTexMtx(1, (dst: mat4, ctx: MaterialRenderContext) => { // Unflipped - texProjCameraSceneTex(dst, ctx.sceneCtx.viewerInput.camera, ctx.sceneCtx.flipYScale); + texProjCameraSceneTex(dst, ctx.sceneCtx.viewerInput.camera.projectionMatrix, ctx.sceneCtx.flipYScale); mat4.mul(dst, dst, ctx.modelToViewMtx); }); diff --git a/src/StarFoxAdventures/render.ts b/src/StarFoxAdventures/render.ts index cb479e2a8..348bc388d 100644 --- a/src/StarFoxAdventures/render.ts +++ b/src/StarFoxAdventures/render.ts @@ -1,27 +1,27 @@ import { mat4, vec3 } from 'gl-matrix'; -import * as Viewer from '../viewer.js'; -import * as GX from '../gx/gx_enum.js'; -import * as GX_Material from '../gx/gx_material.js'; -import { fillSceneParams, fillSceneParamsData, GXMaterialHelperGfx, GXRenderHelperGfx, MaterialParams, DrawParams, SceneParams } from '../gx/gx_render.js'; -import { GfxDevice, GfxFormat, GfxWrapMode, GfxTexFilterMode, GfxMipFilterMode } from '../gfx/platform/GfxPlatform.js'; -import { GfxRenderInst, GfxRenderInstList, GfxRenderInstManager } from "../gfx/render/GfxRenderInstManager.js"; -import { CameraController, computeViewMatrix } from '../Camera.js'; +import { CameraController } from '../Camera.js'; +import { colorNewFromRGBA8, White } from '../Color.js'; import { setBackbufferDescSimple, standardFullClearRenderPassDescriptor } from '../gfx/helpers/RenderGraphHelpers.js'; +import { GfxDevice, GfxFormat, GfxMipFilterMode, GfxTexFilterMode, GfxWrapMode } from '../gfx/platform/GfxPlatform.js'; import { GfxrAttachmentSlot, GfxrGraphBuilder, GfxrPass, GfxrPassScope, GfxrRenderTargetDescription, GfxrRenderTargetID, GfxrResolveTextureID, GfxrTemporalTexture } from '../gfx/render/GfxRenderGraph.js'; -import { colorNewFromRGBA8, White } from '../Color.js'; +import { GfxRenderInst, GfxRenderInstList, GfxRenderInstManager } from "../gfx/render/GfxRenderInstManager.js"; +import * as GX from '../gx/gx_enum.js'; +import * as GX_Material from '../gx/gx_material.js'; +import { DrawParams, fillSceneParams, fillSceneParamsData, GXMaterialHelperGfx, GXRenderHelperGfx, MaterialParams, SceneParams } from '../gx/gx_render.js'; +import { TDDraw } from '../SuperMarioGalaxy/DDraw.js'; import { TextureMapping } from '../TextureHolder.js'; import { nArray } from '../util.js'; -import { TDDraw } from '../SuperMarioGalaxy/DDraw.js'; +import * as Viewer from '../viewer.js'; +import { gfxDeviceNeedsFlipY } from '../gfx/helpers/GfxDeviceHelpers.js'; +import { getMatrixAxisZ } from '../MathHelpers.js'; +import { SceneContext } from '../SceneBase.js'; import { SFAAnimationController } from './animation.js'; -import { MaterialFactory, HeatShimmerMaterial, MaterialRenderContext } from './materials.js'; -import { radsToAngle16, vecPitch } from './util.js'; -import { DepthResampler } from './depthresampler.js'; import { BlurFilter } from './blur.js'; -import { getMatrixAxisZ } from '../MathHelpers.js'; +import { DepthResampler } from './depthresampler.js'; +import { HeatShimmerMaterial, MaterialFactory, MaterialRenderContext } from './materials.js'; +import { radsToAngle16, vecPitch } from './util.js'; import { World } from './world.js'; -import { gfxDeviceNeedsFlipY } from '../gfx/helpers/GfxDeviceHelpers.js'; -import { SceneContext } from '../SceneBase.js'; export interface SceneUpdateContext { viewerInput: Viewer.ViewerRenderInput; @@ -308,7 +308,7 @@ export class SFARenderer implements Viewer.SceneGfx { world: this.world, }; - computeViewMatrix(sceneCtx.worldToViewMtx, viewerInput.camera); + mat4.copy(sceneCtx.worldToViewMtx, viewerInput.camera.viewMatrix); mat4.invert(sceneCtx.viewToWorldMtx, sceneCtx.worldToViewMtx); this.addSkyRenderInsts(device, renderInstManager, this.renderLists, sceneCtx); diff --git a/src/StarFoxAdventures/shapes.ts b/src/StarFoxAdventures/shapes.ts index d58f3de40..0c00925f9 100644 --- a/src/StarFoxAdventures/shapes.ts +++ b/src/StarFoxAdventures/shapes.ts @@ -1,18 +1,17 @@ import { mat4, ReadonlyMat4, vec3 } from 'gl-matrix'; import ArrayBufferSlice from '../ArrayBufferSlice.js'; -import { Camera, computeViewMatrix } from '../Camera.js'; +import { Camera } from '../Camera.js'; import { colorCopy, colorNewFromRGBA } from '../Color.js'; import { AABB } from '../Geometry.js'; -import { makeStaticDataBuffer } from '../gfx/helpers/BufferHelpers.js'; import { GfxBuffer, GfxBufferFrequencyHint, GfxBufferUsage, GfxDevice, GfxIndexBufferDescriptor, GfxInputLayout, GfxVertexBufferDescriptor } from '../gfx/platform/GfxPlatform.js'; import { GfxRenderCache } from '../gfx/render/GfxRenderCache.js'; import { GfxRendererLayer, GfxRenderInst, GfxRenderInstManager, setSortKeyDepth, setSortKeyLayer } from "../gfx/render/GfxRenderInstManager.js"; -import { compilePartialVtxLoader, compileVtxLoaderMultiVat, GX_Array, GX_VtxAttrFmt, GX_VtxDesc, LoadedVertexData, LoadedVertexDraw, LoadedVertexLayout, VertexAttributeInput, VtxLoader } from '../gx/gx_displaylist.js'; -import { createInputLayout, MaterialParams, DrawParams } from '../gx/gx_render.js'; +import { compilePartialVtxLoader, compileVtxLoaderMultiVat, GX_Array, GX_VtxAttrFmt, GX_VtxDesc, LoadedVertexData, LoadedVertexDraw, LoadedVertexLayout, VtxLoader } from '../gx/gx_displaylist.js'; +import * as GX_Material from '../gx/gx_material.js'; +import { createInputLayout, DrawParams, MaterialParams } from '../gx/gx_render.js'; import { transformVec3Mat4w1 } from '../MathHelpers.js'; import { nArray } from '../util.js'; -import * as GX_Material from '../gx/gx_material.js'; import { MaterialRenderContext, SFAMaterial, StandardMapMaterial } from './materials.js'; import { ModelRenderContext } from './models.js'; import { setGXMaterialOnRenderInst } from './render.js'; @@ -83,7 +82,6 @@ class MyShapeHelper { } const scratchMtx0 = mat4.create(); -const scratchMtx1 = mat4.create(); const scratchVec0 = vec3.create(); // The vertices and polygons of a shape. @@ -150,11 +148,8 @@ export class ShapeGeometry { this.drawParams.clear(); - const worldToViewMtx = scratchMtx0; - computeViewMatrix(worldToViewMtx, camera); - - const modelToViewMtx = scratchMtx1; - mat4.mul(modelToViewMtx, worldToViewMtx, modelToWorldMtx); + const modelToViewMtx = scratchMtx0; + mat4.mul(modelToViewMtx, camera.viewMatrix, modelToWorldMtx); // Use GfxRendererLayer.TRANSLUCENT to force sorting behavior as in the game. // The translucent flag must be set before calling setSortKeyDepth, otherwise errors will occur. diff --git a/src/StarFoxAdventures/util.ts b/src/StarFoxAdventures/util.ts index 8292120be..2e1ae16c4 100644 --- a/src/StarFoxAdventures/util.ts +++ b/src/StarFoxAdventures/util.ts @@ -1,7 +1,7 @@ +import { mat4, ReadonlyVec3, vec3 } from 'gl-matrix'; import ArrayBufferSlice from '../ArrayBufferSlice.js'; -import { mat4, vec3, quat, ReadonlyVec3 } from 'gl-matrix'; import { Camera } from '../Camera.js'; -import { computeModelMatrixSRT, getMatrixTranslation, transformVec3Mat4w0 } from '../MathHelpers.js'; +import { getMatrixTranslation } from '../MathHelpers.js'; export function dataSubarray(data: DataView, byteOffset: number, byteLength?: number, index: number = 0, stride: number = byteLength ?? 0): DataView { return new DataView(data.buffer, data.byteOffset + byteOffset + index * stride, byteLength); @@ -134,7 +134,7 @@ export function readVec3(data: DataView, byteOffset: number = 0): vec3 { data.getFloat32(byteOffset + 0), data.getFloat32(byteOffset + 4), data.getFloat32(byteOffset + 8) - ); + ); } // Reads bitfields. Bits are pulled from the most significant bits of each byte @@ -250,4 +250,4 @@ export function setInt16Clamped(data: DataView, byteOffset: number, value: numbe else if (value > 32767) value = 32767; data.setInt16(byteOffset, value, littleEndian); -} \ No newline at end of file +} diff --git a/src/SuperMarioGalaxy/ActorUtil.ts b/src/SuperMarioGalaxy/ActorUtil.ts index 4da17d8ca..831d9cda9 100644 --- a/src/SuperMarioGalaxy/ActorUtil.ts +++ b/src/SuperMarioGalaxy/ActorUtil.ts @@ -905,7 +905,7 @@ export function isValidDraw(actor: LiveActor): boolean { export function loadTexProjectionMtx(m: mat4, textureMapping: TextureMapping, camera: Camera): void { const flipYScale = textureMapping.flipY ? -1 : 1; - texProjCameraSceneTex(m, camera, flipYScale); + texProjCameraSceneTex(m, camera.projectionMatrix, flipYScale); mat4.mul(m, m, camera.viewMatrix); } diff --git a/src/SuperMarioGalaxy/Actors/MiscActor.ts b/src/SuperMarioGalaxy/Actors/MiscActor.ts index c1947bfe7..845e25082 100644 --- a/src/SuperMarioGalaxy/Actors/MiscActor.ts +++ b/src/SuperMarioGalaxy/Actors/MiscActor.ts @@ -6424,6 +6424,8 @@ export class ElectricRailHolder extends NameObj { public override draw(sceneObjHolder: SceneObjHolder, renderInstManager: GfxRenderInstManager, viewerInput: Viewer.ViewerRenderInput): void { super.draw(sceneObjHolder, renderInstManager, viewerInput); + const camera = viewerInput.camera; + const cache = renderInstManager.gfxRenderCache; for (let i = 0; i < ElectricRailType.Count; i++) { const modelObj = this.models[i]; @@ -6433,7 +6435,7 @@ export class ElectricRailHolder extends NameObj { const template = renderInstManager.pushTemplate(); const modelInstance = modelObj.modelInstance!; - mat4.copy(drawParams.u_PosMtx[0], viewerInput.camera.viewMatrix); + mat4.copy(drawParams.u_PosMtx[0], camera.viewMatrix); const materialInstance = modelInstance.materialInstances[0]; materialInstance.setOnRenderInst(cache, template); @@ -6447,7 +6449,7 @@ export class ElectricRailHolder extends NameObj { if (!rail.visibleScenario || !rail.visibleAlive) continue; - materialInstance.fillOnMaterialParams(materialParams, modelInstance.materialInstanceState, viewerInput.camera, modelInstance.modelMatrix, drawParams); + materialInstance.fillOnMaterialParams(materialParams, modelInstance.materialInstanceState, camera.projectionMatrix, camera.viewMatrix, modelInstance.modelMatrix, drawParams); const railTemplate = renderInstManager.pushTemplate(); railTemplate.setSamplerBindingsFromTextureMappings(materialParams.m_TextureMapping); rail.drawRail(sceneObjHolder, renderInstManager, materialInstance.materialHelper, materialParams); diff --git a/src/SuperMarioGalaxy/DrawBuffer.ts b/src/SuperMarioGalaxy/DrawBuffer.ts index 362694fc1..1ab39f035 100644 --- a/src/SuperMarioGalaxy/DrawBuffer.ts +++ b/src/SuperMarioGalaxy/DrawBuffer.ts @@ -147,7 +147,7 @@ class DrawBufferExecuter { for (let i = 0; i < materialOrder.length; i++) { const materialIndex = materialOrder[i]; const materialInstance = this.modelInstance!.materialInstances[materialIndex]; - materialInstance.prepareToRenderShapes(device, renderInstManager, depth, camera, this.modelInstance.modelData, this.modelInstance.materialInstanceState, this.modelInstance.shapeInstanceState); + materialInstance.prepareToRenderShapes(renderInstManager, depth, camera.projectionMatrix, this.modelInstance.modelData, this.modelInstance.materialInstanceState, this.modelInstance.shapeInstanceState); } } @@ -157,7 +157,7 @@ class DrawBufferExecuter { } public drawXlu(device: GfxDevice, renderInstManager: GfxRenderInstManager, camera: Camera): void { - const depth = this.modelInstance.computeDepth(camera); + const depth = this.modelInstance.computeDepth(); this.draw(device, renderInstManager, camera, this.materialOrderXlu, depth); } } diff --git a/src/SuperMarioGalaxy/LiveActor.ts b/src/SuperMarioGalaxy/LiveActor.ts index 596d1fbf7..663abb57e 100644 --- a/src/SuperMarioGalaxy/LiveActor.ts +++ b/src/SuperMarioGalaxy/LiveActor.ts @@ -5,7 +5,7 @@ import { J3DFrameCtrl, J3DFrameCtrl__UpdateFlags } from "../Common/JSYSTEM/J3D/J import { J3DModelData, J3DModelInstance, MaterialInstance, TEX1Data } from "../Common/JSYSTEM/J3D/J3DGraphBase.js"; import { GfxDevice, GfxFormat } from "../gfx/platform/GfxPlatform.js"; import { LoadedVertexData, LoadedVertexLayout, VertexAttributeInput } from "../gx/gx_displaylist.js"; -import { computeEulerAngleRotationFromSRTMatrix, computeModelMatrixSRT, computeNormalMatrix } from "../MathHelpers.js"; +import { computeEulerAngleRotationFromSRTMatrix, computeModelMatrixSRT, computeNormalMatrix, Mat4Identity } from "../MathHelpers.js"; import { align, assertExists, fallback, nArray, nullify } from "../util.js"; import * as Viewer from '../viewer.js'; import { calcGravity, connectToScene, invalidateCollisionPartsForActor, isBckExist, isBckPlaying, isBpkExist, isBpkPlaying, isBrkExist, isBrkPlaying, isBtkExist, isBtkPlaying, isBtpExist, isBtpPlaying, isBvaExist, isBvaPlaying, resetAllCollisionMtx, startBck, startBpk, startBrk, startBtk, startBtp, startBva, validateCollisionPartsForActor } from "./ActorUtil.js"; @@ -241,7 +241,7 @@ function patchBMD(bmd: BMD): void { } // This is roughly ShapePacketUserData::callDL(). -function fillMaterialParamsCallback(materialParams: MaterialParams, materialInstance: MaterialInstance, viewMatrix: ReadonlyMat4, modelMatrix: ReadonlyMat4, camera: Camera, drawParams: DrawParams): void { +function fillMaterialParamsCallback(materialParams: MaterialParams, materialInstance: MaterialInstance, clipFromViewMatrix: ReadonlyMat4, viewFromWorldMatrix: ReadonlyMat4, modelMatrix: ReadonlyMat4, drawParams: DrawParams): void { const material = materialInstance.materialData.material; let hasAnyEnvMap = false; @@ -251,18 +251,15 @@ function fillMaterialParamsCallback(materialParams: MaterialParams, materialInst continue; const matrixMode = texMtx.info & 0x3F; - const isUsingEnvMap = (matrixMode === 0x01 || matrixMode === 0x06 || matrixMode === 0x07); - - if (isUsingEnvMap) - hasAnyEnvMap = true; + hasAnyEnvMap = hasAnyEnvMap || (matrixMode === TexMtxMapMode.EnvmapBasic || matrixMode === TexMtxMapMode.EnvmapOld || matrixMode === TexMtxMapMode.Envmap); const dst = materialParams.u_PostTexMtx[i]; const flipY = materialParams.m_TextureMapping[i].flipY; - materialInstance.calcPostTexMtxInput(dst, texMtx, viewMatrix); + materialInstance.calcPostTexMtxInput(dst, texMtx, viewFromWorldMatrix); const texSRT = scratchMatrix; materialInstance.calcTexSRT(texSRT, i); - materialInstance.calcTexMtx(dst, texMtx, texSRT, modelMatrix, camera, flipY); + materialInstance.calcTexMtx(dst, texMtx, texSRT, modelMatrix, clipFromViewMatrix, flipY); } if (hasAnyEnvMap) { @@ -963,9 +960,9 @@ export class LiveActor extends NameObj { this.calcAndSetBaseMtxBase(); } - protected getActorVisible(camera: Camera): boolean { + protected getActorVisible(camera: Camera | null): boolean { if (this.visibleScenario && this.visibleAlive) { - if (this.boundingSphereRadius !== null) + if (this.boundingSphereRadius !== null && camera !== null) return camera.frustum.containsSphere(this.translation, this.boundingSphereRadius); else return true; @@ -992,14 +989,11 @@ export class LiveActor extends NameObj { setCollisionMtx(this, this.collisionParts); } - public override calcViewAndEntry(sceneObjHolder: SceneObjHolder, camera: Camera, viewMatrix: mat4 | null): void { + public override calcViewAndEntry(sceneObjHolder: SceneObjHolder, camera: Camera | null, viewMatrix: ReadonlyMat4): void { if (this.modelInstance === null) return; - if (viewMatrix !== null) - this.modelInstance.calcView(camera, camera.viewMatrix); - else - this.modelInstance.calcView(null, null); + this.modelInstance.calcView(viewMatrix, camera !== null ? camera.frustum : null); const visible = this.visibleModel && this.getActorVisible(camera); this.modelInstance.visible = visible; @@ -1007,7 +1001,7 @@ export class LiveActor extends NameObj { return; if (this.actorLightCtrl !== null) { - this.actorLightCtrl.loadLight(this.modelInstance, camera); + this.actorLightCtrl.loadLight(this.modelInstance, camera!); } else { // If we don't have an individualized actor light control, then load the default area light. // This is basically what DrawBufferExecuter::draw() and DrawBufferGroup::draw() effectively do. @@ -1038,7 +1032,7 @@ export class LiveActor extends NameObj { // // Rather than emulate this whole system, just hardcode the end result. So, setAmbient = false. const setAmbient = false; - lightInfo.setOnModelInstance(this.modelInstance, camera, setAmbient); + lightInfo.setOnModelInstance(this.modelInstance, camera!, setAmbient); } } } diff --git a/src/SuperMarioGalaxy/Main.ts b/src/SuperMarioGalaxy/Main.ts index 52f4c99da..1a49d3174 100644 --- a/src/SuperMarioGalaxy/Main.ts +++ b/src/SuperMarioGalaxy/Main.ts @@ -284,7 +284,7 @@ export class SMGRenderer implements Viewer.SceneGfx { let texPrjMtx: mat4 | null = null; if (drawType === DrawType.EffectDrawIndirect) { texPrjMtx = scratchMatrix; - texProjCameraSceneTex(texPrjMtx, viewerInput.camera, 1); + texProjCameraSceneTex(texPrjMtx, viewerInput.camera.projectionMatrix, 1); } effectSystem.setDrawInfo(viewerInput.camera.viewMatrix, viewerInput.camera.projectionMatrix, texPrjMtx, viewerInput.camera.frustum); diff --git a/src/SuperMarioGalaxy/NameObj.ts b/src/SuperMarioGalaxy/NameObj.ts index d4b5279e1..2d586fbe2 100644 --- a/src/SuperMarioGalaxy/NameObj.ts +++ b/src/SuperMarioGalaxy/NameObj.ts @@ -7,10 +7,11 @@ import { Camera } from "../Camera.js"; import { gfxRenderInstCompareSortKey, GfxRenderInstExecutionOrder, GfxRenderInstList, GfxRenderInstManager } from "../gfx/render/GfxRenderInstManager.js"; import { LiveActor } from "./LiveActor.js"; import { JMapInfoIter } from "./JMapInfo.js"; -import { mat4 } from "gl-matrix"; +import { mat4, ReadonlyMat4 } from "gl-matrix"; import { assert, nArray, nullify } from "../util.js"; import { ub_SceneParamsBufferSize } from "../gx/gx_render.js"; import { GX_Program } from "../gx/gx_material.js"; +import { Mat4Identity } from "../MathHelpers.js"; export const enum GameBits { SMG1 = 0b01, @@ -235,7 +236,7 @@ export class NameObj { // Default implementation; nothing. } - public calcViewAndEntry(sceneObjHolder: SceneObjHolder, camera: Camera | null, viewMatrix: mat4 | null): void { + public calcViewAndEntry(sceneObjHolder: SceneObjHolder, camera: Camera | null, viewFromWorldMatrix: ReadonlyMat4): void { // Default implementation; nothing. } @@ -407,7 +408,7 @@ export class SceneNameObjListExecutor { if (drawCameraType === DrawCameraType.DrawCameraType_3D) nameObj.calcViewAndEntry(sceneObjHolder, viewerInput.camera, viewerInput.camera.viewMatrix); else if (drawCameraType === DrawCameraType.DrawCameraType_2D) - nameObj.calcViewAndEntry(sceneObjHolder, null, null); + nameObj.calcViewAndEntry(sceneObjHolder, null, Mat4Identity); else throw "whoops"; } @@ -468,7 +469,7 @@ export class SceneNameObjListExecutor { export class NameObjAdaptor extends NameObj { public calcAnimCallback: ((sceneObjHolder: SceneObjHolder) => void) | null = null; - public calcViewAndEntryCallback: ((sceneObjHolder: SceneObjHolder, camera: Camera | null, viewMatrix: mat4 | null) => void) | null = null; + public calcViewAndEntryCallback: ((sceneObjHolder: SceneObjHolder, camera: Camera | null, viewMatrix: ReadonlyMat4) => void) | null = null; public movementCallback: ((sceneObjHolder: SceneObjHolder) => void) | null = null; public drawCallback: ((sceneObjHolder: SceneObjHolder, renderInstManager: GfxRenderInstManager, viewerInput: ViewerRenderInput) => void) | null = null; @@ -477,7 +478,7 @@ export class NameObjAdaptor extends NameObj { this.calcAnimCallback(sceneObjHolder); } - public override calcViewAndEntry(sceneObjHolder: SceneObjHolder, camera: Camera | null, viewMatrix: mat4 | null): void { + public override calcViewAndEntry(sceneObjHolder: SceneObjHolder, camera: Camera | null, viewMatrix: ReadonlyMat4): void { if (this.calcViewAndEntryCallback !== null) this.calcViewAndEntryCallback(sceneObjHolder, camera, viewMatrix); } diff --git a/src/ZeldaTwilightPrincess/Main.ts b/src/ZeldaTwilightPrincess/Main.ts index 53e04ea42..6ea643f83 100644 --- a/src/ZeldaTwilightPrincess/Main.ts +++ b/src/ZeldaTwilightPrincess/Main.ts @@ -490,7 +490,7 @@ export class TwilightPrincessRenderer implements Viewer.SceneGfx { if (group === EffectDrawGroup.Indirect) { texPrjMtx = scratchMatrix; - texProjCameraSceneTex(texPrjMtx, viewerInput.camera, 1); + texProjCameraSceneTex(texPrjMtx, viewerInput.camera.projectionMatrix, 1); } this.globals.particleCtrl.setDrawInfo(viewerInput.camera.viewMatrix, viewerInput.camera.projectionMatrix, texPrjMtx, viewerInput.camera.frustum); diff --git a/src/ZeldaTwilightPrincess/d_kankyo.ts b/src/ZeldaTwilightPrincess/d_kankyo.ts index 9c8123889..cdffbc380 100644 --- a/src/ZeldaTwilightPrincess/d_kankyo.ts +++ b/src/ZeldaTwilightPrincess/d_kankyo.ts @@ -1271,12 +1271,12 @@ export function dKy_GxFog_set(envLight: dScnKy_env_light_c, fog: FogBlock, camer // have global state, we have to do this here. export function dKy_setLight__OnModelInstance(envLight: dScnKy_env_light_c, modelInstance: J3DModelInstance, camera: Camera): void { for (let i = 0; i < envLight.lightStatus.length; i++) - lightSetFromWorldLight(modelInstance.getGXLightReference(i), envLight.lightStatus[i], camera); + lightSetFromWorldLight(modelInstance.getGXLightReference(i), camera.viewMatrix, envLight.lightStatus[i]); } export function dKy_setLight__OnMaterialParams(envLight: dScnKy_env_light_c, materialParams: MaterialParams, camera: Camera): void { for (let i = 0; i < envLight.lightStatus.length; i++) - lightSetFromWorldLight(materialParams.u_Lights[i], envLight.lightStatus[i], camera); + lightSetFromWorldLight(materialParams.u_Lights[i], camera.viewMatrix, envLight.lightStatus[i]); } function setLightTevColorType_MAJI_sub(globals: dGlobals, materialInstance: MaterialInstance, tevStr: dKy_tevstr_c, mode: number): void { @@ -1328,7 +1328,7 @@ function setLightTevColorType_MAJI_light(globals: dGlobals, modelInstance: J3DMo // TODO(jstpierre): allow setting lights per MaterialInstance const envLight = globals.g_env_light; - lightSetFromWorldLight(modelInstance.getGXLightReference(0), tevStr.baseLight, globals.camera); + lightSetFromWorldLight(modelInstance.getGXLightReference(0), globals.camera.viewMatrix, tevStr.baseLight); if (mode === 2) { for (let i = 0; i < tevStr.lights.length; i++) { @@ -1346,7 +1346,7 @@ function setLightTevColorType_MAJI_light(globals: dGlobals, modelInstance: J3DMo // modelInstance.getGXLightReference(i + 2).copy(tevStr.lights[i]); for (let i = 0; i < 6; i++) - lightSetFromWorldLight(modelInstance.getGXLightReference(i + 2), envLight.lightStatus[i + 2], globals.camera); + lightSetFromWorldLight(modelInstance.getGXLightReference(i + 2), globals.camera.viewMatrix, envLight.lightStatus[i + 2]); } } @@ -1378,10 +1378,10 @@ export function setLightTevColorType_MAJI(globals: dGlobals, modelInstance: J3DM const envLight = globals.g_env_light; const light0 = modelInstance.getGXLightReference(0); - lightSetFromWorldLight(light0, tevStr.baseLight, camera); + lightSetFromWorldLight(light0, camera.viewMatrix, tevStr.baseLight); const light1 = modelInstance.getGXLightReference(1); - lightSetFromWorldLight(light1, envLight.lightStatus[1], camera); + lightSetFromWorldLight(light1, camera.viewMatrix, envLight.lightStatus[1]); modelInstance.setColorOverride(ColorKind.C0, tevStr.colorC0); modelInstance.setColorOverride(ColorKind.K0, tevStr.colorK0); diff --git a/src/ZeldaTwilightPrincess/m_do_ext.ts b/src/ZeldaTwilightPrincess/m_do_ext.ts index 72c183aea..0d10deae6 100644 --- a/src/ZeldaTwilightPrincess/m_do_ext.ts +++ b/src/ZeldaTwilightPrincess/m_do_ext.ts @@ -152,8 +152,6 @@ export function mDoExt_modelEntryDL(globals: dGlobals, modelInstance: J3DModelIn if (!modelInstance.visible) return; - const device = globals.modelCache.device; - if (drawListSet === null) drawListSet = globals.dlst.bg; @@ -162,12 +160,13 @@ export function mDoExt_modelEntryDL(globals: dGlobals, modelInstance: J3DModelIn modelInstance.setTexturesEnabled(globals.renderHacks.texturesEnabled); } - modelInstance.calcView(viewerInput.camera, viewerInput.camera.viewMatrix); + const camera = viewerInput.camera; + modelInstance.calcView(camera.viewMatrix, camera.frustum); renderInstManager.setCurrentList(drawListSet[0]); - modelInstance.drawOpa(device, renderInstManager, viewerInput.camera); + modelInstance.drawOpa(renderInstManager, camera.projectionMatrix); renderInstManager.setCurrentList(drawListSet[1]); - modelInstance.drawXlu(device, renderInstManager, viewerInput.camera); + modelInstance.drawXlu(renderInstManager, camera.projectionMatrix); } export function mDoExt_modelUpdateDL(globals: dGlobals, modelInstance: J3DModelInstance, renderInstManager: GfxRenderInstManager, viewerInput: ViewerRenderInput, drawListSet: dDlst_list_Set | null = null): void { diff --git a/src/ZeldaWindWaker/Main.ts b/src/ZeldaWindWaker/Main.ts index c60b8fdcf..eac39cf83 100644 --- a/src/ZeldaWindWaker/Main.ts +++ b/src/ZeldaWindWaker/Main.ts @@ -531,7 +531,7 @@ export class WindWakerRenderer implements Viewer.SceneGfx { if (group === EffectDrawGroup.Indirect) { texPrjMtx = scratchMatrix; - texProjCameraSceneTex(texPrjMtx, viewerInput.camera, 1); + texProjCameraSceneTex(texPrjMtx, viewerInput.camera.projectionMatrix, 1); } this.globals.particleCtrl.setDrawInfo(viewerInput.camera.viewMatrix, viewerInput.camera.projectionMatrix, texPrjMtx, viewerInput.camera.frustum); diff --git a/src/ZeldaWindWaker/d_kankyo.ts b/src/ZeldaWindWaker/d_kankyo.ts index 3bbfa7382..17f8e149a 100644 --- a/src/ZeldaWindWaker/d_kankyo.ts +++ b/src/ZeldaWindWaker/d_kankyo.ts @@ -618,12 +618,12 @@ export function dKy_GxFog_sea_set(envLight: dScnKy_env_light_c, fog: FogBlock, c // have global state, we have to do this here. export function dKy_setLight__OnModelInstance(envLight: dScnKy_env_light_c, modelInstance: J3DModelInstance, camera: Camera): void { for (let i = 0; i < 2; i++) - lightSetFromWorldLight(modelInstance.getGXLightReference(i), envLight.lightStatus[i], camera); + lightSetFromWorldLight(modelInstance.getGXLightReference(i), camera.viewMatrix, envLight.lightStatus[i]); } export function dKy_setLight__OnMaterialParams(envLight: dScnKy_env_light_c, materialParams: MaterialParams, camera: Camera): void { for (let i = 0; i < 2; i++) - lightSetFromWorldLight(materialParams.u_Lights[i], envLight.lightStatus[i], camera); + lightSetFromWorldLight(materialParams.u_Lights[i], camera.viewMatrix, envLight.lightStatus[i]); } export function setLightTevColorType(globals: dGlobals, modelInstance: J3DModelInstance, tevStr: dKy_tevstr_c, camera: Camera): void { @@ -634,10 +634,10 @@ export function setLightTevColorType(globals: dGlobals, modelInstance: J3DModelI } const light0 = modelInstance.getGXLightReference(0); - lightSetFromWorldLight(light0, tevStr.lightObj, camera); + lightSetFromWorldLight(light0, camera.viewMatrix, tevStr.lightObj); const light1 = modelInstance.getGXLightReference(1); - lightSetFromWorldLight(light1, envLight.lightStatus[1], camera); + lightSetFromWorldLight(light1, camera.viewMatrix, envLight.lightStatus[1]); // if (toon_proc_check() == 0) diff --git a/src/ZeldaWindWaker/m_do_ext.ts b/src/ZeldaWindWaker/m_do_ext.ts index 19e930792..7391509d9 100644 --- a/src/ZeldaWindWaker/m_do_ext.ts +++ b/src/ZeldaWindWaker/m_do_ext.ts @@ -90,8 +90,6 @@ export function mDoExt_modelEntryDL(globals: dGlobals, modelInstance: J3DModelIn if (!modelInstance.visible) return; - const device = globals.modelCache.device; - if (drawListSet === null) drawListSet = globals.dlst.bg; @@ -103,12 +101,13 @@ export function mDoExt_modelEntryDL(globals: dGlobals, modelInstance: J3DModelIn modelInstance.setTexturesEnabled(globals.renderHacks.texturesEnabled); } - modelInstance.calcView(viewerInput.camera, viewerInput.camera.viewMatrix); + const camera = viewerInput.camera; + modelInstance.calcView(camera.viewMatrix, camera.frustum); renderInstManager.setCurrentList(drawListSet[0]); - modelInstance.drawOpa(device, renderInstManager, viewerInput.camera); + modelInstance.drawOpa(renderInstManager, camera.projectionMatrix); renderInstManager.setCurrentList(drawListSet[1]); - modelInstance.drawXlu(device, renderInstManager, viewerInput.camera); + modelInstance.drawXlu(renderInstManager, camera.projectionMatrix); } export function mDoExt_modelUpdateDL(globals: dGlobals, modelInstance: J3DModelInstance, renderInstManager: GfxRenderInstManager, viewerInput: ViewerRenderInput, drawListSet: dDlst_list_Set | null = null): void { diff --git a/src/gx/gx_material.ts b/src/gx/gx_material.ts index d74cdbe0d..bd9eab0b3 100644 --- a/src/gx/gx_material.ts +++ b/src/gx/gx_material.ts @@ -5,8 +5,7 @@ import * as GX from './gx_enum.js'; import { colorCopy, colorFromRGBA, TransparentBlack, colorNewCopy } from '../Color.js'; import { GfxFormat } from '../gfx/platform/GfxPlatformFormat.js'; -import { vec3, mat4, ReadonlyVec3 } from 'gl-matrix'; -import { Camera } from '../Camera.js'; +import { vec3, ReadonlyVec3, ReadonlyMat4 } from 'gl-matrix'; import { assert } from '../util.js'; import { IsDepthReversed } from '../gfx/helpers/ReversedDepthHelpers.js'; import { MathConstants, transformVec3Mat4w1, transformVec3Mat4w0 } from '../MathHelpers.js'; @@ -1892,28 +1891,20 @@ export function getRasColorChannelID(v: GX.ColorChannelID): GX.RasColorChannelID } } -export function lightSetWorldPositionViewMatrix(light: Light, viewMatrix: mat4, v: ReadonlyVec3): void { +export function lightSetWorldPosition(light: Light, viewMatrix: ReadonlyMat4, v: ReadonlyVec3): void { transformVec3Mat4w1(light.Position, viewMatrix, v); } -export function lightSetWorldPosition(light: Light, camera: Camera, v: ReadonlyVec3): void { - return lightSetWorldPositionViewMatrix(light, camera.viewMatrix, v); -} - -export function lightSetWorldDirectionNormalMatrix(light: Light, normalMatrix: mat4, v: ReadonlyVec3): void { - transformVec3Mat4w0(light.Direction, normalMatrix, v); - vec3.normalize(light.Direction, v); -} - -export function lightSetWorldDirection(light: Light, camera: Camera, v: ReadonlyVec3): void { +export function lightSetWorldDirection(light: Light, viewMatrix: ReadonlyMat4, v: ReadonlyVec3): void { // TODO(jstpierre): In theory, we should multiply by the inverse-transpose of the view matrix. // However, I don't want to calculate that right now, and it shouldn't matter too much... - return lightSetWorldDirectionNormalMatrix(light, camera.viewMatrix, v); + transformVec3Mat4w0(light.Direction, viewMatrix, v); + vec3.normalize(light.Direction, v); } -export function lightSetFromWorldLight(dst: Light, worldLight: Light, camera: Camera): void { - lightSetWorldPosition(dst, camera, worldLight.Position); - lightSetWorldDirection(dst, camera, worldLight.Direction); +export function lightSetFromWorldLight(dst: Light, viewMatrix: ReadonlyMat4, worldLight: Light): void { + lightSetWorldPosition(dst, viewMatrix, worldLight.Position); + lightSetWorldDirection(dst, viewMatrix, worldLight.Direction); vec3.copy(dst.DistAtten, worldLight.DistAtten); vec3.copy(dst.CosAtten, worldLight.CosAtten); colorCopy(dst.Color, worldLight.Color); diff --git a/src/j3d/sms_scenes.ts b/src/j3d/sms_scenes.ts index eb4aeeb07..bf9c1b416 100644 --- a/src/j3d/sms_scenes.ts +++ b/src/j3d/sms_scenes.ts @@ -477,7 +477,7 @@ class LightConfig { const diffSrc = this.lightObj[0]; const diffDst = modelInstance.getGXLightReference(0); vec3.set(diffDst.Position, diffSrc.x, diffSrc.y, diffSrc.z); - lightSetWorldPosition(diffDst, camera, diffDst.Position); + lightSetWorldPosition(diffDst, camera.viewMatrix, diffDst.Position); colorFromRGBA(diffDst.Color, diffSrc.r/0xFF, diffSrc.g/0xFF, diffSrc.b/0xFF, diffSrc.a/0xFF); vec3.set(diffDst.CosAtten, 1.0, 0.0, 0.0); vec3.set(diffDst.DistAtten, 1.0, 0.0, 0.0); diff --git a/src/rres/brres.ts b/src/rres/brres.ts index 7719596cf..593c7a8c3 100644 --- a/src/rres/brres.ts +++ b/src/rres/brres.ts @@ -3011,8 +3011,8 @@ export class LightSet { m[i].copy(lightObj.light); if (lightObj.space === LightObjSpace.WORLD_SPACE) { - GX_Material.lightSetWorldPositionViewMatrix(m[i], viewMatrix, lightObj.light.Position); - GX_Material.lightSetWorldDirectionNormalMatrix(m[i], viewMatrix, lightObj.light.Direction); + GX_Material.lightSetWorldPosition(m[i], viewMatrix, lightObj.light.Position); + GX_Material.lightSetWorldDirection(m[i], viewMatrix, lightObj.light.Direction); } else if (lightObj.space === LightObjSpace.VIEW_SPACE) { // Parameters are in view-space; already copied correctly. } diff --git a/src/rres/render.ts b/src/rres/render.ts index e50ff8aaa..d81a8fc5d 100644 --- a/src/rres/render.ts +++ b/src/rres/render.ts @@ -406,7 +406,7 @@ class MaterialInstance { } if (texSrt.mapMode === BRRES.MapMode.PROJECTION) { - texProjCameraSceneTex(dstPost, camera, flipYScale); + texProjCameraSceneTex(dstPost, camera.projectionMatrix, flipYScale); // Apply effect matrix. mat4.mul(dstPost, texSrt.effectMtx, dstPost);