Java 导出Eclipse项目会导致不正确的纹理和崩溃,
此问题现已修复。我的着色器属性未正确绑定。 我有一个游戏,从IDE运行时如下所示:Java 导出Eclipse项目会导致不正确的纹理和崩溃,,java,eclipse,opengl,glsl,lwjgl,Java,Eclipse,Opengl,Glsl,Lwjgl,此问题现已修复。我的着色器属性未正确绑定。 我有一个游戏,从IDE运行时如下所示: Plane you = Main.TerrainDemo.shipsID.get(Main.TerrainDemo.UID); Main.TerrainDemo.shader.start(); TexturedModel texturedModel = TerrainDemo.shipModel; //The plane model RawModel model = texturedMod
Plane you = Main.TerrainDemo.shipsID.get(Main.TerrainDemo.UID);
Main.TerrainDemo.shader.start();
TexturedModel texturedModel = TerrainDemo.shipModel; //The plane model
RawModel model = texturedModel.getRawModel();
GL30.glBindVertexArray(model.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, TerrainDemo.shipModel.getTexture().getID()); //The ID of the texture.
glDrawElements(GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
但是,当我使用这些设置从Eclipse导出它时
纹理完全不正确。纹理仍被加载,但它们没有正确地包装到对象上
代码完全相同,因为我只是刚刚导出了它,而且我目前正在同时运行游戏的两个窗口(一个在IDE中运行良好,另一个在导出的JAR中看起来很奇怪)
我还将IDE目录中的所有资源复制到带有外部JAR的文件夹中。IDE目录:
运行外部JAR的目录:
此外,我知道纹理实际上正在加载-它们没有正确包装。我知道这一点是因为:
- 如果你看这个平面,你可以看到它仍然有纹理的元素——它们只是被拉伸和弄乱了
- Skybox也是这样。如果你看,零件仍然在那里,但是再一次,它被错误地包装在OBJ模型上
- 如果我按Q键以使用显示列表渲染地形(多次环绕地形纹理),它将显示纹理。我无法截屏,因为我无法点击Q并截屏
loader.loadTexture("PlaneTexture", 1);
//loadTexture() method:
public int loadTexture(String fileName, int mipmap) {
Texture texture = null;
try {
try{
texture = TextureLoader.getTexture("PNG", new FileInputStream("res/" + fileName + ".png")); //TextureLoader is a Slick-Util class.
}catch (Exception e){
e.printStackTrace();
}
if (texture == null){
throw new Exception("Null texture!");
}
//texture = TextureLoader.getTexture("GIF", new FileInputStream("res/" + fileName + ".png"));
if (mipmap > -10){
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, mipmap);
}
} catch (Exception e) {
e.printStackTrace();
System.err.println("Tried to load texture " + fileName + ".png , didn't work");
System.exit(1);
return -1;
}
textures.add(texture.getTextureID());
return texture.getTextureID();
}
我现在有了纹理的纹理ID。然后,我按如下方式渲染对象(在本例中为平面):
Plane you = Main.TerrainDemo.shipsID.get(Main.TerrainDemo.UID);
Main.TerrainDemo.shader.start();
TexturedModel texturedModel = TerrainDemo.shipModel; //The plane model
RawModel model = texturedModel.getRawModel();
GL30.glBindVertexArray(model.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, TerrainDemo.shipModel.getTexture().getID()); //The ID of the texture.
glDrawElements(GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
尽管我认为它们并不重要,但我的顶点和片段着色器:
//Vertex shader
#version 130
in vec3 position;
in vec2 textureCoords;
in vec3 normal;
out vec2 pass_textureCoords;
out vec3 surfaceNormal;
out vec3 toLightVector;
uniform mat4 transformationMatrix;
uniform vec3 lightPosition;
void main(void){
gl_Position = ftransform();
pass_textureCoords = textureCoords;
surfaceNormal = (transformationMatrix * vec4(normal, 0.0)).xyz;
toLightVector = (vec3(500, 50000, 500)) - (transformationMatrix * vec4(position, 1.0)).xyz;
}
//Fragment shader
#version 130
in vec2 pass_textureCoords;
in vec3 surfaceNormal;
in vec3 toLightVector;
out vec4 out_Color;
uniform sampler2D textureSampler;
uniform vec3 lightColour;
void main(void){
vec3 unitNormal = normalize(surfaceNormal);
vec3 unitLightVector = normalize(toLightVector);
float nDot1 = dot(unitNormal, unitLightVector);
float brightness = max(nDot1, 0.2);
brightness = brightness + 0.5;
vec3 diffuse = brightness * vec3(1, 1, 1);
vec4 textureColor = vec4(diffuse, 1.0) * texture(textureSampler, pass_textureCoords);
if(textureColor.a<1){
discard;
}
out_Color = vec4(textureColor.r, textureColor.g, textureColor.b, 1);
}
在日志文件中,我看到以下内容:
Stack: [0x011d0000,0x01220000], sp=0x0121f1e8, free space=316k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [atioglxx.dll+0xc0b57f]
C [atioglxx.dll+0xbe8b95]
C [atioglxx.dll+0x641852]
C [lwjgl.dll+0x9a28]
j org.lwjgl.opengl.GL20.glUniformMatrix4(IZLjava/nio/FloatBuffer;)V+33
j TMLoading.ShaderProgram.loadMatrix(ILorg/lwjgl/util/vector/Matrix4f;)V+23j
TMLoading.StaticShader.loadTransformationMatrix(Lorg/lwjgl/util/vector/Matrix4f;) V+6
j Joehot200.Plane.render()V+407
j Joehot200.TerrainDemo.render()V+4045
j Joehot200.TerrainDemo.enterGameLoop()V+356
j Joehot200.TerrainDemo.startGame()V+320
j StartScreenExperiments.Test2.resartTDemo()V+128
j StartScreenExperiments.Test2.main([Ljava/lang/String;)V+27
v ~StubRoutines::call_stub
V [jvm.dll+0x1473e5]
换句话说,整个问题(纹理和崩溃)开始看起来很像是与着色器相关的问题(或者是对它们的解析信息,或者是实际的着色器代码本身)
我还做了更多的测试,没有使用显示列表的着色器,纹理效果很好
以下是glUniformMatrix()调用的代码:
更新-所以,赏金还有一个小时,我想我应该补充一些细节:
- 正如我可能在上面的某个地方所说的,游戏在导出时对某些人有效,但对其他人无效。我注意到,当在Java7上运行时,这个游戏总是有效的,但是对于我和另外一名测试人员来说,这并不是决定性的
- 纹理在显示列表中正确渲染纹理正在加载。但是,它们没有正确显示
- 即使您不知道问题所在,也非常感谢您尝试游戏(忽略开始屏幕,我需要制作一个新屏幕),并告诉我结果,以及您的OS/Java详细信息等
- 是的,映射是正确的。我知道有人在评论中提到它可能不是,但我试着把它设置得很高,我确实得到了一个非常模糊的纹理
- 我已经尝试过“将库打包到外部jar中”。我很感激花了这么多时间来回答这个问题,但我在评论中说我已经试过了
- 问题可能是片段着色器(如有人在评论中所建议的),但我目前不确定如何测试它,也不理解为什么它在IDE内部工作,而不是在IDE外部工作
- 我无法测试这一点,所以我不确定这是否有帮助,但OpenGL的一些实现没有在VAOs中保存元素缓冲区。因此,尝试在调用glpaurements之前绑定元素缓冲区,例如
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, someBuffer);
glDrawElements(GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
如果不这样做,则可能会对所有绘图调用使用最后绑定的缓冲区。可能不是答案,但测试一下也无妨。我还注意到,您使用的是旧版本的Slick,因为您仍然有Slick util,它不是最新版本的一部分,因此您也可以尝试更新它。因此,请尝试此操作,而不是提取所需的库,而改为尝试使用Package选项,因为我个人认为在查找那些库文件或链接某些文件时会出现问题,所以只需运行包即可
作为一项测试,使用“将所需库复制到子文件夹”选项导出时会发生什么情况?不同之处在于,您正在破坏正在使用的库,并将它们捣碎到一个胖罐子中。@Gimby我将尝试提供相关代码。问题在于,在大约6000行代码中,决定什么是相关的。你可能是对的,而且纹理可能没有正确加载(如果我的特定方法有问题怎么办),因此我将围绕纹理加载代码进行一些测试。我建议切换到将它们打包到jar中,并将它们作为类路径资源加载;这使得无论您在何处以及如何运行游戏,都几乎不可能失败。胡乱猜测:看起来您的mipmap失败了,但您的纹理加载良好。这就解释了你发布的正确和不正确图片中出现颗粒状结果的原因。因此,如果纹理很好,但mipmapping不好,那么纹理的颗粒度将由非常大或未定义的texcoords产生。只有当您的数据是wro时,这才可能
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, someBuffer);
glDrawElements(GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);