【零基础学WebGL】绘制矩形

我们先来看一下,最终实现的效果。。。。

【零基础学WebGL】绘制矩形_第1张图片

效果看起来真的很简单。一句css的事,还写一篇文章???

别急着走,往下看,有干货 !!!

接下来,进入正题,一步步分解在WebGL世界如何绘制一个矩形。

第一步 :获取WebGL渲染上下文

这里不过多介绍,主要是使用canvas.getContext API,获取webgl上下文。

const createContext = (id: string, width: number, height: number) => { 
  let element: HTMLElement = document.getElementById("id"); 
  if (element && element.tagName !== "canvas") { 
    console.error(`id ${id} element should be a canvas element`); 
    return; 
  } 
 
  let canvas: HTMLCanvasElement; 
  if (!element) { 
    canvas = document.createElement("canvas"); 
    canvas.width = width; 
    canvas.height = height; 
    document.body.appendChild(canvas); 
  } else { 
    canvas = element as HTMLCanvasElement; 
  } 
 
  const gl = canvas.getContext("webgl"); 
  if (!gl) { 
    console.error("webgl is not supported"); 
    return; 
  } 
 
  return gl; 
}; 

第二步:创建着色器

着色器,是一种运行在gpu上的小程序,负责图形渲染管线的特定环节。着色器本质上是一种输入输出程序。

  • 顶点着色器,从顶点数据中接受输入,通过预定义变量gl_Position指定输出数据;
  • 片元着色器,通过预定义变量gl_FragColor指定输出的颜色。

【零基础学WebGL】绘制矩形_第2张图片

创建着色器之前,先分别为顶点着色器和片元着色器编写一段最简单的GLSL代码(类C语言)。

  • 顶点着色器代码
const vertextSource = ` 
  attribute mediump vec2 aVertexPosition; 
 
  void main(void) { 
    gl_Position = vec4(aVertexPosition, 0, 1.0); 
  } 
`; 

首先,使用关键字attribute声明一个类型为vec2(包含2个float分量的向量类型)的顶点变量aVertexPosition。attribute关键字只能出现在顶点着色器,javascript代码可以通过相关的WebGL API把顶点的数据传递给着色器中attribute变量。

然后,把aVertexPosition转换成vec4类型,赋值给与着色器预置变量gl_Position,指定输出。

  • 片元着色器代码
const fragmentSource = ` 
  precision mediump float; 
  uniform vec4 u_color; 
 
  void main() { 
    gl_FragColor = u_color; 
  } 
`; 

首先,使用关键字uniform声明一个类型为vec4(包含4个float分量的向量类型)的普通变量u_color,这个变量的用处是:接受JavaScript通过webgl api传递过来的值,这里表示一个随机颜色值。

有了着色器代码之后,就可以使用webgl api创建着色器了。

  • webgl提供了WebGLRenderingContext.createShader创建顶点着色器和片元着色器。
  • 然后使用WebGLRenderingContext.shaderSource关联GLSL源代码(着色器语法);
  • 最后通过WebGLRenderingContext. compileShader 编译源代码
const createShader = ( 
  gl: WebGLRenderingContext, 
  type: number, 
  source: string 
) => { 
  const shader = gl.createShader(type); 
  gl.shaderSource(shader, source); 
  gl.compileShader(shader); 
 
  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 
    console.error( 
      "a error occured compiling shader", 
      gl.getShaderInfoLog(shader) 
    ); 
    return; 
  } 
 
  return shader; 
}; 

第三步:创建程序

有了着色器程序之后,需要通过program把它们组合起来。这里比较简单,不过多赘述。

const createProgram = (gl: WebGLRenderingContext, shaders: WebGLShader[]) => { 
  const program = gl.createProgram(); 
  shaders.forEach((shader) => gl.attachShader(program, shader)); 
  gl.linkProgram(program); 
 
  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { 
    console.error( 
      "a error occured linking program ", 
      gl.getProgramInfoLog(program) 
    ); 
    return; 
  } 
 
  gl.useProgram(program); 
  return program; 
}; 
}; 

第四步:着色器变量赋值

着色器程序准备好之后,我们需要通过JavaScript代码给着色器中的变量设置值。

首先,给顶点着色器的顶点属性aVertexPosition赋值,过程遵循如下规则:

  • 创建缓冲对象
  • 把缓冲对象和目标点绑定
  • 给缓冲对象填充数据
  • 获取顶点属性aVertexPosition的索引位置
  • 激活顶点属性
  • 设置aVertexPosition从顶点缓冲对象中取值的方式
 /* ***** 顶点属性设置 ***** */ 
 // 绑定缓冲对象到gl.ARRAY_BUFFER目标点 
 const vertexBuffer = gl.createBuffer(); 
 gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); 
 
 // 给缓冲对象填充数据,矩形的四个顶点坐标 
 const vertexData = [ 
   -1.0, 
   -1.0, 
   1.0, 
   -1.0, 
   -1.0, 
   1.0, 
   1.0, 
   1.0, 
  ]; 
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW); 
 
  // 获取顶点属性的在着色器中的索引,并激活它 
  const aVertexPositionLocation = gl.getAttribLocation( 
    program, 
    "aVertexPosition" 
  ); 
  gl.enableVertexAttribArray(aVertexPositionLocation); 
  
  // 设置顶点属性如何从顶点缓冲对象中取值。每次从数组缓冲对象中读取2个值 
  gl.vertexAttribPointer(aVertexPositionLocation, 2, gl.FLOAT, false, 0, 0); 

接下来,就是片元着色器的u_color变量赋值

/* ***** 颜色设置 ***** */ 
const colorLocation = gl.getUniformLocation(program, "u_color"); 
gl.uniform4f(colorLocation, Math.random(), Math.random(), Math.random(), 1.0); 

第五步:绘制

最终的绘制,只需要调用api WebGLRenderingContext.drawArrays。

gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 

结尾

完整代码,见这里。

你可能感兴趣的:(javascript,开发语言,ecmascript)