Skip to content

Commit

Permalink
Add custom ShaderMaterial supporting greedy meshing + atlas texturing
Browse files Browse the repository at this point in the history
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
  • Loading branch information
deathcap committed Jan 12, 2014
1 parent dad8347 commit a58b287
Showing 1 changed file with 92 additions and 23 deletions.
115 changes: 92 additions & 23 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,41 +36,110 @@ function Texture(game, opts) {
var useFlatColors = opts.materialFlatColor === true;
delete opts.materialFlatColor;

// create a canvas for the texture atlas
this.canvas = (typeof document !== 'undefined') ? document.createElement('canvas') : {};
this.canvas.width = opts.atlasWidth || 512;
this.canvas.height = opts.atlasHeight || 512;
var ctx = this.canvas.getContext('2d');
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);

// create core atlas and texture
this.atlas = createAtlas(this.canvas);
this.atlas.tilepad = true;
this._atlasuv = false;
this._atlaskey = false;
this.texture = new this.THREE.Texture(this.canvas);

this.options = {
crossOrigin: 'Anonymous',
materialParams: {
ambient: 0xbbbbbb,
transparent: false,
side: this.THREE.DoubleSide
side: this.THREE.DoubleSide,

uniforms: {
tileMap: {type: 't', value: this.texture},
tileSize: {type: 'f', value: 16.0}, // size of one individual texture tile
tileSizeUV: {type: 'f', value: 16.0 / this.canvas.width} // size of tile in UV units (0.0-1.0)
},
vertexShader: [
'varying vec3 vNormal;',
'varying vec3 vPosition;',
'varying vec2 vUv;', // to set from three.js's "uv" attribute passed in
'',
'void main() {',
' vNormal = normal;',
' vPosition = position;',
' vUv = uv;',
'',
' gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);',
'}'
].join('\n'),
fragmentShader: [
'uniform float tileSize;',
'uniform sampler2D tileMap;',
'uniform float tileSizeUV;',
'uniform vec2 tileOffsets[7];',
'',
'varying vec3 vNormal;',
'varying vec3 vPosition;',
'varying vec2 vUv;',
'',
'void main() {',
// use world coordinates to repeat [0..1] offsets, within _each_ tile face
' vec2 tileUV = vec2(dot(vNormal.zxy, vPosition),',
' dot(vNormal.yzx, vPosition));',

' tileUV = fract(tileUV);',
'',
' // back: flip 180',
' if (vNormal.z < 0.0) tileUV.t = 1.0 - tileUV.t;',
'',
' // left: rotate 90 ccw',
' if (vNormal.x < 0.0) {',
' float r = tileUV.s;',
' tileUV.s = tileUV.t;',
' tileUV.t = 1.0 - r;',
' }',
'',
' // right: rotate 90 cw',
' if (vNormal.x > 0.0) {',
' float r = tileUV.s;',
' tileUV.s = tileUV.t;',
' tileUV.t = r;',
' }', // TODO: might technically need to mirror-image other sides? (can't really tell)
'',

// three.js' UV coordinate is passed as tileOffset, starting point determining the texture
// material type (_not_ interpolated; same for all vertices).
' vec2 tileOffset = vUv;',

// index tile at offset into texture atlas, see references:
// http://0fps.wordpress.com/2013/07/09/texture-atlases-wrapping-and-mip-mapping/
// https://github.com/mikolalysenko/ao-shader/blob/master/lib/ao.fsh
// https://github.com/mikolalysenko/ao-shader/blob/master/lib/ao.vsh
' vec2 texCoord = tileOffset + tileSizeUV * tileUV;',
'',
' gl_FragColor = texture2D(tileMap, texCoord);',
'}'
].join('\n')
},
materialTransparentParams: {
ambient: 0xbbbbbb,
transparent: true,
side: this.THREE.DoubleSide,
//depthWrite: false,
//depthTest: false
// TODO
},
materialType: this.THREE.MeshLambertMaterial,
materialType: this.THREE.ShaderMaterial,
applyTextureParams: function(map) {
map.magFilter = self.THREE.NearestFilter;
map.minFilter = self.THREE.LinearMipMapLinearFilter;
}
};

// create a canvas for the texture atlas
this.canvas = (typeof document !== 'undefined') ? document.createElement('canvas') : {};
this.canvas.width = opts.atlasWidth || 512;
this.canvas.height = opts.atlasHeight || 512;
var ctx = this.canvas.getContext('2d');
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);

// create core atlas and texture
this.atlas = createAtlas(this.canvas);
this.atlas.tilepad = true;
this._atlasuv = false;
this._atlaskey = false;
this.texture = new this.THREE.Texture(this.canvas);
this.options.applyTextureParams(this.texture);

if (useFlatColors) {
Expand All @@ -80,9 +149,7 @@ function Texture(game, opts) {
});
} else {
var opaque = new this.options.materialType(this.options.materialParams);
opaque.map = this.texture;
var transparent = new this.options.materialType(this.options.materialTransparentParams);
transparent.map = this.texture;
this.material = new this.THREE.MeshFaceMaterial([
opaque,
transparent
Expand Down Expand Up @@ -290,17 +357,19 @@ Texture.prototype.paint = function(mesh, materials) {
// | |
// 3 -- 2
// faces on these meshes are flipped vertically, so we map in reverse
// TODO: tops need rotate
if (isVoxelMesh) {
if (face.normal.z === -1 || face.normal.x === 1) {
atlasuv = uvrot(atlasuv, 90);
}
atlasuv = uvinvert(atlasuv);
} else {
atlasuv = uvrot(atlasuv, -90);
}

// range of UV coordinates for this texture (see above diagram)
var topUV = atlasuv[0], rightUV = atlasuv[1], bottomUV = atlasuv[2], leftUV = atlasuv[3];

// pass texture start in UV coordinates
for (var j = 0; j < mesh.geometry.faceVertexUvs[0][i].length; j++) {
mesh.geometry.faceVertexUvs[0][i][j].set(atlasuv[j][0], 1 - atlasuv[j][1]);
//mesh.geometry.faceVertexUvs[0][i][j].set(atlasuv[j][0], 1 - atlasuv[j][1]);
mesh.geometry.faceVertexUvs[0][i][j].set(topUV[0], 1.0 - topUV[1]); // set all to top (fixed tileSizeUV)
}
});

Expand Down

0 comments on commit a58b287

Please sign in to comment.