HDRi illumination and reflections using a shaderMaterial

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 },