I need help making my first shader: Wireframe 3D
Asked Answered
P

10

0

This is the Godot 3D default cube:

I want it to look more like this: The differences between the Default Cube and my wanted cube are: - Faces are not rendered - Every Line must be outlined with a fixed width that stays the same reguardless of camera distance

Before you assume that I already made the shader: This image is an approximation that is a purely static image made in Inkscape. I don't actually know how to translate this into a Godot Shader for use in my actual project, as I could not yet become familiar with shaders in general.

---

Update: In the Godot Engine itself, I have the ability to change the preview to wireframe mode, so why isn't this also a shader available for the final game?

Porter answered 7/2, 2021 at 14:13 Comment(0)
S
0

Maybe the shader on this forum post will help: https://godotforums.org/discussion/22031/wireframe-generator-for-godot-c-shader-source-in-thread

I haven't used it myself, but it looks like it can generate wireframes from 3D models.

Update: In the Godot Engine itself, I have the ability to change the preview to wireframe mode, so why isn't this also a shader available for the final game?

The wireframe mode in the Godot editor (and in Viewport nodes) uses OpenGL code to generate the wireframe, rather than a shader, if my limited understanding is correct. From what I can gather, how it works is that it passes the mesh data to OpenGL but as lines rather than full faces, which makes the wireframe. Because it requires low-level scene data access, I think that's why its not exposed as a shader. (Though please take this all with a grain of salt! I have very limited experience with shaders and the inner workings of Godot)

Starinsky answered 8/2, 2021 at 22:28 Comment(0)
C
0

To create a 'wireframe shader' you need barycentric coordinates. Which have to be provided from outside the shader.

Conjuration answered 9/2, 2021 at 3:3 Comment(0)
M
0

You can use this code with an MeshInstance (for the node).

extends Spatial

onready var mesh_node = get_node("Cube")
onready var mesh_mat = mesh_node.get_surface_material(0)

func _ready():
	make_wire();

func make_wire():
	var array = mesh_node.mesh.surface_get_arrays(0)
	mesh_node.mesh = ArrayMesh.new()
	mesh_node.mesh.add_surface_from_arrays(Mesh.PRIMITIVE_LINES, array)
	mesh_node.set_surface_material(0, mesh_mat)

However I don't believe you can change the width (should be possible but I see a bug about it https://github.com/godotengine/godot/issues/8289 )

The other option, and probably the better one is to look at the code @TwistedTwigleg posted.

Mineralize answered 9/2, 2021 at 6:27 Comment(0)
P
0

@Megalomaniak @TwistedTwigleg @cybereality Thanks very much for your suggestions.

I am currently archiving my old games instead of continuing to work on my new game with the wireframe shader right now. I will continue working on my new game when I am done archiving my old games.

@Megalomaniak I will possibly look into barycentric coordinates when I continue working on my new game.

@TwistedTwigleg's suggestion I have already seen before on my search, and dismissed because I don't believe it can make wireframes where every line reguardless of distance is equally thick on the screen (at least not by itself, so maybe I should not dismiss this suggestion immmidiately).

But @cybereality's suggestion is the first one I will try when I am done archiving.

In the meantime I am still welcoming new suggestions if someone happens to have any.

Porter answered 9/2, 2021 at 7:0 Comment(0)
P
0

@cybereality said: You can use this code with an MeshInstance (for the node).

extends Spatial

onready var mesh_node = get_node("Cube")
onready var mesh_mat = mesh_node.get_surface_material(0)

func _ready():
	make_wire();

func make_wire():
	var array = mesh_node.mesh.surface_get_arrays(0)
	mesh_node.mesh = ArrayMesh.new()
	mesh_node.mesh.add_surface_from_arrays(Mesh.PRIMITIVE_LINES, array)
	mesh_node.set_surface_material(0, mesh_mat)

Thanks very much for this solution. Apart from some missing lines, this works as expected.

These lines remain missing independent of which Culling Option and/or GLES version I choose.

Although some lines are missing, I discovered that if I make every line an Extremely Slim Triangle (or an extremely slim rectangle, such as is possible by extruding the entire model at once but making sure that the extruded vertices overlap exactly with the original vertices) they're actually complete and indistinguashable from the usual 2-vertex lines.

Porter answered 20/2, 2021 at 17:23 Comment(0)
J
0

@cybereality said: You can use this code with an MeshInstance (for the node).

extends Spatial

onready var mesh_node = get_node("Cube")
onready var mesh_mat = mesh_node.get_surface_material(0)

func _ready():
	make_wire();

func make_wire():
	var array = mesh_node.mesh.surface_get_arrays(0)
	mesh_node.mesh = ArrayMesh.new()
	mesh_node.mesh.add_surface_from_arrays(Mesh.PRIMITIVE_LINES, array)
	mesh_node.set_surface_material(0, mesh_mat)

However I don't believe you can change the width (should be possible but I see a bug about it https://github.com/godotengine/godot/issues/8289 )

The other option, and probably the better one is to look at the code @TwistedTwigleg posted.

Sorry to necro this, but could this be used additively to add wireframe to the existing materials on top? Trying to find a way of rendering the wireframe lines on top of the existing material, perhaps as a second material? (but with the black somehow transparent).

Jingoism answered 25/3, 2022 at 10:34 Comment(0)
P
0

@elvisish Thanks very much for pointing me to the bug report, especially because there's a comment that explains how the 1px line width issue is fixed in Godot 4.

I canceled the game that i needed this shader for because the 2 weeks that i developed the game was development hell, unrelated to problems with line rendering but related to gameplay and style. But if i need this line-drawing method for a future 3D game, now i know that i can make it work in Godot 4.

Porter answered 25/3, 2022 at 11:26 Comment(0)
P
0

Unrelated, but: If you want to know what ended up being my actual first Godot shader, written without help but just research and learning: It's Circle Sprite Shader.

Porter answered 25/3, 2022 at 11:30 Comment(0)
M
0

@elvisish said: Sorry to necro this, but could this be used additively to add wireframe to the existing materials on top? Trying to find a way of rendering the wireframe lines on top of the existing material, perhaps as a second material? (but with the black somehow transparent).

You could use that code with two of the same object (one wireframe and one normal). You can also use Barycentric coordinates for a fake wireframe shader. I made this project, it's a bit of a mess, but see if it helps.

Mineralize answered 26/3, 2022 at 7:4 Comment(0)
J
0

@cybereality said:

@elvisish said: Sorry to necro this, but could this be used additively to add wireframe to the existing materials on top? Trying to find a way of rendering the wireframe lines on top of the existing material, perhaps as a second material? (but with the black somehow transparent).

You could use that code with two of the same object (one wireframe and one normal). You can also use Barycentric coordinates for a fake wireframe shader. I made this project, it's a bit of a mess, but see if it helps.

Thanks, I'll check it out, really appreciate it!

Jingoism answered 26/3, 2022 at 15:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.