• 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

Snippet How to use Blendmode to replace shaders

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,414
Blendmodes are powerful, and often you can use this inbuilt power to save other resources. This also avoids techniques such as stencilbuffers, and it adds the possibility to mask using soft 0-255 level alpha.

Here's how you can use it to mask graphics.
Cerberus:
Import Mojo2

Function Main()
    New Game
    Return 0
End  

Class Game Extends App

    Field canvas:Canvas, sprite:Image[8]

    Method OnCreate ()
        canvas = New Canvas() ; SetSwapInterval 1 ; SetUpdateRate 0
        sprite[0] = New Image(64,64,.0,.0,0)
        Return 0
    End
   
    Method OnRender : Int()
   
        ' Draw the background
        canvas.Clear
        canvas.SetColor 0,0,1 ; canvas.DrawRect 0,0,640,480
          canvas.SetColor 1,1,1 ; canvas.DrawLine 0,0,180,180 ; canvas.DrawLine 180-0,180-10,180,180 ; canvas.DrawLine 180-10,180-0,180,180
           canvas.SetColor 1,0,0 ; canvas.DrawRect Millisecs()/10 Mod 640,220,20,20
           ' ------------------------------------------------------------------------------
        ' Mask (draw inside a 64x64 sprite)
        canvas.SetRenderTarget sprite[0]    ' Set sprite as active canvas...
           canvas.Clear 0,0,0,0                ' ...and clear it
        canvas.SetBlendMode BlendMode.Alpha ; canvas.SetColor 0,1,0,1 ; canvas.DrawOval MouseX()-225,MouseY()-225,50,50 ' Draw something
        canvas.SetBlendMode BlendMode.Multiply2 ; canvas.SetColor 0,0,0,0 ; canvas.DrawOval 20,20,10,10                      ' Draw something, this will mask a hole in the above
        canvas.SetBlendMode BlendMode.Alpha ; canvas.SetColor 1,1,1,1 ' We need to reset canvas properties even if we changed them while it was directed to sprite
        canvas.SetRenderTarget Null ' Set canvas to be main canvas once again
         ' ------------------------------------------------------------------------------
       
         canvas.DrawImage sprite[0],200,200 ' Now draw that sprite on the canvas, this will be the foreground.
       
          canvas.Flush
        Return 0      
    End
End
 
Interesting... never really understood how to use SetBlendMode before. sure this will be helpful. tnks(y)(y)
 
Glad you like it.

I'm investigating a lot of other things as well using the standard blendmodes
for instance opaque2 seem to be perfect to create (together with SetColor with some clever math) what is called
"order independent transparency".
 
Do you know a simple way to make my colored button become grayscale?
I want to turn the disable button to dark gray the easy way without using another image
 
Shader is one possibility of course, I wrote this quickly for you.
I include the sourcecode as a zip.
 

Attachments

  • simple.zip
    14.8 KB · Views: 59
Code:
uniform sampler2D ColorTexture;

void shader(){
    vec2 uv=(b3d_ClipPosition.st/b3d_ClipPosition.w)*0.5+0.5;
    vec4 c = texture2D(ColorTexture, uv);

    // Biological average
    float gray = ( (c.r*0.299) + (c.g*0.587) + (c.b*0.114) ) / 3.0;
    vec4 fragColor = vec4(gray,gray,gray, c.a);

    b3d_FragColor = fragColor ;
}
Code:
Import mojo2
Function Main()
    New MyApp
End

Class MyApp Extends App

    Field src : Image,dst : Image,canvas : Canvas,effect : ShaderEffect

    Method OnCreate()
        canvas = New Canvas ; SetUpdateRate 0
        src = Image.Load("graphics.png",0,0,0)
        dst = New Image(src.Width,src.Height,0,0)
        effect = New ShaderEffect
    End

    Method OnRender()
        canvas.Clear
        effect.Render src,dst
        canvas.DrawImage src,0,0
        canvas.DrawImage dst,0,64
        canvas.Flush
    End
End

Class myShader Extends Shader
    Global _i:myShader
    Method New()
        Build(LoadString("shader.glsl"))
    End
    Method OnInitMaterial:Void(material:Material)
        material.SetTexture "ColorTexture",Texture.White()
    End
    Function Instance:myShader()
        If Not _i _i=New myShader
        Return _i
    End
End

Class ShaderEffect
    Global _c:Canvas
    Field _m:Material
    Method New()
        If Not _c _c=New Canvas
        _m=New Material( myShader.Instance() )
    End
    Method Render:Void(src:Image,dst:Image)
        _m.SetTexture "ColorTexture",src.Material.ColorTexture
        _c.Clear 0,0,0,0
        _c.SetRenderTarget dst
        _c.SetViewport 0,0,dst.Width,dst.Height
        _c.SetProjection2d 0,dst.Width,0,dst.Height
        _c.DrawRect 0,0,dst.Width,dst.Height,_m
        _c.Flush
    End
End
 
As you can see, the bad thing about shaders is that you need to have another image of the exact same size as the one you want to draw.

(dst = New Image(src.Width,src.Height,0,0 here)

But of course that's not a usually a problem with todays memory. You can just use a sprite sheet of 256x256 or whatever size you want and clone the image. Speedwise shaders are amazing so it's all about being okay with the extra destination image (you can only read from ONE texture and write to ONE texture in shaders, you can never read AND write to the same).

Note that you don't have to run the shader live in case you don't want to.
It's just a process that reads pixels and writes pixels. It's not that you don't have time to run it every frame, they are cheap. But
running a million of them might be slow so it's good to know that you dont' have to.

This shows how you can also process only once, and be happy:

Code:
    Method OnRender()
        canvas.Clear
        If MouseDown(0) Then effect.Render src,dst
        canvas.DrawImage src,0,0
        canvas.DrawImage dst,0,64
        canvas.Flush
    End
 
Last edited:
I wrote this quickly for you
Thank you. It working great.

It takes quite a lot of steps to accomplish that. But I understand the freedom that comes with it.

By the way, looking at your code.
Code:
_c.DrawRect 0,0,dst.Width,dst.Height,_m
I never knew we could do other than flat color to DrawRect(). Using material...interesting. (y):).
I wish someone could improve our docs. The Mojo2 docs is definitely not for beginners.
dov.jpg
 
That command is the most important command graphical-wise in Cerberus

DrawRect, it is actually slightly faster than drawimage (just a 2% or so). but that's not the point you use it for sprite sheets (texture atlas you used to call it). So start using it :) It's a great habit even for simpler images.

And you never waste any shader power on the whole sheet bec it only process what you actually draw. You can draw 1x1 pixel out of a 4096x4096 sheet al day long.

I don't have too much traffic until 1st May now so, but I hope this is enough to get you going. Love your work with the GUI!
 
  • Wow
Reactions: mag
Regarding the docs I agree but I know they work hard on fixing that so I think when that is done things will be so much better.

There's 1000's of commands listed, but even on a professional level so to speak you only use 10 commands or so.
The docs can frighten, it did to me at least and It begs for alot of questions all the time.
When it actually is all very simple.

Hardware efficiency meets simple syntax if you do it right!
 
  • Like
Reactions: mag
It's actually quiet short and sweet if you put away the standard shader code in an imported module, so what I usually do is something like this.


StructuredCode.png
 

Attachments

  • Gray.zip
    15.9 KB · Views: 69
Thank you. That is short and clear.
 
I know they work hard on fixing that so I think when that is done things will be so much better.
Agreed! It is difficult already to maintain something that is free. Even if people contribute the code, still team needs to check the code etc. It is really time-consuming. So I respect that and thank you.

Mojo 2 things that make me wonder..
  • What is Material in general, and its role?
  • What is the difference between Material & Texture?
And many other things like Lighting and ShadowShader, etc., are confusing. I suspect it is not specific to CerberusX but common practice in graphic languages nowaday. So that info is probably some other place on the net. I found some info like Shader and so on, But really.. it's quite difficult for me to connect back to CX. And yes some are quite easy to figure out.
 
Lightning and Shadow I think are just some simple shaders that they had the idea to include.
They made their own version of a fixed pipeline using shader, I'm not sure. I guess they wanted *some* kind of lightning included, it feels very ad lib but I'm still impressed.
But ya It feels like one of those features that you either don't understand or you will roll your own routines anyway.

The difference between Material and Texture and Images are still a questionmark to me. I settled to forget everything about textures and materials. Images = Textures = Materials in my world.
I had a hard time to differentiate between images and canvases even at the beginning.
 
The difference between Material and Texture and Images are still a questionmark to me. I settled to forget everything about textures and materials. Images = Textures = Materials in my world.
In simple cases you can see them as equivalent as they are used to draw a graphic on the screen. But I try to give a simplified explanation of the differences.
- The texture is the graphic data itself. Its basically the red green blue and alpha values of all pixels in a picture
- The material uses the graphic data of the texture and adds some effects (tinting, lighting, shadows ...) to it using a small program called shader.
- The image is the geometrical frame so to speak to show the material (graphic data with added effects). Most often it is a rectangle made of two triangles that can be transformed in multiple ways.
To get back to the beginning: As long as you take the (rectangular) graphic data, avoid any special effects except connecting the graphic data to the geometry of the image and don't mess around with that geometry you end up with texture, material and image all being visually the same.
 
  • Like
Reactions: mag
Back
Top Bottom