Java 如何从PNG加载LWJGL中的纹理而不使用Slick?
嗨,我对LWJGL(或OpenGL)相当陌生,尽管我有Java方面的经验。我想知道如何在立方体的每一面呈现不同的PNG纹理,我想远离LWJGL以外的其他第三方库。谢谢你的帮助 自LWJGL3起,已包含用于的绑定。这是一个小的单文件实用程序库,可以加载纹理、声音文件或字体Java 如何从PNG加载LWJGL中的纹理而不使用Slick?,java,textures,lwjgl,Java,Textures,Lwjgl,嗨,我对LWJGL(或OpenGL)相当陌生,尽管我有Java方面的经验。我想知道如何在立方体的每一面呈现不同的PNG纹理,我想远离LWJGL以外的其他第三方库。谢谢你的帮助 自LWJGL3起,已包含用于的绑定。这是一个小的单文件实用程序库,可以加载纹理、声音文件或字体 要渲染每侧具有不同纹理的立方体,有两个选项: 使用另一个纹理绑定分别渲染每个面。这是更直接的选择 对所有纹理进行渲染,并渲染整个立方体一次。这并不容易做到,但会提供更好的性能,尤其是在渲染多个多维数据集时 。(它是C++的,但
要渲染每侧具有不同纹理的立方体,有两个选项:
。(它是C++的,但应该很容易转换成java)。这是一个小的单文件实用程序库,可以加载纹理、声音文件或字体
要渲染每侧具有不同纹理的立方体,有两个选项:
。(它是C++的,但应该很容易转换成java)。这是一个小的单文件实用程序库,可以加载纹理、声音文件或字体
要渲染每侧具有不同纹理的立方体,有两个选项:
。(它是C++的,但应该很容易转换成java)。这是一个小的单文件实用程序库,可以加载纹理、声音文件或字体
要渲染每侧具有不同纹理的立方体,有两个选项:
/*
*版权所有LWJGL。版权所有。
*许可条款:https://www.lwjgl.org/license
*/
包org.lwjgl.demo.stb;
导入org.lwjgl.glfw.*;
导入org.lwjgl.opengl.*;
导入org.lwjgl.system.*;
导入java.io.*;
导入java.nio.*;
导入java.util.*;
导入静态java.lang.Math.*;
导入静态org.lwjgl.demo.glfw.GLFWUtil.*;
导入静态org.lwjgl.demo.util.IOUtil.*;
导入静态org.lwjgl.glfw.Callbacks.*;
导入静态org.lwjgl.glfw.glfw.*;
导入静态org.lwjgl.opengl.GL11.*;
导入静态org.lwjgl.opengl.GL12.*;
导入静态org.lwjgl.stb.STBImage.*;
导入静态org.lwjgl.stb.stbimanagesize.*;
导入静态org.lwjgl.system.MemoryStack.*;
导入静态org.lwjgl.system.MemoryUtil.*;
/**机顶盒图像演示*/
公开期末班形象{
私人最终ByteBuffer图像;
私人终审法院;
私人终审法院;
私人最终国际比较;
私人长窗;
私人国际ww;
私有int-wh;
私有布尔ctrlDown;
私有整数规模;
私有回调debugProc;
私有映像(字符串imagePath){
ByteBuffer图像缓冲区;
试一试{
imageBuffer=ioResourceToByteBuffer(imagePath,8*1024);
}捕获(IOE异常){
抛出新的运行时异常(e);
}
try(MemoryStack stack=stackPush()){
IntBuffer w=stack.mallocInt(1);
intbufferh=stack.mallocInt(1);
IntBuffer comp=stack.mallocInt(1);
//使用info读取图像元数据而不解码整个图像。
//我们不需要这个演示,只是测试API。
如果(!stbi_info_from_memory(imageBuffer,w,h,comp)){
抛出新的运行时异常(“读取映像信息失败:+stbi_failure_reason());
}否则{
System.out.println(“确定原因:+stbi_failure_reason());
}
System.out.println(“图像宽度:+w.get(0));
System.out.println(“图像高度:+h.get(0));
System.out.println(“图像组件:+comp.get(0));
System.out.println(“图像HDR:+stbi_是来自_内存(imageBuffer))的_HDR_);
//解码图像
image=stbi\u从内存加载(imageBuffer,w,h,comp,0);
if(image==null){
抛出新的运行时异常(“加载映像失败:+stbi_failure_reason());
}
这个.w=w.get(0);
这个.h=h.get(0);
this.comp=comp.get(0);
}
}
公共静态void main(字符串[]args){
字符串图像路径;
如果(args.length==0){
System.out.println(“使用'antdemo-Dclass=org.lwjgl.demo.stb.Image-Dargs='加载不同的映像。\n”);
imagePath=“lwjgl32.png”;
}否则{
imagePath=args[0];
}
新建图像(imagePath).run();
}
私家车{
试一试{
init();
loop();
}最后{
试一试{
破坏();
}捕获(例外e){
e、 printStackTrace();
}
}
}
私有无效窗口大小更改(长窗口、整型宽度、整型高度){
this.ww=宽度;
这.wh=高度;
glMatrixMode(GL_投影);
glLoadIdentity();
/*
* Copyright LWJGL. All rights reserved.
* License terms: https://www.lwjgl.org/license
*/
package org.lwjgl.demo.stb;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;
import java.io.*;
import java.nio.*;
import java.util.*;
import static java.lang.Math.*;
import static org.lwjgl.demo.glfw.GLFWUtil.*;
import static org.lwjgl.demo.util.IOUtil.*;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.stb.STBImage.*;
import static org.lwjgl.stb.STBImageResize.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;
/** STB Image demo. */
public final class Image {
private final ByteBuffer image;
private final int w;
private final int h;
private final int comp;
private long window;
private int ww;
private int wh;
private boolean ctrlDown;
private int scale;
private Callback debugProc;
private Image(String imagePath) {
ByteBuffer imageBuffer;
try {
imageBuffer = ioResourceToByteBuffer(imagePath, 8 * 1024);
} catch (IOException e) {
throw new RuntimeException(e);
}
try (MemoryStack stack = stackPush()) {
IntBuffer w = stack.mallocInt(1);
IntBuffer h = stack.mallocInt(1);
IntBuffer comp = stack.mallocInt(1);
// Use info to read image metadata without decoding the entire image.
// We don't need this for this demo, just testing the API.
if (!stbi_info_from_memory(imageBuffer, w, h, comp)) {
throw new RuntimeException("Failed to read image information: " + stbi_failure_reason());
} else {
System.out.println("OK with reason: " + stbi_failure_reason());
}
System.out.println("Image width: " + w.get(0));
System.out.println("Image height: " + h.get(0));
System.out.println("Image components: " + comp.get(0));
System.out.println("Image HDR: " + stbi_is_hdr_from_memory(imageBuffer));
// Decode the image
image = stbi_load_from_memory(imageBuffer, w, h, comp, 0);
if (image == null) {
throw new RuntimeException("Failed to load image: " + stbi_failure_reason());
}
this.w = w.get(0);
this.h = h.get(0);
this.comp = comp.get(0);
}
}
public static void main(String[] args) {
String imagePath;
if (args.length == 0) {
System.out.println("Use 'ant demo -Dclass=org.lwjgl.demo.stb.Image -Dargs=<path>' to load a different image.\n");
imagePath = "lwjgl32.png";
} else {
imagePath = args[0];
}
new Image(imagePath).run();
}
private void run() {
try {
init();
loop();
} finally {
try {
destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void windowSizeChanged(long window, int width, int height) {
this.ww = width;
this.wh = height;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, width, height, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
private static void framebufferSizeChanged(long window, int width, int height) {
glViewport(0, 0, width, height);
}
private void init() {
GLFWErrorCallback.createPrint().set();
if (!glfwInit()) {
throw new IllegalStateException("Unable to initialize GLFW");
}
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
GLFWVidMode vidmode = Objects.requireNonNull(glfwGetVideoMode(glfwGetPrimaryMonitor()));
ww = max(800, min(w, vidmode.width() - 160));
wh = max(600, min(h, vidmode.height() - 120));
this.window = glfwCreateWindow(ww, wh, "STB Image Demo", NULL, NULL);
if (window == NULL) {
throw new RuntimeException("Failed to create the GLFW window");
}
// Center window
glfwSetWindowPos(
window,
(vidmode.width() - ww) / 2,
(vidmode.height() - wh) / 2
);
glfwSetWindowRefreshCallback(window, window -> render());
glfwSetWindowSizeCallback(window, this::windowSizeChanged);
glfwSetFramebufferSizeCallback(window, Image::framebufferSizeChanged);
glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
ctrlDown = (mods & GLFW_MOD_CONTROL) != 0;
if (action == GLFW_RELEASE) {
return;
}
switch (key) {
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, true);
break;
case GLFW_KEY_KP_ADD:
case GLFW_KEY_EQUAL:
setScale(scale + 1);
break;
case GLFW_KEY_KP_SUBTRACT:
case GLFW_KEY_MINUS:
setScale(scale - 1);
break;
case GLFW_KEY_0:
case GLFW_KEY_KP_0:
if (ctrlDown) {
setScale(0);
}
break;
}
});
glfwSetScrollCallback(window, (window, xoffset, yoffset) -> {
if (ctrlDown) {
setScale(scale + (int)yoffset);
}
});
// Create context
glfwMakeContextCurrent(window);
GL.createCapabilities();
debugProc = GLUtil.setupDebugMessageCallback();
glfwSwapInterval(1);
glfwShowWindow(window);
glfwInvoke(window, this::windowSizeChanged, Image::framebufferSizeChanged);
}
private void setScale(int scale) {
this.scale = max(-9, scale);
}
private void premultiplyAlpha() {
int stride = w * 4;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int i = y * stride + x * 4;
float alpha = (image.get(i + 3) & 0xFF) / 255.0f;
image.put(i + 0, (byte)round(((image.get(i + 0) & 0xFF) * alpha)));
image.put(i + 1, (byte)round(((image.get(i + 1) & 0xFF) * alpha)));
image.put(i + 2, (byte)round(((image.get(i + 2) & 0xFF) * alpha)));
}
}
}
private int createTexture() {
int texID = glGenTextures();
glBindTexture(GL_TEXTURE_2D, texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
int format;
if (comp == 3) {
if ((w & 3) != 0) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 2 - (w & 1));
}
format = GL_RGB;
} else {
premultiplyAlpha();
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
format = GL_RGBA;
}
glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, image);
ByteBuffer input_pixels = image;
int input_w = w;
int input_h = h;
int mipmapLevel = 0;
while (1 < input_w || 1 < input_h) {
int output_w = Math.max(1, input_w >> 1);
int output_h = Math.max(1, input_h >> 1);
ByteBuffer output_pixels = memAlloc(output_w * output_h * comp);
stbir_resize_uint8_generic(
input_pixels, input_w, input_h, input_w * comp,
output_pixels, output_w, output_h, output_w * comp,
comp, comp == 4 ? 3 : STBIR_ALPHA_CHANNEL_NONE, STBIR_FLAG_ALPHA_PREMULTIPLIED,
STBIR_EDGE_CLAMP,
STBIR_FILTER_MITCHELL,
STBIR_COLORSPACE_SRGB
);
if (mipmapLevel == 0) {
stbi_image_free(image);
} else {
memFree(input_pixels);
}
glTexImage2D(GL_TEXTURE_2D, ++mipmapLevel, format, output_w, output_h, 0, format, GL_UNSIGNED_BYTE, output_pixels);
input_pixels = output_pixels;
input_w = output_w;
input_h = output_h;
}
if (mipmapLevel == 0) {
stbi_image_free(image);
} else {
memFree(input_pixels);
}
return texID;
}
private void loop() {
int texID = createTexture();
glEnable(GL_TEXTURE_2D);
glClearColor(43f / 255f, 43f / 255f, 43f / 255f, 0f);
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
render();
}
glDisable(GL_TEXTURE_2D);
glDeleteTextures(texID);
}
private void render() {
glClear(GL_COLOR_BUFFER_BIT);
float scaleFactor = 1.0f + scale * 0.1f;
glPushMatrix();
glTranslatef(ww * 0.5f, wh * 0.5f, 0.0f);
glScalef(scaleFactor, scaleFactor, 1f);
glTranslatef(-w * 0.5f, -h * 0.5f, 0.0f);
glBegin(GL_QUADS);
{
glTexCoord2f(0.0f, 0.0f);
glVertex2f(0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(w, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(w, h);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(0.0f, h);
}
glEnd();
glPopMatrix();
glfwSwapBuffers(window);
}
private void destroy() {
if (debugProc != null) {
debugProc.free();
}
glfwFreeCallbacks(window);
glfwDestroyWindow(window);
glfwTerminate();
Objects.requireNonNull(glfwSetErrorCallback(null)).free();
}
}