relationship between Object3D and Light

Started by MichaelJPCT, May 29, 2020, 08:27:51 PM

Previous topic - Next topic

MichaelJPCT

Hi,
today i thought of a situation that within several object3d's i want a light to affect only one of them(or several of them).
so i wish there is Light list for Object3D or Object3D list for Light.
setMaxLights() and setDistanceOverride() methods are not enough in this case, because a light is far away from the object3d if i need parallel, directional light, a light can affect any object in range.
moving Object3D to another World also creates more trouble.
using light can't be substitude by additional color, because light has direction.

EgonOlsen

You can disable all light sources in an object with setLighting(...). But that's not sufficient in this case, I guess?

MichaelJPCT

right, turning off all lighting for an object is not what i want.
in my case , there is sun light as a base, then i add a light below an object, to simulate reflected light from the ground, and it's different from ambient lighting. and i want this only for the main character - for performance reason.
there can be other lights in the scene, so setMaxLights(1) for other objects is not a solution either.
this is not important though.

AeroShark333

Perhaps in your situation you could copy and modify the default shader a little to your expectations. It kind of would allow light-manipulation per Object3D once you apply these custom GLSLShaders to different Object3D's. But perhaps a little too complex solution...

Another solution might be to add an IRenderHook to your Object3D's and enable/disable lights in beforeRendering/afterRendering. But I'm not sure if this would work and I'm not sure if this is too great for performance. But in my head, I believe it'd allow for per Object3D (per polygon even...) light manipulation.

MichaelJPCT

i am not sure about iRenderHook solution, but custom shader can work. custom shader can do a lot of things, but it is like last resort for me - i am not into graphics.
i think this problem can be solved easier from engine level. and i think relating Object3D and Light is a good thing, it gives more choices to the engine users. i can think of other cases where it is useful.
for example, a scene is divided into rooms, a light in a room should not affect objects in another room, even if the light is near to the other room. with Object3D list for Light, this scene can be setup easier.

EgonOlsen

I don't think the IRenderHook idea will work. The render hook gets triggered too late in the process, IIRC. At that stage, the lights have already been calculated.

EgonOlsen

Quote from: MichaelJPCT on June 03, 2020, 02:18:32 PM
for example, a scene is divided into rooms, a light in a room should not affect objects in another room, even if the light is near to the other room. with Object3D list for Light, this scene can be setup easier.
The things is, it's not designed that way. The idea was to have a world filled with lights, just like the real world, and objects moving around which will in turn be affected by the closest light sources. Lights per object were never planned. However, I see your point. I'm just not sure how to handle this. I can't add a list of lights to Object3D, because that would break too many things in the lighting code. The "best hack" that I can come up with ATM is to extend the IRenderHook-interface (or create a LightingHook interface) that allows you to suppress some world lights for an Object3D. That's not that great either, but it would fit the engine's render pipeline...I guess...I have to think about this some more...

AeroShark333

I already had a slight feeling the IRenderHook stage was too late for light manipulation...

A solution that might work (depending on your scenario) if your main character is always fully visible and nothing is between the camera plane and the main character, is to create a second World with identical Camera but with an additional Light on top of the already existing Lights. And to render and draw this second main character World after the original World... But I guess this would seem like a bit of a hack.

I don't think jPCT-AE allows the shader variables of the default shader to be manually altered. But I believe this would maybe be one of the easier changes for jPCT that would allow for light manipulation since I suppose the default shader is based on a GLSLShader already anyway. E.g. setting diffuseColor to black or something when it's off. Though, I guess you wouldn't be sure which of the 8 lights is the 'reflection light' if the sorting of the lights array is distance based or based on in which order it got added to the world. But I believe it's something you could calculate then. I guess this solution would need 'getters' though in the GLSLShader class and access to the default shader.

Or maybe the LightingHook is even easier...

MichaelJPCT

Quote from: EgonOlsen on June 03, 2020, 03:15:34 PM
Quote from: MichaelJPCT on June 03, 2020, 02:18:32 PM
for example, a scene is divided into rooms, a light in a room should not affect objects in another room, even if the light is near to the other room. with Object3D list for Light, this scene can be setup easier.
The things is, it's not designed that way. The idea was to have a world filled with lights, just like the real world, and objects moving around which will in turn be affected by the closest light sources. Lights per object were never planned. However, I see your point. I'm just not sure how to handle this. I can't add a list of lights to Object3D, because that would break too many things in the lighting code. The "best hack" that I can come up with ATM is to extend the IRenderHook-interface (or create a LightingHook interface) that allows you to suppress some world lights for an Object3D. That's not that great either, but it would fit the engine's render pipeline...I guess...I have to think about this some more...

when the engine select Lights for object3d, (hence there is setDistanceOverride method) can you do this ? -

if (there is light list) test lights in list;
else test all lights in World;


if (this light has object list) { if (object is in list) light on; else light off }


EgonOlsen

Quote from: MichaelJPCT on June 03, 2020, 05:51:02 PM

when the engine select Lights for object3d, (hence there is setDistanceOverride method) can you do this ? -

if (there is light list) test lights in list;
else test all lights in World;


if (this light has object list) { if (object is in list) light on; else light off }

No, not really. Because these lights still have to be part of the World or otherwise, they won't be processed properly. But if they are part of the World, they will have an influence on all other objects as well. They would limit the lights for one object but not for all the others, which is actually what you want. You could of course use this to add a light list to ALL objects managing them all by yourself, but wouldn't that be a bit tedious?


EgonOlsen

Quote from: AeroShark333 on June 03, 2020, 04:23:31 PM
I don't think jPCT-AE allows the shader variables of the default shader to be manually altered. But I believe this would maybe be one of the easier changes for jPCT that would allow for light manipulation since I suppose the default shader is based on a GLSLShader already anyway. E.g. setting diffuseColor to black or something when it's off. Though, I guess you wouldn't be sure which of the 8 lights is the 'reflection light' if the sorting of the lights array is distance based or based on in which order it got added to the world. But I believe it's something you could calculate then. I guess this solution would need 'getters' though in the GLSLShader class and access to the default shader.
You would have to duplicate one of the default shaders and modify it. I did something like this in my game Naroth to make sure that the player's light is always on. I could look it up, if needed..

MichaelJPCT

Quote from: EgonOlsen on June 04, 2020, 07:51:04 AM
Quote from: MichaelJPCT on June 03, 2020, 05:51:02 PM

when the engine select Lights for object3d, (hence there is setDistanceOverride method) can you do this ? -

if (there is light list) test lights in list;
else test all lights in World;


if (this light has object list) { if (object is in list) light on; else light off }

No, not really. Because these lights still have to be part of the World or otherwise, they won't be processed properly. But if they are part of the World, they will have an influence on all other objects as well. They would limit the lights for one object but not for all the others, which is actually what you want. You could of course use this to add a light list to ALL objects managing them all by yourself, but wouldn't that be a bit tedious?

my plan is this: obj1 without light list, engine process all lights[light 1 2 3 4 5 ... ]; obj2 has list [light1 and 2], engine process light 1 and 2 when drawing obj2; obj3 has list [light 2 and 3], engine process light 2 and 3 when dtawing obj3.
if lights cannot be isolated, can the engine modify the strength of unwanted lights to zero when drawing corresponding object?

EgonOlsen

That should be doable. I'll look into it.

EgonOlsen

Ok, I did something: https://jpct.de/download/beta/jpct_ae.jar

It adds three new methods to Object3D, namely


/**
* Adds a light to the list of lights specific to this object.
* If this list is empty, all world lights be taken into account
* when rendering the object. If there are some lights in this list,
* ONLY these lights will be used to light the object.
* The lights still have to added to the object's World instance
* regardless of being in this light list or not.
*
* @param light the light to add
*/
public void addSpecificLight(Light light)

public void removeSpecificLight(Light light)

public void clearSpecificLights()


This should do what you want it to. I briefly tested it in desktop jPCT and it seemed to work as expected. Please let me know if it helps/works/fails...


MichaelJPCT

thanks Egon, it works.
please also add object list for Light.
the logic is this, if a light has list and the object is not in list , the light is off for this object.

this test is needed only if object has null list.
if object1 has light1 in list and light1 has object2 in list, light1 in fact can lit object1 and 2.
or you may have other way to cross check these 2 types of list.

please use null list if list is empty, because null doesn't refer to additional memory space.