Materials/Textures Tutorial? Rendering more than once in one frame with alpha blending
1 replies, posted
I'm trying to create a script that would render the scene more than once (let's say, 5 times), each with a variation, and blend all these together with equal weights. Conceptually, I think this is what I'm supposed to do:
1. Render scene at 100% alpha
2. Modify scene, render scene at 50% alpha
3. Modify scene, render scene at 33% alpha
4. etc...
There are several vanilla post-processing effects that do some variation of this, and they are:
[url=https://github.com/garrynewman/garrysmod/blob/master/garrysmod/lua/postprocess/motion_blur.lua]Accumulation Motion Blur[/url] (most readable with comments)
[url=https://github.com/garrynewman/garrysmod/blob/master/garrysmod/lua/postprocess/frame_blend.lua]Frame Blend[/url] (crap readability)
[url=https://github.com/garrynewman/garrysmod/blob/master/garrysmod/lua/postprocess/super_dof.lua]Super DoF[/url]
There may be others as well.
The problem is, I've tried and failed to read these scripts. I can't find a good explanation for how Materials and Textures work, and they are basically the entirety of how this is accomplished. I've tried copy-pasting some parts, hacking them together, crossing my fingers for a usable result, trying random things, but to no avail. I just don't have enough (read: any) understanding for how Materials and Textures work, to get this script running.
Some key things:
* This needs to work with the "poster" command, so I'm doing it in GM:RenderScene.
* Processing time is not an issue. It can take an hour for all I care.
My current code, quite probably cringe-worthy:
[lua]if SERVER then print("SoftPoster must be run clientside!") return end // this is a goddamn client script!
// Frame blending code attempted to be copied from: motion_blur.lua
local mat_MotionBlur = Material( "pp/motionblur" )
local tex_MotionBlur = render.GetMoBlurTex0()
local mat_Screen = Material( "pp/fb" )
function SoftPoster(radius, resmul, split)
local i = resmul * resmul + 5 // i = number of calls of GM:RenderScene that need to be hooked, plus 5 for good measure
local up = LocalPlayer():GetAngles():Up()
local right = LocalPlayer():GetAngles():Right()
local origin = LocalPlayer():GetPos()
hook.Add("RenderScene", "SoftPoster", function()
local alpha = 1
LocalPlayer():SetPos(origin)
mat_Screen:SetFloat( "$alpha", 1.0 )
mat_Screen:SetTexture( "$basetexture", tex_MotionBlur )
render.SetMaterial( mat_Screen )
render.RenderView()
LocalPlayer():SetPos(origin + (up * radius) + (right * radius))
mat_Screen:SetFloat( "$alpha", 1.0 / 2.0 )
mat_Screen:SetTexture( "$basetexture", tex_MotionBlur )
render.SetMaterial( mat_Screen )
render.RenderView()
LocalPlayer():SetPos(origin - (up * radius) + (right * radius))
mat_Screen:SetFloat( "$alpha", 1.0 / 3.0 )
mat_Screen:SetTexture( "$basetexture", tex_MotionBlur )
render.SetMaterial( mat_Screen )
render.RenderView()
LocalPlayer():SetPos(origin + (up * radius) - (right * radius))
mat_Screen:SetFloat( "$alpha", 1.0 / 4.0 )
mat_Screen:SetTexture( "$basetexture", tex_MotionBlur )
render.SetMaterial( mat_Screen )
render.RenderView()
LocalPlayer():SetPos(origin - (up * radius) - (right * radius))
mat_Screen:SetFloat( "$alpha", 1.0 / 5.0 )
mat_Screen:SetTexture( "$basetexture", tex_MotionBlur )
render.SetMaterial( mat_Screen )
render.RenderView()
LocalPlayer():SetPos(origin)
-- render.SetMaterial( mat_MotionBlur )
-- render.DrawScreenQuad()
print(i)
i = i - 1
if (i == 0) then
hook.Remove("RenderScene","SoftPoster")
print("Removing hook")
end
return true
end)
RunConsoleCommand("poster", resmul, split)
end[/lua]
I put this code in a lua file in garrysmod/lua, and in-game I use the concommand:
[b]lua_openscript_cl softposter.lua[/b]
I also have the binding:
[b]bind semicolon "lua_run_cl SoftPoster(10, 2)"[/b]
for testing.
I promise the end product that I'm planning will be more elegant to use :P
tl;dr Can you please point me at a proper explanation or tutorial for Materials and Textures?
So, after a night's sleep and a second attempt at figuring out how Accumulated Motion Blur works, I think I have a much better understanding of how things play with each other. However, I'm still having problems. Here's the current iteration of my code:
[lua]if SERVER then print("SoftPoster must be run clientside!") return end // this is a goddamn client script!
// Frame blending code copied from: motion_blur.lua
local mat_MotionBlur = Material( "pp/motionblur" )
local mat_Screen = Material( "pp/fb" )
local tex_MotionBlur = render.GetMoBlurTex0()
local function RenderWithAlpha(addalpha)
render.UpdateScreenEffectTexture()
mat_Screen:SetFloat( "$alpha", addalpha )
local oldRT = render.GetRenderTarget()
render.SetRenderTarget(tex_MotionBlur)
render.SetMaterial(mat_Screen)
render.DrawScreenQuad()
--render.Clear(255, 0, 0, 255, true, true)
render.SetRenderTarget(oldRT)
end
function SoftPoster(radius, resmul, split)
local callsleft = resmul * resmul + 1 -- + 800 -- number of calls of the render hook that need to be hooked, 1 extra called pre-poster
local ent = LocalPlayer():GetEyeTrace().Entity
local up = ent:GetAngles():Up()
local right = ent:GetAngles():Right()
local origin = ent:GetPos()
print("Starting poster")
--hook.Add("RenderScene", "SoftPoster", function()
hook.Add("RenderScreenspaceEffects", "SoftPoster", function()
mat_MotionBlur:SetFloat("$alpha", 1)
mat_MotionBlur:SetTexture( "$basetexture", tex_MotionBlur )
-- Center:
ent:SetPos(origin)
RenderWithAlpha(1)
-- Up Right:
ent:SetPos(origin + (up * radius) + (right * radius))
RenderWithAlpha(1/2)
-- Down Right:
ent:SetPos(origin - (up * radius) + (right * radius))
RenderWithAlpha(1/3)
-- Up Left:
ent:SetPos(origin + (up * radius) - (right * radius))
RenderWithAlpha(1/4)
-- Down Left:
ent:SetPos(origin - (up * radius) - (right * radius))
RenderWithAlpha(1/5)
-- return to normal:
ent:SetPos(origin)
-- This part WORKS, it writes whatever was rendered in RenderWithAlpha to screen:
render.SetMaterial( mat_MotionBlur )
render.DrawScreenQuad()
callsleft = callsleft - 1
if (callsleft == 0) then
hook.Remove("RenderScreenspaceEffects","SoftPoster")
print("Removing hook")
end
--return true
end)
RunConsoleCommand("poster", resmul, split)
end[/lua]
The problem I'm having is one of two (I have no idea how to check which): either the entity doesn't move inbetween calls to RenderWithAlpha even though SetPos is called, or RenderWithAlpha doesn't work correctly.
Please help! :(
Sorry, you need to Log In to post a reply to this thread.