# Simple Cross Section Shader

Discussion in 'Shaders' started by apple_motion, Nov 14, 2009.

1. ### apple_motion

Joined:
Jul 2, 2009
Posts:
169
chenwanwan13 and GarthSmith like this.

Joined:
Aug 11, 2006
Posts:
3,355
3. ### apple_motion

Joined:
Jul 2, 2009
Posts:
169
Thanks for the link Daniel ! I just learnt how to use Shader.SetGlobalMatrix() from there

Also, we seem to use the same method, except I just made everthing inside the shader. (because, I am lazy )

Here is the test code of mine version... (diffuse shading only at the moment)
Code (csharp):
1. // Fast Edition - Single Pass
2.
4. {
5.     Properties
6.     {
7.         section_depth ("section depth (x, y, z, depth)", vector) = (0,0,0,0.15)
8.         section_color ("section color", color) = (0.5,0.1, 0.1, 1)
9.
10.         color_map ("color map", 2D) = "white" {}
11.
12.     }
14.     {
15.         Pass
16.         {
17.             CULL OFF
18.
19. CGPROGRAM //--------------
20. #pragma vertex   vertex_shader
21. #pragma fragment fragment_shader
22.
23. #include "UnityCG.cginc"
24.
25. uniform float4 section_depth;
26. uniform float4 section_color;
27. uniform sampler2D color_map;
28.
29. float4x4 rotate(float3 r)
30. {
31.     float3 c, s;
32.     sincos(r.x, s.x, c.x);
33.     sincos(r.y, s.y, c.y);
34.     sincos(r.z, s.z, c.z);
35.     return float4x4( c.y*c.z,    -s.z,     s.y, 0,
36.                          s.z, c.x*c.z,    -s.x, 0,
37.                         -s.y,     s.x, c.x*c.y, 0,
38.                            0,       0,       0, 1 );
39. }
40.
41. struct a2v
42. {
43.     float4 vertex   : POSITION;
44.     float4 color    : COLOR;
45.     float2 texcoord : TEXCOORD;
46.     float3 normal   : NORMAL;
47. };
48.
49. struct v2f
50. {
51.     float4 position : POSITION;
52.     float2 texcoord : TEXCOORD0;
53.     float3 normal   : TEXCOORD1;
54.     float4 vertex   : TEXCOORD2;
55.     float4 mask     : TEXCOORD3;
56. };
57.
58. v2f vertex_shader( a2v IN )
59. {
60.     v2f OUT;
61.
62.     float4x4 r   = rotate(radians(section_depth.xyz) +_SinTime.xyz);
63.     float4 c     = float4(IN.vertex.xyz,1);
64.
65.     OUT.mask     = mul(r, c);
66.     OUT.position = mul(glstate.matrix.mvp, IN.vertex);
67.     OUT.texcoord = IN.texcoord;
68.     OUT.normal   = IN.normal;
69.     OUT.vertex   = IN.vertex;
70.
71.     return OUT;
72. }
73.
74. void fragment_shader(   v2f IN,
75.                         out float4 finalcolor : COLOR)
76.
77. {
78.     if(IN.mask.x > section_depth.w)
80.
81.     float3 obj_view_dir = IN.vertex.xyz - _ObjectSpaceCameraPos;
82.     float fd = dot(obj_view_dir, IN.normal);
83.     float3 N = (fd > 0) ? float3(1,0,0) : IN.normal;
84.
85.     N = mul(glstate.matrix.invtrans.modelview[0], float4(N, 1));
86.     float diffuse = saturate(dot(glstate.light[0].position, N));
87.
88.     finalcolor = float4(0,0,0,1);
89.     if (fd > 0)
90.     {
91.         finalcolor.xyz = section_color *(diffuse *0.6 +0.4);
92.         return;
93.     }
94.     finalcolor.xyz = tex2D(color_map, IN.texcoord).xyz *(diffuse *0.6 +0.4);
95. }
96. ENDCG //--------------
97.
98.         } // Pass
99.     } // SubShader
100. } // Shader
(Remark: the " +_SinTime.xyz" could be deleted. That's just for the demo)

EDIT: The old attachment "cross_section_v004.shader" has been replaced by the following one.
Code (csharp):
1. r *= float4x4(1,-1,-1, 0, -1, 1,-1, 0, -1,-1, 1, 0, 0, 0, 0, 1 );
(In the "004a" version, one more line is added onto it. since, the "section_depth.xyz" need to be inverted before assign to the cap's normal.)

#### Attached Files:

File size:
3.6 KB
Views:
3,201
geniusz likes this.
4. ### antenna-tree

Joined:
Oct 30, 2005
Posts:
5,324
Cool shader, thanks for sharing it. How are you hollowing out the spheres in the video?

5. ### apple_motion

Joined:
Jul 2, 2009
Posts:
169
Simply model it, a small flipped-face sphere inside a bigger sphere

In fact, you bring out a very good idea, why not add a "thicker" function onto the shader too. so that, I don't need to touch the modeling program anymore. (... save up some time to enjoy my coffee )

Many Thanks !

6. ### monark

Joined:
May 2, 2008
Posts:
1,598
In my version I add a simple lighting equation to the cut surface too, that way it doesn't always have to be constant shaded. Nice that you managed to get all the clipping code into the shader though, very handy for clipping different objects with different planes.

7. ### apple_motion

Joined:
Jul 2, 2009
Posts:
169
Surely, I will add this in my code later

In fact, I still looking for the way to work with intersecting closed objects, by making a real cap

I have this now...

(2 spheres, left with "cross section" shader and right with diffuse shader)

I am working on this method now... re-assign the depth value, but not success when the angle of the clipping plane is changed :s

Code (csharp):
1. float4 c     = float4(IN.vertex.xyz,1);
2. OUT.vpos     = mul(glstate.matrix.modelview[0], c);
Code (csharp):
1. float3 N = IN.normal;
2. float z = IN.vpos.z;
3.
4. if (IN.vpos.z > section_depth.w)
5. {
6.     N = float3(1,0,0);
7.     z = section_depth.w;
8. }
9.
10. float near = _ProjectionParams.y;
11. float far  = _ProjectionParams.z;
12.
13. float a = -far/(far-near);
14. float b = -far*near/(far-near);
15. depth   = (a*z+b)/(-z);
Any new idea ??

8. ### monark

Joined:
May 2, 2008
Posts:
1,598
I guess you'd actually need to project the x,y coordinate onto the clipping plane to get the depth and then test if the object depth was behind.

This is a very interesting approach, I really need to solve the intersection problem to make this useful for what I want and what you are suggesting here is interesting. The question is how do you determine what is "inside" so as to only test the depth for the bits that should be capped? When 2 objects intersect you can't rely on the normals any more.

9. ### Peter Hou

Joined:
Oct 12, 2010
Posts:
66
The attached shader doesn't appear to work in Unity 3.1 - is it still under development?

10. ### apple_motion

Joined:
Jul 2, 2009
Posts:
169
because that poor guy still using unity 2.6 to do the development.... in fact, the development will be resumed very soon

11. ### kenshin

Joined:
Apr 21, 2010
Posts:
940
Hello Apple_motion, your work is very interesting.

Did you updated the shader for Unity 3.3?

12. ### diablo

Joined:
Jan 3, 2011
Posts:
736
Hi Apple_Motion,

I second the request for a Unity 3.3 update! Anyone else interested in this?

El Diablo

13. ### diablo

Joined:
Jan 3, 2011
Posts:
736
bump! Unity 3.3 update, willing to pay!! Apple motion, where are you?

14. ### qholmes

Joined:
Sep 17, 2010
Posts:
162
Yes bump here too??

Q

Joined:
Jan 3, 2011
Posts:
736
bump

Joined:
Feb 28, 2011
Posts:
311
bump

Joined:
Jan 3, 2011
Posts:
736
Bump

18. ### solmyr-fr

Joined:
Jun 18, 2009
Posts:
24
I wanted to do the same thing and I believe the problem was because Unity 3 use Surface shader (so things are handled in another way ...)

The instruction "clip" can be used in the surface function . For instance, for a plane which the equation is a.x +b.y + c.z + d = 0 :

Code (csharp):
1.
3. {
4.    Properties
5.    {
6.       _MainTex ("Texture", 2D) = "white" {}
7.       _a ("_a",Float) = 0.0
8.       _b ("_b",Float) = 0.0
9.       _c ("_c",Float) = 0.0
10.       _d ("_d",Float) = 0.0
11.       _clip ("_clip",Float) = 0
12.     }
14.       Tags { "RenderType" = "Opaque" }
15.       Cull Off
16.       CGPROGRAM
17.       #pragma surface surf Lambert
18.       struct Input {
19.           float2 uv_MainTex;
20.           float3 worldPos;
21.       };
22.
23.       sampler2D _MainTex;
24.       float _a,_b,_c,_d,_clip;
25.
26.       void surf (Input IN, inout SurfaceOutput o)
27.       {
28.           if(_clip == 1)
29.           {
30.              clip (_a *IN.worldPos.x +
31.                 _b *IN.worldPos.y +
32.                 _c *IN.worldPos.z +
33.                 _d > 0 ? -1 :1);
34.          }
35.
36.           o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
37.       }
38.       ENDCG
39.     }
40.     Fallback "Diffuse"
41.   }
42.
In a Unity script; you can activate the clipping plan using Shader.SetGlobalFloat("_clip",1); and move the plan along its normal using Shader.SetGlobalFloat("_d",d); However it seems that you must unexpose the variables from the property block if you want a Shader.SetGlobal function to work.

You can of course do a script to compute _a _b _c _d parameters according to a plan (gameobject) inside the scene to let the user create easily a clipping plane with a desired orientation;

You can rewrite other defaut Unity shaders (bump, alpha, etc...) , you'll juste have to add some properties and the clip instruction.

Tom

Last edited: Aug 26, 2011
19. ### diablo

Joined:
Jan 3, 2011
Posts:
736

Last edited: Sep 2, 2011
20. ### solmyr-fr

Joined:
Jun 18, 2009
Posts:
24
No, it's not an update because it doesn't work the same way.
It just uses the "clip(-1)" function in the surface shader to exclude pixel that will be on one side of the plane for objects that use this shader so it creates a hole in the object.

I havent code the part to fill the intersected zone with a color/texture. I don't know how to do it but you can however easily change the color of a small part of the original object surface wich is near the clipping plane.

Code (csharp):
1.
2. void surf (Input IN, inout SurfaceOutput o)
3. {
4.      float dist = _a *IN.worldPos.x +_b *IN.worldPos.y +_c *IN.worldPos.z +_d;
5.       if(_clip == 1  abs(dist) < 0.02)[COLOR="yellowgreen"]// fill the near surface in yellow[/COLOR]
6.       {
7.         fixed4 c = fixed4(1,1,0,1);
8.         o.Albedo = c.rgb;
9.         o.Alpha = c.a;
10.      }
11.      else if(_clip == 1  dist < -0.02)  [COLOR="yellowgreen"]// exclude pixel outside the plane[/COLOR]
12.      {
13.          clip(-1);
14.      }
15.      else[COLOR="yellowgreen"] // normal diffuse display[/COLOR]
16.      {
17.         fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
18.         o.Albedo = c.rgb;
19.         o.Alpha = c.a;
20.      }
21. }
22.

21. ### diablo

Joined:
Jan 3, 2011
Posts:
736
Ahhh, I see, this does the clipping but doesn't fill it in. Here's another bump.

Joined:
Jan 3, 2011
Posts:
736
bumped

23. ### kurylo3d

Joined:
Nov 7, 2009
Posts:
1,123
Hey I am using this shader in a tablet application, I was wondering if there are any ways to optimize it for better performance. When i zoom in and it encompasses the screen i just drop to like 2 fps.... I am not familiar with writing shaders ands I was wondering first is there a way to make it more optimized, and second... is there a way to make it so it only updates the cross section amount only when i change it with a script?

24. ### Bezzy

Joined:
Apr 1, 2009
Posts:
75
I read somewhere in the mobile optimization section of unity that the discard function could be especially slow on mobile devices?

http://unity3d.com/support/documentation/Manual/Optimizing Graphics Performance.html

It's possible that a mesh based approach might be faster in this instance? Though perhaps not for everything in your scene all at once. Or perhaps to some tricks with multiple camera clipping planes? There's a some settings on the camera to set up individual clipping planes per layer:

http://unity3d.com/support/documentation/ScriptReference/Camera-layerCullDistances.html

Unfortunately, it doesn't give access to NEAR clipping planes per layer, so you may have to forgo this approach and have multiple cameras, pehaps?

25. ### Hummelwalker

Joined:
Oct 28, 2010
Posts:
119
Hello,

I'm not very familar with Shaders. Can anybody explain what I have to do with solmyr's shader to make a cross section?

26. ### RyuMaster

Joined:
Sep 13, 2010
Posts:
468
Thank you very much!! It really works as I wanted it to. What abcd stand for? I want to feed it gameobject plane, should I pass transformation matrix or something like that?

### Digital Ape

Joined:
Apr 11, 2010
Posts:
29,725
If you don't mind it not being solid, you can render in a couple of passes, or just adjust the near clip plane of the 2nd camera rendering the object you want to cross section. By adjusting near clip, you do not have any overhead on mobile. Such sacrifices may be needed. To fill in the gaps will be far more expensive.

28. ### RyuMaster

Joined:
Sep 13, 2010
Posts:
468
Ah, I see now, a == position.x, b == position.y and c == position.z
"d" is a bit of mystery - I assume it just clips in one direction, when I adjust d. What it is actualy stands for in world-space? I want somehow to take plane rotation into account, and clip everything which is on a one side of it

29. ### kurylo3d

Joined:
Nov 7, 2009
Posts:
1,123
@hippocoder

Yea i wanted to do that at first, but the problem is I have multiple objects on top of one another inside and out... So i cant seperate them with seperate cameras... it has to be done at the shader level.

30. ### chrisirhc

Joined:
Jan 26, 2012
Posts:
1
Thanks, interesting implemention of free clipping in surface shaders. However I cannot figure out how to manage some correct capping, if anyone has any clue...

31. ### sjm-tech

Joined:
Sep 23, 2010
Posts:
734
I know that it is a old thread ... but there is no other new resource regarding cross-section shaders... so for use the original apple_motion(thanks) shader in unity 3.5, whaiting a help of a expert shader user....you can remove the gles compiling errors excluding GLES renderers by adding "#pragma exclude_renderers gles" under "CGPROGRAM".
I like very much the (fake) fill effect of the cross-section ...but it don't work well with intersected geometryes.
Could be interesting to have a renew shader with an implementation of the filling of the section.
Max

#### Attached Files:

File size:
29.8 KB
Views:
6,104
File size:
42.2 KB
Views:
4,927
• ###### \$cross_section_v004a_337-no GLES.shader
File size:
3.7 KB
Views:
2,175
Last edited: Jun 18, 2012
32. ### Xeal

Joined:
Jul 10, 2012
Posts:
4
As sjm tech says, it would be really useful to fill the section.

I was thinking of extracting a silhouette texture from the shader and then apply it like a cookie-cutter to a Plane mesh.
However, my shader's skills are not sufficient enough to do it...

Does anyone has already done something similar, or have some clues to begin with ?

33. ### proso

Joined:
May 24, 2012
Posts:
67
I'm looking for something like this. Not a shader, but a tool that can clip a whole object (ofcourse with fill). Is there something like that? Or is someone willing to make that? I think more people can use this.

34. ### thomes

Joined:
Dec 6, 2012
Posts:
8
hello

hope for a little help with giving over the gui-slidervalue to the clipshader parameters _d.

i found a javascript for the GUIslider.now i need the value XXX in the script below to change the clipshader _d value

many thanks for help
thomes

Last edited: Dec 14, 2012
35. ### thomes

Joined:
Dec 6, 2012
Posts:
8
please, i know it seems easy for you, but it woul´d be nice to get help for my question.please also see post above

i tried to access the float-property "_d" in the clipshadermat with things like this...

renderer.material.float_d = hSliderValue;

but this and any other tries did not work.

if anyone coul´d explain me in 2 sentences the right way

big thanks for your time
thomes

Last edited: Dec 21, 2012
36. ### Cascho01

Joined:
Mar 19, 2010
Posts:
1,347
Could someone change sjm techs shader so that the section color is emissive?

Wouldn´t it theoretically work to project a texture onto the flipped inner surfaces?

Last edited: Jan 16, 2013
37. ### sjm-tech

Joined:
Sep 23, 2010
Posts:
734
just to clarify... the shader was made by apple_motion (all credit to him) i make only a small fix to make it usable in 3.5...
after this clarification...could be nice to have a new version with some improvements!

Joined:
Jul 13, 2012
Posts:
54

File size:
3.6 KB
Views:
2,183
39. ### Alan47

Joined:
Mar 5, 2011
Posts:
163
@bilke: I just downloaded your edited version and I'm still getting two compile errors. Could you perhaps be so kind and fix the errors, since I've no idea about shaders internals... ^_^'

Also, a quick example on how to control the cut plane would be very helpful.

Thanks,

Alan

40. ### ripol

Joined:
Oct 23, 2012
Posts:
17
Hi,

I was looking to exactly this kind of shader, I'm just starting working with them, So can you plz show some example using this shader or can you explain me how can I use it.

Thank you in advance

rp

41. ### tomekkie2

Joined:
Jul 6, 2012
Posts:
992
Hey, @sjm tech, I was just playing with various shaders. (on 4.3 Pro)
I don't know much about shaders, but one from this thread seemed to lose the baked shadows.
So I made a similar one, this time basing on the "slices" example from Unity docs:

It required definately less lines of code and shadows (on the front faces, none on the backfaces) are preserved.
I am wondering now whether it would be possible to make a version for transparent materials.

Last edited: Dec 16, 2013
42. ### sjm-tech

Joined:
Sep 23, 2010
Posts:
734
Hi tomekkie2, I also don't know much about shaders .
I hope that a shader guru can give you more interesting answers.
Max

Last edited: Dec 16, 2013
43. ### tomekkie2

Joined:
Jul 6, 2012
Posts:
992
The outcome of my experiments can be seen here:

My choice of free Unity models possibly makes this to look attractive but doesn't doesn't give good results, because often the meshes in general are opened, with no backfaces where would not be seen, no faces on the bottom.

On the contrary, most technical meshes are closed.

So this is just a surface "slices" shader from Unity docs examples with a few lines deleted/added.

The webplayer is here.

44. ### samcsss

Joined:
Sep 1, 2012
Posts:
5
@tomekkie2,
thats really awesome. Is there any chance of posting your code?

45. ### Ippokratis

Joined:
Oct 13, 2008
Posts:
1,521
Happy 2014.
Code (csharp):
2. {
3.     Properties
4.     {
5.       _MainTex ("Texture", 2D) = "white" {}
6.       _section ("Section plane (x angle, y angle, z angle, w displacement)", vector) = (0,0,0,0.15)
7.       _Color ("Section Color", Color) = (1,1,1,0)
8.     }
9.
11.     {
12.       Tags { "RenderType" = "Opaque" }
13.       Cull Off
14.
15.       CGPROGRAM
16.       #pragma surface surf Lambert
17.
18.       struct Input
19.       {
20.           float2 uv_MainTex;
21.           float3 worldPos;
22.           float3 viewDir;
23.           float3 worldNormal;
24.       };
25.
26.       sampler2D _MainTex;
27.       sampler2D _BumpMap;
28.       float4 _section;
29.       fixed4 _Color;
30.
31.       void surf (Input IN, inout SurfaceOutput o)
32.       {
33.         float toClip = _section.x * 0.1 * IN.worldPos.x +
34.                        _section.y * 0.1 * IN.worldPos.y +
35.                        _section.z * 0.1 * IN.worldPos.z +
36.                        _section.w;
37.
38.         clip( toClip);
39.
40.         float fd = dot( IN.viewDir, IN.worldNormal);
41.
42.         if (fd.x > 0)
43.         {
44.             o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
45.             return;
46.         }
47.
48.         o.Emission = _Color;
49.       }
50.       ENDCG
51.     }
52.     Fallback "Diffuse"
53.  }

Last edited: Jan 8, 2014
BeauJames, Harinezumi and shanecelis like this.
46. ### tomekkie2

Joined:
Jul 6, 2012
Posts:
992
Hey, Ippokratis, I have also tried to make it in one pass in both surface as well as vertex shaders, basing on dot between viewing and normal, but I keep on getting a crossection color on the edge:

I don't get any edge artifacts when I going with two passes.

47. ### Ippokratis

Joined:
Oct 13, 2008
Posts:
1,521
Yes, I observed it as well. It became less obvious when I used a high poly sphere.
Using two passes seems a better approach, thanks for mentioning.

48. ### m_bec

Joined:
Feb 3, 2014
Posts:
3
Hi Ippokratis,

If it's not too much trouble, would you mind explaining in simpler terms what's going on in the shader and how someone with no extensive Unity experience might use it?

If I create a sphere and apply the shader, should it work automatically? Or do I apply the shader to a plane and have the plane intersect the sphere?

Thanks!

EDIT: Nevermind, I am an idiot. Figured it out!

Last edited: Feb 3, 2014
49. ### m_bec

Joined:
Feb 3, 2014
Posts:
3
Hi Ippokratis,

Is there a way to edit your shader so that it also has alpha values that can be increased/decreased from another script?

Thanks!

50. ### solmyr-fr

Joined:
Jun 18, 2009
Posts:
24
m_bec : on what part of your object do ou want the alpha value ?
-> on the clipped part : not possible by definition because the instruction "clip()" of the shader implies that concerned polygons are not rendered by your GPU.
-> the remaining part : yes, do not forget "#pragma surface surf Lambert alpha" and to set your output "SurfaceOutput o" alpha value "o.Alpha = _Color.a;"

Example : a human heart with 2 clipping planes
- some meshes use a default unity shader (the internal cavities) and are not affected by the clipping plane
- some others meshes (external parts of the heart) use the clip plane shader and are cut by the 2 clipping planes.

EDIT : even with 2 pass, you can have some ugly artefacts with alpha ... so I recommand to keep the shader as a Opaque.

Last edited: Feb 20, 2014