Note : Godot 3.2.1, Blender 2.82.
Looking at the room I've been working on, it seems it's time to try and implement
windows in the game.
I would like to get at least some basic idea of how to do 'plain' glass,
stained glass with colored shadows, and light shafts.
I'm guessing that should also involve baking light, and using GIProbes and ReflectionProbes. But, one scary new thing at a time ...
Since all of my modeling and texturing so far has been done in Blender, I first tried to create a simple glass material there. As it turns out, Blender has a dedicated 'glass shader' that seems to work out of the box :
Rendering an object with this glass material however only seems to work with the Cycles renderer. Rendering the glass object in Godot also fails.
My next line of attack was to try and find a Godot tutorial, but there doesn't seem
to be much information on how to create nice materials.
I found 2 videos by 'tutor tomato' (see list at the bottom), and one by 'Stanley'.
I also found a glass material on the 'scificar' model in the Godot tps-demo.
The list also includes 2 of the easier Unreal and Unity tutorials
for comparison.
Below are some suggestions on how you can go about creating a basic (non-realistic)
glass material in Godot :
1) No textures :
Notice the 'transparent' flag and the albedo alpha value.
The only other settings in this type of glass are the 'metallic' setting of 1
(meaning : the material will act as a mirror), and the roughness value of 0 (fully smooth
surface).
If you increase the roughness slightly, you will start to see a highlight
from the sun (directional light) in my scene.
It's also possible to add in some 'refraction'. I used a setting of 0.02.
Note : the 'blend mode' (under the 'parameters' heading)
is set to 'mix'. So, normally, this would mean that the default (opaque) render
pipeline is used. That means : no transparency !
If you do want to use transparent materials with the 'mix' blend mode, you have
to turn on the 'transparent' flag so that the engine will use the more expensive
render pipeline for transparent materials.
Another way of forcing the rendering to go through the transparency pipeline
(without setting the transparency flag) is by using any of the other blend modes
(add, subtract, multiply).
2) Simple textures :
This glass is pretty similar to the previous glass, but it uses a texture for the albedo (albedo color = white, with alpha = 30) :
The light green tint comes from the texture (made in Gimp).
The texure is made up of a circle and a border. Tthe 'edge' opacity is set to 24 in the texture used in Godot.
The nice thing about this texture is that you can still change its color from within Godot (I guess it would have been better to create a white texture in Gimp rather than a light green one) simply by changing the albedo color :
This is a silly example of a glass material with an albedo texture and
a normal map:
And, a more serious example : frosted glass (albedo texture + normal map).
The frosted glass was created from a JPG image I found online (search for
'frosted glass').
The normal map was created using the
NVIDIA Texture Tools Exporter. This is a free Windows tool that comes as a
standalone version and an Adobe Photoshop plugin. It can be used for all kinds of
texture-related things (compression, mipmapping, cube maps, transparancy, ...) but
I've only used it for the creation of normal maps.
As far as I can tell, transparent materials cannot cast shadows.
But, of course, you can fake them ...
1) Using existing lamps :
If you use the lamps already present in your scene to create the shadows, it's an all or nothing thing.
The easiest way is to duplicate the transparent object,
make it slightly smaller than the original object ('mesh : make unique'),
give it an opaque material ('material : make unique'), and set it to 'shadow only'.
Of course, do not forget to set the lamp to cast shadows as well !
2) Using a textured plane :
If you have static shadows, you could use a textured plane (maybe deform it a bit) with some emission added ... Just put the plane close to the floor, at the location where you want the shadow to appear.
Of course, this would be even better with some blur, and a shaft of colored light.
Oh well. One can always dream ...
As far as I know, Godot 3.2.1 does not implement 'volumetric light'
(the technical term for 'light shaft'). But we can fake it :
1) Shader material :
The first example is based on the Godot tps demo.
(I added an extra OmniLight (very pale orange) right where the window is,
to give some extra light
to the start of the beam as well as the stone setting for the window.)
And this is how they did it in the demo :
. the mesh :
Open 'demolevel.blend' (demo > level > geometry) in Blender
and search for 'lightshaft'.
. the material :
Open 'level.tscn' in the Godot editor, search the nodes for 'lightshaft', and
take a look at the material ...
The material is actually a Shader material that makes use of a gradient texture (256x256).
At this point, I'm not sure exactly how the shader works (a topic for later),
but you can play with the 'shader params' in Godot and see what effect they have in the scene.
2) Spatial material :
The second example is even simpler.
I created a cone mesh in Blender and uv-unwrapped it. I then imported the mesh
into Godot and gave it a material.
This is how it was done :
I set the 'unshaded' flag to true, and 'culling' to disabled (but both are optional).
I also enabled the 'proximity fade'. The result is that the light beam
'becomes softer'/fades out when it is close to another object (the wall and the floor).
In the image below, I turned the transparency down to better show the effect.
This is what it looks like in-game :
There's one more setting that you might want to turn on, and that's the 'distance fade'.
This makes the light shaft fade out when the player gets close to it. Compare the clip below
with the one above.
I used the default settings for 'PixelAlpha' (0 and 10) :
3) Animated light shaft :
The last example is an animated light beam. I have left the transparancy a bit too low, and made the animation speed a bit too fast so you can see better what happens :
Basically, everything is similar to example 2, except that
I'm now also using an AnimationPlayer node to animate the texture ! Or rather,
I'm keyframing the uv1 xyz offset ...
Of course, the possibilites are endless : almost everything can be animated in
Godot. So you could change the transparency, or the color, or even the texture ...
One thing that would be 'nice to have' here, is a Fresnel effect. The 'Dave Wilson' UE4 tutorial (see list) demonstrates the effect of that : the light beam becomes 'softer' at the edges.
Note : there's one more thing I would like to mention
about materials in Godot. It has confused me for the longest time ... Well, it's still
a bit confusing, but at least I understand -some- of it now.
As mentioned in the 'spatial material' documentation, there are 3 places where one
can set a material !
1) in the material property of the mesh - header 'MeshInstance' :
→ every time this particular mesh is used, it will automatically have the material.
2) in the material property of the node using the mesh (eg. a MeshInstance node)
- header 'Material' :
→ the material is only used with this particular node ; if a material was set
in (1), it is overriden.
3) in the material override property of the node using the mesh -
header 'GeometryInstance' :
→ the material is used only with this particular node, and overrides (1) and (2)
(this is the one that still confuses me - how is this different from (2) ?)
So. That's the end of this rather long blog post.
And now ... back to work !