LWJGL / STB:在IntelliJ中运行与在控制台上运行时不一致

时间:2019-06-30 14:16:19

标签: java intellij-idea lwjgl

在IntelliJ中使用LWJGL和STB TrueType时出现问题。

当我现在尝试创建位图并将所有内容放入Main(下面的“ 代码1 ”)时,一切正常。
一旦我尝试将其拆分创建一个OpenGL上下文(如果我不创建OpenGL上下文而将其拆分也可以正常工作),则加载的字体会由于某种原因损坏,或者该程序因ACCESS_VIOLATION崩溃或在运行时未生成位图。您可以在下面看到损坏的代码,如“ 代码2 ”。

错误的行为虽然仅在通过Intellij Run或Console通过IntelliJ Run使用java 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库,实际上不能以这种方式使用字体吗?

希望您能从任何帮助中了解问题所在并解决此问题。

1 个答案:

答案 0 :(得分:0)

我在LWJGL论坛上提出了问题,并解决了该问题。

  

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

您可以查看帖子here