WebGL Tutorial 绘制第一个三角形

    在三维程序中,绘制第一个三角形就像写一个“Hello World”一样代表的写三维程序的开始,在以往C&C++里用OpenGL绘制一个三角化很容易,但在WebGL里从哪里入手呢?当然,还是先创建VertexBuffer, 然后BindBuffer后Draw一个三角面就可以,但在WebGL里,采用了OpenGL ES2.0的接口,那又如何呢?那必须先写好Shader才可以,怎么WebGL像DirectX 10&11一样啰嗦了?但我觉得这是一个进步,用灵活的可编程Shader代替N多的GL API不是好事么?我比较喜欢简单的程序,相信每个优秀的程序员都喜欢。


1. 创建Shader的function

WebGL有Vertex shader和Fragment shader两种,我们创建一个专门创建和编译Shader的方法:

function buildShader (gl, type, string) {
  var shader;
  if (type === "fragment") {
    shader = gl.createShader(gl.FRAGMENT_SHADER);
  }
  else if (type === "vertex") {
    shader = gl.createShader(gl.VERTEX_SHADER);
  }

  gl.shaderSource(shader, string);
  gl.compileShader(shader);

  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    console.error(gl.getShaderInfoLog(shader));
    console.error(string);
    return null;
  }
  return shader;
}


2. 创建Program的function
有了建好的Shader,我们就可以创建和连接一个Program:

function buildProgram (gl, vertexShader, fragmentShader) {
  var program = gl.createProgram();
  var glVertexShader = buildShader(gl, "vertex", vertexShader);
  var glFragmentShader = buildShader(gl, "fragment", fragmentShader);
  gl.attachShader(program, glVertexShader);
  gl.attachShader(program, glFragmentShader);
  gl.linkProgram(program);

  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
      console.log(fragmentShader);
      console.log(vertexShader);
  }
  
  return program;
}


3. 创建一个简单的Program对像

我们先只写一个最简单的Shader,不用任何顶点变化,基本上是不能再简单了:

var vertexShader =
  'attribute vec4 vPosition;    \n\
   void main()                  \n\
   {                            \n\
      gl_Position = vPosition;  \n\
   }                            \n';
			    
var fragmentShader =
  'precision mediump float; \n\
   void main()                                  \n\
   {                                            \n\
     gl_FragColor = vec4 ( 1.0, 1.0, 0.0, 1.0 );\n\
   }\n';

然后用之前定义的buildProgram来创建Program对像:

program = buildProgram(gl, vertexShader, fragmentShader);


4. 创建VertexBuffer

 在JavaScript无法直接使用二进制数据比较麻烦,但我们可以用Float32Array来创建定点缓存然后交给WebGL,我们首先创建一个Float3dArray:

var vertices = new Float32Array(
                    [0.0, 0.5, 0.0,
                    -0.5, -0.5, 0.0,
                    0.5, -0.5, 0.0]);


然后创建WebGL VBO对像,并把顶点数据交给VBO:

vb = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vb);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);


记得从Program里获得"vPosition"属性的location:

vb.vertexAttribLoc = gl.getAttribLocation(program, "vPosition");

5. 绘制三角形:

剩下的就是绘制三角形了,在之前定义的updateFrame中添加绘制代码,首先是绑定Program:

gl.useProgram(program);


然后绑定VertexBuffer:

gl.bindBuffer(gl.ARRAY_BUFFER, vb);
gl.vertexAttribPointer(vb.vertexAttribLoc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vb.vertexAttribLoc);

最后绘制一个三角形:

gl.drawArrays(gl.TRIANGLES, 0, 3);


在Shader里gl_FragColor被设置成了固定的颜色,你可以随意改,然后只需要刷新下网页就可以,这就是脚本语言最大的魅力,如果不要求大数据和高性能的话。


  




使用 WebGL 绘制正方形需要进行以下步骤: 1. 获取 WebGL 上下文对象 ```javascript const canvas = document.querySelector('canvas'); const gl = canvas.getContext('webgl'); ``` 2. 设置顶点着色器和片元着色器 ```javascript const vertexShaderSource = ` attribute vec2 a_position; void main() { gl_Position = vec4(a_position, 0, 1); } `; const fragmentShaderSource = ` precision mediump float; void main() { gl_FragColor = vec4(1, 0, 0, 1); } `; const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderSource); gl.compileShader(vertexShader); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderSource); gl.compileShader(fragmentShader); ``` 3. 创建着色器程序并链接顶点着色器和片元着色器 ```javascript const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); gl.useProgram(program); ``` 4. 创建缓冲区并绑定数据 ```javascript const positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); const positions = [ -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); ``` 5. 设置顶点属性指针并启用 ```javascript const positionAttributeLocation = gl.getAttribLocation(program, 'a_position'); gl.enableVertexAttribArray(positionAttributeLocation); gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0); ``` 6. 清空画布并绘制正方形 ```javascript gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); ``` 完整的 WebGL 绘制正方形的代码如下: ```javascript const canvas = document.querySelector('canvas'); const gl = canvas.getContext('webgl'); const vertexShaderSource = ` attribute vec2 a_position; void main() { gl_Position = vec4(a_position, 0, 1); } `; const fragmentShaderSource = ` precision mediump float; void main() { gl_FragColor = vec4(1, 0, 0, 1); } `; const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderSource); gl.compileShader(vertexShader); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderSource); gl.compileShader(fragmentShader); const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); gl.useProgram(program); const positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); const positions = [ -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); const positionAttributeLocation = gl.getAttribLocation(program, 'a_position'); gl.enableVertexAttribArray(positionAttributeLocation); gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0); gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); ``` 这样就可以在 canvas 中绘制一个红色的正方形了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值