Img Texture

HTML

<div class="content">
		
    <a href="inside.html" class="item">
				<img  src="https://i.imgur.com/3tU4Vig.jpg" class="js-image" alt="">
				<h2>Some title</h2>
				<p>And some very interesting description.</p>
			</a>
			<!-- END item -->
			<!-- BEGIN item -->
			<a href="inside.html" class="item">
				<img  src="https://i.imgur.com/3tU4Vig.jpg" class="js-image" alt="">
				<h2>Some title</h2>
				<p>And some very interesting description.</p>
			</a>
      </div>

<div id="container"></div>
<script id="vertex" type="x-shader/x-vertex">
uniform float time;
uniform float uProgress;
uniform float uTarget;
uniform float uPosition;
uniform vec2 uResolution;
uniform vec2 uQuadSize;
uniform vec4 uCorners;
varying vec2 vSize;

varying vec2 vUv;
void main() {
    float PI = 3.1415926;
    vUv = uv;
    float sine = sin(PI*uProgress);
    float waves = sine*0.1*sin(5.*length(uv) + 15.*uProgress);

    vec3 pos = position ;
    vec4 defaultState = modelMatrix*vec4( pos, 1.0 );
    vec4 fullScreenState = vec4( position, 1.0 );
    fullScreenState.x *=uResolution.x;
    fullScreenState.y *=uResolution.y;
    fullScreenState.z +=uCorners.x;
    float cornersProgress = mix(
        mix(uCorners.z,uCorners.w,uv.x),
        mix(uCorners.x,uCorners.y,uv.x),
        uv.y
    );




    vec4 finalState = mix(defaultState,fullScreenState,cornersProgress);

    vSize = mix(uQuadSize,uResolution,cornersProgress);

    gl_Position = projectionMatrix * viewMatrix * finalState;
}
</script>
<script id="fragment" type="x-shader/x-fragment">
uniform float time;
uniform float progress;
uniform vec2 uTextureSize;
uniform sampler2D uTexture;
varying vec2 vUv;

varying vec2 vSize;

vec2 getUV(vec2 uv, vec2 textureSize, vec2 quadSize){
    vec2 tempUV = uv - vec2(0.5);

    float quadAspect = quadSize.x/quadSize.y;
    float textureAspect = textureSize.x/textureSize.y;
    if(quadAspect<textureAspect){
        tempUV = tempUV*vec2(quadAspect/textureAspect,1.);
    } else{
        tempUV =...

CSS

*{margin:0;padding:0} 
body{
    background: rgb(15, 19, 37);
    font-weight: 400;
    color: #fff;
}
.header{
    font-weight: 100;
    color: #eee;
    position: fixed;
    left: 50px;
    top: 50px;
    font-size: 30px;
    z-index: 10;
    text-shadow: 0 2px 2px #000
}
.header a{
    text-decoration: none;
    color: #eee;
}
canvas{display: block}
#container{
    width: 100vw;
    height: 100vh;
    position: fixed;
    z-index: -1;
    top: 0;
    left: 0;
    }
    
.content{
    display: inline-flex;
    flex-wrap: nowrap;
    flex-direction: row;
    gap: 100px;
    padding: 200px;
    /* width: auto; */
}

/* item */
.item{
    text-decoration: none;
    color: #eee;
}
.item a{
    text-decoration: none;
    color: #eee;
}
.item h2{
    font-weight: 100;
    color: #fff;
}
.item p{
    font-weight: 100;
    color: #ccc;
}
.item:last-child{
    margin-right: 300px;
}
.item img{
    width: 25vw;
    height: 31.25vw;
    opacity: 0.2;
}
/* single */
.single{

}
.single h1{
    margin-bottom: 1em;
    font-size: 3em;
}
figure{
    margin: 0 0 3em 0;
    display: flex;
    gap: 50px;
}
figure+figure{
    flex-direction: row-reverse;
}
figure img{
    float: left;
    margin-right: 30px;
}
.single__content{
    max-width: 1000px;
    margin: 50px auto;
}
.single__content p{
    margin: 2em 0;
    line-height: 1.7;
    font-size: 1.1em;
}
.single__content a{
    color: #fff;
}
.single__top{
    height: 100vh;
    width: 100%;
    background-size: cover;
    background-position: 50% 50%;
}

.footer{
    border-top: 1px solid #ccc;
    padding-top: 10px;
    
    margin-top: 100px;
    padding-bottom: 150px;
    display: flex;
    font-size: 0.8em;
}
.footer p+p{
    margin-left: auto;
    text-align-last: left;
}


.curtain,.curtainBottom{
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    z-index: 100;
    background: black;
    transform: translate(0,100%)
}

.curtainTop{
    position: fixed;
    width: 100%;
    height:...

JavaScript

var camera, scene, renderer;
var geometry, material, mesh;

init();
animate();

function init() {
  container = document.getElementById('container');
  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
  camera.position.z = 1;
  materials = [];

  scene = new THREE.Scene();

  geometry = new THREE.PlaneBufferGeometry(1, 1, 10, 10);
  material = new THREE.ShaderMaterial({
    // wireframe: true,
    uniforms: {
      time: {
        value: 1.0
      },
      progress: {
        value: 0
      },
      uTexture: {
        value: null
      },
      uTextureSize: {
        value: new THREE.Vector2(10, 10)
      },
      uCorners: {
        value: new THREE.Vector4(0, 0, 0, 0)
      },
      uResolution: {
        value: new THREE.Vector2(this.width, this.height)
      },
      uQuadSize: {
        value: new THREE.Vector2(300, 300)
      }
    },
    vertexShader: document.getElementById('vertex').textContent,
    fragmentShader: document.getElementById('fragment').textContent,
  })


  mesh = new THREE.Mesh(geometry, material);
  /* scene.add( mesh ); */

  image = [...document.querySelectorAll('.js-image')];
  const loader = new THREE.TextureLoader();

  imageStore = image.map(img => {
    let bounds = img.getBoundingClientRect();
    let m = material.clone();
    materials.push(m);
    
    let texture = loader.load(img.src);

    m.uniforms.uTexture.value = texture;
    m.uniforms.progress.value = 0.2;
    let mesh = new THREE.Mesh(geometry, m);
    scene.add(mesh);
    
    return {
      img: img,
      mesh: mesh,
      width: bounds.width,
      height: bounds.height,
      top: bounds.top,
      left: bounds.left,
    }
  })
  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  container.appendChild(renderer.domElement);

}

function animate() {

  requestAnimationFrame(animate);
  renderer.render(scene, camera);

}