go-sdl2 icon indicating copy to clipboard operation
go-sdl2 copied to clipboard

Alpha blending doesn't work on Windows

Open Linus4 opened this issue 5 years ago • 13 comments

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

Linus4 avatar Aug 01 '20 00:08 Linus4

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!

veeableful avatar Aug 03 '20 06:08 veeableful

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.

Linus4 avatar Aug 03 '20 12:08 Linus4

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 avatar Aug 04 '20 10:08 veeableful

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.

veeableful avatar Aug 09 '20 09:08 veeableful

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 avatar Aug 11 '20 18:08 Linus4

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))

Linus4 avatar Aug 12 '20 03:08 Linus4

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.

veeableful avatar Aug 12 '20 07:08 veeableful

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

Linus4 avatar Aug 12 '20 08:08 Linus4

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!

veeableful avatar Aug 13 '20 07:08 veeableful

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.

Linus4 avatar Aug 13 '20 14:08 Linus4

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:).

veeableful avatar Aug 14 '20 08:08 veeableful

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:

Linus4 avatar Aug 14 '20 11:08 Linus4

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

veeableful avatar Aug 15 '20 05:08 veeableful