JSFiddle - React, Tailwind, and code Playground

HTML

<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
    
<script type="importmap">
	{
		"imports": {
			"three": "https://unpkg.com/three/build/three.module.js"
		}
	}
</script>

CSS

body {
	  margin: 0;
}

JavaScript

import * as THREE from 'three';

// init

const camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 1;

const scene = new THREE.Scene();

const geometry = new THREE.TorusKnotGeometry( 0.2, 0.08 );
const material = new THREE.MeshBasicMaterial( {
	map: new THREE.TextureLoader().load(
  	'https://i.imgur.com/5uFU9FR_d.jpg?maxwidth=512&shape=thumb&fidelity=high'
  )
} );
material.map.wrapS = THREE.RepeatWrapping;
material.map.wrapT = THREE.RepeatWrapping;
material.map.repeat.set( 12, 3 );

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

const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animation );
renderer.autoClear = false;
renderer.setScissor( 0, 0.35 * window.innerHeight, window.innerWidth, 0.15 * window.innerHeight );
document.body.appendChild( renderer.domElement );

// animation

const normals = new THREE.MeshNormalMaterial();

function animation( time ) {

	mesh.rotation.x = time / 2000;
	mesh.rotation.y = time / 1000;

  renderer.setScissorTest( false );
	renderer.clear();
	renderer.render( scene, camera );

	renderer.clearDepth();
  scene.traverse(o => {
  	if(o.material) {
    	o.m = o.material;
      o.material = normals;
    }
  });

  renderer.setScissorTest( true );
	renderer.render( scene, camera );
  
	scene.traverse(o => {
  	if(o.m) {
    	o.material = o.m;
    }
  });
}