WebGL程序program对象的创建

program对象由顶点着色器对象片元着色器对象构成,因此,创建program对象包含了两部分,一个是着色器对象的创建,一个是program对象的创建。

总体流程

  1. 创建顶点着色器对象
  2. 创建片元着色器对象
  3. 创建program对象
  4. 将顶点着色器和片元着色器添加到程序中
  5. 将程序链接到webgl上下文
  6. 使用创建的program对象

着色器对象的创建

着色器对象的创建包含三步:

  1. 创建着色器对象
  2. 将着色器源码送入对象
  3. 编译着色器

代码实现

/**
* 创建shader对象
* @param {*} gl webgl上下文对象
* @param {*} type 创建的shader的类型,顶点着色器为gl.VERTEX_SHADER,片元着色器为gl.FRAGMENT_SHADER
* @param {*} source glsl源码
*/
function loadShader(gl, type, source) {
// 创建shader
const shader = gl.createShader(type);
// 将glsl源码送入shader对象
gl.shaderSource(shader, source);
// 编译shader
gl.compileShader(shader); // 检查shader是否编译成功
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert("编译shader时发生错误:" + gl.getShaderInfoLog(shader));
// 编译失败,删除shader
gl.deleteShader(shader);
return null;
} return shader;
}

接口

WebGLShader WebGLRenderingContext.createShader(type)

创建一个Shader对象

  • type:为WebGLRenderingContext.VERTEX_SHADERWebGLRenderingContext.FRAGMENT_SHADER中的一个,表示创建的是顶点着色器还是片元着色器

void WebGLRenderingContext.shaderSource(WebGLShader shader, string source)

设置WebGLShader着色器对象的GLSL代码

  • shader:用于设置程序代码的WebGLShader
  • source:包含glsl程序代码的字符串

void WebGLRenderingContext.compileShader(WebGLShader shader)

编译GLSL着色器,使其称为一个二进制数据,然后被WebGLProgram所使用

  • shader:WebGLShader,顶点着色器或片元着色器

Object WebGLRenderingContext.getShaderParameter(WebGLShader shader, pname)

返回给定的着色器信息

  • shader:需要获取信息的着色器对象
  • pname:指定要查询的信息的属性名称,可以是以下值:
    • WebGLRenderingContext.DELETE_STATUS:标识着色器是否被删除,删除GL_TRUE,未删除GL_FALSE
    • WebGLRenderingContext.COMPILE_STATUS:标识着色器是否编译成功,成功GL_TRUE,不成功GL_FALSE
    • WebGLRenderingContext.SHADER_TYPE:标识着色器的类型
      • WebGLRenderingContext.VERTEX_SHADER:顶点着色器
      • WebGLRenderingContext.FRAGMENT_SHADER:片元着色器

Object WebGLRenderingContext.getShaderInfoLog(WebGLShader shader)

获取着色器的信息日志,包含警告、debug和编译信息

  • shader:需要获取信息的着色器对象

void WebGLRenderingContext.deleteShader(WebGLShader shader)

删除参数提供的shader对象,如果该对象已经被删除,这个方法无效

  • shader:需要删除的shader对象

DOMString WebGLRenderingContext.getShaderSource(shader)

以DOMString的形式返回shader的源码

  • shader:WebGLShader,要获取源码的shader

创建着色器程序对象

创建着色器程序对象需要四步:

  1. 创建program对象
  2. 将着色器程序与着色器对象绑定
  3. 将上下文链接到着色器程序
  4. 使用着色器程序

代码实现

/**
* 初始化着色器程序
* @param {*} gl webgl上下文
* @param {*} vsSource 顶点着色器源码字符串
* @param {*} fsSource 片元着色器源码字符串
*/
function initShaderProgram(gl, vsSource, fsSource) {
// 创建着色器对象
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource); // 创建着色器程序
const shaderProgram = gl.createProgram();
// 将着色器程序与shader绑定
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader); // 将上下文链接到着色器程序
gl.linkProgram(shaderProgram); // gl.validateProgram(shaderProgram); // 检查着色器程序是否创建成功
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("初始化着色器程序错误:" + gl.getProgramInfoLog(shaderProgram));
// 如果创建失败,则删除着色器对象和着色器程序对象
gl.deleteProgram(shaderProgram);
gl.deleteShader(vertexShader);
gl.deleteShader(fragmentShader); return null;
} // 使用着色器程序
gl.useProgram(shaderProgram); return shaderProgram;
}

接口

WebGLProgram WebGLRenderingContext.createProgram()

初始化一个WebGLProgram对象

void WebGLRenderingContext.attachShader(program, shader)

向WebGLProgram中添加一个着色器

  • program:WebGLProgram对象
  • shader:WebGLShader对象

void WebGLRenderingContext.linkProgram(program)

链接给定的WebGLProgram,完成为程序的片元顶点着色器准备GPU代码的过程

  • program:WebGLProgram,指定的着色器程序

Object WebGLRenderingContext.getProgramParameter(program, pname)

返回program的信息

  • program:指定的program
  • pname:Glenum,可以是以下类型:
    • WebGLRenderingContext.DELETE_STATUS:GLboolean,是否被删除
    • WebGLRenderingContext.LINK_STATUS:GLboolean,是否成功地链接
    • WebGLRenderingContext.VALIDATE_STATUS:GLboolean,最后一次验证操作是否成功
    • WebGLRenderingContext.ATTACHED_SHADERS:GLint,返回添加的着色器的数量,之后可以使用WebGLRenderingContext.getAttachedShaders()获取这些shader
    • WebGLRenderingContext.ACTIVE_ATTRIBUTES:GLint,返回shader中激活的attribute变量的数量,之后可以使用WebGLRenderingContext.getActiveAttrib()方法获取这些变量
    • WebGLRenderingContext.ACTIVE_UNIFORMS:GLint,返回shader中激活的uniform变量的数量,之后可以使用WebGLRenderingContext.getActiveUniform()方法获取这些变量
    • WebGLRenderingContext.TRANSFORM_FEEDBACK_BUFFER_MODE [ WebGL2 only ]:GLenum,返回transform feedback激活时的buffer mode
      • WebGLRenderingContext.SEPARATE_ATTRIBS
      • WebGLRenderingContext.INTERLEAVED_ATTRIBS
    • WebGLRenderingContext.TRANSFORM_FEEDBACK_VARYINGS [ WebGL2 only ]:GLint,indicating the number of varying variables to capture in transform feedback mode
    • WebGLRenderingContext.ACTIVE_UNIFORM_BLOCKS [ WebGL2 only ]:GLint, indicating the number of uniform blocks containing active uniforms.

Object WebGLRenderingContext.getProgramInfoLog(program)

获取program中的信息,包括在link中的错误以及合法性的检查

  • program:WebGLProgram对象

void WebGLRenderingContext.deleteProgram(program)

删除一个program,如果已经删除,则不会产生任何效果

  • program:WebGLProgram,需要删除的program

void WebGLRenderingContext.useProgram(program)

将定义好的program对象添加到当前的渲染状态中

  • program:WebGLProgram对象

void WebGLRenderingContext.validateProgram(program)

检查program是否链接成功,同时检查能否在当前webgl中使用

注意一点,在WebGLProgram对象创建成功后,加入的WebGLShader对象就没有用了,可以调用deleteShader将其删除,防止占用内内存

【WebGL系列-02】创建program上下文的更多相关文章

  1. webgl 系列 —— 变换矩阵和动画

    其他章节请看: webgl 系列 变换矩阵和动画 动画就是不停地将某个东西变换(transform).例如将三角形不停地旋转就是一个动画 和 CSS transform 类似,变换有三种形式:平移.缩 ...

  2. webgl 系列 —— 渐变三角形

    其他章节请看: webgl 系列 渐变三角形 本文通过一个渐变三角形的示例逐步分析:varying变量.合并缓冲区.图形装配.光栅化.varying 内插 绘制三个点v1 需求:绘制三个相同颜色的点, ...

  3. webgl 系列 —— 绘制猫

    其他章节请看: webgl 系列 绘制猫 上文我们了解了如何绘制渐变彩色三角形,明白了图形装配.光栅化,以及片元着色器计算片元的颜色. 现在如果让你绘制如下一只猫.难道绘制很多三角形,然后指定它们的颜 ...

  4. webgl 系列 —— 着色器语言

    其他章节请看: webgl 系列 着色器语言 本篇开始学习着色器语言 -- GLSL全称是 Graphics Library Shader Language (图形库着色器语言) GLSL 是一门独立 ...

  5. 【三石jQuery视频教程】02.创建 FontAwesome 复选框和单选框

    视频地址:http://v.qq.com/page/m/8/c/m0150izlt8c.html 大家好,欢迎来到[三石jQuery视频教程],我是您的老朋友 - 三生石上. 今天,我们要通过基本的H ...

  6. Aoite 系列(02) - 超动感的 Ioc 容器

    Aoite 系列(02) - 超动感的 Ioc 容器 Aoite 是一个适于任何 .Net Framework 4.0+ 项目的快速开发整体解决方案.Aoite.Ioc 是一套解决依赖的最佳实践. 说 ...

  7. SAP接口编程 之 JCo3.0系列(02) : JCo Client Programming

    SAP接口编程 之 JCo3.0系列(02) : JCo Client Programming 字数545 阅读52 评论0 喜欢1 JCo3.0调用SAP函数的过程 大致可以总结为以下步骤: 连接至 ...

  8. WPF入门教程系列(一) 创建你的第一个WPF项目

    WPF入门教程系列(一) 创建你的第一个WPF项目 WPF基础知识 快速学习绝不是从零学起的,良好的基础是快速入手的关键,下面先为大家摞列以下自己总结的学习WPF的几点基础知识: 1) C#基础语法知 ...

  9. java io系列02之 ByteArrayInputStream的简介,源码分析和示例(包括InputStream)

    我们以ByteArrayInputStream,拉开对字节类型的“输入流”的学习序幕.本章,我们会先对ByteArrayInputStream进行介绍,然后深入了解一下它的源码,最后通过示例来掌握它的 ...

  10. JavaScript进阶系列02,函数作为参数以及在数组中的应用

    有时候,把函数作为参数可以让代码更简洁. var calculator = { calculate: function(x, y, fn) { return fn(x, y); } }; var su ...

随机推荐

  1. win10环境下 VMware Workstation Pro 安装centos7无法上网

    一.安装centos7 网上类似的教程太多了,我就不一一写了,提供两个网址,先按照教程安装 VMware Workstation Pro ,秘钥在第二个链接里面(亲测可用), 安装完VMware在根据 ...

  2. Jmeter小白使用攻略

    <Jmeter小白使用攻略> 一.主界面 二.如何测试一个接口

  3. 可视化—gojs 超多超实用经验分享(一)

    目录 1. 设置分组模板,默认样式,统一最小宽度,展开收起状态监听 2. 分组名称显示成员个数: 分组名称+成员个数: name(children) 3. 分组成员为空时,不显示 placeholde ...

  4. php获取未解码之前的原始接口请求参数

    前言 目前的几个项目,业务方基本都使用POST方式请求接口,我们本机磁盘会保留一份请求的原始参数用于请求分析和问题排查使用,一般有问题,也会基于seqid(请求唯一id)捞到日志,copy参数模拟请求 ...

  5. Protobuf: 高效数据传输的秘密武器

    当涉及到网络通信和数据存储时,数据序列化一直都是一个重要的话题:特别是现在很多公司都在推行微服务,数据序列化更是重中之重,通常会选择使用 JSON 作为数据交换格式,且 JSON 已经成为业界的主流. ...

  6. 2022-11-18:给定一个数组arr,表示连续n天的股价,数组下标表示第几天 指标X:任意两天的股价之和 - 此两天间隔的天数 比如 第3天,价格是10 第9天,价格是30 那么第3天和第9天的指

    2022-11-18:给定一个数组arr,表示连续n天的股价,数组下标表示第几天 指标X:任意两天的股价之和 - 此两天间隔的天数 比如 第3天,价格是10 第9天,价格是30 那么第3天和第9天的指 ...

  7. 2022-06-04:给定一个数字n,表示一开始有编号1~n的树木,列成一条直线, 给定一个有序数组arr,表示现在哪些树已经没了,arr[i]一定在[1,n]范围, 给定一个数字m,表示你可以补种多

    2022-06-04:给定一个数字n,表示一开始有编号1~n的树木,列成一条直线, 给定一个有序数组arr,表示现在哪些树已经没了,arr[i]一定在[1,n]范围, 给定一个数字m,表示你可以补种多 ...

  8. 2021-12-17:长城守卫军问题。 长城上有连成一排的n个烽火台,每个烽火台都有士兵驻守。 第i个烽火台驻守着ai个士兵,相邻峰火台的距离为1。另外,有m位将军, 每位将军可以驻守一个峰火台,每个

    2021-12-17:长城守卫军问题. 长城上有连成一排的n个烽火台,每个烽火台都有士兵驻守. 第i个烽火台驻守着ai个士兵,相邻峰火台的距离为1.另外,有m位将军, 每位将军可以驻守一个峰火台,每个 ...

  9. 安装Visio 2016与原本的office冲突的最终解决方案

    一. 下载office visio 2016 二. 开始安装 但是提示卸载原本的office 三. 网上找寻答案 于是按照这篇文章https://jingyan.baidu.com/article/1 ...

  10. 使用js闭包封装一个原生的模态框

    现在都是用的是人家封装的框架什么的,但是对于底层的了解也是必须的,不然就无法提升,下面分享一个2 years ago 自己封装的一个提示框 样式很简单(适用于任何分辨率) 具体代码如下 /** * 该 ...