LWJGL3ライブラリーは、STB TrueTypeおよびSean Barrettによって作製されたライブラリーへの結合を含む。私が代わりに使用するために... ...stbtt_PackFontRangeからstbtt_PackFontRangesに切り替えるにはどうすれば間違っているのでしょうか?
stbtt_PackFontRange(pc, ttf, 0, 16, 32, chardata);
を使用してからオーバーサンプリングデモでコードを変換したいというライブラリを理解し、使用するためには
...
STBTTPackRange.Buffer packRanges = STBTTPackRange.malloc(1);
packRanges.put(STBTTPackRange.malloc().set(16, 32, null, 96, chardata));
...
stbtt_PackFontRanges(pc, ttf, 0, packRanges);
...空のテクスチャを生成します。
ドキュメントを読んでstbリポジトリとlwjglリポジトリの例を見ることで私が集めることができる理解から、私がやっていることはうまくいくはずですが、そうではありません。
私はstbtt_PackFontRange(...)
メソッドを使用してstbtt_PackFontRanges(...)
メソッドを使用して切り替えた時点まで、元の〜1行から一度に以下のクラスを変更しました。
コンテキストの完全load_fonts()
方法:
private void load_fonts() {
font_tex = glGenTextures();
chardata = STBTTPackedchar.malloc(96);
chardataIndices = new HashMap<>();
for(int i = 0 ; i < chardata.remaining() ; i++) {
chardataIndices.put(i + 32, i);
}
STBTTPackRange.Buffer packRanges = STBTTPackRange.malloc(1);
packRanges.put(STBTTPackRange.malloc().set(16, 32, null, 96, chardata));
try (STBTTPackContext pc = STBTTPackContext.malloc()) {
ByteBuffer ttf = ioResourceToByteBuffer("demo/monof55.ttf", 512 * 1024);
ByteBuffer bitmap = BufferUtils.createByteBuffer(BITMAP_W * BITMAP_H);
stbtt_PackBegin(pc, bitmap, BITMAP_W, BITMAP_H, 0, 1, NULL);
stbtt_PackSetOversampling(pc, 1, 1);
//below method works
stbtt_PackFontRange(pc, ttf, 0, 16, 32, chardata);
//below method works not
//stbtt_PackFontRanges(pc, ttf, 0, packRanges);
stbtt_PackEnd(pc);
glBindTexture(GL_TEXTURE_2D, font_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_W, BITMAP_H, 0, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
完全修飾TruetypeOversample
クラス、最も簡単lwjgl3 repoをクローニングし、同じ名前のクラスを置換することによって実行することができます
/*
* Copyright LWJGL. All rights reserved.
* License terms: https://www.lwjgl.org/license
*/
package org.lwjgl.demo.stb;
import static org.lwjgl.demo.glfw.GLFWUtil.glfwInvoke;
import static org.lwjgl.demo.util.IOUtil.ioResourceToByteBuffer;
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.GLFW_FALSE;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_B;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_ESCAPE;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_V;
import static org.lwjgl.glfw.GLFW.GLFW_RELEASE;
import static org.lwjgl.glfw.GLFW.GLFW_RESIZABLE;
import static org.lwjgl.glfw.GLFW.GLFW_TRUE;
import static org.lwjgl.glfw.GLFW.GLFW_VISIBLE;
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.glfw.GLFW.glfwDefaultWindowHints;
import static org.lwjgl.glfw.GLFW.glfwGetPrimaryMonitor;
import static org.lwjgl.glfw.GLFW.glfwGetVideoMode;
import static org.lwjgl.glfw.GLFW.glfwInit;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.glfw.GLFW.glfwPollEvents;
import static org.lwjgl.glfw.GLFW.glfwSetErrorCallback;
import static org.lwjgl.glfw.GLFW.glfwSetFramebufferSizeCallback;
import static org.lwjgl.glfw.GLFW.glfwSetKeyCallback;
import static org.lwjgl.glfw.GLFW.glfwSetWindowPos;
import static org.lwjgl.glfw.GLFW.glfwSetWindowShouldClose;
import static org.lwjgl.glfw.GLFW.glfwSetWindowSizeCallback;
import static org.lwjgl.glfw.GLFW.glfwShowWindow;
import static org.lwjgl.glfw.GLFW.glfwSwapBuffers;
import static org.lwjgl.glfw.GLFW.glfwSwapInterval;
import static org.lwjgl.glfw.GLFW.glfwTerminate;
import static org.lwjgl.glfw.GLFW.glfwWindowHint;
import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;
import static org.lwjgl.opengl.GL11.GL_ALPHA;
import static org.lwjgl.opengl.GL11.GL_BLEND;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_CULL_FACE;
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
import static org.lwjgl.opengl.GL11.GL_LIGHTING;
import static org.lwjgl.opengl.GL11.GL_LINEAR;
import static org.lwjgl.opengl.GL11.GL_MODELVIEW;
import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA;
import static org.lwjgl.opengl.GL11.GL_PROJECTION;
import static org.lwjgl.opengl.GL11.GL_QUADS;
import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER;
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL11.glBlendFunc;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glClearColor;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glDisable;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glGenTextures;
import static org.lwjgl.opengl.GL11.glLoadIdentity;
import static org.lwjgl.opengl.GL11.glMatrixMode;
import static org.lwjgl.opengl.GL11.glOrtho;
import static org.lwjgl.opengl.GL11.glTexCoord2f;
import static org.lwjgl.opengl.GL11.glTexImage2D;
import static org.lwjgl.opengl.GL11.glTexParameteri;
import static org.lwjgl.opengl.GL11.glTranslatef;
import static org.lwjgl.opengl.GL11.glVertex2f;
import static org.lwjgl.opengl.GL11.glViewport;
import static org.lwjgl.stb.STBTruetype.stbtt_GetPackedQuad;
import static org.lwjgl.stb.STBTruetype.stbtt_PackBegin;
import static org.lwjgl.stb.STBTruetype.stbtt_PackEnd;
import static org.lwjgl.stb.STBTruetype.stbtt_PackFontRange;
import static org.lwjgl.stb.STBTruetype.stbtt_PackSetOversampling;
import static org.lwjgl.system.MemoryUtil.NULL;
import static org.lwjgl.system.MemoryUtil.memAllocFloat;
import static org.lwjgl.system.MemoryUtil.memFree;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.HashMap;
import java.util.Map;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GLUtil;
import org.lwjgl.stb.STBTTAlignedQuad;
import org.lwjgl.stb.STBTTPackContext;
import org.lwjgl.stb.STBTTPackRange;
import org.lwjgl.stb.STBTTPackedchar;
import org.lwjgl.system.Callback;
/**
* STB Truetype oversampling demo.
*
* <p>This is a Java port of <a href="https://github.com/nothings/stb/blob/master/tests/oversample/main.c">https://github
* .com/nothings/stb/blob/master/tests/oversample/main.c</a>.</p>
*/
public final class TruetypeOversample {
private static final int BITMAP_W = 1024;
private static final int BITMAP_H = 1024;
// ----
private final STBTTAlignedQuad q = STBTTAlignedQuad.malloc();
private final FloatBuffer xb = memAllocFloat(1);
private final FloatBuffer yb = memAllocFloat(1);
private long window;
private Callback debugProc;
// ----
private int ww = 1600;
private int wh = 768;
private int fbw = ww;
private int fbh = wh;
private int font_tex;
private STBTTPackedchar.Buffer chardata;
//Map<char, index_in_chardata_buffer>
private Map<Integer, Integer> chardataIndices;
private boolean black_on_white;
private boolean show_tex;
private TruetypeOversample() {
}
public static void main(String[] args) {
new TruetypeOversample().run("STB Truetype Oversample Demo");
}
private void load_fonts() {
font_tex = glGenTextures();
chardata = STBTTPackedchar.malloc(96);
chardataIndices = new HashMap<>();
for(int i = 0 ; i < chardata.remaining() ; i++) {
chardataIndices.put(i + 32, i);
}
STBTTPackRange.Buffer packRanges = STBTTPackRange.malloc(1);
packRanges.put(STBTTPackRange.malloc().set(
16,
32,
null,
96,
chardata));
try (STBTTPackContext pc = STBTTPackContext.malloc()) {
ByteBuffer ttf = ioResourceToByteBuffer("demo/monof55.ttf", 512 * 1024);
ByteBuffer bitmap = BufferUtils.createByteBuffer(BITMAP_W * BITMAP_H);
stbtt_PackBegin(pc, bitmap, BITMAP_W, BITMAP_H, 0, 1, NULL);
stbtt_PackSetOversampling(pc, 1, 1);
//below method works
stbtt_PackFontRange(pc, ttf, 0, 16, 32, chardata);
//below method works not
// stbtt_PackFontRanges(pc, ttf, 0, packRanges);
stbtt_PackEnd(pc);
glBindTexture(GL_TEXTURE_2D, font_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_W, BITMAP_H, 0, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void draw_init() {
glDisable(GL_CULL_FACE);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glViewport(0, 0, fbw, fbh);
if (black_on_white) {
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
} else {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, ww, wh, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
private static void drawBoxTC(float x0, float y0, float x1, float y1, float s0, float t0, float s1, float t1) {
glTexCoord2f(s0, t0);
glVertex2f(x0, y0);
glTexCoord2f(s1, t0);
glVertex2f(x1, y0);
glTexCoord2f(s1, t1);
glVertex2f(x1, y1);
glTexCoord2f(s0, t1);
glVertex2f(x0, y1);
}
private void print(float x, float y, int font, String text) {
xb.put(0, x);
yb.put(0, y);
chardata.position(0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, font_tex);
glBegin(GL_QUADS);
for (int i = 0; i < text.length(); i++) {
stbtt_GetPackedQuad(
chardata,
BITMAP_W, BITMAP_H,
chardataIndices.get((int)text.charAt(i)),
xb, yb,
q,
true);
drawBoxTC(
q.x0(), q.y0(), q.x1(), q.y1(),
q.s0(), q.t0(), q.s1(), q.t1()
);
}
glEnd();
}
private void draw_world() {
float x = 20;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (black_on_white) {
glColor3f(0.0f, 0.0f, 0.0f);
} else {
glColor3f(1.0f, 1.0f, 1.0f);
}
print(80, 30, 0, "Controls:");
if (black_on_white) {
print(100, 210, 0, "B: toggle to white-on-black");
} else {
print(100, 210, 0, "B: toggle to black-on-white");
}
print(100, 235, 0, "V: view font texture");
print(80, 300, 0, "Current fontsize: 16 pixels");
if (show_tex) {
glBegin(GL_QUADS);
drawBoxTC(200, 400, 200 + BITMAP_W, 300 + BITMAP_H, 0, 0, 1, 1);
glEnd();
} else {
glMatrixMode(GL_MODELVIEW);
glTranslatef(200, 350, 0);
print(x, 100, 0, "This is a test");
print(x, 130, 0, "Now is the time for all good men to come to the aid of their country.");
print(x, 160, 0, "The quick brown fox jumps over the lazy dog.");
}
}
private void draw() {
draw_init();
draw_world();
glfwSwapBuffers(window);
}
private void loopmode(float dt) {
if (dt > 0.25f) {
dt = 0.25f;
}
if (dt < 0.01f) {
dt = 0.01f;
}
draw();
}
private void windowSizeChanged(long window, int width, int height) {
this.ww = width;
this.wh = height;
}
private void framebufferSizeChanged(long window, int width, int height) {
this.fbw = width;
this.fbh = height;
}
private void createWindow(String title) {
GLFWErrorCallback.createPrint().set();
if (!glfwInit()) {
throw new IllegalStateException("Unable to initialize GLFW");
}
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
this.window = glfwCreateWindow(ww, wh, title, NULL, NULL);
if (window == NULL) {
throw new RuntimeException("Failed to create the GLFW window");
}
glfwSetWindowSizeCallback(window, this::windowSizeChanged);
glfwSetFramebufferSizeCallback(window, this::framebufferSizeChanged);
glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
if (action == GLFW_RELEASE) {
return;
}
switch (key) {
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, true);
break;
case GLFW_KEY_V:
show_tex = !show_tex;
break;
case GLFW_KEY_B:
black_on_white = !black_on_white;
break;
}
});
// Center window
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(
window,
(vidmode.width() - ww)/2,
(vidmode.height() - wh)/2
);
// Create context
glfwMakeContextCurrent(window);
GL.createCapabilities();
debugProc = GLUtil.setupDebugMessageCallback();
glfwSwapInterval(1);
glfwShowWindow(window);
glfwInvoke(window, this::windowSizeChanged, this::framebufferSizeChanged);
}
private void run(String title) {
try {
createWindow(title);
load_fonts();
long time = System.nanoTime();
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
long t = System.nanoTime();
float dt = (float)((t - time)/1000000000.0);
time = t;
loopmode(dt);
}
} finally {
try {
destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void destroy() {
chardata.free();
if (debugProc != null) {
debugProc.free();
}
glfwFreeCallbacks(window);
glfwTerminate();
glfwSetErrorCallback(null).free();
memFree(yb);
memFree(xb);
q.free();
}
}