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用法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章