- Home /
Shader gradient moving with object
Shader gradient in object coordinates
How do I make a shader which will draw gradient colour (turning darker and brighter). Also, I want it to be surface shader Here, what I got so far:
Shader "Gradient Shader" {
Properties {
_Color ("Main Color", Color) = (1,.5,.5,1)
}
SubShader {
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Lambert
struct Input {
float3 worldPos;
};
float4 _Color;
void surf (Input IN, inout SurfaceOutput o) {
float f = mul(_Object2World, float4(IN.worldPos,0))[2];
o.Albedo = _Color.rgb*(0.7+ cos(f*100)*0.3 );
o.Alpha = 1;
}
ENDCG
}
FallBack "Diffuse"
}
now, problem is gradient is staying in world when object is moving. I expect that _Object2World multiplication should fix it, but it don't.
How do I make it stick to an object?
Answer by Owen-Reynolds · Sep 17, 2011 at 03:18 PM
worldPos
isn't "stuck" to the model, so can't be used to make an effect which is stuck to the model. The two things that are stuck to the model are uv_MainTex and the local vertex coords (the original ones, before the object ever moves.) The uv-coords tend to have odd patterns, so aren't very useful for gradient-type effects (for example, a leg might be uv-mapped upside-down, to make it fit better in the texture.)
Even though getting the original model coords is the single easiest thing to do, the surface shader doesn't provide them in Input
(bottom of http://unity3d.com/support/documentation/Components/SL-SurfaceShaders.html) If you look at the bottom of the examples section, it says how to add a vertex shader to compute this for you (the very last paragraph says to use this trick.) I didn't see where appdata_full
was defined, but the last two examples have enough info. To get model vertex data can use:
struct Input {
float3 pos; // unused name, to hold local, raw, vert pos
};
void vert (inout appdata_full v, out Input o)) {
// send raw vert coords, unmodified by world, into pixel shader:
o.pos = v.vertex.xyz;
}
// in surf:
float f = o.pos.xy; // or yz or xz
Not tested (but I have written a few surface shaders.)
I believe that Object2World has already been used. The built-in part takes the raw vert coords and mults by obj2world to know where to place the verts. It seems like you could use world2Object (if such a thing exists) or Object2world_invert(?) to reverse direction. But then you'd be doing lots of multiplying and dividing to get back the original numbers. Using a vert shader is more typing, but runs faster and can do more tricks.
I figured that out. Thanks! Here is my shader
Shader "CoinShader" {
Properties {
_Color ("$$anonymous$$ain Color", Color) = (1,.5,.5,1)
}
SubShader {
Tags { "RenderType"="Opaque" }
CGPROGRA$$anonymous$$
#pragma surface surf Lambert vertex:vert
float4 _Color;
struct Input {
float coord;
};
void vert (inout appdata_full v, out Input o) {
o.coord = v.vertex[2];
}
void surf (Input IN, inout SurfaceOutput o) {
float f = IN.coord;//mul(_World2Object, float4(IN.worldPos,0))[2];
o.Albedo = _Color.rgb*(0.7+ cos(f*100)*0.3 );
o.Alpha = 1;
}
ENDCG
}
FallBack "Diffuse"
}
Your answer
Follow this Question
Related Questions
Shader not working in OpenGL (Working in DirectX) 0 Answers
is there a way to make a gradient material, white to black, in Unity3D? 2 Answers
Getting horizontal gradient in unlit sprite shader even sprite is rotated 0 Answers
How to create a shader for a dynamic linear gradient 0 Answers
Newbie shader question for displacement/ gradient of a texture 1 Answer