Error: GL ERROR :GL_INVALID_OPERATION : glTexImage2D

Hi,

We are developing a kind of 3D graph. We are using Angular with Three-full NPM (https://github.com/Itee/three-full). We are implementing the Nodes as particles and we are drawing them with shaders.

Code bellow of the post*

That works pretty good in the web browser (Mozilla and Chromium) with Linux environment but when we test it in the web browser with Windows environment, shaders crash and the drawing of the nodes is not done (appear that error message).

errorWindows
Message error in Mozilla with Windows environment

3d1
3D Graph in Linux environment

3d2
3D Graph in Windows environment

We search what the error means but there’s no clarifying information. The point is that if we use LineMaterial and not Shaders with RawShadersMaterial then it works nice, but with a reduction in performance. Is there any technical issue in Windows System that make it happens? How we can solve it? We try to comment everything about textures but it generate the same error. It seems that the problem in relate especially with the use of both Shaders.

Any chances to provide a live example that demonstrate the issue?

Crossposting:

Hi, Mugen
There it is: https://jsfiddle.net/dmartmilln/a48by2vr/
It’s a simple example of a Sphere in center with different nodes arround it.
Thank you.

Please add ``` before and after your code to format it.

const particles = this.numNodesValue;

if (particles > 0) {

const particle_system_geometry = new THREE.BufferGeometry();

// Buffers
const positionBuffer = new Float32Array(new ArrayBuffer(particles 12)); // For positioning
const colorBuffer = new Uint8Array(new ArrayBuffer(particles 3)); // For giving color to nodes
const sizeBuffer = new Float32Array(new ArrayBuffer(particles 4)); // For giving size to nodes
const highlightBuffer = new Float32Array(new ArrayBuffer(particles 4)); // For giving highlight
const subjectsBuffer = new Float32Array(new ArrayBuffer(particles 4)); // For subjects
const selectedBuffer = new Float32Array(new ArrayBuffer(particles 4)); // For selected

this.radius = Math.min(1000, Math.max(100, Math.sqrt(particles Math.PI 20)));

this.innerDistance = Math.sqrt(Math.pow(this.radius - this.camera.position.x, 2) +
Math.pow(0 - this.camera.position.y, 2) + Math.pow(0 - this.camera.position.z, 2));

const dispersion = this.radiusDispersion;

for (let i = 0; i < particles; i++) {

let particularDispersion = 0;

if (dispersion > 0) {
particularDispersion = (((Math.ceil(Math.random() 11) - 1) / 10) dispersion) + Math.random(); // [0…1] * dispersion
}

highlightBuffer[i] = 1.0;

const angleX = (Math.random() - 0.5) 2 Math.PI;
const angleY = (Math.random() - 0.5) 2 Math.PI;

const posX = (this.radius + particularDispersion) Math.sin(angleX) Math.cos(angleY);
const posY = (this.radius + particularDispersion) Math.sin(angleX) Math.sin(angleY);
const posZ = (this.radius + particularDispersion) * Math.cos(angleX);

positionBuffer[(i 3)] = posX;
positionBuffer[(i 3) + 1] = posY;
positionBuffer[(i * 3) + 2] = posZ;

colorBuffer[(i 3)] = (Math.random() 255);
colorBuffer[(i 3) + 1] = (Math.random() 255);
colorBuffer[(i 3) + 2] = (Math.random() 255);

subjectsBuffer[i] = Math.random() < 0.3 ? 1.0 : 0.0;
selectedBuffer[i] = 0.0;

if (particularDispersion !== 0) {
sizeBuffer[i] = Math.floor((Math.pow(particularDispersion, 2) / Math.pow(dispersion, 2)) * this.sizeDiff);
} else {
sizeBuffer[i] = 0;
}
}

const nodeBufferPosition = new THREE.InterleavedBuffer(positionBuffer, 3);
const nodeBufferColor = new THREE.InterleavedBuffer(colorBuffer, 3);
const nodeBufferSize = new THREE.InterleavedBuffer(sizeBuffer, 1);
const nodeBufferHighlight = new THREE.InterleavedBuffer(highlightBuffer, 1);
const nodeBufferSubject = new THREE.InterleavedBuffer(subjectsBuffer, 1);
const nodeBufferSelected = new THREE.InterleavedBuffer(selectedBuffer, 1);

particle_system_geometry.addAttribute(‘position’, new THREE.InterleavedBufferAttribute(nodeBufferPosition, 3, 0, false));
particle_system_geometry.addAttribute(‘color’, new THREE.InterleavedBufferAttribute(nodeBufferColor, 3, 0, true));
particle_system_geometry.addAttribute(‘size’, new THREE.InterleavedBufferAttribute(nodeBufferSize, 4, 0, true));
particle_system_geometry.addAttribute(‘highlighted’, new THREE.InterleavedBufferAttribute(nodeBufferHighlight, 4, 0, true));
particle_system_geometry.addAttribute(‘subject’, new THREE.InterleavedBufferAttribute(nodeBufferSubject, 4, 0, true));
particle_system_geometry.addAttribute(‘selected’, new THREE.InterleavedBufferAttribute(nodeBufferSelected, 4, 0, true));

const vertexShader = [
‘precision highp float;’,
‘’,
‘uniform mat4 modelViewMatrix;’,
‘uniform mat4 projectionMatrix;’,
‘’,
‘attribute vec3 position;’,
‘attribute vec3 color;’,
‘attribute float size;’,
‘attribute float highlighted;’,
‘attribute float subject;’,
‘attribute float selected;’,
‘’,
‘varying vec3 vColor;’,
‘varying float vHighlighted;’,
‘varying float vSubject;’,
‘varying float vSelected;’,
‘’,
‘void main() {’,
‘’,
’ vColor = color;’,
’ vHighlighted = highlighted;’,
’ vSubject = subject;’,
’ vSelected = selected;’,
’ gl_Position = projectionMatrix modelViewMatrix vec4(position.xyz , 1.0);’,
‘’,
’ if (subject > 0.0) {’,
‘’,
’ gl_PointSize = (10.0 + (size 2.0)) (300.0 / length(gl_Position.xyz));’,
‘’,
’ } else {’,
‘’,
’ gl_PointSize = (15.0 + (size 2.0)) (300.0 / length(gl_Position.xyz));’,
‘’,
’ }’,
‘’,
‘}’
].join(’\n’);
const fragmentShader = [
‘precision highp float;’,
‘’,
‘uniform sampler2D map;’,
‘uniform sampler2D map2;’,
‘uniform sampler2D mapSelected;’,
‘’,
‘varying vec3 vColor;’,
‘varying float vHighlighted;’,
‘varying float vSubject;’,
‘varying float vSelected;’,
‘’,
‘void main() {’,
‘’,
’ vec2 uv = vec2(gl_PointCoord.x, 1.0 - gl_PointCoord.y);’,
‘’,
’ if (vSelected > 0.0) {’,
‘’,
’ vec4 textureColor = vec4(texture2D(mapSelected, uv));’,
’ gl_FragColor = vec4(textureColor vec4(vColor, 1.0));’,
‘’,
’ } else {’,
’ if (vSubject > 0.0) {’,
‘’,
’ vec4 textureColor = vec4(texture2D(map2, uv));’,
’ gl_FragColor = vec4((vec3(1) - textureColor.rgb) vColor, textureColor.a);’,
‘’,
’ } else {’,
‘’,
’ gl_FragColor = vec4(texture2D(map, uv) * vec4(vColor, 1.0));’,
‘’,
’ if (vHighlighted == 0.0) {’,
’ gl_FragColor = vec4(0.3, 0.3, 0.3, gl_FragColor.a);’,
’ }’,
‘’,
’ if (gl_FragColor.a > 0.6) gl_FragColor.a = 1.0;’,
‘’,
’ }’,
’ }’,
‘’,
’ if (gl_FragColor.a < 0.6) discard;’,
‘’,
‘}’
].join(’\n’);

const uniforms = {
map: { type: ‘t’, value: new THREE.TextureLoader().load(’…/…/assets/transparent_sphere.png’)},
map2: { type: ‘t’, value: new THREE.TextureLoader().load(’…/…/assets/reach.svg’)},
mapSelected: { type: ‘t’, value: new THREE.TextureLoader().load(’…/…/assets/Design1.png’)},
};

const nodeMaterial = new THREE.RawShaderMaterial( {
uniforms: uniforms,
vertexShader: vertexShader,
fragmentShader: fragmentShader,
defines: {
USE_MAP: true
},
transparent: true
});

particle_system_geometry.boundingBox = null;
particle_system_geometry.computeBoundingSphere();

this.mesh = new THREE.Points( particle_system_geometry, nodeMaterial );

this.scene.add( this.mesh );const&#32;particles&#32;=&#32;this.numNodesValue;

if (particles > 0) {

const particle_system_geometry = new THREE.BufferGeometry();

// Buffers
const positionBuffer = new Float32Array(new ArrayBuffer(particles 12)); // For positioning
const colorBuffer = new Uint8Array(new ArrayBuffer(particles 3)); // For giving color to nodes
const sizeBuffer = new Float32Array(new ArrayBuffer(particles 4)); // For giving size to nodes
const highlightBuffer = new Float32Array(new ArrayBuffer(particles 4)); // For giving highlight
const subjectsBuffer = new Float32Array(new ArrayBuffer(particles 4)); // For subjects
const selectedBuffer = new Float32Array(new ArrayBuffer(particles 4)); // For selected

this.radius = Math.min(1000, Math.max(100, Math.sqrt(particles Math.PI 20)));

this.innerDistance = Math.sqrt(Math.pow(this.radius - this.camera.position.x, 2) +
Math.pow(0 - this.camera.position.y, 2) + Math.pow(0 - this.camera.position.z, 2));

const dispersion = this.radiusDispersion;

for (let i = 0; i < particles; i++) {

let particularDispersion = 0;

if (dispersion > 0) {
particularDispersion = (((Math.ceil(Math.random() 11) - 1) / 10) dispersion) + Math.random(); // [0…1] * dispersion
}

highlightBuffer[i] = 1.0;

const angleX = (Math.random() - 0.5) 2 Math.PI;
const angleY = (Math.random() - 0.5) 2 Math.PI;

const posX = (this.radius + particularDispersion) Math.sin(angleX) Math.cos(angleY);
const posY = (this.radius + particularDispersion) Math.sin(angleX) Math.sin(angleY);
const posZ = (this.radius + particularDispersion) * Math.cos(angleX);

positionBuffer[(i 3)] = posX;
positionBuffer[(i 3) + 1] = posY;
positionBuffer[(i * 3) + 2] = posZ;

colorBuffer[(i 3)] = (Math.random() 255);
colorBuffer[(i 3) + 1] = (Math.random() 255);
colorBuffer[(i 3) + 2] = (Math.random() 255);

subjectsBuffer[i] = Math.random() < 0.3 ? 1.0 : 0.0;
selectedBuffer[i] = 0.0;

if (particularDispersion !== 0) {
sizeBuffer[i] = Math.floor((Math.pow(particularDispersion, 2) / Math.pow(dispersion, 2)) * this.sizeDiff);
} else {
sizeBuffer[i] = 0;
}
}

const nodeBufferPosition = new THREE.InterleavedBuffer(positionBuffer, 3);
const nodeBufferColor = new THREE.InterleavedBuffer(colorBuffer, 3);
const nodeBufferSize = new THREE.InterleavedBuffer(sizeBuffer, 1);
const nodeBufferHighlight = new THREE.InterleavedBuffer(highlightBuffer, 1);
const nodeBufferSubject = new THREE.InterleavedBuffer(subjectsBuffer, 1);
const nodeBufferSelected = new THREE.InterleavedBuffer(selectedBuffer, 1);

particle_system_geometry.addAttribute(‘position’, new THREE.InterleavedBufferAttribute(nodeBufferPosition, 3, 0, false));
particle_system_geometry.addAttribute(‘color’, new THREE.InterleavedBufferAttribute(nodeBufferColor, 3, 0, true));
particle_system_geometry.addAttribute(‘size’, new THREE.InterleavedBufferAttribute(nodeBufferSize, 4, 0, true));
particle_system_geometry.addAttribute(‘highlighted’, new THREE.InterleavedBufferAttribute(nodeBufferHighlight, 4, 0, true));
particle_system_geometry.addAttribute(‘subject’, new THREE.InterleavedBufferAttribute(nodeBufferSubject, 4, 0, true));
particle_system_geometry.addAttribute(‘selected’, new THREE.InterleavedBufferAttribute(nodeBufferSelected, 4, 0, true));

const vertexShader = [
‘precision highp float;’,
‘’,
‘uniform mat4 modelViewMatrix;’,
‘uniform mat4 projectionMatrix;’,
‘’,
‘attribute vec3 position;’,
‘attribute vec3 color;’,
‘attribute float size;’,
‘attribute float highlighted;’,
‘attribute float subject;’,
‘attribute float selected;’,
‘’,
‘varying vec3 vColor;’,
‘varying float vHighlighted;’,
‘varying float vSubject;’,
‘varying float vSelected;’,
‘’,
‘void main() {’,
‘’,
’ vColor = color;’,
’ vHighlighted = highlighted;’,
’ vSubject = subject;’,
’ vSelected = selected;’,
’ gl_Position = projectionMatrix modelViewMatrix vec4(position.xyz , 1.0);’,
‘’,
’ if (subject > 0.0) {’,
‘’,
’ gl_PointSize = (10.0 + (size 2.0)) (300.0 / length(gl_Position.xyz));’,
‘’,
’ } else {’,
‘’,
’ gl_PointSize = (15.0 + (size 2.0)) (300.0 / length(gl_Position.xyz));’,
‘’,
’ }’,
‘’,
‘}’
].join(’\n’);
const fragmentShader = [
‘precision highp float;’,
‘’,
‘uniform sampler2D map;’,
‘uniform sampler2D map2;’,
‘uniform sampler2D mapSelected;’,
‘’,
‘varying vec3 vColor;’,
‘varying float vHighlighted;’,
‘varying float vSubject;’,
‘varying float vSelected;’,
‘’,
‘void main() {’,
‘’,
’ vec2 uv = vec2(gl_PointCoord.x, 1.0 - gl_PointCoord.y);’,
‘’,
’ if (vSelected > 0.0) {’,
‘’,
’ vec4 textureColor = vec4(texture2D(mapSelected, uv));’,
’ gl_FragColor = vec4(textureColor vec4(vColor, 1.0));’,
‘’,
’ } else {’,
’ if (vSubject > 0.0) {’,
‘’,
’ vec4 textureColor = vec4(texture2D(map2, uv));’,
’ gl_FragColor = vec4((vec3(1) - textureColor.rgb) vColor, textureColor.a);’,
‘’,
’ } else {’,
‘’,
’ gl_FragColor = vec4(texture2D(map, uv) * vec4(vColor, 1.0));’,
‘’,
’ if (vHighlighted == 0.0) {’,
’ gl_FragColor = vec4(0.3, 0.3, 0.3, gl_FragColor.a);’,
’ }’,
‘’,
’ if (gl_FragColor.a > 0.6) gl_FragColor.a = 1.0;’,
‘’,
’ }’,
’ }’,
‘’,
’ if (gl_FragColor.a < 0.6) discard;’,
‘’,
‘}’
].join(’\n’);

const uniforms = {
map: { type: ‘t’, value: new THREE.TextureLoader().load(’…/…/assets/transparent_sphere.png’)},
map2: { type: ‘t’, value: new THREE.TextureLoader().load(’…/…/assets/reach.svg’)},
mapSelected: { type: ‘t’, value: new THREE.TextureLoader().load(’…/…/assets/Design1.png’)},
};

const nodeMaterial = new THREE.RawShaderMaterial( {
uniforms: uniforms,
vertexShader: vertexShader,
fragmentShader: fragmentShader,
defines: {
USE_MAP: true
},
transparent: true
});

particle_system_geometry.boundingBox = null;
particle_system_geometry.computeBoundingSphere();

this.mesh = new THREE.Points( particle_system_geometry, nodeMaterial );

this.scene.add( this.mesh );

This example is very complicated though. Can you strip down the shader / buffers until you render something with no issues?

What are you doing with USE_MAP? Can you try commenting out that define? I’m not sure why you would want it and especially in a RawShaderMaterial, i wouldn’t at all be surprised if this triggers some phantom limbs or something.

What I see at your code is that you are not interleaving your geometry data correctly.

const positionBuffer = new Float32Array(new ArrayBuffer(particles * 12));
const colorBuffer = new Uint8Array(new ArrayBuffer(particles * 3));

Creating a new array buffer for each attribute will not interleave the data in memory. Have a look at the following example in order to see the correct approach. You have to use a single array buffer for all data.

https://threejs.org/examples/webgl_buffergeometry_points_interleaved

Unfortunately, I’m using macOS so I can’t reproduce the mentioned warning. One thing you should avoid is the usage of the following code since it has no effect for RawShaderMaterial:

defines: {
   USE_MAP: true
},

Yeah the interleaved buffer thing seemed a bit confusing, but i figured if it rendered what you expected it somehow worked. I’m really really curious about the USE_MAP.