zworld/engine/render/pass/blur.go
2024-01-14 22:56:06 +08:00

128 lines
2.9 KiB
Go

package pass
import (
"fmt"
"github.com/vkngwrapper/core/v2/core1_0"
"zworld/engine/object"
"zworld/engine/renderapi"
"zworld/engine/renderapi/command"
"zworld/engine/renderapi/descriptor"
"zworld/engine/renderapi/framebuffer"
"zworld/engine/renderapi/material"
"zworld/engine/renderapi/renderpass"
"zworld/engine/renderapi/renderpass/attachment"
"zworld/engine/renderapi/shader"
"zworld/engine/renderapi/texture"
"zworld/engine/renderapi/vertex"
"zworld/engine/renderapi/vulkan"
)
type BlurPass struct {
app vulkan.App
material *material.Material[*BlurDescriptors]
input vulkan.Target
quad vertex.Mesh
desc []*material.Instance[*BlurDescriptors]
tex []texture.T
fbufs framebuffer.Array
pass renderpass.T
}
var _ Pass = &BlurPass{}
type BlurDescriptors struct {
descriptor.Set
Input *descriptor.Sampler
}
func NewBlurPass(app vulkan.App, output vulkan.Target, input vulkan.Target) *BlurPass {
p := &BlurPass{
app: app,
input: input,
}
frames := input.Frames()
p.quad = vertex.ScreenQuad("blur-pass-quad")
p.pass = renderpass.New(app.Device(), renderpass.Args{
Name: "Blur",
ColorAttachments: []attachment.Color{
{
Name: OutputAttachment,
Image: attachment.FromImageArray(output.Surfaces()),
LoadOp: core1_0.AttachmentLoadOpDontCare,
FinalLayout: core1_0.ImageLayoutShaderReadOnlyOptimal,
},
},
Subpasses: []renderpass.Subpass{
{
Name: MainSubpass,
ColorAttachments: []attachment.Name{OutputAttachment},
},
},
})
p.material = material.New(
app.Device(),
material.Args{
Shader: app.Shaders().Fetch(shader.NewRef("blur")),
Pass: p.pass,
Pointers: vertex.ParsePointers(vertex.T{}),
DepthTest: false,
DepthWrite: false,
},
&BlurDescriptors{
Input: &descriptor.Sampler{
Stages: core1_0.StageFragment,
},
})
var err error
p.fbufs, err = framebuffer.NewArray(frames, app.Device(), "blur", output.Width(), output.Height(), p.pass)
if err != nil {
panic(err)
}
p.desc = p.material.InstantiateMany(app.Pool(), frames)
p.tex = make([]texture.T, frames)
for i := range p.tex {
key := fmt.Sprintf("blur-%d", i)
p.tex[i], err = texture.FromImage(app.Device(), key, p.input.Surfaces()[i], texture.Args{
Filter: texture.FilterNearest,
Wrap: texture.WrapClamp,
})
if err != nil {
// todo: clean up
panic(err)
}
p.desc[i].Descriptors().Input.Set(p.tex[i])
}
return p
}
func (p *BlurPass) Record(cmds command.Recorder, args renderapi.Args, scene object.Component) {
quad := p.app.Meshes().Fetch(p.quad)
cmds.Record(func(cmd command.Buffer) {
cmd.CmdBeginRenderPass(p.pass, p.fbufs[args.Frame])
p.desc[args.Frame].Bind(cmd)
quad.Draw(cmd, 0)
cmd.CmdEndRenderPass()
})
}
func (p *BlurPass) Name() string {
return "Blur"
}
func (p *BlurPass) Destroy() {
for _, tex := range p.tex {
tex.Destroy()
}
p.fbufs.Destroy()
p.pass.Destroy()
p.material.Destroy()
}