gen2brain / raylib-go

Go bindings for raylib, a simple and easy-to-use library to enjoy videogames programming.
zlib License
1.53k stars 157 forks source link

Misleading use of color type RGBA. #369

Closed imprity closed 5 months ago

imprity commented 5 months ago

Whether raylib's colors are alpha premultiplied or not is determined by functions like SetBlendMode.

But go's image/color package's color types embed information on whether if it's alpha premultiplied or not.

So I think using image/color's color.RGBA type is misleading since it implies that colors are alpha premultiplied.

I think more honest thing would be to declare and use custom color type with 4 uint8 instead of using go's image/color package's RGBA type.

But maybe it's too late to fix it now....

I wrote some code to demonstrate this problem

package main

import (
    rl "github.com/gen2brain/raylib-go/raylib"
    "image/color"
    "fmt"
)

func main(){
    // declare colors as interfaces
    var red color.Color
    var blue color.Color

    var alphaPremultiplay bool
    var useNRGBA bool

    // set color.NRGBA as their value
    red = color.NRGBA{255, 0, 0, 100} 
    blue = color.NRGBA{0, 0, 255, 100}

    rl.InitWindow(500, 500, "blend-issue")

    for !rl.WindowShouldClose(){
        // press 'a' to toggle blend mode between normal blend and alpha premutiply
        if rl.IsKeyPressed(rl.KeyA){ 
            alphaPremultiplay = !alphaPremultiplay
        }

        // press 'c' to toggle between color.RGBA and color.NRGBA 
        if rl.IsKeyPressed(rl.KeyC){
            useNRGBA = !useNRGBA
        }

        rl.BeginDrawing()

        rl.ClearBackground(color.RGBA{255, 255, 255, 255})

        if alphaPremultiplay{
            //also why doesn't this function accept Blend mode type?
            rl.SetBlendMode(int32(rl.BlendAlphaPremultiply)) 
        }else{
            rl.SetBlendMode(int32(rl.BlendAlpha))
        }

        // use image/color's conversion models to convert color interfaces' colors to desired color model
        redRGBA  := color.RGBAModel.Convert(red).(color.RGBA) 
        blueRGBA := color.RGBAModel.Convert(blue).(color.RGBA) 

        redNRGBA := color.NRGBAModel.Convert(red).(color.NRGBA)
        blueNRGBA := color.NRGBAModel.Convert(blue).(color.NRGBA)

        if useNRGBA{
            rl.DrawRectangle(
                10, 10,
                200, 200,
                color.RGBA(redNRGBA), //forcing it to apccept NRGBA
            )

            rl.DrawCircle(
                160, 150,
                100,
                color.RGBA(blueNRGBA),
            )
        }else{
            rl.DrawRectangle(
                10, 10,
                200, 200,
                redRGBA,
            )

            rl.DrawCircle(
                160, 150,
                100,
                blueRGBA,
            )
        }

        rl.DrawText(
            fmt.Sprintf("[key a] alpha premultiply : %v", alphaPremultiplay),
            10, 300,
            20,
            color.RGBA{0,0,0,255},
        )

        rl.DrawText(
            fmt.Sprintf("[key c] use nrgba color : %v", useNRGBA),
            10, 330,
            20,
            color.RGBA{0,0,0,255},
        )

        rl.EndDrawing()
    }
}
imprity commented 5 months ago

Sorry, I'm dumb and I didn't realize I could just declare something like type RaylibColor = color.RGBA to make it clear this type is intended for raylib.

But then again, if you don't mind, I think doing something like that in raylib-go itself would be a nice way to solve the problem I mentioned above without breaking a backward compatibility : )

imprity commented 5 months ago

Wait, I didn't realize it had it's own color type until 29ba3cc50849d5fd09af003e40bb6870974dab8e ..... Sorry, my bad.