• Dear Cerberus X User!

    As we prepare to transition the forum ownership from Mike to Phil (TripleHead GmbH), we need your explicit consent to transfer your user data in accordance with our amended Terms and Rules in order to be compliant with data protection laws.

    Important: If you accept the amended Terms and Rules, you agree to the transfer of your user data to the future forum owner!

    Please read the new Terms and Rules below, check the box to agree, and click "Accept" to continue enjoying your Cerberus X Forum experience. The deadline for consent is April 5, 2024.

    Do not accept the amended Terms and Rules if you do not wish your personal data to be transferred to the future forum owner!

    Accepting ensures:

    - Continued access to your account with a short break for the actual transfer.

    - Retention of your data under the same terms.

    Without consent:

    - You don't have further access to your forum user account.

    - Your account and personal data will be deleted after April 5, 2024.

    - Public posts remain, but usernames indicating real identity will be anonymized. If you disagree with a fictitious name you have the option to contact us so we can find a name that is acceptable to you.

    We hope to keep you in our community and see you on the forum soon!

    All the best

    Your Cerberus X Team

Implemented [mojo2] DrawPrimitives with vertex color

Holzchopf

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jul 31, 2017
Messages
500
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.
 
These extra functions are such a hack regarding the CX methology. I don't like that.

Why the premultiplying with the alpha value?
 
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.
 
I ment the two that you showed here. Thanks for the info, I guess we have to live with it then.
 
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
 
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?
 
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.
 
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.
 
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?
 
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).
 
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.
 
Back
Top Bottom