Skip to content

Instantly share code, notes, and snippets.

@0beqz
Last active February 29, 2024 01:45
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save 0beqz/8d51b4ae16d68021a09fb504af708fca to your computer and use it in GitHub Desktop.
Save 0beqz/8d51b4ae16d68021a09fb504af708fca to your computer and use it in GitHub Desktop.
Updated code to box-project env-maps in three.js (r137) - credits go to codercat (https://codercat.tk) for the box-projecting code
import * as THREE from "three"
// credits for the box-projecting shader code go to codercat (https://codercat.tk)
const worldposReplace = /* glsl */`
#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )
vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );
#ifdef BOX_PROJECTED_ENV_MAP
vWorldPosition = worldPosition.xyz;
#endif
#endif
`;
const boxProjectDefinitions = /*glsl */`
#ifdef BOX_PROJECTED_ENV_MAP
uniform vec3 envMapSize;
uniform vec3 envMapPosition;
varying vec3 vWorldPosition;
vec3 parallaxCorrectNormal( vec3 v, vec3 cubeSize, vec3 cubePos ) {
vec3 nDir = normalize( v );
vec3 rbmax = ( .5 * cubeSize + cubePos - vWorldPosition ) / nDir;
vec3 rbmin = ( -.5 * cubeSize + cubePos - vWorldPosition ) / nDir;
vec3 rbminmax;
rbminmax.x = ( nDir.x > 0. ) ? rbmax.x : rbmin.x;
rbminmax.y = ( nDir.y > 0. ) ? rbmax.y : rbmin.y;
rbminmax.z = ( nDir.z > 0. ) ? rbmax.z : rbmin.z;
float correction = min( min( rbminmax.x, rbminmax.y ), rbminmax.z );
vec3 boxIntersection = vWorldPosition + nDir * correction;
return boxIntersection - cubePos;
}
#endif
`;
// will be inserted after "vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );"
const getIBLIrradiance_patch = /* glsl */`
#ifdef BOX_PROJECTED_ENV_MAP
worldNormal = parallaxCorrectNormal( worldNormal, envMapSize, envMapPosition );
#endif
`;
// will be inserted after "reflectVec = inverseTransformDirection( reflectVec, viewMatrix );"
const getIBLRadiance_patch = /* glsl */`
#ifdef BOX_PROJECTED_ENV_MAP
reflectVec = parallaxCorrectNormal( reflectVec, envMapSize, envMapPosition );
#endif
`;
export function useBoxProjectedEnvMap(shader, envMapPosition, envMapSize) {
// defines
shader.defines.BOX_PROJECTED_ENV_MAP = true;
// uniforms
shader.uniforms.envMapPosition = {
value: envMapPosition
};
shader.uniforms.envMapSize = {
value: envMapSize
};
// vertex shader
shader.vertexShader = "varying vec3 vWorldPosition;\n" + shader.vertexShader
.replace(
"#include <worldpos_vertex>",
worldposReplace
);
// fragment shader
shader.fragmentShader = boxProjectDefinitions + "\n" + shader.fragmentShader
.replace(
"#include <envmap_physical_pars_fragment>",
THREE.ShaderChunk.envmap_physical_pars_fragment
)
.replace(
"vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );",
`
vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );
${getIBLIrradiance_patch}
`
)
.replace(
"reflectVec = inverseTransformDirection( reflectVec, viewMatrix );",
`
reflectVec = inverseTransformDirection( reflectVec, viewMatrix );
${getIBLRadiance_patch}
`
);
}
@0beqz
Copy link
Author

0beqz commented Feb 24, 2022

Usage:

import { useBoxProjectedEnvMap } from "./BoxProjectedEnvMapHelper"

const envMapPosition = new THREE.Vector3(); // position of the env-map camera (where the env-map was generated)
const envMapSize = new THREE.Vector3(); // size of the room for which the env-map should be box-projected

material.onBeforeCompile = shader => useBoxProjectedEnvMap(shader, envMapPosition, envMapSize);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment