【问题标题】:LWJGL / STB: Inconsistency when running in IntelliJ vs. running over ConsoleLWJGL / STB:在 IntelliJ 中运行与在控制台上运行时的不一致
【发布时间】:2019-06-30 14:16:19
【问题描述】:

在 IntelliJ 中使用 LWJGL 和 STB TrueType 时遇到问题。

当我现在尝试创建位图并将所有内容放入 Main(下面的“代码 1”)时,一切正常。
一旦我尝试拆分它创建一个OpenGL上下文(如果我拆分它而不创建OpenGL上下文它也可以正常工作),加载的字体得到以某种方式损坏,程序要么因 ACCESS_VIOLATION 而崩溃,要么在不生成位图的情况下运行。您可以在下面看到损坏的代码为“代码 2”。

错误行为仅在使用 IntelliJ 使用的 java 运行参数运行时发生 - 无论是通过 Intellij Run 还是通过控制台。
构建到 JAR 并运行它时不会发生这种情况。

有问题的论点如下。如果控制台中缺少这个,它会运行。

-javaagent:\lib\idea_rt.jar=52850:\bin

我已阅读 here,认为 idea_rt.jar 文件“需要提供正常的关闭/退出/堆栈跟踪功能”,因此我不想在 IntelliJ 中禁用它。


注意:在损坏的代码(下面的“代码 2”)中,您会注意到一个“不必要的”行
ByteBuffer data2 = loadByteBufferFromResource("/fonts/arial.ttf");,它模拟加载多种字体。如果我只加载一种字体,一切正常。
您还会注意到代码 2 中的 OpenGL 上下文创建,这似乎也是导致问题的原因(如上所述)


代码 1(有效)

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL;
import org.lwjgl.stb.STBTTFontinfo;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;

import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.glfw.GLFW.glfwDefaultWindowHints;
import static org.lwjgl.glfw.GLFW.glfwInit;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.stb.STBTruetype.stbtt_GetCodepointBitmap;
import static org.lwjgl.stb.STBTruetype.stbtt_InitFont;


public class STBTTExampleOnlyMain {
    private static ByteBuffer loadByteBufferFromResource(String resource) throws IOException {
        try(InputStream stream = STBTTExampleOnlyMain .class.getResourceAsStream(resource)) {
            byte[] bytes = stream.readAllBytes();

            ByteBuffer buffer = BufferUtils.createByteBuffer(bytes.length);
            buffer.put(bytes);
            buffer.flip();

            return buffer;
        }
    }

    public static void main(String[] args) throws IOException {
        ByteBuffer data = loadByteBufferFromResource("/fonts/arial.ttf");
        ByteBuffer data2 = loadByteBufferFromResource("/fonts/arial.ttf");

        STBTTFontinfo font = STBTTFontinfo.create();
        stbtt_InitFont(font, data);

        IntBuffer bufWidth = BufferUtils.createIntBuffer(1);
        IntBuffer bufHeight = BufferUtils.createIntBuffer(1);
        ByteBuffer bitmap = stbtt_GetCodepointBitmap(font, 0, 1, 'a', bufWidth, bufHeight, null, null);

        System.out.println(bitmap);
    }
}


代码 2(损坏)

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL;
import org.lwjgl.stb.STBTTFontinfo;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;

import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.glfw.GLFW.glfwDefaultWindowHints;
import static org.lwjgl.glfw.GLFW.glfwInit;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.stb.STBTruetype.stbtt_GetCodepointBitmap;
import static org.lwjgl.stb.STBTruetype.stbtt_InitFont;


public class STBTTExample {
    private static final Map<Integer, STBTTFontinfo> fontMap = new HashMap<>();

    private static ByteBuffer loadByteBufferFromResource(String resource) throws IOException {
        try(InputStream stream = STBTTExample.class.getResourceAsStream(resource)) {
            byte[] bytes = stream.readAllBytes();

            ByteBuffer buffer = BufferUtils.createByteBuffer(bytes.length);
            buffer.put(bytes);
            buffer.flip();

            return buffer;
        }
    }

    private static void initFont() throws IOException {
        ByteBuffer data = loadByteBufferFromResource("/fonts/arial.ttf");
        ByteBuffer data2 = loadByteBufferFromResource("/fonts/arial.ttf");

        STBTTFontinfo font = STBTTFontinfo.create();
        stbtt_InitFont(font, data);

        fontMap.put(0, font);
    }

    public static void main(String[] args) throws IOException {
        initFont();

        glfwInit();
        glfwDefaultWindowHints();
        long windowHandle = glfwCreateWindow(800, 600, "Test", 0, 0);
        glfwMakeContextCurrent(windowHandle);
        GL.createCapabilities();

        IntBuffer bufWidth = BufferUtils.createIntBuffer(1);
        IntBuffer bufHeight = BufferUtils.createIntBuffer(1);
        ByteBuffer bitmap = stbtt_GetCodepointBitmap(fontMap.get(0), 0, 1, 'a', bufWidth, bufHeight, null, null);

        System.out.println(bitmap);
    }
}


使用文本渲染时,如何解决 IntelliJ 无法运行程序的问题?

我可能误解了 STBTT 库,实际上不能以这种方式使用字体吗?

我们将不胜感激任何帮助以了解问题所在并解决此问题。

【问题讨论】:

  • 可能是您从终端和GUI应用程序调用时操作系统环境不同。
  • @Andrey 我认为提供的代码就足够了。回到家后,我将创建一个包含所有内容的新存储库,并编辑我的问题以链接到它。
  • @LBPFR34K 他们的请求实际上不是为了more代码——而是为了less。请尝试自行缩小问题的大致范围,然后仅发布那部分代码。如果您对如何执行此操作有任何疑问,请参阅我们关于创建Minimal, Complete, and Verifiable Example 的文章。
  • @IronFlare 我实际上理解他们的问题是这不是直接可重现,因为缺少库。但我现在明白了:) 与此同时,我能够制作一个更小的例子,并且刚刚更新了我的问题来描述这个问题。如果您再看一眼,那就太棒了:)

标签: java intellij-idea lwjgl


【解决方案1】:

我已经在 LWJGL 论坛中提出了这个问题并得到了解决。

STBTTFontinfo 对象仅包含元数据。实际字体数据不会从您传递给 stbtt_InitFont 的 ByteBuffer 中复制。仅复制其内存地址,并在必要时通过该指针访问字体数据。您看到的段错误发生是因为您没有在任何地方存储对 ByteBuffer 的引用,它在您尝试使用字体时被 GCed/deallocated。一个简单的解决方法是将您的 Font 类更改为也存储 ByteBuffer。

你可以看帖子here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    • 2016-07-08
    相关资源
    最近更新 更多