Roo*_*kie 6 c++ opengl gradient glsl
我可以只用一个三角形渲染三角形渐变,并为每个角使用glColor.
但如何渲染完美的矩形渐变?我尝试了一个四边形,但中间会变得难看.我也尝试过2x2尺寸的纹理,就像它应该做的那样:从每个角落进行适当的混合,但是当拉伸太多时纹理采样精度变得不准确(我开始看到大于1x1尺寸的像素).
有没有办法在着色器中计算这个?
-
编辑:这是问题所在:
实际上,您想要的渐变类型依赖于每个像素的4种颜色,其中OpenGL通常仅在三角形上插入输入(因此3个输入).使用标准插值法不可能获得完美的梯度.
现在,正如您所提到的,2x2纹理可以做到这一点.如果你确实看到精度问题,我建议将纹理的格式切换到通常需要更高精度的东西(如浮动纹理).
最后,正如您在问题中提到的那样,您可以使用着色器解决此问题.假设你传递一个额外的属性,每个顶点对应于(u,v)=(0,0)(0,1)(1,0)(1,0)一直到像素着色器(使用顶点着色器)只做一个传递).
你可以在像素着色器中执行以下操作(注意,这里的想法是合理的,但我没有测试代码):
顶点着色器片段:
varying vec2 uv;
attribute vec2 uvIn;
uv = uvIn;
Run Code Online (Sandbox Code Playgroud)
片段着色器:
uniform vec3 color0;
uniform vec3 color1;
varying vec2 uv;
// from wikipedia on bilinear interpolation on unit square:
// f(x,y) = f(0,0)(1-x)(1-y) + f(1,0)x(1-y) + f(0,1)(1-x)y + f(1,1) xy.
// applied here:
// gl_FragColor = color0 * ((1-x)*(1-y) + x*y) + color1*(x*(1-y) + (1-x)*y)
// gl_FragColor = color0 * (1 - x - y + 2 * x * y) + color1 * (x + y - 2 * x * y)
// after simplification:
// float temp = (x + y - 2 * x * y);
// gl_FragColor = color0 * (1-temp) + color1 * temp;
gl_FragColor = mix(color0, color1, uv.u + uv.v - 2 * uv.u * uv.v);
Run Code Online (Sandbox Code Playgroud)
问题是因为你使用四核.使用两个三角形绘制四边形,但三角形不在您需要的方向上.
如果我将四边形顶点定义为:
我会说四边形由以下三角形组成:
分配给每个顶点的颜色是:
记住几何(两个三角形),D和B之间的像素是红色和红色之间插值的结果:实际上,红色!
解决方案是具有两个三角形的几何体,但以不同的方式定向:
但是可能你不会得到精确的渐变,因为在四边形的中间你会得到一个完整的黄色,而不是黄色和红色混合.所以,我想你可以使用4个三角形(或三角扇)获得精确的结果,其中居中的顶点是黄色和红色之间的插值.
Wooop!有效的结果并不是我所期待的.我认为渐变是由颜色之间的线性插值产生的,但肯定不是(我真的需要设置LCD颜色空间!).实际上,最具扩展性的解决方案是使用片段着色器进行渲染
保持Bahbar提出的解决方案.我建议开始实现一个传递顶点/片段着色器(只指定顶点和颜色,你应该得到前面的结果); 然后,开始使用mix函数和传递给顶点着色器的纹理坐标.
您真的需要了解具有可编程着色器的渲染管道:每个顶点调用一次顶点着色器,每个片段调用一次片段着色器(没有多重采样,片段是像素;使用多重采样,a像素由许多片段组成,插值以获得像素颜色).
顶点着色器采用输入参数(制服和输入;制服对于glBegin/glEnd之间发出的所有顶点是常量;输入是每个顶点着色器实例的特征(4个顶点,4个顶点着色器实例).
片段着色器将产生片段的顶点着色器输出作为输入(由于三角形,线和点的光栅化).在Bahbar答案中,唯一的输出是uv变量(两个着色器源共用).
在您的情况下,顶点着色器输出顶点纹理坐标UV(按"原样"传递).这些UV坐标可用于每个片段,它们通过根据片段位置插入顶点着色器输出的值来计算.
一旦你有了这些坐标,你只需要两种颜色:你的情况下是红色和黄色(在Bahbar中答案对应于color0和color1制服).然后,根据特定片段的UV坐标混合这些颜色.(*)
(*)以下是着色器的强大功能:您只需修改着色器源即可指定不同的插值方法.通过为片段着色器指定其他制服来实现线性,双线性或样条插值.
好习惯!