2017-12-09 7 views
1

Die LWJGL3-Bibliothek enthält Bindungen zu STB TrueType und anderen Bibliotheken, die von Sean Barrett hergestellt werden.Was mache ich falsch/fehlt, um von stbtt_PackFontRange zu stbtt_PackFontRanges zu wechseln?

Um diese Bibliothek zu verstehen und verwenden ich verwenden ...

stbtt_PackFontRange(pc, ttf, 0, 16, 32, chardata); 

... stattdessen mit ...

STBTTPackRange.Buffer packRanges = STBTTPackRange.malloc(1); 
packRanges.put(STBTTPackRange.malloc().set(16, 32, null, 96, chardata)); 
... 
stbtt_PackFontRanges(pc, ttf, 0, packRanges); 

den Code in der Überabtastungs Demo konvertieren wollte ... was zu einer leeren Textur führt.

Aus dem Verständnis konnte ich durch Lesen der Dokumentationen und Blick auf die Beispiele in der Stb Repo sowie in der Lwjgl Repo sammeln, was ich tue, sollte funktionieren, aber es tut es nicht.

Ich änderte die untere Klasse von der ursprünglichen ~ 1 Zeile auf einmal zu dem Punkt, wo ich von der Methode auf die Verwendung der stbtt_PackFontRanges(...) Methode umgestellt wurde.


Die vollständige load_fonts() Methode für Kontext:

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

Die komplette modifizierte TruetypeOversample Klasse kann am einfachsten durch Klonen der lwjgl3 repo und ersetzt die Klasse mit dem gleichen Namen ausgeführt werden:

/* 
* 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(); 
    } 
} 

Antwort

0

Flip den Puffer ...

Obwohl die zugrunde liegende Bibliothek in C geschrieben ist, ist dieser Wrapper in Java geschrieben und verwendet Java-Puffer, um Daten an die zugrunde liegende Bibliothek zu übergeben. Also nach dem Schreiben in den Puffer müssen Sie flip() es für Lesevorgänge vorbereiten.

Es spielt keine Rolle, dass LWJGL beim Lesen nicht die buffer.position() ändert, es wird immer noch die Position als Startpunkt verwenden.

Verwandte Themen