As you know, Bge, Upbge, Range has that problem that there’s no real indirect lighting … so unless you full your scenes with tons of lamp ( with all the light bleeding it can causes and the severe harm it does on your fps) … your scene will be pretty dull and ugly (get only a single sun as light source to see how ugly your game will look like) . Ofc you can change the shadow color for not having it completely black and so it will be less harsh , but the problem remains : it looks so flat.
And so, Upbge 0.25/Range 1.0 is shipped with that combo of 2 hemi + Environement lighting to give some colors : a global blueish color with some hard orange to emulate some light bouncing off the ground … it roughly do the job : it looks less ugly and your scene is supposed to be happening outdoors.
But , when i came some times ago to a problem : how the hell can i get ride of that static global environement lighting that chase my character even when she is like in a 100 meter deep cave … Why , my character can have only 2 shades : exposed to the sun (with/without EL) and not exposed to the sun (with/without EL) …
The answer is in that often ignored/discarded input of the Extended Material node . That input provides
That input provides how much your material will confirm or cancel the global Environment lighting . Interesting thing : its point-based and not an uniform value → so providing a color texture will give details
And so , for static objects, you just need to provide an AO map and you are done .
Btw, for some reasons, there’s that myth that AO map has to be multiplied with the Diffuse map … it’s completely wrong to do so : color x black = black … you cannot retrieve your colors by adding source lights … your colors are gone , you cant go back. On the opposite : that Ambient input indicates how much you want to get ride of the Environment Lighting only .
Now, for the dynamic objects : problem, the typical baking cannot work ofc … for some reasons, i never encounter some concerns about this problem in the upbge community except some attempt done with a 2d filter that bugs with moving cameras … but there’s a solution i was thinking about and discovered later that such solution exist in games engines like Unity :
Light Probe !
The idea is simple : its to provide a global lighting but with local variations
Before get known on those things, i was thinking about solutions and some people here came with the idea of a ray to either read the closest vertex on the ground or the UV of the poly on the ground … as you might guess problem is when you get off that ground or that your character has to climb some stairs …
Due to the ray technic, the persian gonna get the ambiant color of the deepness before even falling
So, finally i come with this Light-Probe-3D-baking idea i would like to see implemented in Range engine
Get AO values in 3d space
--> bake on Vertex Colors of a Grid mesh the AO --> Record the Values --> Move the Grid +1 unit on the Z - Repeat the 2 above --> Create a 3d Matrix of all the Values --> Record it in a file
first tic :
→ import that 3d matrix of 3d AO values [0,1]
when character is moving :
→ compute the worldposition of your character regarding the virtual 8 surrounding points of a cube in which your character is positionned into at that moment
→ compute a barrymetric weight to assign for each of those 8 surrounding points according their distance to the worldPosition of your character
→ compute a global score as being [weights] x [AO]
→ assign that weighted AO value to your object.color
import bge from math import floor from mathutils import Vector ## get the AO 3d matrix from table import mm scene = bge.logic.getCurrentScene() cont = bge.logic.getCurrentController() obj = scene.objects['Suzanne'] ### X,Y,Z point = obj.worldPosition x , y , z = point f = floor(x) ; g = floor(y) ; h = floor(z) ## virtual cube in which your character is standing in cube = [(f,g,h),(f+1,g,h),(f,g+1,h),(f+1,g+1,h), (f,g,h+1),(f+1,g,h+1),(f,g+1,h+1),(f+1,g+1,h+1)] ## retrieve associated AO values by Z,Y,X values = [ mm[i][i][i] for i in cube] ## just compute once the max normalized length existing in a cube maxl = 3**0.5 ## measure the 8 distances dists = [(Vector(i) - Vector(point)).length for i in cube] ## normalized score barry = [1-i/maxl for i in dists] ## sum of weights must be 1.0 sumb = sum(barry) ws = [i/sumb for i in barry] ## final weighted AO score ao = sum([i*j for i, j in zip(ws,values)]) ## either you bake on high-vertex Grid , either you lerp a bit obj.color = obj.color.lerp((ao,ao,ao,1.0),0.5)
Plug it to the Ambiant input (red, green, blue, they are all the same - only the level 0-1 matters)
Result (sun shadows are off and i baked also the AO on the castle so one can compare)
soon : instead of using the Object color, i will use the Light Data node for making the Ambiant not uni-dimensional