Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
梯度“;斜接;在OpenGL中显示连接处的接缝_Opengl_Gradient - Fatal编程技术网

梯度“;斜接;在OpenGL中显示连接处的接缝

梯度“;斜接;在OpenGL中显示连接处的接缝,opengl,gradient,Opengl,Gradient,我正在做一些关于GL中一些2D工作的基础实验。我试着在一个矩形区域周围画一个“画框”。我希望框架周围有一个一致的梯度,所以我用看起来像四个四边形的几何体来构建它,框架的每侧各一个,逐渐变细,形成梯形,有效地有斜接 垂直坐标在“内部”和“外部”矩形上是相同的,所有内部和外部的颜色也是相同的,所以我希望在边缘处看到完美的混合 但请注意,在下图中,连接的拐角处似乎有一条“接缝”,它比应该的要轻 我觉得我在数学上遗漏了一些可以解释这一点的概念。这个伪影是梯度的结果吗?如果我把所有的颜色都改成不透明的蓝色

我正在做一些关于GL中一些2D工作的基础实验。我试着在一个矩形区域周围画一个“画框”。我希望框架周围有一个一致的梯度,所以我用看起来像四个四边形的几何体来构建它,框架的每侧各一个,逐渐变细,形成梯形,有效地有斜接

垂直坐标在“内部”和“外部”矩形上是相同的,所有内部和外部的颜色也是相同的,所以我希望在边缘处看到完美的混合

但请注意,在下图中,连接的拐角处似乎有一条“接缝”,它比应该的要轻

我觉得我在数学上遗漏了一些可以解释这一点的概念。这个伪影是梯度的结果吗?如果我把所有的颜色都改成不透明的蓝色(比如说),我会得到一个完美的纯蓝色框架

更新:下面添加了代码。对不起,有点冗长。使用2个三角形风扇来代替四边形

谢谢

glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);

// Prep the color array. This is the same for all trapezoids.
// 4 verts * 4 components/color = 16 values. 
GLfloat colors[16];
colors[0] = 0.0;
colors[1] = 0.0;
colors[2] = 1.0;
colors[3] = 1.0;
colors[4] = 0.0;
colors[5] = 0.0;
colors[6] = 1.0;
colors[7] = 1.0;

colors[8] = 1.0;
colors[9] = 1.0;
colors[10] = 1.0;
colors[11] = 1.0;
colors[12] = 1.0;
colors[13] = 1.0;
colors[14] = 1.0;
colors[15] = 1.0;

// Draw the trapezoidal frame areas. Each one is two triangle fans.
// Fan of 2 triangles = 4 verts = 8 values
GLfloat vertices[8];

float insetOffset = 100;
float frameMaxDimension = 1000;

// Bottom 
vertices[0] = 0;
vertices[1] = 0;
vertices[2] = frameMaxDimension;
vertices[3] = 0;
vertices[4] = frameMaxDimension - insetOffset;
vertices[5] = 0 + insetOffset;
vertices[6] = 0 + insetOffset;
vertices[7] = 0 + insetOffset;
glVertexPointer(2, GL_FLOAT , 0, vertices); 
glColorPointer(4, GL_FLOAT, 0, colors);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);    

// Left
vertices[0] = 0;
vertices[1] = frameMaxDimension;
vertices[2] = 0;
vertices[3] = 0;
vertices[4] = 0 + insetOffset;
vertices[5] = 0 + insetOffset;
vertices[6] = 0 + insetOffset;
vertices[7] = frameMaxDimension - inset;    
glVertexPointer(2, GL_FLOAT , 0, vertices); 
glColorPointer(4, GL_FLOAT, 0, colors);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);    

/* top & right would be as expected... */

glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);


我以前有过,它对几何学非常敏感。例如,如果在单独的操作中将它们单独绘制为三角形,而不是三角形扇形,则问题就不那么严重了(或者,至少在我的情况下是这样的,类似但略有不同)

我还尝试过的一件事是,用正确的合成模式(或OpenGL混合)分别绘制三角形,彼此稍微重叠,这样就不会产生效果。我工作了,但我没有使用它,因为它只是最终产品的一小部分,不值得


很抱歉,我不知道这种影响的根本原因是什么:(

如@Newbie在评论中所述


@吉诃多:在绘画程序中打开你的图像,用填充工具点击接缝的某个地方,你会看到它在那里形成90度角线……这意味着“接缝”中只有一种颜色,没有更亮的地方。这只是一种错觉

是的。虽然我不熟悉OpenGL下的这部分数学,但我相信这是三角形顶点之间颜色插值的隐式结果……我确信这被称为“双线性插值”

那么如何解决这个问题呢?一种可能是使用一个纹理,然后只绘制一个纹理四边形(或多个纹理四边形)

但是,在片段着色器中生成这样的边界应该很容易

使用GLSL着色器的一个不错的解决方案。。。
假设您正在绘制一个矩形,其左下角的纹理坐标等于(0,0),右上角的纹理坐标等于(1,1)

然后在片段着色器中按程序生成“斜接”将如下所示,如果我是正确的:

varying vec2 coord;

uniform vec2 insetWidth; // width of the border in %, max would be 0.5

void main() {

    vec3 borderColor = vec3(0,0,1);
    vec3 backgroundColor = vec3(1,1,1); 

    // x and y inset, 0..1, 1 means border, 0 means centre

    vec2 insets = max(-coord + insetWidth, vec2(0,0)) / insetWidth;
如果到目前为止我是正确的,那么现在对于每个像素,
insets.x
的值都在
[0..1]

确定给定点水平插入边界的深度, 和
insets.y
具有类似的垂直深度值

左侧垂直条有
插图。y==0,
底部的水平条有
插图x=0,
,左下角有一对(插图x,插图y),覆盖了从(0,0)到(1,1)的整个2D范围。请参见图片以了解详情:

现在我们需要一个变换,对于给定的(x,y)对,它将给我们一个值
[0..1]
来确定如何混合背景色和前景色。1表示100%边框,0表示0%边框。这可以通过几种方式完成

功能应符合以下要求:

  • 如果x==0且y==0,则为0
  • 如果x==1或y==1,则为1
  • 平滑介于两者之间的值
承担这样的职能:

float bias = max(insets.x,insets.y);
它满足这些要求。事实上,我很确定这个函数会给你和上面一样的“锐利”边缘。试着在纸上计算它,在左下角的矩形内选择坐标

如果我们想要有一个平滑的圆形斜接,我们只需要这里的另一个函数。我认为这样的函数就足够了:

float bias = min( length(insets) , 1 );
这里的
length()
函数就是
sqrt(insets.x*insets.x+insets.y*insets.y)
。重要的是:这意味着:“我们离边界越远(按欧几里德距离计算),边界应该越明显”,min()只是为了使结果不大于1(=100%)

请注意,我们的原始函数遵循完全相同的定义-但距离是根据棋盘(Chebyshev)度量计算的,而不是欧几里德度量

这意味着使用例如曼哈顿公制,您将有第三种可能的斜接形状!其定义如下:

float bias = min(insets.x+insets.y, 1);
我预测这条线也会有一条可见的“对角线”,但对角线会在另一个方向(
“\”

好的,对于代码的其余部分,当我们有偏差[0..1]时,我们只需要混合背景色和前景色:

    vec3 finalColor = mix(borderColor, backgroundColor, bias);
    gl_FragColor = vec4(finalColor, 1); // return the calculated RGB, and set alpha to 1 
}

就是这样!将GLSL与OpenGL结合使用会让生活变得更简单。希望这会有帮助!

我认为你看到的是一个。你的视觉系统对亮度一阶导数的变化非常敏感。为了消除这种影响,你需要模糊你的亮度。如果你沿着穿过这个区域的扫描线绘制亮度,你会请注意,有两条线在一个锐角处相交。为了防止视觉系统突出显示此区域,您需要将此连接处倒圆。您可以通过后期处理模糊或在角处添加一些小三角形来完成此操作,以便于过渡。

图像是否沿底部裁剪?另外,您是否可以发布y我们的代码?是的,这个屏幕截图没有被裁剪成直角。眼睛很好。:)我很快会发布一些代码——我不想发布,因为我设置的时候代码太长了