vbo.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package gls
  5. import (
  6. "github.com/g3n/engine/math32"
  7. "unsafe"
  8. )
  9. // VBO abstracts an OpenGL Vertex Buffer Object
  10. type VBO struct {
  11. gs *GLS // reference to GLS state
  12. handle uint32 // OpenGL handle for this VBO
  13. usage uint32 // Expected usage patter of the buffer
  14. update bool // Update flag
  15. buffer math32.ArrayF32 // Data buffer
  16. attribs []VBOattrib // List of attributes
  17. }
  18. // VBOattrib describes one attribute of an OpenGL Vertex Buffer Object
  19. type VBOattrib struct {
  20. Name string // Name of of the attribute
  21. ItemSize int32 // Number of elements for each item
  22. }
  23. // NewVBO creates and returns a pointer to a new OpenGL Vertex Buffer Object
  24. func NewVBO() *VBO {
  25. vbo := new(VBO)
  26. vbo.init()
  27. return vbo
  28. }
  29. // init initializes this VBO
  30. func (vbo *VBO) init() {
  31. vbo.gs = nil
  32. vbo.handle = 0
  33. vbo.usage = STATIC_DRAW
  34. vbo.update = true
  35. vbo.attribs = make([]VBOattrib, 0)
  36. }
  37. // AddAttrib adds a new attribute to this VBO
  38. func (vbo *VBO) AddAttrib(name string, itemSize int32) *VBO {
  39. vbo.attribs = append(vbo.attribs, VBOattrib{
  40. Name: name,
  41. ItemSize: itemSize,
  42. })
  43. return vbo
  44. }
  45. // Attrib finds and returns pointer the attribute with the specified name
  46. // or nil if not found
  47. func (vbo *VBO) Attrib(name string) *VBOattrib {
  48. for _, attr := range vbo.attribs {
  49. if attr.Name == name {
  50. return &attr
  51. }
  52. }
  53. return nil
  54. }
  55. // AttribAt returns pointer to the VBO attribute at the specified index
  56. func (vbo *VBO) AttribAt(idx int) *VBOattrib {
  57. return &vbo.attribs[idx]
  58. }
  59. // AttribCount returns the current number of attributes for this VBO
  60. func (vbo *VBO) AttribCount() int {
  61. return len(vbo.attribs)
  62. }
  63. // Dispose disposes of this VBO OpenGL resources
  64. // As currently the VBO is used only by the Geometry object
  65. // it is not referenced counted.
  66. func (vbo *VBO) Dispose() {
  67. if vbo.gs != nil {
  68. vbo.gs.DeleteBuffers(vbo.handle)
  69. }
  70. vbo.gs = nil
  71. }
  72. // SetBuffer sets the VBO buffer
  73. func (vbo *VBO) SetBuffer(buffer math32.ArrayF32) *VBO {
  74. vbo.buffer = buffer
  75. vbo.update = true
  76. return vbo
  77. }
  78. // SetUsage sets the expected usage pattern of the buffer.
  79. // The default value is GL_STATIC_DRAW.
  80. func (vbo *VBO) SetUsage(usage uint32) {
  81. vbo.usage = usage
  82. }
  83. // Buffer returns pointer to the VBO buffer
  84. func (vbo *VBO) Buffer() *math32.ArrayF32 {
  85. return &vbo.buffer
  86. }
  87. // Update sets the update flag to force the VBO update
  88. func (vbo *VBO) Update() {
  89. vbo.update = true
  90. }
  91. // Stride returns the stride of this VBO which is the number of bytes
  92. // used by one group attributes side by side in the buffer
  93. // Ex: x y z r g b x y z r g b ...x y z r g b
  94. // The stride will be: sizeof(float) * 6 = 24
  95. func (vbo *VBO) Stride() int {
  96. stride := 0
  97. elsize := int(unsafe.Sizeof(float32(0)))
  98. for _, attrib := range vbo.attribs {
  99. stride += elsize * int(attrib.ItemSize)
  100. }
  101. return stride
  102. }
  103. // Transfer is called internally and transfer the data in the VBO buffer to OpenGL if necessary
  104. func (vbo *VBO) Transfer(gs *GLS) {
  105. // If the VBO buffer is empty, ignore
  106. if vbo.buffer.Bytes() == 0 {
  107. return
  108. }
  109. // First time initialization
  110. if vbo.gs == nil {
  111. vbo.handle = gs.GenBuffer()
  112. gs.BindBuffer(ARRAY_BUFFER, vbo.handle)
  113. // Calculates stride
  114. stride := vbo.Stride()
  115. // For each attribute
  116. var items uint32
  117. var offset uint32
  118. elsize := int32(unsafe.Sizeof(float32(0)))
  119. for _, attrib := range vbo.attribs {
  120. // Get attribute location in the current program
  121. loc := gs.prog.GetAttribLocation(attrib.Name)
  122. if loc < 0 {
  123. continue
  124. }
  125. // Enables attribute and sets its stride and offset in the buffer
  126. gs.EnableVertexAttribArray(uint32(loc))
  127. gs.VertexAttribPointer(uint32(loc), attrib.ItemSize, FLOAT, false, int32(stride), offset)
  128. items += uint32(attrib.ItemSize)
  129. offset = uint32(elsize) * items
  130. }
  131. vbo.gs = gs // this indicates that the vbo was initialized
  132. }
  133. if !vbo.update {
  134. return
  135. }
  136. // Transfer the VBO data to OpenGL
  137. gs.BindBuffer(ARRAY_BUFFER, vbo.handle)
  138. gs.BufferData(ARRAY_BUFFER, vbo.buffer.Bytes(), &vbo.buffer[0], vbo.usage)
  139. vbo.update = false
  140. }