diff --git a/src/AShortHike/Scenes.ts b/src/AShortHike/Scenes.ts index 3d9af7784..b87b51a61 100644 --- a/src/AShortHike/Scenes.ts +++ b/src/AShortHike/Scenes.ts @@ -30,7 +30,7 @@ layout(std140) uniform ub_MaterialParams { varying vec2 v_LightIntensity; varying vec2 v_TexCoord0; -#ifdef VERT +#if defined VERT void mainVS() { Mat4x3 t_WorldFromLocalMatrix = CalcWorldFromLocalMatrix(); vec3 t_PositionWorld = Mul(t_WorldFromLocalMatrix, vec4(a_Position, 1.0)); @@ -45,14 +45,18 @@ void mainVS() { } #endif -#ifdef FRAG +#if defined FRAG uniform sampler2D u_Texture; void mainPS() { - vec4 t_Color = u_Color * texture(u_Texture, v_TexCoord0); + vec4 t_Color = u_Color; + +#if defined USE_TEXTURE + t_Color *= texture(u_Texture, v_TexCoord0); if (t_Color.a < u_AlphaCutoff) discard; +#endif float t_LightIntensity = gl_FrontFacing ? v_LightIntensity.x : v_LightIntensity.y; float t_LightTint = 0.2 * t_LightIntensity; @@ -73,7 +77,9 @@ class TempMaterial extends UnityMaterialInstance { constructor(runtime: UnityRuntime, private materialData: UnityMaterialData) { super(); - this.materialData.fillTextureMapping(this.textureMapping[0], '_MainTex'); + const hasMainTex = this.materialData.fillTextureMapping(this.textureMapping[0], '_MainTex'); + this.program.setDefineBool('USE_TEXTURE', hasMainTex); + this.alphaCutoff = fallback(this.materialData.getFloat('_Cutoff'), 0.0); if (this.materialData.name.includes('Terrain')) @@ -203,7 +209,7 @@ class TerrainMaterial extends UnityMaterialInstance { class AShortHikeMaterialFactory extends UnityMaterialFactory { public createMaterialInstance(runtime: UnityRuntime, materialData: UnityMaterialData): UnityMaterialInstance { // TODO(jstpierre): Pull out serialized shader data - if (materialData.name.includes('_Splat3')) + if (materialData.texturesByName.has('_Splat3')) return new TerrainMaterial(runtime, materialData); else return new TempMaterial(runtime, materialData); @@ -243,6 +249,8 @@ class UnityRenderer implements Viewer.SceneGfx { } public render(device: GfxDevice, viewerInput: Viewer.ViewerRenderInput) { + viewerInput.camera.setClipPlanes(1); + const mainColorDesc = makeBackbufferDescSimple(GfxrAttachmentSlot.Color0, viewerInput, standardFullClearRenderPassDescriptor); const mainDepthDesc = makeBackbufferDescSimple(GfxrAttachmentSlot.DepthStencil, viewerInput, standardFullClearRenderPassDescriptor); @@ -283,7 +291,6 @@ class AShortHikeSceneDesc implements Viewer.SceneDesc { const renderer = new UnityRenderer(runtime); return renderer; } - } const id = 'AShortHike'; diff --git a/src/Common/Unity/AssetManager.ts b/src/Common/Unity/AssetManager.ts index fa393b1ef..7bdd9e13b 100644 --- a/src/Common/Unity/AssetManager.ts +++ b/src/Common/Unity/AssetManager.ts @@ -1,15 +1,14 @@ -import { vec2, vec3, vec4 } from 'gl-matrix'; -import { UnityVersion, UnityAssetFile, UnityAssetFileObject, UnityClassID, UnityGameObject, UnityPPtr, UnityStreamingInfo, UnityMesh, UnityMeshCompression, UnityVertexFormat, UnitySubMesh, UnityAABB, UnityChannelInfo, UnityGLTextureSettings, UnityTextureFormat, UnityTexture2D, UnityMaterial, UnityTextureColorSpace } from '../../../rust/pkg/noclip_support'; +import { vec2, vec3 } from 'gl-matrix'; +import { UnityAABB, UnityAssetFile, UnityAssetFileObject, UnityChannelInfo, UnityClassID, UnityGLTextureSettings, UnityMaterial, UnityMesh, UnityMeshCompression, UnityPPtr, UnityStreamingInfo, UnitySubMesh, UnityTexture2D, UnityTextureColorSpace, UnityTextureFormat, UnityVersion, UnityVertexFormat } from '../../../rust/pkg/noclip_support'; import ArrayBufferSlice from '../../ArrayBufferSlice.js'; import { Color, TransparentBlack, colorNewFromRGBA } from '../../Color.js'; import { DataFetcher } from '../../DataFetcher.js'; -import { downloadBlob } from '../../DownloadUtils.js'; import * as Geometry from '../../Geometry.js'; import { Destroyable, SceneContext } from '../../SceneBase.js'; import { TextureMapping } from '../../TextureHolder.js'; import { coalesceBuffer, makeStaticDataBuffer } from '../../gfx/helpers/BufferHelpers.js'; -import { fillColor, fillVec4, fillVec4v } from '../../gfx/helpers/UniformBufferHelpers.js'; +import { fillColor, fillVec4 } from '../../gfx/helpers/UniformBufferHelpers.js'; import { GfxBufferUsage, GfxDevice, GfxFormat, GfxIndexBufferDescriptor, GfxInputLayout, GfxInputLayoutBufferDescriptor, GfxMipFilterMode, GfxSampler, GfxSamplerDescriptor, GfxTexFilterMode, GfxTexture, GfxVertexAttributeDescriptor, GfxVertexBufferDescriptor, GfxVertexBufferFrequency, GfxWrapMode, makeTextureDescriptor2D } from '../../gfx/platform/GfxPlatform.js'; import { FormatCompFlags, getFormatCompByteSize, setFormatCompFlags } from '../../gfx/platform/GfxPlatformFormat.js'; import { GfxRenderCache } from '../../gfx/render/GfxRenderCache.js'; @@ -149,6 +148,7 @@ export class AssetFile { private doneLoadingHeader(buffer: Uint8Array): void { this.ensureAssetFile(buffer); this.assetFile.append_metadata_chunk(buffer); + console.log(this.path, this.assetFile.get_version_string()); this.unityObjects = this.assetFile.get_objects(); for (let i = 0; i < this.unityObjects.length; i++) this.unityObjectByFileID.set(this.unityObjects[i].file_id, this.unityObjects[i]); @@ -240,10 +240,9 @@ export class AssetFile { if (pptr.file_index === 0) { return this; } else { - let externalFilename = assertExists(this.assetFile.get_external_path(pptr)); - if (externalFilename.startsWith("Library/")) { - externalFilename = externalFilename.replace("Library/", "Resources/"); - } + let externalFilename = assertExists(this.assetFile.get_external_path(pptr)).toLowerCase(); + if (externalFilename.startsWith("library/")) + externalFilename = externalFilename.replace("library/", "resources/"); return assetSystem.fetchAssetFile(externalFilename, true); } } @@ -296,13 +295,13 @@ export class AssetFile { return this.promiseCache.get(pathID)! as Promise; const promise = this.fetchObject(pathID).then((objData) => { - return createFunc(assetSystem, objData).then((v) => { - this.dataCache.set(pathID, v); - return v; - }).catch(e => { - console.error(`failed to fetch ${this.path}: ${pathID}, ${e}`); - throw e; - }); + return createFunc(assetSystem, objData).then((v) => { + this.dataCache.set(pathID, v); + return v; + }).catch(e => { + console.error(`failed to fetch ${this.path}: ${pathID}, ${e}`); + throw e; + }); }); this.promiseCache.set(pathID, promise); return promise; diff --git a/src/Common/Unity/GameObject.ts b/src/Common/Unity/GameObject.ts index 8367b44b6..16336b4be 100644 --- a/src/Common/Unity/GameObject.ts +++ b/src/Common/Unity/GameObject.ts @@ -11,6 +11,7 @@ import { ViewerRenderInput } from "../../viewer.js"; import { AssetFile, AssetLocation, AssetObjectData, UnityAssetResourceType, UnityAssetSystem, UnityChannel, UnityMaterialData, UnityMeshData, createUnityAssetSystem } from "./AssetManager.js"; import { rust } from "../../rustlib.js"; import { UnityMeshRenderer, UnityVec3, UnityQuaternion, UnityTransform, UnityPPtr, UnityGameObject, UnityMeshFilter, UnityAssetFileObject, UnityVersion } from "../../../rust/pkg/noclip_support.js"; +import { AABB } from "../../Geometry.js"; export abstract class UnityComponent { public async load(level: UnityLevel): Promise { @@ -193,8 +194,6 @@ export class MeshRenderer extends UnityComponent { if (meshData === null) return; - // TODO(jstpierre): AABB culling - if (this.staticBatchSubmeshCount > 0) { mat4.copy(this.modelMatrix, noclipSpaceFromUnitySpace); } else { @@ -203,6 +202,12 @@ export class MeshRenderer extends UnityComponent { mat4.copy(this.modelMatrix, transform.modelMatrix); } + // TODO(jstpierre): AABB culling + const aabb = new AABB(); + aabb.transform(meshData.bbox, this.modelMatrix); + if (!viewerInput.camera.frustum.contains(aabb)) + return; + const template = renderInstManager.pushTemplate(); let offs = template.allocateUniformBuffer(UnityShaderProgramBase.ub_ShapeParams, 12); diff --git a/src/NeonWhite/Scenes.ts b/src/NeonWhite/Scenes.ts index 9e1703b25..0ebbe2bd4 100644 --- a/src/NeonWhite/Scenes.ts +++ b/src/NeonWhite/Scenes.ts @@ -140,6 +140,8 @@ class UnityRenderer implements Viewer.SceneGfx { } public render(device: GfxDevice, viewerInput: Viewer.ViewerRenderInput) { + viewerInput.camera.setClipPlanes(1); + const mainColorDesc = makeBackbufferDescSimple(GfxrAttachmentSlot.Color0, viewerInput, standardFullClearRenderPassDescriptor); const mainDepthDesc = makeBackbufferDescSimple(GfxrAttachmentSlot.DepthStencil, viewerInput, standardFullClearRenderPassDescriptor); diff --git a/src/SourceEngine/BSPFile.ts b/src/SourceEngine/BSPFile.ts index e6d0335a5..b9be8576d 100644 --- a/src/SourceEngine/BSPFile.ts +++ b/src/SourceEngine/BSPFile.ts @@ -579,9 +579,8 @@ function buildOverlay(overlayInfo: OverlayInfo, faceInfos: BSPFaceInfo[], bspSur const overlayPoints = nArray(4, () => new MeshVertex()); buildOverlayPoints(overlayPoints, overlayInfo); - fetchVertexFromBuffer(surfacePoints[0], vertexData, indexData[index + 0]); - fetchVertexFromBuffer(surfacePoints[1], vertexData, indexData[index + 1]); - fetchVertexFromBuffer(surfacePoints[2], vertexData, indexData[index + 2]); + for (let i = 0; i < 3; i++) + fetchVertexFromBuffer(surfacePoints[i], vertexData, indexData[index + i]); // Store our surface plane for later, so we can re-project back to it... surfacePlane.setTri(surfacePoints[0].position, surfacePoints[2].position, surfacePoints[1].position); diff --git a/src/gfx/platform/GfxPlatform.ts b/src/gfx/platform/GfxPlatform.ts index 046a84ba0..a9f55a027 100644 --- a/src/gfx/platform/GfxPlatform.ts +++ b/src/gfx/platform/GfxPlatform.ts @@ -459,6 +459,7 @@ export interface GfxDevice { readBuffer(o: GfxReadback, dstOffset: number, buffer: GfxBuffer, srcOffset: number, byteSize: number): void; readPixelFromTexture(o: GfxReadback, dstOffset: number, a: GfxTexture, x: number, y: number): void; submitReadback(o: GfxReadback): void; + /** * Checks if the readback object {@param o} is ready. If so, this will write the full set of readback * values to {@param dst}, starting at index {@param dstOffs}, and returns true. If the readback is diff --git a/src/rustlib.ts b/src/rustlib.ts index 691509f52..3e0a35347 100644 --- a/src/rustlib.ts +++ b/src/rustlib.ts @@ -19,7 +19,7 @@ export async function loadRustLib() { const url = await import('url'); const wasmPath = path.join(path.dirname(url.fileURLToPath(import.meta.url)), '../rust/pkg/noclip_support_bg.wasm'); const wasm = fs.readFileSync(wasmPath); - rust.initSync(wasm); + rust.initSync({ module: wasm }); } */