Trying to implement a texture on a large scaled plane using RepeatWrapping. MeshBasicMaterial works well, but ShaderMaterial causes flickering. Here is the code snippet:
<!DOCTYPE html>
<html>
<head>
<title>MeshShaderMaterialExample</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0, shrink-to-fit=no">
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b7c3dfc5d2d2f787998f829987">[email protected]</a>/examples/js/controls/TrackballControls.js"></script>
<script src="js/TWEEN.js"></script>
<style type="text/css">
body {
width: 100%;
height: 100%;
background-color: #000;
color: #fff;
margin: 0px;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<script>
var camera, scene, renderer;
var container, mesh, geometry;
var controls, effect;
var tweenUpdate="false";
var tweenOver="true";
var textureData=
{
"texture_0":
{
"img":"gman.png"
},
"texture_1":
{
"img":"gman.png"
}}
var magicPosition = { magicTrans:0 };
var magicTarget = { magicTrans:1 };
var magicTween = new TWEEN.Tween(magicPosition).to(magicTarget, 1000);
magicTween.easing(TWEEN.Easing.Linear.None);
var currentTexture=0;
var nextTexture=0;
var uniforms = {
textures: {
value: []
},
repeat: {
type: 'f',
value: 100
},
transition: {
value: 0
},
currentUniform: {
value: 0
},
nextUniform: {
value: 0
}
};
var textureLoader = new THREE.TextureLoader();
var pics=[];
for (var i = 0; i < Object.keys(textureData).length; i++) {
var ass="texture_"+i;
pics[i]= textureData[ass].img;
console.log(pics[i]);
}
pics.forEach((p, idx)=>{
textureLoader.load(p, function(tex){
tex.needsUpdate = true;
uniforms.textures.value[idx] = tex;
uniforms.textures.value[idx].needsUpdate = true;
// console.log(tex);
uniforms.textures.value[idx].minFilter = THREE.LinearFilter;
})
});
var vertShader = `
varying vec2 vUv;
uniform float repeat;
void main()
{
vUv = repeat * uv;
vec4 mvPosition = modelViewMatrix * vec4(position, 1 );
gl_Position = projectionMatrix * mvPosition;
}
`;
var fragShader = `
uniform sampler2D textures[` + pics.length + `];
uniform float transition;
uniform float currentUniform;
uniform float nextUniform;
varying vec2 vUv;
vec4 getTexture(int index){
for(int i = 0; i < ` + pics.length + `; i++){
if (i == index){ return texture2D(textures[i],vUv); }
}
}
void main()
{
float chunk = 1. / ` + 1 + `.; // amount of transitions = 1
float t = floor(transition / chunk);
int idx0 = int(currentUniform);
int idx1 = int(nextUniform);
gl_FragColor = mix(
getTexture(idx0),
getTexture(idx1),
(transition - (float(t) * chunk)) * ` + 1 + `.
);
}
`;
window.onload=function()
{
init();
animate();
}
function init(){
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
controls = new THREE.TrackballControls( camera,renderer.domElement );
camera.position.z = 500;
console.log(camera.fov);
scene = new THREE.Scene();
scene.add(camera);
var magicPlaneMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vertShader,
fragmentShader: fragShader,
side: THREE.DoubleSide
});
for (var i = 0; i < Object.keys(textureData).length; i++) {
uniforms.textures.value[i].wrapS = uniforms.textures.value[i].wrapT = THREE.RepeatWrapping;
uniforms.textures.value[i].needsUpdate = true;
}
var magicPlaneGeometry = new THREE.PlaneBufferGeometry(1000, 1000, 16, 16);
var magicPlaneMesh = new THREE.Mesh(magicPlaneGeometry, magicPlaneMaterial);
magicPlaneMesh.position.y = -500;
magicPlaneMesh.rotation.x = Math.PI / 2;
magicPlaneMesh.scale.x=10;
magicPlaneMesh.scale.y=10;
scene.add(magicPlaneMesh);
changeMagicPlane(currentTexture);
document.addEventListener( 'wheel', onDocumentMouseWheel, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseWheel( event ) {
var fov = camera.fov + event.deltaY * 0.05;
camera.fov = THREE.Math.clamp( fov, 10, 75 );
console.log(camera.fov);
camera.updateProjectionMatrix();
}
function animate() {
if(tweenUpdate=="true")
{
TWEEN.update();
}
renderer.render( scene, camera );
controls.update();
requestAnimationFrame( animate );
}
function changeMagicPlane(asset){
var assNum= parseInt(asset);
nextTexture = assNum;
uniforms.nextUniform.value = nextTexture;
magicTween.start();
tweenUpdate="true";
tweenOver="false";
}
magicTween.onUpdate(function(){
uniforms.transition.value = magicPosition.magicTrans;
});
magicTween.onComplete(function(){
tweenUpdate="false";
tweenOver="true";
magicPosition.magicTrans=0;
currentTexture=nextTexture;
uniforms.currentUniform.value = currentTexture;
console.log("Current: "+currentTexture);
});
</script>
</body>
</html>
Utilizing ShaderMaterial for crossfading with a 256x256 pixel texture image.
Code includes Tween.js from () and uses gman.png available at (https://i.sstatic.net/CbEMh.png)