跟着書走,今天該畫點了。
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 的一部分,它由兩個WebGLShader
s (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);