0

所以我查看了OpenGL ES 着色器规范,但没有看到这样的......

例如 - 我创建了简单的“捏放大”和“旋转转身”和“移动中心” HYDRA 像素弯曲过滤器。它可以在闪存中执行。它基于默认的像素弯曲器旋转示例,并且

<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 着色器语言中的模拟是什么?

更新:

所以我创建了类似于我的 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 中并点击在此处输入图像描述...玩得开心。所以..现在我有另一个问题...我想要一个图像和黑色而不是同一图像的副本...任何人都知道该怎么做?

4

1 回答 1

1

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

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

您可以使用 step 函数并乘以它的结果以获得越界像素的黑色,或者为您的纹理提供单个像素黑色边框并切换到钳位而不是重复,也可以通过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) 的盒子,但看起来着色器会转向一些明显歪斜的地方,所以我不确定你想要什么。

于 2011-06-05T15:23:38.953 回答