What is OpenGL ES 2 Shader language analog for HYDRA (pixel bender) sampleLinear?
So I look onto OpenGL ES shader specs but do not see such...
For example - I created simple "pinch to zoon" and "rotate to turn around" and "move to move center" HYDRA pixel bender filter. it can be executed in flash. It is based on default pixel bender twirl example and 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
//开发者_JS百科 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 );
}
}
So now I want to port it into OpenGL ES shader. math and parameters are convertable into OpenGL ES shader language, but what to do with sampleLinear? what is analog for it in openGL ES shader languge?
update:
So I had created something similar to my HYDRA filter... compatable with webGL and OpenGL ES shaders...
#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);
}
To see how it works get modern browser, navigate to shadertoy provide it with one texture ( http://www.iquilezles.org/apps/shadertoy/presets/tex4.jpg
for example), paste my code into editable text aeria and hit
Per Adobe's Pixel Blender Reference, sampleLinear "Handles coordinates not at pixel centers by performing bilinear interpolation on the adjacent pixel values."
The correct way to achieve that in OpenGL is to use texture2D, as you already are, but to set the texture environment for linear filtering via glTexParameter.
You can use the step function and multiply by its result to get black for out-of-bounds pixels, or give your texture a single pixel black border and switch to clamping rather than repeat, also via glTexParameter
.
If you want to do it in code, try:
#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);
}
That'd restrict colours to coming from the box from (0, 0) to (1, 1), but it looks like the shader heads off to some significantly askew places, so I'm not sure exactly what you want.
精彩评论