Skip to content

Commit

Permalink
fix textures for full blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
zardoy committed Dec 13, 2024
1 parent 09d8aaa commit 069831c
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 42 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
"http-browserify": "^1.7.0",
"http-server": "^14.1.1",
"https-browserify": "^1.0.0",
"mc-assets": "^0.2.23",
"mc-assets": "^0.2.25",
"minecraft-inventory-gui": "github:zardoy/minecraft-inventory-gui#next",
"mineflayer": "github:zardoy/mineflayer",
"mineflayer-pathfinder": "^2.4.4",
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion prismarine-viewer/examples/baseScene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ export class BasePlaygroundScene {
renderer.setSize(window.innerWidth, window.innerHeight)

// Create viewer
const viewer = new Viewer(renderer, { numWorkers: 6, showChunkBorders: false, })
const viewer = new Viewer(renderer, { numWorkers: 6, showChunkBorders: false, isPlayground: true })
viewer.setFirstPersonCamera(null, viewer.camera.rotation.y, viewer.camera.rotation.x)
window.viewer = viewer
viewer.world.blockstatesModels = blockstatesModels
Expand Down
41 changes: 29 additions & 12 deletions prismarine-viewer/examples/webgpuBlockModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import worldBlockProvider from 'mc-assets/dist/worldBlockProvider'
import PrismarineBlock, { Block } from 'prismarine-block'
import { IndexedBlock } from 'minecraft-data'
import { getPreflatBlock } from '../viewer/lib/mesher/getPreflatBlock'
import { WEBGPU_FULL_TEXTURES_LIMIT } from './webgpuRendererShared'

export const prepareCreateWebgpuBlocksModelsData = () => {
const blocksMap = {
Expand All @@ -27,15 +28,17 @@ export const prepareCreateWebgpuBlocksModelsData = () => {
}

const isPreflat = versionToNumber(viewer.world.version!) < versionToNumber('1.13')
const provider = worldBlockProvider(viewer.world.blockstatesModels, viewer.world.blocksAtlases, 'latest')
const provider = worldBlockProvider(viewer.world.blockstatesModels, viewer.world.blocksAtlasParser?.atlasJson ?? viewer.world.blocksAtlases, 'latest')
const PBlockOriginal = PrismarineBlock(viewer.world.version!)

const interestedTextureTiles = new Set<string>()
const blocksDataModelDebug = {} as AllBlocksDataModels
const blocksDataModel = {} as AllBlocksDataModels
const blocksProccessed = {} as Record<string, boolean>
let i = 0
const allBlocksStateIdToModelIdMap = {} as AllBlocksStateIdToModelIdMap

const addBlockModel = (state: number, name: string, props: Record<string, any>, mcBlockData?: IndexedBlock) => {
const addBlockModel = (state: number, name: string, props: Record<string, any>, mcBlockData?: IndexedBlock, defaultState = false) => {
const models = provider.getAllResolvedModels0_1({
name,
properties: props
Expand Down Expand Up @@ -75,10 +78,14 @@ export const prepareCreateWebgpuBlocksModelsData = () => {
if (Math.floor(blockData.rotation[faceIndex]) !== blockData.rotation[faceIndex]) {
throw new Error(`Invalid rotation ${rotation} ${name}`)
}
interestedTextureTiles.add(texture.debugName)
}
const k = i++
allBlocksStateIdToModelIdMap[state] = k
blocksDataModel[k] = blockData
if (defaultState) {
blocksDataModelDebug[name] ??= blockData
}
blocksProccessed[name] = true
if (mcBlockData) {
blockData.transparent = mcBlockData.transparent
Expand All @@ -91,19 +98,19 @@ export const prepareCreateWebgpuBlocksModelsData = () => {
water: 'water_still',
lava: 'lava_still'
}
for (const b of loadedData.blocksArray) {
outer: for (const b of loadedData.blocksArray) {
for (let state = b.minStateId; state <= b.maxStateId; state++) {
if (interestedTextureTiles.size >= WEBGPU_FULL_TEXTURES_LIMIT) {
console.warn(`Limit in ${WEBGPU_FULL_TEXTURES_LIMIT} textures reached for full blocks, skipping others!`)
break outer
}
const mapping = blocksMap[b.name]
const block = PBlockOriginal.fromStateId(mapping && loadedData.blocksByName[mapping] ? loadedData.blocksByName[mapping].defaultState : state, 0)
if (isPreflat) {
getPreflatBlock(block)
}
const textureOverride = textureOverrideFullBlocks[block.name]
if (!textureOverride && (block.shapes.length === 0 || !block.shapes.every(shape => {
return shape[0] === 0 && shape[1] === 0 && shape[2] === 0 && shape[3] === 1 && shape[4] === 1 && shape[5] === 1
}))) {
continue
}

const textureOverride = textureOverrideFullBlocks[block.name] as string | undefined
if (textureOverride) {
const k = i++
const texture = provider.getTextureInfo(textureOverride)
Expand All @@ -119,14 +126,24 @@ export const prepareCreateWebgpuBlocksModelsData = () => {
filterLight: b.filterLight
}
blocksDataModel[k] = blockData
} else {
addBlockModel(state, block.name, block.getProperties(), b)
interestedTextureTiles.add(textureOverride)
continue
}

if (block.shapes.length === 0 || !block.shapes.every(shape => {
return shape[0] === 0 && shape[1] === 0 && shape[2] === 0 && shape[3] === 1 && shape[4] === 1 && shape[5] === 1
})) {
continue
}

addBlockModel(state, block.name, block.getProperties(), b, state === b.defaultState)
}
}
return {
blocksDataModel,
allBlocksStateIdToModelIdMap
allBlocksStateIdToModelIdMap,
interestedTextureTiles,
blocksDataModelDebug
}
}
export type AllBlocksDataModels = Record<string, BlocksModelData>
Expand Down
5 changes: 3 additions & 2 deletions prismarine-viewer/examples/webgpuRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ export class WebgpuRenderer {
postMessage({ type: 'rendererProblem', isContextLost: true, message: info.message })
})

this.setBlocksModelData()
this.updateBlocksModelData()
this.createNewDataBuffers()

this.indirectDrawParams = new Uint32Array([quadVertexCount, 0, 0, 0])
Expand Down Expand Up @@ -564,7 +564,7 @@ export class WebgpuRenderer {
}
}

private setBlocksModelData () {
public updateBlocksModelData () {
const keys = Object.keys(this.blocksDataModel)
// const modelsDataLength = keys.length
const modelsDataLength = +keys.at(-1)!
Expand All @@ -581,6 +581,7 @@ export class WebgpuRenderer {
modelsBuffer[+i * 2 + 1] = tempBuffer2
}

this.modelsBuffer?.destroy()
this.modelsBuffer = this.createVertexStorage(modelsDataLength * cubeByteLength, 'modelsBuffer')
this.device.queue.writeBuffer(this.modelsBuffer, 0, modelsBuffer)
}
Expand Down
3 changes: 3 additions & 0 deletions prismarine-viewer/examples/webgpuRendererShared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export const rendererParamsGui = {
earlyZRejection: true
}

export const WEBGPU_FULL_TEXTURES_LIMIT = 1024
export const WEBGPU_HEIGHT_LIMIT = 1024

export type RendererInitParams = GPURequestAdapterOptions & {}

export type RendererParams = typeof defaultWebgpuRendererParams
4 changes: 4 additions & 0 deletions prismarine-viewer/examples/webgpuRendererWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ export const workerProxyType = createWorkerProxy({
updateMaxFps (fps) {
maxFps = fps
},
updateModels (blocksDataModel: WebgpuRenderer['blocksDataModel']) {
webgpuRenderer!.blocksDataModel = blocksDataModel
webgpuRenderer!.updateBlocksModelData()
},
addAddBlocksFlat (positions: number[]) {
const chunks = new Map<string, any>()
for (let i = 0; i < positions.length; i += 3) {
Expand Down
9 changes: 5 additions & 4 deletions prismarine-viewer/viewer/lib/worldrendererCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export const worldCleanup = buildCleanupDecorator('resetWorld')

export const defaultWorldRendererConfig = {
showChunkBorders: false,
numWorkers: 4
numWorkers: 4,
isPlayground: false
}

export type WorldRendererConfig = typeof defaultWorldRendererConfig
Expand All @@ -45,7 +46,6 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
threejsCursorLineMaterial: LineMaterial
@worldCleanup()
cursorBlock = null as Vec3 | null
isPlayground = false
displayStats = true
@worldCleanup()
worldConfig = { minY: 0, worldHeight: 256 }
Expand Down Expand Up @@ -312,14 +312,15 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
}
}

async updateTexturesData (resourcePackUpdate = false) {
async updateTexturesData (resourcePackUpdate = false, prioritizeBlockTextures?: string[]) {
const blocksAssetsParser = new AtlasParser(this.blocksAtlases, blocksAtlasLatest, blocksAtlasLegacy)
const itemsAssetsParser = new AtlasParser(this.itemsAtlases, itemsAtlasLatest, itemsAtlasLegacy)
const customBlockTextures = Object.keys(this.customTextures.blocks?.textures ?? {}).filter(x => x.includes('/'))
const { atlas: blocksAtlas, canvas: blocksCanvas } = await blocksAssetsParser.makeNewAtlas(this.texturesVersion ?? this.version ?? 'latest', (textureName) => {
const texture = this.customTextures?.blocks?.textures[textureName]
if (!texture) return
return texture
}, this.customTextures?.blocks?.tileSize)
}, /* this.customTextures?.blocks?.tileSize */undefined, prioritizeBlockTextures, customBlockTextures)
const { atlas: itemsAtlas, canvas: itemsCanvas } = await itemsAssetsParser.makeNewAtlas(this.texturesVersion ?? this.version ?? 'latest', (textureName) => {
const texture = this.customTextures?.items?.textures[textureName]
if (!texture) return
Expand Down
31 changes: 14 additions & 17 deletions prismarine-viewer/viewer/lib/worldrendererWebgpu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { workerProxyType } from '../../examples/webgpuRendererWorker'
import { useWorkerProxy } from '../../examples/workerProxy'
import { defaultWebgpuRendererParams, rendererParamsGui } from '../../examples/webgpuRendererShared'
import { loadJSON } from './utils.web'
import { WorldRendererCommon } from './worldrendererCommon'
import { WorldRendererCommon, WorldRendererConfig } from './worldrendererCommon'
import { MesherGeometryOutput } from './mesher/shared'
import { addNewStat, addNewStat2, updateStatText } from './ui/newStats'
import { isMobile } from './simpleUtils'
Expand All @@ -28,16 +28,16 @@ export class WorldRendererWebgpu extends WorldRendererCommon {
postRender = () => {}
preRender = () => {}
rendererParams = defaultWebgpuRendererParams
initCalled = false

webgpuChannel: typeof workerProxyType['__workerProxy'] = this.getPlaceholderChannel()
rendererDevice = '...'
powerPreference: string | undefined

constructor (config, { powerPreference } = {} as any) {
constructor (config: WorldRendererConfig, { powerPreference } = {} as any) {
super(config)
this.powerPreference = powerPreference

void this.initWebgpu()
void this.readyWorkerPromise.then(() => {
this.addWebgpuListener('rendererProblem', (data) => {
this.issueReporter.reportProblem(data.isContextLost, data.message)
Expand Down Expand Up @@ -163,7 +163,12 @@ export class WorldRendererWebgpu extends WorldRendererCommon {
}

async updateTexturesData (resourcePackUpdate = false): Promise<void> {
await super.updateTexturesData()
const { blocksDataModelDebug: blocksDataModelBefore, interestedTextureTiles } = prepareCreateWebgpuBlocksModelsData()
await super.updateTexturesData(undefined, [...interestedTextureTiles].map(x => x.replace('block/', '')))
const { blocksDataModel, blocksDataModelDebug, allBlocksStateIdToModelIdMap } = prepareCreateWebgpuBlocksModelsData()
// this.webgpuChannel.updateModels(blocksDataModel)
this.sendDataForWebgpuRenderer({ allBlocksStateIdToModelIdMap })
void this.initWebgpu(blocksDataModel)
if (resourcePackUpdate) {
const blob = await fetch(this.material.map!.image.src).then(async (res) => res.blob())
this.webgpuChannel.updateTexture(blob)
Expand Down Expand Up @@ -203,23 +208,15 @@ export class WorldRendererWebgpu extends WorldRendererCommon {
}
}

async initWebgpu () {
async initWebgpu (blocksDataModel) {
if (this.initCalled) return
this.initCalled = true
// do not use worker in safari, it is bugged
const USE_WORKER = defaultWebgpuRendererParams.webgpuWorker

const playground = this.isPlayground
if (!this.material.map) {
await new Promise<void>(resolve => {
// this.material.map!.image.onload = () => {
// resolve()
// }
this.renderUpdateEmitter.once('textureDownloaded', resolve)
})
}
const playground = this.config.isPlayground
const { image } = (this.material.map!)
const imageBlob = await fetch(image.src).then(async (res) => res.blob())
const { blocksDataModel: modelsData, allBlocksStateIdToModelIdMap } = prepareCreateWebgpuBlocksModelsData()
this.sendDataForWebgpuRenderer({ allBlocksStateIdToModelIdMap })

const existingCanvas = document.getElementById('viewer-canvas')
existingCanvas?.remove()
Expand Down Expand Up @@ -252,7 +249,7 @@ export class WorldRendererWebgpu extends WorldRendererCommon {
imageBlob,
playground,
pickObj(localStorage, 'vertShader', 'fragShader', 'computeShader'),
modelsData,
blocksDataModel,
{ powerPreference: this.powerPreference as GPUPowerPreference }
)

Expand Down

0 comments on commit 069831c

Please sign in to comment.