Skip to content

LineMaterial webgl shader crashes with big line width #32001

@mwmarcos

Description

@mwmarcos

Description

When adding many (2mio) lines with huge line width (500) the webgl shader crashes, resulting in Context Loss.

I've created an example that reliably reproduces the bug. When clicking on the left button, 2mio lines are added with line width 1. This works. But when clicking the right button it adds 2mio lines with line width 500, resulting in the bug. My screen flashes white and then the developer console displays:

WebGL: CONTEXT_LOST_WEBGL: loseContext: context lostUnderstand this warning
three.module.js:15856 THREE.WebGLRenderer: Context Lost.

After that when reloading I'm not able to get a webgl context and need to restart the browser:

THREE.WebGLRenderer: A WebGL context could not be created. Reason:  Web page caused context loss and was blocked

It makes no difference if I use Line2 instead of LineSegment2. Also this is the case in chrome and firefox.

Reproduction steps

  1. Add 2 million Line2 or LineSegment2 with line width 500
  2. Render them

Code

import * as THREE from 'three';
import { LineSegments2 } from 'three/addons/lines/LineSegments2.js';
import { LineMaterial } from 'three/addons/lines/LineMaterial.js';
import { LineGeometry } from 'three/addons/lines/LineGeometry.js';

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x111111);
const camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 0.01, 1000);
camera.position.set(0, 0, 100);

const renderer = new THREE.WebGLRenderer({ antialias: false });
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

let currentLines = null;

function addMillionLines(linewidth) {
    if (currentLines) {
        scene.remove(currentLines);
        if (currentLines.geometry) currentLines.geometry.dispose();
        if (currentLines.material) currentLines.material.dispose();
        currentLines = null;
    }

    const N = 2_000_000;
    const floats = N * 2 * 3;
    const positions = new Float32Array(floats);

    const range = 50;
    const segLen = 0.2;
    for (let i = 0, j = 0; i < N; i++) {
        const cx = (Math.random() - 0.5) * range;
        const cy = (Math.random() - 0.5) * range;
        const cz = (Math.random() - 0.5) * range;
        const dx = (Math.random() - 0.5) * segLen;
        const dy = (Math.random() - 0.5) * segLen;
        const dz = (Math.random() - 0.5) * segLen;
        positions[j++] = cx - dx;
        positions[j++] = cy - dy;
        positions[j++] = cz - dz;
        positions[j++] = cx + dx;
        positions[j++] = cy + dy;
        positions[j++] = cz + dz;
    }

    const geometry = new LineGeometry();
    geometry.setPositions(positions);
    const material = new LineMaterial({linewidth: linewidth});
    const lines = new LineSegments2(geometry, material);
    lines.computeLineDistances();
    scene.add(lines);
    currentLines = lines;

    camera.position.z = Math.max(100, camera.position.z);
    camera.lookAt(0,0,0);
}

document.getElementById('btnSmall').addEventListener('click', () => addMillionLines(1));
document.getElementById('btnLarge').addEventListener('click', () => addMillionLines(500));

function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}
animate();

Live example

Screenshots

Image

Version

r180

Device

Desktop

Browser

Chrome

OS

Windows

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions