gls-browser.go 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966
  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. //go:build wasm
  5. // +build wasm
  6. package gls
  7. import (
  8. "fmt"
  9. "github.com/g3n/engine/util/wasm"
  10. "syscall/js"
  11. "unsafe"
  12. )
  13. // GLS encapsulates the state of a WebGL context and contains
  14. // methods to call WebGL functions.
  15. type GLS struct {
  16. stats Stats // statistics
  17. prog *Program // current active shader program
  18. programs map[*Program]bool // shader programs cache
  19. checkErrors bool // check openGL API errors flag
  20. // Cache WebGL state to avoid making unnecessary API calls
  21. activeTexture uint32 // cached last set active texture unit
  22. viewportX int32 // cached last set viewport x
  23. viewportY int32 // cached last set viewport y
  24. viewportWidth int32 // cached last set viewport width
  25. viewportHeight int32 // cached last set viewport height
  26. lineWidth float32 // cached last set line width
  27. sideView int // cached last set triangle side view mode
  28. frontFace uint32 // cached last set glFrontFace value
  29. depthFunc uint32 // cached last set depth function
  30. depthMask int // cached last set depth mask
  31. stencilMask uint32 // cached last set stencil mask
  32. capabilities map[int]int // cached capabilities (Enable/Disable)
  33. blendEquation uint32 // cached last set blend equation value
  34. blendSrc uint32 // cached last set blend src value
  35. blendDst uint32 // cached last set blend equation destination value
  36. blendEquationRGB uint32 // cached last set blend equation rgb value
  37. blendEquationAlpha uint32 // cached last set blend equation alpha value
  38. blendSrcRGB uint32 // cached last set blend src rgb
  39. blendSrcAlpha uint32 // cached last set blend src alpha value
  40. blendDstRGB uint32 // cached last set blend destination rgb value
  41. blendDstAlpha uint32 // cached last set blend destination alpha value
  42. polygonModeFace uint32 // cached last set polygon mode face
  43. polygonModeMode uint32 // cached last set polygon mode mode
  44. polygonOffsetFactor float32 // cached last set polygon offset factor
  45. polygonOffsetUnits float32 // cached last set polygon offset units
  46. // js.Value storage maps
  47. programMap map[uint32]js.Value
  48. shaderMap map[uint32]js.Value
  49. bufferMap map[uint32]js.Value
  50. framebufferMap map[uint32]js.Value
  51. renderbufferMap map[uint32]js.Value
  52. textureMap map[uint32]js.Value
  53. uniformMap map[uint32]js.Value
  54. vertexArrayMap map[uint32]js.Value
  55. // Next free index to be used for each map
  56. programMapIndex uint32
  57. shaderMapIndex uint32
  58. bufferMapIndex uint32
  59. framebufferMapIndex uint32
  60. renderbufferMapIndex uint32
  61. textureMapIndex uint32
  62. uniformMapIndex uint32
  63. vertexArrayMapIndex uint32
  64. // Canvas and WebGL Context
  65. canvas js.Value
  66. gl js.Value
  67. }
  68. // New creates and returns a new instance of a GLS object,
  69. // which encapsulates the state of an WebGL context.
  70. // This should be called only after an active WebGL context
  71. // is established, such as by creating a new window.
  72. func New(webglCtx js.Value) (*GLS, error) {
  73. gs := new(GLS)
  74. gs.reset()
  75. gs.checkErrors = false
  76. gs.gl = webglCtx
  77. // Create js.Value storage maps
  78. gs.programMap = make(map[uint32]js.Value)
  79. gs.shaderMap = make(map[uint32]js.Value)
  80. gs.bufferMap = make(map[uint32]js.Value)
  81. gs.framebufferMap = make(map[uint32]js.Value)
  82. gs.renderbufferMap = make(map[uint32]js.Value)
  83. gs.textureMap = make(map[uint32]js.Value)
  84. gs.uniformMap = make(map[uint32]js.Value)
  85. gs.vertexArrayMap = make(map[uint32]js.Value)
  86. // Initialize indexes to be used with the maps above
  87. gs.programMapIndex = 1
  88. gs.shaderMapIndex = 1
  89. gs.bufferMapIndex = 1
  90. gs.framebufferMapIndex = 1
  91. gs.renderbufferMapIndex = 1
  92. gs.textureMapIndex = 1
  93. gs.uniformMapIndex = 1
  94. gs.vertexArrayMapIndex = 1
  95. gs.setDefaultState()
  96. return gs, nil
  97. }
  98. // SetCheckErrors enables/disables checking for errors after the
  99. // call of any WebGL function. It is enabled by default but
  100. // could be disabled after an application is stable to improve the performance.
  101. func (gs *GLS) SetCheckErrors(enable bool) {
  102. gs.checkErrors = enable
  103. }
  104. // CheckErrors returns if error checking is enabled or not.
  105. func (gs *GLS) CheckErrors() bool {
  106. return gs.checkErrors
  107. }
  108. // reset resets the internal state kept of the WebGL
  109. func (gs *GLS) reset() {
  110. gs.lineWidth = 0.0
  111. gs.sideView = uintUndef
  112. gs.frontFace = 0
  113. gs.depthFunc = 0
  114. gs.depthMask = uintUndef
  115. gs.capabilities = make(map[int]int)
  116. gs.programs = make(map[*Program]bool)
  117. gs.prog = nil
  118. gs.activeTexture = uintUndef
  119. gs.blendEquation = uintUndef
  120. gs.blendSrc = uintUndef
  121. gs.blendDst = uintUndef
  122. gs.blendEquationRGB = 0
  123. gs.blendEquationAlpha = 0
  124. gs.blendSrcRGB = uintUndef
  125. gs.blendSrcAlpha = uintUndef
  126. gs.blendDstRGB = uintUndef
  127. gs.blendDstAlpha = uintUndef
  128. gs.polygonModeFace = 0
  129. gs.polygonModeMode = 0
  130. gs.polygonOffsetFactor = -1
  131. gs.polygonOffsetUnits = -1
  132. }
  133. // setDefaultState is used internally to set the initial state of WebGL
  134. // for this context.
  135. func (gs *GLS) setDefaultState() {
  136. gs.ClearColor(0, 0, 0, 1)
  137. gs.ClearDepth(1)
  138. gs.ClearStencil(0)
  139. gs.Enable(DEPTH_TEST)
  140. gs.DepthFunc(LEQUAL)
  141. gs.FrontFace(CCW)
  142. gs.CullFace(BACK)
  143. gs.Enable(CULL_FACE)
  144. gs.Enable(BLEND)
  145. gs.BlendEquation(FUNC_ADD)
  146. gs.BlendFunc(SRC_ALPHA, ONE_MINUS_SRC_ALPHA)
  147. // TODO commented constants not available in WebGL
  148. //gs.Enable(VERTEX_PROGRAM_POINT_SIZE)
  149. //gs.Enable(PROGRAM_POINT_SIZE)
  150. //gs.Enable(MULTISAMPLE)
  151. gs.Enable(POLYGON_OFFSET_FILL)
  152. //gs.Enable(POLYGON_OFFSET_LINE)
  153. //gs.Enable(POLYGON_OFFSET_POINT)
  154. }
  155. // Stats copy the current values of the internal statistics structure
  156. // to the specified pointer.
  157. func (gs *GLS) Stats(s *Stats) {
  158. *s = gs.stats
  159. s.Shaders = len(gs.programs)
  160. }
  161. // ActiveTexture selects which texture unit subsequent texture state calls
  162. // will affect. The number of texture units an implementation supports is
  163. // implementation dependent, but must be at least 48 in GL 3.3.
  164. func (gs *GLS) ActiveTexture(texture uint32) {
  165. if gs.activeTexture == texture {
  166. return
  167. }
  168. gs.gl.Call("activeTexture", int(texture))
  169. gs.checkError("ActiveTexture")
  170. gs.activeTexture = texture
  171. }
  172. // AttachShader attaches the specified shader object to the specified program object.
  173. func (gs *GLS) AttachShader(program, shader uint32) {
  174. gs.gl.Call("attachShader", gs.programMap[program], gs.shaderMap[shader])
  175. gs.checkError("AttachShader")
  176. }
  177. // BindBuffer binds a buffer object to the specified buffer binding point.
  178. func (gs *GLS) BindBuffer(target int, vbo uint32) {
  179. gs.gl.Call("bindBuffer", target, gs.bufferMap[vbo])
  180. gs.checkError("BindBuffer")
  181. }
  182. // BindTexture lets you create or use a named texture.
  183. func (gs *GLS) BindTexture(target int, tex uint32) {
  184. gs.gl.Call("bindTexture", target, gs.textureMap[tex])
  185. gs.checkError("BindTexture")
  186. }
  187. // BindVertexArray binds the vertex array object.
  188. func (gs *GLS) BindVertexArray(vao uint32) {
  189. gs.gl.Call("bindVertexArray", gs.vertexArrayMap[vao])
  190. gs.checkError("BindVertexArray")
  191. }
  192. // BlendEquation sets the blend equations for all draw buffers.
  193. func (gs *GLS) BlendEquation(mode uint32) {
  194. if gs.blendEquation == mode {
  195. return
  196. }
  197. gs.gl.Call("blendEquation", int(mode))
  198. gs.checkError("BlendEquation")
  199. gs.blendEquation = mode
  200. }
  201. // BlendEquationSeparate sets the blend equations for all draw buffers
  202. // allowing different equations for the RGB and alpha components.
  203. func (gs *GLS) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
  204. if gs.blendEquationRGB == modeRGB && gs.blendEquationAlpha == modeAlpha {
  205. return
  206. }
  207. gs.gl.Call("blendEquationSeparate", int(modeRGB), int(modeAlpha))
  208. gs.checkError("BlendEquationSeparate")
  209. gs.blendEquationRGB = modeRGB
  210. gs.blendEquationAlpha = modeAlpha
  211. }
  212. // BlendFunc defines the operation of blending for
  213. // all draw buffers when blending is enabled.
  214. func (gs *GLS) BlendFunc(sfactor, dfactor uint32) {
  215. if gs.blendSrc == sfactor && gs.blendDst == dfactor {
  216. return
  217. }
  218. gs.gl.Call("blendFunc", int(sfactor), int(dfactor))
  219. gs.checkError("BlendFunc")
  220. gs.blendSrc = sfactor
  221. gs.blendDst = dfactor
  222. }
  223. // BlendFuncSeparate defines the operation of blending for all draw buffers when blending
  224. // is enabled, allowing different operations for the RGB and alpha components.
  225. func (gs *GLS) BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
  226. if gs.blendSrcRGB == srcRGB && gs.blendDstRGB == dstRGB &&
  227. gs.blendSrcAlpha == srcAlpha && gs.blendDstAlpha == dstAlpha {
  228. return
  229. }
  230. gs.gl.Call("blendFuncSeparate", int(srcRGB), int(dstRGB), int(srcAlpha), int(dstAlpha))
  231. gs.checkError("BlendFuncSeparate")
  232. gs.blendSrcRGB = srcRGB
  233. gs.blendDstRGB = dstRGB
  234. gs.blendSrcAlpha = srcAlpha
  235. gs.blendDstAlpha = dstAlpha
  236. }
  237. // BufferData creates a new data store for the buffer object currently
  238. // bound to target, deleting any pre-existing data store.
  239. func (gs *GLS) BufferData(target uint32, size int, data interface{}, usage uint32) {
  240. dataTA, free := wasm.SliceToTypedArray(data)
  241. gs.gl.Call("bufferData", int(target), dataTA, int(usage))
  242. gs.checkError("BufferData")
  243. free()
  244. }
  245. // ClearColor specifies the red, green, blue, and alpha values
  246. // used by glClear to clear the color buffers.
  247. func (gs *GLS) ClearColor(r, g, b, a float32) {
  248. gs.gl.Call("clearColor", r, g, b, a)
  249. gs.checkError("ClearColor")
  250. }
  251. // ClearDepth specifies the depth value used by Clear to clear the depth buffer.
  252. func (gs *GLS) ClearDepth(v float32) {
  253. gs.gl.Call("clearDepth", v)
  254. gs.checkError("ClearDepth")
  255. }
  256. // ClearStencil specifies the index used by Clear to clear the stencil buffer.
  257. func (gs *GLS) ClearStencil(v int32) {
  258. gs.gl.Call("clearStencil", int(v))
  259. gs.checkError("ClearStencil")
  260. }
  261. // Clear sets the bitplane area of the window to values previously
  262. // selected by ClearColor, ClearDepth, and ClearStencil.
  263. func (gs *GLS) Clear(mask uint) {
  264. gs.gl.Call("clear", int(mask))
  265. gs.checkError("Clear")
  266. }
  267. // CompileShader compiles the source code strings that
  268. // have been stored in the specified shader object.
  269. func (gs *GLS) CompileShader(shader uint32) {
  270. gs.gl.Call("compileShader", gs.shaderMap[shader])
  271. gs.checkError("CompileShader")
  272. }
  273. // CreateProgram creates an empty program object and returns
  274. // a non-zero value by which it can be referenced.
  275. func (gs *GLS) CreateProgram() uint32 {
  276. gs.programMap[gs.programMapIndex] = gs.gl.Call("createProgram")
  277. gs.checkError("CreateProgram")
  278. idx := gs.programMapIndex
  279. gs.programMapIndex++
  280. return idx
  281. }
  282. // CreateShader creates an empty shader object and returns
  283. // a non-zero value by which it can be referenced.
  284. func (gs *GLS) CreateShader(stype uint32) uint32 {
  285. gs.shaderMap[gs.shaderMapIndex] = gs.gl.Call("createShader", int(stype))
  286. gs.checkError("CreateShader")
  287. idx := gs.shaderMapIndex
  288. gs.shaderMapIndex++
  289. return idx
  290. }
  291. // DeleteBuffers deletes n​buffer objects named
  292. // by the elements of the provided array.
  293. func (gs *GLS) DeleteBuffers(bufs ...uint32) {
  294. for _, buf := range bufs {
  295. gs.gl.Call("deleteBuffer", gs.bufferMap[buf])
  296. gs.checkError("DeleteBuffers")
  297. gs.stats.Buffers--
  298. delete(gs.bufferMap, buf)
  299. }
  300. }
  301. // DeleteShader frees the memory and invalidates the name
  302. // associated with the specified shader object.
  303. func (gs *GLS) DeleteShader(shader uint32) {
  304. gs.gl.Call("deleteShader", gs.shaderMap[shader])
  305. gs.checkError("DeleteShader")
  306. delete(gs.shaderMap, shader)
  307. }
  308. // DeleteProgram frees the memory and invalidates the name
  309. // associated with the specified program object.
  310. func (gs *GLS) DeleteProgram(program uint32) {
  311. gs.gl.Call("deleteProgram", gs.programMap[program])
  312. gs.checkError("DeleteProgram")
  313. delete(gs.programMap, program)
  314. }
  315. // DeleteTextures deletes n​textures named
  316. // by the elements of the provided array.
  317. func (gs *GLS) DeleteTextures(tex ...uint32) {
  318. for _, t := range tex {
  319. gs.gl.Call("deleteTexture", gs.textureMap[t])
  320. gs.checkError("DeleteTextures")
  321. delete(gs.textureMap, t)
  322. gs.stats.Textures--
  323. }
  324. }
  325. // DeleteVertexArrays deletes n​vertex array objects named
  326. // by the elements of the provided array.
  327. func (gs *GLS) DeleteVertexArrays(vaos ...uint32) {
  328. for _, v := range vaos {
  329. gs.gl.Call("deleteVertexArray", gs.vertexArrayMap[v])
  330. gs.checkError("DeleteVertexArrays")
  331. delete(gs.vertexArrayMap, v)
  332. gs.stats.Vaos--
  333. }
  334. }
  335. // ReadPixels returns the current rendered image.
  336. // x, y: specifies the window coordinates of the first pixel that is read from the frame buffer.
  337. // width, height: specifies the dimensions of the pixel rectangle.
  338. // format: specifies the format of the pixel data.
  339. // format_type: specifies the data type of the pixel data.
  340. // more information: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/readPixels
  341. func (gs *GLS) ReadPixels(x, y, width, height, format, formatType int) []byte {
  342. size := (width - x) * (height - y) * 4
  343. pixels := make([]byte, size)
  344. jsPixels := js.Global().Get("Uint8Array").New(size)
  345. gs.gl.Call("readPixels", x, y, width, height, format, formatType, jsPixels)
  346. gs.checkError("ReadPixels")
  347. js.CopyBytesToJS(jsPixels, pixels)
  348. return pixels
  349. }
  350. func (gs *GLS) StencilOp(fail, zfail, zpass uint32) {
  351. gs.gl.Call("stencilOp", int(fail), int(zfail), int(zpass))
  352. gs.checkError("StencilOp")
  353. }
  354. func (gs *GLS) StencilFunc(mode uint32, ref int32, mask uint32) {
  355. gs.gl.Call("stencilFunc", int(mode), int(ref), int(mask))
  356. gs.checkError("StencilFunc")
  357. }
  358. // StencilMask enables or disables writing into the stencil buffer.
  359. func (gs *GLS) StencilMask(mask uint32) {
  360. if gs.stencilMask == mask {
  361. return
  362. }
  363. gs.gl.Call("stencilMask", int(mask))
  364. gs.checkError("StencilMask")
  365. gs.stencilMask = mask
  366. }
  367. // DepthFunc specifies the function used to compare each incoming pixel
  368. // depth value with the depth value present in the depth buffer.
  369. func (gs *GLS) DepthFunc(mode uint32) {
  370. if gs.depthFunc == mode {
  371. return
  372. }
  373. gs.gl.Call("depthFunc", int(mode))
  374. gs.checkError("DepthFunc")
  375. gs.depthFunc = mode
  376. }
  377. // DepthMask enables or disables writing into the depth buffer.
  378. func (gs *GLS) DepthMask(flag bool) {
  379. if gs.depthMask == intTrue && flag {
  380. return
  381. }
  382. if gs.depthMask == intFalse && !flag {
  383. return
  384. }
  385. gs.gl.Call("depthMask", flag)
  386. gs.checkError("DepthMask")
  387. if flag {
  388. gs.depthMask = intTrue
  389. } else {
  390. gs.depthMask = intFalse
  391. }
  392. }
  393. // DrawArrays renders primitives from array data.
  394. func (gs *GLS) DrawArrays(mode uint32, first int32, count int32) {
  395. gs.gl.Call("drawArrays", int(mode), first, count)
  396. gs.checkError("DrawArrays")
  397. gs.stats.Drawcalls++
  398. }
  399. // DrawElements renders primitives from array data.
  400. func (gs *GLS) DrawElements(mode uint32, count int32, itype uint32, start uint32) {
  401. gs.gl.Call("drawElements", int(mode), count, int(itype), start)
  402. gs.checkError("DrawElements")
  403. gs.stats.Drawcalls++
  404. }
  405. // Enable enables the specified capability.
  406. func (gs *GLS) Enable(cap int) {
  407. if gs.capabilities[cap] == capEnabled {
  408. gs.stats.Caphits++
  409. return
  410. }
  411. gs.gl.Call("enable", int32(cap))
  412. gs.checkError("Enable")
  413. gs.capabilities[cap] = capEnabled
  414. }
  415. // Disable disables the specified capability.
  416. func (gs *GLS) Disable(cap int) {
  417. if gs.capabilities[cap] == capDisabled {
  418. gs.stats.Caphits++
  419. return
  420. }
  421. gs.gl.Call("disable", cap)
  422. gs.checkError("Disable")
  423. gs.capabilities[cap] = capDisabled
  424. }
  425. // EnableVertexAttribArray enables a generic vertex attribute array.
  426. func (gs *GLS) EnableVertexAttribArray(index uint32) {
  427. gs.gl.Call("enableVertexAttribArray", index)
  428. gs.checkError("EnableVertexAttribArray")
  429. }
  430. // CullFace specifies whether front- or back-facing facets can be culled.
  431. func (gs *GLS) CullFace(mode uint32) {
  432. gs.gl.Call("cullFace", int(mode))
  433. gs.checkError("CullFace")
  434. }
  435. // FrontFace defines front- and back-facing polygons.
  436. func (gs *GLS) FrontFace(mode uint32) {
  437. if gs.frontFace == mode {
  438. return
  439. }
  440. gs.gl.Call("frontFace", int(mode))
  441. gs.checkError("FrontFace")
  442. gs.frontFace = mode
  443. }
  444. // GenBuffer generates a ​buffer object name.
  445. func (gs *GLS) GenBuffer() uint32 {
  446. gs.bufferMap[gs.bufferMapIndex] = gs.gl.Call("createBuffer")
  447. gs.checkError("CreateBuffer")
  448. idx := gs.bufferMapIndex
  449. gs.bufferMapIndex++
  450. gs.stats.Buffers++
  451. return idx
  452. }
  453. // GenFramebuffer creates a new framebuffer.
  454. // Framebuffers store (usually two) render buffers.
  455. func (gs *GLS) GenFramebuffer() uint32 {
  456. gs.framebufferMap[gs.framebufferMapIndex] = gs.gl.Call("createFramebuffer")
  457. gs.checkError("CreateFramebuffer")
  458. idx := gs.framebufferMapIndex
  459. gs.framebufferMapIndex++
  460. gs.stats.Fbos++
  461. return idx
  462. }
  463. // GenRenderbuffer creates a new render buffer.
  464. func (gs *GLS) GenRenderbuffer() uint32 {
  465. gs.renderbufferMap[gs.renderbufferMapIndex] = gs.gl.Call("createRenderbuffer")
  466. gs.checkError("CreateRenderbuffer")
  467. idx := gs.renderbufferMapIndex
  468. gs.renderbufferMapIndex++
  469. gs.stats.Rbos++
  470. return idx
  471. }
  472. // BindFramebuffer sets the current framebuffer.
  473. func (gs *GLS) BindFramebuffer(fb uint32) {
  474. gs.gl.Call("bindFramebuffer", FRAMEBUFFER, gs.framebufferMap[fb])
  475. gs.checkError("BindFramebuffer")
  476. }
  477. // BindRenderbuffer sets the current render buffer.
  478. func (gs *GLS) BindRenderbuffer(rb uint32) {
  479. gs.gl.Call("bindRenderbuffer", RENDERBUFFER, gs.renderbufferMap[rb])
  480. gs.checkError("BindRenderbuffer")
  481. }
  482. // RenderbufferStorage allocates space for the bound render buffer.
  483. // Format is the internal storage format, e.g. RGBA32F
  484. func (gs *GLS) RenderbufferStorage(format uint, width int, height int) {
  485. gs.gl.Call("renderbufferStorage", int(format), width, height)
  486. gs.checkError("RenderbufferStorage")
  487. }
  488. // FramebufferRenderbuffer attaches a renderbuffer object to the bound framebuffer object.
  489. // Attachment is one of COLOR_ATTACHMENT0, DEPTH_ATTACHMENT, or STENCIL_ATTACHMENT.
  490. func (gs *GLS) FramebufferRenderbuffer(attachment uint, rb uint32) {
  491. gs.gl.Call("framebufferRenderbuffer", DRAW_FRAMEBUFFER, int(attachment), RENDERBUFFER, gs.renderbufferMap[rb])
  492. gs.checkError("FramebufferRenderbuffer")
  493. }
  494. // FramebufferTexture2D attaches a level of a texture object as a logical buffer to the currently bound framebuffer object
  495. func (gs *GLS) FramebufferTexture2D(attachment uint, textarget uint, tex uint32) {
  496. gs.gl.Call("framebufferTexture2D", FRAMEBUFFER, int(attachment), int(textarget), int(tex), 0)
  497. gs.checkError("FramebufferTexture2D")
  498. }
  499. // CheckFramebufferStatus get the framebuffer status
  500. func (gs *GLS) CheckFramebufferStatus() uint32 {
  501. res := gs.gl.Call("checkFramebufferStatus", FRAMEBUFFER)
  502. gs.checkError("CheckFramebufferStatus")
  503. return uint32(res.Int())
  504. }
  505. // ReadBuffer sets the buffer for reading using ReadPixels.
  506. // Attachment is one of COLOR_ATTACHMENT0, DEPTH_ATTACHMENT, or STENCIL_ATTACHMENT.
  507. func (gs *GLS) ReadBuffer(attachment uint) {
  508. gs.gl.Call("readBuffer", int(attachment))
  509. gs.checkError("ReadBuffer")
  510. }
  511. // GenerateMipmap generates mipmaps for the specified texture target.
  512. func (gs *GLS) GenerateMipmap(target uint32) {
  513. gs.gl.Call("generateMipmap", int(target))
  514. gs.checkError("GenerateMipmap")
  515. }
  516. // GenTexture generates a texture object name.
  517. func (gs *GLS) GenTexture() uint32 {
  518. gs.textureMap[gs.textureMapIndex] = gs.gl.Call("createTexture")
  519. gs.checkError("GenTexture")
  520. idx := gs.textureMapIndex
  521. gs.textureMapIndex++
  522. gs.stats.Textures++
  523. return idx
  524. }
  525. // GenVertexArray generates a vertex array object name.
  526. func (gs *GLS) GenVertexArray() uint32 {
  527. gs.vertexArrayMap[gs.vertexArrayMapIndex] = gs.gl.Call("createVertexArray")
  528. gs.checkError("GenVertexArray")
  529. idx := gs.vertexArrayMapIndex
  530. gs.vertexArrayMapIndex++
  531. gs.stats.Vaos++
  532. return idx
  533. }
  534. // GetAttribLocation returns the location of the specified attribute variable.
  535. func (gs *GLS) GetAttribLocation(program uint32, name string) int32 {
  536. loc := gs.gl.Call("getAttribLocation", gs.programMap[program], name).Int()
  537. gs.checkError("GetAttribLocation")
  538. return int32(loc)
  539. }
  540. // GetProgramiv returns the specified parameter from the specified program object.
  541. func (gs *GLS) GetProgramiv(program, pname uint32, params *int32) {
  542. sparam := gs.gl.Call("getProgramParameter", gs.programMap[program], int(pname))
  543. gs.checkError("GetProgramiv")
  544. switch pname {
  545. case DELETE_STATUS, LINK_STATUS, VALIDATE_STATUS:
  546. if sparam.Bool() {
  547. *params = TRUE
  548. } else {
  549. *params = FALSE
  550. }
  551. default:
  552. *params = int32(sparam.Int())
  553. }
  554. }
  555. // GetProgramInfoLog returns the information log for the specified program object.
  556. func (gs *GLS) GetProgramInfoLog(program uint32) string {
  557. res := gs.gl.Call("getProgramInfoLog", gs.programMap[program]).String()
  558. gs.checkError("GetProgramInfoLog")
  559. return res
  560. }
  561. // GetShaderInfoLog returns the information log for the specified shader object.
  562. func (gs *GLS) GetShaderInfoLog(shader uint32) string {
  563. res := gs.gl.Call("getShaderInfoLog", gs.shaderMap[shader]).String()
  564. gs.checkError("GetShaderInfoLog")
  565. return res
  566. }
  567. // GetString returns a string describing the specified aspect of the current GL connection.
  568. func (gs *GLS) GetString(name uint32) string {
  569. res := gs.gl.Call("getParameter", int(name)).String()
  570. gs.checkError("GetString")
  571. return res
  572. }
  573. // GetUniformLocation returns the location of a uniform variable for the specified program.
  574. func (gs *GLS) GetUniformLocation(program uint32, name string) int32 {
  575. loc := gs.gl.Call("getUniformLocation", gs.programMap[program], name)
  576. if wasm.Equal(loc, js.Null()) {
  577. return -1
  578. }
  579. gs.uniformMap[gs.uniformMapIndex] = loc
  580. gs.checkError("GetUniformLocation")
  581. idx := gs.uniformMapIndex
  582. gs.uniformMapIndex++
  583. return int32(idx)
  584. }
  585. // GetViewport returns the current viewport information.
  586. func (gs *GLS) GetViewport() (x, y, width, height int32) {
  587. return gs.viewportX, gs.viewportY, gs.viewportWidth, gs.viewportHeight
  588. }
  589. // LineWidth specifies the rasterized width of both aliased and antialiased lines.
  590. func (gs *GLS) LineWidth(width float32) {
  591. if gs.lineWidth == width {
  592. return
  593. }
  594. gs.gl.Call("lineWidth", width)
  595. gs.checkError("LineWidth")
  596. gs.lineWidth = width
  597. }
  598. // LinkProgram links the specified program object.
  599. func (gs *GLS) LinkProgram(program uint32) {
  600. gs.gl.Call("linkProgram", gs.programMap[program])
  601. gs.checkError("LinkProgram")
  602. }
  603. // GetShaderiv returns the specified parameter from the specified shader object.
  604. func (gs *GLS) GetShaderiv(shader, pname uint32, params *int32) {
  605. sparam := gs.gl.Call("getShaderParameter", gs.shaderMap[shader], int(pname))
  606. gs.checkError("GetShaderiv")
  607. switch pname {
  608. case DELETE_STATUS, COMPILE_STATUS:
  609. if sparam.Bool() {
  610. *params = TRUE
  611. } else {
  612. *params = FALSE
  613. }
  614. default:
  615. *params = int32(sparam.Int())
  616. }
  617. }
  618. // Scissor defines the scissor box rectangle in window coordinates.
  619. func (gs *GLS) Scissor(x, y int32, width, height uint32) {
  620. gs.gl.Call("scissor", x, y, int(width), int(height))
  621. gs.checkError("Scissor")
  622. }
  623. // ShaderSource sets the source code for the specified shader object.
  624. func (gs *GLS) ShaderSource(shader uint32, src string) {
  625. gs.gl.Call("shaderSource", gs.shaderMap[shader], src)
  626. gs.checkError("ShaderSource")
  627. }
  628. // TexImage2D specifies a two-dimensional texture image.
  629. func (gs *GLS) TexImage2D(target uint32, level int32, iformat int32, width int32, height int32, format uint32, itype uint32, data interface{}) {
  630. dataTA, free := wasm.SliceToTypedArray(data)
  631. gs.gl.Call("texImage2D", int(target), level, iformat, width, height, 0, int(format), int(itype), dataTA)
  632. gs.checkError("TexImage2D")
  633. free()
  634. }
  635. // CompressedTexImage2D specifies a two-dimensional compressed texture image.
  636. func (gs *GLS) CompressedTexImage2D(target uint32, level uint32, iformat uint32, width int32, height int32, size int32, data interface{}) {
  637. // todo
  638. }
  639. // TexParameteri sets the specified texture parameter on the specified texture.
  640. func (gs *GLS) TexParameteri(target uint32, pname uint32, param int32) {
  641. gs.gl.Call("texParameteri", int(target), int(pname), param)
  642. gs.checkError("TexParameteri")
  643. }
  644. // PolygonMode controls the interpretation of polygons for rasterization.
  645. func (gs *GLS) PolygonMode(face, mode uint32) {
  646. log.Warn("PolygonMode not available in WebGL")
  647. }
  648. // PolygonOffset sets the scale and units used to calculate depth values.
  649. func (gs *GLS) PolygonOffset(factor float32, units float32) {
  650. if gs.polygonOffsetFactor == factor && gs.polygonOffsetUnits == units {
  651. return
  652. }
  653. gs.gl.Call("polygonOffset", factor, units)
  654. gs.checkError("PolygonOffset")
  655. gs.polygonOffsetFactor = factor
  656. gs.polygonOffsetUnits = units
  657. }
  658. // Uniform1i sets the value of an int uniform variable for the current program object.
  659. func (gs *GLS) Uniform1i(location int32, v0 int32) {
  660. gs.gl.Call("uniform1i", gs.uniformMap[uint32(location)], v0)
  661. gs.checkError("Uniform1i")
  662. gs.stats.Unisets++
  663. }
  664. // Uniform1f sets the value of a float uniform variable for the current program object.
  665. func (gs *GLS) Uniform1f(location int32, v0 float32) {
  666. gs.gl.Call("uniform1f", gs.uniformMap[uint32(location)], v0)
  667. gs.checkError("Uniform1f")
  668. gs.stats.Unisets++
  669. }
  670. // Uniform2f sets the value of a vec2 uniform variable for the current program object.
  671. func (gs *GLS) Uniform2f(location int32, v0, v1 float32) {
  672. gs.gl.Call("uniform2f", gs.uniformMap[uint32(location)], v0, v1)
  673. gs.checkError("Uniform2f")
  674. gs.stats.Unisets++
  675. }
  676. // Uniform3f sets the value of a vec3 uniform variable for the current program object.
  677. func (gs *GLS) Uniform3f(location int32, v0, v1, v2 float32) {
  678. gs.gl.Call("uniform3f", gs.uniformMap[uint32(location)], v0, v1, v2)
  679. gs.checkError("Uniform3f")
  680. gs.stats.Unisets++
  681. }
  682. // Uniform4f sets the value of a vec4 uniform variable for the current program object.
  683. func (gs *GLS) Uniform4f(location int32, v0, v1, v2, v3 float32) {
  684. gs.gl.Call("uniform4f", gs.uniformMap[uint32(location)], v0, v1, v2, v3)
  685. gs.checkError("Uniform4f")
  686. gs.stats.Unisets++
  687. }
  688. // UniformMatrix3fv sets the value of one or many 3x3 float matrices for the current program object.
  689. func (gs *GLS) UniformMatrix3fv(location int32, count int32, transpose bool, pm *float32) {
  690. data := (*[1 << 30]float32)(unsafe.Pointer(pm))[:9*count]
  691. dataTA, free := wasm.SliceToTypedArray(data)
  692. gs.gl.Call("uniformMatrix3fv", gs.uniformMap[uint32(location)], transpose, dataTA)
  693. free()
  694. gs.checkError("UniformMatrix3fv")
  695. gs.stats.Unisets++
  696. }
  697. // UniformMatrix4fv sets the value of one or many 4x4 float matrices for the current program object.
  698. func (gs *GLS) UniformMatrix4fv(location int32, count int32, transpose bool, pm *float32) {
  699. data := (*[1 << 30]float32)(unsafe.Pointer(pm))[:16*count]
  700. dataTA, free := wasm.SliceToTypedArray(data)
  701. gs.gl.Call("uniformMatrix4fv", gs.uniformMap[uint32(location)], transpose, dataTA)
  702. free()
  703. gs.checkError("UniformMatrix4fv")
  704. gs.stats.Unisets++
  705. }
  706. // Uniform1fv sets the value of one or many float uniform variables for the current program object.
  707. func (gs *GLS) Uniform1fv(location int32, count int32, v *float32) {
  708. data := (*[1 << 30]float32)(unsafe.Pointer(v))[:count]
  709. dataTA, free := wasm.SliceToTypedArray(data)
  710. gs.gl.Call("uniform1fv", gs.uniformMap[uint32(location)], dataTA)
  711. free()
  712. gs.checkError("Uniform1fv")
  713. gs.stats.Unisets++
  714. }
  715. // Uniform2fv sets the value of one or many vec2 uniform variables for the current program object.
  716. func (gs *GLS) Uniform2fv(location int32, count int32, v *float32) {
  717. data := (*[1 << 30]float32)(unsafe.Pointer(v))[:2*count]
  718. dataTA, free := wasm.SliceToTypedArray(data)
  719. gs.gl.Call("uniform2fv", gs.uniformMap[uint32(location)], dataTA)
  720. free()
  721. gs.checkError("Uniform2fv")
  722. gs.stats.Unisets++
  723. }
  724. // Uniform3fv sets the value of one or many vec3 uniform variables for the current program object.
  725. func (gs *GLS) Uniform3fv(location int32, count int32, v *float32) {
  726. data := (*[1 << 30]float32)(unsafe.Pointer(v))[:3*count]
  727. dataTA, free := wasm.SliceToTypedArray(data)
  728. gs.gl.Call("uniform3fv", gs.uniformMap[uint32(location)], dataTA)
  729. free()
  730. gs.checkError("Uniform3fv")
  731. gs.stats.Unisets++
  732. }
  733. // Uniform4fv sets the value of one or many vec4 uniform variables for the current program object.
  734. func (gs *GLS) Uniform4fv(location int32, count int32, v *float32) {
  735. data := (*[1 << 30]float32)(unsafe.Pointer(v))[:4*count]
  736. dataTA, free := wasm.SliceToTypedArray(data)
  737. gs.gl.Call("uniform4fv", gs.uniformMap[uint32(location)], dataTA)
  738. free()
  739. gs.checkError("Uniform4fv")
  740. gs.stats.Unisets++
  741. }
  742. // VertexAttribPointer defines an array of generic vertex attribute data.
  743. func (gs *GLS) VertexAttribPointer(index uint32, size int32, xtype uint32, normalized bool, stride int32, offset uint32) {
  744. gs.gl.Call("vertexAttribPointer", index, size, int(xtype), normalized, stride, offset)
  745. gs.checkError("VertexAttribPointer")
  746. }
  747. // Viewport sets the viewport.
  748. func (gs *GLS) Viewport(x, y, width, height int32) {
  749. gs.gl.Call("viewport", x, y, width, height)
  750. gs.checkError("Viewport")
  751. gs.viewportX = x
  752. gs.viewportY = y
  753. gs.viewportWidth = width
  754. gs.viewportHeight = height
  755. }
  756. // UseProgram sets the specified program as the current program.
  757. func (gs *GLS) UseProgram(prog *Program) {
  758. if prog.handle == 0 {
  759. panic("Invalid program")
  760. }
  761. gs.gl.Call("useProgram", gs.programMap[prog.handle])
  762. gs.checkError("UseProgram")
  763. gs.prog = prog
  764. // Inserts program in cache if not already there.
  765. if !gs.programs[prog] {
  766. gs.programs[prog] = true
  767. log.Debug("New Program activated. Total: %d", len(gs.programs))
  768. }
  769. }
  770. // checkError checks if there are any WebGL errors and panics if so.
  771. func (gs *GLS) checkError(name string) {
  772. if !gs.checkErrors {
  773. return
  774. }
  775. err := gs.gl.Call("getError")
  776. if err.Int() != NO_ERROR {
  777. panic(fmt.Sprintf("%s error: %v", name, err))
  778. }
  779. }