The cos and sin functions take radians. If you want to convert degrees to radians you just need to multiply the degree value by a value. Search online for the value to use, or use a calculator
But I want to scroll the texture based on an angle only. Therefore it would be a waste of performance to do this per pixel in the shader because the movement based 1 frame and not per pixel.
What I need is the math of rotate angle to UV(x,y)
Script:
Shader.SetVector("_AngleToUV", Angle2UV(angle));
Vector2 Angle2UV(double angle) {
///// .... code for transform angle to UV(x,y)... //////
return v2
Based on the small code, _AngleToUV.x and _AngleToUV.y should be calculated previously when it’s used in the shader.
And what values _AngleToUV.x/y should have if they transformed with -sin/-cos inside the shader? If your solution should be _AngleToUV.x/y = angle then your example produce complete wrong values eg on 180° (0.8011526 -0.5984601)
Hmm, I want to simply move/scroll a texture by UV’s based on a given angle in the surf shader. Not deform vertexes / texture in local space by an Extrusion. Perhaps it’s described not clear enough: Thread “Moving UVs of a texture by an angle 0-360°” A small math code example in c# here would be enough.
Vector2 Angle2UV(double angle) {
///// .... code for transform angle to UV(x,y)... //////
return v2
I simply provided those links to show you how to write a per vertex manipulation. The UV is a per vertex attribute. You can replace the extrusion code with something that modifies the UV instead…
The math for rotating a texture doesn’t change depending on if you’re doing it per pixel, or per vertex, or pre-computing it.
float s = sin ( radians );
float c = cos ( radians );
float2x2 rotationMatrix = float2x2( c, -s, s, c);
uv = mul ( uv - 0.5, rotationMatrix ) + 0.5;
Also that thread has several examples of doing the UV rotation in the vertex shader (in fact most are doing it that way).
If you don’t want to compute the cos and sin in the shader, then store them in a vector like you’re attempting. But make sure you’re passing the correct information to the Mathf.Cos and Mathf.Sin functions. They both take radians, just like cos and sin in the shader. Unity’s C# has a handy value to do that with.
Those values, 0.8011526 and -0.5984601, is what happens when you pass the value 180 to a Cos and Sin function expecting radians and not degrees. The math is correct, your expectation for the values to use are wrong. That’s why I mentioned degree to radian conversion in my first post.
Thank you boglus. I will test and check all this for performance too.
From dreamtech Mitko told me to use in script
var v2 = Quaternion.AngleAxis(angle, Vector3.forward) * -Vector2.up;
v2.x = -v2.x;
and passt to the shader.
Thank you very much to all.
I mean, that works, but it’s a lot more expensive. Calculating the quaternion using AngleAxis is doing the exact same cosine and sine calculations needed to do the rotation matrix, along with a ton more work, and then you’re applying that quaternion to the vector, which is also a ton more work, just to get the cosine and sine value.
So he just needs:
uv += AngleToSinCos(angle) * scrollAmount;
A guess a useful bit of information is the value that comes out of the AngleToSinCos function is a normalized Vector2 direction that should match the angle orientation he described above. If you multiply that by some value you can control the pan speed as well.
If I was going to do this in a shader I would do something like:
Sampling the texture from the world position requires IN.worldPos.xz * scale.xx.
But changing the angle in real-time cause the texture to float extremely fast and bad. Because the vector2 of frac() is now virtually up-scaled by 1000 through IN.worldPos.xz * = 0.001;
Cause a lot smoother results, but the texture jumps if frac() restarts from 0. frac() should become 0 if the moving length of the scrolledUV.x/y is > 1.
If you have an idea by use IN.worldPos.xz * scale.xx and angle change in real-time, without fast texture floating and jumping, you made my day!
Has nothing to do with the frac(), that’s you can’t change the angle with out it looking terrible using this method. If you need to change the angle and have everything behave gracefully you must do it in script. This is because you have to accumulate the offset each frame, which is something you can’t do in the shader.
In the shader you just have the angle, and the amount of offset (the time * pan rate), so if you change the angle you’re rotating that already offset position. Similarly changing the pan rate will look terrible too.
So, instead you’ll want to do something like this:
public float angle;
public float panSpeed;
public Material mat;
public String textureSlot = "_MainTex";
public Vector2 offset = Vector2.zero;
void Update() {
// get pan direction vector
Vector2 dir = AngleToSinCos(angle);
// calculate offset delta, add to current delta
offset += dir * Time.deltaTime * panSpeed;
// apply modulo to wrap offset between 0~1
offset.x = Offset.x % 1f;
offset.y = Offset.y % 1f;
// assuming you're using a texture slot with TRANSFORM_TEX in the shader
mat.SetTextureOffset(textureSlot, offset)
// otherwise pass it as a vector
// mat.SetVector("_PanOffset", offset);
}