I want to implement IBL (Image-Based Lighting) in THREE.js, and I’m looking into how to use environment maps. Below is my custom shader (fragment shader).
const fragmentShader = `
uniform samplerCube envMap;
in vec3 vReflect;
out vec4 color;
void main() {
vec3 reflectColor = textureCube(envMap, vReflect).rgb;
color = vec4(reflectColor, 1.0);
}`
I want to pass the environment map texture to the uniform samplerCube envMap; and wrote the following code as usual, but I wasn’t able to pass it correctly.
const material = new THREE.ShaderMaterial({
glslVersion : THREE.GLSL3,
uniforms : {
lightDirection : { value : new THREE.Vector3(1, 1, 1) },
baseColor : { value : new THREE.Color(1, 1, 1) },
envMap : { value : envMap }
},
vertexShader,
fragmentShader,
side : THREE.FrontSide,
});
After researching, it seems that if I set the environment map to scene.background as shown below, it will be passed to the fragment shader. However, this results in a completely unintended background being rendered. This behavior makes no sense to me, so I wonder why this is happening. Also, is there a way to handle this?
I found a previous post that mentioned the need to define “envMap” in the material properties. So, after getting scolded by the TypeScript compiler and Lint, I added the following code, but it didn’t solve the problem:
(material as any).envMap = reflectionCube;
A warning is output in the browser’s console as follows:
WebGL: INVALID_OPERATION: bindTexture: textures can not be used with multiple targets
@seanwasere
Thank you for your cooperation. Could this be a bug in THREE.js?
Also, I’m curious why my sample appears jagged compared to your sample, even though the code is almost identical. Could it be because of a difference in the THREE.js version?
I’m struggling to figure out how to update the version on JSFiddle… I’ve been wrestling with the CDN.
After several hours of struggle, I was able to update THREE.js on JSFiddle to the latest version. The jaggy issue has been resolved, but the main issue remains unresolved.
Deleting line 18 makes the screen completely black.
I think perhaps what you are loading isn’t a cubemap (not 6 faces loaded via cubemap loader) but a 2d equirectangular map… which would require using a sampler2D instead of samplerCube.
I switched to MeshStandardMaterial with envMap = your envmap and it works…
(without setting scene.environment or .background)
@manthrax@seanwasere
Thank you very much.
It worked well with my sample too. I deeply appreciate both of your answer.
I wanted to apply IBL to the result of volume rendering CT images and was looking for a way to implement IBL with a custom shader.