skybox.go 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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 graphic
  5. import (
  6. "github.com/g3n/engine/core"
  7. "github.com/g3n/engine/geometry"
  8. "github.com/g3n/engine/gls"
  9. "github.com/g3n/engine/material"
  10. "github.com/g3n/engine/math32"
  11. "github.com/g3n/engine/texture"
  12. )
  13. // Skybox is the Graphic that represents a skybox.
  14. type Skybox struct {
  15. Graphic // embedded graphic object
  16. uniMVm gls.Uniform // model view matrix uniform location cache
  17. uniMVPm gls.Uniform // model view projection matrix uniform cache
  18. uniNm gls.Uniform // normal matrix uniform cache
  19. }
  20. // SkyboxData contains the data necessary to locate the textures for a Skybox in a concise manner.
  21. type SkyboxData struct {
  22. DirAndPrefix string
  23. Extension string
  24. Suffixes [6]string
  25. }
  26. // NewSkybox creates and returns a pointer to a Skybox with the specified textures.
  27. func NewSkybox(data SkyboxData) (*Skybox, error) {
  28. skybox := new(Skybox)
  29. geom := geometry.NewCube(1)
  30. skybox.Graphic.Init(skybox, geom, gls.TRIANGLES)
  31. skybox.Graphic.SetCullable(false)
  32. for i := 0; i < 6; i++ {
  33. tex, err := texture.NewTexture2DFromImage(data.DirAndPrefix + data.Suffixes[i] + "." + data.Extension)
  34. if err != nil {
  35. return nil, err
  36. }
  37. matFace := material.NewStandard(math32.NewColor("white"))
  38. matFace.AddTexture(tex)
  39. matFace.SetSide(material.SideBack)
  40. matFace.SetUseLights(material.UseLightNone)
  41. // Disable writes to the depth buffer (call glDepthMask(GL_FALSE)).
  42. // This will cause every other object to draw over the skybox, making it always appear behind everything else.
  43. // It doesn't matter how small/big the skybox is as long as it's visible by the camera (within near/far planes).
  44. matFace.SetDepthMask(false)
  45. skybox.AddGroupMaterial(skybox, matFace, i)
  46. }
  47. // Creates uniforms
  48. skybox.uniMVm.Init("ModelViewMatrix")
  49. skybox.uniMVPm.Init("MVP")
  50. skybox.uniNm.Init("NormalMatrix")
  51. // The skybox should always be rendered last among the opaque objects
  52. skybox.SetRenderOrder(100)
  53. return skybox, nil
  54. }
  55. // RenderSetup is called by the engine before drawing the skybox geometry
  56. // It is responsible to updating the current shader uniforms with
  57. // the model matrices.
  58. func (skybox *Skybox) RenderSetup(gs *gls.GLS, rinfo *core.RenderInfo) {
  59. mvm := *skybox.ModelViewMatrix()
  60. // Clear translation
  61. mvm[12] = 0
  62. mvm[13] = 0
  63. mvm[14] = 0
  64. // mvm.ExtractRotation(&rinfo.ViewMatrix) // TODO <- ExtractRotation does not work as expected?
  65. // Transfer mvp uniform
  66. location := skybox.uniMVm.Location(gs)
  67. gs.UniformMatrix4fv(location, 1, false, &mvm[0])
  68. // Calculates model view projection matrix and updates uniform
  69. var mvpm math32.Matrix4
  70. mvpm.MultiplyMatrices(&rinfo.ProjMatrix, &mvm)
  71. location = skybox.uniMVPm.Location(gs)
  72. gs.UniformMatrix4fv(location, 1, false, &mvpm[0])
  73. // Calculates normal matrix and updates uniform
  74. var nm math32.Matrix3
  75. nm.GetNormalMatrix(&mvm)
  76. location = skybox.uniNm.Location(gs)
  77. gs.UniformMatrix3fv(location, 1, false, &nm[0])
  78. }