I'm using GC
for writing shaders inside Unity3D
.
I'm using vertex colors attributes for passing some parameters to the shader. They won't be used so for defining colors, and should be forwarded from vertex shader to pixel shader without modifyng them.
This is the structure I'm taking as input from Unity3D to the vertex shader:
struct appdata_full {
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
fixed4 color : COLOR;
#if defined(SHADER_API_XBOX360)
half4 texcoord2 : TEXCOORD2;
half4 texcoord3 : TEXCOORD3;
half4 texcoord4 : TEXCOORD4;
half4 texcoord5 : TEXCOORD5;
#endif
};
This is the structure returned by vertex shader as input to the fragment:
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
fixed4 col: COLOR;
};
If I simply forward the parameter to the fragment shader, of course it will be interpolated:
v2f vert (appdata_full v)
{
v2f output;
//....
output.col = v.color;
}
I'd like to pass v.color
parameter not interpolated to the fragment shader.
Is this possible?if yes how?
EDIT
like Tim pointed out, this is the expected behavior, because of the shader can't do anything else than interpolating colors if those are passed out from vertex shader to fragment. I'll try to explain better what I'm trying to achieve. I'm using per vertex colors to store other kind of information than colors. Without telling all details on what I'm doing with that, let's say you can consider each color vertex as an id(each vertex of the same triangle, will have the same color. Actually each vertex of the same mesh).
So I used the color trick to mask some parameters because I have no other way to do this. Now this piece of information must be available at the fragment shader in some way. If a pass as an out parameter of the vertex shader, this information encoded into a color will arrive interpolated at the fragment, that can't no longer use it.
I'm looking for a way of propagating this information unchanged till the fragment shader (maybe is possible to use a global variable or something like that?if yes how?).
I'm not sure this counts for an answer but it's a little much for a comment. As Bjorke points out, the fragment shader will always receive an interpolated value. If/when Unity supports Opengl 4.0 you might have access to Interpolation qualifiers, namely 'flat' that disables interpolation, deriving all values from a provoking vertex.
That said, the problem with trying to assign the same "color" value to all vertices of a triangle is that the vertex shader iterates over the vertices once, not per triangle. There will always be a "boundary" region where some vertex shares multiple edges with other vertices of a different "color" or "id", see my dumb example below. When applied to a box at (0,0,0), the top will be red, the bottom green, and the middle blue.
Shader "custom/colorbyheight" {
Properties {
_Unique_ID ("Unique Identifier", float) = 1.0
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
fixed4 color : COLOR;
};
uniform float _Unique_ID;
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
float3 worldpos = mul(_Object2World, v.vertex).xyz;
if(worldpos[1] >= 0.0)
o.color.xyz = 0.35; //unique_id = 0.35
else
o.color.xyz = 0.1; //unique_id = 0.1
o.color.w = 1.0;
return o;
}
fixed4 frag (v2f i) : COLOR0 {
// local unique_id's set by the vertex shader and stored in the color
if(i.color.x >= 0.349 && i.color.x <=0.351)
return float4(1.0,0.0,0.0,1.0); //red
else if(i.color.x >= 0.099 && i.color.x <=0.11)
return float4(0.0,1.0,0.0,1.0); //green
// global unique_id set by a Unity script
if(_Unique_ID == 42.0)
return float4(1.0,1.0,1.0,1.0); //white
// Fallback color = blue
return float4(0.0,0.0,1.0,1.0);
}
ENDCG
}
}
}
In your addendum note you say "Actually each vertex of the same mesh." If that's the case, why not use a modifiable property, like I have included above. Each mesh just needs a script then to change the unique_id.
public class ModifyShader : MonoBehaviour {
public float unique_id = 1;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
renderer.material.SetFloat( "_Unique_ID", unique_id );
}
}