Что такое аналог языка OpenGL ES 2 Shader для HYDRA (пиксельный бендер) sampleLinear? - PullRequest
0 голосов
/ 05 июня 2011

Так что я смотрю на Спецификации шейдера OpenGL ES , но не вижу таких ...

Например - я создал простые "щепотка к зоону" и "поворот для поворота" и«Переместить в центр» HYDRA Pixel Bender фильтр.это может быть выполнено во вспышке.Он основан на примере закрутки пиксельного бендера и 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 шейдерном языке?

обновление:

Итак, я создал нечто похожее на мой фильтр 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);
}

Чтобы увидеть, как работает современный браузер, перейдите к шейдерной и предоставьте ему одну текстуру (например, http://www.iquilezles.org/apps/shadertoy/presets/tex4.jpg),вставьте мой код в редактируемый текст aeria и нажмите enter image description here ... Веселитесь.Итак ... теперь у меня есть другая проблема ... Я хочу иметь одно изображение и черное вокруг него, а не копии того же самого изображения ... Кто-нибудь знает, как это сделать?

1 Ответ

1 голос
/ 05 июня 2011

По данным 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), но похоже, что шейдер уходит в несколько значительно искаженных мест, поэтому я не уверен, что именно вы хотите .

...