OpenGL:如何呈现完美的矩形渐变? [英] OpenGL: How to render perfect rectangular gradient?

查看:1564
本文介绍了OpenGL:如何呈现完美的矩形渐变?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



但是如何渲染完美的矩形渐变呢?我试着用一个四边形,但中间会得到丑陋的缝。我也尝试了2x2大小的纹理,它是像它应该做:适当的混合从每个角落,但纹理采样精度变得不准确,当拉伸太多(我开始看到像素大于1x1大小)。



有什么方法可以在着色器中计算这个值吗?



-



修改

这是问题:



http://img143.imageshack.us/img143/7066/gradients.png



< img src =http://img143.imageshack.us/img143/7066/gradients.pngalt =http://img143.imageshack.us/img143/7066/gradients.png>

$ b确实,你想要的依赖于每个像素的4种颜色的渐变,其中OpenGL通常只在三角形内插输入(所以3个输入)。只有使用标准插值器,才能获得完美的梯度。



现在,如你所说,2x2纹理可以做到。如果你确实看到精度问题,我建议将纹理的格式切换到通常需要更高精度的东西(例如浮动纹理)。



最后,也在你的问题,你可以解决这个与着色器。假设你把对应于(u,v)=(0,0)(0,1)(1,0)(1,0)的每个顶点的额外属性传递给像素着色器



您可以在像素着色器中执行以下操作(注意,这里的想法是声音,但我没有测试代码):



顶点着色器片段:

  varying vec2 uv; 
attribute vec2 uvIn;

uv = uvIn;

片段着色器:

  uniform vec3 color0; 
uniform vec3 color1;
varying vec2 uv;

//来自wikipedia的单位正方形上的双线性插值:
// 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)
//这里应用:
// gl_FragColor = color0 *((1-x)*(1-y)+ x * y)+ color1 * -x)* y)
// gl_FragColor = color0 *(1 - x - y + 2 * x * y)+ color1 *(x + y - 2 * x * y)
//简化:
// 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);


I can render triangular gradient with simply just one triangle and using glColor for each corner.

But how to render perfect rectangular gradient? I tried with one quad, but the middle will get ugly seam. I also tried with texture of 2x2 size, it was like it should be done: proper blending from each corner, but the texture sampling precision becomes unprecise when stretched too much (i started to see pixels bigger than 1x1 size).

Is there some way of calculating this in a shader perhaps?

--

Edit: Here is the problem:

http://img143.imageshack.us/img143/7066/gradients.png

解决方案

Indeed, the kind of gradient you want relies on 4 colors at each pixel, where OpenGL typically only interpolates input over triangles (so 3 inputs). Getting the perfect gradient is not possible just with the standard interpolants.

Now, as you mentioned, a 2x2 texture can do it. If you did see precision issues, I suggest switching the format of the texture to something that typically requires more precision (like a float texture).

Last, and as you mentioned also in your question, you can solve this with a shader. Say you pass an extra attribute per-vertex that corresponds to (u,v) = (0,0) (0,1) (1,0) (1,0) all the way to the pixel shader (with the vertex shader just doing a pass-through).

You can do the following in the pixel shader (note, the idea here is sound, but I did not test the code):

Vertex shader snippet:

varying vec2 uv;
attribute vec2 uvIn;

uv = uvIn;

Fragment shader:

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);

这篇关于OpenGL:如何呈现完美的矩形渐变?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆