postprocessor.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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 renderer implements the scene renderer.
  5. package renderer
  6. import "github.com/g3n/engine/gls"
  7. type Postprocessor struct {
  8. Width int32
  9. Height int32
  10. Fbo uint32
  11. Tex uint32
  12. Vao uint32
  13. Prg *gls.Program
  14. screen []float32
  15. Renderer *Renderer
  16. }
  17. func (r *Renderer) CreatePostprocessor(width, height int32, vertexShaderSource, fragmentShaderSource string) *Postprocessor {
  18. pp := &Postprocessor{
  19. Width: width,
  20. Height: height,
  21. Renderer: r,
  22. screen: []float32{
  23. // xyz color texture coords
  24. -1, 1, 0, 1, 1, 1, 0, 1,
  25. -1, -1, 0, 1, 1, 1, 0, 0,
  26. 1, -1, 0, 1, 1, 1, 1, 0,
  27. 1, 1, 0, 1, 1, 1, 1, 1,
  28. -1, 1, 0, 1, 1, 1, 0, 1,
  29. 1, -1, 0, 1, 1, 1, 1, 0,
  30. },
  31. }
  32. pp.Fbo = r.gs.GenFramebuffer()
  33. r.gs.BindFramebuffer(pp.Fbo)
  34. // set up a texture to render into
  35. pp.Tex = r.gs.GenTexture()
  36. r.gs.BindTexture(gls.TEXTURE_2D, pp.Tex)
  37. r.gs.TexImage2D(gls.TEXTURE_2D, 0, gls.RGB, width, height, gls.RGB, gls.UNSIGNED_BYTE, nil)
  38. r.gs.TexParameteri(gls.TEXTURE_2D, gls.TEXTURE_WRAP_S, gls.CLAMP_TO_EDGE)
  39. r.gs.TexParameteri(gls.TEXTURE_2D, gls.TEXTURE_WRAP_T, gls.CLAMP_TO_EDGE)
  40. r.gs.TexParameteri(gls.TEXTURE_2D, gls.TEXTURE_MIN_FILTER, gls.NEAREST)
  41. r.gs.TexParameteri(gls.TEXTURE_2D, gls.TEXTURE_MAG_FILTER, gls.NEAREST)
  42. r.gs.BindTexture(gls.TEXTURE_2D, 0)
  43. r.gs.FramebufferTexture2D(gls.COLOR_ATTACHMENT0, gls.TEXTURE_2D, pp.Tex)
  44. // attach depth and stencil buffers
  45. rbo := r.gs.GenRenderbuffer()
  46. r.gs.BindRenderbuffer(rbo)
  47. r.gs.RenderbufferStorage(gls.DEPTH24_STENCIL8, int(width), int(height))
  48. r.gs.BindRenderbuffer(0)
  49. r.gs.FramebufferRenderbuffer(gls.DEPTH_STENCIL_ATTACHMENT, rbo)
  50. // check the framebuffer status
  51. if r.gs.CheckFramebufferStatus() != gls.FRAMEBUFFER_COMPLETE {
  52. log.Fatal("Can't create frame buffer")
  53. }
  54. r.gs.BindFramebuffer(0)
  55. // create the "screen" quad
  56. vbo := r.gs.GenBuffer()
  57. r.gs.BindBuffer(gls.ARRAY_BUFFER, vbo)
  58. r.gs.BufferData(gls.ARRAY_BUFFER, 4*len(pp.screen), pp.screen, gls.STATIC_DRAW)
  59. pp.Vao = r.gs.GenVertexArray()
  60. r.gs.BindVertexArray(pp.Vao)
  61. r.gs.BindBuffer(gls.ARRAY_BUFFER, vbo)
  62. var offset uint32
  63. // position attribute
  64. r.gs.VertexAttribPointer(0, 3, gls.FLOAT, false, 8*4, offset)
  65. r.gs.EnableVertexAttribArray(0)
  66. offset += 3 * 4
  67. // color attribute
  68. r.gs.VertexAttribPointer(1, 3, gls.FLOAT, false, 8*4, offset)
  69. r.gs.EnableVertexAttribArray(1)
  70. offset += 3 * 4
  71. // texture coord attribute
  72. r.gs.VertexAttribPointer(2, 2, gls.FLOAT, false, 8*4, offset)
  73. r.gs.EnableVertexAttribArray(2)
  74. offset += 2 * 4
  75. // the screen shaders
  76. pp.Prg = r.gs.NewProgram()
  77. pp.Prg.AddShader(gls.VERTEX_SHADER, vertexShaderSource)
  78. pp.Prg.AddShader(gls.FRAGMENT_SHADER, fragmentShaderSource)
  79. err := pp.Prg.Build()
  80. if err != nil {
  81. log.Fatal("can't create shader: %e", err)
  82. }
  83. return pp
  84. }
  85. func (pp *Postprocessor) Render(fbwidth, fbheight int, render func()) {
  86. // render into the low-res texture
  87. gs := pp.Renderer.gs
  88. gs.Viewport(0, 0, pp.Width, pp.Height)
  89. gs.BindFramebuffer(pp.Fbo)
  90. gs.Enable(gls.DEPTH_TEST)
  91. render()
  92. // show texture on screen
  93. gs.Viewport(0, 0, int32(fbwidth), int32(fbheight))
  94. gs.BindFramebuffer(0)
  95. gs.ClearColor(1, 1, 1, 1)
  96. gs.Clear(gls.COLOR_BUFFER_BIT)
  97. gs.UseProgram(pp.Prg)
  98. gs.Disable(gls.DEPTH_TEST)
  99. gs.BindTexture(gls.TEXTURE_2D, pp.Tex)
  100. gs.BindVertexArray(pp.Vao)
  101. gs.DrawArrays(gls.TRIANGLES, 0, int32(len(pp.screen)/8))
  102. }