nDrawExts - Portable drawing extensions for Mojo

Monkey Forums/User Modules/nDrawExts - Portable drawing extensions for Mojo

Nobuyuki(Posted 2013) [#1]

nDrawExts is my first attempt at creating a native Monkey module. It's purpose is to override the SetBlend() function of Mojo in a backwards-compatible way, adding more blending effects to choose from for targets that support them while avoiding the need to hack Mojo to achieve this. It also adds a few new functions, SetLogicOp() and SetAlphaThreshold(), which allow for even more low-level blending effects. The project's available for download here:


As of right now, it only supports the glfw target, but I'm sure it could easily support the ios target, and maybe also android too, if the native code can be made to properly reference the surface context on that target. All of these targets leverage the "state machine" style of OpenGL in one way or another, and should be relatively similar to each other.

I am not very experienced in gl programming, nor C++, so hopefully this code isn't a big mess. Anyone wishing to help extend this module is welcome to do so. Thanks go out to therevills for help acquiring the graphics context on glfw.


Beaker(Posted 2013) [#2]
Nice. Looks useful.

Nobuyuki(Posted 2013) [#3]
Support for the stencil buffer has been added. The following screenshot demonstrates the use of the stencil buffer by drawing a checkerboard in the far background where the bubble is located, behind the monkey:

In order to use the stencil buffer, you must manually clear it just like you would the screen, using ClearStencil(), and explicitly enable it where it should be used. Other than ClearStencil, there are 3 other functions:

EnableStencil() and DisableStencil() signal where the stencil will be applied. Think of them like block keywords for the stencil drawing routine. Anything inside these calls will either be drawn to the stencil buffer, or stencilled according to the existing stencil mask.

DrawToStencil(enabled:Bool) is a switch which is active inside the stenciled part of the render block. To begin drawing to the stencil, call this method with the argument True. All drawing routines are mapped to the stencil, including DrawImage, which is masked using the current alpha threshold (use SetAlphaThreshold before a stencil pass to set this). To stop drawing to the stencil, and to draw the objects you want to have stencilled, you must then call this routine again with the argument False before calling any more draw routines.

Using these in the correct order, it should be able to do multiple render passes, but I haven't tested it like that, so be aware!

If nothing is drawn to the stencil buffer while the stencil buffer is enabled, nothing will be drawn. I hope to add a function which inverts the stencil mask so that more effects are possible (like destructible terrain), but for right now, this functionality covers a large majority of the type of effects most people have been wishing they could do in Monkey.

Shinkiro1(Posted 2013) [#4]
That's so cool :)
But I think something doesn't work for me. Running the example I can always see the checkered background (unlike in your screen above).
Using v66 on OSX 10.8 (in debug and release built).

All the other blending stuff works perfectly.

Nobuyuki(Posted 2013) [#5]
hmm, that shouldn't happen! I'm not quite certain what the problem could be.... Can anyone else here confirm this problem on their systems? I'm running a rather oldish graphics card and maybe I'm not setting the test up correctly when things write to the stencil buffer...

I am going to try adding a few things to see if it fixes the example. Are you able to check out from the source tree? Please check out the latest source (NOT in downloads) and let me know if this fixes your problem?

If you're unable to check out from the source tree, lemme know and I'll get a build up for you.

Raz(Posted 2013) [#6]
This looks like it will be really useful to me, I look forward to giving it a try! Thanks:)

Shinkiro1(Posted 2013) [#7]
Checked out the newest version and it still gives me the same results.

Edit: Using v69 makes no difference.

Nobuyuki(Posted 2013) [#8]

Are you comfortable messing around in the source code? I asked a friend of mine what the problem might be, and it may have to do with differences in how glfw initializes the graphics context on the different platforms. We need a pixel format that includes at least a 1-bit stencil buffer, which apparently is happening on Windows, but maybe not happening on OSX for whatever reason.

Here's a hack you can try to modify the glfw target, which isn't an ideal solution (and something that this project hoped to avoid), but might work. Go to your monkey folder and look for targets\glfw\main.cpp. On line 226, change this:


and recompile a clean build of the example project.

What this does is it changes the initialized graphics context's stencil buffer's bit depth from 0 (ie: GLFW looks for a "sane default") to 8 (GLFW attempts to create an 8-bit stencil buffer). This should work, but I guess some platforms aren't guaranteed to have an 8-bit stencil buffer, or Mark would've set it up differently. All platforms should have support for a stencil buffer, though, so I wouldn't know why sending the argument 0 wouldn't have set this up to begin with.

Anyway, let me know if this works for you. Anyone here using glfw on linux, let me know if the code has problems for you too, and if this hack fixes it!

Nobuyuki(Posted 2013) [#9]
nDrawExts has been updated to support clearing the surface with alpha transparency. This may not be useful in the obvious sense, but is more for working with ReadPixels(). You can use Cls2(r,g,b,a) to clear the surface in a way that allows ReadPixels to work with alpha values.

The matting color of the alpha clear value still counts, unfortunately, so non-solid colors will matte in the direction of the clear color. I'm sure this can be solved with some sort of alpha pre-multiplication junk, or perhaps I'm just not implementing Cls2 correctly, but anyone with any knowledge on the subject, I'm reaching out to you. In the meantime, calling Cls2(128,128,128,0) before drawing seems to matte most things reasonably.

More information on Cls2() here: http://www.monkeycoder.co.nz/Community/posts.php?topic=5272

Raz(Posted 2013) [#10]
About 3-4 months ago I considered GLFW to be the weakest of the targets (mainly because of a slow down bug relating to having a joypad plugged in!), but now it's by far the best for me and extensions like this only add to that further :)