Not logged inGosu Forums
Forum back to libgosu.org Help Search Register Login
Up Topic Gosu / Extending Gosu / Ashton - shaders and framebuffers in Ruby
1 2 Previous Next  
- - By Spooner Date 2012-07-09 15:48 Edited 2012-07-15 18:17
I've started developing a gem to incorporate shaders and framebuffers into Ruby/Gosu, using a high-level framework. Although mostly my own work, I did use the existing post-processing code to get me started, by  Mathias in C++ and jsb's port of that to Ruby. I also peeked at Mon_Ouie's implementation of shaders in Ray.

* Shader allows for all sorts of real-time manipulation of textures and vertices and, being written in a C-like language run on your graphics card, they will run painfully fast, even in Ruby :) Aston will support both full-screen post-processing (blur, pixelate, etc) and affecting individual Image/Font/primitive draw operations.
* Framebuffer allows for drawing Image/Font, etc., directly into other Images, as though they were the window. A very limited version of this ability to draw off-screen is currently available as Window#render_to_image, provided by TexPlay.
* Although not directly related, I also have a ParticleEmitter class which manages large-scale particle drops. It supports shaders and is relatively efficient compared to anything you could implement in Ruby, even though it can update and draw a lot of moving particles. Current benchmark is 18k particles @ 40FPS, so you should be able to use it with a couple of thousand at a time quite nicely.

I've only released a --pre gem, but the github project is spooner/ashton. I've added a todo list on the wiki.

I'm aiming at strict OpenGL2.0/GLSL 1.10 compatibility in the gem, but that wouldn't stop people using more advanced stuff for their own projects if they don't mind alienating people with ancient hardware (e.g. Maverick's laptop only supports OpenGL2.0).
Parent - - By Spooner Date 2012-07-10 00:21 Edited 2012-07-11 08:47
I sorted out my dumb mistake with the shaders that was holding me back, after a lot of banging of heads!

I've have released an 0.0.1alpha gem today, but it is far from production-ready:

    gem install ashton --pre

Mainly, I expect to completely revamp the API a few times before it gets to beta quality - any thoughts on this, based on what I have done so far are welcome. As are suggestions of the sorts of things that should be in the gem (hopefully somewhat related!).

I have a few examples it might be worth looking at, though! I'm quite impressed that such effects are even possible in Ruby, but then it is OpenGL doing all the heavy lifting :)

To jlnr (and any other Gosu source hackers): I'm having a real problem with not being able to force drawing when I want it, in order to draw into a buffer or with a shader. I can use Window#flush, but that will flush _everything_ that is pending not just the items in a block (or, in the case of the :shader option I've added to Image#draw et al, to individual items). Is there a way to do this now, or can it be added, either on individual #draws or in some sort of Gosu#draw_immediate = true/false option?
Parent - - By lol_o2 Date 2012-07-11 08:16
I'd suggest Stencil operations for framebuffer or some alpha-replacing (e.g. to make holes using transparent images). I played a bit with the gem and the speed looks promising :)
Parent - - By Spooner Date 2012-07-11 08:29
Hard to tell too much about the speed, really, since the examples are not really doing much. Since Opengl is doing all the work, there shouldn't be an issue, but I will eventually convert chunks of code into a C-extension once I've got the design complete and working.

I'm looking at trying to implement some sort of shadow-casting effect with shaders at this very moment :)

Is there any use to depth buffers in the framebuffer class, or would that only be if people wanted to use proper opengl in them (in which case, such hard-core people might prefer to manage the fbo themselves)? I'll look into stencils and alpha-replacing for you.

I am considering whether Image#draw_points points_array, z, etc would be worth implementing (using point sprites). I suspect that could be a lot faster than a lot of individual draws if you have a lot of moving particles, but I'm worried that the cost in particle systems is more about the Ruby code managing them than anything else.

I'm aiming at strict OpenGL2.0/GLSL 1.10 compatibility in the gem, but that wouldn't stop people using more advanced stuff for their own projects if they don't mind alienating people with ancient hardware (e.g. Maverick's laptop only supports OpenGL2.0).
Parent - - By jlnr (dev) Date 2012-07-11 10:32
A particle system is one of those things that everyone can agree on, I think, so it would make more sense to outsource the engine altogether into a flexible C/C++ library. Bonus points for getting the balance on customizability just right. :)

I would worry that point sprites will end up being another mess like GL_LINE / Window#draw_line.
Parent - - By Spooner Date 2012-07-11 10:59
jlnr Why would point-sprites be like GL_LINE? Yeah, they would be GL_POINT, but sprites drawn at those positions. The advantage to us would be passing a 100x2 array of points, to draw 100 sprites, rather than doing 100 Image#draw calls. You can't use #record for this, since the vertexes would be continually moving, but I could use vertex arrays (or is that what is underneath #record? I'm still a bit of an opengl noob).

Admittedly, doing the physics in C as well would make additional benefits. If you can suggest any appropriate engines, do so, otherwise I could consider a very simple one myself, since that may even be easier to integrate into Gosu and it doesn't have to do much (apart from set velocity, texture, size & lifespan of created particles).
Parent - - By jlnr (dev) Date 2012-07-11 11:39
GL_LINE was a total disaster because it turned out to work differently on every driver and only caused confusion and bug reports.  I wouldn't trust GL_POINT to work any better. A wasteful quad per particle should be fine, everything else seems to be good for debug UI only. :(

record uses a vertex array but doesn't let you change the positions afterwards, mostly because I haven't figured out a nice interface to do so. Of course the particle engine could use its own gl(z) {} block to render everything with an optimized vertex array. Then I also don't know if there is an issue with keeping the VA in VRAM vs. system RAM.

Physics? My particles never bounce off any walls so it's basically just a loop over all my particles to add vx to x and ax to vx etc. - I don't think a wrapping a library for that is worth the hassle :)
Parent - - By Spooner Date 2012-07-11 11:53
I thought the issue with GL_LINE was that it wasn't pixel-perfect, so if you were drawing boxes, then things wouldn't line up. This wouldn't make any difference to GL_POINT-based particles, surely?

gl(z) {} seems to break when mixed with shaders and shaders are the easiest way to affect particles in movement (e.g. changing colour and size based on distance from origin or similar manipulations).

Velocity and acceleration calculations are both "physics". Particles just don't have collision physics :P The problem with having a lot of particles (say 100) in Ruby is that they grind very, very quickly, even with trivial physics implemented in Ruby-slow-a-thon.
Parent - - By jlnr (dev) Date 2012-07-12 04:12
Well, being off by one pixel would be enough to trigger bug reports! :) And this is before even touching line width/point size or texturization (in the case of points).

gl(z) should not break with shaders, I thought the crash was related to calling Image#draw inside the block :S Can you please open a ticket on github with the code attached?

As for the particle system…I was thinking of a simple C based library that would do the particle physics in a tight for loop. It wouldn't even have to be deeply tied to Gosu if it used a vertex array.
Parent - By Spooner Date 2012-07-12 10:39
Well, it depends on what people are using things for. I agree that in Gosu, pixel-perfection idiot-proofing makes sense, since people will want to build GUIs out of lines, but points in a particle system can definitely be approximations :)

I'll try to make a minimum repeatable shader/gl problem today.

Yes, that is what I was thinking too. I started on implementing a particle-emitter in Ruby yesterday, with the intention of porting it to C. I'm trying to write the code in Ruby and will try to use a VBO to make it as fast and optimised as I can. I have really got to quite like building in high-level Ruby, when I don't have such clear design in mind, and getting everything working/tested before converting it, method at a time, into C.
Parent - By RavensKrag Date 2012-07-14 19:45
Indeed, GL_LINE is defined by OpenGL is such a way that it is ambiguous as to whether it should be inclusive or exclusive of the first/last point.  However, GL_POINT has no such problem; as far as I know.
Parent - - By Spooner Date 2012-07-11 08:52
Regarding alpha-replacing, I think that might be difficult to implement, since it would be a new drawing operation (:default, :add and :multiply being implemented so far). Without re-writing the image/font/drawing code, I might find it impossible to control the drawing mode, even into framebuffers.
Parent - - By lol_o2 Date 2012-07-11 09:13 Edited 2012-07-11 09:18
What I want with this is simple light/shadow effect (like here). I previously made it with TexPlay but it was toooo slow. So if it's possible with shaders, you don't need to bother with alpha-replacing or Stencil just for me :)

BTW, I tested framebuffer example with 100 waves and FPS dropped "only" to 30

Edit:
Also if it's possible, you could make some get_pixel method faster than in TexPlay.
Parent - By Spooner Date 2012-07-11 09:34
If you are using Texplay's  Image#circle, then yeah, that would be totally impossible in real-time. I think you could have done it in real-time, however, with Window#render_to_texture, drawing white circular images into a black image, then image.clear dest_select :white to make the white bits into "holes" ( render_to_texture uses the screen as a buffer, so only works in RGB). You may have had to increase the pixel size of the lighting though, to get it fast enough, but that is rather moot now, I hope!

Obviously, you can do that a lot more easily with a framebuffer with a stencil of some kind. Shaders would do it too, I think, passing the game texture and a stencil texture. This is what I need to do, but I want to also cast shadows (well, OK, that tutorial is using regular opengl to do it at the polygon level, not shaders on a pixel level, but we need to use shaders, since doing that processing in Ruby would be too slow, I think).
Parent - By Spooner Date 2012-07-11 09:47 Edited 2012-07-11 09:52
I don't know about getpixel. I'll look at the texplay source to see how banister did it and if I can improve on that. One thing I could think of was to be able to pass an array of points to get/set pixel, since then you aren't continually dipping into C and back.

EDIT: Thing is that doing anything like that in Ruby is pointless. My plan is to implement brand new features in Ruby, then port those to C and then maybe add some stuff that we can already do, but would like to do faster, in C.
Parent - - By RunnerPack Date 2012-07-13 23:54
First of all, thank you for doing this! I've been watching this thread since your first post, but I haven't been able to test it until now. It doesn't work for me, but I'm hoping there's a simple work-around.

I have the OpenGL gem you posted about in your "Game of Scones" thread (0.8.0.pre1 x86-mingw32) but I'm getting this error when I try to run the demos:

C:\Ruby\lib\ruby\gems\1.9.1\gems\ashton-0.0.1alpha\examples>shader_image_example.rb
C:/Ruby/lib/ruby/gems/1.9.1/gems/ashton-0.0.1alpha/lib/ashton/base_shader.rb:18:in initialize': undefined method version_supported?' for GL:Module (NoMethodError)
        from C:/Ruby/lib/ruby/gems/1.9.1/gems/ashton-0.0.1alpha/lib/ashton/shader.rb:23:in initialize'
        from C:/Ruby/lib/ruby/gems/1.9.1/gems/ashton-0.0.1alpha/examples/shader_image_example.rb:21:in
new'
        from C:/Ruby/lib/ruby/gems/1.9.1/gems/ashton-0.0.1alpha/examples/shader_image_example.rb:21:in initialize'
        from C:/Ruby/lib/ruby/gems/1.9.1/gems/ashton-0.0.1alpha/examples/shader_image_example.rb:41:in
new'
        from C:/Ruby/lib/ruby/gems/1.9.1/gems/ashton-0.0.1alpha/examples/shader_image_example.rb:41:in `<main>'

Any ideas? I'm really looking forward to seeing this working...
Parent - - By Spooner Date 2012-07-14 00:27
That should just be checking you have OpenGL 2.0+ (absolute minimum needed for shaders). Is there a chance you are loading the wrong 'opengl', such as the ruby-opengl posted on this forum a while back? If you have the ruby-opengl gem installed too, it might be picking the wrong one. In any case, try with
    bundle exec ruby examples/shader_image_example.rb
just to make sure it is running with the correct gem.

You'll be happy to know that shader_image_example.rb is the dullest one :)

This is still very much alpha, of course, so I expect wobbliness - remember that I am very nearly always  in the freenode #gosu IRC channel for moral support.
Parent - - By RunnerPack Date 2012-07-14 17:23
1. ruby-opengl isn't installed.
2. Even the examples that came with the "opengl" gem don't work, so it's probably not Ashton's fault.
3. Ashton seems to build fine, but most of the unit tests fail due to the same undefined method 'version_supported?' for GL:Module error.
4. The "bundle" command gives:
D:\rubydev\gosu\ashton>bundle exec ruby examples/shader_image_example.rb
D:/rubydev/gosu/ashton/lib/ashton/shader.rb:309:in 'link': Shader link error: Fragment info (Ashton::ShaderLinkError)
-------------
(14) : error C5051: profile does not support conditional returns

        from D:/rubydev/gosu/ashton/lib/ashton/shader.rb:56:in 'initialize'
        from examples/shader_image_example.rb:24:in 'new'
        from examples/shader_image_example.rb:24:in 'initialize'
        from examples/shader_image_example.rb:74:in 'new'
        from examples/shader_image_example.rb:74:in '<main>'


It probably doesn't like my old video card. It's an AGP Geforce 6600 GT, and I have to run an older driver to prevent glitchy graphics.

Also, my Ruby environment is in a general state of disrepair. I may be reinstalling windows in the near future (to move to a new PC), so I'll just try again later with a fresh system. I hope I can get it working soon enough to help you tackle some "TODO" items (and solidify some of the wobbliness ;)
Parent - - By Spooner Date 2012-07-14 17:39
Right, the 6600 is _just_ at the cusp of OpenGL 2.0, which is where I'd set my minimum compatibility. Possibly an issue with your drivers.

The problem with my shader code I include is that I have asked them to be run in glsl 1.10 (that is, the version that comes with opengl), which helps me avoid using some newer features, although I'm using OpenGL4.2/glsl4.20. It isn't great at telling me about stuff like the conditional return error you found.

Try the framebuffer_example.rb, since that uses OpenGL, but not shaders, so you might have more luck (try with and without bundle exec please). If the shader gets as far as compiling with bundle exec, that implies that not doing so is loading another opengl gem, since it wouldn't get past version_supported? otherwise.

I'd suggest you report this issue to https://github.com/larskanis/opengl (I _think_ this is where the gem is generated from and is active, unlike the old ruby-opengl by drbrain).
Parent - - By RunnerPack Date 2012-07-14 18:23
D:\rubydev\gosu\ashton>bundle exec ruby examples\framebuffer_example.rb

*** Runs great! No errors and a constant 59/60fps! ***

D:\rubydev\gosu\ashton>examples\framebuffer_example.rb
D:/rubydev/gosu/ashton/lib/ashton/framebuffer.rb:167:in 'create_framebuffer': undefined method 'glGenFramebuffersEXT' for #<Ashton::Framebuffer:0xe88450 @height=600, @width=800> (NoMethodError)
        from D:/rubydev/gosu/ashton/lib/ashton/framebuffer.rb:9:in 'initialize'
        from D:/rubydev/gosu/ashton/examples/framebuffer_example.rb:20:in 'new'
        from D:/rubydev/gosu/ashton/examples/framebuffer_example.rb:20:in 'initialize'
        from D:/rubydev/gosu/ashton/examples/framebuffer_example.rb:51:in 'new'
        from D:/rubydev/gosu/ashton/examples/framebuffer_example.rb:51:in '<main>'

D:\rubydev\gosu\ashton>cd c:\Ruby\lib\ruby\gems\1.9.1\gems\ashton-0.0.1alpha\examples

C:\Ruby\lib\ruby\gems\1.9.1\gems\ashton-0.0.1alpha\examples>framebuffer_example.rb
C:/Ruby/lib/ruby/gems/1.9.1/gems/ashton-0.0.1alpha/lib/ashton/framebuffer.rb:143:in 'init_framebuffer': undefined method 'glGenFramebuffersEXT' for #<Ashton::Framebuffer:0xe98770 @height=600, @width=800> (NoMethodError)
        from C:/Ruby/lib/ruby/gems/1.9.1/gems/ashton-0.0.1alpha/lib/ashton/framebuffer.rb:21:in 'initialize'
        from C:/Ruby/lib/ruby/gems/1.9.1/gems/ashton-0.0.1alpha/examples/framebuffer_example.rb:20:in 'new'
        from C:/Ruby/lib/ruby/gems/1.9.1/gems/ashton-0.0.1alpha/examples/framebuffer_example.rb:20:in 'initialize'
        from C:/Ruby/lib/ruby/gems/1.9.1/gems/ashton-0.0.1alpha/examples/framebuffer_example.rb:49:in 'new'
        from C:/Ruby/lib/ruby/gems/1.9.1/gems/ashton-0.0.1alpha/examples/framebuffer_example.rb:49:in '<main>'


I would report the error, but when the problem is likely due to the age of my machine, I usually just try to modify my system to fix it, rather than trying to get developers to support my ancient and/or broken machine... :P

An example of this is when I hacked my registry to report a newer build date for my video driver to work around a lock-out in the Flash 11 3D hardware acceleration (it works fine, they just want fewer support emails from owners too dumb to update their video drivers).

I still haven't narrowed down the exact version of the nVidia drivers that produces the garbled graphics, but there may be newer drivers I can use. If I ever do find the first non-working version, I will report that to nVidia, since they claim the latest driver supports my card, and it clearly doesn't.
Parent - - By Spooner Date 2012-07-14 18:56 Edited 2012-07-14 19:03
There is obviously something odd going on and yes, I don't think I can reasonably support a card of that age using legacy drivers.

It is my intention, however, to not use anything beyond OpenGL2.0, in order to keep low-spec and older generation cards able to use Ashton - I absolutely can't go back further than that because that is when shaders and framebuffers were first introduced as extensions to the main OpenGL specification (they came into OpenGL officially in 3.0, I think, when they wouldn't need the EXT in their names). I suspect that if you don't use decent drivers, then although you are running OpenGL2.0, you aren't running OpenGL2.0+extensions, but I don't know enough about it to say anything about that.

The main problem is that it is hard to replicate an OpenGL 2.0 card running OpenGL 2.0 compared to my OpenGL 4.2 card running OpenGL2.0. I can fix that issue with 'return' you reported in your previous post though, but I'm not sure whether there won't be more issues still lying around.

EDIT: Actually, framebuffers should require OpenGL1.1. It is shaders that require 2.0. I think Gosu itself relies on 1.1.
Parent - By RunnerPack Date 2012-07-14 20:34 Edited 2012-07-14 21:13
Actually, I used to be able to run jsb's Ruby shader stuff successfully using ruby-opengl, so I don't think it's a card/driver issue. But, if you want to skip adding support for older cards for right now, that's fine. Maybe I can help test/fix stuff once the lib's more mature. Thanks for helping me get the frame-buffer stuff working, at least.

EDIT: I just started fresh with the latest RubyInstaller (1.9.3) and Devkit. I installed Gosu, opengl, and ashton. The frame-buffer example runs fine (without bundler), but the rest of the examples give me this:

c:/Ruby/lib/ruby/gems/1.9.1/gems/ashton-0.0.1alpha/lib/ashton/base_shader.rb:34:in 'glBindFragDataLocationEXT': Extension GL_EXT_gpu_shader4 is not available on this system (NotImplementedError)

The good news is that jsb's shader stuff runs again, so I know I have some shader support. Whether it's enough to support what you want to do is another thing entirely...
Parent - - By Spooner Date 2012-07-14 19:49
The keyword return apparently isn't supported in GLSL1.10 (OpenGL2.0), so I refactored the code to remove them. Problem is I have no idea what other gotchas will jump on me as I make more code.

I need a better way to test... I do have an OpenGL 2.0 graphics card (8400GS), but manually swapping video-cards seems a bit heavy-handed!
Parent - By RunnerPack Date 2012-07-14 20:35
Maybe you could find a cheap system to drop that card into on craigslist.
Parent - By Spooner Date 2012-07-15 17:51
Added several screenshots, from the examples, to the first post. Getting there :)
Parent - - By lol_o2 Date 2014-09-27 11:35
I just installed Ruby 1.9.3 on my laptop, installed Gosu and Ashton and when trying to run Ashton, I get error like: 193: %1 is not a valid Win32 application - from ashton.so What may be the problem? Gosu alone works as intended.
Parent - - By Spooner Date 2014-09-28 00:46
Er...not a clue on that info.
Parent - By lol_o2 Date 2014-09-28 17:13
I downgraded to Ruby 1.9.2 - miracle happened. I think it was problem with my Ruby installation.

And to not make another post: there's a bug in newest version of Ashton - drawing onto Framebuffer is glitched in fullscreen, easy to test in texture_render_example. I'm Win 7 x64.
Parent - By banister Date 2014-11-09 13:20
what's up spooner, ltns
Parent - - By RunnerPack Date 2015-03-19 04:23
Regarding the shadow-casting:

Have you seen this page? https://github.com/mattdesl/lwjgl-basics/wiki/2D-Pixel-Perfect-Shadows

Quote:

"My technique is inspired by Catalin Zima's dynamic lighting, although the process discussed in this article is rather different and requires far fewer passes."

It has code examples and descriptions that should give you some ideas. It's written in Java using LibGDX, but it shouldn't be too hard to translate.

I noticed the "issue" you created for splitting the shadow stuff into a separate gem, so I thought you might want to just start from scratch using this more efficient system.

PS: I'm making some progress on that multitexturing thing you helped me with :D
Parent - - By Spooner Date 2015-03-19 12:48
Sadly, I've stopped trying to make games for Ruby (Unity just opens up so much more). This means that Ashton is very much in minimal maintenance mode. I think the shadows would be nice and I'll merge and release a new version if someone sorts it out, but I doubt I'll bother to spend more time on the shadows, on the off chance I can get out working.
Parent - - By lol_o2 Date 2015-03-19 17:33
Does this mean that Ashton is pretty dead right now? FrameBuffers have "few" bugs that could be fixed... I know I can't demand you to fix all of this, but if you won't work on Ashton anymore, looks like I'll have to learn some C/OpenGL to fix it myself.
Parent - By Spooner Date 2015-03-19 18:50
Sorry, but that is about the size of it.
- - By Spooner Date 2012-07-22 16:27 Edited 2012-07-22 19:32
Tried to implement some shadow-casting lighting effects with Ashton::Lighting::LightSource and Ashton::Lighting::Manager. Sadly, this doesn't work without glitches yet, but it is based on someone else's shader/XNA code and should eventually look like: http://www.youtube.com/watch?v=m0-VW0N57ss

Added some more functionality implemented in C for speed:

    Framebuffer#[x, y]             #=> Get colour (Gosu::Color, which is more Gosu-friendly than Texplay's RGBA float array) from a framebuffer texture
    Framebuffer#transparent?(x, y) #=> true if the colour is entirely transparent. Useful for pixel-perfect collision detection.
    Framebuffer#refresh_cache      #=> Reload the texture data from the graphics card (for example if the framebuffer has been draw to in a #render block).

As can be seen, these operations are orders of magnitude faster than their TexPlay equivalents (for a 1000x1000 image)!

    Framebuffer#refresh_cache  0.204000   0.110000   0.314000 (  0.161133)
    Framebuffer#[]             0.046000   0.000000   0.046000 (  0.045898)
    Framebuffer#transparent?   0.000000   0.000000   0.000000 (  0.000977)

    TexPlay equivalents
    Image#refresh_cache        1.079000   0.453000   1.532000 (  0.780274)
    Image#[]                   0.078000   0.000000   0.078000 (  0.083984)
    Image#[][3] == 0.0         0.109000   0.000000   0.109000 (  0.113281)

I do not intend to implement any special draw commands on the Framebuffer texture data, as TexPlay does with images, since it can be rendered to very easily with Gosu's image/font/draw commands (or directly in OpenGL). This means there will never be a need to sync data (that is, push pixel data to the graphics card).
Parent - By Spooner Date 2012-07-24 14:22 Edited 2012-07-24 14:27
I added Framebuffer#rgba (returns array of Fixnum) and Framebuffer#red/green/blue/alpha. This allows you to get the colour information exactly as efficiently as you require (this will be useful to me for reading data from images processed by shaders).

View benchmarks

Interesting to note that retrieving a 4-element colour array is actually 10x faster if it contains Fixnum (0..255) rather than Float (0.0..1.0). The conclusion is that although a lot of the image processing that TexPlay does is easier using Floats internally (in C), it would have been more efficient to pass integers out to Ruby.
Parent - - By RavensKrag Date 2012-08-05 20:00
"I do not intend to implement any special draw commands on the Framebuffer texture data..."

Does this mean that you're not messing with the internals of Gosu at all, and only interacting through it's interfaces? Could another engine with the same interface as Gosu use Ashton?
Parent - By Spooner Date 2012-08-05 20:25
No, I don't mean that. I mean that I won't offer an Image#circle or Image#splice via Ashton, because you could do that with shaders or just drawing an image in a #render block. This was necessary in TexPlay, because it didn't come with any method to draw directly into an Image (until it added #render_to_image, but that was slow and limited), and was very slow since it performed these tasks in a client-side pixel cache.

Ashton does use client-side pixel caches, but read-only, since they are purely used as a fast way to read pixel data. All writing to images should be done inside a #render block using standard Gosu/OpenGL drawing methods.
- - By lol_o2 Date 2012-07-26 12:31
I forgot to ask sooner: is this possible with some shaders? http://www.libgosu.org/cgi-bin/mwf/topic_show.pl?tid=720
Like rendering specified RGB color value as another, maybe different in each frame.
Parent - By Maverick Date 2012-07-26 15:45
Yep.
Parent - - By Spooner Date 2012-07-26 22:53
Yes, I'm sure it is possible, but changing whole palettes dynamically makes little sense. Are you sure it isn't an old-fashioned way to achieve something that is now easier, faster and smoother with a specific fragment shader, but back in the day the only way to do it was with crude palette changing? What is the actual _effect_ you are trying to achieve? Not how you want to do it, but what is the visual effect you want to be seen by the user?
Parent - - By lol_o2 Date 2012-07-27 08:06
You saw my game, player is in 8 color schemes that has only few color varying. I want to leave only 1 scheme and change it to look like others so I don't need to load >100 images just to change few colors.
Parent - - By Spooner Date 2012-07-27 08:38
Oh, it is the player wearing different suits? Doesn't really make much difference anyway, as long as you aren't changing a huge number of colours at once. You do know you can do this quickly and easily in Texplay already? Would be slightly faster in a shader, but I'm not sure it is worth the extra effort to implement it unless you want to do that yourself.


# The frames of animation for your character. Might want to dup them so that you keep copies of all the different colour schemes after creating them.
@frames.each do |frame|
    # Hash of { old_color => new_color }
   @color_replacements.each_pair do |old_color, new_color|
       frame.clear :color => new_color, :dest_select => old_color, :tolerance => 0.001
   end
end
Parent - - By lol_o2 Date 2012-07-27 09:03
Oh, thanks for this, it seems fast enough. :)
Parent - - By Spooner Date 2012-07-27 09:26
The only real advantage a shader implementation would have over this would be that you could do it in real-time, so you wouldn't need to have 8 versions of the sprites in memory, but I'm sure the memory footprint is the least of your worries :)
Parent - - By lol_o2 Date 2012-07-27 09:42
Maybe it's possible in real-time, because I only need to change 1-2 images that are actually drawn. Image.dup has no sense, because cloning images into memory takes the same time as loading them from file.
Parent - By Spooner Date 2012-07-27 09:47 Edited 2012-07-27 10:02
It really shouldn't be slow (dup that is), but the way Gosu implements it isn't too good at all. Reminds me that I can implement a nearly instantaneous Ashton::Texture#dup :)

EDIT: Yep, at 1022x1022 pixels, Ashton::Texture#dup is over 30 times faster than Gosu::Image#dup (6ms vs 225ms) :P
- By Spooner Date 2012-07-27 09:24
Renamed Ashton::Framebuffer as Ashton::Texture since it is a texture with a framebuffer, not a framebuffer with a texture. If I can, I'll add a framebuffer-based #render to Gosu::Image too.

Added Ashton::SignedDistanceField, which is an absolutely wonderful system to detect collisions against static scenery, lines of sight and many more wonderful things.
- By Spooner Date 2012-08-05 16:40
Well, I've been beating Ashton's ParticleEmitter with a stick and now it is considerably more efficient! From 40FPS for 18k particles in the particles example (when I made the original post in this thread), I've bumped that to 47FPS for a whopping 124k particles. Yay for being a lot more wise in the ways of C and OpenGL! I think that is a lot more reasonable and does mean you can have quite complex particle systems in your Ruby games.

What I haven't done yet, however, is allow for:
* particle animation. You can shrink/grow/rotate/fade out already, just not switch images. Not sure of the best way to do this though (in terms of API, not implementation).
* collision of the particles with scenery (the latter I will use my signed distance field for, so it should be pretty quick). Making the particles bounce rather than simply die on contact may be more than I bother with though :D
* callbacks when particles die (though in anything but a tiny pixel systems, Ruby wouldn't be able to handle this very well at all!).
- - By lol_o2 Date 2012-08-22 20:06
I need a grayscale effect, so could you make next release? Or just give working shader with instructions how to implement in current version.
I can wait, but it's better to see the result while working.
Parent - - By Spooner Date 2012-08-22 21:48
There is already a grayscale shader included in Ashton. Look at examples/shader_image_example.rb to see how to use it. In fact, I'd strongly recommend you look at all the examples, since there is a lot of good stuff in there :)

In fact, you can see the effect in one of the posted screenshots!
Up Topic Gosu / Extending Gosu / Ashton - shaders and framebuffers in Ruby
1 2 Previous Next  

Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill