我可以只用一个三角形渲染三角形渐变,每个角都使用glColor。
但如何渲染完美的矩形渐变?我尝试了一个四边形,但中间会变得难看。我也试过2x2尺寸的纹理,就像它应该做的那样:从每个角落进行适当的混合,但是当拉伸太多时纹理采样精度变得不合适(我开始看到大于1x1尺寸的像素)。
是否有某种方法可以在着色器中计算它?
-
编辑:问题在于:
答案 0 :(得分:7)
问题是因为你使用四核。使用两个三角形绘制四边形,但三角形不在您需要的方向上。
如果我将四边形顶点定义为:
我会说四边形由以下三角形组成:
分配给每个顶点的颜色为:
记住几何体(两个三角形), D 和 B 之间的像素是红色和红色之间插值的结果:确实是红色!
解决方案是具有两个三角形的几何体,但以不同的方式定向:
但可能你不会得到精确的渐变,因为在四边形中间你会得到一个完整的黄色,而不是一个黄色与红色混合。所以,我想你可以使用4个三角形(或三角扇)获得精确的结果,其中居中的顶点是黄色和红色之间的插值。
Wooop!有效的结果并不是我所期待的。我认为渐变是由颜色之间的线性插值产生的,但肯定不是(我真的需要设置LCD颜色空间!)。实际上,最具扩展性的解决方案是使用片段着色器进行渲染。
保留 Bahbar 提出的解决方案。我建议开始实现一个传递顶点/片段着色器(只指定顶点和颜色,你应该得到前面的结果);然后,开始使用 mix 函数和传递给顶点着色器的纹理坐标。
您真的需要了解具有可编程着色器的渲染管道:每个顶点调用一次顶点着色器,每个片段调用一次片段着色器(没有多重采样,片段是像素;使用多重采样, aa像素由许多片段组成,这些片段被内插以获得像素颜色。
顶点着色器采用输入参数(制服和输入;制服对于glBegin / glEnd之间发出的所有顶点都是常量;输入是每个顶点着色器实例的特征(4个顶点,4个顶点着色器实例)。
片段着色器将产生片段的顶点着色器输出作为输入(由于三角形,线和点的光栅化)。在 Bahbar 答案中,唯一的输出是 uv 变量(两个着色器源共有)。
在这种情况下,顶点着色器输出顶点纹理坐标UV(按“原样”传递)。这些UV坐标可用于每个片段,它们是通过根据片段位置插入顶点着色器输出的值来计算的。
一旦你有了这些坐标,你只需要两种颜色:你的情况下是红色和黄色( Bahbar 答案对应 color0 和 color1 < / em>制服)。然后,根据特定片段的UV坐标混合这些颜色。 (*)
(*)以下是着色器的强大功能:您只需修改着色器源即可指定不同的插值方法。通过为片段着色器指定其他制服来实现线性,双线性或样条插值。
良好的做法!
答案 1 :(得分:7)
实际上,您想要的渐变类型依赖于每个像素的4种颜色,其中OpenGL通常仅在三角形上插入输入(因此3个输入)。使用标准插值法无法获得完美的渐变效果。
现在,正如您所提到的,2x2纹理可以做到这一点。如果你确实看到精度问题,我建议将纹理的格式切换为通常需要更高精度的东西(如浮动纹理)。
最后,正如您在问题中提到的,您可以使用着色器解决此问题。假设你传递一个额外的属性,每个顶点对应于(u,v)=(0,0)(0,1)(1,0)(1,0)一直到像素着色器(使用顶点着色器)只做一个传递。)
你可以在像素着色器中执行以下操作(注意,这里的想法是合理的,但我没有测试代码):
Vertex着色器片段:
varying vec2 uv;
attribute vec2 uvIn;
uv = uvIn;
片段着色器:
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);
答案 2 :(得分:0)
您的所有顶点是否具有相同的深度(Z)值,并且您的所有三角形是否完全在屏幕上?如果是这样,那么在使用glColor的两个三角形构成的四边形上获得“完美”颜色渐变应该没有问题。如果没有,那么你的OpenGL实现可能会很难对待颜色。
这让我怀疑你可能有一个非常古老或奇怪的OpenGL实现。我建议你告诉我们你正在使用什么平台,以及你有哪个版本的OpenGL ......?
如果没有更多信息,我建议您尝试编写着色器,并避免告诉OpenGL您想要“颜色”。如果可能的话,告诉它你想要一个“texcoord”,但无论如何都要把它当成一种颜色。这种技巧在某些颜色准确度太低的情况下起作用。
答案 3 :(得分:0)
好吧,我不打算给你一个具体的答案,但你应该能够取得进展。
首先,你必须知道你想要什么。你说你可以做一个三角形的渐变。我怀疑你的意思是来自NeHe的代码:example image。
现在,我们的调色板有三种基本颜色,红色,绿色和蓝色。因此,正如您所想,制作三角形调色板似乎合乎逻辑且容易。
现在,如果你想将其转换成四边形,你首先必须考虑你想要它的样子。我要在哪里换角?四边形中间应该是什么?等等...在你发现你应该开始编码之后。我怀疑你在不考虑你想要的东西的情况下立即开始编码。