Glsl 如何使用着色器控制顶点之间的颜色?

Glsl 如何使用着色器控制顶点之间的颜色?,glsl,shader,webgl,fragment-shader,Glsl,Shader,Webgl,Fragment Shader,有没有办法用着色器控制顶点之间的颜色? 就像经典教程中在屏幕上绘制三角形一样,顶点具有相应的红色、绿色和蓝色。中间的值是插值的。 除了修改几何体和在内部添加更多顶点之外,还有其他方法可以控制中间地带的颜色吗?为三角形着色最常用的方法是。第二种最常见的方法是添加顶点。正如@derhass所指出的,理论上你可以创建一个片段着色器,它可以改变中间部分的颜色。但要做到这一点,需要为片段着色器提供更多数据,因为片段着色器不知道正在绘制三角形的哪个像素。因此,即使在技术上不添加更多顶点,最终也会向几何体添加

有没有办法用着色器控制顶点之间的颜色? 就像经典教程中在屏幕上绘制三角形一样,顶点具有相应的红色、绿色和蓝色。中间的值是插值的。
除了修改几何体和在内部添加更多顶点之外,还有其他方法可以控制中间地带的颜色吗?

为三角形着色最常用的方法是。第二种最常见的方法是添加顶点。正如@derhass所指出的,理论上你可以创建一个片段着色器,它可以改变中间部分的颜色。但要做到这一点,需要为片段着色器提供更多数据,因为片段着色器不知道正在绘制三角形的哪个像素。因此,即使在技术上不添加更多顶点,最终也会向几何体添加更多数据以实现这一点

此外,您提出的任何解决方案都可能相当不灵活,因为使用纹理(最常见的着色方式)会给您带来大量灵活性。例如,你可以制作一个片段着色器,让你在三角形中间选取1个新的颜色。
const gl=document.querySelector('canvas').getContext('webgl');
常数vs=`
属性向量4位置;
属性向量4颜色;
属性向量3角;
可变的vec4 v_颜色;
可变vec3 v_角;
void main(){
gl_位置=位置;
v_color=颜色;
v_角=角;
}
`;
常数fs=`
高精度浮点;
可变的vec4 v_颜色;
可变vec3 v_角;
//可能是制服
常数vec4 centerColor=vec4(0,1,0,1);
void main(){
vec3中心=vec3(1.0/3.0);
浮动边=距离(中心、v_角)/0.75;
gl_FragColor=混合(中心颜色、v_颜色、边缘);
}
`;
常量prg=twgl.createProgram(gl[vs,fs]);
const posLoc=gl.getAttriblLocation(prg,“位置”);
const colorLoc=gl.getAttribLocation(prg,“color”);
const cornerLoc=gl.getAttribLocation(prg,'corner');
函数createBufferAndSetupAttribute(总账、loc、数据){
const buf=gl.createBuffer();
gl.bindBuffer(gl.ARRAY\u BUFFER,buf);
总账缓冲数据(总账数组缓冲区、新Float32Array(数据)、总账静态绘图);
//通常情况下,这些将在渲染时发生
gl.EnableVertexAttributeArray(loc);
总账VertexAttribute指针(loc,3,总账浮点,false,0,0);
}
createBufferAndSetupAttribute(gl、posLoc、[
0,  1, 0,
1, -1, 0,
-1, -1, 0,
]);
createBufferAndSetupAttribute(gl、colorLoc、[
1, 0, 0,
1, 0, 1,
0, 0, 1,
]);
createBufferAndSetupAttribute(总账、CornerLocal、[
1, 0, 0,
0, 1, 0,
0, 0, 1,
]);
德国劳埃德船级社使用计划(prg);
总图数组(总图三角形,0,3)

只要有一点想象力,几乎任何事情都是可能的。然而,不可能从任何地方变出信息

最小数据 标准三角形缺少添加新插值颜色所需的信息。该信息是2D坐标(如纹理坐标)和颜色

然后可以使用二维坐标混合其他颜色

数据结构 在本例中,地图坐标作为属性
map
添加到每个顶点,同时添加顶点
color
和位置(
vert
2D)。额外的颜色被添加为统一的
中间颜色
,从而将其限制为具有相同内部颜色的所有三角形

但是,您可以将该颜色添加为附加顶点属性,或者如果只有少数唯一颜色,则可以将其添加为统一数组,然后添加用于索引到统一颜色数组中的顶点属性

混合 最基本的混合可以假设贴图是相对于原点的,原点是三角形的中心。然后只需使用与原点的距离,将中间颜色与插值像素颜色混合

// midColor is uniform 
// colV and colM are varying, and hold the color and internal color 2D mapping
gl_FragColor = vec4(mix(midColor, colV, length(colM)), 1);
该示例使用了相同的技术,但只是添加了一点来改进颜色插值,并将原点向上移动一点,以在视觉上平衡中心

顶点着色器 片段着色器 混合由定义
smoothStart
smoothEnd

#define smoothStart 0.15
#define smoothEnd 0.5
uniform vec3 midColor;
varying vec3 colV;
varying vec2 colM;
void main() {
    vec3 mixed = sqrt(
        mix(
            midColor * midColor, 
            colV * colV,
            smoothstep(smoothStart, smoothEnd, length(colM - vec2(0, 1.0 / 3.0)))
        )
    );
    gl_FragColor = vec4(mixed, 1);
}`;
示例代码
const CONTEXT=“webgl”;
const GL_OPTIONS={alpha:false,depth:false,premultpliedAlpha:false,preserveDrawingBufer:true};
Math.TAU=Math.PI*2;
Math.sinWave=(相位,周期=1,最小值=-1,最大值=1)=>Math.sin((相位*Math.TAU)/周期)*(最大值-最小值)+min;
常量GL_设置={
get context(){return this.gl=canvas.getContext(context,gl_OPTIONS)},
get vertexSrc(){return`${CONTEXT===“webgl2”?“#version 300 es:”}
#定义方面${(innerHeight/innerWidth).toFixed(4)}
属性向量2垂直;
属性向量3颜色;
属性向量2图;
均匀浮动时间;
可变vec3colv;
可变向量2 colM;
void main(){
浮动z=sin(时间)*垂直x;
gl_位置=向量4(cos(时间)*垂直x*纵横比,垂直y,z*0.5+0.5,z+1.0);
colV=颜色;
colM=map;
}`;
},
get fragmentSrc(){return`${CONTEXT===“webgl2”?“#version 300 es:”}
高精度浮点;
#定义smoothStart 0.15
#定义平滑0.5
均匀的vec3中间色;
可变vec3colv;
可变向量2 colM;
void main(){
vec3 mixed=sqrt(mix(midColor*midColor,colV*colV,smoothstep)(smoothStart,smoothEnd,length(colM-vec2(0,1.0/3.0 ')));
gl_FragColor=vec4(混合,1);
}`;
},
获取位置(){return[“A_vert”、“A_color”、“A_map”、“U_midColor”、“U_time”],
compileAndAttach(程序,src,type=this.gl.VERTEX\u着色器){
const gl=this.gl,shader=gl.createShader(类型);
gl.shaderSource(着色器,src);
gl.compileShader(着色器);
如果(!gl.getShaderParameter(着色器,gl.COMPILE_STATUS)){抛出新错误(“WebGL着色器编译错误\n”+gl.getShad
#define smoothStart 0.15
#define smoothEnd 0.5
uniform vec3 midColor;
varying vec3 colV;
varying vec2 colM;
void main() {
    vec3 mixed = sqrt(
        mix(
            midColor * midColor, 
            colV * colV,
            smoothstep(smoothStart, smoothEnd, length(colM - vec2(0, 1.0 / 3.0)))
        )
    );
    gl_FragColor = vec4(mixed, 1);
}`;