webGL入门-初始化着色器流程

初始化着色器流程

<canvas id="glcanvas" width="640" height="480"></canvas>
复制代码
// 初始化着色器程序,让WebGL知道如何绘制我们的数据
function initShaders(gl, vshader, fshader) {
  // 创建指定类型的着色器
  var vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader);
  var fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader);
  if (!vertexShader || !fragmentShader) {
    return null;
  }

  // s4. 创建 WebGLProgram
  var program = gl.createProgram();
  if (!program) {
    return null;
  }

  // s5. 把 WebGLShader 添加到 WebGLProgram
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);

  // s6. 链接给入的 WebGLProgram 对象,从而完成为程序的片元和顶点着色器准备GPU代码的过程
  gl.linkProgram(program);

  // 检查链接的结果
  var linked = gl.getProgramParameter(program, gl.LINK_STATUS); // 返回WebGLProgram程序对象的信息
  if (!linked) {
    var error = gl.getProgramInfoLog(program); // 返回 WebGLProgram 对象的信息日志
    console.log('Failed to link program: ' + error);
    gl.deleteProgram(program); // 删除 WebGLProgram
    gl.deleteShader(fragmentShader); // 删除 WebGLShader
    gl.deleteShader(vertexShader); // 删除 WebGLShader
    return null;
  }

  if (!program) {
    console.log('Failed to create program');
    return false;
  }

  // s7. 将定义好的 WebGLProgram 对象添加到当前的渲染状态中
  gl.useProgram(program);

  return true;
}

// 创建指定类型的着色器,上传source源码并编译
function loadShader(gl, type, source) {
  // s1. 创建一个 WebGLShader 着色器对象
  var shader = gl.createShader(type);
  if (shader == null) {
    console.log('unable to create shader');
    return null;
  }

  // s2. 设置 WebGLShader 着色器(顶点着色器及片元着色器)的GLSL程序代码。
  gl.shaderSource(shader, source);

  // s3. 编译一个GLSL着色器,使其成为为二进制数据,然后就可以被WebGLProgram对象所使用.
  gl.compileShader(shader);

  // 检查编译结果
  var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS); // 返回着色器的信息
  if (!compiled) {
    var error = gl.getShaderInfoLog(shader); // 返回 WebGLShader 对象的信息日志
    console.log('Failed to compile shader: ' + error);
    gl.deleteShader(shader); // 删除 WebGLShader
    return null;
  }

  return shader;
}
复制代码
  // 顶点着色器程序
  const VSHADER_SOURCE = 
  `void main() {
    gl_Position = vec4(0.0, 0.0, 0.0, 1.0); // 设置坐标
    gl_PointSize = 10.0; // 设置尺寸
  }`

  // 片元着色器程序
  const FSHADER_SOURCE = 
  `void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 设置颜色
  }`

  function main() {
    // 1.获取canvas元素
    const canvas = document.getElementById('glcanvas')

    // 2.获取webgl绘图上下文
    const gl = canvas.getContext('webgl')

    if (!gl) {
      alert('不支持webgl')
      return
    }

    // 初始化着色器
    if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
      console.log('着色器初始化失败')
      return
    }

    // 3.设置背景色(指定清空canvas的颜色)
    gl.clearColor(0.0, 1.0, 0.0, 1.0)

    // 4.清空canvas
    gl.clear(gl.COLOR_BUFFER_BIT)

    // 5.绘制一个点
    gl.drawArrays(gl.POINTS, 0, 1)
  }

  main()
复制代码

分析

上一篇文章中分析了绘制一个点的流程,但是初始化着色器这步是忽略的,现在具体分析着色器的初始化流程

  • 1.创建一个 WebGLShader 着色器对象------gl.createShader
  • 2.设置 WebGLShader 着色器的GLSL程序代码------gl.shaderSource
  • 3.编译一个GLSL着色器,使其成为为二进制数据,然后就可以被WebGLProgram对象所使用------gl.compileShader

  • 4.创建 WebGLProgram 程序对象------gl.createProgram
  • 5.把 WebGLShader 添加到 WebGLProgram------gl.attachShader
  • 6.链接给入的 WebGLProgram 对象,从而完成为程序的片元和顶点着色器准备GPU代码的过程------gl.linkProgram
  • 7.将定义好的 WebGLProgram 对象添加到当前的渲染状态中------gl.useProgram

20180610133650677.jpg

gl.createShader()

WebGLRenderingContext.createShader() 用于创建一个 WebGLShader 着色器对象,该对象可以使用 WebGLRenderingContext.shaderSource() 和 WebGLRenderingContext.compileShader() 方法配置着色器代码

/**
 * @param type 参数为gl.VERTEX_SHADER 或 gl.FRAGMENT_SHADER两者中的一个
 * gl.VERTEX_SHADER   // 用于创建顶点着色器
 * gl.FRAGMENT_SHADER   // 用于创建片段着色器
 */
WebGLShader gl.createShader(type);
复制代码

gl.shaderSource()

WebGLRenderingContext.shaderSource() 方法用于设置 WebGLShader 着色器(顶点着色器及片元着色器)的GLSL程序代码

/**
 * 将source指定的字符串形式的代码传入shader指定的着色器。如果之前已经向shader传入过代码了,旧的代码将会被替代掉
 * @param shader 用于设置程序代码的 WebGLShader (着色器对象)
 * @param source 包含GLSL程序代码的字符串
 */
void gl.shaderSource(shader, source);
复制代码

gl.compileShader()

WebGLRenderingContext.compileShader() 用于编译一个GLSL着色器,使其成为为二进制数据,然后就可以被WebGLProgram对象所使用

/**
 * @param shader 一个片元或顶点着色器 (WebGLShader)
 */
void gl.compileShader(shader)
复制代码

gl.createProgram()

WebGLRenderingContext.createProgram() 方法用于创建和初始化一个 WebGLProgram 对象

WebGLProgram gl.createProgram();
复制代码

gl.attachShader()

WebGLRenderingContext.attachShader() 方法负责往 WebGLProgram 添加一个片段或者顶点着色器

/**
 * @param program 一个 WebGLProgram 对象
 * @param shader 一个类型为片段或者顶点的 WebGLShader
 */
void gl.attachShader(program, shader);
复制代码

gl.linkProgram()

WebGLRenderingContext.linkProgram() 方法链接给定的WebGLProgram,从而完成为程序的片元和顶点着色器准备GPU代码的过程

/**
 * @param program 一个用于链接的 WebGLProgram
 */
void gl.linkProgram(program);
复制代码

gl.useProgram()

WebGLRenderingContext.useProgram() 方法将定义好的 WebGLProgram 对象添加到当前的渲染状态中

/**
 * @param program 需要添加的WebGLProgram对象
 */
void gl.useProgram(program);
复制代码

猜你喜欢

转载自juejin.im/post/7066335207510507534