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

153 lines
3.8 KiB
Go

package pass
import (
"github.com/vkngwrapper/core/v2/core1_0"
"zworld/engine/render/uniform"
"zworld/engine/renderapi/command"
"zworld/engine/renderapi/descriptor"
"zworld/engine/renderapi/material"
"zworld/engine/renderapi/renderpass"
"zworld/engine/renderapi/shader"
"zworld/engine/renderapi/texture"
"zworld/engine/renderapi/vertex"
"zworld/engine/renderapi/vulkan"
)
type LightDescriptors struct {
descriptor.Set
Camera *descriptor.Uniform[uniform.Camera]
Lights *descriptor.Storage[uniform.Light]
Diffuse *descriptor.Sampler
Normal *descriptor.Sampler
Position *descriptor.Sampler
Occlusion *descriptor.Sampler
Shadow *descriptor.SamplerArray
}
type LightShader interface {
Bind(command.Buffer, int)
Descriptors(int) *LightDescriptors
Destroy()
}
type lightShader struct {
mat *material.Material[*LightDescriptors]
instances []*material.Instance[*LightDescriptors]
diffuseTex []texture.T
normalTex []texture.T
positionTex []texture.T
occlusionTex []texture.T
}
func NewLightShader(app vulkan.App, pass renderpass.T, gbuffer GeometryBuffer, occlusion vulkan.Target) LightShader {
mat := material.New(
app.Device(),
material.Args{
Shader: app.Shaders().Fetch(shader.NewRef("light")),
Pass: pass,
Subpass: LightingSubpass,
Pointers: vertex.ParsePointers(vertex.T{}),
DepthTest: false,
},
&LightDescriptors{
Camera: &descriptor.Uniform[uniform.Camera]{
Stages: core1_0.StageFragment,
},
Lights: &descriptor.Storage[uniform.Light]{
Stages: core1_0.StageFragment,
Size: 256,
},
Diffuse: &descriptor.Sampler{
Stages: core1_0.StageFragment,
},
Normal: &descriptor.Sampler{
Stages: core1_0.StageFragment,
},
Position: &descriptor.Sampler{
Stages: core1_0.StageFragment,
},
Occlusion: &descriptor.Sampler{
Stages: core1_0.StageFragment,
},
Shadow: &descriptor.SamplerArray{
Stages: core1_0.StageFragment,
Count: 32,
},
})
frames := gbuffer.Frames()
lightsh := mat.InstantiateMany(app.Pool(), frames)
var err error
diffuseTex := make([]texture.T, frames)
normalTex := make([]texture.T, frames)
positionTex := make([]texture.T, frames)
occlusionTex := make([]texture.T, frames)
for i := 0; i < frames; i++ {
diffuseTex[i], err = texture.FromImage(app.Device(), "deferred-diffuse", gbuffer.Diffuse()[i], texture.Args{
Filter: texture.FilterNearest,
})
if err != nil {
panic(err)
}
normalTex[i], err = texture.FromImage(app.Device(), "deferred-normal", gbuffer.Normal()[i], texture.Args{
Filter: texture.FilterNearest,
})
if err != nil {
panic(err)
}
positionTex[i], err = texture.FromImage(app.Device(), "deferred-position", gbuffer.Position()[i], texture.Args{
Filter: texture.FilterNearest,
})
if err != nil {
panic(err)
}
occlusionTex[i], err = texture.FromImage(app.Device(), "deferred-ssao", occlusion.Surfaces()[i], texture.Args{
Filter: texture.FilterNearest,
})
if err != nil {
panic(err)
}
lightDesc := lightsh[i].Descriptors()
lightDesc.Diffuse.Set(diffuseTex[i])
lightDesc.Normal.Set(normalTex[i])
lightDesc.Position.Set(positionTex[i])
lightDesc.Occlusion.Set(occlusionTex[i])
}
return &lightShader{
mat: mat,
instances: lightsh,
diffuseTex: diffuseTex,
normalTex: normalTex,
positionTex: positionTex,
occlusionTex: occlusionTex,
}
}
func (ls *lightShader) Bind(buf command.Buffer, frame int) {
ls.instances[frame].Bind(buf)
}
func (ls *lightShader) Descriptors(frame int) *LightDescriptors {
return ls.instances[frame].Descriptors()
}
func (ls *lightShader) Destroy() {
for _, view := range ls.diffuseTex {
view.Destroy()
}
for _, view := range ls.normalTex {
view.Destroy()
}
for _, view := range ls.positionTex {
view.Destroy()
}
for _, view := range ls.occlusionTex {
view.Destroy()
}
ls.mat.Destroy()
}