Implemented [mojo2] DrawPrimitives with vertex color

Holzchopf

Moderator
Staff member
Joined
Jul 31, 2017
Location
Bern, Switzerland
Hi there

I made a modification to mojo2.graphics / DrawList: I added a DrawPrimitives and a DrawIndexedPrimitives that both take an additional array for individual vertex colours. For the curious, you can find it on GitHub. But the ugly things are, that
  1. vertex colours have to be pre-multiplied
  2. vertex colours are stored in abgr instead of argb
Now for convenience I'm preparing two functions: One that premultiplies and reorders rgb components of a colour and one that does the same for all colours in a vertex colour array.

So far they look like this:
Code:
' Converts pColor from ARGB to ABGR and premultiplies RGB
' Returns ABGR color
' PM stands for pre-multiplied
Function Argb2AbgrPM:Int(pColor:Int)
    Local a:Int, r:Int, g:Int, b:Int
    Local fa:Float
    ' extract color components
    a = (pColor Shr 24) & $ff
    r = (pColor Shr 16) & $ff
    g = (pColor Shr 08) & $ff
    b = (pColor       ) & $ff
    ' premultiply
    fa = Float(a) / 255.0
    r *= fa
    g *= fa
    b *= fa
    ' reorder
    Return (a Shl 24) | (b Shl 16) | (g Shl 08) | r
End

' Converts all colors in pColors from ARGB to ABGR and premultiplies RGB
' PM stans for pre-multiplied
Function Argb2AbgrPM:Void(pColors:Int[])
    For Local i:Int = 0 Until pColors.Length
        pColors[i] = Argb2AbgrPM( pColors[i] )
    Next
End
I think the name shouldn't be a problem. But I don't know where to put them - as functions into mojo2.graphics directly or as methods/functions into one of the classes of mojo2, and if, into which.

What would you prefer? I'm almost (say 51%) satisfied having them as separate functions.
 

MikeHart

Administrator
Staff member
Joined
Jun 19, 2017
Location
Germany
These extra functions are such a hack regarding the CX methology. I don't like that.

Why the premultiplying with the alpha value?
 

Holzchopf

Moderator
Staff member
Joined
Jul 31, 2017
Location
Bern, Switzerland
What do you mean with hacking? Everything was prepared on the side of Mojo2 for this, but the functions allowing to use this functionality were missing. Or do you mean the two I pasted in the code tags? Then I'm 100% on your side :) (or actually :( would fit better).

The premultiplying sucks, I know. I really dislike that. But in my defence, Mojo2 expects everything to be premultiplied - vertex colors, pixels in textures... Usually it's done within the functions in Mojo2 (e.g. SetColor premultiplies rgb with alpha). But I'm not going to include the premultiplying of vertex colours within the drawing functions, because
  1. It's unnecessary to do it every frame when you could prepare it
  2. There are cases where the user just doesn't want to have premultiplicated colours
It's a thing of the devil. But in Whoever-Wrote-Mojo2's defence, the HTML5 target always premultiplies image data. Always. There seem to be "fixes" for that, but none of the workarounds I found in the Webs worked. So to achieve consistency across all platforms/targets, the premultiplication was permanently implemented in Mojo2.

Didn't I read somewhere that you were planning to write your own "Mojo" or graphics modules? I wish you all the luck to find your ways around such insanity.
 

MikeHart

Administrator
Staff member
Joined
Jun 19, 2017
Location
Germany
I ment the two that you showed here. Thanks for the info, I guess we have to live with it then.
 

MikeHart

Administrator
Staff member
Joined
Jun 19, 2017
Location
Germany
Ok, as I have added the lost blendmodes, I think when I merge your request now, I will overwrite them again.
Please push these new drawprimitive methods plus there docs and the premultiplying methods together.
Sorry for the extra work.

About the names, how about...

PreMultiplyARGB2ABGR

PreMultiplyARGB2ABGR
 

Holzchopf

Moderator
Staff member
Joined
Jul 31, 2017
Location
Bern, Switzerland
No worries!

I'd prefer PreMultiplyArgb2Abgr. Not only because I think capitalized abbreviations look better than abbreviations in all-caps, but also because it seems to be the way to go (see OpenUrl, HttpRequest, PushJson, TcpStream and so on).

Still - is adding them as standalone functions acceptable or should they be members of... DrawList, maybe?
 

Raph

New Member
Joined
Aug 25, 2017
Why not hide most of this from users most of the time? The commonly used function should just take colors in the common format. Extra steps should happen behind the scenes rather than manually. Allow people to call into lower level functions if they really need to -- which they rarely will.

Otherwise, the first thing I will do is wrap DrawPrimitives plus these conversion calls into a new call of my own, and always use that.
 

Holzchopf

Moderator
Staff member
Joined
Jul 31, 2017
Location
Bern, Switzerland
Why not hiding it? Well...

The most commonly used functions don't need the color to be passed as one Int and I'd say DrawPrimitives isn't exactly one of the commonly used functions. The only function I could find that is already in Mojo2 and takes the color as one Int, is WritePixels. And this one also needs the conversion to be done manually.

Wrapper functions could be added and would be a nice extra. But honestly, I think the user that is going to use that functionality (drawing primitives with individual vertex colors) is more concerned about the overhead a behind-the-scenes color conversion each time you call the DrawPrimitives function will cause than calling the conversion manually only when needed.
 

Raph

New Member
Joined
Aug 25, 2017
Performance is an excellent argument, for sure. I just hate having yet another color format to keep track of and it being inconsistent across the API. I also wouldn't assume that DrawPrimitives will only be used by advanced users. Once you allow vertex coloring, people will want to use it all the way up to ordinary sprites. The primary audience for Monkey/Cerberus is not low level programmers, after all.

I wonder whether a SetColor-style call where the result is cached until changed would make sense? It'd still incur the cost if you switch colors on every vertex of course, but in that case you could do conversions in advance and call it the way you currently have it.

I presume vertex color is an optional argument defaulting to white?
 

Holzchopf

Moderator
Staff member
Joined
Jul 31, 2017
Location
Bern, Switzerland
I just hate having yet another color format to keep track of and it being inconsistent across the API.
There are currently two color formats visible to the user (or ways to set the color): The one with SetAlpha(a) and SetColor(r,g,b) that take a,r,g,b as floats 0-1, and the one where you pass one int with abgr ordered bytes from 0-255. The latter one isn't an invention by me, so I didn't introduce more inconsistency than there already was =P It seems to be the mojo2 default and internally it's the only format in use (SetAlpha and SetColor auto-convert to abgr, but this only happens once per Set* call, so not that much performance loss).

AFAIK you can tell OpenGL which format to use. But baybe one of the targets doesn't support argb and thus everything had to be abgr, idk.

I'm not quite seeing what you mean by your SetColor-style call for the individual vertex colors =/ Could you explain a bit deeper please? I currently absolutely have no clue how this should work =D

Oh and yeah, vertex colors are optional. If you don't pass them, all vertices will be colored the same (set with SetAlpha and SetColor).
 

Raph

New Member
Joined
Aug 25, 2017
Ah, did WritePixels in mojo2 change to be ABGR? It was ARGB in mojo1. I just checked the docs and it doesn't actually give the format, just says it has to be premultiplied.

As far as a SetColor-style thing, I am not sure either. It was just a random thought. It wouldn't make sense for DrawPrimitives since that's an arbitrary number of verts. Does SetColor use vertex colors behind the scenes right now? I could see a setup whereby there are n color registers, and a SetVertexColors(numVerts, colorArr[]) lets you set them up all at once, and they'd apply to that many verts in the poly... for those who want to do vertex colors with DrawQuad and similar calls.
 
Top Bottom