# HDRi illumination and reflections using a shaderMaterial

**URL:** <https://discourse.threejs.org/t/hdri-illumination-and-reflections-using-a-shadermaterial/63304>\
**Category:** Questions\
**Tags:** shader-material, hdri, materials, shaders\
**Created:** [March 27, 2024, 9:03am UTC](https://discourse.threejs.org/t/hdri-illumination-and-reflections-using-a-shadermaterial/63304 "2024-03-27T09:03:49Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![iamagro](https://avatars.discourse-cdn.com/v4/letter/i/59ef9b/32.png) [@iamagro](https://discourse.threejs.org/u/iamagro)\
**Post date:** [March 27, 2024, 9:03am UTC](https://discourse.threejs.org/t/hdri-illumination-and-reflections-using-a-shadermaterial/63304/1 "2024-03-27T09:03:49Z")

</div>

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:

```javascript
uEnvironmentMap: { value: cubeMap },
uCameraPosition: { value: camera.position },

```

where I also create the cubemap of the environment for the reflections:

```javascript
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:

```javascript
// 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 },

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/4/5/4512a1cd0ffb2c6802bfddaa8eb5f490fe99e5c6.jpeg)

> uRoughness: { value: 2 },  
> uReflectivity: { value: 0.9 },

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/2/f/2f18068dfe86add673460268a4f5acfe8d1aa747.jpeg)

> uRoughness: { value: 2 },  
> uReflectivity: { value: 0 },

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/2/2/227aecf3e060d854942ab56886e08e9bfe500520.jpeg)
