使用 slick 在 LWJGL 中显示我的 3D 盒子上的纹理时出现问题。早些时候我遇到了错误:
WARN:class org.newdawn.slick.opengl.PNGImageData failed to read the data
java.lang.UnsupportedOperationException: Unsupported format for this image
说它无法读取图像。所以我将图像转换为 24 位(也尝试了 8 位),现在我只得到:
INFO:Use Java PNG Loader = true
显示了我的 3D 立方体,但上面没有纹理。不知道该怎么做才能让它显示我的纹理。
纹理类:
package com.base.engine;
import static org.lwjgl.opengl.GL11.*;
public class Texture {
private int id;
public Texture(int id) {
this.id = id;
}
public void bind() {
glBindTexture(GL_TEXTURE_2D, id);
}
public int getID() {
return id;
}
}
材质类
package com.base.engine;
public class Material
{
private Texture texture;
private Vector3f color;
public Material(Texture texture)
{
this(texture, new Vector3f(1,1,1));
}
public Material(Texture texture, Vector3f color)
{
this.texture = texture;
this.color = color;
}
public Texture getTexture()
{
return texture;
}
public void setTexture(Texture texture)
{
this.texture = texture;
}
public Vector3f getColor()
{
return color;
}
public void setColor(Vector3f color)
{
this.color = color;
}
}
游戏类:
package com.base.engine;
import java.io.FileInputStream;
import java.io.InputStream;
public class Game
{
private Mesh mesh;
private Shader shader;
private Material material;
private Transform transform;
private Camera camera;
public Game()
{
mesh = ResourceLoader.loadMesh("box.obj");
material = new Material(ResourceLoader.loadTexture("test.png"), new Vector3f(0,1,1));
shader = BasicShader.getInstance();
camera = new Camera();
// Vertex[] vertices = new Vertex[] {new Vertex(new Vector3f(-1,-1,0), new Vector2f(0,0)),
// new Vertex(new Vector3f(0,1,0), new Vector2f(0.5f,0)),
// new Vertex(new Vector3f(1,-1,0), new Vector2f(1.0f,0)),
// new Vertex(new Vector3f(0,-1,1), new Vector2f(0.5f,1.0f))};
//
// int[] indices = new int[] {3,1,0,
// 2,1,3,
// 0,1,2,
// 0,2,3};
//
// mesh.addVertices(vertices, indices);
Transform.setProjection(70f, Window.getWidth(), Window.getHeight(), 0.1f, 1000);
Transform.setCamera(camera);
transform = new Transform();
}
public void input()
{
camera.input();
// if(Input.getKeyDown(Input.KEY_UP))
// System.out.println("We've just pressed up!");
// if(Input.getKeyUp(Input.KEY_UP))
// System.out.println("We've just released up!");
//
// if(Input.getMouseDown(1))
// System.out.println("We've just right clicked at " + Input.getMousePosition().toString());
// if(Input.getMouseUp(1))
// System.out.println("We've just released right mouse button!");
}
float temp = 0.0f;
public void update()
{
temp += Time.getDelta();
float sinTemp = (float)Math.sin(temp);
transform.setTranslation(sinTemp, 0, 5);
transform.setRotation(0, sinTemp * 180, 0);
//transform.setScale(0.7f * sinTemp, 0.7f * sinTemp, 0.7f * sinTemp);
}
public void render()
{
RenderUtil.setClearColor(Transform.getCamera().getPos().div(2048f).abs());
shader.bind();
shader.updateUniforms(transform.getTransformation(), transform.getProjectedTransformation(), material);
mesh.draw();
}
}
RenderUtil 类:
package com.base.engine;
import static org.lwjgl.opengl.GL11.*;
public class RenderUtil
{
public static void clearScreen()
{
//TODO: Stencil Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
public static void setTextures(boolean enabled)
{
if(enabled)
glEnable(GL_TEXTURE_2D);
else
glDisable(GL_TEXTURE_2D);
}
public static void unbindTextures()
{
glBindTexture(GL_TEXTURE_2D, 0);
}
public static void setClearColor(Vector3f color)
{
glClearColor(color.getX(), color.getY(), color.getZ(), 1.0f);
}
public static void initGraphics()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glFrontFace(GL_CW);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
//TODO: Depth clamp for later
glEnable(GL_TEXTURE_2D);
glEnable(GL_FRAMEBUFFER_SRGB);
}
public static String getOpenGLVersion()
{
return glGetString(GL_VERSION);
}
}
着色器类:
package com.base.engine;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL32.*;
import java.util.HashMap;
public class Shader
{
private int program;
private HashMap<String, Integer> uniforms;
public Shader()
{
program = glCreateProgram();
uniforms = new HashMap<String, Integer>();
if(program == 0)
{
System.err.println("Shader creation failed: Could not find valid memory location in constructor");
System.exit(1);
}
}
public void bind()
{
glUseProgram(program);
}
public void updateUniforms(Matrix4f worldMatrix, Matrix4f projectedMatrix, Material material)
{
}
public void addUniform(String uniform)
{
int uniformLocation = glGetUniformLocation(program, uniform);
if(uniformLocation == 0xFFFFFFFF)
{
System.err.println("Error: Could not find uniform: " + uniform);
new Exception().printStackTrace();
System.exit(1);
}
uniforms.put(uniform, uniformLocation);
}
public void addVertexShader(String text)
{
addProgram(text, GL_VERTEX_SHADER);
}
public void addGeometryShader(String text)
{
addProgram(text, GL_GEOMETRY_SHADER);
}
public void addFragmentShader(String text)
{
addProgram(text, GL_FRAGMENT_SHADER);
}
public void compileShader()
{
glLinkProgram(program);
if(glGetProgram(program, GL_LINK_STATUS) == 0)
{
System.err.println(glGetProgramInfoLog(program, 1024));
System.exit(1);
}
glValidateProgram(program);
if(glGetProgram(program, GL_VALIDATE_STATUS) == 0)
{
System.err.println(glGetProgramInfoLog(program, 1024));
System.exit(1);
}
}
private void addProgram(String text, int type)
{
int shader = glCreateShader(type);
if(shader == 0)
{
System.err.println("Shader creation failed: Could not find valid memory location when adding shader");
System.exit(1);
}
glShaderSource(shader, text);
glCompileShader(shader);
if(glGetShader(shader, GL_COMPILE_STATUS) == 0)
{
System.err.println(glGetShaderInfoLog(shader, 1024));
System.exit(1);
}
glAttachShader(program, shader);
}
public void setUniformi(String uniformName, int value)
{
glUniform1i(uniforms.get(uniformName), value);
}
public void setUniformf(String uniformName, float value)
{
glUniform1f(uniforms.get(uniformName), value);
}
public void setUniform(String uniformName, Vector3f value)
{
glUniform3f(uniforms.get(uniformName), value.getX(), value.getY(), value.getZ());
}
public void setUniform(String uniformName, Matrix4f value)
{
glUniformMatrix4(uniforms.get(uniformName), true, Util.createFlippedBuffer(value));
}
}
基本着色器类:
package com.base.engine;
public class BasicShader extends Shader
{
private static final BasicShader instance = new BasicShader();
public static BasicShader getInstance()
{
return instance;
}
private BasicShader()
{
super();
addVertexShader(ResourceLoader.loadShader("basicVertex.vs"));
addFragmentShader(ResourceLoader.loadShader("basicFragment.fs"));
compileShader();
addUniform("transform");
addUniform("color");
}
public void updateUniforms(Matrix4f worldMatrix, Matrix4f projectedMatrix, Material material)
{
if(material.getTexture() != null)
material.getTexture().bind();
else
RenderUtil.unbindTextures();
setUniform("transform", projectedMatrix);
setUniform("color", material.getColor());
}
}
基本顶点.vs
#version 330
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
out vec2 texCoord0;
uniform mat4 transform;
void main()
{
gl_Position = transform * vec4(position, 1.0);
texCoord0 = texCoord;
}
基本片段.fs
#version 330
in vec2 texCoord0;
out vec4 fragColor;
uniform vec3 color;
uniform sampler2D sampler;
void main()
{
vec4 textureColor = texture(sampler, texCoord0.xy);
if(textureColor == vec4(0,0,0,0))
fragColor = vec4(color, 1);
else
fragColor = textureColor * vec4(color, 1);
}
谢谢您的帮助!