什么是HYDRA(像素弯曲器)sampleLinear的OpenGL ES 2 Shader语言模拟?

时间:2011-06-05 11:30:34

标签: opengl-es shader pixel-shader pixel-bender hydra

所以我看看OpenGL ES shader specs,但看不到这样......

例如 - 我创建了简单的“捏到zoon”和“旋转转动”和“移动到移动中心”HYDRA像素弯曲滤镜。它可以在flash中执行。它基于默认像素弯曲器旋转示例和this

<languageVersion: 1.0;> 

kernel zoomandrotate
<   namespace : "Pixel Bender Samples";
    vendor : "Kabumbus";
    version : 3;
    description : "rotate and zoom an image around"; >
{
    // define PI for the degrees to radians calculation
    const float PI = 3.14159265;

    // An input parameter to specify the center of the twirl effect.
    // As above, we're using metadata to indicate the minimum,
    // maximum, and default values, so that the tools can set the values 
    // in the correctly in the UI for the filter.
    parameter float2 center
    <
        minValue:float2(0.0, 0.0);
        maxValue:float2(2048.0, 2048.0);
        defaultValue:float2(256.0, 256.0);
    >;

    // An input parameter to specify the angle that we would like to twirl.
    // For this parameter, we're using metadata to indicate the minimum,
    // maximum, and default values, so that the tools can set the values 
    // in the correctly in the UI for the filter.
    parameter float twirlAngle
    <
        minValue:float(0.0);
        maxValue:float(360.0);
        defaultValue:float(90.0);
    >;

     parameter float zoomAmount
    <
        minValue:float(0.01);
        maxValue:float(10.0);
        defaultValue:float(1);
    >;

    // An input parameter that indicates how we want to vary the twirling
    // within the radius.  We've added support to modulate by one of two 
    // functions, a gaussian or a sinc function.  Since Flash does not support
    // bool parameters, we instead are using this as an int with two possible
    // values. Setting this parameter to be 1 will
    // cause the gaussian function to be used, unchecking it will cause 
    // the sinc function to be used.
    parameter int gaussOrSinc
    <
        minValue:int(0);
        maxValue:int(1);
        defaultValue:int(0);
    >;

    input image4 oImage;
    output float4 outputColor;

    // evaluatePixel(): The function of the filter that actually does the 
    //                  processing of the image.  This function is called once 
    //                  for each pixel of the output image.
    void
    evaluatePixel()
    {
        // convert the angle to radians
        float twirlAngleRadians = radians(twirlAngle);

        // calculate where we are relative to the center of the twirl
        float2 relativePos = outCoord() - center;

        // calculate the absolute distance from the center normalized 
        // by the twirl radius.
        float distFromCenter = length( relativePos );
        distFromCenter = 1.0;
        // modulate the angle based on either a gaussian or a sync.
        float adjustedRadians;

        // precalculate either the gaussian or the sinc weight
        float sincWeight = sin( distFromCenter ) * twirlAngleRadians / ( distFromCenter );
        float gaussWeight = exp( -1.0 * distFromCenter * distFromCenter ) * twirlAngleRadians;

        // protect the algorithm from a 1 / 0 error
        adjustedRadians = (distFromCenter == 0.0) ? twirlAngleRadians : sincWeight;

        // switch between a gaussian falloff or a sinc fallof
        adjustedRadians = (gaussOrSinc == 1) ? adjustedRadians : gaussWeight;

        // rotate the pixel sample location.
        float cosAngle = cos( adjustedRadians );
        float sinAngle = sin( adjustedRadians );

        float2x2 rotationMat = float2x2(
            cosAngle,   sinAngle,
            -sinAngle,  cosAngle
        );

        relativePos = rotationMat * relativePos; 
        float scale =  zoomAmount;
        // sample and set as the output color.  since relativePos
        // is related to the center location, we need to add it back in.
        // We use linear sampling to smooth out some of the pixelation.
        outputColor = sampleLinear( oImage, relativePos/scale + center );
    }
}

所以现在我想把它移植到OpenGL ES着色器中。数学和参数可以转换为OpenGL ES着色器语言,但是如何处理sampleLinear?什么是openGL ES shader语言中的模拟?

更新

所以我创建了类似于我的HYDRA过滤器......与webGL和OpenGL ES着色器兼容......

#ifdef GL_ES
precision highp float;
#endif

uniform vec2 resolution;
uniform float time;
uniform sampler2D tex0;


void main(void)
{
    vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;
    // a rotozoom
    vec2 cst = vec2( cos(.5*time), sin(.5*time) );
    mat2 rot = 0.5*cst.x*mat2(cst.x,-cst.y,cst.y,cst.x);
    vec3 col = texture2D(tex0,0.5*rot*p+sin(0.1*time)).xyz;

    gl_FragColor = vec4(col,1.0);
}

要查看其工作原理,请使用现代浏览器,导航至shadertoy为其提供一个纹理(例如http://www.iquilezles.org/apps/shadertoy/presets/tex4.jpg),将我的代码粘贴到可编辑的文本aeria中并点击enter image description here .. 。 玩得开心。那么..现在我还有另一个问题......我想要一个图像,并且周围有黑色而不是同一图像的副本......任何人都知道该怎么做?

1 个答案:

答案 0 :(得分:1)

根据Adobe Pixel Blender Reference,sampleLinear“通过对相邻像素值执行双线性插值来处理不在像素中心的坐标。”

在OpenGL中实现这一目标的正确方法是使用texture2D,就像你现在一样,但是通过glTexParameter设置线性过滤的纹理环境。

您可以使用步进功能并乘以其结果以获得越界像素的黑色,或者为纹理提供单个像素黑色边框并切换到钳位而不是重复,也可以通过glTexParameter

如果您想在代码中执行此操作,请尝试:

#ifdef GL_ES
precision highp float;
#endif

uniform vec2 resolution;
uniform float time;
uniform sampler2D tex0;


void main(void)
{
    vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;
    // a rotozoom
    vec2 cst = vec2( cos(.5*time), sin(.5*time) );
    mat2 rot = 0.5*cst.x*mat2(cst.x,-cst.y,cst.y,cst.x);
    vec2 samplePos = 0.5*rot*p+sin(0.1*time);
    float mask = step(samplePos.x, 0.0) * step(samplePos.y, 0.0) * (1.0 - step(samplePos.x, 1.0)) * (1.0 - step(samplePos.y, 1.0));
    vec3 col = texture2D(tex0,samplePos).xyz;

    gl_FragColor = vec4(col*mask,1.0);
}

这会限制从(0,0)到(1,1)的方框中的颜色,但是它看起来像着色器到了一些明显偏斜的地方,所以我不确定你想要什么