共计 4576 个字符,预计需要花费 12 分钟才能阅读完成。
纯色三角形
咱们首先借助缓冲区绘制一个三角形:
残缺的代码如下:
<canvas width=200 height=200 style="outline:1px solid gray;">
十分道歉,您的浏览器不反对 canvas!
</canvas>
<!-- 顶点着色器 -->
<script type='x-shader/x-vertex' id='vs'>
attribute vec4 a_position;
void main(){gl_Position=a_position;}
</script>
<!-- 片段着色器 -->
<script type='x-shader/x-fragment' id='fs'>
precision mediump float;
uniform vec4 u_color;
void main(){gl_FragColor=u_color;}
</script>
<script>
var gl = document.getElementsByTagName('canvas')[0].getContext('webgl');
var loadShader = function (type, source) {var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
return shader;
};
var vertexShader = loadShader(gl.VERTEX_SHADER, document.getElementById('vs').innerHTML),
fragmentShader = loadShader(gl.FRAGMENT_SHADER, document.getElementById('fs').innerHTML);
var glProgram = gl.createProgram();
gl.attachShader(glProgram, vertexShader);
gl.attachShader(glProgram, fragmentShader);
gl.linkProgram(glProgram);
gl.useProgram(glProgram);
// 设置三角形的色彩(红色)var u_color = gl.getUniformLocation(glProgram, 'u_color');
gl.uniform4f(u_color, 1, 0, 0, 1);
// 创立缓冲区
var buffer = gl.createBuffer();
// 把缓冲区对象绑定到指标
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
// 筹备好点的数据
var data = new Float32Array([
-0.7, -0.7, 0,
0.7, -0.7, 1,
0, 0.7, 0
]);
// 写入数据到缓冲区
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
// 获取变量地位
var a_position = gl.getAttribLocation(glProgram, "a_position");
// 把缓冲区对象调配给指标变量
gl.vertexAttribPointer(a_position, 3, gl.FLOAT, false, data.BYTES_PER_ELEMENT * 3, 0);
// 连贯指标对象和缓冲区对象
gl.enableVertexAttribArray(a_position);
// 绘制一个三角形
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
接着,咱们未来解读下面这段代码。
着色器
三角形一共有 3 个点,因而不能再写死了,须要定义变量应用缓冲区进行传递,顶点着色器批改如下:
attribute vec4 a_position;
void main(){gl_Position=a_position;}
尽管三角形是纯色的,色彩能够写死,不过咱们想演示一下如何通过变量设置色彩,因而片元着色器也进行批改:
precision mediump float;
uniform vec4 u_color;
void main(){gl_FragColor=u_color;}
设置单个色彩
和点不同,色彩就一个值,无需借助缓冲区,比较简单,咱们先看下具体代码:
var u_color = gl.getUniformLocation(glProgram, 'u_color');
gl.uniform4f(u_color, 1, 0, 0, 1);
色彩值是 rgba(1,0,0,1),也就是不通明的红色。
借助缓冲区设置点
首先,筹备好缓冲区对象:
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
而后,筹备好数据,并写入缓冲区中:
var data = new Float32Array([
-0.7, -0.7, 0,
0.7, -0.7, 1,
0, 0.7, 0
]);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
最初,把缓冲区中的数据调配给点变量 a_position 即可:
var a_position = gl.getAttribLocation(glProgram, "a_position");
gl.vertexAttribPointer(a_position, 3, gl.FLOAT, false, data.BYTES_PER_ELEMENT * 3, 0);
gl.enableVertexAttribArray(a_position);
绘制
gl.drawArrays(gl.TRIANGLES, 0, 3);
如此,一个红色的三角形就画好了。那么,既然点能够传递 3 个,可不可以每个点的色彩也能够不一样?当然能够了。
渐变色三角形
当初,咱们再把这个三角形变成渐变色的,先看看最终成果:
同样的,先看看残缺代码,后续咱们一一进行必要的解释:
<canvas width=200 height=200 style="outline:1px solid gray;">
十分道歉,您的浏览器不反对 canvas!
</canvas>
<!-- 顶点着色器 -->
<script type='x-shader/x-vertex' id='vs'>
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 v_color;
void main(){
gl_Position=a_position;
v_color=a_color;
}
</script>
<!-- 片段着色器 -->
<script type='x-shader/x-fragment' id='fs'>
precision mediump float;
varying vec4 v_color;
void main(){gl_FragColor=v_color;}
</script>
<script>
var gl = document.getElementsByTagName('canvas')[0].getContext('webgl');
var loadShader = function (type, source) {var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
return shader;
};
var vertexShader = loadShader(gl.VERTEX_SHADER, document.getElementById('vs').innerHTML),
fragmentShader = loadShader(gl.FRAGMENT_SHADER, document.getElementById('fs').innerHTML);
var glProgram = gl.createProgram();
gl.attachShader(glProgram, vertexShader);
gl.attachShader(glProgram, fragmentShader);
gl.linkProgram(glProgram);
gl.useProgram(glProgram);
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
// 筹备好点的数据
var data = new Float32Array([
-0.7, -0.7, 0, 1, 0, 0,
0.7, -0.7, 1, 0, 1, 0,
0, 0.7, 0, 0, 0, 1
]);
// 写入数据到缓冲区
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
// 点的地位
var a_position = gl.getAttribLocation(glProgram, "a_position");
gl.vertexAttribPointer(a_position, 3, gl.FLOAT, false, data.BYTES_PER_ELEMENT * 6, 0);
gl.enableVertexAttribArray(a_position);
// 点的色彩
var a_color = gl.getAttribLocation(glProgram, "a_color");
gl.vertexAttribPointer(a_color, 3, gl.FLOAT, false, data.BYTES_PER_ELEMENT * 6, data.BYTES_PER_ELEMENT * 3);
gl.enableVertexAttribArray(a_color);
// 绘制一个三角形
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
应用缓冲区设置点的色彩
着色器
只有顶点着色器能够传递多个数据,因而,须要先革新顶点着色器后通过管道实现:
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 v_color;
void main(){
gl_Position=a_position;
v_color=a_color;
}
而后,片段着色器借助桥梁进行接管:
precision mediump float;
varying vec4 v_color;
void main(){gl_FragColor=v_color;}
这里的 varying 类型的变量就相当于桥梁,当然,桥梁能够有多个。
借助缓冲区设置色彩
点的设置和之前一样,咱们只须要批改一下点色彩的设置即可:
var a_color = gl.getAttribLocation(glProgram, "a_color");
gl.vertexAttribPointer(a_color, 3, gl.FLOAT, false, data.BYTES_PER_ELEMENT * 6, data.BYTES_PER_ELEMENT * 3);
gl.enableVertexAttribArray(a_color);
余下的,就和之前一样了。
正文完