diff --git a/prismarine-viewer/examples/playground.ts b/prismarine-viewer/examples/playground.ts index 693c4eef..a834b28d 100644 --- a/prismarine-viewer/examples/playground.ts +++ b/prismarine-viewer/examples/playground.ts @@ -13,18 +13,8 @@ import JSZip from 'jszip' import { TWEEN_DURATION } from '../viewer/lib/entities' import Entity from '../viewer/lib/entity/Entity' // import * as Mathgl from 'math.gl' -import { m4 } from 'twgl.js' -import Stats from 'stats.js' - -//@ts-ignore -import Dirt from 'minecraft-assets/minecraft-assets/data/1.17.1/blocks/dirt.png' -//@ts-ignore -import Stone from 'minecraft-assets/minecraft-assets/data/1.17.1/blocks/stone.png' - -//@ts-ignore -import VertShader from './_VertexShader.vert' -//@ts-ignore -import FragShader from './_FragmentShader.frag' +import { findTextureInBlockStates } from '../../src/playerWindows' +import { initWeblRenderer } from './webglRenderer' globalThis.THREE = THREE //@ts-ignore @@ -95,8 +85,7 @@ async function main() { const mcData = require('minecraft-data')(version) window['loadedData'] = mcData -const stats = new Stats() -gui.add(params, 'version', globalThis.includedVersions) + gui.add(params, 'version', globalThis.includedVersions) gui.add(params, 'block', mcData.blocksArray.map(b => b.name).sort((a, b) => a.localeCompare(b))) const metadataGui = gui.add(params, 'metadata') gui.add(params, 'supportBlock') @@ -139,279 +128,10 @@ gui.add(params, 'version', globalThis.includedVersions) // await schem.paste(world, new Vec3(0, 60, 0)) const worldView = new WorldDataEmitter(world, viewDistance, targetPos) - - const canvas = document.createElement('canvas') - const gl = canvas.getContext('webgl2')! - - const program = createProgram(gl, VertShader, FragShader) - const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100000) - - let vertices = new Float32Array([ - -0.5, -0.5, -0.5, 0.0, 0.0, - 0.5, -0.5, -0.5, 1.0, 0.0, - 0.5, 0.5, -0.5, 1.0, 1.0, - 0.5, 0.5, -0.5, 1.0, 1.0, - -0.5, 0.5, -0.5, 0.0, 1.0, - -0.5, -0.5, -0.5, 0.0, 0.0, - - -0.5, -0.5, 0.5, 0.0, 0.0, - 0.5, -0.5, 0.5, 1.0, 0.0, - 0.5, 0.5, 0.5, 1.0, 1.0, - 0.5, 0.5, 0.5, 1.0, 1.0, - -0.5, 0.5, 0.5, 0.0, 1.0, - -0.5, -0.5, 0.5, 0.0, 0.0, - - -0.5, 0.5, 0.5, 1.0, 0.0, - -0.5, 0.5, -0.5, 1.0, 1.0, - -0.5, -0.5, -0.5, 0.0, 1.0, - -0.5, -0.5, -0.5, 0.0, 1.0, - -0.5, -0.5, 0.5, 0.0, 0.0, - -0.5, 0.5, 0.5, 1.0, 0.0, - - 0.5, 0.5, 0.5, 1.0, 0.0, - 0.5, 0.5, -0.5, 1.0, 1.0, - 0.5, -0.5, -0.5, 0.0, 1.0, - 0.5, -0.5, -0.5, 0.0, 1.0, - 0.5, -0.5, 0.5, 0.0, 0.0, - 0.5, 0.5, 0.5, 1.0, 0.0, - - -0.5, -0.5, -0.5, 0.0, 1.0, - 0.5, -0.5, -0.5, 1.0, 1.0, - 0.5, -0.5, 0.5, 1.0, 0.0, - 0.5, -0.5, 0.5, 1.0, 0.0, - -0.5, -0.5, 0.5, 0.0, 0.0, - -0.5, -0.5, -0.5, 0.0, 1.0, - - -0.5, 0.5, -0.5, 0.0, 1.0, - 0.5, 0.5, -0.5, 1.0, 1.0, - 0.5, 0.5, 0.5, 1.0, 0.0, - 0.5, 0.5, 0.5, 1.0, 0.0, - -0.5, 0.5, 0.5, 0.0, 0.0, - -0.5, 0.5, -0.5, 0.0, 1.0 - ]) - - let CubePositions = [] as any - - //write random coordinates to cube positions xyz ten cubes; - for (let i = 0; i < 100_000; i++) { - let x = Math.random() * 100 - 50; - let y = Math.random() * 100 - 50; - let z = Math.random() * 100 - 100; - CubePositions.push([x, y, z]); - } - - let VBO, VAO = gl.createVertexArray(); - VBO = gl.createBuffer(); - //EBO = gl.createBuffer(); - - gl.bindVertexArray(VAO); - gl.bindBuffer(gl.ARRAY_BUFFER, VBO) - gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW) - - //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, EBO) - //gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW) - - gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 5 * 4, 0) - gl.enableVertexAttribArray(0) - - gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 5 * 4, 3 * 4) - gl.enableVertexAttribArray(1) - - //gl.vertexAttribPointer(2,2,gl.FLOAT, false, 8*4 , 6*4) - //gl.enableVertexAttribArray(2) - - - gl.bindBuffer(gl.ARRAY_BUFFER, null); - gl.bindVertexArray(null) - - let image = new Image(); - // simple black white chess image 10x10 - image.src = Dirt - let image2 = new Image(); - // simple black white chess image 10x10 - image2.src = '/textures/1.18.1.png' - - console.log(image.src) - await new Promise((resolve) => { - image.onload = resolve - }) - await new Promise((resolve) => { - image2.onload = resolve - }) - - let pitch = 0, yaw = 0; - let x = 0, y = 0, z = 0; - - const keys = (e) => { - const code = e.code - const pressed = e.type === 'keydown' - if (pressed) { - if (code === 'KeyW') { - z--; - } - if (code === 'KeyS') { - z++; - } - if (code === 'KeyA') { - x--; - } - if (code === 'KeyD') { - x++; - } - } - } - window.addEventListener('keydown', keys) - window.addEventListener('keyup', keys) - - // mouse - const mouse = { x: 0, y: 0 } - const mouseMove = (e) => { - if (e.buttons === 1) { - yaw += e.movementY/20; - pitch += e.movementX/20; - } - } - window.addEventListener('mousemove', mouseMove) - const viewer = new Viewer(null as any | null, 1) globalThis.viewer = viewer - viewer.world.texturesVersion = ('1.18.1') - viewer.world.updateTexturesData() - await new Promise(resolve => { - // console.log('viewer.world.material.map!.image', viewer.world.material.map!.image) - // viewer.world.material.map!.image.onload = () => { - // console.log(this.material.map!.image) - // resolve() - // } - viewer.world.renderUpdateEmitter.once('blockStatesDownloaded', resolve) - }) - console.log(viewer.world.downloadedBlockStatesData) - const names = Object.keys(viewer.world.downloadedBlockStatesData) - let texture1 = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, texture1); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - //.tset texture fgl.ering paramegl.s - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, image.width, image.height, 0, gl.RGB, gl.UNSIGNED_BYTE, image); - //gl.generateMipmap(gl.TEXTURE_2D); - - let texture2 = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, texture2); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - //.tset texture fgl.ering paramegl.s - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, image2.width, image2.height, 0, gl.RGB, gl.UNSIGNED_BYTE, image2); - //gl.generateMipmap(gl.TEXTURE_2D); - - gl.useProgram(program) - - gl.uniform1i(gl.getUniformLocation(program, "texture1"), 0); - gl.uniform1i(gl.getUniformLocation(program, "texture2"), 1); - - //gl.attachShader(program, program) - gl.enable(gl.DEPTH_TEST) - //gl.generateMipmap() - //gl.enable(gl) - //gl.clearColor(0, 0, 0, 1) - //gl.clear(gl.COLOR_BUFFER_BIT) - document.body.appendChild(canvas) - - let view = m4.lookAt([0, 0, 2], [0, 0, 0], [0, 1, 0]) - const projection = m4.perspective(75 * Math.PI / 180, gl.canvas.width / gl.canvas.height, 0.1, 512) - // view = m4.identity(); - // m4.rotateX(view, yaw * Math.PI / 180) - // m4.rotateY(view, pitch * Math.PI / 180) - // m4.translate(view, [x,y,z], view) - let ModelUniform = gl.getUniformLocation(program, "model") - let uvUniform = gl.getUniformLocation(program, "uv"); - let ViewUniform = gl.getUniformLocation(program, "view") - let ProjectionUniform = gl.getUniformLocation(program, "projection") - - // stats.addPanel(new Stats.Panel('FPS', '#0ff', '#002')) - document.body.appendChild(stats.dom) - const loop = (performance) => { - stats.begin() - gl.canvas.width = window.innerWidth * window.devicePixelRatio - gl.canvas.height = window.innerHeight * window.devicePixelRatio - gl.viewport(0, 0, gl.canvas.width, gl.canvas.height) - - view = m4.identity(); - m4.rotateX(view, yaw * Math.PI / 180, view) - m4.rotateY(view, pitch * Math.PI / 180, view) - m4.translate(view, [x,y,z], view) - - gl.clearColor(0.1, 0, 0, 0); - gl.clear(gl.COLOR_BUFFER_BIT) - gl.clear(gl.DEPTH_BUFFER_BIT) - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, texture1); - gl.activeTexture(gl.TEXTURE1); - gl.bindTexture(gl.TEXTURE_2D, texture2); - - gl.useProgram(program) - - gl.uniformMatrix4fv(ViewUniform, false, view); - gl.uniformMatrix4fv(ProjectionUniform, false, projection); - - - - gl.bindVertexArray(VAO) - - - let i = 0 - CubePositions.forEach((cubePosition) => { - const model = m4.identity() - - m4.translate(model, [cubePosition[0], cubePosition[1], cubePosition[2]], model); - //m4.rotateX(model, performance / 1000*i/800 + Math.random() / 100, model); - //m4.rotateY(model, performance / 2500*i/800 + Math.random() / 100, model) - //m4.rotateZ(model, Math.random() / 1010, model) - gl.uniformMatrix4fv(ModelUniform, false, model); - gl.uniform2fv(uvUniform, [i%64 * 1/64,parseInt(i/64) * 1/64]); - - // let result - // i %= names.length / 2 - // for (const name of ['stone']) { - // result = viewer.world.downloadedBlockStatesData[name]?.variants?.['']?.[0]?.model?.elements?.[0]?.faces?.north?.texture - // i++ - // if (result) break - // } - // const - // const tileSize = image.width - // const blocks = - // result = { - // v: 3*1/64, - // u: 4*1/64 - // } - - i++ - i %= 800; - - - gl.drawArrays(gl.TRIANGLES, 0, 36); - }) - ///model.translate([0, 0, 0], model) - - requestAnimationFrame(loop) - //gl.Swa - stats.end() - } - loop(performance.now) - - // gl.deleteVertexArray(VAO); - // gl.deleteBuffer(VBO) - // gl.deleteBuffer(EBO) - // gl.deleteProgram(program) + initWeblRenderer() return @@ -461,34 +181,3 @@ gui.add(params, 'version', globalThis.includedVersions) // }) } main() - -export const createProgram = (gl: WebGL2RenderingContext, vertexShader: string, fragmentShader: string) => { - const createShader = (gl: WebGL2RenderingContext, type: number, source: string) => { - const shaderName = type === gl.VERTEX_SHADER ? 'vertex' : 'fragment' - const shader = gl.createShader(type)! - gl.shaderSource(shader, source) - gl.compileShader(shader) - - const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS) - if (!success) { - const info = gl.getShaderInfoLog(shader) - gl.deleteShader(shader) - throw new Error(`Shader ${shaderName} compile error: ` + info) - } - return shader - } - - - - const program = gl.createProgram()! - gl.attachShader(program, createShader(gl, gl.VERTEX_SHADER, vertexShader)!) - gl.attachShader(program, createShader(gl, gl.FRAGMENT_SHADER, fragmentShader)!) - gl.linkProgram(program) - const linkSuccess = gl.getProgramParameter(program, gl.LINK_STATUS) - if (!linkSuccess) { - const info = gl.getProgramInfoLog(program) - gl.deleteProgram(program) - throw new Error('Program link error: ' + info) - } - return program -} diff --git a/prismarine-viewer/viewer/lib/viewer.ts b/prismarine-viewer/viewer/lib/viewer.ts index d4c4f066..f58a7ba3 100644 --- a/prismarine-viewer/viewer/lib/viewer.ts +++ b/prismarine-viewer/viewer/lib/viewer.ts @@ -7,9 +7,7 @@ import { Primitives } from './primitives' import { getVersion } from './version' import EventEmitter from 'events' import { EffectComposer, RenderPass, ShaderPass, FXAAShader } from 'three-stdlib' -import { WorldHolder } from './worldrenderer' -THREE.ShaderChunk export class Viewer { scene: THREE.Scene ambientLight: THREE.AmbientLight @@ -30,10 +28,22 @@ export class Viewer { fxaaPass: ShaderPass renderPass: RenderPass - constructor(public holder: WorldHolder, numWorkers?: number, public enableFXAA = false) { - this.world = new WorldRenderer(holder, numWorkers) - // this.entities = new Entities(this.scene) - // this.primitives = new Primitives(this.scene, this.camera) + constructor(public renderer: THREE.WebGLRenderer, numWorkers?: number, public enableFXAA = false) { + // https://discourse.threejs.org/t/updates-to-color-management-in-three-js-r152/50791 + THREE.ColorManagement.enabled = false + renderer.outputColorSpace = THREE.LinearSRGBColorSpace + + this.scene = new THREE.Scene() + this.scene.matrixAutoUpdate = false // for perf + this.resetScene() + if (this.enableFXAA) { + this.enableFxaaScene() + } + this.world = new WorldRenderer(this.scene, numWorkers) + this.entities = new Entities(this.scene) + this.primitives = new Primitives(this.scene, this.camera) + + this.domElement = renderer.domElement } resetScene () { @@ -182,15 +192,15 @@ export class Viewer { tweenJs.update() } - // render () { - // if (this.composer) { - // this.renderPass.camera = this.camera - // this.composer.render() - // } else { - // this.renderer.render(this.scene, this.camera) - // } - // this.entities.render() - // } + render () { + if (this.composer) { + this.renderPass.camera = this.camera + this.composer.render() + } else { + this.renderer.render(this.scene, this.camera) + } + this.entities.render() + } async waitForChunksToRender () { await this.world.waitForChunksToRender() diff --git a/src/playerWindows.ts b/src/playerWindows.ts index bdbe34a1..a0e08e99 100644 --- a/src/playerWindows.ts +++ b/src/playerWindows.ts @@ -127,7 +127,7 @@ export const onGameLoad = (onLoad) => { }) } -const findTextureInBlockStates = (name) => { +export const findTextureInBlockStates = (name) => { assertDefined(viewer) const blockStates: BlockStates = viewer.world.customBlockStatesData || viewer.world.downloadedBlockStatesData const vars = blockStates[name]?.variants