Как мы можем отображать одинаковые объекты на двух холстах в webgl?
Я нахожусь в ситуации, когда у меня два холста, и я хочу отобразить один и тот же объект на обоих холстах (на самом деле мне нужно отображать разные объекты на каждом холсте, но я хочу начать с показа одного и того же объекта на обоих), но я Я не могу этого сделать, может кто-нибудь помочь мне в этом?
Моя попытка сделать это: (у меня есть два холста (canvas и 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>
2 ответа
Нет, к сожалению, вы не можете делиться объектами WebGL между холстами в WebGL 1.0
Что вы пытаетесь достичь?
Некоторые решения:
Сплит 1 холст
Если вам нужно несколько видов, как во многих программах 3D-моделирования, вы можете разделить один холст, используя
gl.enable(gl.SCISSOR_TEST)
,gl.scissor
а такжеgl.viewport
, Вот один примерРисуем на одном холсте, затем копируем на другие холсты
В этом случае вы визуализируете на холст за пределами экрана с помощью WebGL, а затем используете несколько видимых холстов 2d для отображения с помощью 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
визуализировать точно, где какой-то другой элемент.В этом случае вы создаете один холст WebGL размером с окно, а с помощью CSS помещаете его в фоновый режим. Затем вы создаете заполнитель
<div>
или другой элемент, представляющий, где вы хотите, чтобы холст появился.Затем вы можете спросить браузер, где именно находится этот элемент, и использовать эту информацию для установки области просмотра и ножниц, а затем выполнить рендеринг в эту область, чтобы он выглядел так, как будто это холст.
var canvas = document.getElementById("canvas"),
canvas2 = document.getElementById("canvas2");
gl = canvas.getContext("experimental-webgl");
gl2 = canvas.getContext("experimental-webgl");
Я думаю, что вы пропустили ссылку на второй элемент холста