I have a large plane with a texture map in three.js and I'm finding that the default settings I'm using cause too much blurring in the mid-distance. I want to increase the DOF so more of the floor material is in focus (especially along the right side).
http://i.imgur.com/JBYtFk6.jpg
Original: http://jsfiddle.net/5L5vxjkm/4/
Performance is not a factor so anything that improves the texture fidelity and/or focus is acceptable provided it works on latest Firefox in Xvfb (ie, using OS mesa drivers).
I did attempt to adapt http://threejs.org/examples/webgl_postprocessing_dof.html but it isn't giving me the expected results (still too blurry):
With DOF Postprocessing: http://jsfiddle.net/u7g48bt2/1/
The abbreviated code is below (see jsFiddle link for complete source)
doRender = function() {
renderer = new THREE.WebGLRenderer({antialias:true, preserveDrawingBuffer:true});
FOV = 60;
camera = new THREE.PerspectiveCamera(FOV, WIDTH/HEIGHT, .1, 8000);
camera.position.x = -100;
camera.position.y = 300;
camera.position.z = 1000;
camera.lookAt(new THREE.Vector3( 0, 300, 0 )); // look down and center
// Add Floor planes
// FLOOR
floorTexture.needsUpdate = true;
var floorMaterial = new THREE.MeshPhongMaterial( { map: floorTexture, side: THREE.DoubleSide } );
var floorGeometry = new THREE.PlaneBufferGeometry(4*1024, 4*1024, 256, 256);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.doubleSided = true;
floor.rotation.x = Math.PI / 2;
floor.rotation.z = Math.PI / 3.9; // increase to rotate CCW
scene.add(floor);
var moreFloor2 = floor.clone();
moreFloor2.translateY(-4*1024);
scene.add(moreFloor2);
}
window.onload = function() {
// Enable cross-origin access to images
THREE.ImageUtils.crossOrigin = '';
floorTexture = THREE.ImageUtils.loadTexture('http://i.imgur.com/iEDVgsN.jpg?1', THREE.UVMapping, doRender);
};
Solution was simple in the end:
floorTexture.anisotropy = renderer.getMaxAnisotropy();
Which sets anisotropy to 16 I think.
UPDATE: Works on FF for Windows but under Xvfb / Mesa renderer.maxAnisotropy returns 0. Any workarounds?
UPDATE 2: It LIES! Manually setting floorTexture.anisotropy to values up to 16 actually works, meaning the maxAnisotropy returned by three.js under xvfb/mesa is plain wrong. Therefore this solution does work after all with a minor change:
floorTexture.anisotropy = 16;
UPDATE 3: My mistake! Anisotropic was NOT working. Solution was to switch the backend mesa driver to one that does support it:
DISPLAY=:5 LIBGL_ALWAYS_SOFTWARE=1 GALLIUM_DRIVER=softpipe firefox &
Many thanks to glennk on dri-devel#irc.freenode.org for this fix.
Related
I'm working on building up quite a complex static render in the browser with three.js and have gotten stuck early in the process trying to produce correct shadows with a single THREE.DirectionalLight representing the sun in my scene. All the geometry (contained in another .js file) has shadows enabled. The green sphere is for debugging purposes and is translated (50,0,50) to the center of the plane to represent the target for the camera and location of DirectionalLight.target. The directional light position and main camera position did set correctly.
My theory on why the shadows aren't working is because the orthogonal camera representing the shadow camera is pointing off in the wrong direction. I failed yesterday to figure out and solve the behaviour of the directional light helper (white line to the origin) and shadow camera helper (right).
I'm assuming the correct orientation, and the orientation I'm aiming for, has the directional light helper and shadow camera helper aligned to the center of the plane. After so much research yesterday, my shadow camera doesn't seem to automatically pick up the light position / light target vector. Why are they still anchored to the origin?
Does anyone have any suggestions about how to fix the DirectionalLight.target in my scene? Why are the DirectionalLightHelper and CameraHelper inconsistent?
// Set up
const canvus = document.getElementById('canvus');
const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
//Camera
const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 500);
camera.position.set(200, 100, 100);
camera.lookAt(50, 0, 50);
// Lighting
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(100, 200, 200);
directionalLight.target.position.set(50, 0, 50);
directionalLight.castShadow = true;
directionalLight.shadow.bias = 0.0001;
directionalLight.shadow.mapSize.width = 1024; // default
directionalLight.shadow.mapSize.height = 1024; // default
const view_n = 50;
directionalLight.shadow.camera = new THREE.OrthographicCamera(
-view_n,
view_n,
view_n,
-view_n,
60,
150
);
scene.add(directionalLight, directionalLight.target);
//helpers
const lighthelper = new THREE.DirectionalLightHelper(directionalLight, 10);
const camerahelper = new THREE.CameraHelper(directionalLight.shadow.camera);
scene.add(lighthelper);
scene.add(camerahelper);
//Main Render
createBasicGeometry(scene); // from geometry.js
createGroundPlane(scene); // from geometry.js
renderer.render(scene, camera);
Update 2020-1-5
I had initially tried setting the camera and also found examples of people setting a new ortho shadow camera directly. As I'm motivated to overcome the issue, and for thoroughness, I updated my code to reflect the suggestion and unfortunately the problem persists. I've re-checked that all mesh geometry is set to both object.receiveShadow = true and object.castShadow = true with the MeshPhongMaterial. It's completely confounding why directionalLight.target.position.set(50, 0, 50) is not updating as expected. What is the cause of this behaviour?
// Updated Lighting
const view_n = 50;
directionalLight.castShadow = true;
directionalLight.shadow.bias = 0.0001;
directionalLight.shadow.camera.right = view_n;
directionalLight.shadow.camera.left = -view_n;
directionalLight.shadow.camera.top = view_n;
directionalLight.shadow.camera.bottom = -view_n;
directionalLight.shadow.camera.near = 60;
directionalLight.shadow.camera.far = 150;
directionalLight.shadow.mapSize.width = 1024; // default
directionalLight.shadow.mapSize.height = 1024; // default
scene.add(directionalLight, directionalLight.target);
When I dump the directionalLight I get the target position I expected, though not aligned correctly in the scene. While the camera position gives another strange results.
console.log(directionalLight.target.position);
//Vector3ย {x: 50, y: 0, z: 50, isVector3: true}
console.log(directionalLight.shadow.camera.position);
directionalLight.shadow.camera = new THREE.OrthographicCamera(
-view_n,
view_n,
view_n,
-view_n,
60,
150
);
Please do not overwrite the camera reference of LightShadow.camera. Configure the directional light like so:
dirLight.castShadow = true;
dirLight.shadow.camera.top = view_n;
dirLight.shadow.camera.bottom = - view_n;
dirLight.shadow.camera.left = - view_n;
dirLight.shadow.camera.right = view_n;
dirLight.shadow.camera.near = 60;
dirLight.shadow.camera.far = 150;
Besides shadow casting only works if all shadow casting objects (like your boxes) have castShadow set to true. All shadow receiving objects (like your floor) must set receiveShadow to true.
Perhaps because I'm doing this render statically without an animation loop this problem cropped up but was solved by inserting updateMatrixWorld to the directional light target. (Unforuately I wasn't able to update the shadow's camerahelper but at least the shadows are now working as expected.)
directionalLight.target.updateMatrixWorld();
scene.add(directionalLight);
scene.add(directionalLight.target);
Edit;
working codepen (need to provide video file to avoid cross-origin policy)
https://codepen.io/bw1984/pen/pezOXm
I am attempting to modify the excellent rutt etra example here https://airtightinteractive.com/demos/js/ruttetra/ to work for video (still using threejs) and am encountering strange issues with performance.
My code currently works as expected, and actually runs quite smoothly on chrome on my macbook pro, but seems to cause some sort of slow memory leak which i assume is to do with all the heavy lifting which is having to be done by getImageData. Strangely enough its only noticeable once i attempt to refresh the tab, so looks like it may be related to the garbage collection in chrome maybe? anyway to shunt the grunt work onto the GPU instead of killing the CPU?
I just wondered if i am missing anything obvious in terms of code optimisation or if the performance issues i am facing are to be expected given the nature of what i am trying to do.
I am only interested in WebGL / chrome functionality so dont really need to worry about browser compatibility of any kind.
<script>
var container, camera, scene, renderer, controls;
// PI
var PI = Math.PI;
var TWO_PI = PI*2;
// size
SCREEN_WIDTH = window.innerWidth;
SCREEN_HEIGHT = window.innerHeight;
SCREEN_PIXEL_RATIO = window.devicePixelRatio;
// camera
var VIEW_ANGLE = 45;
var ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT;
var NEAR = 0.1;
var FAR = 20000000;
// video raster
var video;
var videoImage;
var videoImageContext;
var _imageHeight;
var _imageWidth;
// lines
var _lineGroup;
// gui
var _guiOptions = {
stageSize: 1,
scale: 1.0,
scanStep: 5,
lineThickness: 10.0,
opacity: 1.0,
depth: 50,
autoRotate: false
};
// triggered from audio.php getMediaStream
function runme()
{
console.log('runme running');
init();
animate();
}
runme();
function init()
{
container = document.createElement('div');
document.body.appendChild(container);
//----------
// scene
//----------
scene = new THREE.Scene();
//----------
// camera
//----------
camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
//camera.position.set(0,0,450);
camera.position.set(0,150,300);
//----------
// objects
//----------
// create the video element
video = document.createElement('video');
// video.id = 'video';
// video.type = ' video/ogg; codecs="theora, vorbis" ';
video.src = 'data/sintel.ogv';
//video.src = 'data/az.mp4';
video.load(); // must call after setting/changing source
video.play();
videoImage = document.createElement('canvas');
//videoImage.width = 480;
//videoImage.height = 204;
videoImageContext = videoImage.getContext('2d');
_imageWidth = videoImage.width;
_imageHeight = videoImage.height;
//videoImageContext.fillStyle = '#ffffff';
//videoImageContext.fillRect(0, 0, videoImage.width, videoImage.height);
//----------
// controls
//----------
controls = new THREE.OrbitControls(camera);
//----------
// events
//----------
window.addEventListener('resize', onWindowResize, false);
//----------
// render
//----------
var args = {
//antialias: true // too slow
}
renderer = new THREE.WebGLRenderer(args);
renderer.setClearColor(0x000000, 1);
renderer.setPixelRatio(SCREEN_PIXEL_RATIO); //Set pixel aspect ratio
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
// attach to dom
container.appendChild(renderer.domElement);
//render();
}
function render()
{
if(video.readyState === video.HAVE_ENOUGH_DATA && !video.paused && !video.ended) // and video.currentTime > 0
{
//_imageWidth = videoImage.width;
//_imageHeight = videoImage.height;
videoImageContext.drawImage(video,0,0,_imageWidth,_imageHeight);
// Grab the pixel data from the backing canvas
var _data = videoImageContext.getImageData(0,0,videoImage.width,videoImage.height).data;
//log(data);
//_pixels = data;
var x = 0, y = 0;
if(_lineGroup)
{
scene.remove(_lineGroup);
//_lineGroup = null;
}
_lineGroup = new THREE.Object3D();
var _material = new THREE.LineBasicMaterial({
color: 0xffffff,
linewidth: _guiOptions.lineThickness
});
// loop through the image pixels
for(y = 0; y < _imageHeight; y+= _guiOptions.scanStep)
{
var _geometry = new THREE.Geometry();
for(x=0; x<_imageWidth; x+=_guiOptions.scanStep)
{
var color = new THREE.Color(getColor(x, y, _data));
var brightness = getBrightness(color);
var posn = new THREE.Vector3(x -_imageWidth/2,y - _imageHeight/2, -brightness * _guiOptions.depth + _guiOptions.depth/2);
//_geometry.vertices.push(new THREE.Vertex(posn));
_geometry.vertices.push(posn);
_geometry.colors.push(color);
_color = null;
_brightness = null;
_posn = null;
}
// add a line
var _line = new THREE.Line(_geometry, _material);
//log(line);
_lineGroup.add(_line);
// gc
_geometry = null;
}
scene.add(_lineGroup);
_data = null;
_line = null;
}
renderer.render(scene,camera);
}
function animate(){
requestAnimationFrame(animate);
stats.update();
render();
}
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
}
// Returns a hexadecimal color for a given pixel in the pixel array.
function getColor(x, y, _pixels)
{
var base = (Math.floor(y) * _imageWidth + Math.floor(x)) * 4;
var c = {
r: _pixels[base + 0],
g: _pixels[base + 1],
b: _pixels[base + 2],
a: _pixels[base + 3]
};
return (c.r << 16) + (c.g << 8) + c.b;
}
// return pixel brightness between 0 and 1 based on human perceptual bias
function getBrightness(c)
{
return ( 0.34 * c.r + 0.5 * c.g + 0.16 * c.b );
}
</script>
any help anyone could provide would be much appreciated, even if its just pointing me in the right direction as i am only just beginning to experiment with this stuff and have almost given myself an aneurysm trying to wrap my tiny mind around it.
The slow memory leak is most likely due to:
// add a line
var _line = new THREE.Line(_geometry, _material);
//log(line);
_lineGroup.add(_line);
THREE.Line is an object, containing other objects and lots of data. Every time you instantiate it, it creates .matrix, .matrixWorld, .modelViewMatrix, .normalMatrix which are all arrays with a bunch of numbers. .position,.quaternion, .scale, .rotation and probably .up are vectors,quats etc. and are slightly smaller but also arrays with special constructors.
Allocating all this every 16 miliseconds only to be released the next frame is probably the cause of your "leak".
You should create a pool of THREE.Line objects, and draw that every frame instead. The number of drawn objects you can control with .visible and mutate their transformation properties.
#pailhead I took your advice about pre-rendering the lines and lineGroup in advance and then updating the vertices on each animation frame instead and now its purring like a kitten. Also needed to insert the following line to make sure updated coords are picked up;
e.geometry.verticesNeedUpdate = true;
I cant figure out how to get a hosted video to work on codepen (cross-origin policy violation issues) but i have put a version up anyway to show the working code.
https://codepen.io/bw1984/pen/pezOXm
I will try to get a self-hosted (working) version up as soon as i can
I've been trying in vain to get colour working, but that will have to be an exercise for another day.
Finally, i need a normal shadow. But using Spot / Directional lights with Lambert / Phong materials i get no proper result:
picture with examples
When i use Spot Light with Lambert Material, this material don't react to light (pic. 1, 2).
When i use Spot Light with Phong Material, i get shadow, like pattern, not smooth (pic. 3, 4).
When i use Directional Light with Lambert / Phong material, i get smooth, but not proper shadow (pic. 5 - 8).
I use this preferences for shadows:
renderer.shadowMap.enabled = true;
renderer.shadowMapSoft = true;
renderer.shadowCameraNear = 3;
renderer.shadowCameraFar = camera.far;
renderer.shadowCameraFov = 50;
renderer.shadowMapBias = 0.0039;
renderer.shadowMapDarkness = 0.5;
renderer.shadowMapWidth = 1024;
renderer.shadowMapHeight = 1024;
And this for lights:
var ambientLight =new THREE.AmbientLight( 0x555555 );
scene.add(ambientLight);
and
var spotLight = new THREE.SpotLight( 0xffffff);
spotLight.position.set( 12, 22, -25 );
spotLight.castShadow = true;
scene.add(spotLight );
and
var directionalLight=new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set( 12, 22, -25 );
directionalLight.castShadow = true;
scene.add(directionalLight);
Also, i use the same castShadow and receiveShadow propertyes for all of this examples.
If it needing, other code can be watched as sourcecode of this page:
Spot Light, Lambert Material
This code the same for all of my examples, excluding light - material combinations.
Realtime shadows in Three.js are tricky in general. Here are some basics to follow to improve your example.
Limit the shadow.camera-frustum:
spotLight.shadow.camera.near = 25;
spotLight.shadow.camera.far = 50;
spotLight.shadow.camera.fov = 30;
Increase the shadow.mapSize:
spotLight.shadow.mapSize.width = 2048;
spotLight.shadow.mapSize.height = 2048;
Use shadowBias to reduce artefacts:
spotLight.shadowBias = -0.003;
The result isnt perfect because now light seams inside the room are showing up. It requires more tweaking and trade-ofs, but maybe its good enough for your needs:
https://jsfiddle.net/wbrj8uak/8/
Just leaving a comment here, regarding 2phaยดs updated example and why im restoring it:
setting the camera position results in a disappearing shadow inside the room. This is sure confusing for the poster who wants to have a shadow inside, thats why i just left his code the way he supplied it.
I have the following problem. When I use Three.js point light like this:
var color = 0xffffff;
var intensity = 0.5;
var distance = 200;
position_x = 0;
position_y = 0;
position_z = 0;
light = new THREE.PointLight(color, intensity, distance);
light.position.set(position_x, position_y, position_z);
scene.add(light);
It works as expected when there is a "small" object (mesh) positioned close to the light on the scene. However, when there is a large object (let us say a floor):
var floorTexture = new THREE.ImageUtils.loadTexture( 'floor.jpg' );
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set( 1, 1);
var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } );
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = -0.5;
floor.rotation.x = Math.PI / 2;
scene.add(floor);
Then the light will not be shown on it. At first I thought it is due to the fact that the floor center is positioned further away from the point light so the point light cannot reach it with the distance set to 200 (even though part of the floor is closer than the mentioned distance). Therefore I have tryied to increase this distance - no luck.
There is a workaround to create a floor out of small parts. Then the point light again works as expected but there is a problem with this approach - namely it drastically decreases FPS due to the large number of "floor objects" to be rendered.
My guess is that I am missing something. I know that there are other types of light which cover the whole scene but I am trying to create a lamp, so I think I need to use a point light. But I might be wrong. Any help or hint how to make this work would be appreciated.
MeshBasicMaterial does not support lights. Use MeshPhongMaterial.
MeshLambertMaterial also supports lights, but it is not advisable in your case for reasons explained here: Three.js: What Is The Exact Difference Between Lambert and Phong?.
three.js r.66
I'm quite new in html5 and three.js. I've been experimenting a bit with it, and basically what I want done is to have a Mesh (I'm using planeGeometry, as the tutorial I followed used it). The Mesh shows different Textures, which can change later on.
Here's what my code looks like:
angelTexture = THREE.ImageUtils.loadTexture("images/textures/chars/angel/angel.png");
angelTexture.offset.x = -0.75;
angelTexture.offset.y = -0.75;
angelMesh = new THREE.Mesh( new THREE.PlaneGeometry(79, 53, 79, 53), new THREE.MeshBasicMaterial( { map: angelTexture, wireframe: false } ));
angelMesh.position.x = 0;
angelMesh.position.y = 0;
scene.add(angelMesh);
The problem is that whenever I offset, the Mesh seems big enough to show all the other Sprites (I'm using the texture as a 2D Sprite that I offset to animate it). The result is quite disastrous and I am still figuring out how to control how big the Mesh is so that it shows only one snapshot of the Sprite. All my attempts seem only to resize the Mesh as well as the underlying Texture and still shows all the Sprites.
Can someone point me in the right direction? Thanks in advance.
...
My friend came up with a solution...
I missed the repeat property.
angelTexture = THREE.ImageUtils.loadTexture("images/textures/chars/angel/angel.png");
angelTexture.offset.x = -0.75;
angelTexture.offset.y = -0.75;
angelTexture.repeat.x = 0.25;
angelTexture.repeat.y = 0.25;
scene.add(angelMesh);
Hope this helps others having the same problem.
I had the same question a while ago, and so I have written up a complete example of animating using a spritesheet as the texture for a PlaneGeometry, and then updating the texture at regular intervals -- check out the example at
http://stemkoski.github.io/Three.js/Texture-Animation.html
and view the commented source code for additional explanation.
Update (2021):
Here is an updated version of the function I recommend using. It fixes the issue with the incorrect tile display order, it automatically updates the next frame, and it returns an object you can use to stop and re-start the animation as desired.
function TextureAnimator(texture, tilesHoriz, tilesVert, tileDispDuration)
{
let obj = {};
obj.texture = texture;
obj.tilesHorizontal = tilesHoriz;
obj.tilesVertical = tilesVert;
obj.tileDisplayDuration = tileDispDuration;
obj.numberOfTiles = tilesHoriz * tilesVert;
obj.texture.wrapS = THREE.RepeatWrapping;
obj.texture.wrapT = THREE.RepeatWrapping;
obj.texture.repeat.set( 1/tilesHoriz, 1/tilesVert );
obj.currentTile = 0;
obj.nextFrame = function()
{
obj.currentTile++;
if (obj.currentTile == obj.numberOfTiles)
obj.currentTile = 0;
let currentColumn = obj.currentTile % obj.tilesHorizontal;
obj.texture.offset.x = currentColumn / obj.tilesHorizontal;
let currentRow = Math.floor( obj.currentTile / obj.tilesHorizontal );
obj.texture.offset.y = obj.tilesVertical - currentRow / obj.tilesVertical;
}
obj.start = function()
{ obj.intervalID = setInterval(obj.nextFrame, obj.tileDisplayDuration); }
obj.stop = function()
{ clearInterval(obj.intervalID); }
obj.start();
return obj;
}
I've noted in my comment to Lee Stemkoski that spritesheets that have more than one row do not work the same when using the newer THREE.TextureLoader().
I am using the following 4x4 sprite image in my tests.
With no modification to Lee Stemkoski's TextureAnimator function, assuming you have a full 16 tile spritesheet.
var texture = new THREE.TextureLoader().load('grid-sprite.jpg');
var annie = new TextureAnimator(texture, 4, 4, 16, 150);
The animated texture runs backwards.
Codepen Demo
So I made my own which I call ๐๐๐ THREE.SpriteSheetTexture ๐๐๐
THREE.SpriteSheetTexture = function(imageURL, framesX, framesY, frameDelay, _endFrame) {
var timer, frameWidth, frameHeight,
x = 0, y = 0, count = 0, startFrame = 0,
endFrame = _endFrame || framesX * framesY,
CORSProxy = 'https://cors-anywhere.herokuapp.com/',
canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
canvasTexture = new THREE.CanvasTexture(canvas),
img = new Image();
img.crossOrigin = "Anonymous"
img.onload = function(){
canvas.width = frameWidth = img.width / framesX;
canvas.height = frameHeight = img.height / framesY;
timer = setInterval(nextFrame, frameDelay);
}
img.src = CORSProxy + imageURL;
function nextFrame() {
count++;
if(count >= endFrame ) {
count = 0;
};
x = (count % framesX) * frameWidth;
y = ((count / framesX)|0) * frameHeight;
ctx.clearRect(0, 0, frameWidth, frameHeight);
ctx.drawImage(img, x, y, frameWidth, frameHeight, 0, 0, frameWidth, frameHeight);
canvasTexture.needsUpdate = true;
}
return canvasTexture;
}
And what you need to know about it
imageURL is the URL of your spritesheet
framesX is how many frames fit along the x axis (left and right)
framesY is how many frames fit along the y axis (up and down)
delay is how long it the texture waits to change to the next frame
_endFrame is optional - How many frames are there (in case it doesnt use a full row)
That all looks something like this
texture = new THREE.SpriteSheetTexture('https://s3-us-west-2.amazonaws.com/s.cdpn.io/68819/grid-sprite.jpg', 4, 4, 100, 16);
var material = new THREE.MeshBasicMaterial({
map: texture
});
geometry = new THREE.BoxGeometry( 200, 200, 200 );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
And there was much rejoicing!!!
Codepen Demo Here
#Cmndo to make frames flow moves in the right order you just need to update this:
texture.offset.y = currentRow / this.tilesVertical;
to this:
texture.offset.y = this.tilesVertical - (currentRow / this.tilesVertical);
In this example:
https://github.com/stemkoski/stemkoski.github.com/blob/master/Three.js/Texture-Animation.html
To make frames move in the right direction use:
texture.offset.y = (1 - currentRow / _tilesVertical) - (1 / _tilesVertical);
instead of
texture.offset.y = currentRow / this.tilesVertical;