Javascript 如何在webgl的两个画布中显示相同的对象?

Javascript 如何在webgl的两个画布中显示相同的对象?,javascript,webgl,webgl-extensions,Javascript,Webgl,Webgl Extensions,我的情况是,我有两个画布,我想在两个画布中显示相同的对象(事实上,我必须在每个画布中显示不同的对象,但我想先在两个画布中显示相同的对象),但我无法做到这一点, 有人能帮我做这件事吗 我的尝试是:(我有两个灰色的画布(canvas ans canvas2),两个画布都显示多个正方形,但只显示一个),如何在两个画布中显示。 我要尝试的代码是: <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"&

我的情况是,我有两个画布,我想在两个画布中显示相同的对象(事实上,我必须在每个画布中显示不同的对象,但我想先在两个画布中显示相同的对象),但我无法做到这一点, 有人能帮我做这件事吗

我的尝试是:(我有两个灰色的画布(canvas ans canvas2),两个画布都显示多个正方形,但只显示一个),如何在两个画布中显示。 我要尝试的代码是:

<!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>

var-gl,gl2;
函数createProgram(gl、vertexShader、fragmentShader)
{
var vs=gl.createShader(gl.VERTEX\u着色器);
gl.shaderSource(vs,vertexShader);
总帐编译主管(vs);
如果(!gl.getShaderParameter(vs,gl.COMPILE_状态))
警报(gl.getShaderInfoLog(vs));
//////
var fs=gl.createShader(gl.FRAGMENT\u着色器);
gl.shaderSource(fs,fragmentShader);
总帐编辑主任(fs);
如果(!gl.getShaderParameter(fs,gl.COMPILE_状态))
警报(gl.getShaderInfoLog(fs));
program=gl.createProgram();
总分类:attachShader(项目,vs);
总承包商助理(项目,财政司);
总账链接程序(程序);
if(!gl.getProgramParameter(程序、总账链接状态))
警报(gl.getProgramInfoLog(程序));
返回程序;
}
函数createShaderFromScriptElement(gl、shaderName)
{
var Shader=document.getElementById(shaderName).firstChild.nodeValue;
返回着色器;
}
函数start()
{            
var canvas=document.getElementById(“canvas”);
canvas2=document.getElementById(“canvas2”);
gl=canvas.getContext(“实验性webgl”);
gl2=canvas2.getContext(“实验性webgl”);
如果(!gl){alert(“gl加载时出错”);}
如果(!gl2){alert(“GL加载时出错”);}
//var vertexShader2=createShaderFromScriptElement(gl,“2d顶点着色器”);
//var fragmentShader2=createShaderFromScriptElement(gl,“2d片段着色器”);
var vertexShader=createShaderFromScriptElement(gl,“2d顶点着色器”);
var fragmentShader=createShaderFromScriptElement(gl,“2d片段着色器”);
var program=createProgram(gl、vertexShader、fragmentShader);
gl.useProgram(程序);
var positionLocation=gl.GetAttriblLocation(程序,“a_位置”);
var colorLocation=gl.getUniformLocation(程序,“u_颜色”);
var resolutionLocation=gl.getUniformLocation(程序,“u_resolution”);
var buffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY\u BUFFER,BUFFER);
gl.uniform2f(决议位置,200200);
gl.EnableVertexAttributeArray(位置位置);
gl.VertexAttribute指针(位置位置,2,gl.FLOAT,false,0,0);
对于(var ii=0;ii<5005;++ii)
{
//设置一个随机矩形
setRectangle(gl,randomInt(300),randomInt(300),50,50);
//设置一个随机颜色。
gl.uniform4f(colorLocation,Math.random(),Math.random(),Math.random(),1);
//画矩形。
总图数组(总图三角形,0,3);
gl2.drawArray(gl2.TRIANGLES,0,3);
}
函数randomInt(范围)
{
返回Math.floor(Math.random()*范围);
}
//用定义矩形的值填充缓冲区。
函数集矩形(总图、x、y、宽度、高度)
{
var-x1=x;
var x2=x+宽度;
变量y1=y;
变量y2=y+高度;
gl.bufferData(gl.ARRAY\u BUFFER,新Float32Array([
x1,y1,
x1,-y1,
-x1,y1,
])、总图、静态图);
}
}
属性向量2 a_位置;
均匀vec2u_分辨率;
void main(){
//将矩形从像素转换为0.0到1.0
vec2 zeroToOne=a_位置/u_分辨率;
//从0->1转换为0->2
vec2 zeroToTwo=zeroToOne*2.0;
//从0->2转换为-1->+1(剪辑空间)
vec2 clipSpace=zeroToTwo-1.0;
gl_Position=vec4(clipSpace*vec2(1,-1),0,1);
}
精密中泵浮子;
均匀的vec4 u_颜色;
void main()
{
gl\u FragColor=u\u color;//绿色
}

我认为您错过了对第二个画布元素的引用

否,不幸的是,您无法在WebGL 1.0中跨画布共享WebGL对象

你想完成什么

一些解决方案:

  • 拆分1个画布

    如果像许多三维建模程序一样需要多个视图,可以使用
    gl.enable(gl.SCISSOR_TEST)
    gl.SCISSOR
    gl.viewport
    拆分单个画布

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

    在这种情况下,您可以使用WebGL渲染到屏幕外画布 使用显示多个可见画布二维画布 绘图图像

    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
    精确渲染其他元素所在的位置

    在本例中,您将创建一个与窗口大小相同的WebGL画布 并使用CSS将其置于背景中。然后创建一个占位符
    或其他元素来表示画布的位置
    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, ...);