• 作者:老汪软件技巧
  • 发表时间:2024-11-01 21:02
  • 浏览量:

webgl介绍什么是webgl

WebGL是一种3D绘图协议,衍生于OpenGLES2.0,可以结合HTML5和JavasSript在网页上绘制和渲染二/三维图形

webgl的应用场景webgl的优势

内嵌在浏览器中,不需要安装任何插件即可运行只需要一个文本编辑器和浏览器,就可以编写三维图形程序

image.png

image.png

webgl开源框架Three.js: JavaScript 3D WebGL库Babylonjs:Web3D图形引擎KickJs:Web的开源图形和游戏引擎ClayGL:构建可扩展的Web3D应用程序PlayCanvas:网络游戏和3D图形引擎WebGLStudio.is和Litescene.is:开源Web 3D图形编辑器和创建器canvas和webgl的区别

canvas是HTML5新增的一个 DOM 元素

用途:显示 二维 和 三维 的图像

绘制:二维图形可以使用(Canvas APl或 WebGL API)三维图形使用 WebGL API

canvas Api提供二维绘图的方式-》canvas.getContext('2d')webgl Api提供三维绘图的方式-》canvas.getContext('webgl')

webgl程序什么是着色器

着色器就是让开发者自己去编写一段程序,用来代替固定染管线,来处理图像的渲染。

衍生可以接什么词__衍生可以替换成哪个词

image.png

image.png

image.png

流程介绍:

image.png

现在我们来绘制一个点

html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Titletitle>
  <script src="../lib/index.js">script>
head>
<body>
  <canvas id="canvas" width="400" height="400">
    此浏览器不支持canvas
  canvas>
body>
html>
<script>
  const ctx = document.getElementById('canvas')
  const gl = ctx.getContext('webgl')
  // 着色器
  // 创建着色器源码
  const VERTEX_SHADER_SOURCE = `
    // 必须要存在 main 函数
    void main() {
      // 要绘制的点的坐标
      gl_Position = vec4(0.0,0.0,0.0,1.0);
      // 点的大小
      gl_PointSize = 30.0;
    }
  `; // 顶点着色器
  //  gl_Position vec4(0.0,0.0,0.0,1.0)  x, y, z, w齐次坐标 (x/w, y/w, z/w)
  // gl_FragColor vec4(1.0,0.0,0.0,1.0) r, g, b, a
  const FRAGMENT_SHADER_SOURCE = `
    void main() {
      gl_FragColor = vec4(1.0,0.0,0.0,1.0);
    }
  `; // 片元着色器
  // 创建着色器
  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)
  // 执行绘制
  // 要绘制的图形是什么, 从哪个开始,   使用几个顶点
  gl.drawArrays(gl.POINTS, 0, 1);
script>

可以看得出来有从创建着色器、编译着色器、创建程序对象这一块的代码是一定的,可以进行封装

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;
}

绘制多个点

html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Titletitle>
  <script src="../lib/index.js">script>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    canvas{
      margin: 50px auto 0;
      display: block;
      background: yellow;
    }
  style>
head>
<body>
  <canvas id="canvas" width="400" height="400">
    此浏览器不支持canvas
  canvas>
body>
html>
<script>
  const ctx = document.getElementById('canvas')
  const gl = ctx.getContext('webgl')
  // 创建着色器源码
  const VERTEX_SHADER_SOURCE = `
    uniform vec4 uPosition;
    // 只传递顶点数据
    attribute vec4 aPosition;
    void main() {
      gl_Position = aPosition; // vec4(0.0,0.0,0.0,1.0)
      gl_PointSize = 10.0;
    }
  `; // 顶点着色器
  const FRAGMENT_SHADER_SOURCE = `
    precision mediump float;
    uniform vec2 uColor;
    void main() {
      gl_FragColor = vec4(uColor.r, uColor.g, 0.0,1.0); // vec4
    }
  `; // 片元着色器
  const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
  const aPosition = gl.getAttribLocation(program, 'aPosition');
  const uColor = gl.getUniformLocation(program, 'uColor')
  const points = []
  ctx.onclick = function(ev) {
    // 坐标
    const x = ev.clientX
    const y = ev.clientY
    const domPosition = ev.target.getBoundingClientRect();
    const domx = x - domPosition.left
    const domy = y - domPosition.top;
    //计算点在canvas的坐标
    /*
    0 200 400
    -1 0 1
    -200 0 200
    -1 0 1
    需要先 -200 (当前画布的宽度) 然后再 除以 200
    1 0 -1
    0 200 400
    200 0 -200 / 200
    需要先让 200 减这个数,然后再 / 200
    * */
    const halfWidth = ctx.offsetWidth / 2
    const halfHeight = ctx.offsetHeight / 2
    const clickX = (domx - halfWidth) / halfWidth
    const clickY = (halfHeight - domy) / halfHeight
    points.push({
      clickX, clickY
    })
    for (let i = 0; i < points.length; i++) {
      gl.vertexAttrib2f(aPosition, points[i].clickX, points[i].clickY)
      gl.uniform2f(uColor, points[i].clickX, points[i].clickY)
      gl.drawArrays(gl.POINTS, 0, 1);
    }
  }
script>