How to write a Cross Section Shader

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By path9263

This tutorial outlines exactly what I want to do however I am really struggling to figure out how to implement it in Godot. If there is a better way to implement this same effect that’s fine too!

I would be happy even just with a basic, single plane cross section, though I would use multiple planes if I could figure it out. I am also not planning on having overlapping objects like the layers of the earth in the tutorial, just cutting a single object is good enough for me! I am also not concerned with how lighting affects the cross section, shadows would be nice but if it’s just a solid color that would be very much acceptable too.

Example of what I would like to achieve:
Cross Section Example

Thank you very much for any help or information!

Well, it’s not perfect and it’s done differently but I’ve come up with something. I think the technique in the tutorial is better but I don’t think stencil buffers are available in Godot. The main issue I am having now is with light and shadows. I would like for my cross-section shader to not affect the shadows of the original mesh, ie: I want the hidden parts to still cast shadows. What I have is #2 in the image below, what I want is #3 (Photoshopped).

enter image description here

Any suggestions on how to fix this would be very much appreciated!

For anyone interested, the shaders I used to make the cross section are as follows. There are two of them, the first one generates the red cross-section, take note of the render_modes, they are very important. The second draws the rest of the geometry that hasn’t been cut away. I set the second shader as the “next pass” property of the first shader. Right now they just hide everything that has a Z position that is < 0.

Shader One:

shader_type spatial;
render_mode blend_mix, depth_draw_alpha_prepass, unshaded, cull_front;

varying vec4 world_pos;
uniform vec4 sectionColor : hint_color;

void vertex() {
	world_pos = WORLD_MATRIX * vec4(VERTEX, 1.0);  // get coords as world coords
	VERTEX -= (NORMAL * 0.001); // bias to stop z-fighting with neighboring meshes
}

void fragment() {
	if(world_pos.z >= 0.0){  
				ALBEDO = sectionColor.rgb;
			} else {
				discard;
			}
}

Shader Two:

shader_type spatial;
render_mode blend_mix,cull_back,diffuse_burley,specular_schlick_ggx;

varying vec4 world_pos;
uniform vec4 baseColor : hint_color;

void vertex() {
	world_pos = WORLD_MATRIX * vec4(VERTEX, 1.0);  // get coords as world coords
}

void fragment() {
	ALPHA = 1.0;
	if(world_pos.z >= 0.0){  
				ALBEDO = baseColor.rgb;
			} else {
				discard;
			}
}

There is likely a better way of doing this, and if there is I’d love to know about it. I haven’t tried it on large complex meshes yet so I don’t know how it will to performance wise.

path9263 | 2018-05-09 02:16

After playing around with this some more… it just isn’t going to work how I have done it. It might work for a very simple effect but it practice it just has too many problems. It looks like access to the stencil buffer/frame buffers is really required to pull this off. Hopefully that will be an addition in 3.1. Or perhaps someone knows of a different way to do this that will work in Godot 3.0.X?

path9263 | 2018-05-10 16:27

:bust_in_silhouette: Reply From: 19PHOBOSS98

Never Give Up. I know it’s been 2 years but I just started making these:

I didn’t use stencil buffers, just had to know which vertices to alpha off

I was looking for some reference on it myself just this Thursday and I stumbled on your question. Idk why but it felt like I had to get off my bum and help you out.

There’s more to come: sphere’s and cylinders ,etc
(but you might have to wait a while for those)

I hope this helps and that I’m not to late

plus you should watch these as references too:
https://www.youtube.com/watch?v=MAzkNgzWK9w
https://www.youtube.com/watch?v=HR3flKges_A
https://www.youtube.com/watch?v=_YTw-pFuWig

they’re not Godot but this is where I started

19PHOBOSS98 | 2020-08-29 10:43