9
$\begingroup$

One of my favorite techniques in Blender is editing vertex normals to make stylized trees like in this article: link

The technique works in a nutshell like this:

  1. create leaves texture and model in shape of three quads
  2. create a blob and add particle system on it, use leaves object as source
  3. turn particles into independent objects, join it all into one object
  4. increase the size of the blob
  5. add data transfer modifier to the leaves and change vertex normals so they point outwards towards the blob

Relevant gif that outlines the steps

I'm trying to replicate this in geometry nodes of 3.0, but I got stuck on the last step. So, using geometry nodes 3.0, can I adjust vertex normals so they point outwards of the shape for this 'stylized shading'.

$\endgroup$

2 Answers 2

8
+50
$\begingroup$

This is a lovely technique.

The approach, here, is to capture the normals of the blob on which the leaves are instanced, and pass it out to the GN modifier, so it can be picked up by your shader.

enter image description here

This GN group takes the blob as an input, constructs the 3-plane leaves, and instances them on the blob surface. It exposes the scale and density of the leaves to the modifier as inputs, and passes out the normals of the original blob in the 'Normal' output field.

It also duplicates the blob, scaled down, as a further instancing surface, to increase the illusion of volume. Out in the modifier, I named the Normal output blob_normal, and passed it to this shader, via an Attribute node:

enter image description here

The individual UV mapping of the leaf-planes survive the GN treatment, and can be accessed through the named attribute uv_map. Here, that's used to make a procedural leaf-alpha-map for the planes, so their square edges are somewhat concealed. (You may be using an image-map; then the only relevant parts of this tree would be the nodes in yellow.)

enter image description here

(Blender 3.0 Candidate .. I didn't pack the world in the file. If you need one for lighting, you will have to fish out one of your own)

$\endgroup$
10
  • $\begingroup$ Oops, really, you should expose the set material to the GN input, too, so you can use the group for green trees, yellow trees, whatever. I'm sure there are other tweaks you will be making for yourself. $\endgroup$
    – Robin Betts
    Nov 28, 2021 at 20:55
  • 1
    $\begingroup$ Thanks, I was just about to say it was impossible in comments lol :) Shame that we can't just output actual normals anymore though, GN feels like a constant game of one step forward, one step back. $\endgroup$
    – Nathan
    Nov 28, 2021 at 23:31
  • 2
    $\begingroup$ @Nathan Very frustrating .. We are right? There's no way to set actual UV maps or actual normals on the geometry? Just attributes to be picked up by the shader? Surely there must be plans to make that happen.. for export, and everything... $\endgroup$
    – Robin Betts
    Nov 28, 2021 at 23:56
  • 1
    $\begingroup$ Apart from providing solution to my question, you have also showed that UV maps DON'T get destroyed after using Realize instances node like I thought they were. I'll forward this to another question that a different person had a month ago. $\endgroup$ Nov 29, 2021 at 16:30
  • 1
    $\begingroup$ @Bloop Spotted! Thank you! At first sight this part of the answer is complete rubbish. I think the attributr has to be transferred to be meaningful. Can't remember how it got here before posting. Attending to it $\endgroup$
    – Robin Betts
    Aug 21, 2022 at 8:31
1
$\begingroup$

While you can't edit vertex normals directly from Geometry Nodes can you still access the attribute from Python and use that to set your vertex normals.

Assuming you already have the same setup as in Robin Betts's answer:

  1. Enable Auto Smooth.
  2. Apply the Geometry Nodes modifier and all modifiers before it.
  3. Go to the Scripting Workspace.
  4. Create a new text file in the text editor on the right and paste the following in it:
import bpy 


ob = bpy.context.object
me = ob.data

normals = []
for v in me.attributes['name_of_your_normals_attribute'].data:
    normals.append(v.vector)
        
me.normals_split_custom_set_from_vertices(normals)
  1. Change name_of_your_normals_attribute to the name the appropriate Attribute Output from the geometry node modifier (blob_normal in Robin Betts's answer).
  2. With your object selected, click the play-button icon on the top of the text-editor to run the script (Shortcut: Alt + P).
  3. Click inside the 3D viewport to update it and see the result.

Limitation here is that this is destructive (aka, not a modifier) and requires the Geometry Nodes modifier (and all modifiers prior to it) to be applied. If exporting for a game engine or something similar this shouldn't be too much of an issue as long as you keep a back-up of the original object with the modifiers still in place.

I'm also aware this isn't exactly the answer to the question as it's not using geometry nodes to achieve this result. But I stumbled across the same problem, already aware of the solution Robin Betts gave (which is the correct way of doing things as long as your model stays inside Blender), but required the result to be exportable to a game engine. So this is the solution I ended up going with. If anybody knows a more elegant solution I would be glad to hear it.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .