Hi!
How do I get a shader in unity that does something like this:
Specifically I want an infinite straight track to look bendy. Preferably with the ability to control the amount of bending from script.
Thanks!
Hi!
How do I get a shader in unity that does something like this:
Specifically I want an infinite straight track to look bendy. Preferably with the ability to control the amount of bending from script.
Thanks!
That is done with an image effect. Do you have unity Pro?
I have pro. I’m no shader lab pro but I assume there’s some kind of warping factor applied based on distance from the camera. There are a number of mobile games that use this same technique to create a curved surface from flat geometry but I can’t for the life of me find out how to do it.
I came across a possible answer to this a while looking for an answer to one of my own problems. Bunny83’s post here has a warping shader:
http://answers.unity3d.com/questions/288835/how-to-make-plane-look-curved.html
It’s actually all done in a vertex shader, which means the effect is fully compatible with Unity Free. The original GLSL by Gaeel is here.
Unfortunately, you can’t do this easily in a surface shader because the deformation happens in view space, whereas vertex modification functions in surface shaders have to operate in object space.
Here’s an adaptation of my vertex/fragment template to use Gaeel’s vertex modification:
Shader "Gaeel's Distortion" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
float2 uv_MainTex : TEXCOORD0;
};
float4 _MainTex_ST;
v2f vert(appdata_base v) {
v2f o;
//o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
//Gaeel's vertex modification starts here...
float4 pos = mul(UNITY_MATRIX_MV, v.vertex);
float distanceSquared = pos.x * pos.x + pos.z * pos.z;
pos.y += 5*sin(distanceSquared*_SinTime.x/1000);
float y = pos.y;
float x = pos.x;
float om = sin(distanceSquared*_SinTime.x/5000) * _SinTime.x;
pos.y = x*sin(om)+y*cos(om);
pos.x = x*cos(om)-y*sin(om);
o.pos = mul(UNITY_MATRIX_P, pos);
//...and ends here.
o.uv_MainTex = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
sampler2D _MainTex;
float4 frag(v2f IN) : COLOR {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
return c;
}
ENDCG
}
}
}
Thanks guys, I will take a look at those.
Thanks for posting this, I’d been looking at trying to port the original daxnitro GLSL curvature shader that Gael’s Distortion shader was based on into Unity but my shader skills were somewhat lacking. This has helped me immensely in porting it.
However I now have an issue where the curvature effect is applied even in the scene view, whereas with this Warp shader the effect is only applied when you actually run the game. Does anyone know why this would be?
My modified code is listed below and any help would be appreciated.
Shader "Curvature" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="AlphaTest" }
//LOD 200
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
float2 uv_MainTex : TEXCOORD0;
};
float4 _MainTex_ST;
v2f vert(appdata_base v) {
v2f o;
//o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
//Curvature vertex modification
float4 pos = mul(UNITY_MATRIX_MV, v.vertex);
float distanceSquared = pos.x * pos.x + pos.z * pos.z;
// World Radius = 500; World Radius Squared = 250000
pos.y -= 500 - sqrt(max(1.0 - distanceSquared / 250000, 0.0)) * 500;
o.pos = mul(UNITY_MATRIX_P, pos);
//
o.uv_MainTex = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
sampler2D _MainTex;
float4 frag(v2f IN) : COLOR {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
return c;
}
ENDCG
}
}
}
And the original daxnitro curvature code is:
void main() {
vec4 position = gl_ModelViewMatrix * gl_Vertex;
if (gl_Color.a != 0.8) {
// Not a cloud.
float distanceSquared = position.x * position.x + position.z * position.z;
position.y -= WORLD_RADIUS - sqrt(max(1.0 - distanceSquared / WORLD_RADIUS_SQUARED, 0.0)) * WORLD_RADIUS;
}
gl_Position = gl_ProjectionMatrix * position;
The scene view in the editor is using the same rendering routine as the game view does. This means any vertex shader effects are applied in a pass just as they would be in-game.
Thanks for the reply. I’d come to this conclusion myself and figured out that the original warp shader posted wasn’t active in the scene view because it uses shader functions that rely on time (sinTime etc.) and of course the scene view is static so nothing to generate the necessary time data.
I’ve fixed the issue now in my shader code by passing in a property for the radius value, so while editing I can turn the effect off and then when running the game I can switch it on.