This extension contains ready-to-use forward shading lighting for 3D games made with Defold. Just set the provided material to your mesh and place light sources on the scene.
Technically it supports about ~200 light sources, but the performance limit is about 20-30 sources at the moment. Need to implement clustered forward shading to get a valuable performance boost.
All the lighting data passed to the shader program as the texture, so it doesn’t use a render script.
At this time, any intervention in the render script turns the external library into an example project. This is one of the reasons why all the data is passed with the texture here.
But the development of libraries with additional render passes will be possible after adding the modularity of the rendering pipeline that has been rumored
This is on an experimentation stage at the moment. I’m not sure if it will ever become a single prescribed solution to modular render scripts or if it is better to have it as an opt-in thing much the same way as camera or screen management solutions are made available today.
Unfortunately, the problem is that rendering modularity does not solve the problem of effect conflict.
For example, you have some extension with deferred rendering pipeline.
And you need to insert your custom pass there instead of the “final build” pass, which implements cluster lighting.
And other user also want to add Bloom - so he need a couple more passes after all the existing ones.
And now other user want to add SSLR - where does he stick them?
It all makes sense if you make one big extension with all the effects, and then you can just turn them off if you want to.
But making individual effects modular is quite inconvenient. And the problem is not manually changing the render script, but that it’s rather problematic to make a universal effect that will easily connect and combine with all variations of user projects.
Well, very strong points! I don’t have enough experience to tell how to make it better, other than in terms of “the easier it is to plug and run, the better”.
If the best way is to make one big extension with switchable options, some kind of consolidation is needed for such a solution. At first look it’s too unrealistic to make this usable and efficient without consolidated development.
My idea is that you probably want to insert custom passes into the graph, but only for certain scenarios (mostly debugging) but not a completely modular approach because that is probably a lot bigger and more complex undertaking… On the whole the purpose of at least my project is that I’d rather develop it as a fixed set of features into an asset that can be dropped into any project to get a good looking game without too much hassle.
I happen to have seen this example before and found it very promising. )
I was thinking along the same lines - create a custom pipeline where only post-processing effects or shadow renders can be plugged in. And nothing else.
With that limitation, it’s easier to make an good architecture.
I do have a completely modular approach for GMAI, that I hope to open source once I get the time. It’s more rather optimised with post-processing filters in mind, but it looks somewhat like this:
local pipeline = require "main.render.pipeline"
local dispatcher = require "crit.dispatcher"
local save_file = require "lib.save_file"
local h_filter_set_enabled = hash("filter_set_enabled")
local h_config_change = hash("config_change")
go.property("enabled", true)
go.property("hook", hash("gui"))
go.property("alpha", true)
local function update_enabled(self)
pipeline.set_module_enabled(self.module, self.enabled and not save_file.config.reduce_vfx)
end
function init(self)
self.module = pipeline.register_module(self.hook, {
sort_order = 10,
output = 1,
render_passes_before = {{
output = pipeline.INPUT,
clear = true,
clear_color = vmath.vector4(0),
}},
render_passes = {{
inputs = {pipeline.INPUT},
output = 1,
settings = self.alpha and "filter_alpha" or "filter",
predicate = "chromatic_abberation",
-- Optimise away clears done to pipeline.OUTPUT
-- since all the pixels will be overwritten anyway
is_clear_invariant = not self.alpha,
}},
})
self.sub_id = dispatcher.subscribe({ h_config_change })
update_enabled(self)
end
function on_message(self, message_id, message)
if message_id == h_filter_set_enabled then
self.enabled = message.enabled
update_enabled(self)
elseif message_id == h_config_change then
if message.key == "reduce_vfx" then
update_enabled(self)
end
end
end
function final(self)
pipeline.unregister_module(self.module)
dispatcher.unsubscribe(self.sub_id)
end