This video goes through using a hierarchy of object in unity
seen from United States
seen from Russia
seen from United States
seen from United States
seen from United States
seen from Germany
seen from China
seen from Germany
seen from Poland
seen from Netherlands

seen from United States

seen from Russia

seen from Switzerland

seen from T1
seen from China
seen from Türkiye
seen from China

seen from France
seen from Türkiye

seen from United States
This video goes through using a hierarchy of object in unity
This video goes into more depth about event driven programming in unity
I need to convert the code to work with z values as well. This is the result of the edit, I have converted everything to float4, which does simplify things, and then I do the same thing to the z value that I do to the x:
half4 frag (v2f i) : COLOR { float4 color; float4 position, useBrick; position = i.untransformedPos / _BrickSize; if (frac(position.y * 0.5) > 0.5) { position.x += 0.5; position.z += 0.5; } position = frac(position); useBrick = step(position, _BrickPct); color = lerp(_MortarColor, _BrickColor, useBrick.x * useBrick.y * useBrick.z); return half4(color); }
The result, after tweeking the properties to make it look nice, is shown above.
Moving towards the other wall reveals that the horizontals are present, but only on one side.
It must be because I am only checking the x and y positions of the bricks, I need to include the z.
Editing the properties makes it look better, but where are the horizontal lines?
I won't edit the vertex shader at all, it currently passes through a position, which is all I need (I will get rid of the LightIntensity parameter).
So I will turn to the fragment shader itself.
First up are the variables:
vec3 color; vec2 position, useBrick;
I convert the colour into a float4 and the vec2s into a float2:
float4 color; float2 position, useBrick;
The next bit sets the position variable:
position = MCposition / BrickSize;
MCposition is the position value coming in from the vertex shader, which in our Cg shader is i.pos:
position = i.pos / BrickSize;
The next bit is a set of calculations.
position = i.pos / BrickSize; if (fract(position.y * 0.5) > 0.5) position.x += 0.5; position = fract(position); useBrick = step(position, BrickPct); color = mix(MortarColor, BrickColor, useBrick.x * useBrick.y); color *= LightIntensity;
I'm not sure if all the build in functions from GLSL exist in Cg, but I will assume they do as the functionality is normally similar. It will throw an error if I'm wrong. For now I can leave it the same except for deleting the bit about LightIntensity. The last bit outputs the colour value
gl_FragColor = vec4 (color, 1.0);
I will just copy the color variable into the corresponding line from my old shader:
return half4(color);
So this is the end result"
Shader "BrickShader" { Properties { _BrickColor ("Brick Color", Color) = (1.0, 0.3, 0.2,1) _MortarColor ("Mortar Color", Color) = (0.85, 0.86, 0.84,1) _BrickSize ("Brick Size", Vector) = (0.30, 0.15, 0, 0) _BrickPct ("Brick Pct", Vector) = (0.90, 0.85, 0, 0) } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" float4 _BrickColor; float4 _MortarColor; float4 _BrickSize; float4 _BrickPct; struct v2f { float4 pos : SV_POSITION; }; v2f vert (appdata_base v) { v2f o; o.pos = mul (UNITY_MATRIX_MVP, v.vertex); return o; } half4 frag (v2f i) : COLOR { float4 color; float2 position, useBrick; position = i.pos / _BrickSize; if (fract(position.y * 0.5) > 0.5) position.x += 0.5; position = fract(position); useBrick = step(position, _BrickPct); color = mix(_MortarColor, _BrickColor, useBrick.x * useBrick.y); return half4(color); } ENDCG } } Fallback "VertexLit" }
When I first ran this it failed because I had forgotten to put in the underscores "_" before the variable names. The next time it has more fundamental problems. It said there was an implicit cast from float4 to float2 on this line:
position = i.pos / _BrickSize;
And it was completely right, of course, i.pos is a float4 while position is a float2. To get around this I select just the x and y components of i.pos, using a special shader notation:
position = i.pos.xy / _BrickSize.xy;
I also need to do the same further down:
useBrick = step(position, _BrickPct.xy);
Another error says "'fract' : no matching overloaded function found at line 14", which I guess means that the fract function doesn't exist in Cg. A quick look on Google shows that it is actually "frac".
There are similar issues for the other built in functions. This page is useful:
http://http.developer.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html
mix also gives an error, the correct name is lerp (short for linear interpolation).
The last error is the following one which seems a bit more confusing:
Shader error in 'BrickShader': Program 'frag', variable/member "pos" has semantic "POSITION" which is not visible in this profile at line 40
It looks like it means that I can't access a position parameter in a fragment shader.
So I probably need to pass it as a non-position parameter. Looking back at the original vertex program I realised that MCposition was passed separately from the main position, and that is was, in fact the untransformed vertex position. I therefore added a new variable to the struct:
struct v2f { float4 pos : SV_POSITION; float4 untransformedPos; };
edited the vertex shader:
v2f vert (appdata_base v) { v2f o; o.pos = mul (UNITY_MATRIX_MVP, v.vertex); o.untransformedPos = v.vertex; return o; }
and changed the relevant line in the fragment shader:
position = i.untransformedPos.xy / _BrickSize.xy;
The result works and is shown above. It isn't exactly what I want it to look like but it's a start. The full code is here:
Shader "BrickShader" { Properties { _BrickColor ("Brick Color", Color) = (1.0, 0.3, 0.2,1) _MortarColor ("Mortar Color", Color) = (0.85, 0.86, 0.84,1) _BrickSize ("Brick Size", Vector) = (0.30, 0.15, 0, 0) _BrickPct ("Brick Pct", Vector) = (0.90, 0.85, 0, 0) } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" float4 _BrickColor; float4 _MortarColor; float4 _BrickSize; float4 _BrickPct; struct v2f { float4 pos : SV_POSITION; float4 untransformedPos; }; v2f vert (appdata_base v) { v2f o; o.pos = mul (UNITY_MATRIX_MVP, v.vertex); o.untransformedPos = v.vertex; return o; } half4 frag (v2f i) : COLOR { float4 color; float2 position, useBrick; position = i.untransformedPos.xy / _BrickSize.xy; if (frac(position.y * 0.5) > 0.5) position.x += 0.5; position = frac(position); useBrick = step(position, _BrickPct.xy); //useBrick = float2(0, 0); color = lerp(_MortarColor, _BrickColor, useBrick.x * useBrick.y); return half4(color); } ENDCG } } Fallback "VertexLit" }
That finally works, and I can edit the colour and size properties in the interfaces, as shown above.
However, they don't have any effect on the shader, there is more to do.
Translating the Brick shader 1
We have a nice shader in GLSL, but we need to turn it into Cg.
Let's start with the properties:
uniform vec3 BrickColor, MortarColor; uniform vec2 BrickSize; uniform vec2 BrickPct;
We need to create Unity properties for them so we can change them in the editor:
Properties { _BrickColor ("Brick Color", Color) = (1.0, 0.3, 0.2,1) _MortarColor ("Mortar Color", Color) = (0.85, 0.86, 0.84,1) _BrickSize ("Brick Size", 2D) = (0.30, 0.15) _BrickPct ("Brick Pct", 2D) = (0.90, 0.85) }
The two colour properties are of type Color as before.
I got the values from the application source code of the original brick shader.
For the type of the others, I looked on this page for the list of types, and 2D looked the most appropriate:
http://unity3d.com/support/documentation/Components/SL-Properties.html
I also need to create the variables within the Cg shader. The equivalents of vec3 and vec2 are float3 and float2 (but in fact I will use float4 for the colours to be consistent with how Unity colours work:
float4 _BrickColor; float4 _MortarColor; float2 _BrickSize; float2 _BrickPct;
This doesn't immediately work as I've deleted the _Color property that my shader used, but if I replace that with _BrickColor.
Even once I do that it doesn't work. I try deleting the 2D properties to see if that is the problem and it does work.
So the 2D properties are the problem. Looking more carefully it turns out that 2D doesn't mean 2D vector, it means a texture. Unity doesn't seem to support 2D vectors, only 4D ones, so I need to convert it.
Properties { _BrickColor ("Brick Color", Color) = (1.0, 0.3, 0.2,1) _MortarColor ("Mortar Color", Color) = (0.85, 0.86, 0.84,1) _BrickSize ("Brick Size", Vector) = (0.30, 0.15, 0, 0) _BrickPct ("Brick Pct", Vector) = (0.90, 0.85, 0, 0) }
I could have combined BrickSize and BrickPct into a single 4D vector but it is probably clearer for now not to do so. I also need to change the Cg variables:
float4 _BrickColor; float4 _MortarColor; float4 _BrickSize; float4 _BrickPct;