question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Attributes render out of order in shared Webgl environment

See original GitHub issue

Describe the bug

I’m using shared Webgl for map, but found that since version r118, the rendered attributes data will be rendered garbled, I found that the needUpdate function does not return true; if I force needUpdate to return true, then it seems to work

Code

// code goes here
function needsUpdate(geometry, index) {
        // good
        return true;
	const cachedAttributes = currentState.attributes;
	const geometryAttributes = geometry.attributes;
	let attributesNum = 0;

	for (const key in geometryAttributes) {
		const cachedAttribute = cachedAttributes[key];
		const geometryAttribute = geometryAttributes[key];
		if (cachedAttribute === undefined) return true;
		if (cachedAttribute.attribute !== geometryAttribute) return true;
		if (cachedAttribute.data !== geometryAttribute.data) return true;
		attributesNum++;
	}

	if (currentState.attributesNum !== attributesNum) return true;
	if (currentState.index !== index) return true;
	return false;
}

Live example I can not get jsfidle , so…

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
    <title>自定义三维图层</title>
    <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" />
    <style>
        html,
        body,
        #container {
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>
    <div id="container"></div>
    <script src="https://webapi.amap.com/maps?v=2.0&key=dc695ce0c94242cb2f1eaddfe6ba580e"></script>

    <!-- error -->
    <!-- <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r134/three.js"></script> -->

    <!-- good -->
    <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r117/three.js"></script>
    
    <script type="text/javascript">
        var map = new AMap.Map('container', {
            center: [116.54, 39.79],
            zooms: [2, 20],
            zoom: 14,
            viewMode: '3D',
            pitch: 50,
        });
        // map.getLayers().forEach(function (layer) {
        //     // layer.hide()
        // })

        var camera;
        var renderer;
        var scene;
        // 数据转换工具
        var customCoords = map.customCoords;
        // 数据使用转换工具进行转换,这个操作必须要提前执行(在获取镜头参数 函数之前执行),否则将会获得一个错误信息。
        var data = customCoords.lngLatsToCoords([
            [116.52, 39.79],
            [116.54, 39.79],
            [116.56, 39.79],
        ]);

        // 创建 GL 图层
        var gllayer = new AMap.GLCustomLayer({
            // 图层的层级
            zIndex: 10,
            // 初始化的操作,创建图层过程中执行一次。
            init: (gl) => {
                // 这里我们的地图模式是 3D,所以创建一个透视相机,相机的参数初始化可以随意设置,因为在 render 函数中,每一帧都需要同步相机参数,因此这里变得不那么重要。
                // 如果你需要 2D 地图(viewMode: '2D'),那么你需要创建一个正交相机
                camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 100, 1 << 10);

                renderer = new THREE.WebGLRenderer({
                    // context: gl,  // 地图的 gl 上下文
                    alpha: true,
                    antialias: true,
                    canvas: gl.canvas,
                });
                // 自动清空画布这里必须设置为 false,否则地图底图将无法显示
                renderer.autoClear = false;
                scene = new THREE.Scene();

                //  这里可以使用 three 的各种材质,示例使用的是 three 的自定义 shader
                // var material = new THREE.PointsMaterial({
                //     color: 0xff00f0,
                //     size: 100,
                //     depthTest: false,
                //     transparent: true,
                //     vertexColors: false,
                //     isMaterial: true,
                //     precision: 'highp',
                //     premultipliedAlpha: true,
                //     dithering: true,
                //     toneMapped: false,
                // });
                var material = new THREE.RawShaderMaterial({
                    depthTest: true,
                    transparent: true,
                    side: THREE.DoubleSide,
                    vertexShader: `
                    precision highp float;
                    attribute vec3 position;
                    attribute vec4 color;
                    uniform mat4 modelViewMatrix; // optional
                    uniform mat4 projectionMatrix; // optional
                    varying vec4 vColor;
                    void main() {
                        vColor = color;
                        gl_PointSize = 100.0;
                        gl_Position = projectionMatrix * modelViewMatrix * vec4( position.xy, 0, 1.0 );
                    }
                `,
                    fragmentShader: `
                    precision highp float;
                    varying vec4 vColor;
                    void main() {
                        gl_FragColor = vColor;
                    }
                `,
                });
                var geometry = new THREE.BufferGeometry();

                var ver = [];
                var color = [];
                for (var i = 0; i < data.length; i++) {
                    var d = data[i];
                    // 每一个点的坐标,x/y/z,这里我们给 10 米的高度。
                    ver.push(d[0], d[1], 1000 * Math.random());

                    // 每个点的颜色随机给
                    color.push(0.6, 0.5, 0.7, 1);
                }
                // console.log(ver);
                // geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
                geometry.setAttribute('position', new THREE.Float32BufferAttribute(ver, 3));
                geometry.setAttribute('color', new THREE.BufferAttribute(new Float32Array(color), 4));
                var mesh = new THREE.Points(geometry, material);
                scene.add(mesh);

                // const stats = new Stats();
                // container.appendChild( stats.dom );
            },
            render: () => {
                // 这里必须执行!!重新设置 three 的 gl 上下文状态。
                renderer.state.reset();
                renderer.resetAttributes && renderer.resetAttributes();
                var { near, far, fov, up, lookAt, position } = customCoords.getCameraParams();

                // 2D 地图下使用的正交相机
                // var { near, far, top, bottom, left, right, position, rotation } = customCoords.getCameraParams();

                // console.log(near, far, fov, up, lookAt, position);
                // 这里的顺序不能颠倒,否则可能会出现绘制卡顿的效果。
                camera.near = near;
                camera.far = far;
                camera.fov = fov;
                camera.position.set(...position);
                camera.up.set(...up);
                camera.lookAt(...lookAt);
                camera.updateProjectionMatrix();

                // 2D 地图使用的正交相机参数赋值
                // camera.top = top;
                // camera.bottom = bottom;
                // camera.left = left;
                // camera.right = right;
                // camera.position.set(...position);
                // camera.updateProjectionMatrix();

                renderer.render(scene, camera);
            },
        });
        map.add(gllayer);
    </script>
</body>

</html>

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:8 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
Mugen87commented, Jun 20, 2022

AFAIK three.js does not support shared WebGL environments.

Not true, you can share the same WebGL context over different libraries (e.g. mapbox and three.js).

renderer.state.reset();
renderer.resetAttributes && renderer.resetAttributes();

Can you please replace this code via:

renderer.resetState();

I believe you run into #20549.

0reactions
Phlicesscommented, Jun 20, 2022

It seems the error is fixed with the latest release (r141): https://jsfiddle.net/whk592t8/

#23691 does the trick.

OK~ Good Job !

Read more comments on GitHub >

github_iconTop Results From Across the Web

WebGL Rendering to a Texture
How to render to a texture. ... We just need WebGL to allocate the texture. ... Tell the position attribute how to get...
Read more >
In WebGL - when instancing geometry, is it possible to pass ...
It depends on what you mean by. is it possible to pass per-vertex data for each instance of the geometry that gets rendered?...
Read more >
WebGLRenderer – three.js docs
Returns an object that describes the attributes set on the WebGL context when it was created. # .getActiveCubeFace () : Integer. Returns the...
Read more >
WebGL2 Optimization - Instanced Drawing
WebGL has a feature called instanced drawing. It is basically a way to draw more than one of the same thing faster than...
Read more >
Rendering order in the Built-in Render Pipeline - Unity - Manual
By default, Unity places objects in the render queue specified in their Unity shader. You define this value using the [Queue] SubShader tag....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found