我们如何在webgl中的两个画布中显示相同的对象? [英] How can we have display of same objects in two canvas in webgl?

查看:189
本文介绍了我们如何在webgl中的两个画布中显示相同的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的情况是我有两个画布,我想在两个画布中显示相同的对象(事实上我必须在每个画布中显示不同的对象,但我想从两个画面中显示相同的对象开始) ,但我无法做到这一点,
可能有人请我这样做吗?

I am under a situation that i have two canvas, and i want to display the same object in both canvas (in fact i have to display different objects in each canvas, but i want to start by showing same object in both), but i am not able to do this, could some one please hlep me in doing this ?

我尝试做的是:(我有两个灰色的画布(帆布和帆布2),它在两者中都显示多个方块,但它只显示在一个) ,如何在两者中显示。
我要尝试的代码是:

My try to do it is: (i have two canvas (canvas ans canvas2) in grey and it display mutiple square in both, but it is displayed in only one), how to display in both. My code to try is :

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <script class="WebGL">
        var gl,gl2;
        function createProgram(gl, vertexShader, fragmentShader)
        {
            var vs = gl.createShader(gl.VERTEX_SHADER);
            gl.shaderSource(vs, vertexShader);
            gl.compileShader(vs);

            if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS))
                alert(gl.getShaderInfoLog(vs));
            //////
            var fs = gl.createShader(gl.FRAGMENT_SHADER);
            gl.shaderSource(fs, fragmentShader);
            gl.compileShader(fs);

            if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS))
                alert(gl.getShaderInfoLog(fs));
            program = gl.createProgram();
            gl.attachShader(program, vs);
            gl.attachShader(program, fs);
            gl.linkProgram(program);
            if (!gl.getProgramParameter(program, gl.LINK_STATUS))
                alert(gl.getProgramInfoLog(program));
            return program;
        }
        function createShaderFromScriptElement(gl , shaderName)
        {
            var Shader = document.getElementById(shaderName).firstChild.nodeValue;
            return Shader;
        }
        function start()
        {            
            var canvas = document.getElementById("canvas");
            canvas2 = document.getElementById("canvas2");
            gl = canvas.getContext("experimental-webgl");
            gl2 = canvas2.getContext("experimental-webgl");
            if (!gl) { alert("error while GL load"); }
            if (!gl2) { alert("error while GL load"); }

          //  var vertexShader2 = createShaderFromScriptElement(gl, "2d-vertex-shader");
          //  var fragmentShader2 = createShaderFromScriptElement(gl, "2d-fragment-shader");
              var vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
              var fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");

              var program = createProgram(gl, vertexShader, fragmentShader);

            gl.useProgram(program);
            var positionLocation = gl.getAttribLocation(program, "a_position");
            var colorLocation = gl.getUniformLocation(program, "u_color");
            var resolutionLocation = gl.getUniformLocation(program, "u_resolution");

            var buffer = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
            gl.uniform2f(resolutionLocation, 200, 200);

            gl.enableVertexAttribArray(positionLocation);
            gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
            for (var ii = 0; ii < 5005; ++ii)
            {
                // Setup a random rectangle
                setRectangle(gl, randomInt(300), randomInt(300), 50, 50);
                // Set a random color.
                gl.uniform4f(colorLocation, Math.random(), Math.random(), Math.random(), 1);
                // Draw the rectangle.
                gl.drawArrays(gl.TRIANGLES, 0, 3);
                gl2.drawArrays(gl2.TRIANGLES, 0, 3);
            }
            function randomInt(range)
            {
                return Math.floor(Math.random() * range);
            }

            // Fills the buffer with the values that define a rectangle.
            function setRectangle(gl, x, y, width, height)
            {
                var x1 = x;
                var x2 = x + width;
                var y1 = y;
                var y2 = y + height;
                gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
                   x1, y1,
                   x1, -y1,
                   -x1, y1,
                 ]), gl.STATIC_DRAW);
            }
        }
    </script>
    <script id="2d-vertex-shader" type="x-shader/x-vertex">
        attribute vec2 a_position;
        uniform vec2 u_resolution;

        void main() {
        // convert the rectangle from pixels to 0.0 to 1.0
        vec2 zeroToOne = a_position / u_resolution;

        // convert from 0->1 to 0->2
        vec2 zeroToTwo = zeroToOne * 2.0;

        // convert from 0->2 to -1->+1 (clipspace)
        vec2 clipSpace = zeroToTwo - 1.0;

        gl_Position = vec4(clipSpace* vec2(1, -1), 0, 1);
        }
    </script>

    <script id="2d-fragment-shader" type="x-shader/x-fragment">
        precision mediump float;
        uniform vec4 u_color;

        void main()
        {
          gl_FragColor = u_color;  // green
        }
    </script>
</head>
<body onload="start()">
    <div style="text-align: center">

    </div>
    <table style="width:100%; height: 10%;">

        <tr>
            <td style="width:200px; max-width:200px; background-color:gray ">
                <canvas id="canvas" width="300" height="300"></canvas>
            </td>
            <td style="width:200px; max-width:200px; background-color:gray; ">
                <canvas id="canvas2" width="300" height="300"></canvas>
            </td>
        </tr>
    </table>
</body>
</html>


推荐答案

不,遗憾的是,你无法跨画布共享WebGL对象在WebGL 1.0中

No, unfortunately you can not share WebGL objects across canvases in WebGL 1.0

你想要完成什么?

一些解决方案:


  • 拆分1帆布

  • Split 1 canvas

如果您需要多个视图,例如许多3D建模程序,您可以使用 gl.enable(gl.SCISSOR_TEST)拆分单个画布, gl.scissor gl.viewport 这是一个示例

If you need multiple views like many 3D modeling programs you can split a single canvas using gl.enable(gl.SCISSOR_TEST), gl.scissor and gl.viewport. Here's one example

绘制到一个画布,然后复制到其他画布

Draw to one canvas, then copy to other canvases

在这种情况下,您使用WebGL渲染到屏幕外画布,然后
使用多个可见画布2d画布通过使用
drawImage来显示。

In this case you render to an offscreen canvas with WebGL then use multiple visible canvas 2d canvases to display by using drawImage.

gl = offscreenCanvas.getContext("webgl");
ctx1 = onscreenCanvas1.getContext("2d");
ctx2 = onscreenCanvas2.getContext("2d");

// render whatever you want to appear in onscreenCanvas1
renderScene(scene1Settings, gl);
// copy the result to offscreenCanvas1
ctx1.drawImage(gl.canvas, ...);


// render whatever you want to appear in onscreenCanvas2
renderScene(scene2Settings, gl);
// copy the result to offsceenCanvas2
ctx2.drawImage(gl,canvas, ...);


  • 制作1个画布大小的窗口,把它放在后台,使用第一个技术(剪刀,视口)和 getBoundingClientRect 准确呈现其他元素的位置。

  • Make 1 canvas the size of the window, put it in the background, use the first technique (scissor, viewport) and getBoundingClientRect to render exactly where some other element is.

    在这种情况下,你制作单个WebGL画布,窗口大小为
    ,并使用CSS将其放在后台。然后你创建一个占位符
    < div> 或其他元素来表示你想要画布到
    的位置。

    In this case you make a single WebGL canvas the size of the window and using CSS put it in the background. Then you create a placeholder <div> or other element to represent where you want a canvas to appear.

    然后,您可以向浏览器询问该元素的确切位置,
    使用该信息设置视口和剪刀,然后渲染到
    该区域,使其看起来像是画布

    You can then ask the browser exactly where that element appears and use that info to set the viewport and scissor and then render to that area to make it appear like it's a canvas

    Example1
    Example2

    这篇关于我们如何在webgl中的两个画布中显示相同的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆