日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

?前言

大部分公司的都會有可視化的需求,但是用echarts,antv等圖表庫,雖然能快速產出成果,但是還是要知道他們底層其實用canvas或svg來做渲染,canvas瀏覽器原生支持,h5天然支持的接口,而svg相比矢量化,但是對大體量的點的處理沒有canvas好,但是可以操作dom等優勢。canvas和svg我們一般只能做2d操作,當canvas.getContext('webgl')我們就能獲取webgl的3d上下文,通過glsl語言操作gpu然后渲染了。理解webgl,可以明白h5的很多三維的api底層其實都是webgl實現,包括對canvas和svg也會有新的認知。

canvas和webgl的區別

canvas和webgl都可以做二維三維圖形的繪制。底層都會有對應的接口獲取。cancvas一般用于二維canvas.getContext("2d")?,三維一般可以通過canvas.getContext('webgl')

窺探WebGL

理解建模

如果你有建模軟件基礎的話,相信3dmax、maya、su等軟件你一定不會陌生,本質其實就是點、線、面來組成千變萬化的事物。打個比方球體就是無數個點連成線然后每三根線形成面,當然有常見的四邊形,其實也是兩個三邊形組成,為什么不用四邊形,因為三邊形更穩定、重心可計算、數據更容易測算。

所以核心也就是點、線、三角面

了解WebGL

WebGL可以簡單理解為是openGL的拓展,讓web端通過js可以有強大的圖形處理能力。當然為了與顯卡做交互你必須得會glsl語言。

GLSL

glsl著色器語言最重要的就是頂點著色器和片元著色器。簡單理解為一個定位置一個添顏色。

簡單繪制一個點

webgl會有大量的重復性前置工作,也就是創建著色器 -> 傳入著色器源碼 -> 編譯著色器 -> 創建著色器程序 -> 綁定、連接、啟用著色器 -> 可以繪制了!

一般而言我們是不會重復寫這個東西,封裝好了直接調用就行。

function initShader (gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE) {
    const vertexShader = gl.createShader(gl.VERTEX_SHADER);

    const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

    gl.shaderSource(vertexShader, VERTEX_SHADER_SOURCE);
    gl.shaderSource(fragmentShader, FRAGMENT_SHADER_SOURCE);

    //編譯著色器
    gl.compileShader(vertexShader);
    gl.compileShader(fragmentShader);

    //創建程序對象
    const program = gl.createProgram();

    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);

    gl.linkProgram(program);
    gl.useProgram(program);

    return program;
}
 
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./initShader.js"></script>
</head>

<body>
  <canvas id="canvas" width="300" height="400">
    不支持canvas
  </canvas>
</body>

<script>
  const ctx = document.getElementById('canvas')
  const gl = ctx.getContext('webgl')

  //著色器: 通過程序用固定的渲染管線,來處理圖像的渲染,著色器分為兩種,頂點著色器:頂點理解為坐標,片元著色器:像素

  //頂點著色器源碼
  const VERTEX_SHADER_SOURCE = `
    void main() {
      gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
      gl_PointSize = 10.0;
    }  
  `
  //片元著色器源碼
  const FRAGMENT_SHADER_SOURCE = `
    void main() {
      gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }   
  `
  //創建著色器
  const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)

  //執行繪制
  gl.drawArrays(gl.POINTS, 0, 1)
  //gl.drawArrays(gl.LINES, 0, 1)
  //gl.drawArrays(gl.TRIANGLES, 0, 1)

</script>

</html>

繪制效果如下:

圖片

相信看了上面有段代碼會有疑惑

圖片

gl_position代表坐標,vec4就一個存放個4個float的浮點數的容量,定義坐標, 分別對應x、y、z、w,也就是三維坐標,但是w就等于比例縮放xyz而已,一般在開發中,我們的瀏覽器的坐標要跟這個做個轉換對應上,gl_POintSize是點的大小,注意是浮點數

 

圖片

 

gl_flagColor渲染的像素是紅色,是因為這類似于比例尺的關系需要做個轉換, (R值/255,G值/255,B值/255,A值/1) ->(1.0, 0.0, 0.0, 1.0)

繪制動態點

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./initShader.js"></script>
</head>

<body>
  <canvas id="canvas" width="300" height="400">
    不支持canvas
  </canvas>
</body>

<script>
  const canvas = document.getElementById('canvas')
  const gl = canvas.getContext('webgl')
    
  const VERTEX_SHADER_SOURCE = `
    precision mediump float;
    attribute vec2 a_Position;
    attribute vec2 a_Screen_Size;
    void main(){
      vec2 position = (a_Position / a_Screen_Size) * 2.0 - 1.0; 
      position = position * vec2(1.0, -1.0);
      gl_Position = vec4(position, 0, 1);
      gl_PointSize = 10.0;
    }  
  `
  const FRAGMENT_SHADER_SOURCE = `
   precision mediump float;
   uniform vec4 u_Color;
   void main() {
    vec4 color = u_Color / vec4(255, 255, 255, 1);
    gl_FragColor = color; 
   }
  `
  //前置工作,著色器可以渲染了!
  const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)

  //獲取glsl的變量對應的屬性做修改
  var a_Position = gl.getAttribLocation(program, 'a_Position');
  var a_Screen_Size = gl.getAttribLocation(program, 'a_Screen_Size');
  var u_Color = gl.getUniformLocation(program, 'u_Color');
  gl.vertexAttrib2f(a_Screen_Size, canvas.width, canvas.height); //給glsl的屬性賦值兩個浮點數
  
  //給個默認背景顏色
  gl.clearColor(0, 0, 0, 1.0);
  gl.clear(gl.COLOR_BUFFER_BIT);

  //存儲點擊位置的數組。
  var points = [];
  canvas.addEventListener('click', e => {
    var x = e.pageX;
    var y = e.pageY;
    var color = { r: Math.floor(Math.random() * 256), g: Math.floor(Math.random() * 256), b: Math.floor(Math.random() * 256), a: 1 };
    points.push({ x: x, y: y, color: color })
        
    gl.clearColor(0, 0, 0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    
    for (let i = 0; i < points.length; i++) {
      var color = points[i].color;
      gl.uniform4f(u_Color, color.r, color.g, color.b, color.a);
      gl.vertexAttrib2f(a_Position, points[i].x, points[i].y);
      gl.drawArrays(gl.POINTS, 0, 1);
    }
  })
</script>

</html>

vec2 position = (a_Position / a_Screen_Size) * 2.0 - 1.0; 注意這里的坐標轉換,從canvas轉為ndc坐標,其實就是看范圍就行,[0, 1] -> [0, 2] -> [-1, 1]。上面總體的流程總結下就是,定義著色器,定義glsl著色器源碼 -> 通過api獲取canvas的信息轉換坐標系 -> 監聽點擊事件傳遞變量到glsl中 -> 通過pointer緩存 -> drawArrays繪制。但是這種方法,很明顯有大量的重復渲染,每次遍歷都要把之前渲染的重復執行。

大致效果

 

圖片

 

總結

通過簡單的webgl入門,已經有了初步的認知,大致的流程為:著色器初始化 -> 著色器程序對象 -> 控制變量 -> 繪制,為了更好的性能,后面會使用緩沖區來解決重復渲染的問題,這樣我們的頂點不會一個一個設置而直接會被緩存,包括后面一些動態效果會涉及到矩陣的轉換,如平移、縮放、旋轉、復合矩陣。

分享到:
標簽:WebGL
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定