UVcoords in shader?

AdamW's icon

Hi,

I'm a total glsl rookie trying to write a shader that gives you individual control over the four cornerpoints of your UV. Like the "Perspective Transform" image unit. But I can't get it to work. I realize I need something other then the texture2DRect call, but when I try to use texture2DProj it gives me errors. I guess I need a varying vec4 texcoord somehow, but how?
Any pointers in the right direction would be great.

tia

Joshua Kit Clayton's icon

On Jan 3, 2007, at 9:10 AM, Adam Wittsell wrote:

> I'm a total glsl rookie trying to write a shader that gives you
> individual control over the four cornerpoints of your UV. Like the
> "Perspective Transform" image unit. But I can't get it to work. I
> realize I need something other then the texture2DRect call, but
> when I try to use texture2DProj it gives me errors. I guess I need
> a varying vec4 texcoord somehow, but how?
> Any pointers in the right direction would be great.

Check out any of the texdisplace shaders to see how to manipulate
texture coordinates. td.resample.jxs is probably a good one to start
getting a feel for this. td.rota.jxs is more along the lines of
"Perspective Transform", but the bound mode logic is a little
confusing. Here's esse ntially what that would look like if you
didn't care about the bound modes. (*much simpler*).

void main()
{
    // where is the point?
    vec2 sizea = texdim0;
    vec2 point = texcoord0;

    //transformation matrices
    mat2 sca = mat2 (1./zoom.x,0.,0.,1./zoom.y);//scaling matrix (zoom)
    mat2 rot = mat2 (cos(theta),sin(theta),-sin(theta),cos(theta));//
rotation matrix

    //perform transform
    vec2 tc = ((((point-anchor*sizea)*rot)*sca)+anchor*sizea)+offset;

    //sample textures
    gl_FragColor = texture2DRect(tex0,tc);
}

For more information regarding shaders, I would recommend checking
out some of the resources listed at the following link, as well as
NVidia's GPUGems series:

-Joshua

AdamW's icon

Thanks for the tips Joshua.
I have tried to look on the net and the texdisp shaders, but I still don't get it. Every example I find deals with the transformation of a rectangle and not the individual points. Why can't it be easy as in Maya ;)?

Andrew Benson's icon

Hi Adam,
It sounds like what you need is a little primer on linear algebra.
Since what you are manipulating (texcoords) are cartesian coordinates,
look for ways to tranform those coordinates into the shape, size, and
location you are looking for. For a start, here's a page that discusses
some basic transformation matrices:

Good luck!

Cheers,
Andrew B.

Wesley Smith's icon

Are you tryting to do projective texture mapping like this:
http://developer.nvidia.com/object/Projective_Texture_Mapping.html ?
If so, you don't want to use a 4-component texcoord but a 3 component
texcoord. The 3 components are the usual U, V but in homogenous
coordinates with the 3rd value used for the perspective divide. For
the 4 component version, the 3rd value holds a depth value. This for
is used for shadow mapping.

wes

Here's a version of td.lumadisplace.jxs but in GLSL.

    Luminance based texture displacement
        Amplitude of displacement (x,y)
        Offset

AdamW's icon

What I'm trying to achieve is a way to do perspective transformation in the texture space itself. The point being that I then could have several texture layers composited together with slabs ending up on one videoplane, but still have 3D-control over each layer individually.
So far I managed to get around my lack of math by using the Jash 3Dmatrix objects and feed the result into the "Perspective Transform" image unit. The problem is that the effect forbids pointA to have a larger x-value then PointB. So I can only rotate the object +-90 degrees in y (patch below).
I guess the best approach would be to have a vertex shader manipulate the slab geometry itself, so I just have to grit my teeth and get down with the matrices.
Any other suggestions from you pros are very welcome.

Max Patch
Copy patch and select New From Clipboard in Max.

Joshua Kit Clayton's icon

If you're just looking to do 4 point interpolation, where the four
corners of the rectangle can be tied to new coords, this math is very
simple and doesn't require learning about matrix transformations.
Otherwise, you'll need to learn a bit of matrix math (or just use
textured geometry with jit.gl.sketch or jit.gl.mesh instead of using
slab)

Here's a rough example of how you'd accomplish the four point
interpolation in a jitter shader. Warning email client coded, so
there might be mistakes.

uniform vec2 bottomleft;
uniform vec2 bottomright;
uniform vec2 topleft;
uniform vec2 topright;

varying vec2 texcoord0;
varying vec2 texdim0;
uniform sampler2DRect tex0;

void main()
{
    // normalize our texture coordinate to range 0-1 based on texture
dimensions    
    vec2 normpoint = texcoord0/texdim0;

    // four point interpolation:

    // interpolate across X axis for top two points
    vec2 toptemp = xfade(topleft,topright,vec2(texcoord0.x));

    // interpolate across X axis for bottom two points
    vec2 bottomtemp = xfade(bottomleft,bottomright,vec2(texcoord0.x));

    // interpolate across Y axis with top/bottom temporaries
    vec2 tc = xfade(bottomtemp,toptemp,vec2(texcoord0.y));

    // if the four corners are specified with normalized texture
coordinates, need to scale again
    tc = tc*texdim0;

    //sample texture
    gl_FragColor = texture2DRect(tex0,tc);
}

-Joshua

AdamW's icon

Thank's Joshua! This looks exactly like what I'm after. It refuses to compile though. It says "ERROR: 0:19: 'xfade' : no matching overloaded function found". I think the code came through all right.

Andrew Benson's icon

That's because xfade() is not a valid built-in GLSL function. I think
JKC meant to use mix() here.

AB

Joshua Kit Clayton's icon

On Jan 3, 2007, at 1:57 PM, Andrew Benson wrote:

> That's because xfade() is not a valid built-in GLSL function. I think
> JKC meant to use mix() here.

Ja. Sorry about that. Was just typing real quick in email client, and
spaced out on the GLSL mix call.

-Joshua

AdamW's icon

I got it up and running now, but it seems that the transformation is nonlinear. I modified your code to include the normpoint you declared, but didn't use, but it made no difference. It's a very cool effect, but not quite what I was after ;).

{
    vec2 normpoint = texcoord0/texdim0;
    vec2 toptemp = mix(topleft,topright,vec2(normpoint.x));
    vec2 bottomtemp = mix(bottomleft,bottomright,vec2(normpoint.x));
    vec2 tc = mix(bottomtemp,toptemp,vec2(normpoint.y));
    tc = tc*texdim0;
    gl_FragColor = texture2DRect(tex0,tc);
}

[img]index.php?t=getfile&id=406&private=0[/img]

Andrew Benson's icon

Hi Adam,
Could you send us a copy of the complete shader that you are using?
It's very strange that you are getting these non-linear results.

Cheers,
Andrew B.

AdamW's icon

Here it is.
I probably did something wrong when I tried to change it.

     shader for performing srcdim/dstdim operations
        topleft
        topright
        bottomright
        bottomleft

Joshua Kit Clayton's icon

On Jan 3, 2007, at 2:53 PM, Adam Wittsell wrote:

> I got it up and running now, but it seems that the transformation
> is nonlinear. I modified your code to include the normpoint you
> declared, but didn't use, but it made no difference. It's a very
> cool effect, but not quite what I was after ;).

Technically bilinear interpolation isn't a linear operation. Sorry
for this false solution to your problem. I thought that this would
give you roughly the results you were looking for, but obviously not.
What you'll need to do to get the exact same solution as the
"Perspective Transform" image unit is solve for the rectangular plane
in 3d space which projects to the four screen points specified. This
will definitely require some linear algebra.

If you don't care about the perspective transform and that the shape
is a rectangle in 3d space (instead of some arbitrary quadrilateral
in 2d space), the problem is a little bit simpler, and you can easily
accomplish with sketch and glvertex/gltexture instead of using
jit.gl.slab, letting OpenGL do the rest for you.

Finally, another thing to mention for people interested in linear
transforms to texture coordinates without using shaders, keep in mind
that you can use the tex_plane_s and tex_plane_t attributes of
jit.gl.* objects in tex_mode 1 and 3 (search archives for some
examples), or use gltranslate/glscale/glrotate with glmatrixmode
texture in sketch. These approaches of course can invalidate
assumptions made by the passthrudim vertex shader that grabs the
diagonal texture matrix values to establish pixel width height for
rectangular textures.

Probably more detail with less usable information than you were
looking for, but hopefully this points you in the right direction if
you want to get your hands dirty.

-Joshua

AdamW's icon

Thank's for the tips guys. Will try to get down with the matrices.

Cheers

nesa's icon

A late follow-up...

Here are some great free video lectures for all who missed them in school:

They helped me realizing that jit.la object names are not referencing Los
Angeles...

> It sounds like what you need is a little primer on linear algebra.