In Neverwinter Nights Model Shadows are done on placeables, creatures, items and tiles. Only Trimesh nodes in a model can cast a shadow.
Shadows are Stencil shadows and thus reasonably simple - but can go wrong when a complex trismesh node is used to define the shadow mesh to use. This is why many even base game models either show no shadows (the model has them turned off) or have really odd shadows at certain angles or distances (the mesh used to generate them is not perfect or too complex).
The contents of this page handle general informations about model shadows, how to implement a model with shadows as a custom .mdl into your module - and solutions for issues that might (and probably will) come along the way. If you happen to encounter a problem that can't be solved with any of the solutions below, you can always ask around in the community and the discord. Note that the given solutions might not apply to your specific problem. If the bug perists, or if you find a way around it, by all means, do share it with us to keep the flame alive.
It goes with saying that you have a backup of your file before you head out to edit or export it, therefore the author of this page takes no responsibility if data gets lost along the way.
What are shadows essentially? This question might be irritating to some and feel like it's actually easy to answer.
However, as with anything, the case if often more complex as explained the quote down below:
Shadows are a result of the absence of light due to occlusion (occlusion: blocking off, blockage). When a light source's light rays do not hit an object because it gets occluded by some other object, the object is in shadow. Shadows add a great deal of realism to a lit scene and make it easier for a viewer to observe spatial relationships between objects. They give a greater sense of depth to our scene and objects. [...]
Shadows are a bit tricky to implement though, specifically because in current real-time (rasterized graphics) research a perfect shadow algorithm hasn't been developed yet. Taken from LearnOpenGL, click here to learn more (Note: Neverwinter uses OpenGL)
The concept of shadow mapping is quite simple. All you need is a light source for your environment and a scene it interacts with. To demonstrate this, let's say the ground there in our image is a single tile of our area and the cube is an object in it's way - for example a crate.
The light source is constantly lighting up the space around itself where it is placed in our environment. This is described in many shapes, sometimes as a cone (car lights), sometimes a sphere (torch or light bulb) and other times it's the sun. What is important though, is that once the light hits the object in it's way, it will describe the rest of it's path as occluded, thus rendering the faces it can not physically reach as dark. The game uses basic Stencil Shadows and does not use shadow mapping or advanced modern shadow techniques.
Since I've previously mentioned there are many shapes, the one NWN uses for it's environment is of course a sun.
That means that it will cast light over the whole scene indifferent to how close the objects are to the source, instead the angle the light hits the object from is the only important measure. In our rendered example to the left, we use a point light, which is similar to a torch.
The further away the object is, the longer the shadow grows and the weaker the light illuminates the tile and the object itself.
On the right we see the clear, constant distribution of light only obstructed by objects in it's way. In this sense, it is just a single crate. This is the light cast by the sun.
The tile itself only casts shadows from an elevated position and if a large object necessarily demands it.
Notice how the weed on the ground does not cast any shadows at all, but the cliffs do. Your placeables will typically cast shadows as well.
Shadow Mapping example as seen in Blender, rendered in Eevee
Shadow Mapping example as seen in NWNToolset, Crate & Weed
Shadow Mapping example as seen in NWNToolset, Weed, Stones & Cliffs
Working with Shadows
I assume that you have somewhat basic knowledge about how to handle import-export using NeverBlender and that you can manipulate a mesh to visually express your creative ideas.
If for some reason you haven't used Blender before, nor have you installed the import-export plug-in NeverBlender and have no experience with it at all, I would recommend you to to download them, read the instructions to NeverBlender from the Neverwinter Vault Page and visit some tutorials and videos on how to create your own model and import it into your module.
Note: This page does not cover NWN 2 related modelling, nor will it explain how to UV Map and texture your model.
NeverBlender is a plug-in that will cover your basic needs for Placeables, Doors, Models, Phenotypes, Walkmeshes, Animations and much more. I recommend it strongly, as Blender is a Free Open-Source Tool for 3D Modelling, Animation & Rendering - and as of late a gradually growing, powerful physics engine.
You own 3DS Max and have the NWMax Plug-In for it?
Do replace this text and add in your workflow here to enable shadows in your model export.
Neverblender Step-By-Step Tutorial
Step 1 - Loading Up your File:
Load up your project file (after having created a backup file for it.) For this tutorial I will load up one of my recent head models. To learn how to extract models as a readable MDL ASCII file, click here. Or one of the links for more information on UV Mapping or Texture Painting in general.
For my example, I have taken pfh0_head155, remodelled it, renamed it to pfh0_head200 and did the same for it's pfh0_head200g. You may notice that my mesh has more polygons than the average head model for a NWN character. How you choose to model your head is up to you, enjoy the freedom.
Keep in mind for the future: p = part-based, f / m = female / male, h = human, 0 = Phenotype Normal, head = model attached to head node, 200 = ID, g = geometry. A model can not be loaded in the Creature Wizard with no geometry.
The hierachy goes as follows:
|pfh0_head200 (PARENT: root of your head, it should be centered and rotated to x0.0, y0.0, z0.0, scaled to 1.0)
|→ pfh0_head200g (CHILD TO pfh0_head200 | PARENT OF pfh0_head200g: this is your head model.)
|→→ pfh0_head200g (CHILD TO pfh0_head200g | PARENT OF image_textures: These are the data properties of your model)
|→→→ image_texture (CHILD TO pfh0_head200g: The material that will be laid over your texture.)
|→→ Vertex Groups (CHILD TO pfh0_head200g | PARENT TO constraints: This is your vertex group 'folder')
|→→→ constraints (CHILD TO Vertex Groups: Vertex Groups are used for dangly mesh weight assignment.)
|→ shadow_dummy (CHILD TO pfh0_head200: This is a hidden mesh. You will learn about it later.)
|→→ shadow_dummy (CHILD TO shadow_dummy: Data property of the shadow dummy mesh
|→→→ material (CHILD TO shadow_dummy: unused material generated by the export.)
Step 2 - Checking your properties:
Your root should be an empty plain axes and have the classification set to Character, the Supermodel as null and the animation scale to 1 in your object properties. Character describes the root of your model to be of the type Character, which is essential for character models to load up correctly. make sure to name it properly.
You can give it entirely different names, too, but for the purpose of this tutorial we won't do that as this is also an entirely different topic.
Next, your head model should be parented to your root (CTRL+P → Set Parent → Object). Make sure the head of your model's neck (the center between the end corners of your jaw) is perfectly! centered to the middle of your root where the two straight lines cross. This is the point where the head bottom 'attaches' to the neck phenotype's top.
Check your object properties once more: Aurora Base Properties → Classification → Character & Supermodel → null & Animation Scale → 1.00. This part is unnecessary if you've parented it before, so double check if the model was parented correctly and the settings are the same.
We will ignore image_textures, vertex groups and the shadow dummy + it's material for now.
My Properties Checklist
- My Root is an Empty Plain Axes
- My Model is Parented to the Root and now a Child of it
- I have a material for my model.
- (Optional, Danglymesh:) My constraints for the Vertex Group are weight painted for Danglymesh
- (Aurora Base Properties) I have set Classification to: Character
- (Aurora Base Properties) I have set Supermodel to null
- (Aurora Base Properties) I have set Animation Scale to 1.00
To finish this all up, we will now also add an additional property for our head model which the root does not have as an visible option. In your Object Properties, scroll further down until you see the Aurora Mesh Properties. This is our most vital tab. It has just a few ticks, a a few sliders and checkmark options. To learn more about it, go here.
If you are using a danglymesh like me, set your type to Danglymesh and make sure to paint your assigned vertexes accordingly, like the danglymesh tutorial above suggests. What period, Tightness and Displacement you use, is your preference for the kind of dangly material you're working with. Triangulate the Faces like described in the Trimeshes below.
If it's just a static mesh, set it to Trimesh. Trimesh. Now what does that mean? Triangulated Mesh. Have you triangulated your faces yet? Do it now. Edit Mode → Search → Triangulate Faces (Or just CTRL+F and Dropdown to the option).
Now that your model is finally ready to be exported, we are now entering the part that's important for the shadows to work ... behold.
Step 3 - Going Dark:
To export our model with a shadow, check the Shadow Checkbox below the Render Checkbox. This will, as we have learned with Shadow Mapping above, make the Object's faces which meet the ray of light be lit while the back creates a shadow map over the surface the angle of the light source is pointing to and therefore occludes the light on the other side of the model and the passing light ray onto the ground/wall/surface.
Now export your mesh as an .MDL, open up NWHak, update your .hak file, open up the Toolset and your module that contains your custom content .hak file and take a look.
Great! It works! Perfectly. ... Or does it?
Don't panic. While I'm not really sure why this happens, this usually happens to models with a higher polygon count. I assume that some vertices might stretch out to the shadow map, but that's just blind guessing at this point. Instead. Let's find a solution in the bug category down below.
Bug Reports and Solutions
Bug (Solved): Shadows Stretching / Rip & Tear Glitch
Unknown (Know the cause? Edit here)
The shadows of my head model look weird and stretched. They occasionally tear and explode when the character moves. I think it has something to do with the high amount of polygons I've put in? Is there a fix for it?
- Create a second mesh that vaguely has the shape of your characters head
- Place the model where your character's head would be
- Don't worry about your model going through your initial head model
- Triangulate the mesh
- Name it shadow_dummy or something you might prefer
- Parent it to your root empty plain axes
- In the Object Properties → Aurora Mesh Properties, set the Shadow Dummy's Render Checkbox OFF, Check the Shadow Checkbox ON (Your Shadow Dummy won't be rendered at all now, but it's shadow will influence the shadow map on the surface)
- In the Object Properties → Aurora Mesh Properties, set the Head Model's Shadow Checkbox OFF, leave the Render Checkbox ON (Your Head Model will still render entirely, but it's shadow map cast onto the surface will not be processed.)
- Export & Test
- Leave a Like on this page & join the Community ♥
- There's always another way. Found another solution?
- Post it here.
Bug (Solved): TEMPLATE NAME
- SOLUTION STEPS
Bug (Pending): Some Bug Name / Alternative Name
You Or me?
Only copy paste reported bugs to the pending column if you're actually up for the task.
When you're done, document your solution & move it to the left. Please keep the color codes to their respective column.
Bug (REPORT): I've fallen / And I can't get up
If your bug is similar to the reported bug, you can still add images and text here.
Delete and move the entire entry towards the Pending Box if you're working on it.