THREE.MeshBasicMaterial vs THREE.ShaderMaterial

Friends! Tell me how to make the result the same when using THREE.MeshBasicMaterial and THREE.ShaderMaterial. The left image is obtained using THREE.MeshBasicMaterial, and the right image is obtained by outputting the same texture using a simple shader void main() { gl_FragColor = texture2D(image, v_uv); }. How can I make the left and right pictures the same?

> <!DOCTYPE html>
> <html lang="en">
> 	<head>
> 		<meta charset="utf-8">
> 		<title>DomIK.JS</title>
> 		<link rel="stylesheet" type="text/css" href="./static/stylesheet.css">
> 	</head>
> 	<body>
> 		<script type="importmap">
> 			{
> 				"imports": {
> 					"three":               "./vendor/build/three.module.min.js",
> 					"three/addons/":       "./vendor/jsm/",
> 					"bidi-js":             "./vendor/build/bidi.mjs"
> 				}
> 			}
> 		</script>
> 		<script id="vertexShader" type="x-shader/x-vertex">
> 			varying vec2 v_uv;
> 			void main()	{
>                 v_uv = uv;
>                 gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
> 		}
> 		</script>
> 		<script id="fragmentShader" type="x-shader/x-fragment">
> 			varying vec2 v_uv;
> 			uniform sampler2D image;
> 			void main()	{
> 				gl_FragColor = texture2D(image, v_uv);
> 			}
> 		</script>
> 		<script type="module">
> 
> import * as THREE from 'three';
> let camera, scene, renderer;
> let mesh;
> 
> init();
> animate();
> 
> function init() {
> 	camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 100 );
> 	camera.position.z = 2;
> 	scene = new THREE.Scene();
> 	const texture = new THREE.TextureLoader().load( 'https://sungreen.github.io/projects/DomIK.js/v2.0/content/cheker.png' );
> 	texture.colorSpace = THREE.SRGBColorSpace;
> 	const geometry = new THREE.PlaneGeometry();
> 	const mat1 = new THREE.MeshBasicMaterial( { map: texture } );
> 	const uniforms = { image: { type: 't', value: texture } };
> 	const mat2 = new THREE.ShaderMaterial( {
> 	uniforms: uniforms,
> 	vertexShader: document.getElementById( 'vertexShader' ).textContent,
> 	fragmentShader: document.getElementById( 'fragmentShader' ).textContent
> 	} );
> 	mesh = new THREE.Mesh( geometry, mat1 );
> 	mesh.position.x = -0.7;
> 	scene.add( mesh );
> 	mesh = new THREE.Mesh( geometry, mat2 );
> 	mesh.position.x = 0.7;
> 	scene.add( mesh );
> 	renderer = new THREE.WebGLRenderer( { antialias: true } );
> 	renderer.setPixelRatio( window.devicePixelRatio );
> 	renderer.setSize( window.innerWidth, window.innerHeight );
> 	document.body.appendChild( renderer.domElement );
> }
> 
> function animate() {
> 	requestAnimationFrame( animate );
> 	renderer.render( scene, camera );
> }
> </script> 
> 	</body>
> </html>

Write your fragment shader like so:

varying vec2 v_uv;
uniform sampler2D image;
void main()	{
    gl_FragColor = texture2D(image, v_uv);
    #include <colorspace_fragment>
}

This ensures color space conversion happens at the end of your shader.

4 Likes

Magic! Thanks a lot!