Colors 如何正确混合两个三角形的颜色并删除对角线涂抹

Colors 如何正确混合两个三角形的颜色并删除对角线涂抹,colors,glsl,webgl,gradient,linear-interpolation,Colors,Glsl,Webgl,Gradient,Linear Interpolation,我正在学习WebGL,我已经画了一个全屏的四边形,每个顶点都有颜色。无照明、法线、透视矩阵或深度缓冲区;我只是画一个渐变背景。这就是我得到的: 看起来不错,但我忍不住注意到从右下角到左上角的对角线涂抹。我觉得这是对远相反顶点进行线性插值的产物。我画了两个三角形:左下角和右上角。我想用OpenGL而不是WebGL会得到类似的结果 给定相同的四种颜色和相同大小的矩形,有没有办法渲染它,使两个三角形之间的边不那么明显?也许更多的顶点,或者不同的混合函数?我不确定每个像素的颜色应该是什么;我只想知道如

我正在学习WebGL,我已经画了一个全屏的四边形,每个顶点都有颜色。无照明、法线、透视矩阵或深度缓冲区;我只是画一个渐变背景。这就是我得到的:

看起来不错,但我忍不住注意到从右下角到左上角的对角线涂抹。我觉得这是对远相反顶点进行线性插值的产物。我画了两个三角形:左下角和右上角。我想用OpenGL而不是WebGL会得到类似的结果


给定相同的四种颜色和相同大小的矩形,有没有办法渲染它,使两个三角形之间的边不那么明显?也许更多的顶点,或者不同的混合函数?我不确定每个像素的颜色应该是什么;我只想知道如何去除对角线涂抹。

问题是右上角三角形不知道左下角,因此右上角三角形不包括左下角的任何蓝色(反之亦然)

有几种方法可以解决这个问题

一种是使用2x2纹理进行线性采样。你必须做一些额外的数学来得到正确的插值,因为纹理只在像素之间插值

+-------+-------+
|       |       |
|   +-------+   |
|   |   |   |   |
+---|---+---|---+
|   |   |   |   |
|   +-------+   |
|       |       |
+-------+-------+
上面是一个4像素的纹理,延伸到14×6。采样发生在像素之间,因此只有该中心区域将获得渐变。在该区域之外,将使用纹理之外的像素进行采样,因此使用REPEAT或在纹理的另一侧使用REPEAT

const gl=document.querySelector('canvas').getContext('webgl');
常数tl=[254,217,138];
常数tr=[252252252252];
常数bl=[18,139,184];
常数br=[203,79,121];
常量tex=gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D,tex);
gl.pixelStorei(gl.UNPACK_校准,1);
gl.texImage2D(
gl.U 2D,
0,//mip级别
gl.RGB,//内部格式
2,//宽度,
2、//高度,
0,//边框
gl.RGB,//格式
gl.UNSIGNED_字节,//类型
新的UINT8阵列([…bl,…br,…tl,…tr]);
gl.texParameteri(gl.TEXTURE_2D、gl.TEXTURE_WRAP_S、gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE\u 2D、gl.TEXTURE\u WRAP\u T、gl.CLAMP\u至边缘);
gl.texParameteri(gl.TEXTURE\u 2D,gl.TEXTURE\u MIN\u过滤器,gl.LINEAR);
gl.texParameteri(gl.TEXTURE\u 2D,gl.TEXTURE\u MAG\u过滤器,gl.LINEAR);
常数vs=`
属性向量4位置;
属性向量2 texcoord;
可变矢量2 v_texcoord;
void main(){
gl_位置=位置;
v_texcoord=texcoord;
}
`;
常数fs=`
精密中泵浮子;
可变矢量2 v_texcoord;
常量vec2 texSize=vec2(2,2);//我可以把这个传进来吗
均匀采样2d-tex;
void main(){
gl_FragColor=纹理2d(tex,
(v_texcoord*(texSize-1.0)+0.5)/texSize);
}
`;
const program=twgl.createProgram(gl[vs,fs]);
const positionLoc=gl.getAttriblLocation(程序“位置”);
const texcoordLoc=gl.getAttribLocation(程序“texcoord”);
函数createBufferAndSetupAttribute(loc,数据){
const buffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY\u BUFFER,BUFFER);
总账缓冲数据(总账数组缓冲区、新Float32Array(数据)、总账静态绘图);
gl.EnableVertexAttributeArray(loc);
gl.VertexAttribute指针(
loc,
2,//每次迭代2个元素
gl.FLOAT,//缓冲区中的数据类型
false,//规范化
0,//步幅
0,//偏移量
);
}
createBufferAndSetupAttribute(positionLoc[
-1, -1,
1, -1,
-1,  1,
-1,  1,
1, -1,
1,  1,
]);
createBufferAndSetupAttribute(texcoordLoc[
0,  0,
1,  0,
0,  1,
0,  1,
1,  0,
1,  1,
]);
gl.useProgram(程序);
//注意:无需设置采样器统一,因为它是默认设置
//设置为0,这是我们无论如何都要设置的。
gl.绘图阵列(gl.三角形,0,6)
canvas{边框:1px纯黑;}

尺寸编号 应该将四边形的二维坐标空间传递给片段着色器,而不是一维(每个通道)颜色空间

然后,在片段着色器中,您可以在2D空间中执行颜色插值,以消除由于在1D中进行对角线插值而产生的颜色伪影

线性颜色插值的着色器片段,其中
coord2D
是二维坐标空间

pixel = vec4(vec3(mix(
        mix(colors[0], colors[1], coord2D.x),
        mix(colors[2], colors[3], coord2D.x),
        coord2D.y
    )), 1);
改进的颜色插值 当通过RGB值对颜色进行插值时,结果可能会在相反的色调之间在视觉上变暗

一个简单的解决方法是通过在颜色通道值的平方之间插值,使用更接近sRGB颜色模型的近似值。最终输出是插值的平方根

插入片段

pixel = vec4(sqrt(vec3(mix(
        mix(colors[0], colors[1], coord2D.x),
        mix(colors[2], colors[3], coord2D.x),
        coord2D.y
    ))) / 255.0, 1);
请注意,统一
颜色中的颜色通道值位于对数空间中<代码>[R^2,G^2,B^2]
,因此范围从0到65025

例子 在示例中,单击画布在插值方法之间切换

您会注意到,当使用约sRGB时,画布中心朝向中心边缘的亮度不会比角落处可感知的亮度低很多

还请注意,从底部蓝色和redish到顶部橙色和白色的过渡的平衡向下移动,靠近中心。这是因为插值RGB模型将使具有来自2个或多个通道的强分量的颜色变暗,红色、绿色、蓝色和黑色将占主导地位,而黄色、青色、品红和白色则使插值看起来移动并延伸RGB原色

var程序,colorsLoc,modelLoc,loc,text=“interpolation.Click for”,model=“RGB”//或sRGB
const vertSrc=`#版本300 es
vec2垂直;
输出vec2坐标2d;
void main(){
coord2D=verts*0.5+0.5;//转换为四元空间0,0 1,1
gl_位置=向量4(顶点,1,1);
}`;
常量fragSrc=`#版本300 es
#定义channelMax 255.0
//颜色位置索引
#定义TR 3
#定义