Hello, I’m looking to replicate the illumination and reflection effects of a 360 HDRi using a ShaderMaterial instead of a MeshStandardMaterial. How should I approach this?
So far, I’ve managed to achieve reflections (have I done it correctly?), but I’m unsure how to utilize the HDRi for illumination.
I’m importing these uniforms from a main.js:
uEnvironmentMap: { value: cubeMap },
uCameraPosition: { value: camera.position },
where I also create the cubemap of the environment for the reflections:
const r = "./assets/cubemap/";
const urls = [r + "px.jpg", r + "nx.jpg", r + "py.jpg", r + "ny.jpg", r + "pz.jpg", r + "nz.jpg"];
const cubeMap = await new THREE.CubeTextureLoader().loadAsync(urls);
cubeMap.mapping = THREE.CubeReflectionMapping;
cubeMap.encoding = THREE.sRGBEncoding;
Here’s the shader:
// shaders.js
export const hdrReflectionMaterial = {
uniforms: {
uRoughness: { value: 0.5 },
uReflectivity: { value: 0.6 },
},
vertexShader: `
varying vec3 vWorldPosition;
varying vec3 vWorldNormal;
void main() {
vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
vWorldNormal = normalize(mat3(modelMatrix) * normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform samplerCube uEnvironmentMap;
uniform float uRoughness;
uniform float uReflectivity;
uniform vec3 uCameraPosition;
varying vec3 vWorldPosition;
varying vec3 vWorldNormal;
void main() {
vec3 viewDirection = normalize(uCameraPosition - vWorldPosition);
vec3 reflection = reflect(-viewDirection, normalize(vWorldNormal));
// Fresnel-Schlick approximation for reflectivity based on view angle
float fresnel = pow(1.0 - max(dot(viewDirection, normalize(vWorldNormal)), 0.0), 5.0);
fresnel = mix(uReflectivity, 1.0, fresnel);
// Sample the HDR environment map for specular reflection
vec3 specColor = textureCube(uEnvironmentMap, reflection, uRoughness).rgb;
// Base color (white) mixed with reflection color
vec3 baseColor = vec3(1.0, 1.0, 1.0); // Materiale base bianco
vec3 color = mix(baseColor, specColor, fresnel); // Mix basato sulla riflettività
gl_FragColor = vec4(color, 1.0);
}
`
};
These are the results:
uRoughness: { value: 0.5 },
uReflectivity: { value: 0.6 },
uRoughness: { value: 2 },
uReflectivity: { value: 0.9 },
uRoughness: { value: 2 },
uReflectivity: { value: 0 },