- Home /
The question is answered, right answer was accepted
Shader vertex position depends on camera ?
Hi guys,
I'm new to cg shader writing and I encounter a problem. I'm trying to make variation on the color of the vertex using their world position.
So I watched some exemple on the web to see how to do that and I found that : href="http://en.wikibooks.org/wiki/CgProgramming/Unity/ShadinginWorldSpace">http://en.wikibooks.org/wiki/Cg">http://en.wikibooks.org/wiki/CgProgramming/Unity/ShadinginWorldSpace
href="http://en.wikibooks.org/wiki/Cg_Programming/Unity/Shading_in_World_Space">http://en.wikibooks.org/wiki/Cg_Programming/Unity/Shading_in_World_Space">http://en.wikibooks.org/wiki/Cg_Programming/Unity/Shading_in_World_Space but it seems that output.positioninworld_space = mul(_Object2World, input.vertex); varies with the camera position and i can't any other exemple that are not using this =/
thank you by advance for your help !
Here is the code of my shader :
Shader "MFMobile/Cloud" {
Properties {
_MainTex ("RGBA Texture Image", 2D) = "white" {}
_CloudBaseColor ("CloudBaseColor", Color) = (0.5,0.5,0.5,1)
_CloudPositon("Cloudposition",Vector)= (0.0,0.0,0.0,0.0)
}
SubShader {
Tags {"Queue" = "Transparent"}
Pass {
Cull Front // first render the back faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha OneMinusSrcAlpha
// blend based on the fragment's alpha value
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
uniform sampler2D _MainTex;
uniform float _Cutoff;
uniform float4 _CloudPositon;
struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
};
vertexOutput vert(vertexInput input)
{
vertexOutput output;
output.tex = input.texcoord;
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
}
float4 frag(vertexOutput input) : COLOR
{
return tex2D(_MainTex, float2(input.tex));
}
ENDCG
}
Pass {
Cull Back // now render the front faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha OneMinusSrcAlpha
// blend based on the fragment's alpha value
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
uniform sampler2D _MainTex;
uniform float _Cutoff;
uniform float4 _LightColor0;
uniform float4 _CloudBaseColor;
uniform float4 _Camera2World;
uniform float4 _CloudPositon;
struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
float4 cloudShadow : COLOR;
float3 worldPos : TEXCOORD1;
};
vertexOutput vert(vertexInput input)
{
vertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
// transform into worlspace
float4 world_space_vertex = mul( _Object2World, input.vertex );
if(world_space_vertex.y>1){
output.cloudShadow = float4(0.9,0.9,0.9,1.0);
}else{
output.cloudShadow = _CloudBaseColor;
}
output.tex = input.texcoord;
return output;
}
float4 frag(vertexOutput input) : COLOR
{
return float4 (tex2D(_MainTex, float2(input.tex)) *_LightColor0*input.cloudShadow);
}
ENDCG
}
}
// Fallback "Unlit/Transparent"
}
Answer by Bunny83 · Jul 11, 2014 at 10:15 PM
_Object2World does what the name suggest. So there is for sure no camera position involved.
_Object2World is actually what the object's Transform component represents. It transforms a local space position into worldspace. This matrix is also called "M" (model-matrix) and is also part of the combined MVP matrix which also contains the View and Projection matrix. The View matrix is actually the inverse Transform of the camera. So it transforms worldspace positions into the camera's local space. The Projection matrix finally does the 3D->2D mapping either in a perspective or orthographic way.
It might help if you showed your actual shader code so we can see where you did what.
Thanks for your help !
I updated my message with the code of the shader. I'm trying to make a shader for clouds rendering and my first idea was to use the vertex world position to make the cloudbase darker.
There is probably a better way to do it but I think it is a good start to learn cg shader writing ;)
I took a look at your shader and after some tests it seems that _LightColor0 has a very weak color and it's alpha is 0. At least my fron faces aren't visible at all. Also in Unity's Lighting.cginc
they always ignore the alpha channel.
All in all this shader looks alot like "work in progress" as there are many parameters which are either not used and / or not added to the properties list at the top (like Cutoff, _Camera2World and _CloudPositon)
I'm not sure what exactly this shader should do. Anyways I can't reproduce what you state in your question. If i move a sphere at position (0,1,0) the upper half gets the 0.9 as multiplier and the lower half gets the cloudbasecolor.
It's generally not a good idea to use "if statements" in shaders. That's because the GPU works totally different than a CPU. The GPU is designed to perform the same actions on a huge amount of data. Branches can kill the performance, however yours probably won't hurt much as the shader compiler try to convert them to an expression.
The next thing is doing hard switches of colors at vertex level are very visible and can cause strange artefacts. Usually you do a lerp in a certain range around the desired border. Also this should be done in the fragment shader to get a smooth transition.
Hey in fact you were right it is working on a primitive mesh. The problem was that I was using it as a shader for particles and in order to get the world coordinates of particles vertex you must multiply by _Camera2World matrix not by _Object2World ;)
See here for an exemple I found : https://gist.github.com/Farfarer/158b23f694c2c995f93e
I have still some work on this shader because that the code is not clean but here is the result for the moment =)
Well, particle systems are a completely different topic....
What render mode do you use in your particle renderer? All billboard modes are simulated in viewspace while the "mesh" mode is simulated in local space. That's why you have to use _Camera2World and not _Object2World in this case.
To be honest this is something that should be more documented.
Yeah I'm using billboard mode that's why it was not working with _Object2World.
The result is quite good now I have to learn what's optimized and what's not ;)
I found a good series of tutorials on writing shader for unity here :
http://cgcookie.com/unity/cgc-courses/noob-to-pro-shader-writing-for-unity-4-beginner/
Follow this Question
Related Questions
Prevent ColorMask obscuring parts of an object's mesh 0 Answers
Unexpected behavior in Vertex/Fragment shader when using saturate method (CG) 0 Answers
Shader Vertex Position During Animation 1 Answer
Adding transparency to vertex shader? 0 Answers
How to get the position of a vertex in a particles-shader? 0 Answers