'Image rendered from useLoader @react-three/fiber using shaderMaterial has different color from its original color

Here is my problem, my project is generated from create-react-app, followed by some @react-three/fiber and glsl dependencies, I render simple planeBufferGeometry and for the material I use shaderMaterial

here is code for planeBufferGeometry: (Geometries.jsx)

import React, { useRef } from 'react';
import * as THREE from 'three';
import { useFrame, useLoader } from '@react-three/fiber';
import './PlaneShaderMaterial';
import tiger from './images/tiger.jpg';

export const Plane = () => {
  const meshRef = useRef();
  const shaderRef = useRef();

  useFrame(() => {
    if (shaderRef.current) {
      shaderRef.current.uTime += 0.05;
    }
  });

  const [img] = useLoader(THREE.TextureLoader, [tiger]);

  return (
    <mesh ref={meshRef} position={[0, 0, 0]}>
      <planeBufferGeometry attach="geometry" args={[1, 1, 10, 10]} />
      {/* <meshBasicMaterial side={THREE.DoubleSide} map={img} attach="material" /> */}
      <planeShaderMaterial
        attach="material"
        ref={shaderRef}
        side={THREE.DoubleSide}
        uTexture={img}
      />
    </mesh>
  );
};

here is the code for the shaderMaterial: (PlaneShaderMaterial.jsx)

import * as THREE from 'three';
import { shaderMaterial } from '@react-three/drei';
import { extend } from '@react-three/fiber';
import glsl from 'babel-plugin-glsl/macro';

const uniform = {
  uColor: new THREE.Color(1.0, 0.0, 0.0),
  uTexture: new THREE.Texture(),
  uTime: 0,
  distanceFromCenter: 0,
};

const vertexShader = glsl`
  precision mediump float;
  varying vec2 vUv;
  uniform float uTime;

  void main() {

    vec3 pos = position;
    vUv = uv;

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
  }
`;

const fragmentShader = glsl`
  precision mediump float;
  uniform vec3 uColor;
  varying vec2 vUv;
  uniform float uTime;
  uniform sampler2D uTexture;

  void main() {
    vec4 t = texture2D(uTexture, vUv);

    gl_FragColor = vec4(t);
  }
`;

const PlaneShaderMaterial = shaderMaterial(
  // Uniform
  uniform,
  // vertex shader
  vertexShader,
  // fragment shader
  fragmentShader,
);

here is the code in App.jsx:

import React, { Suspense } from 'react';
import './App.css';
import CameraControls from './CameraControls.jsx';
import { Canvas } from '@react-three/fiber';
import { Plane } from './Geometries';

const Scene = () => {
  return (
    <Canvas
      gl={{ antialias: true, alpha: true }}
      camera={{
        fov: 70,
        aspect: window.innerWidth / window.innerHeight,
        near: 0.001,
        far: 1000,
        position: [0, 0, 2],
      }}
      style={{
        display: 'block',
        zIndex: '10',
      }}
    >
      <CameraControls />
      <Suspense fallback={null}>
        <Plane />
      </Suspense>
    </Canvas>
  );
};

function App() {
  return (
    <div style={{ height: '100vh', width: '100vw' }}>
      <Scene />
    </div>
  );
}

export default App;

This is the original image: tiger.jpg

This is the image after rendered with useLoader and textured with shaderMaterial: rederedImage

But when I tried to change the material to MeshBasicMaterial, the color was correct, I think that the problem has something to do with the shaderMaterial not the react-fiber useLoader which preLoads the image

So the rendered image has a little darker color than its original color. I've tried to change the SRGBEncoding but it doesn't work. Any idea how to make it the same color?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source