1.webgl中实现根据顶点位置,来确定颜色
要实现这个功能的话,重点是gl_FragCoord该内置变量
2.gl_FragCoord
该内置变量的第一个分量,和第二个分量表示
片元在<canvas></canvas>坐标系统中的坐标值。
1.顶点着色器
const VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
'}\n'
很平常的代码,不做解释。
2.片元着色器
var FSHADER_SOURCE =
'precision mediump float;\n' +
'uniform float u_Width;\n' +
'uniform float u_Height;\n' +
'void main() {\n' +
' gl_FragColor = vec4(gl_FragCoord.x/u_Width, 0.0, gl_FragCoord.y/u_Height, 1.0);\n' +
'}\n';
- uniform float u_Width 和 uniform float u_Height;这两个变量,是用来表示webgl的颜色缓冲区的高度,宽度的。因为webgl中的坐标系 x [-1,1] 和 y [-1,1]的
- gl_FragColor = vec4(gl.FragCoord.x / u_Width, 0.0, gl_FragCoord.y / u_Height, 1.0)
是将其压缩到 [-1,1]之间。
3.实例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#canvas {
height: 400px;
width: 400px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const gl = canvas.getContext('webgl');
// console.log(gl, 'gl')
const createShader = (type, source) => {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
const compileState = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!compileState) {
const err = gl.getShaderInfoLog(shader);
console.log('着色器编译报错信息为:' + err);
gl.deleteShader(shader);
return null
}
return shader
}
const VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
'}\n'
var FSHADER_SOURCE =
'precision mediump float;\n' +
'uniform float u_Width;\n' +
'uniform float u_Height;\n' +
'void main() {\n' +
' gl_FragColor = vec4(gl_FragCoord.x/u_Width, 0.0, gl_FragCoord.y/u_Height, 1.0);\n' +
'}\n';
// createShader(gl.FRAGMENT_SHADER, FSHADER_SOURCE)
const ceateProgram = (vshadher, fshader) => {
const vertexShader = createShader(gl.VERTEX_SHADER, vshadher);
const fragmentShader = createShader(gl.FRAGMENT_SHADER, fshader);
console.log(vertexShader, fragmentShader)
if (!vertexShader || !fragmentShader) {
return null
}
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
const linkState = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!linkState) {
const err = gl.getProgramInfoLog(program);
console.log('链接报错'+err)
gl.deleteShader(vertexShader)
gl.deleteShader(fragmentShader);
gl.deleteProgram(program);
alert(66)
}
// alert(program)
// console.log(program, 'program')
gl.program = program
gl.useProgram(program);
}
ceateProgram(VSHADER_SOURCE,FSHADER_SOURCE);
console.log(gl.program, 'gl.program')
const initBuffer = () => {
const buffer = gl.createBuffer();
const data = new Float32Array([
0.5, 0.0,
-0.5, 0.0,
0.0,0.5
])
const size = data.BYTES_PER_ELEMENT;
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
// console.log(a_Position, 'a_Position')
// gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
const u_width = gl.getUniformLocation(gl.program, 'u_Width');
const u_Height = gl.getUniformLocation(gl.program, 'u_Height');
// console.log(u_Height, 'u_Height')
// console.log(u_width, 'u_Height')
gl.uniform1f(u_width, gl.drawingBufferWidth);
gl.uniform1f(u_Height, gl.drawingBufferHeight);
// console.log(gl.drawingBufferHeight, 'gl.drawingBufferHeight')
gl.enableVertexAttribArray(a_Position);
// gl.bindBuffer(gl.ARRAY_BUFFER, null);
// console.log(gl.drawingBufferHeight, 'drawingBufferHeight')
}
initBuffer()
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3)
</script>
</body>
</html>
效果图
一个渐变的三级形.