gls.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  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 allows access to the OpenGL functions.
  5. package gls
  6. import (
  7. "github.com/g3n/engine/util/logger"
  8. "github.com/go-gl/gl/v3.3-core/gl"
  9. "math"
  10. )
  11. // GLS allows access to the OpenGL functions and keeps state to
  12. // minimize functions calling.
  13. // It also keeps some statistics of some OpenGL objects currently allocated
  14. type GLS struct {
  15. // Statistics
  16. Stats struct {
  17. Vaos int // Number of Vertex Array Objects
  18. Vbos int // Number of Vertex Buffer Objects
  19. Textures int // Number of Textures
  20. }
  21. Prog *Program // Current active program
  22. programs map[*Program]bool // Programs cache
  23. checkErrors bool // Check openGL API errors flag
  24. viewportX int32
  25. viewportY int32
  26. viewportWidth int32
  27. viewportHeight int32
  28. lineWidth float32
  29. sideView int
  30. depthFunc uint32
  31. depthMask int
  32. capabilities map[int]int
  33. blendEquation uint32
  34. blendSrc uint32
  35. blendDst uint32
  36. blendEquationRGB uint32
  37. blendEquationAlpha uint32
  38. blendSrcRGB uint32
  39. blendSrcAlpha uint32
  40. blendDstRGB uint32
  41. blendDstAlpha uint32
  42. polygonOffsetFactor float32
  43. polygonOffsetUnits float32
  44. }
  45. const (
  46. capUndef = 0
  47. capDisabled = 1
  48. capEnabled = 2
  49. )
  50. const (
  51. uintUndef = math.MaxUint32
  52. intFalse = 0
  53. intTrue = 1
  54. )
  55. // Polygon side view.
  56. const (
  57. FrontSide = iota + 1
  58. BackSide
  59. DoubleSide
  60. )
  61. // Package logger
  62. var log = logger.New("GLS", logger.Default)
  63. // New creates and returns a new instance of an GLS object
  64. // which encapsulates the state of an OpenGL context
  65. // This should be called only after an active OpenGL context
  66. // was established, such as by creating a new window.
  67. func New() (*GLS, error) {
  68. gs := new(GLS)
  69. gs.Reset()
  70. // Initialize GL
  71. err := gl.Init()
  72. if err != nil {
  73. return nil, err
  74. }
  75. gs.SetDefaultState()
  76. gs.checkErrors = true
  77. return gs, nil
  78. }
  79. // SetCheckErrors enables/disables checking for errors after the
  80. // call of any OpenGL function. It is enabled by default but
  81. // could be disabled after an application is stable to improve the performance.
  82. func (gs *GLS) SetCheckErrors(enable bool) {
  83. gs.checkErrors = enable
  84. }
  85. // ChecksErrors returns if error checking is enabled or not.
  86. func (gs *GLS) CheckErrors() bool {
  87. return gs.checkErrors
  88. }
  89. // Reset resets the internal state kept of the OpenGL
  90. func (gs *GLS) Reset() {
  91. gs.lineWidth = 0.0
  92. gs.sideView = uintUndef
  93. gs.depthFunc = 0
  94. gs.depthMask = uintUndef
  95. gs.capabilities = make(map[int]int)
  96. gs.programs = make(map[*Program]bool)
  97. gs.Prog = nil
  98. gs.blendEquation = uintUndef
  99. gs.blendSrc = uintUndef
  100. gs.blendDst = uintUndef
  101. gs.blendEquationRGB = 0
  102. gs.blendEquationAlpha = 0
  103. gs.blendSrcRGB = uintUndef
  104. gs.blendSrcAlpha = uintUndef
  105. gs.blendDstRGB = uintUndef
  106. gs.blendDstAlpha = uintUndef
  107. gs.polygonOffsetFactor = -1
  108. gs.polygonOffsetUnits = -1
  109. }
  110. func (gs *GLS) SetDefaultState() {
  111. gl.ClearColor(0, 0, 0, 1)
  112. gl.ClearDepth(1)
  113. gl.ClearStencil(0)
  114. gs.Enable(gl.DEPTH_TEST)
  115. gs.DepthFunc(gl.LEQUAL)
  116. gl.FrontFace(gl.CCW)
  117. gl.CullFace(gl.BACK)
  118. gs.Enable(gl.CULL_FACE)
  119. gs.Enable(gl.BLEND)
  120. gs.BlendEquation(gl.FUNC_ADD)
  121. gs.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
  122. gs.Enable(gl.VERTEX_PROGRAM_POINT_SIZE)
  123. gs.Enable(gl.PROGRAM_POINT_SIZE)
  124. gs.Enable(gl.MULTISAMPLE)
  125. gs.Enable(gl.POLYGON_OFFSET_FILL)
  126. gs.Enable(gl.POLYGON_OFFSET_LINE)
  127. gs.Enable(gl.POLYGON_OFFSET_POINT)
  128. }
  129. func (gs *GLS) ActiveTexture(texture uint32) {
  130. gl.ActiveTexture(texture)
  131. gs.checkError("ActiveTexture")
  132. }
  133. func (gs *GLS) BindBuffer(target int, vbo uint32) {
  134. gl.BindBuffer(uint32(target), vbo)
  135. gs.checkError("BindBuffer")
  136. }
  137. func (gs *GLS) BindTexture(target int, tex uint32) {
  138. gl.BindTexture(uint32(target), tex)
  139. gs.checkError("BindTexture")
  140. }
  141. func (gs *GLS) BindVertexArray(vao uint32) {
  142. gl.BindVertexArray(vao)
  143. gs.checkError("BindVertexArray")
  144. }
  145. func (gs *GLS) BlendEquation(mode uint32) {
  146. if gs.blendEquation == mode {
  147. return
  148. }
  149. gl.BlendEquation(mode)
  150. gs.checkError("BlendEquation")
  151. gs.blendEquation = mode
  152. }
  153. func (gs *GLS) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
  154. if gs.blendEquationRGB == modeRGB && gs.blendEquationAlpha == modeAlpha {
  155. return
  156. }
  157. gl.BlendEquationSeparate(uint32(modeRGB), uint32(modeAlpha))
  158. gs.checkError("BlendEquationSeparate")
  159. gs.blendEquationRGB = modeRGB
  160. gs.blendEquationAlpha = modeAlpha
  161. }
  162. func (gs *GLS) BlendFunc(sfactor, dfactor uint32) {
  163. if gs.blendSrc == sfactor && gs.blendDst == dfactor {
  164. return
  165. }
  166. gl.BlendFunc(sfactor, dfactor)
  167. gs.checkError("BlendFunc")
  168. gs.blendSrc = sfactor
  169. gs.blendDst = dfactor
  170. }
  171. func (gs *GLS) BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
  172. if gs.blendSrcRGB == srcRGB && gs.blendDstRGB == dstRGB &&
  173. gs.blendSrcAlpha == srcAlpha && gs.blendDstAlpha == dstAlpha {
  174. return
  175. }
  176. gl.BlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha)
  177. gs.checkError("BlendFuncSeparate")
  178. gs.blendSrcRGB = srcRGB
  179. gs.blendDstRGB = dstRGB
  180. gs.blendSrcAlpha = srcAlpha
  181. gs.blendDstAlpha = dstAlpha
  182. }
  183. func (gs *GLS) BufferData(target uint32, size int, data interface{}, usage uint32) {
  184. gl.BufferData(target, size, gl.Ptr(data), usage)
  185. gs.checkError("BufferData")
  186. }
  187. func (gs *GLS) ClearColor(r, g, b, a float32) {
  188. gl.ClearColor(r, g, b, a)
  189. }
  190. func (gs *GLS) Clear(mask int) {
  191. gl.Clear(uint32(mask))
  192. }
  193. func (gs *GLS) DeleteBuffers(vbos ...uint32) {
  194. gl.DeleteBuffers(int32(len(vbos)), &vbos[0])
  195. gs.checkError("DeleteBuffers")
  196. }
  197. func (gs *GLS) DeleteTextures(tex ...uint32) {
  198. gl.DeleteTextures(int32(len(tex)), &tex[0])
  199. gs.checkError("DeleteTextures")
  200. gs.Stats.Textures -= len(tex)
  201. }
  202. func (gs *GLS) DeleteVertexArrays(vaos ...uint32) {
  203. gl.DeleteVertexArrays(int32(len(vaos)), &vaos[0])
  204. gs.checkError("DeleteVertexArrays")
  205. }
  206. func (gs *GLS) DepthFunc(mode uint32) {
  207. if gs.depthFunc == mode {
  208. return
  209. }
  210. gl.DepthFunc(mode)
  211. gs.checkError("DepthFunc")
  212. gs.depthFunc = mode
  213. }
  214. func (gs *GLS) DepthMask(flag bool) {
  215. if gs.depthMask == intTrue && flag {
  216. return
  217. }
  218. if gs.depthMask == intFalse && !flag {
  219. return
  220. }
  221. gl.DepthMask(flag)
  222. gs.checkError("DepthMask")
  223. if flag {
  224. gs.depthMask = intTrue
  225. } else {
  226. gs.depthMask = intFalse
  227. }
  228. }
  229. func (gs *GLS) DrawArrays(mode uint32, first int32, count int32) {
  230. gl.DrawArrays(mode, first, count)
  231. gs.checkError("DrawArrays")
  232. }
  233. func (gs *GLS) DrawElements(mode uint32, count int32, itype uint32, start uint32) {
  234. gl.DrawElements(mode, int32(count), itype, gl.PtrOffset(int(start)))
  235. gs.checkError("DrawElements")
  236. }
  237. func (gs *GLS) Enable(cap int) {
  238. if gs.capabilities[cap] == capEnabled {
  239. return
  240. }
  241. gl.Enable(uint32(cap))
  242. gs.checkError("Enable")
  243. gs.capabilities[cap] = capEnabled
  244. }
  245. func (gs *GLS) EnableVertexAttribArray(index uint32) {
  246. gl.EnableVertexAttribArray(index)
  247. gs.checkError("EnableVertexAttribArray")
  248. }
  249. func (gs *GLS) Disable(cap int) {
  250. if gs.capabilities[cap] == capDisabled {
  251. return
  252. }
  253. gl.Disable(uint32(cap))
  254. gs.checkError("Disable")
  255. gs.capabilities[cap] = capDisabled
  256. }
  257. func (gs *GLS) FrontFace(mode uint32) {
  258. gl.FrontFace(mode)
  259. gs.checkError("FrontFace")
  260. }
  261. func (gs *GLS) GenBuffer() uint32 {
  262. var buf uint32
  263. gl.GenBuffers(1, &buf)
  264. gs.checkError("GenBuffers")
  265. gs.Stats.Vbos++
  266. return buf
  267. }
  268. func (gs *GLS) GenerateMipmap(target uint32) {
  269. gl.GenerateMipmap(target)
  270. gs.checkError("GenerateMipmap")
  271. }
  272. func (gs *GLS) GenTexture() uint32 {
  273. var tex uint32
  274. gl.GenTextures(1, &tex)
  275. gs.checkError("GenTextures")
  276. gs.Stats.Textures++
  277. return tex
  278. }
  279. func (gs *GLS) GenVertexArray() uint32 {
  280. var vao uint32
  281. gl.GenVertexArrays(1, &vao)
  282. gs.checkError("GenVertexArrays")
  283. gs.Stats.Vaos++
  284. return vao
  285. }
  286. func (gs *GLS) GetString(name uint32) string {
  287. cstr := gl.GetString(name)
  288. return gl.GoStr(cstr)
  289. }
  290. func (gs *GLS) GetViewport() (x, y, width, height int32) {
  291. return gs.viewportX, gs.viewportY, gs.viewportWidth, gs.viewportHeight
  292. }
  293. func (gs *GLS) LineWidth(width float32) {
  294. if gs.lineWidth == width {
  295. return
  296. }
  297. gl.LineWidth(width)
  298. gs.checkError("LineWidth")
  299. gs.lineWidth = width
  300. }
  301. func (gs *GLS) SetDepthTest(mode bool) {
  302. if mode {
  303. gs.Enable(gl.DEPTH_TEST)
  304. } else {
  305. gs.Disable(gl.DEPTH_TEST)
  306. }
  307. }
  308. func (gs *GLS) SetSideView(mode int) {
  309. if gs.sideView == mode {
  310. return
  311. }
  312. switch mode {
  313. // Default: show only the front size
  314. case FrontSide:
  315. gs.Enable(gl.CULL_FACE)
  316. gl.FrontFace(gl.CCW)
  317. // Show only the back side
  318. case BackSide:
  319. gs.Enable(gl.CULL_FACE)
  320. gl.FrontFace(gl.CW)
  321. // Show both sides
  322. case DoubleSide:
  323. gs.Disable(gl.CULL_FACE)
  324. default:
  325. panic("SetSideView() invalid mode")
  326. }
  327. gs.sideView = mode
  328. }
  329. func (gs *GLS) TexImage2D(target uint32, level int32, iformat int32, width int32, height int32, border int32, format uint32, itype uint32, data interface{}) {
  330. gl.TexImage2D(uint32(target), int32(level), int32(iformat), int32(width), int32(height), int32(border), uint32(format), uint32(itype), gl.Ptr(data))
  331. gs.checkError("TexImage2D")
  332. }
  333. func (gs *GLS) TexStorage2D(target int, levels int, iformat int, width, height int) {
  334. gl.TexStorage2D(uint32(target), int32(levels), uint32(iformat), int32(width), int32(height))
  335. gs.checkError("TexStorage2D")
  336. }
  337. func (gs *GLS) TexParameteri(target uint32, pname uint32, param int32) {
  338. gl.TexParameteri(target, pname, param)
  339. gs.checkError("TexParameteri")
  340. }
  341. func (gs *GLS) PolygonMode(face, mode int) {
  342. gl.PolygonMode(uint32(face), uint32(mode))
  343. gs.checkError("PolygonMode")
  344. }
  345. func (gs *GLS) PolygonOffset(factor float32, units float32) {
  346. if gs.polygonOffsetFactor == factor && gs.polygonOffsetUnits == units {
  347. return
  348. }
  349. gl.PolygonOffset(factor, units)
  350. gs.checkError("PolygonOffset")
  351. gs.polygonOffsetFactor = factor
  352. gs.polygonOffsetUnits = units
  353. }
  354. func (gs *GLS) Uniform1i(location int32, v0 int32) {
  355. gl.Uniform1i(location, v0)
  356. gs.checkError("Uniform1i")
  357. }
  358. func (gs *GLS) Uniform1f(location int32, v0 float32) {
  359. gl.Uniform1f(location, v0)
  360. gs.checkError("Uniform1f")
  361. }
  362. func (gs *GLS) Uniform2f(location int32, v0, v1 float32) {
  363. gl.Uniform2f(location, v0, v1)
  364. gs.checkError("Uniform2f")
  365. }
  366. func (gs *GLS) Uniform3f(location int32, v0, v1, v2 float32) {
  367. gl.Uniform3f(location, v0, v1, v2)
  368. gs.checkError("Uniform3f")
  369. }
  370. func (gs *GLS) Uniform4f(location int32, v0, v1, v2, v3 float32) {
  371. gl.Uniform4f(location, v0, v1, v2, v3)
  372. gs.checkError("Uniform4f")
  373. }
  374. func (gs *GLS) UniformMatrix3fv(location int32, count int32, transpose bool, v []float32) {
  375. gl.UniformMatrix3fv(location, count, transpose, &v[0])
  376. gs.checkError("UniformMatrix3fv")
  377. }
  378. func (gs *GLS) UniformMatrix4fv(location int32, count int32, transpose bool, v []float32) {
  379. gl.UniformMatrix4fv(location, count, transpose, &v[0])
  380. gs.checkError("UniformMatrix4fv")
  381. }
  382. // Use set this program as the current program.
  383. func (gs *GLS) UseProgram(prog *Program) {
  384. if prog.handle == 0 {
  385. panic("Invalid program")
  386. }
  387. gl.UseProgram(prog.handle)
  388. gs.checkError("UseProgram")
  389. gs.Prog = prog
  390. // Inserts program in cache if not already there.
  391. if !gs.programs[prog] {
  392. gs.programs[prog] = true
  393. log.Debug("New Program activated. Total: %d", len(gs.programs))
  394. }
  395. }
  396. func (gs *GLS) VertexAttribPointer(index uint32, size int32, xtype uint32, normalized bool, stride int32, offset uint32) {
  397. gl.VertexAttribPointer(index, size, xtype, normalized, stride, gl.PtrOffset(int(offset)))
  398. gs.checkError("VertexAttribPointer")
  399. }
  400. func (gs *GLS) Viewport(x, y, width, height int32) {
  401. gl.Viewport(x, y, width, height)
  402. gs.checkError("Viewport")
  403. gs.viewportX = x
  404. gs.viewportY = y
  405. gs.viewportWidth = width
  406. gs.viewportHeight = height
  407. }
  408. // checkError checks the error code of the previously called OpenGL function
  409. func (gls *GLS) checkError(fname string) {
  410. if gls.checkErrors {
  411. ecode := gl.GetError()
  412. if ecode != 0 {
  413. log.Fatal("Error:%d calling:%s()", ecode, fname)
  414. }
  415. }
  416. }