「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」
前期练习
OpenGL有内置函数mix
是一个特殊线性插值函数,两个参数值基于第三个参数插值genType mix(genType x,genType y,float a)
,即(x*(1-a)+y*a)
。简单理解就是a
的值决定了x
和y
的强弱关系。a
取值范围在[0,1]
之间,a
值越大,结果值中y
占比会越大;a
值越小,结果值中y
占比会越小;
如下代码使用mix
函数输入两个vec4
向量分别表示红色和白色,a
值从0.1-0.8。可以看到a
值越来越大时最后呈现结果上颜色越来越趋向白色。但a
值是1.0时呈现结果就是白色
void main() {
vec2 uv = gl_FragCoord.xy / iResolution.xy;
gl_FragColor = mix(vec4(1.0,0.0,0.0,1.0),vec4(1.0,1.0,1.0,1.0),0.8);
}
a=0.1 | a=0.5 | a=0.8 | a=1.0 |
---|---|---|---|
mix函数结合绘制形状
前面已知使用公式绘制形状后,下面去实现如何在已有纹理上去覆盖形状内容,得到奇特的图片效果。
圆形混合
已知绘制圆形函数,如sdfCircle
函数所示,但d
值大于0时表示超出了圆的绘制范围,若小于0时表示在圆范围内,及sdfCircle
函数返回值是true/false
。将sdfCircle
函数结果带入到mix
函数作为a
的入参true
是0.0不混合newColor
,1.0表示混合newColor
并且是百分百占比也就是完全显示圆形内容。
bool sdfCircle(vec2 uv,float r){
uv -= 0.5; // x: <-0.5, 0.5>, y: <-0.5, 0.5>
uv.x *= iResolution.x/iResolution.y; // x: <-0.5, 0.5> * aspect ratio, y: <-0.5, 0.5>
uv.x += 0.2;
uv.y -= 0.2;
float d = length(uv) - r;
return d > 0.; // 大于0超出画圆范围,小于0在画圆范围内
}
void main() {
vec2 uv = gl_FragCoord.xy / iResolution.xy;
bool isCircle = sdfCircle(uv,0.25);
vec4 color = texture(iChannel3,uv);
float blackwhite = (color.r + color.g + color.b) * 0.333;
vec3 col = vec3(blackwhite);
vec4 newColor = mix(color,vec4(0.,0.,1.0,1.0),0.5);
// newColor.g = newColor.b;
// newColor.b = newColor.b + 100.0;
gl_FragColor = mix(vec4(col,1.0),newColor,isCircle ? 0.: 1.0);
}
实现结果上圆形图案0.5
透明度覆盖在纹理图片之上。
矩形混合
矩形混合实现方式和圆形是一样的。不同之处在于这里混合覆盖了两个叠加的矩形图形。因为底色纹理是黑色背景,所以如例子中多个矩形叠加混合效果时,红色矩形和绿色矩形分别先和纹理图片混合后再进行两次mix
函数将两个矩阵混合到整体纹理之上。
bool sdfSquare(vec2 uv,float size,float offset){
uv -= 0.5; // x: <-0.5, 0.5>, y: <-0.5, 0.5>
uv.x *= iResolution.x/iResolution.y; // x: <-0.5, 0.5> * aspect ratio, y: <-0.5, 0.5>
uv.x += offset;
uv.y -= offset;
float d = max(abs(uv.x),abs(uv.y)) - size;
return d > 0.; // 大于0超出画圆范围,小于0在画圆范围内
}
void main() {
vec2 uv = gl_FragCoord.xy / iResolution.xy;
// 纹理图片
vec4 color = texture(iChannel3,uv);
float blackwhite = (color.r + color.g + color.b) * 0.333;
vec4 col = vec4(vec3(blackwhite),1.0);
//色块红
bool isRedSquare = sdfSquare(uv,0.3,0.1);
vec4 redColor = mix(color,vec4(0.6118, 0.0824, 0.0824, 1.0),0.5);
//色块绿
bool isGreenSquare = sdfSquare(uv,0.15,-0.25);
vec4 greenColor = mix(color,vec4(0.4, 0.7412, 0.0824, 0.877),0.5);
//混合模式
vec4 square = mix(col,redColor,isRedSquare? 0.: 0.75);
square = mix(square,greenColor,isGreenSquare? 0.: 0.75);
gl_FragColor = square;
}