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 image after rendered with useLoader and textured with shaderMaterial:
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?
I just had the same problem. The only thing that worked for me was a gamma correction.