From 47a05ba8132263d9490e8b6f895f689befaf17fa Mon Sep 17 00:00:00 2001 From: deathcap Date: Mon, 2 Dec 2013 19:01:30 -0800 Subject: [PATCH] Revert to pre-atlas voxel-texture. Fixes https://github.com/deathcap/voxpopuli/issues/14 voxel-texture 0.5.0 switched to use texture atlases, packing all the block textures into one graphic for efficiency purposes. However, this introduces two problems: - With the culled mesher (default as of voxel-engine 0.17+), I get serious lag spikes (30-60 ms frames, or unplayably higher) when placing/breaking blocks, and also slow page load as the meshes are built (see https://github.com/deathcap/voxpopuli/issues/10) - With the greedy mesher, performance is much better (fixes first issue) but textures are stretched across each of the greedily constructed meshes, instead of tiled across each block (see https://github.com/deathcap/voxpopuli/issues/14) Example: https://f.cloud.github.com/assets/5897956/1651233/1f478c9e-5aca-11e3-82cc-4028f1e1b1da.png There are techniques for texturing greedy meshes, detailed in this article: http://0fps.wordpress.com/2013/07/09/texture-atlases-wrapping-and-mip-mapping/ - Using array textures is ideal, but they won't be supported until WebGL 2.0 at earliest https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7 - Otherwise, they can be tiled manually, but this requires a few tricks, would certainly be worthwhile to implement, but is fairly complex. Maybe later, once I understand it better. So for now, (unfortunately) I've reverted back to voxel-texture without atlases. This keeps mesh recalculation fast (when breaking/placing blocks) and avoids stretched textures but may slow down complex scenes with many materials (see performance improvement @shama noted in https://github.com/maxogden/voxel-engine/pull/69). --- README.md | 12 +++++++++--- index.js | 13 ++++++++----- package.json | 2 +- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 67c67c6..755810d 100644 --- a/README.md +++ b/README.md @@ -242,11 +242,17 @@ For example, here we have 4 faces colliding with the bottom of our object: ### Textures -Loading textures onto the texture atlas. +Loading textures creates multiple "materials". -```game.materials.load(['obsidian', 'dirt'], function(textures) { })``` +```var materials = game.materials.load(['obsidian', 'dirt'])``` -Both of these textures will be loaded into the texture atlas and expanded creating 2 voxel block types. +Both of these textures come with 6 materials, one for each side of a cube, giving a total of 12 materials. By default, faces 1 to 6 are assigned materials 1 to 6. You can assign materials to faces in however you want. For example, we could load materials 7 to 12 (e.g. the dirt materials) like so: + +```js +mesh.geometry.faces.forEach(function (face, index) { + face.materialIndex = index + 6 // obsidian texture indices 0 - 5, dirt 6 - 11 +}) +``` ### Texture-less worlds with flat colors diff --git a/index.js b/index.js index 8fb8710..e14f3ad 100644 --- a/index.js +++ b/index.js @@ -53,7 +53,7 @@ function Game(opts) { this.playerHeight = opts.playerHeight || 1.62 this.meshType = opts.meshType || 'surfaceMesh' - this.mesher = opts.mesher || voxel.meshers.culled + this.mesher = opts.mesher || voxel.meshers.greedy this.materialType = opts.materialType || THREE.MeshLambertMaterial this.materialParams = opts.materialParams || {} this.items = [] @@ -92,6 +92,7 @@ function Game(opts) { if (process.browser) { this.materials = texture({ game: this, + THREE: THREE, texturePath: opts.texturePath || './textures/', materialType: opts.materialType || THREE.MeshLambertMaterial, materialParams: opts.materialParams || {}, @@ -226,14 +227,16 @@ Game.prototype.canCreateBlock = function(pos) { } Game.prototype.createBlock = function(pos, val) { - if (typeof val === 'string') val = this.materials.find(val) + if (typeof val === 'string') val = this.materials.findIndex(val) + if (pos.chunkMatrix) return this.chunkGroups.createBlock(pos, val) if (!this.canCreateBlock(pos)) return false this.setBlock(pos, val) return true } Game.prototype.setBlock = function(pos, val) { - if (typeof val === 'string') val = this.materials.find(val) + if (typeof val === 'string') val = this.materials.findIndex(val) + if (pos.chunkMatrix) return this.chunkGroups.setBlock(pos, val) var old = this.voxels.voxelAtPosition(pos, val) var c = this.voxels.chunkAtPosition(pos) var chunk = this.voxels.chunks[c.join('|')] @@ -546,8 +549,8 @@ Game.prototype.showChunk = function(chunk) { this.voxels.meshes[chunkIndex] = mesh if (this.isClient) { if (this.meshType === 'wireMesh') mesh.createWireMesh() - else mesh.createSurfaceMesh(this.materials.material) - this.materials.paint(mesh) + else mesh.createSurfaceMesh(new THREE.MeshFaceMaterial(this.materials.get())) + this.materials.paint(mesh.geometry) } mesh.setPosition(bounds[0][0], bounds[0][1], bounds[0][2]) mesh.addToScene(this.scene) diff --git a/package.json b/package.json index 8da168c..028a51a 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "voxel-view": "git://github.com/deathcap/voxel-view.git", "voxel-raycast": "0.2.1", "voxel-control": "git://github.com/deathcap/voxel-control.git", - "voxel-texture": "0.5.6", + "voxel-texture": "0.4.0", "voxel-physical": "0.0.10", "voxel-region-change": "0.1.0", "raf": "0.0.1",