2019年7月29日 星期一

多個 WebGLRenderContext 的問題

多個 WebGLRenderContext 的問題

前言

  在 Canvas2D 時沒有所謂的 Canvas 製造的資源,但 WebGLRenderContext 卻會有,如 VBO、  IBO 與 Texture ...等,這些資源能給同一個網頁的其它  WebGLRenderContext 使用嗎?會有這樣的疑問主要是因為要用 Electron 做一個遊戲編輯器,初步的版面配置如下
遊戲編輯器的版面配置
其中 GameView 與 ResourceView 都是 WebGLRenderContext ,GameView 用來顯示場景, ResourceView 用來顯示 Texture 或 Mesh 之類的資源,這樣的狀況就會發生需要多個 WebGLRenderContext 的狀況,在此把學習的過程做個紀錄。

內容

  在google後沒找到明確的答案,所以就直接寫一個範例直接實驗,這次的範例主要參考
Drawing a triangle with WebGL ,範例如下
HTML 的部分
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
<canvas id="myCanvas1" width=400 height=300></canvas>
<canvas id="myCanvas2" width=400 height=300></canvas>
</body>
</html>

JavaScript 的部分
let canvas1 = document.getElementById('myCanvas1');
let glCTX1 = canvas1.getContext('webgl');
let canvas2 = document.getElementById('myCanvas2');
let glCTX2 = canvas2.getContext('webgl');
//Create vertex buffer from glCTX1
let globalVertexBuf = glCTX1.createBuffer();
glCTX1.bindBuffer(glCTX1.ARRAY_BUFFER, globalVertexBuf);
glCTX1.bufferData(
  glCTX1.ARRAY_BUFFER, 
  new Float32Array([ 0.0,1.0,0.0,  -1.0,-1.0,0.0,  1.0,-1.0,0.0 ]), 
  glCTX1.STATIC_DRAW
);

function simpleDraw(glContext,vbo){
  let vertShader = glContext.createShader(glContext.VERTEX_SHADER);
  glContext.shaderSource(
    vertShader , 
    'attribute vec3 pos;void main(void){gl_Position=vec4(pos, 1.0);}'
  );
  glContext.compileShader(vertShader);
  let fragShader = glContext.createShader(glContext.FRAGMENT_SHADER);
  glContext.shaderSource(
    fragShader, 
    'void main(void){gl_FragColor=vec4(1,1,1,1);}'
  );
  glContext.compileShader(fragShader);
  let prog = glContext.createProgram();
  glContext.attachShader(prog, vertShader);
  glContext.attachShader(prog, fragShader);
  glContext.linkProgram(prog);
  glContext.useProgram(prog);
  //
  glContext.viewport(0,0,glContext.canvas.width,glContext.canvas.height);
  glContext.clearColor(0, 0, 1, 1);
  glContext.clear(glContext.COLOR_BUFFER_BIT);
  //
  if(vbo){
    glContext.bindBuffer(glContext.ARRAY_BUFFER, vbo);
  }
  else{
    let vertexBuf = glContext.createBuffer();
    glContext.bindBuffer(glContext.ARRAY_BUFFER, vertexBuf);
    glContext.bufferData(
      glContext.ARRAY_BUFFER, 
      new Float32Array([ 0.0,0.5,0.0,  -0.5,-0.5,0.0,  0.5,-0.5,0.0 ]), 
      glContext.STATIC_DRAW
    );
  }
  //
  let posLoc = glContext.getAttribLocation(prog, "pos");
  glContext.vertexAttribPointer(posLoc, 3, glContext.FLOAT, false, 0, 0);
  glContext.enableVertexAttribArray(posLoc);

  glContext.drawArrays(glContext.TRIANGLES, 0, 3);
}

simpleDraw(glCTX1);
simpleDraw(glCTX2,globalVertexBuf);

程式會透過 simpleDraw() 來繪製一個三角形,如果 vbo 沒輸入的話會自己建一個, globalVertexBuf 從 glCTX1 製作,用來實驗  glCTX1  的資源是否可以給  glCTX2 使用,最後看到 simpleDraw() 的喚起,第二個喚起會將 globalVertexBuf 傳入來繪製,也是本次實驗的重點,執行的結果如下
範例的執行結果

不幸的是"不行", WebGLRenderContext 各自的資源只能給自己用,看來遊戲編輯器的版面配置必須邀遷就這個特性改變了。

參考資料

Drawing a triangle with WebGL

沒有留言:

張貼留言