Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore texture atlas support #19

Closed
deathcap opened this issue Dec 9, 2013 · 13 comments
Closed

Restore texture atlas support #19

deathcap opened this issue Dec 9, 2013 · 13 comments

Comments

@deathcap
Copy link
Member

deathcap commented Dec 9, 2013

See deathcap/voxel-engine@47a05ba #14

@deathcap
Copy link
Member Author

Currently can only be enabled programmatically, editing source and setting useAtlas: true (allowing dynamic runtime reconfiguration would require some more work, to reinitialize voxel-texture then game.showAllChunks()).

On:

screen shot 2013-12-11 at 8 26 39 pm

off (default):

screen shot 2013-12-11 at 8 26 18 pm

@deathcap
Copy link
Member Author

Added dynamic useAtlas toggling option in:

voxel-debug: deathcap/voxel-debug@26d9149
voxel-texture: deathcap/voxel-texture@3f65bf0 (and earlier)

deployed to http://deathcap.github.io/voxpopuli/ in 695ad52

@deathcap
Copy link
Member Author

deathcap commented Jan 6, 2014

Reopening to investigate fixing the stretching and enable atlas by default - currently texturing is the largest performance bottleneck (especially noticeable with voxel-clientmc, complex scenes), uv/atlas helps dramatically

@deathcap deathcap reopened this Jan 6, 2014
@deathcap
Copy link
Member Author

deathcap commented Jan 7, 2014

I think what is needed to solve the stretching is a custom fragment shader. Example fragment shader from https://developer.mozilla.org/en-US/docs/Web/WebGL/Using_textures_in_WebGL#The_fragment_shader:

    gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));

the fragment's color is computed by fetching the texel (that is, the pixel within the texture) that the sampler says best maps to the fragment's position

For tiling, will need something like (t * count) % size [for each dimension], where count = how many voxels to repeat across, and size = size of texture in u/v space (0..1, e.g. 0.1 if 10 textures in the atlas).

@deathcap
Copy link
Member Author

deathcap commented Jan 7, 2014

algorithm in JavaScript (will need to be converted to GLSL), only X dimension (need Y, too), ignoring texture2D/sampler lookup for now:

var tileCount = 5; // number of voxels to cover
var uStart = 0.0; // UV coordinate in atlas at beginning of texture
var uEnd = 0.5; // UV coordinate in atlas at end of texture (0.0-0.5 allows two textures, second at 0.5-1.0)

// repeats tiles from [0..1] across x [0..1], given number of times
var tile = function(x, times) {
  return x % (1 / times) * times;
};

// scale x [fromLow..fromHigh] to [toLow, toHigh]
var scale = function(x, fromLow, fromHigh, toLow, toHigh) {
  return (x - fromLow) * (toHigh - toLow) / (fromHigh - fromLow) + toLow;
};

gl_FragColor = scale(tile(x, tileCount), 0, 1, uStart, uEnd);

visualization with https://github.com/deathcap/noisecomp:

screen shot 2014-01-06 at 7 37 37 pm

repeats five times, from 0 (white) to 0.5 (gray)

deathcap added a commit to deathcap/noisecomp that referenced this issue Jan 7, 2014
@deathcap
Copy link
Member Author

deathcap commented Jan 7, 2014

http://0fps.wordpress.com/2013/07/09/texture-atlases-wrapping-and-mip-mapping/ says:

vec2 tileUV = vec2(dot(normal.zxy, position), 
               dot(normal.yzx, position))
vec2 texCoord = tileOffset + tileSize * fract(tileUV)

set https://github.com/mikolalysenko/voxel-mipmap-demo

@deathcap
Copy link
Member Author

deathcap commented Jan 9, 2014

Started looking into shaders.. voxel-texture currently uses MeshLambertMaterial, from three.js, which has uniforms, vertex shader, and fragment shader defined in https://github.com/mrdoob/three.js/tree/master/src/renderers/shaders - fairly abstractly, built up from ShaderChunks in ShaderLib. three.js provides a ShaderMaterial allowing custom uniforms (array of variable names, type, value to pass), vertexShader, and fragmentShader (text strings of GLSL programs compiled for the graphics card). Tried to replicate lambert shading with ShaderLib, but not clear how, because of the organization of three.js: https://github.com/mrdoob/three.js/blob/master/src/materials/MeshLambertMaterial.js is basically only a data type, all of the actual logic is spread out elsewhere.. (you can pass vertexShader: this.THREE.ShaderLib.lambert.vertexShader, fragmentShader: this.THREE.ShaderLib.lambert.fragmentShader, but the uniforms have to be set, too. this.THREE.ShaderLib.lambert.uniforms is only a template for the uniforms, intended to be cloned then .values set.), much of it in this 6000+ line file https://github.com/mrdoob/three.js/blob/master/src/renderers/WebGLRenderer.js with 'instanceof THREE.MeshLambertMaterial' checks, hmm...

@deathcap
Copy link
Member Author

deathcap commented Jan 9, 2014

http://stackoverflow.com/questions/12627422/custom-texture-shader-in-three-js

^ This custom shader code with texture maps works as a starting point. mikolalysenko's shaders from http://0fps.wordpress.com/2013/07/09/texture-atlases-wrapping-and-mip-mapping/ are in https://github.com/mikolalysenko/ao-shader/tree/master/lib - computing position from attrib0, normal and tile coordinate from attrib1 in the vertex shader, passing texCoord and tileCoord to the fragment shader; vec2 uv = texCoord; as opposed to voxel-texture which sets the UV coordinates from three.js, passed into the vertex shader as 'uv'.

@deathcap
Copy link
Member Author

Found this: http://www.realtimerendering.com/blog/webgl-debugging-and-profiling-tools/
Firefox 27 beta http://www.mozilla.org/en-US/firefox/beta/ has a very useful built-in Shader Editor
With its help, made some progress (this is with greedy meshing enabled):

screen shot 2014-01-11 at 2 19 49 pm

with https://github.com/deathcap/voxel-texture/tree/shadertest as of https://github.com/deathcap/voxel-texture/tree/d702869d81c0f8728e773b46f587014bbfd0481d

The texture coordinates are calculated from the fractional part of the world position coordinates (since voxels are 1x1x1, fractional parts are within voxels), instead of having three.js set and pass the UV coordinates (mesh.geometry.faceVertexUvs).

Still to do:

@deathcap
Copy link
Member Author

https://github.com/deathcap/voxel-texture/tree/93115824a52d8408e3995687afade618cb9adfb2

Added uniform vec2 tileOffsets[7] in fragmentShader to specify UV coordinates of each of the cube faces, passed in through ShaderMaterial uniforms:

 mesh.surfaceMesh.material.materials[0].uniforms.tileOffsets.value[faceIndex] = new self.game.THREE.Vector2(topUV[0], 1.0 - topUV[1]); 

sort of works, but the uniforms are shared amongst all meshes.. stuck on how to separate them out properly. I think uniforms are the right way to pass this information, as the tileOffsets remain constant throughout the entire geometry (unlike e.g. attributes, per vertex and passed to the vertex shader; or varyings, passed from vertex shader to fragment shader).

But voxel-texture only has one material for everything. this.material, set to a MeshFaceMaterial (originally with two MeshLambertMaterials; I've changed to ShaderMaterial). self.material.needsUpdate is set true in _afterLoading(), and getMesh() returns this.material...

@deathcap
Copy link
Member Author

voxel-enginehttps://github.com/maxogden/voxel-engine/blob/6873a3f6d9e15d9f1106063ef294cf887b2fb0a6/index.js#L562

else mesh.createSurfaceMesh(this.materials.material)

calls into voxel-mesh with the material. Was temporarily changed in my branch deathcap/voxel-engine@58967db to getMesh() for non-atlas compatibility. Pre-atlas texture API in max-mapper/voxel-engine@6b5e5e8 :

 -    else mesh.createSurfaceMesh(new THREE.MeshFaceMaterial(this.materials.get()))
 -    this.materials.paint(mesh.geometry)
 +    else mesh.createSurfaceMesh(this.materials.material)
 +    this.materials.paint(mesh)

and:

TextureSimple.prototype.getMesh = function() {
  return new this.THREE.MeshFaceMaterial(this.get());
};

TextureSimple.prototype.get = function(index) {
  if (index == null) return this.materials;

where materials = array of all materials. The atlas-based voxel-texture uses a MeshFaceMaterial also, but the array only has two elements, 0 for opaque and 1 for transparent (vs one for each block material texture). three.js MeshFaceMaterial works with Face3, materialIndex points into MeshFaceMaterial.materials.

deathcap added a commit to deathcap/voxel-texture that referenced this issue Jan 12, 2014
At last, texture atlasing with greedy meshing. In summary,
used the UV coordinates from three.js (may be a better
way to do this?) as the starting tile texture offsets,
then repeated with tile UVs from fract() of pos . n. Works
but this custom shader is very basic at the moment.

Ref voxel/voxelmetaverse#19
@deathcap
Copy link
Member Author

Here we go:

screen shot 2014-01-12 at 5 22 05 am

screen shot 2014-01-12 at 5 22 23 am

Highly noticeable artifacts though..

deathcap added a commit to deathcap/voxel-texture that referenced this issue Jan 12, 2014
@deathcap
Copy link
Member Author

screen shot 2014-01-12 at 5 26 22 am

deathcap added a commit to deathcap/voxel-texture that referenced this issue Jan 12, 2014
Fixes texture stretching when used with greedy voxel mesher (adds tiling)

Squashed commit of the following:

commit 3baac16
Author: deathcap <[email protected]>
Date:   Sun Jan 12 05:26:36 2014 -0800

    Re-enable atlaspack tilepad. Fixes edge artifacts

    Ref voxel/voxelmetaverse#19

commit 0f4cf41
Author: deathcap <[email protected]>
Date:   Sun Jan 12 05:11:42 2014 -0800

    Add rotation in GLSL per side. Textures finally correct!

    At last, texture atlasing with greedy meshing. In summary,
    used the UV coordinates from three.js (may be a better
    way to do this?) as the starting tile texture offsets,
    then repeated with tile UVs from fract() of pos . n. Works
    but this custom shader is very basic at the moment.

    Ref voxel/voxelmetaverse#19

commit 02214ea
Author: deathcap <[email protected]>
Date:   Sun Jan 12 04:49:33 2014 -0800

    Remove UV coord rotation - side textures are now correct, but need rotation

commit c6b3079
Author: deathcap <[email protected]>
Date:   Sun Jan 12 04:28:23 2014 -0800

    Flip texture Y (aka V, aka T) in JS instead of GLSL

commit 4430410
Author: deathcap <[email protected]>
Date:   Sun Jan 12 04:22:08 2014 -0800

    Set tileCoord from passed vUv coordinate (topmost only)

    Gets close to proper material texturing, but not quite. Some block
    faces render as expected but others have the wrong texture. Still,
    closest I've gotten so far yet with greedy meshing + atlas uv + vjs..

commit bf7a410
Author: deathcap <[email protected]>
Date:   Sun Jan 12 04:04:52 2014 -0800

    Restore three.js passing UV coords, though unused (commented out - texCoord=vUv stretches)

commit bd3a80b
Author: deathcap <[email protected]>
Date:   Sun Jan 12 03:53:49 2014 -0800

    Revert "Attempt at passing UV texture coordinates from attributes, instead of uniforms"

    This reverts commit ce2c76c.

commit ce2c76c
Author: deathcap <[email protected]>
Date:   Sun Jan 12 03:53:32 2014 -0800

    Attempt at passing UV texture coordinates from attributes, instead of uniforms

commit 9311582
Author: deathcap <[email protected]>
Date:   Sat Jan 11 20:21:49 2014 -0800

    Bug: tileOffsets uniform update changes all meshes

commit 505e0de
Author: deathcap <[email protected]>
Date:   Sat Jan 11 19:03:22 2014 -0800

    Set tileOffsets from atlaspack top UV

commit fcab718
Author: deathcap <[email protected]>
Date:   Sat Jan 11 18:41:14 2014 -0800

    Test setting tileOffsets uniforms from paint()

commit 47c9236
Author: deathcap <[email protected]>
Date:   Sat Jan 11 17:46:22 2014 -0800

    Pass array of tileOffsets, for each of 6 faces

commit 4d7bab0
Author: deathcap <[email protected]>
Date:   Sat Jan 11 17:13:24 2014 -0800

    Use a more convenient faceIndex equation, 3-z-2x-3y

commit 4710a16
Author: deathcap <[email protected]>
Date:   Sat Jan 11 17:06:07 2014 -0800

    Calculate face index from normal

commit d702869
Author: deathcap <[email protected]>
Date:   Sat Jan 11 14:13:01 2014 -0800

    Pass tileOffset as uniform; cleanup

commit ad3bf53
Author: deathcap <[email protected]>
Date:   Sat Jan 11 13:24:46 2014 -0800

    Use dot product for tileUV, fixes vertical faces

    Formula from http://0fps.wordpress.com/2013/07/09/texture-atlases-wrapping-and-mip-mapping/

commit cf6d721
Author: deathcap <[email protected]>
Date:   Sat Jan 11 12:56:23 2014 -0800

    Working tiling using fract() on position, but only on horizontal faces and with hardcoded material

    Screenshot: http://i.imgur.com/jLKX9Np.png

commit 416548c
Author: deathcap <[email protected]>
Date:   Sat Jan 11 11:59:18 2014 -0800

    Back to stretched custom shader material

commit fd8c2fb
Author: deathcap <[email protected]>
Date:   Thu Jan 9 19:04:36 2014 -0800

    Now I'm just guesisng :/

commit 1fed727
Author: deathcap <[email protected]>
Date:   Thu Jan 9 18:58:57 2014 -0800

    Move tile calculation to vertex shader

commit 2b6120b
Author: deathcap <[email protected]>
Date:   Thu Jan 9 18:50:07 2014 -0800

    Remove unneeded scale function

commit d555e2d
Author: deathcap <[email protected]>
Date:   Thu Jan 9 18:35:26 2014 -0800

    Add scale(), but might not be needed

commit 3b6fdfa
Author: deathcap <[email protected]>
Date:   Thu Jan 9 18:24:46 2014 -0800

    Disable tilepad for now

commit 4cc5949
Author: deathcap <[email protected]>
Date:   Thu Jan 9 18:24:04 2014 -0800

    Reorganize constructor to initialize uniforms

commit de992da
Author: deathcap <[email protected]>
Date:   Thu Jan 9 18:14:51 2014 -0800

    Add atlasSize uniform for clarity

commit e176a67
Author: deathcap <[email protected]>
Date:   Thu Jan 9 18:12:42 2014 -0800

    Scale by 16/512 (texture/atlas), now voxel textures are sized correctly but not of the right material

commit 42f118e
Author: deathcap <[email protected]>
Date:   Thu Jan 9 18:07:07 2014 -0800

    Now each tile displays the entire texture atlas. Progress?

commit e75fb66
Author: deathcap <[email protected]>
Date:   Thu Jan 9 18:00:31 2014 -0800

    Start porting https://github.com/mikolalysenko/ao-shader/blob/master/lib/ao.vsh . Only stripes so far

commit c218832
Author: deathcap <[email protected]>
Date:   Thu Jan 9 17:38:00 2014 -0800

    Attempt at tiling with fract(), not quite right

commit d5eb246
Author: deathcap <[email protected]>
Date:   Thu Jan 9 13:31:56 2014 -0800

    Pass normal and position varyings

commit 87a33c2
Author: deathcap <[email protected]>
Date:   Thu Jan 9 13:14:40 2014 -0800

    Simple but working custom shader with textures

    Custom uniforms, vertex shader, and fragment shader
    Based on http://stackoverflow.com/questions/12627422/custom-texture-shader-in-three-js

commit d4022d1
Author: deathcap <[email protected]>
Date:   Wed Jan 8 21:28:11 2014 -0800

    Test using ShaderMaterial (no texture)

https://github.com/deathcap/voxel-texture/tree/shadertest
deathcap added a commit that referenced this issue Jan 12, 2014
…el-pickaxe, voxel-voila

deathcap/voxel-debug@f71ef9e Add option to disable/enable useFourTap sampling for voxel-texture
deathcap/voxel-engine@76123a2 Update voxel-texture - adds 4-tap sampling
voxel/voxel-pickaxe@0abe074 Add block/item display names
voxel/voxel-voila@4204367 Lookup block data, if voxel-blockdata installed
voxel/voxel-voila@e2bdd6f Only show detailed info when crouching

Commit message generated by https://github.com/deathcap/lmno-cl
deathcap added a commit that referenced this issue Feb 28, 2014
deathcap/inventory-window@25ec626 0.2.3
deathcap/inventory-window@8a4c396 Update dependencies
deathcap/inventory-window@f93ac07 Use git URL for dependency until NPM is back up
deathcap/inventory-window@f82eb8f Scale images manually using nearest neighbor, fix blurry pixel art. Closes GH-19

Commit message generated by https://github.com/deathcap/lmno-cl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant