topical media & game development
graphic-flex-image-effects-07-source-wrapToSphere.pbk / pbk
<languageVersion : 1.0;>
kernel WrapToSphere
< namespace: "27Bobs";
vendor: "Todd Yard";
version: 1;
description: "Wraps image around sphere.";
>
{
parameter float radius
<
minValue: float(5.0);
maxValue: float(512.0);
defaultValue: float(144.0);
description: "The radius of the sphere.";
>;
parameter float textureWidth
<
minValue: float(5.0);
maxValue: float(1024.0);
defaultValue: float(360.0);
description: "The width of the texture to wrap.";
>;
parameter float textureHeight
<
minValue: float(5.0);
maxValue: float(1024.0);
defaultValue: float(288.0);
description: "The height of the texture to wrap.";
>;
const float PI = 3.14159265;
input image4 source;
output pixel4 result;
void
evaluatePixel()
{
float2 coord = outCoord();
float2 center = float2(radius, radius);
pixel4 px;
// all pixels outside the radius made transparent
if (distance(coord, center) > radius) {
px = sample(source, coord);
px.a = 0.0;
} else {
// equations taken from (and explained at):
// http://blogs.msdn.com/coding4fun/archive/2006/10/31/912562.aspx
// http://www.cs.unc.edu/~rademach/xroads-RT/RTarticle.html
float2 relativePos = coord - center;
float theta = acos(length(relativePos)/radius);
float z = (sin(theta)*radius);
float3 p = float3(relativePos.x, relativePos.y, -z);
// north pole vector
float3 n = float3(0, 1, 0);
// equator vector
float3 e = float3(0, 0, 1);
// normalize() should work, but is buggy in PixelBender;
// the following two lines do the same thing
// p = normalize(p);
float pLength = length(p);
p = float3(p.x/pLength, p.y/pLength, p.z/pLength);
float phi = acos(-dot(n, p));
float u;
float v = phi/PI;
if (z == radius) {
u = 0.5;
} else {
u = (acos(max(min(dot(p, e)/sin(phi), 1.0), -1.0)))/(2.0*PI);
if (dot(cross(n, e), p) > 0.0) {
u = 1.0-u;
}
}
u *= float(textureWidth);
v *= float(textureHeight);
if (u > float(textureWidth)) {
px = pixel4(1.0, 0.0, 0.0, 1.0);
} else if (u < 0.0) {
px = pixel4(0.0, 1.0, 0.0, 1.0);
} else if (v > float(textureHeight)) {
px = pixel4(0.0, 0.0, 1.0, 1.0);
} else if (v < 0.0) {
px = pixel4(1.0, 0.0, 1.0, 1.0);
} else {
px = sample(source, float2(u, v));
px.a = 1.0;
}
}
result = px;
}
}
(C) Æliens
18/6/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.