webgl学习(二)

跟着书走,今天该画点了。

1、html就不说了,直接把js代码放上来,然后慢慢分析。

// HelloPint2.js (c) 2012 matsuda
// 顶点着色器
var VSHADER_SOURCE = 
  'attribute vec4 a_Position;\n' + // attribute variable
  'void main() {\n' +
  '  gl_Position = a_Position;\n' +
  '  gl_PointSize = 10.0;\n' +
  '}\n'; 

// 片元着色器
var FSHADER_SOURCE = 
  'void main() {\n' +
  '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
  '}\n';

function main() {
  // 获取canvas元素
  var canvas = document.getElementById('webgl');

  // 获取webgl上下文
  var gl = getWebGLContext(canvas);
  if (!gl) {
    console.log('Failed to get the rendering context for WebGL');
    return;
  }

  //初始化着色器
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }

  // Get the storage location of a_Position
  var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  if (a_Position < 0) {
    console.log('Failed to get the storage location of a_Position');
    return;
  }

  // Pass vertex position to attribute variable
  gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);

  // 设置清空用的背景色
  gl.clearColor(0.0, 0.0, 0.0, 1.0);

  // 清空背景色,用上行代码设置的颜色
  gl.clear(gl.COLOR_BUFFER_BIT);
    
  // Draw
  gl.drawArrays(gl.POINTS, 0, 1);
}

2、顶点着色器、片元着色器

// VSHADER_SOURCE 、FSHADER_SOURCE 分别存储的是顶点点着色器与片元着色器的程序,字符串的形式。
// \n有助于定位你的着色器程序运行出错的地方,当然也可以不加了。
var VSHADER_SOURCE = 
//此处是定义了一个 vec4 类型的变量。为的是接受外面传来的位置。
  'attribute vec4 a_Position;\n' + 
  'void main() {\n' +
  '  gl_Position = a_Position;\n' +  //  
  '  gl_PointSize = 10.0;\n' +    //设定点的尺寸
  '}\n'; 
在本地他就是一个字符串,
// Fragment shader program
var FSHADER_SOURCE = 
  'void main() {\n' +
  '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' + //设定点的颜色
  '}\n';

里面的顶点着色器与片元着色器是很复杂的明天开始详细说。

3、获取webgl绘图上下文 

var gl = getWebGLContext(canvas);

4、初始化shader

if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }

这个函数是《webg编程指南》的作者封装的函数。初始化shader不复杂,就是麻烦。

首先字符串是肯定没用滴,得经过一番操作。我这边倒着推。

1)、想要使用着色器,首先要知道哪个函数是‘使用’,传递什么参数。

      答:.useProgram(WebGLProgram )。他的作用是将定义好的WebGLProgram 对象添加到当前的渲染状态中。

2)、WebGLProgram又是啥呐?

答:WebGLProgram 是 WebGL API 的一部分,它由两个WebGLShaders (webgl 着色器)组成,分别为顶点着色器和片元着色器。创建一个 WebGLProgram 需要调用 GL 上下文的createProgram() 方法,然后调用attachShader()方法附加上着色器,之后你才能将它们连接到一个可用的程序。

例:

//创建一个WebGlProgram
var program = gl.createProgram();

// 往WebGlProgram添加预先存在的着色器
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
//用linkProgram()搞成一个可用的程序
gl.linkProgram(program);
//getProgramParameter检测linkProgram()的执行结果
if ( !gl.getProgramParameter( program, gl.LINK_STATUS) ) {
///错误的信息
  var info = gl.getProgramInfoLog(program);
  throw 'WebGL program 不能编译. \n\n' + info;
}

3)、问题2中的attachShader()有两个参数,分别是 WebGLProgram 对象和WebGLShader对象。WebGLProgram对象就是createProgram()返回的。那么WebGLShader对象是啥?

答:要创建一个 WebGLShader 需要使用 .createShader()。然后通过 .shaderSource() 然后挂接GLSL源代码 , 最后调用 .compileShader() 完成着色器(shader)的编译。 此时 WebGLShader 仍不是可用的形式,他需要被添加到一个 WebGLProgram里。

  //创建WebGLShader对象,参数为gl.VERTEX_SHADER(顶点着色器) 或 gl.FRAGMENT_SHADER(片元着色器)两 
 //者中的一个。
  var shader = gl.createShader( type );
 //sourceCode 就是js文件开头存储的顶点着色器与片元着色器(字符串,要与上一行代码的type对应)。
  gl.shaderSource( shader, sourceCode );
//编译
  gl.compileShader( shader );
  //编译结果
  if ( !gl.getShaderParameter(shader, gl.COMPILE_STATUS) ) {
    var info = gl.getShaderInfoLog( shader );
    throw "Could not compile WebGL program. \n\n" + info;
  }

4)、整理得

//已知着色器
var VSHADER_SOURCE = 
  'attribute vec4 a_Position;\n' + // attribute variable
  'void main() {\n' +
  '  gl_Position = a_Position;\n' +
  '  gl_PointSize = 10.0;\n' +
  '}\n'; 

var FSHADER_SOURCE = 
  'void main() {\n' +
  '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
  '}\n';
//已知上下文  
 gl
步骤:
1、将string着色器整理成WebGLShader
   let vertexShader= gl.createShader(gl.VERTEX_SHADER);
   let fragmentShader= gl.createShader(gl.VERTEX_SHADER);

   gl.shaderSource(vertexShader,VSHADER_SOURCE );
   gl.compileShader(shaderSource);

   gl.shaderSource(fragmentShader,FSHADER_SOURCE );
   gl.compileShader(shaderSource);

2、创建WebGLProgram,并将WebGLShader怼进去
   let program= gl.createProgram();

   program.attachShader(program,vertexShader);
   program.attachShader(program,fragmentShader);

   gl.linkProgram(program);

3、使用WebGLProgram
   gl.useProgram(program);


注:看作者的代码发现如果linkProgram()失败了,就删除program、shader
       gl.deleteProgram(program);
       gl.deleteShader(fragmentShader);
       gl.deleteShader(vertexShader);

5、获取着色器中定义的变量

//这是着色器中定义的变量
attribute vec4 a_Position;  
//用这种方法获取WebGLProgram对象中 attribute变量a_Position的位置
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');

6、给attribute变量赋值

 gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);

WebGLRenderingContext.vertexAttrib[1234]f[v]() 是 WebGL API 的方法,可以为顶点attibute变量赋值。

7、最终绘图gl.drawArrays(gl.POINTS, 0, 1);

drawArrays用法

你可能感兴趣的:(webgl)