veandco / go-sdl2

SDL2 binding for Go
https://godoc.org/github.com/veandco/go-sdl2
BSD 3-Clause "New" or "Revised" License
2.17k stars 219 forks source link

Alpha blending doesn't work on Windows #471

Open Linus4 opened 3 years ago

Linus4 commented 3 years ago

Description

Rendering a string using the RendererUTF8Blended function from the ttf package ignores the alpha value specified in the sdl.Color after cross-compiling from Linux to Windows. It does, however, work on Linux.

Code example

 func drawString(renderer *sdl.Renderer, text string, color sdl.Color, x, y int32, font *ttf.Font) {                                                                                                                                       
         textSurface, err := font.RenderUTF8Blended(text, color)                                                                                                                                                                           
         if err != nil {                                                                                                                                                                                                                   
                 log.Fatal(err)                                                                                                                                                                                                            
         }                                                                                                                                                                                                                                 
         defer textSurface.Free()                                                                                                                                                                                                          
         textTexture, err := renderer.CreateTextureFromSurface(textSurface)                                                                                                                                                                
         if err != nil {                                                                                                                                                                                                                   
                 log.Fatal(err)                                                                                                                                                                                                            
         }                                                                                                                                                                                                                                 
         defer textTexture.Destroy()                                                                                                                                                                                                       
         textRect := &sdl.Rect{                                                                                                                                                                                                            
                 X: x,                                                                                                                                                                                                                     
                 Y: y,                                                                                                                                                                                                                     
                 W: textSurface.W,                                                                                                                                                                                                         
                 H: textSurface.H,                                                                                                                                                                                                         
         }                                                                                                                                                                                                                                 
         err = renderer.Copy(textTexture, nil, textRect)                                                                                                                                                                                   
         if err != nil {                                                                                                                                                                                                                   
                 log.Fatal(err)                                                                                                                                                                                                            
         }                                                                                                                                                                                                                                 
 }

Library version

v0.4.4

veeableful commented 3 years ago

Hi @Linus4, have you tried setting the texture's blend mode via textTexture.SetBlendMode(sdl.BLENDMODE_BLEND) before copying it onto the renderer surface?

If that doesn't work, could you provide a minimal but complete application code that I can just build? Thanks!

Linus4 commented 3 years ago

Hi @veeableful , I tried out setting the texture's blend mode, but it did not change anything.

Here's a small test-application: alpha-blending-issue-app.zip

main.go

package main

import (
    "fmt"
    "os"

    "github.com/veandco/go-sdl2/sdl"
    "github.com/veandco/go-sdl2/ttf"
)

var (
    colorOpaque      = sdl.Color{45, 135, 45, 255}
    colorTransparent = sdl.Color{45, 135, 45, 125}
)

func main() {
    if len(os.Args) < 2 {
        fmt.Println("You need to provide the path to a ttf font file as argument.")
        return
    }
    err := sdl.Init(sdl.INIT_VIDEO)
    if err != nil {
        panic(err)
    }
    defer sdl.Quit()

    err = ttf.Init()
    if err != nil {
        panic(err)
    }
    defer ttf.Quit()

    font, err := ttf.OpenFont(os.Args[1], 24)
    if err != nil {
        panic(err)
    }
    defer font.Close()

    window, err := sdl.CreateWindow("alpha blending issue", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, 400, 200, sdl.WINDOW_SHOWN)
    if err != nil {
        panic(err)
    }
    defer window.Destroy()

    renderer, err := sdl.CreateRenderer(window, -1, sdl.RENDERER_SOFTWARE)
    if err != nil {
        panic(err)
    }

    drawString(renderer, "Hello", colorOpaque, 50, 50, font)
    drawString(renderer, " World", colorTransparent, 200, 50, font)
    renderer.Present()

    sdl.Delay(5000)
}

func drawString(renderer *sdl.Renderer, text string, color sdl.Color, x, y int32, font *ttf.Font) {
    textSurface, err := font.RenderUTF8Blended(text, color)
    if err != nil {
        panic(err)
    }
    defer textSurface.Free()
    textTexture, err := renderer.CreateTextureFromSurface(textSurface)
    if err != nil {
        panic(err)
    }
    defer textTexture.Destroy()
    textRect := &sdl.Rect{
        X: x,
        Y: y,
        W: textSurface.W,
        H: textSurface.H,
    }
    err = renderer.Copy(textTexture, nil, textRect)
    if err != nil {
        panic(err)
    }
}

This is using go-sdl v0.4.4 and CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc GOOS=windows GOARCH=amd64 go build -tags static -ldflags "-s -w" to cross-compile to Windows.

veeableful commented 3 years ago

Ah I think I might have found the problem. It seems that the included SDL_ttf static library in the repository is on version 2.0.14 which apparently doesn't support alpha component of text color (according to the release note of 2.0.15 here). I'll see if I can update it.

veeableful commented 3 years ago

Hi @Linus4, sorry for the wait! I've been struggling to develop an automated way to update all the static libraries as it was created by another contributor with very different OS setup from mine. As a workaround, I have managed to build static library version of SDL2_ttf for Windows amd64. You can replace the libSDL2_ttf_windows_amd64.a file in $GOPATH/src/github.com/veandco/go-sdl2/.go-sdl2-libs/ with the file on the link here though I think in order to use that, you might be required to not use Go Modules.

Let me know if it works! I will continue to attempt to automate the builds of static libraries.

Linus4 commented 3 years ago

Hi @veeableful , thanks for your help! I'm getting a few errors when I try to build the test application with your version of libSDL2_ttf_windows_amd64.a (without go modules). I think for my main project though, I need to use modules.

# github.com/veandco/go-sdl2/ttf
/usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: ../../veandco/go-sdl2/ttf/../.go-sdl2-libs/libSDL2_ttf_windows_amd64.a(SDL_ttf.o):SDL_ttf.c:(.text+0x21c): undefined reference to `SDL_RWseek'
/usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: ../../veandco/go-sdl2/ttf/../.go-sdl2-libs/libSDL2_ttf_windows_amd64.a(SDL_ttf.o):SDL_ttf.c:(.text+0x248): undefined reference to `SDL_RWread'
/usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: ../../veandco/go-sdl2/ttf/../.go-sdl2-libs/libSDL2_ttf_windows_amd64.a(SDL_ttf.o):SDL_ttf.c:(.text+0x291): undefined reference to `SDL_RWclose'
/usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: ../../veandco/go-sdl2/ttf/../.go-sdl2-libs/libSDL2_ttf_windows_amd64.a(SDL_ttf.o):SDL_ttf.c:(.text+0x2c1): undefined reference to `SDL_RWtell'
/usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: ../../veandco/go-sdl2/ttf/../.go-sdl2-libs/libSDL2_ttf_windows_amd64.a(SDL_ttf.o):SDL_ttf.c:(.text+0x2e7): undefined reference to `SDL_RWclose'
/usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: ../../veandco/go-sdl2/ttf/../.go-sdl2-libs/libSDL2_ttf_windows_amd64.a(SDL_ttf.o):SDL_ttf.c:(.text+0x321): undefined reference to `SDL_RWclose'
/usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: ../../veandco/go-sdl2/ttf/../.go-sdl2-libs/libSDL2_ttf_windows_amd64.a(SDL_ttf.o):SDL_ttf.c:(.text+0x3dd): undefined reference to `SDL_RWsize'
/usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: ../../veandco/go-sdl2/ttf/../.go-sdl2-libs/libSDL2_ttf_windows_amd64.a(SDL_ttf.o):SDL_ttf.c:(.text+0x1dd8): undefined reference to `SDL_RWclose'
collect2: error: ld returned 1 exit status
Linus4 commented 3 years ago

I run Fedora and they provide a package mingw32-SDL2_ttf which is on version 2.0.15. I took the library and used it to compile the test application. It worked and alpha blending worked on windows, too. (I can't build my project like this, though. (modules))

veeableful commented 3 years ago

Hi @Linus4, thanks for working it out and providing me the solution! Did you copy just libSDL2_ttf.dll.a file, replace .go-sdl2-libs/libSDL2_ttf_windows_386.a, and ran CGO_ENABLED=1 CC=i686-w64-mingw32-gcc GOOS=windows GOARCH=386 go build -tags static -ldflags "-s -w"? I tried that but it doesn't seem to run on my Windows VM.

If this method works, I'll update the libraries with the libraries from the Fedora packages at least for the Windows ones and bump up the version so you can use it immediately.

Linus4 commented 3 years ago

Hi @veeableful , this is what I did: sudo cp /usr/x86_64-w64-mingw32/lib/libSDL2_ttf.a $GOPATH/src/github.com/veandco/go-sdl2/.go-sdl2-libs/libSDL2_ttf_windows_amd64.a, (removed go.mod and go.sum) and then CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc GOOS=windows GOARCH=amd64 go build -tags static -ldflags "-s -w".

I'm not 100% sure the file libSDL2_ttf_windows_amd64.a comes from the mingw32-SDL2_ttf package, though. I also have these packages installed: SDL2_ttf-2.0.15-2.fc30.x86_64 and SDL2_ttf-devel-2.0.15-2.fc30.x86_64.

If this method works, I'll update the libraries with the libraries from the Fedora packages at least for the Windows ones and bump up the version so you can use it immediately.

That would be fantastic! If it works, that is :P

veeableful commented 3 years ago

Hi @Linus4, I couldn't find the file /usr/x86_64-w64-mingw32/lib/libSDL2_ttf.a even after I installed the three packages mingw32-SDL2_ttf, SDL2_ttf, and SDL2_ttf-devel. Did you compile and install SDL2_ttf yourself using the MinGW compiler?

Since I couldn't make it work with the Fedora package, I tried another way which is to download from MSys. It worked for me but I'm afraid that it might not work for you. Could you try copying the library there into .go-sdl2-libs again and recompile to run on your Windows 10? If it works for you as well, then I'll use this one!

Many thanks in advance!

Linus4 commented 3 years ago

Hi @veeableful , now that you say it, I probably did compile and install SDL2_ttf myself, but I forgot because this was more than a year ago. :P It worked with the library from MSys. :tada: I moved libSDL2_ttf.a to .../.go-sdl2-libs/libSDL2_ttf_windows_amd64.a and built the app like I did before.

veeableful commented 3 years ago

Hi @Linus4, thanks for trying the MSys packages out! I have updated the Windows SDL2_ttf libraries but decided not to increment the version since we can just use the commit (e.g. go get -u -v github.com/veandco/go-sdl2/sdl@e1e6fdd) and this update is somewhat different from normal procedure so I don't want to risk it just yet. So if you don't mind, could you use the commit as the version for now? I will eventually update the version once I'm sure they all are updated and work (which might take some time :sweat_smile:).

Linus4 commented 3 years ago

Hi @veeableful , I've tried it with the command you posted and everything worked perfectly! Using the commit as the version is fine. Better don't rush anything ;) Thank you! :partying_face:

veeableful commented 3 years ago

Yay, I'm glad that it works! And you're welcome 😃