WebGL: INVALID_OPERATION: bindTexture: textures can not be used with multiple targets

Hey community,

i am trying to use an enviroment map in my fragment shader. The goal is to create a reflection effect on a surface that is animated using perlin noise. This is my fragment shader:

uniform samplerCube uTexture;
varying vec3 vNormal;
varying float vPerlinStrength;

void main() {
    vec3 envColor = textureCube(uTexture, vNormal).rgb;

    float temp = vPerlinStrength + 0.5;
    temp *= 0.5;

    vec3 finalColor = envColor * temp;

    gl_FragColor = vec4(finalColor, 1.0);
}

But when using this shader i get this error:

WebGL: INVALID_OPERATION: bindTexture: textures can not be used with multiple targets

And also my object has an all black surface so something is clearly not working.

I researched the error and apparently it is caused by applying the enviroment map to 2D and 3D surfaced at the same time. But the problem is that i can’t find where i am using the texture wrong.

Here is the javascript of my scene:

<script>
	import { onMount } from 'svelte';
	import * as THREE from 'three';
	import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
	import organicVertexShader from '/src/lib/utils/shaders/sphere/organic-vertext.glsl';
	import organicFragmentShader from '/src/lib/utils/shaders/sphere/organic-fragment.glsl';
	import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader';

	let scene, camera, renderer, sphere, controls, material;

	async function loadEnvironmentMap() {
		return new Promise((resolve, reject) => {
			const rgbeLoader = new RGBELoader();
			rgbeLoader.load(
				'/src/lib/assets/enviroment.hdr',
				(texture) => {
					console.log('HDR image loaded');
					const pmremGenerator = new THREE.PMREMGenerator(renderer);
					const cubeRenderTarget = pmremGenerator.fromEquirectangular(texture);
					
					scene.background = new THREE.Color(0xffffff);
                                        //scene.background = cubeRenderTarget.texture;
					//scene.environment = cubeRenderTarget.texture;
					resolve(cubeRenderTarget.texture);
				},
				undefined,
				reject
			);
		});
	}

	async function init() {
		renderer = new THREE.WebGLRenderer({ antialias: true });
		scene = new THREE.Scene();
		camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
		renderer.setSize(window.innerWidth, window.innerHeight);
		document.body.appendChild(renderer.domElement);

		try {
			const environmentMap = await loadEnvironmentMap();
			const geometry = new THREE.IcosahedronGeometry(1, 200);

			material = new THREE.ShaderMaterial({
				uniforms: {
					uTexture: { value: environmentMap },
					uTime: { value: 0.0 },
					uDistortionFrequency: { value: 1.0 },
					uDistortionStrength: { value: 2.5 },
					uDisplacementFrequency: { value: 2.0 },
					uDisplacementStrength: { value: 0.2 }
				},
				vertexShader: organicVertexShader,
				fragmentShader: organicFragmentShader
			});

			sphere = new THREE.Mesh(geometry, material);
			scene.add(sphere);

			camera.position.z = 5;
			controls = new OrbitControls(camera, renderer.domElement);
			controls.update();

			window.addEventListener('resize', () => {
				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();
				renderer.setSize(window.innerWidth, window.innerHeight);
			});

			const clock = new THREE.Clock();
			const animate = function () {
				const elapsedTime = clock.getElapsedTime();
				material.uniforms.uTime.value = elapsedTime / 20;
				controls.update();
				renderer.render(scene, camera);
				requestAnimationFrame(animate);
			};
			animate();
		} catch (error) {
			console.error('Error loading environment map:', error);
		}
	}

	onMount(async () => {
		console.log('onMount');
		await init();
		console.log('initialized');
	});
</script>

I already tried to remove these lines

     scene.background = cubeRenderTarget.texture
     scene.environment = cubeRenderTarget.texture;

but the error still persists.

I think i am doing something wrong in the way i am handleing the enviroment map and passing it to the shader, but i am a bit lost.

Any tipps and help would be really appriciated :slight_smile:

I would think that removing those 2 lines would fix that error… since you’re only using the map in your shader now…
It’s possible the PMRemGenerator is holding on to it somehow. Maybe do a
pmremGenerator.dispose() before you resolve(

Thanks for the response :slight_smile:

Sadly the error still persists with the two lines removed and the dispose() function.

This is the code i tried and it still throws the error:

async function loadEnvironmentMap() {
		return new Promise((resolve, reject) => {
			const rgbeLoader = new RGBELoader();
			rgbeLoader.load(
				'/src/lib/assets/enviroment.hdr',
				(texture) => {
					console.log('HDR image loaded');
					const pmremGenerator = new THREE.PMREMGenerator(renderer);
					const cubeRenderTarget = pmremGenerator.fromEquirectangular(texture);
					scene.background = new THREE.Color(0xffffff);
					pmremGenerator.dispose();
					resolve(cubeRenderTarget.texture);
				},
				undefined,
				reject
			);
		});
	}