/
erbgmap.go
161 lines (141 loc) · 4.73 KB
/
erbgmap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//
package env
import (
"math"
"github.com/go-gl/mathgl/mgl32"
"github.com/lakal3/vge/vge/vasset"
"github.com/lakal3/vge/vge/vk"
"github.com/lakal3/vge/vge/vmodel"
"github.com/lakal3/vge/vge/vscene"
)
// Render equirectangular projection image as background
type EquiRectBGNode struct {
pool *vk.MemoryPool
imBg *vk.Image
dsPool *vk.DescriptorPool
ds *vk.DescriptorSet
}
func (eq *EquiRectBGNode) Process(pi *vscene.ProcessInfo) {
db, ok := pi.Phase.(vscene.DrawPhase)
if ok {
dc := db.GetDC(vscene.LAYERBackground)
if dc != nil {
eq.Draw(dc)
}
}
}
func (e *EquiRectBGNode) Dispose() {
if e.pool != nil {
e.pool.Dispose()
e.pool, e.imBg = nil, nil
}
if e.dsPool != nil {
e.dsPool.Dispose()
e.dsPool, e.ds = nil, nil
}
}
func (eq *EquiRectBGNode) Draw(dc *vmodel.DrawContext) {
sfc := vscene.GetSimpleFrame(dc.Frame)
if sfc == nil {
return // Not supported
}
cache := sfc.GetCache()
pl := dc.Pass.Get(cache.Ctx, kEqPipeline, func(ctx vk.APIContext) interface{} {
return eq.newPipeline(dc)
}).(vk.Pipeline)
dsFrame := sfc.BindFrame()
cb := getCube(cache.Ctx, cache.Device)
dc.Draw(pl, 0, 36).AddInputs(cb.bVtx).AddDescriptors(dsFrame, eq.ds)
}
func (eq *EquiRectBGNode) newPipeline(dc *vmodel.DrawContext) *vk.GraphicsPipeline {
cache := dc.Frame.GetCache()
ctx := cache.Ctx
gp := vk.NewGraphicsPipeline(ctx, cache.Device)
gp.AddVextexInput(ctx, vk.VERTEXInputRateVertex, vk.FORMATR32g32b32Sfloat)
la := getLayout(ctx, cache.Device)
laFrame := vscene.GetUniformLayout(ctx, cache.Device)
gp.AddLayout(ctx, laFrame)
gp.AddLayout(ctx, la)
gp.AddShader(ctx, vk.SHADERStageVertexBit, eqrect_vert_spv)
gp.AddShader(ctx, vk.SHADERStageFragmentBit, eqrect_frag_spv)
gp.Create(ctx, dc.Pass)
return gp
}
func NewEquiRectBGNode(ctx vk.APIContext, dev *vk.Device, far float32, bgKind string, bgContent []byte) *EquiRectBGNode {
la := getLayout(ctx, dev)
sampler := getEnvSampler(ctx, dev)
eq := &EquiRectBGNode{}
eq.dsPool = vk.NewDescriptorPool(ctx, la, 1)
eq.ds = eq.dsPool.Alloc(ctx)
eq.pool = vk.NewMemoryPool(dev)
var desc vk.ImageDescription
vasset.DescribeImage(ctx, bgKind, &desc, bgContent)
eq.imBg = eq.pool.ReserveImage(ctx, desc, vk.IMAGEUsageTransferDstBit|vk.IMAGEUsageSampledBit)
eq.pool.Allocate(ctx)
cp := vmodel.NewCopier(ctx, dev)
defer cp.Dispose()
cp.CopyToImage(eq.imBg, bgKind, bgContent, desc.FullRange(), vk.IMAGELayoutShaderReadOnlyOptimal)
eq.ds.WriteImage(ctx, 0, 0, eq.imBg.DefaultView(ctx), sampler)
return eq
}
var kEqLayout = vk.NewKey()
var kEnvSampler = vk.NewKey()
var kEqPipeline = vk.NewKey()
var kCube = vk.NewKey()
type cubeVertex struct {
pool *vk.MemoryPool
bVtx *vk.Buffer
}
func (cv *cubeVertex) Dispose() {
if cv.pool != nil {
cv.pool.Dispose()
cv.pool, cv.bVtx = nil, nil
}
}
func (cv *cubeVertex) addCube(tr mgl32.Mat4) (aPos []float32) {
aPos = cv.addPlane(aPos, tr)
aPos = cv.addPlane(aPos, tr.Mul4(mgl32.HomogRotate3DX(math.Pi/2)))
aPos = cv.addPlane(aPos, tr.Mul4(mgl32.HomogRotate3DX(math.Pi/-2)))
aPos = cv.addPlane(aPos, tr.Mul4(mgl32.HomogRotate3DY(math.Pi/2)))
aPos = cv.addPlane(aPos, tr.Mul4(mgl32.HomogRotate3DY(math.Pi)))
aPos = cv.addPlane(aPos, tr.Mul4(mgl32.HomogRotate3DY(-math.Pi/2)))
return
}
func (cv *cubeVertex) addPlane(aPos []float32, tr mgl32.Mat4) []float32 {
aPos = cv.addPos(aPos, tr, mgl32.Vec3{-1, -1, 1})
aPos = cv.addPos(aPos, tr, mgl32.Vec3{1, -1, 1})
aPos = cv.addPos(aPos, tr, mgl32.Vec3{1, 1, 1})
aPos = cv.addPos(aPos, tr, mgl32.Vec3{-1, -1, 1})
aPos = cv.addPos(aPos, tr, mgl32.Vec3{1, 1, 1})
aPos = cv.addPos(aPos, tr, mgl32.Vec3{-1, 1, 1})
return aPos
}
func (cv *cubeVertex) addPos(aPos []float32, tr mgl32.Mat4, pos mgl32.Vec3) []float32 {
pos2 := tr.Mul4x1(pos.Vec4(1))
aPos = append(aPos, pos2[:3]...)
return aPos
}
func getCube(ctx vk.APIContext, dev *vk.Device) *cubeVertex {
return dev.Get(ctx, kCube, func(ctx vk.APIContext) interface{} {
cv := &cubeVertex{}
cv.pool = vk.NewMemoryPool(dev)
cv.bVtx = cv.pool.ReserveBuffer(ctx, 36*4*4, false, vk.BUFFERUsageTransferDstBit|vk.BUFFERUsageVertexBufferBit)
cv.pool.Allocate(ctx)
aPos := cv.addCube(mgl32.Ident4())
cp := vmodel.NewCopier(ctx, dev)
defer cp.Dispose()
cp.CopyToBuffer(cv.bVtx, vk.Float32ToBytes(aPos))
return cv
}).(*cubeVertex)
}
func getLayout(ctx vk.APIContext, dev *vk.Device) *vk.DescriptorLayout {
return dev.Get(ctx, kEqLayout, func(ctx vk.APIContext) interface{} {
return vk.NewDescriptorLayout(ctx, dev, vk.DESCRIPTORTypeCombinedImageSampler, vk.SHADERStageFragmentBit, 1)
}).(*vk.DescriptorLayout)
}
func getEnvSampler(ctx vk.APIContext, dev *vk.Device) *vk.Sampler {
sampler := dev.Get(ctx, kEnvSampler, func(ctx vk.APIContext) interface{} {
return vk.NewSampler(ctx, dev, vk.SAMPLERAddressModeClampToEdge)
}).(*vk.Sampler)
return sampler
}