共计 1959 个字符,预计需要花费 5 分钟才能阅读完成。
引子
JavaScript WebGL 绘制一个面之后想着能够尝试简单一点的了,没想到设置色彩的时候又呈现问题了。
- Origin
- My GitHub
设置色彩
在之前的示例中,都是设置繁多的色彩,但每个顶点都能够领有各自的色彩信息。
基于绘制三角形次要有上面几方面变动:
- 数据
- 顶点着色器
- 片元着色器
- 缓冲色彩数据
数据
色彩数据有 4 个重量:R、G、B、A。
let colors = [
1.0, 0.0, 0.0, 1.0, // red
0.0, 1.0, 0.0, 1.0, // green
0.0, 0.0, 1.0, 1.0, // blue
];
顶点着色器
之前都是只提供了地位变量,对于色彩须要提供额定的色彩变量进行存储。此外还须要输入对应的色彩到下一个阶段。
const source = `
attribute vec3 vertexPos;
attribute vec4 vertexColor;
varying vec4 vColor;
void main(void){gl_Position = vec4(vertexPos, 1);
vColor = vertexColor;
}
`;
这外面多了一个 varying
类型的变量,这是一种顶点着色器给片断着色器传值的形式。
片元着色器
片元着色器承受对应的变量也要进行申明。
const fragmentSource = `
precision highp float;
varying vec4 vColor;
void main(void){gl_FragColor = vColor;}
`;
这里呈现了变量,须要用 precision highp float
设置片元着色器的浮点数精度。顶点着色器有默认的精度能够不必显式设置。
缓冲色彩数据
顶点地位数据进行了缓冲,色彩数据也要进行缓冲。
/**
* 缓冲色彩数据
* @param {*} gl WebGL 上下文
* @param {*} shaderProgram 着色器程序
* @param {*} colorData 色彩数据
*/
function setColorBuffers(gl, shaderProgram, colorData) {
// 创立空白的缓冲对象
const buffer = gl.createBuffer();
// 绑定指标
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
// WebGL 不反对间接应用 JavaScript 原始数组类型,须要转换
const dataFormat = new Float32Array(colorData);
// 初始化数据存储
gl.bufferData(gl.ARRAY_BUFFER, dataFormat, gl.DYNAMIC_DRAW);
// 获取对应数据索引,变量跟顶点着色器外面对应
const vertexPos = gl.getAttribLocation(shaderProgram, "vertexColor");
// 解析顶点数据
gl.vertexAttribPointer(vertexPos, 4, gl.FLOAT, false, 0, 0);
// 启用顶点属性,顶点属性默认是禁用的。gl.enableVertexAttribArray(vertexPos);
}
成果
这是示例,成果如下:
发现色彩突变发散开来了,这个是因为在光栅化过程中,转变为像素时对色彩进行了插值。
在程序中只定义了三个顶点的色彩,它们之间像素的色彩会随着像素地位变动,相邻像素之间同一种单色的差值是定值。如果不想要这样的成果,能够在片元着色器中自定义。
动静自定义示例
这是示例,片元着色器次要变动:
const fragmentSource = `
precision highp float;
varying vec4 vColor;
int findMax(float r, float g, float b) {if (r > g && r > b) {return 0;}
if (g > r && g > b) {return 1;}
return 2;
}
void main(void){
float red = vColor.r;
float green = vColor.g;
float blue = vColor.b;
int max = findMax(red, green, blue);
vec4 finalColor = vColor;
if (max == 0) {finalColor = vec4(1.0, 0.0, 0.0, 1.0);
}
else if (max == 1) {finalColor = vec4(0.0, 1.0, 0.0, 1.0);
}
else if (max == 2) {finalColor = vec4(0.0, 0.0, 1.0, 1.0);
}
gl_FragColor = finalColor;
}
`;
findMax
办法会对每个像素的色彩的重量进行比拟,将最终色彩设置为最大的一个重量。上面是成果:
参考资料
- 应用着色器 MDN
- WebGL lessons
- 着色器
- WebGL 根底绘制之三:给物体上色
正文完
发表至: javascript
2022-01-01