I’m thinking of adding some post-effects into the game with the possibility to dynamically turn them on/off. What might be the best (easiest/tidiest) way to do that?
Right now i can only think of the solutionn using the 1x1 quads for each post-effect, i.e. in render script:
0. Add multiple quads to the scene, each with unique rendering tag. Create one render texture, that will be used in each post-effect shader
With no post-effects enabled render camera straight to the screen
Otherwise, render it to the texture. After that render enabled post-effects one-by-one into the same texture, and the last one onto the screen.
So, the questions are:
Can i use the same render texture as input of the shader and as current render target? If not, i’ll ahve to create unique texture for every shader (and render every effect into the texture used in the next effect).
Are there any limitations to max amount of render predicates or something like that?
I think that there are no other ways to do it. I used a few render target for 2d light.
I use one quad model for all render target. I think you can have 2 render target.And draw post-effect first at texture one, second in texture two, then again one, etc.
1)I do not think that your can use same render texture as input of the shader and as current render target.It sound’s like bad idea to change texture, and use this texture in shader in same time.
Please write something about your solution, because i later will need some post-effects for my game.
Managed to run two post-effects simultaneously. Right now i’m reading and writing from the same texture and it works for me, at least in editor. If this wouldn’t work in the future, it can easily be fixed by something like this (pseudocode):
enable_render_target(texture_1)
enable_texture(0, texture_2)
-- Draw effect #1
disable_texture(0, texture_2)
disable_render_target(texture_1)
enable_render_target(texture_2)
enable_texture(0, texture_1)
-- Draw effect #2
disable_texture(0, texture_1)
disable_render_target(texture_2)
...
enable_texture(0, texture_1)
-- Draw last effect onto the screen, choose the needed texture from the previous pass
disable_texture(0, texture_1)
-- Of course, doing all this in cycle, not with copy-pasting like here
Right now my code looks like this:
-- TODO Check if we have any effect to render, otherwise it will break rn
render.enable_render_target(self.target_effect)
-- draw everything as usual here, render target texture has screen's width and height
...
render.disable_render_target(self.target_effect)
-- Prepare render parameters, ignore depth, cull and everything,
-- as we are drawing from quad to quad now and shouldn't care about any of this
-- (i don't have this as i have everything disabled before in main render)
render.set_depth_mask(false)
render.disable_state(render.STATE_DEPTH_TEST)
render.disable_state(render.STATE_CULL_FACE)
-- Set up projections to render quad
render.set_view(vmath.matrix4())
render.set_projection(vmath.matrix4())
-- Render every effect
local effects = { 'effect_grain', 'effect_night' } -- Currently enabled effects, materials added in the *.render file
local effects_count = #effects
for i, effect_name in ipairs(effects) do
local drawing_to_texture = i < effects_count
if drawing_to_texture then
-- Draw every effect except the last one into the texture
-- Should probably call this only once
render.enable_render_target(self.target_effect)
end
-- Enable texture for shader to read
render.enable_texture(0, self.target_effect, render.BUFFER_COLOR_BIT)
-- Create constants buffer with time for post-effects
local constants_buffer = render.constant_buffer()
constants_buffer.time = vmath.vector4(RenderHelper.time)
-- Clear previous data (not needed if everything is filled and depth buffer is ignored etc)
--render.clear({[render.BUFFER_COLOR_BIT] = self.clear_color, [render.BUFFER_DEPTH_BIT] = 1 })
-- Swap material for the effect and draw our quad
render.enable_material(effect_name)
render.draw(self.quad_effect_pred, constants_buffer)
render.disable_material(effect_name)
-- Disable texture for reading, could probably call that on the last effect (only once)
render.disable_texture(0, self.target_effect)
if drawing_to_texture then
render.disable_render_target(self.target_effect)
end
end
-- Render gui as usual (render it in the beginning if needed)
...
I have another question now. Lets say, i want to pass 2 additional textures to the shader. This is “constant” textures - sprites in project. How can add them to the shader. Right now i suppose i only have DIFFUSE_TEXTURE, which is “Texture” field in the model object, so i can add one texture (though it will be the same for every effect shader, because i use one quad for each of them), how can i add another one?
I don’t quite understand how does “samplers” array in materials settings work and if i can use it somehow.