1.在html中創建canvas 畫布css
<canvas id="canvas"></canvas>
2.在js中獲取canvas畫布html
const canvas=document.getElementById('canvas’);
3.使用canvas 獲取webgl 繪圖上下文node
const gl=canvas.getContext('webgl’);
4.指定將要用來清空繪圖區的顏色web
gl.clearColor(0,0,0,1);
5.使用以前指定的顏色,清空繪圖區算法
gl.clear(gl.COLOR_BUFFER_BIT);
總體代碼canvas
<canvas id="canvas"></canvas><script> const canvas=document.getElementById('canvas'); canvas.width=window.innerWidth; canvas.height=window.innerHeight; const gl=canvas.getContext('webgl'); gl.clearColor(0,0,0,1); gl.clear(gl.COLOR_BUFFER_BIT);</script>
clearColor(r,g,b,a) 中的參數是紅、綠、藍、透明度,其定義域是[0,1]瀏覽器
css 中有一個「rgba(255,255,255,1)」 顏色,其中r、g、b的定義域是[0,255],這裏要和webgl裏的顏色區分一下。網絡
咱們能夠簡單瞭解一下將css顏色解析爲webgl 顏色的原理:app
const rgbaCSS = "rgba(255,0,0,1)";const reg = RegExp(/\((.*)\)/);const rgbaStr = reg.exec(rgbaCSS)[1];const rgb = rgbaStr.split(",").map((ele) => parseInt(ele));const r = rgb[0] / 255;const g = rgb[1] / 255;const b = rgb[2] / 255;const a = rgb[3]; gl.clearColor(r, g, b, a); gl.clear(gl.COLOR_BUFFER_BIT);
在three.js 裏有一個很是完美的顏色對象-Color,咱們經過這個對象能夠輕鬆的控制顏色。ide
1.引入Color 對象
import { Color } from "https://unpkg.com/three/build/three.module.js";
我這是經過CDN 引入的,這種方法不適用於nodejs,由於nodejs 沒法直接經過網絡路徑請求資源。
2.實例化Color 對象
const color = new Color(1, 0, 0);
3.創建色相偏移動畫
!(function ani() { color.offsetHSL(0.005, 0, 0); gl.clearColor(color.r, color.g, color.b, 1); gl.clear(gl.COLOR_BUFFER_BIT); requestAnimationFrame(ani); })();
關於顏色的操做咱們就說到這,Color 對象還有不少其它方法,能夠在threejs官網查看。
1.在html中創建canvas 畫布
<canvas id="canvas"></canvas>
2.在js中獲取canvas畫布
const canvas=document.getElementById('canvas');
3.使用canvas 獲取webgl 繪圖上下文
const gl=canvas.getContext('webgl');
4.在script中創建頂點着色器和片元着色器,glsl es
//頂點着色器<script id="vertexShader" type="x-shader/x-vertex"> void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); gl_PointSize = 100.0; }</script>//片元着色器<script id="fragmentShader" type="x-shader/x-fragment"> void main() { gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0); }</script>
5.在js中獲取頂點着色器和片元着色器的文本
const vsSource = document.getElementById('vertexShader').innerText;const fsSource = document.getElementById('fragmentShader').innerText;
6.初始化着色器
initShaders(gl, vsSource, fsSource);
7.指定將要用來清空繪圖區的顏色
gl.clearColor(0,0,0,1);
8.使用以前指定的顏色,清空繪圖區
gl.clear(gl.COLOR_BUFFER_BIT);
9.繪製頂點
gl.drawArrays(gl.POINTS, 0, 1);
總體代碼
<canvas id="canvas"></canvas><!-- 頂點着色器 --><script id="vertexShader" type="x-shader/x-vertex"> void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); gl_PointSize = 100.0; }</script><!-- 片元着色器 --><script id="fragmentShader" type="x-shader/x-fragment"> void main() { gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0); }</script><script> // canvas 畫布 const canvas = document.getElementById('canvas'); canvas.width=window.innerWidth; canvas.height=window.innerHeight; // webgl畫筆 const gl = canvas.getContext('webgl'); // 頂點着色器 const vsSource = document.getElementById('vertexShader').innerText; // 片元着色器 const fsSource = document.getElementById('fragmentShader').innerText; // 初始化着色器 initShaders(gl, vsSource, fsSource); // 指定將要用來清理繪圖區的顏色 gl.clearColor(0., 0.0, 0.0, 1.0); // 清理繪圖區 gl.clear(gl.COLOR_BUFFER_BIT); // 繪製頂點 gl.drawArrays(gl.POINTS, 0, 1); function initShaders(gl,vsSource,fsSource){ //建立程序對象 const program = gl.createProgram(); //創建着色對象 const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource); const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource); //把頂點着色對象裝進程序對象中 gl.attachShader(program, vertexShader); //把片元着色對象裝進程序對象中 gl.attachShader(program, fragmentShader); //鏈接webgl上下文對象和程序對象 gl.linkProgram(program); //啓動程序對象 gl.useProgram(program); //將程序對象掛到上下文對象上 gl.program = program; return true; } function loadShader(gl, type, source) { //根據着色類型,創建着色器對象 const shader = gl.createShader(type); //將着色器源文件傳入着色器對象中 gl.shaderSource(shader, source); //編譯着色器對象 gl.compileShader(shader); //返回着色器對象 return shader; }</script>
對於上面的步驟一、二、3,你們應該都比較好理解,接下來我們詳細說一下第4 步,在script 裏用GLSL ES語言寫着色器。
webgl 繪圖須要兩種着色器:
看了這兩個名詞的解釋,我想不少初學者會是懵的。
我給你們翻譯翻譯:
補間動畫你們知道不?頂點着色器裏的頂點就是補間動畫裏的關鍵幀,片元着色器裏的片元就是關鍵幀之間以某種算法算出的插值。固然,我們webgl裏的片元是像素的意思。
再給你們舉一個更簡單、更貼切的例子:
兩點決定一條直線你們知道不?頂點着色器裏的頂點就是決定這一條直線的兩個點,片元着色器裏的片元就是把直線畫到畫布上後,這兩個點之間構成直線的每一個像素。
關於概念我們就說到這,接下來我們說着色器語言。
webgl 的着色器語言是GLSL ES語言
<script id="vertexShader" type="x-shader/x-vertex"> void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); gl_PointSize = 100.0; } </script>
<script id="fragmentShader" type="x-shader/x-fragment"> void main() { gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0); } </script>
void main() {…… } 是主體函數。
在頂點着色器中,gl_Position 是頂點的位置,gl_PointSize 是頂點的尺寸,這種名稱都是固定的,不能寫成別的。
在片元着色器中,gl_FragColor 是片元的顏色。
vec4() 是一個4維矢量對象。
將vec4() 賦值給頂點點位gl_Position 的時候,其中的前三個參數是x、y、z,第4個參數默認1.0,其含義咱們後面會詳解;
將vec4() 賦值給片元顏色gl_FragColor 的時候,其中的參數是r,g,b,a。
至於GLSL ES語言的其它知識,我們會在後面另開一篇詳解,這裏先以入門爲主。
在第6步中,咱們使用了一個自定義的方法initShaders() ,這是用於初始化着色器的,接下來我們詳細說一下。
初始化着色器的步驟:
創建程序對象,目前這只是一個手繪板的外殼。
const shaderProgram = gl.createProgram();
創建頂點着色器對象和片元着色器對象,這是手繪板裏用於接收觸控筆信號的零部件,兩者能夠分工合做,把觸控筆的壓感(js信號)解析爲計算機語言(GLSL ES),而後讓計算機(瀏覽器的webgl 渲染引擎)識別顯示。
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
將頂點着色器對象和片元着色器對象裝進程序對象中,這就完成的手繪板的拼裝。
gl.attachShader(shaderProgram, vertexShader); gl.attachShader(shaderProgram, fragmentShader);
鏈接webgl 上下文對象和程序對象,就像鏈接觸控筆和手繪板同樣(觸控筆裏有傳感器,能夠向手繪板發送信號)。
gl.linkProgram(shaderProgram);
啓動程序對象,就像按下了手繪板的啓動按鈕,使其開始工做。
gl.useProgram(program);
上面第二步中的創建着色對象方法loadShader(),是一個自定義的方法,其參數是(webgl上下文對象,着色器類型,着色器源文件),gl.VERTEX_SHADER 是頂點着色器類型,gl.FRAGMENT_SHADER是片元着色器類型。
function loadShader(gl, type, source) { const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); return shader; }
gl.createShader(type) :根據着色器類型創建着色器對象的方法。
gl.shaderSource(shader, source):將着色器源文件傳入着色器對象中,這裏的着色器源文件就是咱們以前在script 裏用GLSL ES寫的着色程序。
在之後的學習裏,initShaders 會常常用到,因此咱們能夠將其模塊化。
function initShaders(gl,vsSource,fsSource){ //建立程序對象 const program = gl.createProgram(); //創建着色對象 const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource); const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource); //把頂點着色對象裝進程序對象中 gl.attachShader(program, vertexShader); //把片元着色對象裝進程序對象中 gl.attachShader(program, fragmentShader); //鏈接webgl上下文對象和程序對象 gl.linkProgram(program); //啓動程序對象 gl.useProgram(program); //將程序對象掛到上下文對象上 gl.program = program; return true; }function loadShader(gl, type, source) { //根據着色類型,創建着色器對象 const shader = gl.createShader(type); //將着色器源文件傳入着色器對象中 gl.shaderSource(shader, source); //編譯着色器對象 gl.compileShader(shader); //返回着色器對象 return shader; }export {initShaders}
後面在須要的時候,import 引入便可。
import {initShaders} from '../jsm/Utils.js';