WebGL小姐姐教我學畫畫之起手式

初次接觸WebGL,若有錯誤之處歡迎留言,共同窗習進步. vjavascript

WebGL的自畫像

我,WebGL,全名Web Graphics Library,是爲了讓死宅程序猿們(攤手)能在瀏覽器上隨心所欲的畫女友,並還能動手動腳,而屈尊降臨於猿類的世界內。哇哈哈哈哈,快來臣服於我吧,哇嘎嘎嘎嗝~java

WebGL啓動說明書

WebGL小姐姐神通廣大,法力無邊。那咱們怎麼用她來創造一個猿猿幸(有)福(女)美(朋)滿(友)的世界呢?web

首先,咱們須要一個名爲canvas的祭壇,舉行一個召喚WebGL小姐姐的小儀式。canvas

const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
複製代碼

那麼,WebGL小姐姐Get到手了,接下來咱們須要先將兩樣'祭品'交給她的兩名侍女。api

  1. 準備用於建立軀體的原材料和賦予靈魂的色彩兩樣祭品
  • gl_Position是每次繪製的點,是vec4類型,分別空間點(x, y, z)和最後一個w。對於w能夠參考文章Explaining Homogeneous Coordinates & Projective Geometry,能夠理解爲投影儀與空間點的距離,距離不一樣會致使縮放效應,距離遠則投放的物體越大。咱們這裏使用沒有縮放效果的值1.0,並使用了position這個定義的變量值。每次繪製gpu buffer會更新position的值.
const vertexShaderSource = ` precision mediump float; attribute vec2 position; void main(void) { gl_Position = vec4(position.x, position.y, 0.0, 1.0); } `;
複製代碼
  • 每次繪製都會使用glFragColor定義的顏色值,一樣是vec4類型,分別表明(r, g, b, a)
const fragmentShaderSource = ` precision mediump float; void main(void) { gl_FragColor = vec4(0.7, 0.5, 0.38, 0.0); } `
複製代碼

關於precision:因爲openGL沒有聲明float類型的默認精度,因此其姐妹WebGL也就須要爲shader聲明精度。又因爲高精度openGL沒有支持,低精度在手機上能夠有兼容問題,因此默認推薦mediump。參考stackoverflow.com/a/28540641/…Use mediump precision in WebGL when possible瀏覽器

  1. 喚醒侍女並讓她們把祭品處理好
const vertexShader = gl.createShader(gl.VERTEX_SHADER); // 喚醒
gl.shaderSource(vertexShader, vertexShaderSource); // 上交祭品
gl.compileShader(vertexShader); // 處理祭品
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
    // 因爲祭品偶爾不新鮮或者侍女偷懶,咱們要好好確認祭品是否處理完畢
    throw new Error(`Error in compileing vertexShader: ${gl.getShaderInfoLog(vertexShader)}`);
}


const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
    throw new Error(`Error in compileing vertexShader: ${gl.getShaderInfoLog(vertexShader)}`);
}
複製代碼

祭品已準備穩當,接下來就是要請出WebGL小姐姐御用創世神器program並使用祭品開光,而後交與小姐姐手中。bash

const program = gl.createProgram(); // 神器現世
gl.attachShader(program, vertexShader); // 開第一封印:原料
gl.attachShader(program, fragmentShader); // 開第二封印:色開
gl.linkProgram(program); // 交與小姐姐

if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    // 咳咳,因爲神器與祭品偶爾沒法契合,致使神器失效,須要檢查一下 ~_~
    throw new Error(`invalid program: ${gl.getProgramInfoLog(program)}`);
}

複製代碼

注意了注意了,WebGL小姐姐起手式完畢,開天闢地,萬物復甦。咱們如今能夠向她許願,描述咱們心中的猩福世界了~v;v~編輯器

WebGL的許願池上的許願樹

WebGL小姐姐有多個許願池,咱們這裏使用gl.ARRAY_BUFFER。而後告訴神器program怎麼收取願望。學習

const buffer = gl.createBuffer(); // 建立許願樹
gl.bindBuffer(gl.ARRAY_BUFFER, buffer); // 將許願樹種到`ARRAY_BUFFER`這個許願池內

// 獲取神器`program`的`position`之力
const position = gl.getAttribLocation(program, 'position');
// position之力爲2個float類型的數一組,不轉化`buffer`類型,
// 從頭開始,不跳過任何一個願望
gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(position);
複製代碼

WebGl的創世之做

小姐姐迎着絲毫都沒有的狂風,望着漫無編輯器的虛無黑暗,眼角迸發出一絲絲精光,大筆一揮, 左一劃右一揮。webgl

gl.viewport(0, 0, 400, 400);
gl.useProgram(program);

gl.clearColor(255 / 255, 192 / 255, 203 / 255, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

gl.lineWidth(1.5);

const points = new Float32Array([
    -0.9, 0.9,
    0.0, 0.0,
    0.9, -0.9,
]);

gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);
gl.drawArrays(gl.LINE_LOOP, 0, points.length / 2);

gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
    -0.9, -0.9,
    0.0, 0.0,
    0.9, 0.9
]), gl.STATIC_DRAW);
gl.drawArrays(gl.LINE_LOOP, 0, 3);
複製代碼

創世之做在漫天閃電,山崩海嘯之下莊嚴出世!! 登登登,piapia(背景樂)

最後來一張WebGL繪製整個過程的流程圖:

未完待續


本文章首發於本人公衆號:楓之葉


若您能喜歡本文,並欲轉發本文請保留公衆號聲明與公衆號二維碼。謝謝 ^v^

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息