Asset - Shaders TMC LUX Lighting Engine

I

icuurd12b42

Guest


TMC LUX Lighting Engine

DEMO

Outputs: Windows, Windows YYC, Android Compatibility Mode Option Available in Engine

Type: Engine

Included: Lighting Engine, Texture Normal Tool, Platform Engine, Top Down Demo.

Asset Store: https://marketplace....lighting-engine

Getting Started: HERE

Cel Shading and weird color blending:
http://gmc.yoyogames...85392&p=4925307

Old Forum: http://gmc.yoyogames.com/index.php?showtopic=685392&p=4925307

UPDATES
V1.0.1: http://gmc.yoyogames...85392&p=4925337

GMS2 Notes

Picture In Picture GMS2 2.1.5.246 bug fix

Array Too Large for Shader Error FIX

_spec Shaders math fix

Related Tools:

Convert your blender or Google Sketchup or other model to obj then use
GMModelFix: http://gmc.yoyogames...howtopic=397461
to orient, sort the facet and generate vertex normals on the model
and use
d3d22d: http://gmc.yoyogames...howtopic=598939
to load the model and generate texture normals for 2d sprite


Description:

The TMC LUX Lighting Engine consist of 4 shaders to do texture normal lighting with specular and ambient occlusion as extra rendering options. The lighting engine also has a sprite based lighting engine and shader which can be used for nice ambient effects such as light coming from a window. this sub system does not depend on a texture normal. Also include is a basic shadow system which.

The asset also comes with Preview/Fix Tool with a few necessary features such as converting a grayscale heightmap to a normal texture, flipping the normal texture color values arround and other basic image manipulations.

Perhaps the second best feature included in the asset is the platform engine which supports slopes and moving platforms.

Features:
  • Texture Normal Lighting Engine
  • Sprite Based Illumination Engine
  • Simple Shadow Engine
  • Robust Platformer
  • Preview and Normal Manipulation Tool
  • Virtually limitless number of lights in the room*
  • Virtually limitless number of Sprited Lights in the room*
  • 1000 lights in view*
  • 20 Lights per rendered sprite/primitives*
  • Ludicrous number of sprited lights in view
  • Layered system to have different layers of illumination
  • Sample objects covering all basis
  • Z support for positioning lights in actual 3d space
  • Cel Shading, Multiple Levels of Smoothness
  • Android Compatibility Mode Option Available in Engine. My phone can't run this and surely others can't while other may so I made sure the system and subsystems can be disabled without effort
*Though the system allows for a quasi limitless number of lights in your level, only 1000 lights in view and 20 lights per instance can be drawn. a limit that cannot be reached ATM unless you have a super-computer however the sheer number of lights in view will overwhelm far before you reach the speed limit of most decent PC as long as you don't try to render the entire room with a million lights. As it is with everything a right balance has to be achieved with the view size, room size and number of rendered lights and instances

With this asset I offer access to my slack tutoring group for private support, simply email me to set you up.

THINGS TO BE AWARE OF
The asset texture group I used in the test was not exported, or should I say the sprite's group was not reset to default so the demo sprites will merge with whatever group Studio decides in your project. Just go through the demo sprites and reset the texture group to default...

Remember, for most optimal rendering, use the texture groups feature to group your sprites and images properly and set the group to no-cropping, no re-scaling. Please beware of the texture grouping parenting. it's a bit hiffy and if you use the feature you may end up with your sprites spread all over the texture pages. children groups are split in favor of the parent texture group page when studio packs the sprites on the page.

For best performance it is best that all your images related to a render be on the same page. In the case of the animation, it is best that all images required by the shader, the diffuse (sprite), normal, specular, occlusion be on the same texture page as opposed to have a texture page for each image. I tried taking advantage of the other texture gpu slots (which occurs if you draw through a shared and pass extra images and those are not on the same page as the source) but this proved very inefficient.


Youtube:
Features Overview

SHD Platformer video

Playlist showing the evolution of the system
https://www.youtube....EL7hIm_Lh-BRMx2

Screen Shots:





Please read the READ_ME_NOW script in the asset for help and please don't be afraid to post any question if you need help adding the system to your game
 
Last edited by a moderator:
I

icuurd12b42

Guest
Notes on Sprited Lights:

Sprited lights allows adding pseudo lights that affect the scene in its entirety. This allows for having a lighting system for object that don’t have a normal texture. . The drawback is you loose the reflection effect a real light brings and the black pixels in the scene produce a null result, meaning they stay black. Very useful for lights coming out a window which scene designers like to add…


The light is a sprite of any shape or size you want. And it’s actually drawn batched with other sprited lights post process. It’s quite simple, you call tmc_lux_add_sprited_light that takes arguments very similar to draw_sprite plus a z, radius and shadow casting argument. Since the call is batched, not processed right away, you can call it anywhere from the step event to the draw, including the collision event.


See the car object in the demo.


Sprited lights by default are processed at the end of the draw event by the controller which has a very low depth so it draws last so these lights draw above everything.


But you can add a depth handler if you want those lights to only affect things behind everything else. Like say you only want a light to affect the background but not the foreground/overall scene. Like lights on the ground you don't want to draw over a cloud or a higher platform…

Sprited lights do have a z value. The depth handler handles the lights below it, if the light is handled it will be removed from the list so other handlers will not process it.

The performance drop really mainly depends on the number of depth handlers because each handler causes a snapshot of the entire scene to be re-rendered. It is quite important if using (many of) those that your application_surface is not humongous. Like you don’t want to render 4k 10 times every draw)

A flashlight could be a sprited light instead of a cone. Also warning spinning lights (2 cones end to end) can also be sprited lights, these lights are super efficient, you can have a ton of those with little cost in performance.

I have mentioned on numerous occasion on the old forum that you should never blindly resize the application surface to the size of your display, mainly because on some cheap 4k card this may fail, but in this occasion it is very much beneficial to keep the application surface size to a reasonable size, say 1080p if your game was designed for 1080p.

mainly the surface_resize(application_surface,w,h) code should be
Code:
w = min(port_size_width,display_size_width);
h = min(port_size_height,display_size_height);
surface_resize(application_surface,w,h);
*port_size_width and display_size_width can be of any source depending on your setup, view_wport to view_wview to roow_width and the display_size_width can anything for window_get_width, display_get_width, application_get_position, room width... it depends on your setup so that is why I'm not being specific here.

also since Studio may have to re-create the surface behind your back, you should query the application_surface_size every step. Also sice there is a chance that the application surface may not exist, yes it can happen you need to check for that. so the full code is

Code:
if(surface_exists(application_surface))
{
    w = min(port_size_width,display_size_width);
    h = min(port_size_height,display_size_height);
    if(surface_get_width(application_surface)!=w or surface_get_height(application_surface)!=h )
    {
        surface_resize(application_surface,w,h);
    }
}
 
Last edited by a moderator:

kburkhart84

Firehammer Games
Wow, all this time in the new forum and nobody has responded at all to this post. Anyway...I'm curious...have you done much work updating this(and any or your other assets for that matter) for GMS2? I'm sure I'll be using it and of course would like to be able to use this asset with it as well. I'm thinking it won't take too much work to make that update, and I know it is still months away, but I'm curious.

In fact, I'm beginning to play around with Substance Designer and Painter for creating some stylized textures(with height/normals) and then exporting those textures to Blender in order to render out sprites for your LUX system. I'm thinking it is going to end up working out really well.
 
I

icuurd12b42

Guest
I'm hoping the stuff will work without change for gms2... so much stuff.
 

kburkhart84

Firehammer Games
Yeah...I'm actually re-writing my kbinput extension. It really needs some new features that I can't just add so a re-write is necessary. In the process I intend on making sure it works for GMS2, though I don't think there are going to be many changes needed to make it work.

Yours will probably be more difficult than mine, considering the changes to the view/camera system, and the changes to the drawing functions(turned into gpu_*). I don't know what all of those functions are used internally to your system, but hopefully it will not be too much.
 
I

icuurd12b42

Guest
Actually the demo has no 3d, though the lighting system is in 3d space, it uses the normal view projection. but I do have a d3d_cube and an ellipsoid in the demo.

Not looking forward to having to fix my assets though. right now I'm not worried because no asset can be installed in gms2
 

kburkhart84

Firehammer Games
Yeah...I figured you'd have more to do than mine. All my extension(kbinput) does is wrap up the input functions for custom inputs, etc... and I don't think any of those functions changed between the 2 versions.
 

andulvar

Member
Can this system work with no specialized sprites (normals, diffuse....etc)? I'd like to get simple light with pixel luminescence without requiring the extra assets.
 
I

icuurd12b42

Guest
the sprited light system does not use normals, specular or occlusion textures
 

JaimitoEs

Member
Can this system work with no specialized sprites (normals, diffuse....etc)? I'd like to get simple light with pixel luminescence without requiring the extra assets.
You can exclude the normal and specular pass shader surely tweaking a little bit the code.
 

andulvar

Member
the sprited light system does not use normals, specular or occlusion textures
Ok, I picked it up. The sprited light works quite well, but shadows I'm having trouble with. It seems like the shadows always assume a floating object even if the object and the light are the same depth. If I wanted to always have the shadows anchored to some point of the sprite and then elongate them based on the distance from the light, is that something I can modify easily?

You can exclude the normal and specular pass shader surely tweaking a little bit the code.
It's not that simple, the shaders are based on them and without those arguments it would pretty much require an entire re-write.
 
I

icuurd12b42

Guest
The shadow system is a simple top down approach, it is not a light obscuring-shadow-penumbra type system.
 
I

icuurd12b42

Guest
Niice, if you can share your concept with us, I'm sure others would appreciate. I have a method in The Tank Game wip which repeatedly draws the sprites, as opposed to your example which scales a canned shadow. the data in the lights array has enough information for you to determine the distance of the cast. I was thinking to add the stuff in, but it definitely complicates things and definitely not up to par with the sort of code I'm prepared to make an asset out of
 

andulvar

Member
Sure, the example above is super simple but with the right animated shadow sprite it turns out pretty nice. In the final version, the type of light, the strength of the light and the color of the light should all affect the shadow. This example just draws a black shadow with adjusted angle/alpha based on any lights close by no matter the color or strength.

In the shadow casting object I used the following:
In the Create event:
Code:
shadow_count=0               //total shadows
shadow_angle[0]=0           //shadow direction
shadow_length[0]=0          //shadow length
shadow_dis = 700             //distance from light to show shadows
In the Step event:
Code:
shadow_count=0                                           //reset to 0
if(instance_exists(obj_light_test))
{
    with(obj_light_test)
    {
        light_dis = point_distance(x,y,other.x,other.y)    //check distance
        if(light_dis<other.shadow_dis)                           //if distance to the light is within range to draw a shadow
        {
            other.shadow_angle[other.shadow_count] = point_direction(x,y,other.x,other.y)     //get the shadow direction
            other.shadow_length[other.shadow_count] = point_distance(x,y,other.x,other.y)    //get the shadow length factor through the distance to the light
            other.shadow_count++                                 //increment to the next shadow
        }
    }

}
And in the Draw event:
Code:
for(j=0;j<shadow_count;j++)
    {
        x_scale = (shadow_length[j]/100)*.45                     //basically every 100 pixels away from the light source the shadow grows 45% and loses .
        alpha = (1-(shadow_length[j]/100*.15))/(shadow_count*.5)                     //alter the shadow alpha based on the distance and number of lights in range
        draw_sprite_ext(test_shadow,0,x,y,x_scale,1,shadow_angle[j],c_black,alpha)      //draw the scaled shadow black with adjusted alpha
    }
 
Last edited:
I

icuurd12b42

Guest
this could all be done in the draw using the lights array

see
tmc_lux_do_sprited_lights where I do the sprited lights and the shadows

line 145 onward to see how to loop through the regular lights array and get the data from the array in order to figure out where the shadow goes

simillar loop at 243 (disabled code) for sprited lights.

there you can see the enums that refer to the array item specific to the x,y,z,range for the lights and also, for the regular light, the math to determine the light casting radius and how the cone is handled and also how to determine where the casted shadow will on the plane and if it will be in view... the loop looks complicated because I do a ton of things you dont need to think about...

In any case the distance of the shadow cast can be determined from the x,y,z of the light and the x,y,z (z could be assumed to be the height) of your character on the walking plane (assumes the plane is at 0 altitude)
 

andulvar

Member
this could all be done in the draw using the lights array

see
tmc_lux_do_sprited_lights where I do the sprited lights and the shadows

In any case the distance of the shadow cast can be determined from the x,y,z of the light and the x,y,z (z could be assumed to be the height) of your character on the walking plane (assumes the plane is at 0 altitude)
I've really only just scratched the surface of the content included but I saw each light created will have the following:

Code:
sprited_light[SPRITED_LIGHT.SHADOW_PROCESSED]
sprited_light[SPRITED_LIGHT.PROCESSED] 
sprited_light[SPRITED_LIGHT.SHADOW_CASTING]
sprited_light[SPRITED_LIGHT.RADIUS]
sprited_light[SPRITED_LIGHT.ALPHA] 
sprited_light[SPRITED_LIGHT.COLOUR]
sprited_light[SPRITED_LIGHT.ROT]
sprited_light[SPRITED_LIGHT.YSCALE] 
sprited_light[SPRITED_LIGHT.XSCALE] 
sprited_light[SPRITED_LIGHT.Z] 
sprited_light[SPRITED_LIGHT.Y] 
sprited_light[SPRITED_LIGHT.X]
sprited_light[SPRITED_LIGHT.INDEX] 
sprited_light[SPRITED_LIGHT.SPRITE]

But then I also see these in the code blocks you referenced:
Code:
light[LIGHT.POWER]
light[LIGHT.FALLOFF]
light[LIGHT.RANGE]
light[LIGHT.R]
light[LIGHT.G]
light[LIGHT.B]
light[LIGHT.CONE_CO]
light[LIGHT.FX]
light[LIGHT.FY]
light[LIGHT.FZ]

I'm a little confused by the differences between:
  • LIGHT
  • SPRITED_LIGHT
  • light
  • sprited_light
And then there are similar references for "shadow". Those look like eaxctly what I would want to reference, but I'll need to tinker a while to get the correct calls to find a good method for using the data there. It's worth noting my particular game will only have 3 light planes (floor, wall, and ceiling) so I don't really need a mathematical determination for the shadow length/strength/blur to depth ratio when I can just use 3 static values I like. Especially when the ratios I want are probably off from eachother given the depths but I like that possibility is there.

Side note: Light as a word starts to look reeeeeeaaaly weird after typing it a few dozen times. ;p
 
I

icuurd12b42

Guest
the lights array hold sub arrays as items, each item is a light. a light is an array (structure) where array index [0] is x, [1] is y, [2] is z for example. I created an ENUM called LIGHT to define the array index so that light_x = light[LIGHT.X]; for example so that I dont mess up with the array index position.

the sprited_lights array uses the same concept. each array item is a sprited_light array (structure) so sprited_light_x = sprited_light[SPRITED_LIGHT.X];

you can do a global search for enum to find all the properties for the light and sprited_light structures

a light is a 3d light which uses the normals method and a sprited_light is the type of light that uses sprites for faking lights. 2 different methods in the engine, but they both have a x,y,z, a color in one for or another and a range or radius in one form or another
 
I

icuurd12b42

Guest
Where are the docs?
The functions are all documented in the comments of each script and the README script. Please use the middle mouse click on the function name to open the script and read the comments therein.

Any lacunes will be covered here in this forum.

Quick Start Guide:

0) Make sure you imported everything in your project, delete the extra stuff when your game is done and keep your work in a separate group
1) Add tmc_lux_lights_controller_obj in your boot room or in your Light enabled level rooms
2) tmc_lux_init_globals() is called when the tmc_lux_lights_controller_obj object is created. You can change the global settings there. Or make a copy of the script and have the function call your script with your own init sequence where you set your own settings for the initialisation process. Make sure your script is elsewhere than in the TMC LUX folder. This will ensure that when you update you won't nuke your settings.
3) Clone one of the object in the demo that sort of does what you want and tweak the member variables


Basic Concept:

The light controller handles your lighting demands every step, it handles the lights added in this frame and provides the extra details your light aware objects will need for drawing with lights.


Adding Lights:

Minimally you only need to know
tmc_lux_add_light()
tmc_lux_add_light_cone()
and
tmc_lux_add_sprited_light()
for adding lights.

You add a light instance of your design that calls either of these every end step or draw. If you want to turn off a light, simply don't call the function that adds the light in the end step (or draw). if you want to flicker the light, simply change the value each step. Use whatever method you are more comfortable with. I use a time based system and noise, but you can simply use random() to set the parameters.

Each 3d light has a Z value, range, light color, light power and drop off value, the cone have a direction and a cone angle factor.

I usually set the depth to be the Z value.

The radius/range define the maximum possible distance the light can cast. The power and the dropoff values will affect how far a light will cast within that range

The sprite light is not a 3d light. It is considered top down and colour and alpha define it's color and power really. the range should basically be the radius of a circle that encomapsses the sprite


Sidetrack:

The safest place to place a light in the level (call those scripts) in the end step. the system is depth (z) aware in my setup so it does not matter which light was added first or last, but you can technically add lights in the draw event as well. adding lights in the draw event would add them by depth order potentially making things faster but any light aware instance that would have be already rendered (for 3d lights) would not re-render with the new light


Shadow:

Shadows work like lights.

tmc_lux_add_sprited_shadow() is called each end step or draw to add a shadow on the system, much as you would add a light. It is basically like tmc_lux_add_sritd_light() which is basically a draw_sprite_ext (with the extra Z as argument) but it does not draw but adds draw information for the post rendering process to add shadows in the render.

Shadows are 3d and sprite lights aware but require the sprite light system to be enabled to cast...

Shadows only draw if the instance (at x,y,x) and the lights in range (at x,y,z) cast a visible shadow in view on ground (at z 0)

If an instance does not cast shadows, simply don't call the add shadow function.

The lights have a shadow cast override flag so you can have lights that don't cast shadows from the shadow casters


Light Aware Instances:

Light aware instances are basically all the instances that draw with 3d lights (and optionally, shadows). These draw with the shader which does the normal mapping and specular and ambient occlusion with the images specified. I have setup the example with objects that use a lot of member variables to help setup an instance. There are a lot of parameters to be used for the shaders so having it all passed in a script call would be more confusing so I simply decided to use member variables instead, more strictly so for these than light instance.

Basically you setup the x,y,z of the instance, on create or each step/enmd step (if moving), along with all other conventional image_VARIABLES. the draw event shows how the right shader is used in the circonstance. The code basically set the proper shader according to what lighting support I want for the instance

I usually set the depth to be the Z value.

See tmc_lux_demo_ship4_obj for a complete full ON 3d light aware render with shadow.
See tmc_lux_demo_ship3, See tmc_lux_demo_ship2 and See tmc_lux_demo_ship objects drawing with less and less features

If your instance casts shadow simply call the add shadow function in the step or draw.


Post Rendering (Sprited Lights and Shadows and Layering)

The sprited lights and the shadow system is performed on the final game image at the end of the draw cycle. Basically the application_surface needs to be ON for this. At the end of the draw cycle the application_surface is cloned, the clone is mixed with the light sprites and shadows and placed back on the application_surface.

The sprited lights are not true lights, they are sprites mixed with the render to glow the render in a way that emulated lights. with it you can have nice effect like lights coming in from a window, or complex lights. though the system is not realistic it adds to the ambiance of the game. The drawback is you can't have a sprited light on a totally black surface (AKA in total darkness). it would not do anything to a black color.

The shadow system is basically taking advantage of having got the application_surface clone (implemented initially for the sprited lights) and it simply adds shadow blobs (sprites ar per your instructions)) on the clone before the sprited lights are handled.

This is done in the post render process. actually in the draw event by the controller which is set to be drawn last in that event (see its depth). However on occasion you would want shadows and lights to be handled in layers, when you want shadows (and sprited lights) to be handle before doing anything else that would normally appear above the shadow.

tmc_lux_add_sprited_lights_handler() will add a layer handler at a specific depth (z), (If you want layers) you need to call this once when the level starts to setup your depth layers... this will create a handler instance to handle everything sprited light and shadow related that was added at the a deeper depth/z... Ultimately you can also drop a few tmc_lux_sprited_lights_handler_obj objects in the room and use the room instance code to manually set the depth value for each handler/layer.
 
Last edited by a moderator:
I

icuurd12b42

Guest
"But I dont want to clone your object!!!"
What variables do I need to set and when?


for light enabled object, objects that reflect lights
basically, every m_ variables in the create and the z variable
Code:
//the ambient color for this object
m_AmbientColor = c_white;
m_Ambient_Power = .3;
m_Ambient = tmc_lux_light_color_to_array(m_AmbientColor,m_Ambient_Power);

//the texture coords on the texture page
//here I assume images used will be from the sprite_index, 0 for sprite, 1 for normal, 2 for specular, 3 for occlusion
//Here I get all the stuff because I assume the use of the most complete of the 4 shaders
m_SrcTexPos = sprite_get_uvs(sprite_index,0);
m_NormTexPos = sprite_get_uvs(sprite_index,1);
m_SpecTexPos = sprite_get_uvs(sprite_index,2);
m_OccTexPos = sprite_get_uvs(sprite_index,3);

//the texture from each of the sprites. this could be done in the draw, probably safer in the draw
//here I assume images used will be from the sprite_index, 0 for sprite (no textere fetch neede), 1 for normal, 2 for specular, 3 for occlusion
m_NormTex = sprite_get_texture(sprite_index,1);
m_SpecTex = sprite_get_texture(sprite_index,2);
m_OccTex = sprite_get_texture(sprite_index,3);


m_LightUnder = true;

m_LightSmooth = 1;

//Extra z coord
z = depth;//0;

//flip normal rgb default to no flip
m_FlipRGB = tmc_lux_make_flip_rgb_array(0,0,0);
and the draw
Code:
tmc_lux_set_norm_spec_occ_shdr();; //this shader does everything. you may choose a shader that does less from the 4 available
//draw
draw_self();
//reset
if(tmc_lux_get_lights_enabled()) shader_reset();
note the create fetches the textures required for the rendering depending on the type of object it is. in the case of the ships that are not animated every texture it needs is in a single sprite and so the textures are fetched in the create for efficiency's sake

for animated sprites like the platformer character, the textures needed are split into multiple animated sprites, one for the diffuse (original images) one for the normals and so on. so the textures a fetched in the draw every time
create
Code:
//image_xscale = random_range(.25,1);
//image_yscale = image_xscale;

//the ambient color for this object
m_AmbientColor = c_white;
m_Ambient_Power = .3;
m_Ambient = tmc_lux_light_color_to_array(m_AmbientColor,m_Ambient_Power);

m_Diffuse = sprite_index;
m_Normal = tmc_lux_demo_stand_norm_spr;
m_Specular = tmc_lux_demo_stand_spec_spr;
m_Occlusion = tmc_lux_demo_stand_occ_spr;

m_LightUnder = true;

m_LightSmooth = 4;

//Extra z coord
z = depth;

//flip normal rgb default to no flip
m_FlipRGB = tmc_lux_make_flip_rgb_array(0,0,0);
draw:
Code:
// for each image involved, and at the current image index
//the texture coords on the texture page
m_SrcTexPos = sprite_get_uvs(m_Diffuse,image_index);
m_NormTexPos = sprite_get_uvs(m_Normal,image_index);
m_SpecTexPos =sprite_get_uvs(m_Specular,image_index);
m_OccTexPos = sprite_get_uvs(m_Occlusion,image_index);

//and the texture... the diffuse is the sprite_index so no need to fect that one
m_NormTex = sprite_get_texture(m_Normal,image_index);
m_SpecTex = sprite_get_texture(m_Specular,image_index);
m_OccTex = sprite_get_texture(m_Occlusion,image_index);

tmc_lux_change_flip_rgb_array(m_FlipRGB,image_xscale<0,0,0);



tmc_lux_set_norm_spec_occ_shdr();
draw_self();
if(tmc_lux_get_lights_enabled()) shader_reset();
the lights themselves are pretty self evident as far as the variables used
create:
Code:
z = -100;//random_range(-1000,1000);
x = x;
y = y;

color = merge_colour(c_red,merge_color(c_lime,c_blue,random(1)),random(1));
strength = 1;///random(1);
falloff = 0.01;//max(.0001,random(1));
range = 2000;// * strength;
end step:
Code:
tmc_lux_add_light(x,y,z,color,strength,falloff,range,1,true);
 

kburkhart84

Firehammer Games
I'm working on my little demo asteroids game. I wanted to have an object both create a light and be affected by the lighting system. But I don't want the light it creates to affect the origin object. Basically, I want bullets to also be lights and be affected by lights, accept the light the bullet itself creates. The reason for this is because having a light right on an object creates blowout. Below are solutions I have.

1. Move the light above the bullet instead of right on it(and adjust light settings accordingly). I don't like this much, as I want to light to be even with the playing field plane directly on the side of the other objects, and moving the light above the x/y plane would ruin that(though it would get rid of the blowout of course).

2. Work with the m_lightUnder variable, to make lights below the certain depth not affect the bullets. This would allow the bullet to not be lit by the light, but it would also sacrifice OTHER bullets being lit by the light. This is frankly a kind of wonky workaround and wouldn't get the exact results I'm looking for.

3. This solution currently isn't possible, but if instead of returning "true" on creating a light, you returned an "identifier" to the light, and you added scripts to enable/disable the light at specific moments, I could simply disable that light during the draw event of the bullet, and then re-enable it afterwards. I'm understanding that this isn't as easy as I make it sound though, because you have the organization system behind it, choosing lights based on distance/priority etc... and allowing lights to easily be disabled during the draw event could cause problems with this. Maybe a solution could be to disable/enable the light, but with the caveat that it won't do any actual changing of your distance/priority system. In other words, I can disable the light, but it won't magically enable some other light to take it's place, rather simply sacrifice the one light.

Am I missing something? Is there a solution I'm not seeing?
 
I

icuurd12b42

Guest
if you only want to disable the light casted by a bullet for that bullet you could add the light in the draw event AFTER you draw the bullet... But I dont think that will work all the time.

I would add another entry in the tmc_lux_add_light's array structure. like the id of the instance not affected by the light.. I would clone the add light function so not to touch the original code and call that function to add light... passing on your own data through the new function's arguments or using instance variables...

in the function you can add the id to the array....you can start shoving your own data from the enum's LIGHT._LAST element onward...
like at LIGHT._LAST+0 for the id, LIGHT._LAST+1 for another data item and so on.
... orig code up to the new spot
var light = global.tmc_lux_lights[global.tmc_lux_light_at];
global.tmc_lux_light_at++;
light[@LIGHT._LAST+2] = argument10; //new user element 2
light[@LIGHT._LAST+1] = argument9; //new user element 1
light[@LIGHT._LAST+0] = id; //new user element 0
...original array setting
light[@LIGHT.SHADOW_PROCESSED] = 0;
....


I would then clone the tmc_lux_set_???_shdr script you are using for the game... again so not to mess with the original code. so you can use that set shader script when you draw...

In that set shader script, I would filter out the light list based on the extra data you added. like if the id stored in the array is the id of the instance that called the script, don't add the light to the final shader array just by extending this if
if(light[@LIGHT.Z]<=TheZ or LightUnder)

to use your filter
if(light[@LIGHT.Z]<=TheZ or LightUnder or light[@LIGHT._LAST+0] != id)

Yep. that should work
 
Last edited by a moderator:
I

icuurd12b42

Guest
I agree, though I would rather keep it as is for now.

I am here if you need customisation. It's the reason I added that _LAST entry in every structure.

Made some corrections to the sample code I posted
 
Last edited by a moderator:

kburkhart84

Firehammer Games
No problem, support has been fine, and customization should be somewhat doable even without support the way you coded the thing in the first place. It was more about the feature suggestion, mainly since in my opinion that would be a commonly requested feature.
 

kburkhart84

Firehammer Games
So I'm gonna post a couple screenies just because I can!



Screen1.png Screen2.png Screen3.png

I'm still going to do some adjustments, and possibly make the changes you suggested about not lighting up the bullets(see how the bullets light up kinda ugly). I'm also going to change some things, for example the asteroid color is too dark and too red as well. I think a gray color will work better. Notice how the ship and roids light up with the bullets though!

My plans for this include having explosions that will make some nice lighting as well, and in fact may very well explode some lights along with the particles, so the primary system will flicker brightly, and it would release lighting particles too.
 
I

icuurd12b42

Guest
you can also play with the normal texture of your bullets... you are not obligated to have them match the shape of the bullet.

I also play with the z of the lights sometimes to place it a little higher than the object itself

also you could use light cones... and have the bullet be in the excluded region of the ligh cone. A cone can have the shape of a spotlight to a shape of a peach... the bullet could be in the peach's crack if you catch what I mean...

If you are planning on light particles, consider using sprited lights which are way more efficient... you can have one true light for the initial glare of the explosion and sprited lights particles for the sparks.

I would also make the same suggestion for light emitting bullets if your game is to be bullet intensive. the demo shows both. you have basically a very high upper limit for the number of sprited lights
 

kburkhart84

Firehammer Games
I think my best bet is just to follow your suggestion and do a bit of code to make it just exclude the light for that specific bullet. All the rest seems like it works. I wouldn't have to mess with switching to cones or anything that way as well.

About the particles, even though my plan is to kind of "push the limits" of GMS and LUX, I'm not trying to just make like every particle be a light. I'm thinking a huge explosion might emit lie 5-10 lights, which is a pretty high number but should be doable.

Actually, the bullets die so quickly that there won't be tons of bullets on screen at any one point.

In any case, this project is really about trying to see how far the limits go, and see how well it works on my integrated graphics laptop. I'm also considering if it is truly worth using this art pipeline with GMS or not. I'm considering that if by using the 2d engine with LUX(for nice lighting) if I can get good performance on lower end devices, it is good. If I can't get enough performance with the look I'm wanting, then I'll either need to raise the system requirements, at which point it may be better to just go full 3d with a 3d engine(I'm making 3d models to get these graphics anyway...). It depends on the performance I get on the lower end. I get the feeling it is going to be fine as long as I don't go too extreme with things.
 
I

icuurd12b42

Guest
Remember the number of (rendered) 3d lights per instance (drawn) depends on your graphics hardware capabilities. that is why I have the option to limit the lights from 0 to 20. if an instance requires more than the set limit, the furthest/dimmest ones will be ignored. the default is 10. The GPU burden grows exponentially, at least it did on my other older graphics card (for some reason).
 

kburkhart84

Firehammer Games
Yeah, I've got a pretty good understanding of what you are doing with light limits. I'm not expecting to get good performance on mobile, but I'm curious how well it will work on integrated graphics, and if would work good enough to justify doing this instead of full-on 3d as far as performance goes. I'm currently just working with your default settings, and the "extra" lights like bullets are limited in range anyway so it won't be noticeable that things dropoff. I may find out that it won't be any faster than just doing 3d in another engine, but who knows?
 

kburkhart84

Firehammer Games
So....I'm having trouble getting the filtering to work....I'm not exactly sure why though. I figured out what appears to be a logic error on the part of the following code you gave me.
Code:
if(light[@LIGHT.Z]<=TheZ or LightUnder or light[@LIGHT._LAST]!=id)
The reason is because that is going to evaluate to true if any of those 3 comparisons is true, meaning that the 3rd one I added is likely not even getting considered. So, if I'm understanding correctly, the stuff that happens if this is true is where the light is actually getting added, so the statement needs to evaluate to false in order for the filtering to be affected. So I changed the code to the following, and it still doesn't work for whatever reason.
Code:
if((light[@LIGHT.Z]<=TheZ or LightUnder) and light[@LIGHT._LAST]!=id)
Logically, the statement should have evaluated to false if the id was equal to the LIGHT._LAST part of the array. So this makes zero sense. I even added an "else" to the if statement in case it really was resolving false(and I'm somehow mistaking what is happening) but it never executes what is in the else statement either, so I'm not figuring out what is missing.
Code:
if((light[@LIGHT.Z]<=TheZ or LightUnder) and light[@LIGHT._LAST]!=id)
        {
            lightpos[totlights*3+0] = light[@LIGHT.X];
            lightpos[totlights*3+1] = light[@LIGHT.Y];
            lightpos[totlights*3+2] = light[@LIGHT.Z];
           
            lightcols[totlights*4+0] = light[@LIGHT.R];
            lightcols[totlights*4+1] = light[@LIGHT.G];
            lightcols[totlights*4+2] = light[@LIGHT.B];
            lightcols[totlights*4+3] = light[@LIGHT.POWER];
           
            lightfalloffs[totlights] = light[@LIGHT.FALLOFF];
           
            ranges[totlights] = light[@LIGHT.RANGE];
   
            conespecs[totlights*4+0] = light[@LIGHT.FX];
            conespecs[totlights*4+1] = light[@LIGHT.FY];
            conespecs[totlights*4+2] = light[@LIGHT.FZ];
            conespecs[totlights*4+3] = light[@LIGHT.CONE_CO];       
           
            totlights++;
        }
        else
            show_debug_message("false");
Now, I've done the basic steps, debugging, etc... I know the first bullet gets id 100310, and I have verified(via the debugger) that position 17 of the light(in your array) is indeed set to that value. I'm assuming that _LAST is 17, and I'm using the "constant" in both functions anyway. So what am I missing? Thanks in advance for looking.
 

kburkhart84

Firehammer Games
LOL, just figured it out!

Code:
with(tmc_lux_get_anchor(x,y))
The filtering is happening inside of that with statement, therefore it needed to be other.id, not just id because of course the id would be for the anchor, not for the other object. I still had to keep the logic change I mentioned above, with the and instead of all or logic gates. I figured out the problem by emitting the id variable right next to where I was accessing it(instead of in the draw event where it would show the right value) and it would never show the bullet id I knew it to be.
Code:
if((light[@LIGHT.Z]<=TheZ or LightUnder) and light[@LIGHT._LAST]!=other.id)
But that did the trick. I changed the ambient lighting for the bullets(they were too dark) and you can now see that I get what I was looking for. The bullets light up everything else, but aren't affected by their own light.

Screen4.png
 
I

icuurd12b42

Guest
Ooops, sorry for the multiple logical errors. glad you figured it out!!

When I validate the code for gms:2 I'll add that feature which, last night, I thought maybe I could also use a variation of this to have groups... also hoping to add light beams... we'll see. I started to go through all my assets this last week for gms2 validation. so maybe in a week or so...
 

kburkhart84

Firehammer Games
Hey, no problem...I can handle a little code myself. I was actually going to end up coding a shader similar to what you have here when I ran across LUX and decided it was a better deal to purchase instead of take my time to create it.

Groups..........I like the idea. You laid enough groundwork for the future when you put the constants for the array positions, which is a good thing. There is indeed some room for a few improvements. The shadow system would be great(but much more complex of course). In any case I have my solution working in my game for the moment. If the whole art pipeline works out, I may very well be more appreciative of the features you add as I would be using them in future projects.
 
I

icuurd12b42

Guest
GMS2
I tested on gms2 I thought it was not working because the darn room0 that is now included in a new project was, well, giving me a black screen lol... Of course

For the demo to work properly you will need to move room0 to the end of the resource list and you will need to set the default group (temporarily at least, until you set up you own groups) to no crop and no scale

upload_2017-5-14_1-44-32.png
Mind you you will also need to do the same in gms1 because texture group information is not packaged in assets...

the following compatibility script is required
__view_get


Converted builtin : line 27 : view_xview -> __view_get( e__VW.XView, 0 )
Converted builtin : line 29 : view_xview -> __view_get( e__VW.XView, 0 )
Converted builtin : line 28 : view_yview -> __view_get( e__VW.YView, 0 )
Converted builtin : line 30 : view_yview -> __view_get( e__VW.YView, 0 )
Converted builtin : line 29 : view_wview -> __view_get( e__VW.WView, 0 )
Converted builtin : line 30 : view_hview -> __view_get( e__VW.HView, 0 )

It's a shame that gms2 include EVERYTHING in one compatibility package. but if you feel you need to clean that up, you only need to keep

__init_view()
which defined the enum, no need to call it I think
and
__view_get()
 
Last edited by a moderator:

kburkhart84

Firehammer Games
I installing the new version of GMS2 and testing right now...I'm going to feel quite stupid if my issue was all about the 2 settings in the texture group, but considering the graphical errors I was getting it very well could be that.

***********************

WOW...it was the automatic cropping that did it. All of that crap I was trying to figure out and that was the key. In fact, if you import a project from GMS1(at least in my case) those options are already disabled, which is why I couldn't figure out what was going on. I had imported a project with LUX and it was working, but when creating a new project and just importing LUX's assets game me the problems. And I also just opened up a newly created project in GMS2, and indeed those two options are enabled by default.

Thanks for that!
 
Last edited:
I

icuurd12b42

Guest
I installing the new version of GMS2 and testing right now...I'm going to feel quite stupid if my issue was all about the 2 settings in the texture group, but considering the graphical errors I was getting it very well could be that.

***********************

WOW...it was the automatic cropping that did it. All of that crap I was trying to figure out and that was the key. In fact, if you import a project from GMS1(at least in my case) those options are already disabled, which is why I couldn't figure out what was going on. I had imported a project with LUX and it was working, but when creating a new project and just importing LUX's assets game me the problems. And I also just opened up a newly created project in GMS2, and indeed those two options are enabled by default.

Thanks for that!
the texture group thing was an issue in the past with gms1... I had a note about it in the asset text. but I think I removed it when they fixed it? not sure. I know I had a mention somewhere.

And yeah, to explain why this happens is I made the shader aware or the position and width/height that the images for the normal, occlusion and so on occupy on the texture page they reside on. this allows not having to use the Use For 3d Flag and so reduces the swaps dramatically... But the image needs to be intact on the texture page, that is not "cropped" to save space.
 
Last edited by a moderator:

kburkhart84

Firehammer Games
Yeah, once I saw what the fix was, I pretty much knew what the cause was as far as your code. In fact, that specific issue, with getting the 'real' texture coords, etc... was something I had ran into when I started trying to code my own similar system(which I never got far into thanks to LUX).

I think I never ran across the texture group settings issues while using GMS1 just because the 'default' settings were different from GMS2. Now that things are different from default settings, we are going to need to change it for each project and texture group. This isn't really a big deal, but something to watch.
 
I

icuurd12b42

Guest
Just remember to set a group or groups that have the setting right. you dont need it for everything, only the images that are involved with LUX. There is apparently a way to setup group property parenting but I was not really able to make that work. I basically have a group for everything without using that feature.
 

kburkhart84

Firehammer Games
Honestly...from what I have seen, the texture groups feature is most useful on something like HTML5, mobile, or games that are meant to work on integrated graphics....none of which I would expect to support heavy usage of LUX anyway. Unless you have a really large game, I would expect all of your textures to fit in the VRAM of any modern (discrete/dedicated) graphics card, which is needed to support heavy LUX usage anyway. I'm not sure how useful the texture group features will be in this instance regardless.
 
I

icuurd12b42

Guest
Honestly...from what I have seen, the texture groups feature is most useful on something like HTML5, mobile, or games that are meant to work on integrated graphics....none of which I would expect to support heavy usage of LUX anyway. Unless you have a really large game, I would expect all of your textures to fit in the VRAM of any modern (discrete/dedicated) graphics card, which is needed to support heavy LUX usage anyway. I'm not sure how useful the texture group features will be in this instance regardless.
FPS degeneration due to swaps start at around 6-10 swaps on portables (phones, tablets and I guess html5). the value is higher on Windows. At around 50-120. so, it's still something to be cautious about, all you need to blow your game to crap is to have 2 characters that are not on the same page drawn one after each other 60 times.

There's different address space in GPU, gpu have active slots to draw from. just because your texture is in GPU ram does not really mean it's "ready to go". a swap is when a texture is placed in one of the active slots
 
Am I correct in thinking that the LUX extension doesn't cast proper shadows, just projected sprite shadows? I'm looking to be able to have a cone light that is obscured as it hits a wall (collision object) and that then casts a shadow on the other side automatically.
 
I

icuurd12b42

Guest
Am I correct in thinking that the LUX extension doesn't cast proper shadows, just projected sprite shadows? I'm looking to be able to have a cone light that is obscured as it hits a wall (collision object) and that then casts a shadow on the other side automatically.
Yes, you are correct. Nocturne has a shadow casting system.
 
A

AlexM

Guest
Hey,

i just got into the Lux Engine. After looking through the demo, I found that i might go with the sprited lights first. So to test around i created a simple sprite to check on the lighting effect, but I found that not all colors of the test sprite would be lit up:

Check the attached pictures for 1, 3 and 6 lights in the demo room
(Left is reference / right is with sprited light from demo)

I have the impression, that the blending does not affect all colors the same way. Up to the point that some aren't even affected at all. Am I maybe doing something wrong?

Thank you and best Regards
Alex
 

Attachments

I

icuurd12b42

Guest
Hey,

i just got into the Lux Engine. After looking through the demo, I found that i might go with the sprited lights first. So to test around i created a simple sprite to check on the lighting effect, but I found that not all colors of the test sprite would be lit up:

Check the attached pictures for 1, 3 and 6 lights in the demo room
(Left is reference / right is with sprited light from demo)

I have the impression, that the blending does not affect all colors the same way. Up to the point that some aren't even affected at all. Am I maybe doing something wrong?

Thank you and best Regards
Alex
That's right. the sprited lights do not affect all the colors the same way and the way they do also depend on the light color. typically darker background colors are less affected by the light than those that are lighter or those that have values in all r,g,b channels. If you turn the sprited light compatibility mode ON it will revert to bm_add.

A lot of sprited lights
upload_2018-8-13_4-43-27.png

Compatibility Mode

upload_2018-8-13_4-46-52.png

Note that if you want to use bm_add/compatibility mode... you will need to have the sprites less transparent...

@Nocturne , why is the forum complaining about images being too big when I seen ppl post 15MB animated gifs basically the size of the screen? it's weird...
 
A

AlexM

Guest
Ah yes it works with compatibility mode on, but what is the drawback of this? I guess that is not the normal way of doing it?

Is there a way that the light will not affect the background? I assume it can be done via the layer handler?
 
I

icuurd12b42

Guest
Ah yes it works with compatibility mode on, but what is the drawback of this? I guess that is not the normal way of doing it?

Is there a way that the light will not affect the background? I assume it can be done via the layer handler?
the layer handler is used to process the lights in the draw queue so if you need process ligths say below clouds for example separately from lights above clouds or ui elements... it is a means to prevent light drawing above everything, it is not a mean to not affect things already drawn.

if you want a background, have an object deep in the draw depth clear the application surface with alpha 0. cancel the application surface auto drawing and draw your background in the gui draw or end draw and draw the application surface yourself on top of it. the places where the alpha is still ~0 in the application surface will show the background image through it, unaffected by lights... I think that should do it.
 
I

icuurd12b42

Guest
Does this system have specular and occlusion maps?
normals, specular and occlusion, yes. with matching (streamlined) shaders which you can choose from depending on what you have for lighting for the asset...
 
Top