libgdx 透明覆盖层

4

我正在使用libgdx编写一个使用OpenGL的JWindow类型UI。不知何故,即使启用了GL20.GL_BLEND,我的应用程序仍然具有黑色背景。

以下是我的代码:

package com.mygdx.game;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.viewport.FitViewport;

public class MyGdxGame extends ApplicationAdapter {

    Stage stage;
    SpriteBatch batch;
    ShapeRenderer shapeRenderer;

    @Override
    public void create() {
        stage = new Stage(new FitViewport(2560, 1440));
        batch = new SpriteBatch();
        shapeRenderer = new ShapeRenderer();
        shapeRenderer.setAutoShapeType(true);
    }

    @Override
    public void render() {
        Gdx.gl.glEnable(GL20.GL_BLEND);
        Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);

        Gdx.gl.glClearColor(0, 0, 0, .25f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);



        batch.begin();
        shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
        shapeRenderer.setColor(Color.RED);
        shapeRenderer.rect(100, 25, 200, 450);

        shapeRenderer.set(ShapeRenderer.ShapeType.Filled);
        shapeRenderer.setColor(Color.GREEN);
        shapeRenderer.rect(303, 24, 10, 451);
        shapeRenderer.end();
        batch.end();

        Gdx.gl.glDisable(GL20.GL_BLEND);
    }

    @Override
    public void resize(int width, int height) {
        stage.getViewport().update(width, height, true);
    }

    @Override
    public void dispose() {
        stage.dispose();
        batch.dispose();
        shapeRenderer.dispose();
    }

}

我发现有人在C语言中问了同样的问题(如何制作带透明背景的OpenGL渲染上下文?)。我甚至试过将LwglAWTCanvas添加到JWindow中,但仍无法使背景透明。
我想要一个清晰的背景,这样我就可以在用户屏幕上绘制矩形/形状。
谢谢!

这并不是一个重复的问题,因为它并非以母语形式提出。 - Jonathan Beaudoin
这就是我想指出的。在Java中没有答案,请参见此处 - pleluron
@pleluron 请看下面我的回答。我能够使用JNA使这成为可能。 - Jonathan Beaudoin
1个回答

4

我使用JNA在Windows上成功实现了这个。

import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.badlogic.gdx.graphics.Color;
import com.mygdx.game.CharlatanoOverlay;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinUser;

import static com.sun.jna.platform.win32.WinUser.*;

public class DesktopLauncher {

    public static final WinDef.DWORD DWM_BB_ENABLE = new WinDef.DWORD(0x00000001);
    public static final WinDef.DWORD DWM_BB_BLURREGION = new WinDef.DWORD(0x00000002);
    public static final WinDef.DWORD DWM_BB_TRANSITIONONMAXIMIZED = new WinDef.DWORD(0x00000004);

    public static final WinDef.HWND HWND_TOPPOS = new WinDef.HWND(new Pointer(-1));

    private static final int SWP_NOSIZE = 0x0001;
    private static final int SWP_NOMOVE = 0x0002;

    private static final int WS_EX_TOOLWINDOW = 0x00000080;
    private static final int WS_EX_APPWINDOW  = 0x00040000;

    public static void main(String[] arg) {
        LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
        System.setProperty("org.lwjgl.opengl.Window.undecorated", "true");
        cfg.width = LwjglApplicationConfiguration.getDesktopDisplayMode().width-1;
        cfg.height = LwjglApplicationConfiguration.getDesktopDisplayMode().height-1;
        cfg.resizable = false;
        cfg.fullscreen = false;
        cfg.initialBackgroundColor = new Color(0, 0, 0, 0);

        new LwjglApplication(new CharlatanoOverlay(), cfg);

        WinDef.HWND hwnd;
        while ((hwnd = User32.INSTANCE.FindWindow(null, "CharlatanoOverlay")) == null) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(hwnd);
        System.out.println(transparentWindow(hwnd));
    }

    public static boolean transparentWindow(WinDef.HWND hwnd) {
        DWM_BLURBEHIND bb = new DWM_BLURBEHIND();
        bb.dwFlags = DWM_BB_ENABLE;
        bb.fEnable = true;
        bb.hRgnBlur = null;
        DWM.DwmEnableBlurBehindWindow(hwnd, bb);

        int wl = User32.INSTANCE.GetWindowLong(hwnd, WinUser.GWL_EXSTYLE);
        wl = wl | WinUser.WS_EX_LAYERED | WinUser.WS_EX_TRANSPARENT;
        User32.INSTANCE.SetWindowLong(hwnd, WinUser.GWL_EXSTYLE, wl);

        wl &= ~(WS_VISIBLE);

        wl |= WS_EX_TOOLWINDOW;   // flags don't work - windows remains in taskbar
        wl &= ~(WS_EX_APPWINDOW);

        User32.INSTANCE.ShowWindow(hwnd, SW_HIDE); // hide the window
        User32.INSTANCE.SetWindowLong(hwnd, GWL_STYLE, wl); // set the style
        User32.INSTANCE.ShowWindow(hwnd, SW_SHOW); // show the window for the new style to come into effect
        User32.INSTANCE.SetWindowLong(hwnd, WinUser.GWL_EXSTYLE, wl);

        return User32.INSTANCE.SetWindowPos(hwnd, HWND_TOPPOS, 0, 0, 2560, 1440, SWP_NOMOVE | SWP_NOSIZE);
    }
}

DWM:

import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;

public class DWM {

    static {
        Native.register("Dwmapi");
    }

    public static native WinNT.HRESULT DwmEnableBlurBehindWindow(WinDef.HWND hWnd, DWM_BLURBEHIND pBlurBehind);

}

DWM_BLURBEHIND:

import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef;

import java.util.Arrays;
import java.util.List;

public class DWM_BLURBEHIND extends Structure {

    public WinDef.DWORD dwFlags;
    public boolean  fEnable;
    public WinDef.HRGN hRgnBlur;
    public boolean  fTransitionOnMaximized;

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("dwFlags", "fEnable", "hRgnBlur", "fTransitionOnMaximized");
    }

}

干得好,我不知道这是可能的。看起来我们也可以通过jna访问xlib,以提供一个便携式的解决方案。 - pleluron
@pleluron 正在进行这项工作。为libgdx拥有一个跨平台的JWindow类型OpenGL画布将是非常棒的。 :D - Jonathan Beaudoin
@jonathan-beaudoin 你在Linux上是否已经搞定了这个问题?很希望能够实现这种跨平台效果! - PureSpider

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接