object.go (2353B)
1 package tofu 2 3 import ( 4 "image/color" 5 6 "github.com/go-gl/gl/v3.3-core/gl" 7 ) 8 9 type Point2D struct { 10 X, Y float32 11 } 12 13 type Point3D struct { 14 X, Y, Z float32 15 } 16 17 type Object struct { 18 Vertices []Point3D 19 Colors []color.Color 20 TexCoords []Point2D 21 Faces [][3]uint32 22 vao *VAO 23 } 24 25 func (obj Object) data() []float32 { 26 data := make([]float32, 8 * len(obj.Vertices)) 27 for i := 0; i < len(obj.Vertices); i++ { 28 data[8 * i] = obj.Vertices[i].X 29 data[8 * i + 1] = obj.Vertices[i].Y 30 data[8 * i + 2] = obj.Vertices[i].Z 31 r, g, b, _ := obj.Colors[i].RGBA() 32 data[8 * i + 3] = float32(r)/0xffff 33 data[8 * i + 4] = float32(g)/0xffff 34 data[8 * i + 5] = float32(b)/0xffff 35 data[8 * i + 6] = obj.TexCoords[i].X 36 data[8 * i + 7] = obj.TexCoords[i].Y 37 } 38 return data 39 } 40 41 func (obj Object) faceData() []uint32 { 42 fdata := make([]uint32, 3 * len(obj.Faces)) 43 for i, v := range obj.Faces { 44 fdata[3 * i] = v[0] 45 fdata[3 * i + 1] = v[1] 46 fdata[3 * i + 2] = v[2] 47 } 48 return fdata 49 } 50 51 // Load copies object data into the GPU. 52 func (obj *Object) Load() { 53 obj.vao = newVAO(obj) 54 } 55 56 type VAO struct { 57 id uint32 58 vbo *Buffer 59 ebo *Buffer 60 } 61 62 const ( 63 UniformVertex = iota 64 UniformColor 65 UniformTexCoords 66 ) 67 68 func newVAO(obj *Object) *VAO { 69 var id uint32 70 gl.GenVertexArrays(1, &id) 71 vao := &VAO{id: id, vbo: newBuffer(), ebo: newBuffer()} 72 vao.bind() 73 data := obj.data() 74 vao.setData(data) 75 vao.setAttribute(UniformVertex, 3, 8, 0) 76 vao.setAttribute(UniformColor, 3, 8, 3) 77 vao.setAttribute(UniformTexCoords, 2, 8, 6) 78 fdata := obj.faceData() 79 vao.setFaces(fdata) 80 return vao 81 } 82 83 func (vao *VAO) bind() { 84 gl.BindVertexArray(vao.id) 85 } 86 87 func (vao *VAO) setAttribute(uniformNum uint32, size int, stride int, offset int) { 88 gl.VertexAttribPointerWithOffset(uniformNum, int32(size), gl.FLOAT, 89 false, int32(stride) * 4, uintptr(offset) * 4) 90 gl.EnableVertexAttribArray(uniformNum) 91 } 92 93 func (vao *VAO) setData(data []float32) { 94 gl.BindBuffer(gl.ARRAY_BUFFER, vao.vbo.id) 95 gl.BufferData(gl.ARRAY_BUFFER, len(data) * 4, 96 gl.Ptr(data), gl.STATIC_DRAW) 97 } 98 99 func (vao *VAO) setFaces(data []uint32) { 100 gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, vao.ebo.id) 101 gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(data) * 4, 102 gl.Ptr(data), gl.STATIC_DRAW) 103 } 104 105 type Buffer struct { 106 id uint32 107 } 108 109 func newBuffer() *Buffer { 110 var id uint32 111 gl.GenBuffers(1, &id) 112 return &Buffer{id: id} 113 }