2022-01-20 21:58:50 +08:00
|
|
|
package render
|
|
|
|
|
|
|
|
import (
|
|
|
|
"image/color"
|
|
|
|
"unsafe"
|
|
|
|
|
|
|
|
"edgaru089.ml/go/gl01/internal/asset"
|
|
|
|
"edgaru089.ml/go/gl01/internal/util/itype"
|
|
|
|
"github.com/go-gl/gl/all-core/gl"
|
|
|
|
"github.com/go-gl/mathgl/mgl32"
|
|
|
|
)
|
|
|
|
|
|
|
|
// framewire vertex
|
|
|
|
type frvertex struct {
|
|
|
|
pos itype.Vec3f
|
|
|
|
color itype.Vec4f
|
|
|
|
}
|
|
|
|
|
|
|
|
// FramewireRenderer is a renderer drawing framewires.
|
|
|
|
//
|
|
|
|
// It is mainly for debugging uses.
|
|
|
|
type FramewireRenderer struct {
|
|
|
|
shader *Shader
|
|
|
|
|
|
|
|
vao, vbo uint32
|
|
|
|
vertex []frvertex
|
|
|
|
}
|
|
|
|
|
|
|
|
// Framewire is a global FramewireRenderer managed by game logic, for debugging.
|
|
|
|
var Framewire = &FramewireRenderer{}
|
|
|
|
|
|
|
|
func (f *FramewireRenderer) Init() (err error) {
|
|
|
|
|
|
|
|
f.shader, err = NewShader(asset.FramewireShaderVert, asset.FramewireShaderFrag)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
f.shader.SetUniformMat4("model", mgl32.Ident4())
|
|
|
|
gl.BindFragDataLocation(f.shader.Handle(), 0, gl.Str("outputColor\x00"))
|
|
|
|
|
|
|
|
gl.GenVertexArrays(1, &f.vao)
|
|
|
|
gl.BindVertexArray(f.vao)
|
|
|
|
gl.GenBuffers(1, &f.vbo)
|
|
|
|
gl.BindBuffer(gl.ARRAY_BUFFER, f.vbo)
|
|
|
|
|
|
|
|
vertAttrib := uint32(gl.GetAttribLocation(f.shader.Handle(), gl.Str("vert\x00")))
|
|
|
|
gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, int32(unsafe.Sizeof(frvertex{})), gl.PtrOffset(int(unsafe.Offsetof(frvertex{}.pos))))
|
|
|
|
|
|
|
|
colorAttrib := uint32(gl.GetAttribLocation(f.shader.Handle(), gl.Str("vertColor\x00")))
|
|
|
|
gl.VertexAttribPointer(colorAttrib, 4, gl.FLOAT, false, int32(unsafe.Sizeof(frvertex{})), gl.PtrOffset(int(unsafe.Offsetof(frvertex{}.color))))
|
|
|
|
|
|
|
|
gl.EnableVertexAttribArray(vertAttrib)
|
|
|
|
gl.EnableVertexAttribArray(colorAttrib)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func colorToVec4f(color color.Color) itype.Vec4f {
|
|
|
|
r, g, b, a := color.RGBA()
|
|
|
|
return itype.Vec4f{float32(r) / 0xffff, float32(g) / 0xffff, float32(b) / 0xffff, float32(a) / 0xffff}
|
|
|
|
}
|
|
|
|
|
|
|
|
// PushLine pushes a line from p0 to p1 into the vertex array.
|
|
|
|
func (f *FramewireRenderer) PushLine(p0, p1 itype.Vec3f, color0, color1 color.Color) {
|
|
|
|
f.vertex = append(f.vertex,
|
|
|
|
frvertex{
|
|
|
|
pos: p0,
|
|
|
|
color: colorToVec4f(color0),
|
|
|
|
},
|
|
|
|
frvertex{
|
|
|
|
pos: p1,
|
|
|
|
color: colorToVec4f(color1),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-02-24 20:20:33 +08:00
|
|
|
const FramewireSizeShrink = 1e-4
|
2022-01-20 21:58:50 +08:00
|
|
|
|
|
|
|
// PushBox pushes a 3D box into the vertex array.
|
|
|
|
//
|
|
|
|
// The size of the box is shrunk by a little bit so that it is not obstructed by the world.
|
|
|
|
func (f *FramewireRenderer) PushBox(box itype.Boxf, color color.Color) {
|
|
|
|
box = itype.Boxf{
|
|
|
|
OffX: box.OffX + FramewireSizeShrink,
|
|
|
|
OffY: box.OffY + 5*FramewireSizeShrink,
|
|
|
|
OffZ: box.OffZ + FramewireSizeShrink,
|
|
|
|
SizeX: box.SizeX - 2*FramewireSizeShrink,
|
|
|
|
SizeY: box.SizeY - 10*FramewireSizeShrink,
|
|
|
|
SizeZ: box.SizeZ - 2*FramewireSizeShrink,
|
|
|
|
}
|
|
|
|
base := box.MinPoint()
|
|
|
|
|
|
|
|
f.PushLine(base, base.Addv(box.SizeX, 0, 0), color, color)
|
|
|
|
f.PushLine(base, base.Addv(0, 0, box.SizeZ), color, color)
|
|
|
|
f.PushLine(base.Addv(box.SizeX, 0, box.SizeZ), base.Addv(box.SizeX, 0, 0), color, color)
|
|
|
|
f.PushLine(base.Addv(box.SizeX, 0, box.SizeZ), base.Addv(0, 0, box.SizeZ), color, color)
|
|
|
|
|
|
|
|
f.PushLine(base, base.Addv(0, box.SizeY, 0), color, color)
|
|
|
|
f.PushLine(base.Addv(box.SizeX, 0, 0), base.Addv(box.SizeX, box.SizeY, 0), color, color)
|
|
|
|
f.PushLine(base.Addv(0, 0, box.SizeZ), base.Addv(0, box.SizeY, box.SizeZ), color, color)
|
|
|
|
f.PushLine(base.Addv(box.SizeX, 0, box.SizeZ), base.Addv(box.SizeX, box.SizeY, box.SizeZ), color, color)
|
|
|
|
|
|
|
|
f.PushLine(base.Addv(0, box.SizeY, 0), base.Addv(box.SizeX, box.SizeY, 0), color, color)
|
|
|
|
f.PushLine(base.Addv(0, box.SizeY, 0), base.Addv(0, box.SizeY, box.SizeZ), color, color)
|
|
|
|
f.PushLine(base.Addv(box.SizeX, box.SizeY, box.SizeZ), base.Addv(box.SizeX, box.SizeY, 0), color, color)
|
|
|
|
f.PushLine(base.Addv(box.SizeX, box.SizeY, box.SizeZ), base.Addv(0, box.SizeY, box.SizeZ), color, color)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Render renders the framewire into the current OpenGL context and clears it.
|
|
|
|
func (f *FramewireRenderer) Render(view *View) {
|
|
|
|
if len(f.vertex) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
f.shader.UseProgram()
|
|
|
|
f.shader.SetUniformMat4("view", view.View())
|
|
|
|
f.shader.SetUniformMat4("projection", view.Perspective())
|
|
|
|
|
|
|
|
gl.BindVertexArray(f.vao)
|
|
|
|
gl.BindBuffer(gl.ARRAY_BUFFER, f.vbo)
|
|
|
|
gl.BufferData(gl.ARRAY_BUFFER, len(f.vertex)*int(unsafe.Sizeof(frvertex{})), gl.Ptr(f.vertex), gl.STREAM_DRAW)
|
|
|
|
|
|
|
|
gl.DrawArrays(gl.LINES, 0, int32(len(f.vertex)))
|
|
|
|
|
|
|
|
f.vertex = f.vertex[0:0]
|
|
|
|
}
|