Adding image in the script code "Bad TV Shader"? - image

I want to be able to add images in the script code "Bad TV Shader" (https://www.airtightinteractive.com/demos/js/badtvshader/). It was originally developed for video, but I want to implement an image that also is under these distortion and noise effects.
Who can help I would be very grateful! =)
<script>
//Bad TV Effect Demo
//Using Three.js r.66
//by Felix Turner / www.airtight.cc / #felixturner
var camera, scene, renderer;
var video, videoTexture,videoMaterial;
var composer;
var shaderTime = 0;
var badTVParams, badTVPass;
var staticParams, staticPass;
var rgbParams, rgbPass;
var filmParams, filmPass;
var renderPass, copyPass;
var gui;
var pnoise, globalParams;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(55, 1080/ 720, 20, 3000);
camera.position.z = 1000;
scene = new THREE.Scene();
//Load Video
video = document.createElement( 'video' );
video.loop = true;
video.src = "res/fits.mp4";
video.play();
//Use webcam
// video = document.createElement('video');
// video.width = 320;
// video.height = 240;
// video.autoplay = true;
// video.loop = true;
// //Webcam video
// window.URL = window.URL || window.webkitURL;
// navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
// //get webcam
// navigator.getUserMedia({
// video: true
// }, function(stream) {
// //on webcam enabled
// video.src = window.URL.createObjectURL(stream);
// }, function(error) {
// prompt.innerHTML = 'Unable to capture WebCam. Please reload the page.';
// });
//init video texture
videoTexture = new THREE.Texture( video );
videoTexture.minFilter = THREE.LinearFilter;
videoTexture.magFilter = THREE.LinearFilter;
videoMaterial = new THREE.MeshBasicMaterial( {
map: videoTexture
} );
//Add video plane
var planeGeometry = new THREE.PlaneGeometry( 1080, 720,1,1 );
var plane = new THREE.Mesh( planeGeometry, videoMaterial );
scene.add( plane );
plane.z = 0;
plane.scale.x = plane.scale.y = 1.45;
//add stats
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
//init renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( 800, 600 );
document.body.appendChild( renderer.domElement );
//POST PROCESSING
//Create Shader Passes
renderPass = new THREE.RenderPass( scene, camera );
badTVPass = new THREE.ShaderPass( THREE.BadTVShader );
rgbPass = new THREE.ShaderPass( THREE.RGBShiftShader );
filmPass = new THREE.ShaderPass( THREE.FilmShader );
staticPass = new THREE.ShaderPass( THREE.StaticShader );
copyPass = new THREE.ShaderPass( THREE.CopyShader );
//set shader uniforms
filmPass.uniforms[ "grayscale" ].value = 0;
//Init DAT GUI control panel
badTVParams = {
mute:true,
show: true,
distortion: 3.0,
distortion2: 1.0,
speed: 0.3,
rollSpeed: 0.1
}
staticParams = {
show: true,
amount:0.5,
size2:4.0
}
rgbParams = {
show: true,
amount: 0.005,
angle: 0.0,
}
filmParams = {
show: true,
count: 800,
sIntensity: 0.9,
nIntensity: 0.4
}
gui = new dat.GUI();
gui.add(badTVParams, 'mute').onChange(onToggleMute);
var f1 = gui.addFolder('Bad TV');
f1.add(badTVParams, 'show').onChange(onToggleShaders);
f1.add(badTVParams, 'distortion', 0.1, 20).step(0.1).listen().name("Thick Distort").onChange(onParamsChange);
f1.add(badTVParams, 'distortion2', 0.1, 20).step(0.1).listen().name("Fine Distort").onChange(onParamsChange);
f1.add(badTVParams, 'speed', 0.0,1.0).step(0.01).listen().name("Distort Speed").onChange(onParamsChange);
f1.add(badTVParams, 'rollSpeed', 0.0,1.0).step(0.01).listen().name("Roll Speed").onChange(onParamsChange);
f1.open();
var f2 = gui.addFolder('RGB Shift');
f2.add(rgbParams, 'show').onChange(onToggleShaders);
f2.add(rgbParams, 'amount', 0.0, 0.1).listen().onChange(onParamsChange);
f2.add(rgbParams, 'angle', 0.0, 2.0).listen().onChange(onParamsChange);
f2.open();
var f4 = gui.addFolder('Static');
f4.add(staticParams, 'show').onChange(onToggleShaders);
f4.add(staticParams, 'amount', 0.0,1.0).step(0.01).listen().onChange(onParamsChange);
f4.add(staticParams, 'size2', 1.0,100.0).step(1.0).onChange(onParamsChange);
f4.open();
var f3 = gui.addFolder('Scanlines');
f3.add(filmParams, 'show').onChange(onToggleShaders);
f3.add(filmParams, 'count', 50, 1000).onChange(onParamsChange);
f3.add(filmParams, 'sIntensity', 0.0, 2.0).step(0.1).onChange(onParamsChange);
f3.add(filmParams, 'nIntensity', 0.0, 2.0).step(0.1).onChange(onParamsChange);
f3.open();
gui.close();
onToggleShaders();
onToggleMute();
onParamsChange();
window.addEventListener('resize', onResize, false);
renderer.domElement.addEventListener('click', randomizeParams, false);
onResize();
randomizeParams();
}
function onParamsChange() {
//copy gui params into shader uniforms
badTVPass.uniforms[ "distortion" ].value = badTVParams.distortion;
badTVPass.uniforms[ "distortion2" ].value = badTVParams.distortion2;
badTVPass.uniforms[ "speed" ].value = badTVParams.speed;
badTVPass.uniforms[ "rollSpeed" ].value = badTVParams.rollSpeed;
staticPass.uniforms[ "amount" ].value = staticParams.amount;
staticPass.uniforms[ "size" ].value = staticParams.size2;
rgbPass.uniforms[ "angle" ].value = rgbParams.angle*Math.PI;
rgbPass.uniforms[ "amount" ].value = rgbParams.amount;
filmPass.uniforms[ "sCount" ].value = filmParams.count;
filmPass.uniforms[ "sIntensity" ].value = filmParams.sIntensity;
filmPass.uniforms[ "nIntensity" ].value = filmParams.nIntensity;
}
function randomizeParams() {
if (Math.random() <0.2){
//you fixed it!
badTVParams.distortion = 0.1;
badTVParams.distortion2 =0.1;
badTVParams.speed =0;
badTVParams.rollSpeed =0;
rgbParams.angle = 0;
rgbParams.amount = 0;
staticParams.amount = 0;
}else{
badTVParams.distortion = Math.random()*10+0.1;
badTVParams.distortion2 =Math.random()*10+0.1;
badTVParams.speed =Math.random()*.4;
badTVParams.rollSpeed =Math.random()*.2;
rgbParams.angle = Math.random()*2;
rgbParams.amount = Math.random()*0.03;
staticParams.amount = Math.random()*0.2;
}
onParamsChange();
}
function onToggleMute(){
video.volume = badTVParams.mute ? 0 : 1;
}
function onToggleShaders(){
//Add Shader Passes to Composer
//order is important
composer = new THREE.EffectComposer( renderer);
composer.addPass( renderPass );
if (filmParams.show){
composer.addPass( filmPass );
}
if (badTVParams.show){
composer.addPass( badTVPass );
}
if (rgbParams.show){
composer.addPass( rgbPass );
}
if (staticParams.show){
composer.addPass( staticPass );
}
composer.addPass( copyPass );
copyPass.renderToScreen = true;
}
function animate() {
shaderTime += 0.1;
badTVPass.uniforms[ 'time' ].value = shaderTime;
filmPass.uniforms[ 'time' ].value = shaderTime;
staticPass.uniforms[ 'time' ].value = shaderTime;
if ( video.readyState === video.HAVE_ENOUGH_DATA ) {
if ( videoTexture ) videoTexture.needsUpdate = true;
}
requestAnimationFrame( animate );
composer.render( 0.1);
stats.update();
}
function onResize() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
</script>

Using video or image is the same process, you can use Planegeometry and TextureLoader to place an image instead of a video like this :
YourGroup = new THREE.Group();
var YourImage = new THREE.TextureLoader();
YourImage.load( 'folder/to_image.png', function ( texture ) {
var geometry = new THREE.PlaneGeometry( width, height );
var material = new THREE.MeshBasicMaterial({
map: texture,
transparent: true,
});
var mesh = new THREE.Mesh( geometry, material );
YourGroup.add( mesh );
});
scene.add( YourGroup );
Note:
Here i created a group with everything to put inside (a planegeometry with BasicMaterial to apply my loaded image to Plane, and create a mesh from these two.
I put a Png instead of jpeg because of transparency for Mesh.
I add my group to scene.

Related

Three.JS VRAM memory leak when adding removing THREE.Geometry to scene

I have encountered a VRAM memory leak in my app.
The app adds and removes THREE.Geometry very often to create a volumetric animation.
If instead of a THREE.Geometry with it's own populated vertices, I used instead THREE.SphereBufferGeometry, the memory leak doesn't happen.
I have created a minimal app to prove this memory leak is real.
The memory leak increase VRAM memory very slowly, but it does fill up in the end.
I think that pools won't help, since it's VRAM and not managed memory.
I do use dispose.
If you can make this sample work and not have memory leak, that might solve my issue:
https://jsfiddle.net/4a7ksryd/16/
Edit: I am adding here the code of the app:
var camera, scene, renderer;
var geometry, material, mesh;
var lastSphere;
var lastGeo;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 1;
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
var light = new THREE.DirectionalLight( 0xffffff, 1, 100 );
light.position.set( 0, 4, 0 ); //default; light shining from top
light.castShadow = true; // default false
//Set up shadow properties for the light
light.shadow.mapSize.width = 1024; // default
light.shadow.mapSize.height = 1024; // default
light.shadow.camera.near = 1; // default
light.shadow.camera.far = 20; // default
scene.add( light );
//Create a sphere that cast shadows (but does not receive them)
geometry = new THREE.SphereBufferGeometry( 0.1, 32, 32 );
material = new THREE.MeshStandardMaterial( { color: 0xff0000 } );
// geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
// material = new THREE.MeshNormalMaterial();
mesh = new THREE.Mesh( geometry, material );
mesh.position.y = 0.1;
mesh.castShadows = true;
mesh.receiveShadow = false;
scene.add( mesh );
var planeGeometry = new THREE.PlaneBufferGeometry( 15, 15, 1, 1 );
var planeMaterial = new THREE.MeshStandardMaterial( { color: 0xffffff, emissive:0x111111 } )
var plane = new THREE.Mesh( planeGeometry, planeMaterial );
plane.position.y = -0.2;
plane.rotation.x = -Math.PI / 2;
plane.receiveShadow = true;
scene.add( plane );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
var dim = 32;
var geo1 = new THREE.Geometry();
const numVertices = dim*dim;
var vertices = new Array(numVertices);
for (var i=0; i<vertices.length; i++)
{
const x = i%dim;
const y = (Math.floor(i/dim))%dim;
vertices[i] = new THREE.Vector3(x*0.1, y*0.1, 0);
}
const numFaces = (dim-1)*(dim-1)*2;
var faces = new Array(numFaces);
for (var i=0; i<(faces.length/2); i++)
{
const x = i%(dim-1);
const y = Math.floor(i/(dim-1))%(dim-1);
faces[2*i] = new THREE.Face3(x+y*dim, x+1+y*dim, x+(y+1)*dim);
faces[2*i+1] = new THREE.Face3(x+1+y*dim, x+1+(y+1)*dim, x+(y+1)*dim);
}
var uv = new Array(numFaces);
for (var i=0; i<uv.length; i++)
uv[i] = [new THREE.Vector2(0, 0), new THREE.Vector2(0, 0), new THREE.Vector2(0, 0)];
geo1.faces = faces;
geo1.vertices = vertices;
geo1.faceVertexUvs[0] = uv;
geo1.uvsNeedUpdate = true;
geo1.verticesNeedUpdate = true;
geo1.elementsNeedUpdate = true;
// var sphereGeometry = new THREE.SphereBufferGeometry( 0.1, 256, 256 );
var sphereGeometry = geo1;
var sphereMaterial = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var sphere = new THREE.Mesh( sphereGeometry, sphereMaterial );
sphere.position.y = 0.1+Math.sin(mesh.rotation.x)*0.1;
sphere.position.x = 0.5;
sphere.castShadow = true; //default is false
sphere.receiveShadow = false; //default
if (lastGeo!=null)
lastGeo.dispose();
if (lastSphere!=null)
scene.remove(lastSphere);
scene.add( sphere );
lastSphere = sphere;
lastGeo = sphereGeometry;
// geo1.dispose();
renderer.render( scene, camera );
}
This is actually a bug in three.js. I've filed a PR to fix the issue:
https://github.com/mrdoob/three.js/pull/20479

Three js enabling shadow render slow

I am loading a building model to the scene using GLTFLoader and apply some texture, also Adding two PointLight source with shadow enabled. I am using self shadow for the building, that is the building itself should create shadow from light source.
But when I load the page, I am having some performance issue withe page, the frame rate is too slow on status and entire system behave hang.
But if disable the shadow everything work as expected. Is this expected or I can improve it on coding.
Here is the working fiddle
http://jsfiddle.net/n9eg3kox/
var camera, scene, renderer, stats;
var mesh;
var controls;
var BuildingObj;
var OutFloor;
var enableShadow = true; // if I make it false the code work fine
var pointLight2, pointLight3;
function init() {
var webglEl = document.getElementById('webgl');
if (!Detector.webgl) {
Detector.addGetWebGLMessage(webglEl);
alert("WebGL no Support");
return;
}
THREE.ImageUtils.crossOrigin = '';
renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setPixelRatio(window.devicePixelRatio * 1.5);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.physicallyCorrectLights = true;
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.shadowMap.enabled = enableShadow;
renderer.toneMapping = THREE.ReinhardToneMapping;
webglEl.appendChild(renderer.domElement);
renderer.setClearColor(0x555555, 1);
var width = window.innerWidth, height = window.innerHeight;
camera = new THREE.PerspectiveCamera(45, width / height, 0.01, 2000);
camera.position.x = 0;
camera.position.y = 4;
camera.position.z = 30;
scene = new THREE.Scene();
var axesHelper = new THREE.AxesHelper(100);
scene.add(axesHelper);
var intensity = 5;
var distance = 40;
var decay = 1.0;
pointLight2 = new THREE.PointLight(0xFFFFFF, intensity);
pointLight2.add(new THREE.Mesh(new THREE.SphereBufferGeometry(3, 16, 16), new THREE.MeshPhongMaterial({ color: 0xfffdfb, emissive: 0xfffdfb, emissiveIntensity: 100 })));
pointLight2.position.set(-60, 80, 40);
pointLight2.castShadow = enableShadow;
pointLight2.visible = true;
pointLight2.shadow.mapSize.width = 1024;
pointLight2.shadow.mapSize.height = 1024;
scene.add(pointLight2);
pointLight3 = new THREE.PointLight(0xFFFFFF, intensity);
pointLight3.add(new THREE.Mesh(new THREE.SphereBufferGeometry(3, 16, 16), new THREE.MeshPhongMaterial({ color: 0xfffdfb, emissive: 0xfffdfb, emissiveIntensity: 100 })));
pointLight3.position.set(60, 80, 40);
pointLight3.castShadow = enableShadow;
pointLight3.shadow.mapSize.width = 1024;
pointLight3.shadow.mapSize.height = 1024;
pointLight3.visible = true;
scene.add(pointLight3);
//var light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 21 );
//scene.add( light );
controls = new THREE.OrbitControls(camera, webglEl);
stats = new Stats();
webglEl.appendChild(stats.dom);
loadObject();
animate();
}
function animate() {
controls.update();
stats.update();
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function loadObject() {
var loader = new THREE.GLTFLoader();
loader.load(
//'./Model/GLTF/test.glb',
'./test/test.glb',
function (gltf) {
gltf.scene.traverse(function (node) {
if (node.isGroup) {
if (node.name === "Building") {
BuildingObj = node;
} else if (node.name === "Cube") {
OutFloor = node;
}
}
});
scene.add(OutFloor);
scene.add(BuildingObj);
applyMaterialToObject();
},
function (xhr) {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
},
function (error) {
console.log('An error happened---' + error);
}
);
}
function applyMaterialToObject(object) {
for (var i = 0; i < BuildingObj.children.length; i++) {
var obj = BuildingObj.children[i];
var material = new THREE.MeshStandardMaterial({ roughness: 0.8, metalness: 0.3, bumpScale: - 0.05, color: 0xffffff, });
loadTexturesToMaterial(BuildingObj.children[i], material, "./test/brick.jpg", "./test/brick_b.jpg", "./test/brick_r.jpg", 25, 70, Math.PI / 2);
}
for (var i = 0; i < OutFloor.children.length; i++) {
var obj = OutFloor.children[i];
var material = new THREE.MeshStandardMaterial({ roughness: 0.5, metalness: 0.8, bumpScale: - 0.05, color: 0xffffff });
loadTexturesToMaterial(obj, material, "./test/tile2.jpg", "./test/tile2_b.jpg", "./test/tile2_r.jpg", 35, 100, Math.PI / 2);
}
}
function loadTexturesToMaterial(obj, material, map_img, bumpMap_img, roughnessMap_img, v_count, h_count, rotation) {
obj.receiveShadow = enableShadow;
obj.castShadow = enableShadow;
obj.material = material;
obj.material.side = THREE.DoubleSide;
var textureLoader = new THREE.TextureLoader();
textureLoader.load(map_img, function (map) {
map.wrapS = THREE.RepeatWrapping;
map.wrapT = THREE.RepeatWrapping;
map.rotation = rotation;
map.repeat.set(v_count, h_count);
obj.material.map = map;
obj.material.needsUpdate = true;
});
textureLoader.load(bumpMap_img, function (map) {
map.wrapS = THREE.RepeatWrapping;
map.wrapT = THREE.RepeatWrapping;
map.rotation = rotation;
map.repeat.set(v_count, h_count);
obj.material.bumpMap = map;
obj.material.needsUpdate = true;
});
textureLoader.load(roughnessMap_img, function (map) {
map.wrapS = THREE.RepeatWrapping;
map.wrapT = THREE.RepeatWrapping;
map.rotation = rotation;
map.repeat.set(v_count, h_count);
obj.material.roughnessMap = map;
obj.material.needsUpdate = true;
});
}
Note: I have created the model using blender.
Edit: Texture and model link
https://github.com/SourceCodeZone/3D

Three.js : remove texture on top/bottom of CylinderGeometry

I'm using Three.js to make basic 3D cylinder rendering. I'm using TextureLoader to load texture async (based on UI interactions).
All is ok, but I would like those textures not to be applied on the cylinder top / bottom.
How can I achieve that?
Here's what I've done so far:
function threeJsRenderer() {
var width = 325;
var height = 375;
var scene = new THREE.Scene();
var camera = new THREE.OrthographicCamera(width / - 2, width / 2, height / 2, height / - 2, -200, 1000);
var renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setClearColor( 0x000000, 0 );
renderer.setSize(width,height);
document.getElementById('projection').appendChild(renderer.domElement);
// CylinderGeometry(radiusTop : Float, radiusBottom : Float, height : Float, radialSegments : Integer, heightSegments : Integer, openEnded : Boolean, thetaStart : Float, thetaLength : Float)
var geometry = new THREE.CylinderGeometry(135,128,110,64,1, false, 0, Math.PI-2);
var loader = new THREE.TextureLoader();
var material = new THREE.MeshPhongMaterial();
var cone = new THREE.Mesh();
var pointLight = new THREE.AmbientLight( 0xFFFFFF );
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;
scene.add(pointLight);
camera.position.z = 40;
camera.position.y = 0;
cone.rotation.x = 0.01;
cone.rotation.y = -10;
jQuery(document).on('new3DConfigReady', function () {
scene.remove(cone);
var newGeometry = new THREE.CylinderGeometry(state.cylinderGeometry.radiusTop,state.cylinderGeometry.radiusBottom,state.cylinderGeometry.height,64,1, false, 0, Math.PI-2);;
cone = new THREE.Mesh(newGeometry, material);
cone.rotation.x = 0.01;
cone.rotation.y = -0.55;
cone.position.y = state.cylinderGeometry.positionY;
geometry.dispose();
if(state.textureUrl !== ''){
scene.add(cone);
}
});
jQuery(document).on('newTextureReady', function () {
loader.load( state.textureUrl, function (texture){
material.map = texture;
material.map.anisotropy = 256;
material.map.needsUpdate = true;
material.needsUpdate = true;
scene.add(cone);
});
});
var render = function () {
requestAnimationFrame(render);
renderer.render(scene, camera);
};
render();
}
Using a materials array you can have different materials on the sides and ends of your cylinder.
var geometry = new THREE.CylinderBufferGeometry( 5, 5, 10, 16, 1 );
var materials = [
new THREE.MeshPhongMaterial( { map: texture } ),
new THREE.MeshPhongMaterial( { color: 0x0000ff } ),
new THREE.MeshPhongMaterial( { color: 0xff0000 } )
];
var mesh = new THREE.Mesh( geometry, materials );
three.js r.100

Video transition in Three.js

I want to play multiple videos in Three.js environment. I have finished loading video as texture and play it below and stuck at how to implement to load multiple video textures and play. Also adding some transition into it :(. Hope anyone can help me , give me some suggestions or right direction to do it. I'm fresh to webGL and Three.js.
// MAIN
// standard global variables
var container, scene, camera, renderer, controls, stats;
// custom global variables
var video, videoImage, videoImageContext, videoTexture;
var mouseX = 0;
var mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight;
init();
animate();
// FUNCTIONS
function init() {
// SCENE
scene = new THREE.Scene();
// CAMERA
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
camera.position.set(0,200,500);
camera.lookAt(scene.position);
// RENDERER
if ( Detector.webgl )
renderer = new THREE.WebGLRenderer( {antialias:true} );
else
renderer = new THREE.CanvasRenderer();
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
renderer.setClearColor (0xFFFFFF, 1);
container = document.getElementById( 'ThreeJS' );
container.appendChild( renderer.domElement );
// CONTROLS
// controls = new THREE.OrbitControls( camera, renderer.domElement );
// EVENTS
THREEx.WindowResize(renderer, camera);
// LIGHT
// var light = new THREE.PointLight(0xffffff);
// light.position.set(0,250,0);
// scene.add(light);
// FLOOR
var floorTexture = new THREE.ImageUtils.loadTexture( 'logo.jpg' );
var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } );
var floorGeometry = new THREE.PlaneGeometry(500, 500, 0, 0);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
// floor.wrapS = THREE.RepeatWrapping;
// floor.position.y = -0.5;
// floor.rotation.x = - (Math.PI / 2);
floor.position.y = -100;
floor.rotation.x = - (Math.PI / 2);
scene.add(floor);
///////////
// VIDEO //
///////////
// create the video element
video = document.createElement( 'video' );
// video.id = 'video';
// video.type = ' video/ogg; codecs="theora, vorbis" ';
video.src = "video3.mp4";
video.load(); // must call after setting/changing source
video.play();
// alternative method --
// create DIV in HTML:
// <video id="myVideo" autoplay style="display:none">
// <source src="videos/sintel.ogv" type='video/ogg; codecs="theora, vorbis"'>
// </video>
// and set JS variable:
// video = document.getElementById( 'myVideo' );
videoImage = document.createElement( 'canvas' );
videoImage.width = 1280;
videoImage.height = 546;
videoImageContext = videoImage.getContext( '2d' );
// background color if no video present
videoImageContext.fillStyle = '#000000';
videoImageContext.fillRect( 0, 0, videoImage.width, videoImage.height );
videoTexture = new THREE.Texture( videoImage );
videoTexture.minFilter = THREE.LinearFilter;
videoTexture.magFilter = THREE.LinearFilter;
var movieMaterial = new THREE.MeshBasicMaterial( { map: videoTexture, overdraw: true, side:THREE.DoubleSide } );
// the geometry on which the movie will be displayed;
// movie image will be scaled to fit these dimensions.
var movieGeometry = new THREE.PlaneGeometry( 600, 300, 4, 4 );
var movieScreen = new THREE.Mesh( movieGeometry, movieMaterial );
movieScreen.position.set(0,50,-200);
scene.add(movieScreen);
camera.position.set(0,200,450);
var vector = new THREE.Vector3(0,200,450);
camera.lookAt(movieScreen.position);
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
}
function onDocumentMouseMove(event) {
mouseX = ( event.clientX - windowHalfX );
mouseY = ( event.clientY - windowHalfY ) * 0.2;
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
camera.position.x += ( mouseX - camera.position.x ) * 0.05;
camera.position.y += ( - mouseY - camera.position.y ) * 0.05;
camera.lookAt(scene.position);
if ( video.readyState === video.HAVE_ENOUGH_DATA )
{
videoImageContext.drawImage( video, 0, 0 );
if ( videoTexture )
videoTexture.needsUpdate = true;
}
renderer.render( scene, camera );
}

Three.js Restrict the mouse movement to Scene only

I am working on the cube example from three.js (webgl_interactive_cubes_gpu.html). I realized that events goes to the entire html page. I mean i can rotate, zoom in or zoom out, even if the mouse pointer is not inside the scene..
I google a little bit and found some answers (Allow mouse control of three.js scene only when mouse is over canvas) but they do not work for me..Below is my code...
var container, stats;
var camera, controls, scene, renderer;
var pickingData = [], pickingTexture, pickingScene;
var objects = [];
var highlightBox;
var mouse = new THREE.Vector2();
var offset = new THREE.Vector3( 10, 10, 10 );
init();
animate();
function init() {
container = document.getElementById( "container" );
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 1000;
//camera.translateZ( -500 );
controls = new THREE.TrackballControls(camera);
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 4;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
scene = new THREE.Scene();
pickingScene = new THREE.Scene();
pickingTexture = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight );
pickingTexture.minFilter = THREE.LinearFilter;
pickingTexture.generateMipmaps = false;
scene.add( new THREE.AmbientLight( 0x555555 ));
var light = new THREE.SpotLight( 0xffffff, 1.5 );
light.position.set( 0, 500, 2000 );
scene.add( light );
var geometry = new THREE.Geometry(),
pickingGeometry = new THREE.Geometry(),
pickingMaterial = new THREE.MeshBasicMaterial( { vertexColors: THREE.VertexColors } ),
defaultMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors} );
function applyVertexColors( g, c ) {
g.faces.forEach( function( f ) {
var n = ( f instanceof THREE.Face3 ) ? 3 : 4;
for( var j = 0; j < n; j ++ ) {
f.vertexColors[ j ] = c;
}
} );
}
var geom = new THREE.BoxGeometry(0.005, 0.005, 0.005 );
var color = new THREE.Color();
var matrix = new THREE.Matrix4();
var quaternion = new THREE.Quaternion();
var coord="219_163_189;130_173_179;161_113_231;
var splitCoord=coord.split(";");
var coordColr="0_255_255;255_255_0;0_0_255;0_255_0;255_255_0;
var splitCoordColor=coordColr.split(";");
for ( var i = 0; i < splitCoord.length; i++ ) {
var position = new THREE.Vector3();
var xyz=splitCoord[i].split("_");
var col=splitCoordColor[i].split("_");
position.x = xyz[0];
position.y = xyz[1];
position.z = xyz[2];
var rotation = new THREE.Euler();
rotation.x = 0
rotation.y = 0;
rotation.z = 0;
var scale = new THREE.Vector3();
scale.x = 200 + 100;
scale.y = 200 + 100;
scale.z = 200 + 100;
quaternion.setFromEuler(rotation, false );
matrix.compose( position, quaternion, scale);
col[0]=col[0]/255;
col[1]=col[1]/255;
col[2]=col[2]/255;
applyVertexColors(geom, color.setRGB(col[0], col[1], col[2]));
geometry.merge(geom, matrix);
// give the geom's vertices a color corresponding to the "id"
applyVertexColors( geom, color.setHex( i ) );
pickingGeometry.merge( geom, matrix );
pickingData[ i ] = {
position: position,
rotation: rotation,
scale: scale
};
}
var drawnObject = new THREE.Mesh( geometry, defaultMaterial );
scene.add(drawnObject);
pickingScene.add( new THREE.Mesh( pickingGeometry, pickingMaterial ) );
highlightBox = new THREE.Mesh(
new THREE.BoxGeometry( 0.01, 0.01, 0.01 ),
new THREE.MeshLambertMaterial( { color: 0xffff00 }
) );
scene.add( highlightBox );
renderer = new THREE.WebGLRenderer( );
//renderer.setClearColor( 0xffffff );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(800, 800);
renderer.sortObjects = false;
container.appendChild(renderer.domElement);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
//renderer.domElement.addEventListener('mousemove', onMouseMove );
}
function onMouseMove( e ) {
mouse.x = e.clientX;
mouse.y = e.clientY;
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function pick() {
//render the picking scene off-screen
renderer.render( pickingScene, camera, pickingTexture );
//create buffer for reading single pixel
var pixelBuffer = new Uint8Array( 4 );
//read the pixel under the mouse from the texture
renderer.readRenderTargetPixels(pickingTexture, mouse.x, pickingTexture.height - mouse.y, 1, 1, pixelBuffer);
//interpret the pixel as an ID
var id = ( pixelBuffer[0] << 16 ) | ( pixelBuffer[1] << 8 ) | ( pixelBuffer[2] );
var data = pickingData[ id ];
if (data) {
//move our highlightBox so that it surrounds the picked object
if ( data.position && data.rotation && data.scale ){
highlightBox.position.copy( data.position );
highlightBox.rotation.copy( data.rotation );
highlightBox.scale.copy( data.scale ).add( offset );
highlightBox.visible = true;
}
} else {
highlightBox.visible = false;
}
}
function render() {
controls.update();
pick();
renderer.render( scene, camera );
}
any help is greatly appreciated..
Thanks
You can pass in the canvas as an argument to the TrackballsControls constructor.
var controls = new THREE.TrackballControls(camera, renderer.domElement);
That should solve the problem.
EDIT: included a working example,
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, 400 / 300, 1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(400, 300);
document.body.appendChild(renderer.domElement);
var controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 4;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({
color: 0x00ff00
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
var render = function() {
requestAnimationFrame(render);
controls.update();
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
};
render();
could not get your code to run at all so..

Resources