2019年10月7日 星期一

WebGL的繪製線段

WebGL的繪製線段

前言

  最近想整合曲線( Curve )到引擎,需要將曲線( Curve )繪製出來,曲線( Curve )要繪製出來就需要靠繪製大量的直線來實現,但想想自己只有在 OpenGL 與 Direct3D 繪製線段, WebGL 的繪製方法也一樣嗎?在此做個紀錄。

內容

  WebGL 繪製線段的方法和 OpenGL 差不多,有一點不太一樣,就是 WebGL 的繪製線段不能控制線段寬度,這裡提供一個繪製線段的範例,方便日後實驗繪製曲線( Curve )
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>
<br>
<input id="btnUpdate"type="button" value="Update"/>
</body>
</html>

Javascript 的部分
let canvas1 = document.getElementById('myCanvas1');
let glCTX1 = canvas1.getContext('webgl');
let vboPrimitiveCon = 0;
let vbo=createDynamicBuffer(glCTX1);
let shaderProg = createShader(glCTX1);
//
function createShader(glContext){
  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);  
  
  return prog;
}
function createDynamicBuffer(glContext){
  let vertexBuf = glContext.createBuffer();
  glContext.bindBuffer(glContext.ARRAY_BUFFER, vertexBuf);
  let dataArray=new Float32Array([ 
       0.0, 0.5, 0.0,  
      -0.5,-0.5, 0.0,  
      -0.5,-0.5, 0.0,
       0.5,-0.5, 0.0,
       0.5,-0.5, 0.0,
       0.0, 0.5, 0.0
    ]);
  glContext.bufferData(
    glContext.ARRAY_BUFFER, 
    dataArray, 
    glContext.DYNAMIC_DRAW
  );
  vboPrimitiveCon = dataArray.length / 3;
  return vertexBuf;
}
function simpleDraw(glContext){
  glContext.useProgram(shaderProg);
  //
  glContext.viewport(0,0,glContext.canvas.width,glContext.canvas.height);
  glContext.clearColor(0, 0, 1, 1);
  glContext.clear(glContext.COLOR_BUFFER_BIT);
  //
  glContext.bindBuffer(glContext.ARRAY_BUFFER, vbo);
  let posLoc = glContext.getAttribLocation(shaderProg, "pos");
  glContext.vertexAttribPointer(posLoc, 3, glContext.FLOAT, false, 0, 0);
  glContext.enableVertexAttribArray(posLoc);

  glContext.drawArrays(glContext.LINES, 0, vboPrimitiveCon);
}

function myRender(){
  simpleDraw(glCTX1);
  //
  window.requestAnimationFrame(myRender);
}
document.getElementById("btnUpdate").onclick=function(evt){
  let dataArray=new Float32Array([ 
       0.0,-0.5, 0.0,  
      -0.5, 0.5, 0.0,  
      -0.5, 0.5, 0.0,
       0.5, 0.5, 0.0,
       0.5, 0.5, 0.0,
       0.0,-0.5, 0.0
  ]);
  glCTX1.bindBuffer(glCTX1.ARRAY_BUFFER, vbo);
  glCTX1.bufferSubData(glCTX1.ARRAY_BUFFER,0,dataArray);
  vboPrimitiveCon = dataArray.length / 3;
}
window.onload = function(){
  window.requestAnimationFrame(myRender);
  
}


這次的範例從 解決多個 WebGLRenderContext 之間無法共享資源的問題 的範例修改而來,Vertex buffer 的部分採用動態的方式來建造,初始化時會給一個正三角的線段資料,畫面如下
範例執行畫面

範例有個 Update 的按鈕,按下去後會填充倒三角形的資料到 Vertex buffer ,畫面如下
更改Vertex buffer 的線段資料

這次的範例是個開端,之後會再推出繪製曲線( Curve )的範例。

相關文章

解決多個 WebGLRenderContext 之間無法共享資源的問題

沒有留言:

張貼留言