T4 Modules Howto Guide/Frame Buffers

From Tales of Maj'Eyal
Revision as of 19:42, 8 July 2013 by Ibanix (Talk | contribs) (Ibanix moved page Frame Buffers to T4 Modules Howto Guide/Frame Buffers: namespace collision prevention)

Jump to: navigation, search

[Quoting Darkgod from the forums]

Hum shaders ... You need to understand one thing about how this all works.
To use a fullscreen or fullmap shader the game makes a FBO (framebuffer object, like a virtual screen that outputs to a texture), displays the map inside it and then displays the FBO's texture through the shader. The shader is applied to each and every pixel drawn from the texture.

So first you setup your FBOs, for that just copy ToME's Game:createFBOs() method and call it as tome does (in setupDisplayMode).
Now your fbos are created and your shaders are loaded. You need to use them now. Not all displays can do shaders or FBO though, so you need two versions of your map display code:
Where your module probably just does (if you copied example module):


      self.level.map:display(nil, nil, nb_keyframe)
      self.target:display()

You instead do:


      -- Display using Framebuffer, so that we can use shaders and all
      local map = game.level.map
      if self.fbo then
         self.fbo:use(true)
            map:display(0, 0, nb_keyframe)
         self.fbo:use(false, self.full_fbo)
         self.fbo:toScreen(map.display_x, map.display_y, map.viewport.width, map.viewport.height, self.fbo_shader.shad)

         if self.target then self.target:display() end

      -- Basic display; no FBOs
      else
         map:display(nil, nil, nb_keyframe)
         if self.target then self.target:display() end
      end

This will make the map display in its own texture and then use the fbo shader on it.
ToME uses two fbos, one for the map and one for the whole screen.
The fullscreen one must thus also be used:
At the top of Game:display() right after the "if self.change_res_dialog" you add a line:


   if self.full_fbo then self.full_fbo:use(true) end

And then at the very bottom of Game:display() you do:


   if self.full_fbo then
      self.full_fbo:use(false)
      self.full_fbo:toScreen(0, 0, self.w, self.h, self.full_fbo_shader.shad)
   end

This will display all the game inside a fbo and then display it with the given shader.

Now shaders themselves. They live in data/gfx/shaders/ There must usualy be two file per shaders, a .lua file that describes it and a .frag one that is the shader code to run on the GPU. Try to see how main_fbo and full_fbo shaders in ToME work. They probably are enough for your needs but you can play with them as you need (or ask more specific questions).

Now if you did it all right your game should display .. just as before!
So we need to tell the shaders to do stuff. First tell the full_fbo shader to handle gamme correction instead of the OS (it usualy looks better):
define


support_shader_gamma = true

in Game.lua, before the init method (like ToME does).
If at that point you get a fully dark screen, try to add


self:setGamma(config.settings.gamma_correction / 100)

right at the end of createFBOs.

Now the fun part!
Say you want to colorize your game in red, you simply do:


game.fbo_shader:setUniform("colorize", {1,0.2,0,1})

Somewhere in your code. To restore default you do:


game.fbo_shader:setUniform("colorize", {0,0,0,0})

ToME's relevant code for that is in Player:updateMainShader()

Go play with those

Go back to T4 Modules Howto Guide