Home Technical Talk

A question about GLSL shaders

Hello all!

I'm trying to develop my 3D skills, particularly GLSL, but unfortunately I've gotten a bit stuck as I want to do something that I can't find any online documentation for. I've been a longtime reader of Polycount so I thought I'd sign up and see if I could get any assistance from the community :)

Within my shader program I'm trying to rotate a texture around an arbitrary point (specifically I want to use the centre point as the origin). While I can translate horizontally/vertically or warp my textures I have no idea how to rotate them. Could anyone please help me out? I'd really appreciate it!

(For those who have used the UDK/UE3 material editor, I am basically trying to recreate the 'rotator' node)

Replies

  • Xoliul
    Offline / Send Message
    Xoliul polycounter lvl 16
    You just need some basic math: sine and/or cosine.
  • DarthNater
    Offline / Send Message
    DarthNater polycounter lvl 10
    You'll also have to find the center point of your texture, because if you rotate it without, it will more than likely just rotate from 0,0. The center point will be half your res. of x and y.
  • Xoliul
    Offline / Send Message
    Xoliul polycounter lvl 16
    In UV coordinates that will always be (0.5f,0.5f). It is completely resolution independent.
  • DarthNater
    Offline / Send Message
    DarthNater polycounter lvl 10
    Snap, I didn't realize they meant within the shader, I thought they wanted to rotate the image outside of it :P
  • Viento
    Thanks for the swift replies! I think that I probably should have explained myself a bit better.

    While I have to rotate the UVs with sine/cosine I am unsure exactly how to access the coords of the UV vertices in GLSL. I have been learning it from online tutorials which have been great for getting results, but haven't always explained what is actually going on when I use things like gl_texcoords[0] or gl_multitexcoords0 etc.

    For example I know that the following GLSL will scroll a texture...

    vec2 Texcoord = gl_MultiTexCoord0.st;
    float offset_x = 2.0;
    float offset_y = 2.0;
    vec4 example = texture2D( baseMap, vec2(Texcoord.s+offset_x, Texcoord.t+offset_y) );


    ...but I don't know what is going in in regard to the actual UV coords.

    Could anyone give me a quick example of how I would go about rotating UVs?

    Thanks again for the help so far.
  • Xoliul
    Offline / Send Message
    Xoliul polycounter lvl 16
    Hmm I get the impression you lack some general understanding of how a shader works. You always have to keep in mind you're calculations are meant for one pixel at a time, but will be sequentially (well sorta) executed for all of the pixels on screen. So that means the texture coordinate you're working with, is that of the current pixel. The texcoord itself doesn't do anything yet, it's passed to your fragment program / pixel shader by the vertex shader (dunno if they have another name for this in GLSL). You just use this coordinate to do a texture lookup. You can do whatever you want with the coordinates for this texture lookup; use hardcoded values to get the same sampled pixel all over your model, multiply them to scale (tile), add a value to offset, etc...

    So do you see how your fragment program is a piece of dynamic code: it always uses different values, depending on which pixel it's currently running for? And do you see how the UV coordinates are not "changed", they're just modified just before they are used in the code?

    ask if you don't get it yet, it's important that you grasp this stuff :)
  • Viento
    Thanks for that reply. You are totally right, I think I have been completely mislead by poorly written online tutorials. I thought I had to manipulate the UVs themselves rather then the individual pixels, which makes far more sense. I guess I am more artistically minded than mathematically minded so I have been learning practically from examples.

    EDIT:

    I have this frag shader now. It seems to be rotating the texture which is great, but it only works on a quad. If I apply it to a cube, for example, the texture is rotated across the whole object rather than each face. I also wonder if this is the most efficient way I could be doing this. :poly142:

    uniform sampler2D baseMap;
    uniform float timer;
    uniform float rotspeed;
    uniform vec2 offset;

    varying vec2 Texcoord;

    void main( void )
    {

    float cosX,sinX;
    float cosY,sinY;

    sinX = sin(rotspeed*timer);
    cosX = cos(rotspeed*timer);

    sinY = sin(rotspeed*timer);
    cosY = cos(rotspeed*timer);

    mat2 rotationMatrix = mat2( cosX, -sinX,
    sinY, cosX);

    float scaletimer=timer;

    vec2 newcoords=((Texcoord-offset)*(rotationMatrix));
    newcoords+=offset;




    gl_FragColor = texture2D( baseMap, newcoords );

    }
  • Xoliul
    Offline / Send Message
    Xoliul polycounter lvl 16
    Well the way the rotation calculations affect your final result greatly depends on how your object is unwrapped. Just visualize it by going into your UV editor, selecting all UV's, and rotating aroung the centrepoint. That's what you'll be doing in code as well.
    If you want it to look like every face of the cube is rotating around its' own centrepoint, you'll have to unwrap every face overlapping, in Max this would be the default unwrapping of a cube. You can't really have unique unwrapping rotating around its own face centre...

    Maybe show what you're trying to achieve with a screenshot?
  • Viento
    Excellent, I have fixed it now.

    I am viewing the shader in RenderMonkey and it seems that the default cube model it comes with has its UVs layed out as a cross shape. I exported a default cube from Max and the shader looks perfect now. It was only a simple effect - I was trying to make a fan blade spin.

    Thanks for all the help. I think I need to find a book or two about GLSL!
Sign In or Register to comment.