Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.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 es 片段着色器中的轮廓/锐利过渡_Opengl Es_Opengl Es 2.0_Glsl - Fatal编程技术网

Opengl es 片段着色器中的轮廓/锐利过渡

Opengl es 片段着色器中的轮廓/锐利过渡,opengl-es,opengl-es-2.0,glsl,Opengl Es,Opengl Es 2.0,Glsl,我想在片段着色器中创建像素之间的锐利过渡效果,但我不确定如何做到这一点 在我的顶点着色器中,我有一个可变浮点x在片段着色器中,我使用此值设置颜色的不透明度。我量化当前值以产生分层效果。我想做的是在一个非常小的影响水平,以产生一个独特的边界(完全不同的颜色)。例如,如果x>0.1并且对于任何相邻像素x您正确地认为您无法访问相邻像素,这是因为无法保证像素的写入顺序,它们都是并行绘制的。如果可以访问帧缓冲区中的相邻像素,则会得到不一致的结果 但是,如果您愿意,可以在后期处理中执行此操作。将整个场景绘制

我想在片段着色器中创建像素之间的锐利过渡效果,但我不确定如何做到这一点


在我的顶点着色器中,我有一个
可变浮点x在片段着色器中,我使用此值设置颜色的不透明度。我量化当前值以产生分层效果。我想做的是在一个非常小的影响水平,以产生一个独特的边界(完全不同的颜色)。例如,如果
x>0.1
并且对于任何相邻像素
x您正确地认为您无法访问相邻像素,这是因为无法保证像素的写入顺序,它们都是并行绘制的。如果可以访问帧缓冲区中的相邻像素,则会得到不一致的结果

但是,如果您愿意,可以在后期处理中执行此操作。将整个场景绘制到帧缓冲区纹理中,然后使用过滤着色器将该纹理绘制到屏幕上


当从着色器中的纹理绘制时,您可以随意采样相邻的纹理,以便轻松比较两个相邻纹理之间的增量。

如果您的OpenGL ES实现支持扩展,您可以通过正向/反向差分获得变量的变化率,并对2×2四元网格中的相邻像素进行着色:

float outline(float t, float threshold, float width)
{
    return clamp(width - abs(threshold - t) / fwidth(t), 0.0, 1.0);
}
此函数返回指定宽度行的覆盖率,其中
t
≈ <代码>阈值
,使用
fwidth
确定距离截止点的距离。请注意,
fwidth(t)
相当于
abs(dFdx(t))+abs(dFdy(t))
并计算in的宽度,这可能会使对角线过胖。如果您愿意:


除了Pivot基于导数的实现外,还可以使用基于源图像像素尺寸的偏移量从源图像中获取相邻像素。宽度或高度(以像素为单位)的倒数是与当前纹理坐标的偏移量,您需要在此处使用该偏移量

例如,这里有一个顶点着色器,我用来计算围绕中心像素的八个像素的偏移量:

 attribute vec4 position;
 attribute vec4 inputTextureCoordinate;

 uniform highp float texelWidth; 
 uniform highp float texelHeight; 

 varying vec2 textureCoordinate;
 varying vec2 leftTextureCoordinate;
 varying vec2 rightTextureCoordinate;

 varying vec2 topTextureCoordinate;
 varying vec2 topLeftTextureCoordinate;
 varying vec2 topRightTextureCoordinate;

 varying vec2 bottomTextureCoordinate;
 varying vec2 bottomLeftTextureCoordinate;
 varying vec2 bottomRightTextureCoordinate;

 void main()
 {
     gl_Position = position;

     vec2 widthStep = vec2(texelWidth, 0.0);
     vec2 heightStep = vec2(0.0, texelHeight);
     vec2 widthHeightStep = vec2(texelWidth, texelHeight);
     vec2 widthNegativeHeightStep = vec2(texelWidth, -texelHeight);

     textureCoordinate = inputTextureCoordinate.xy;
     leftTextureCoordinate = inputTextureCoordinate.xy - widthStep;
     rightTextureCoordinate = inputTextureCoordinate.xy + widthStep;

     topTextureCoordinate = inputTextureCoordinate.xy - heightStep;
     topLeftTextureCoordinate = inputTextureCoordinate.xy - widthHeightStep;
     topRightTextureCoordinate = inputTextureCoordinate.xy + widthNegativeHeightStep;

     bottomTextureCoordinate = inputTextureCoordinate.xy + heightStep;
     bottomLeftTextureCoordinate = inputTextureCoordinate.xy - widthNegativeHeightStep;
     bottomRightTextureCoordinate = inputTextureCoordinate.xy + widthHeightStep;
 }
下面是一个片段着色器,它使用该着色器执行Sobel边缘检测:

 precision mediump float;

 varying vec2 textureCoordinate;
 varying vec2 leftTextureCoordinate;
 varying vec2 rightTextureCoordinate;

 varying vec2 topTextureCoordinate;
 varying vec2 topLeftTextureCoordinate;
 varying vec2 topRightTextureCoordinate;

 varying vec2 bottomTextureCoordinate;
 varying vec2 bottomLeftTextureCoordinate;
 varying vec2 bottomRightTextureCoordinate;

 uniform sampler2D inputImageTexture;

 void main()
 {
    float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
    float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;
    float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
    float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
    float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
    float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
    float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
    float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;
    float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
    float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;

    float mag = length(vec2(h, v));

    gl_FragColor = vec4(vec3(mag), 1.0);
 }
我传入
texelWidth
texelHeight
制服,分别为图像的1/width和1/height。这确实需要您跟踪输入图像的宽度和高度,但它应该适用于所有OpenGL ES设备,而不仅仅是那些具有派生扩展的设备


我在顶点着色器中进行纹理偏移计算有两个原因:偏移计算只需要在每个顶点执行一次,而不是在每个片段中执行一次,更重要的是,一些基于平铺的延迟渲染器对依赖纹理读取的反应非常差,其中纹理偏移是在片段着色器中计算的。对于在这些设备上删除这些依赖纹理读取的着色器程序,性能可以高出20倍。

这太棒了。我想知道为什么这些函数在默认情况下没有包含在ES中(因为它们在完整规范中从1.10开始就存在)。我现在只需要找到一份参考资料,说明在哪些设备上支持这种扩展。@edA-qamort-ora-y:因为ES 2.0必须支持尽可能广泛的硬件。ES 2.0目前支持的所有东西都不支持显式导数。@Pivot这个问题可能会晚一点出现,但您实际为t、阈值和宽度输入了什么值?我希望宽度是所需的轮廓宽度?我将非常感谢您的回答:)我将接受这个答案,因为在Pivot的回答中,似乎很少有ES设备支持标准衍生产品(这有望在几年后成为正确答案)。这很好。然而,我已经了解到,与动态顶点属性相比,动态修改纹理在某些设备上的实现较差。我认为动态纹理会让我感觉更好,但我担心这些糟糕的设备。
 precision mediump float;

 varying vec2 textureCoordinate;
 varying vec2 leftTextureCoordinate;
 varying vec2 rightTextureCoordinate;

 varying vec2 topTextureCoordinate;
 varying vec2 topLeftTextureCoordinate;
 varying vec2 topRightTextureCoordinate;

 varying vec2 bottomTextureCoordinate;
 varying vec2 bottomLeftTextureCoordinate;
 varying vec2 bottomRightTextureCoordinate;

 uniform sampler2D inputImageTexture;

 void main()
 {
    float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
    float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;
    float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
    float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
    float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
    float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
    float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
    float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;
    float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
    float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;

    float mag = length(vec2(h, v));

    gl_FragColor = vec4(vec3(mag), 1.0);
 }