3. Shaping Functions Part.1
10. Drawing a circle
10.1 The Cg methons you really need to know
- step(edge,n)
- smoothstep(edge0,edge1,n)
- clamp(n,min,max)
- lerp(x,y,a)
We want inCircle to be 1.0 when length(i.position.xy) < 0.25 and 0.0 when is longer.Quad is from (-0.5,0.5,0) to (0.5,0.5,0)
Now caculate the color through specific point :
Black Point:
i.position.xy = float2(-0.5,0)
_Point on the middle left
length(i.position.xy) = 0.5
_length
step(0.25,0.5) = 1.0
_return 1,but we need not yellow here
1.0-step(0.25,0.5)=0
_now black
Yellow Point:
i.position.xy = float2(0,0.1)
_Point in circle
length(i.position.xy) = 0.1
_length
step(0.25,0.1) = 0
_return 0,but we need not black here
1.0-step(0.25,0.1)=1
_now yellow
so shader :
fixed4 frag (v2f i) : SV_Target
{
float inCircle = 1 - step(0.25, length( i.position.xy ));
//if just using inCircle will be white because of blue channel
fixed3 color = fixed3(1,1,0) * inCircle;
return fixed4(color, 1.0);
}
11. Drawing a square
We will create our own custom function.
Yellow inside Black outside:
float InRect(float2 center,float2 pt,float2 size)
{
//pt is pixel point
//center2pt vector
//return 1 when pos is inside a rectangle defined by size ande center
//ie. (pt - center) > - halfsize and (pt - center) < halfsize
float2 p = pt - center;
float2 halfSize = size/2;
// range : if inside return 1 else 0
float hor = step(-halfSize,p.x) - step(halfSize,p.x);
float ver = step(-halfSize,p.y) - step(halfSize,p.y);
return hor*ver;
}
fixed4 frag (v2f i) : SV_Target
{
float2 center = float2(0,0);
float2 pt = i.position.xy;
float2 size = 0.5;
float inRect = InRect(center,pt,size);
fixed3 color = fixed3(1,1,0) * inRect;
return fixed4(color, 1.0);
}
ENDCG
the most important part:
float2 p = pos - center;
Relative position…
float hor = step(-halfSize.x,p.x) - step(halfSize.x,p.x);
Inside (-halfSize,halfSize) pixel will be yellow,return 1
And x y code also can simplify our InRect function replacing the hor and ver with a single float2 vector:
// range : if inside return 1 else 0
// float hor = step(-halfSize.x,p.x) - step(halfSize.x,p.x);
// float ver = step(-halfSize.y,p.y) - step(halfSize.y,p.y);
float2 test = step(-halfSize,p) - step(halfSize,p);
//return hor*ver;
return test.x * test.y;
- You can use the step function more than once in a calculation
- If you are testing for the value being less than an edge value, then substract the return value from 1.0.
- You can create custom functions that return a value.
12.Moving our shap
12.1 Chanllenge
Make shape:
- Left of center
- 0.5 wide
- 0.25 high
fixed4 frag (v2f i) : SV_Target
{
//here is changed
float2 center = float2(-0.25,0);
float2 pos = i.position.xy;
float2 size = float2(0.5,0.25);
float inRect = InRect(center,pos,size);
fixed3 color = fixed3(1,1,0) * inRect;
return fixed4(color, 1.0);
}
ENDCG
}
}
}
12.2 Challenge2
Two squares:
- Yellow,size 0.3,left of center
- Green,size 0.4,right of center
fixed4 frag (v2f i) : SV_Target
{
float inRectYellow = InRect(float2(-0.25,0),0.3,i.position.xy);
float inRectGreen = InRect(float2(0.25,0),0.4,i.position.xy);
//1 + 0 = 1;so use plus
fixed3 color = fixed3(1,1,0) * inRectYellow + fixed3(0,1,0) * inRectGreen;
return fixed4(color,1.0);
}
ENDCG
13. Moving the square with mouse??
Texture coordinates for the Quad is from (0,0) to (1,1).
这里很奇怪,好像是说uv是从0到1,但是顶点的位置是-0.5到+0.5还蛮奇怪的,后面的课程应该会讲吧
How to move:
Just square center follow let mouseposition.
public class TrackMouse : MonoBehaviour
{
Material material;
Vector4 mouse;
//Camera camera;
// Start is called before the first frame update
void Start()
{
Renderer rend = GetComponent<Renderer>();
material = rend.material;
mouse = new Vector4();
mouse.z = Screen.height;
mouse.w = Screen.width;
//camera = Camera.main;
}
// Update is called once per frame
void Update()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray,out hit))
{
//textureCoord命中的纹理坐标
mouse.x = hit.textureCoord.x;
mouse.y = hit.textureCoord.y;
}
material.SetVector("_Mouse", mouse);
}
}
Use material.SetVector("_Mouse",mouse);
Change value _Mouse of Shader
//shader: change center place
fixed4 frag (v2f_img i) : SV_Target
{
float2 pos = i.uv;
float2 size = 0.2;
//_Mouse.xy = 0.1;
float inrect = InRect(_Mouse.xy,pos,size);
fixed3 color = fixed3(1,1,0) * inrect;
return fixed4(color,1.0);
}
ENDCG
14. Moving the shape over time
- Use the uniform -_Time
- Plus the trig functions : sin and cos
Use the charecter sin^2+cos^2 = 1
to make a circle moving
float2 center = float2(cos(_Time.y),sin(_Time.y)) * _Radius;
and use time.w
15. Rotating the square
Now we will make square rotate itself around center:
float2x2(c,-s,s,c)
15.1 Using the mul function
If you multiply in a matrix by a vector then the matrix is the first parameter and the vector is the second.
15.2 if pixel is in the rotated square(解决)
float2 pt = mul(mat,pos)
float2x2 getRotationMatrix(float theta)
{
float s = sin(theta);
float c = cos(theta);
return float2x2(c,s,-s,c);
}
fixed4 frag (v2f i) : SV_Target
{
float2 center = float2(0, 0);
float2 pos = i.position * 2.0;
float2 size = _Size;
float2x2 mat = getRotationMatrix(_Time.y);
float2 pt = mul(mat,pos);//new texture pos
float3 color = _Color * rect(pt, size, center);
return fixed4(color, 1.0);
}
ENDCG
}
如果要换中心旋转,那么就要先将pos减去center,做一个相对旋转,然后再加上center。
How to rotate(self) about a point :
float2 pt = mul(mat,pos-center) + center;
这里如果不懂的话,就得想到Games101了。
因为旋转和缩放是线性变换,我们构造旋转矩阵和缩放矩阵的时候都是针对原点来构造的,所以需要先把该点平移到原点,然后旋转,缩放,再平移回去。
15.3 Summary
- Trig functions, sin and cos take radian parameters.
- There are 2pie(6.28) radians in a full revolution
- You can create a matrix using float2x2,float3x3,float4x4
- In this course all matrices are square
- You can multiply a float2x2 by a float2,float3x3 by a float3,float4x4 by a float4
16. Changing the rotation centre and scaling
Now we want the rectangle to rotate around one of its corners.
如果正方形长宽都是0.3,那么就是(-0.15,-0.15)to (0.15,015)
计算的时候,也就是通过相对锚点的halfsize来限制。
16.1 Anchor
Add anchor variable:
拆解锚点,旋转之前将锚点移到原点,所以每一帧绘制的时候都要将锚点移到原点,这样才能确定该点的颜色。
float rect(float2 pt, float2 size, float2 center,float2 anchor){
//return 0 if not in rect and 1 if it is
//step(edge, x) 0.0 is returned if x < edge, and 1.0 is returned otherwise.
float2 p = pt - center;
float2 halfsize = size/2.0;
//也是一个相对关系,添加了都减去anchor
float horz = step(-halfsize.x - anchor.x, p.x) - step(halfsize.x-anchor.x, p.x);
float vert = step(-halfsize.y - anchor.y, p.y) - step(halfsize.y - anchor.y, p.y);
return horz*vert;
}
16.2 Scale
when scale = 1
[ 1 0 0 1 ] \begin{bmatrix} 1&0\\ 0&1\\ \end{bmatrix} [1001]
when scale = 2
[ 2 0 0 2 ] \begin {bmatrix} 2&0\\ 0&2\\ \end{bmatrix} [2002]
How to change the scale :
float2x2 getScaleMatrix(float scale)
{
return float2x2(scale,0,0,scale);
}
fixed4 frag (v2f i) : SV_Target
{
float2 center = float2(0.5, 0);
float2 pos = i.position * 2.0;
float2 size = _Size;
float2 anchor = _Anchor.xy;
float2x2 matr = getRotationMatrix(_Time.y);
float2x2 mats = getScaleMatrix(sin(_Time.y)/2 + 1);
float2x2 mat = mul(matr,mats);
float2 pt = mul(mat,pos-center) + center;
float3 color = _Color * rect(pt, size, center,anchor);
return fixed4(color, 1.0);
}
ENDCG