gl01/internal/render/render_framewire.go

128 lines
4.1 KiB
Go

package render
import (
"image/color"
"unsafe"
"edgaru089.ink/go/gl01/internal/asset"
"edgaru089.ink/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),
},
)
}
const FramewireSizeShrink = 1e-4
// 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]
}