webgl入门

1-刷底色的基本步骤

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]浏览器

2-灵活操做webgl中的颜色

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官网查看。

3-webgl 的绘图步骤

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语言写着色器。

5-着色器

5-1-着色器的概念

webgl 绘图须要两种着色器:

  • 顶点着色器(Vertex shader):描述顶点的特征,如位置、颜色等。
  • 片元着色器(Fragment shader):进行逐片元处理,如光照。

看了这两个名词的解释,我想不少初学者会是懵的。

我给你们翻译翻译:

补间动画你们知道不?顶点着色器里的顶点就是补间动画里的关键帧,片元着色器里的片元就是关键帧之间以某种算法算出的插值。固然,我们webgl里的片元是像素的意思。

再给你们举一个更简单、更贴切的例子:

两点决定一条直线你们知道不?顶点着色器里的顶点就是决定这一条直线的两个点,片元着色器里的片元就是把直线画到画布上后,这两个点之间构成直线的每一个像素。

关于概念我们就说到这,接下来我们说着色器语言。

5-2-着色器语言

webgl 的着色器语言是GLSL ES语言

  • 顶点着色程序,要写在type=“x-shader/x-vertex” 的script中。
<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>
  • 片元着色程序,要写在type=“x-shader/x-fragment” 的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() ,这是用于初始化着色器的,接下来我们详细说一下。

6-着色器初始化

初始化着色器的步骤:

  1. 创建程序对象,目前这只是一个手绘板的外壳。

    const shaderProgram = gl.createProgram();
  2. 创建顶点着色器对象和片元着色器对象,这是手绘板里用于接收触控笔信号的零部件,两者能够分工合做,把触控笔的压感(js信号)解析为计算机语言(GLSL ES),而后让计算机(浏览器的webgl 渲染引擎)识别显示。

    const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
  3. 将顶点着色器对象和片元着色器对象装进程序对象中,这就完成的手绘板的拼装。

    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
  4. 链接webgl 上下文对象和程序对象,就像链接触控笔和手绘板同样(触控笔里有传感器,能够向手绘板发送信号)。

    gl.linkProgram(shaderProgram);
  5. 启动程序对象,就像按下了手绘板的启动按钮,使其开始工做。

    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写的着色程序。

  • gl.compileShader(shader):编译着色器对象。

在之后的学习里,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';
相关文章
相关标签/搜索