【发布时间】:2014-04-26 00:15:55
【问题描述】:
由于某种原因,当我尝试使用 LWJGL 渲染纹理时,纹理仅呈现为纯色。我不认为纹理加载有问题(我使用的是 Slick Util 库),因为纹理的颜色似乎是图像中的主要颜色。
模型类:
public class Model {
private FloatBuffer vertices, uvValues;
private int vertexID, uvID;
private int vertexAttrib, uvAttrib;
private Texture tex;
private ByteBuffer texData;
private int textureID;
private int textureLocation;
private Matrix4f modelMatrix;
private FloatBuffer modelBuffer;
private int modelMatrixLocation;
public Model(float[] verts, float[] uvs, int modelLocation, String texPath, int texLocation){
vertices = createBuffer(verts);
vertexAttrib = 0;
vertexID = createVBO(vertices, vertexAttrib, 3);
tex = TextureUtils.loadTexturePNG(texPath);
texData = createBuffer(tex);
textureID = bindTextureData(tex, texData);
textureLocation = texLocation;
uvValues = createBuffer(uvs);
uvAttrib = 1;
uvID = createVBO(uvValues, uvAttrib, 2);
modelMatrix = new Matrix4f();
modelMatrixLocation = modelLocation;
modelBuffer = createBuffer(modelMatrix);
}
private static FloatBuffer createBuffer(float[] vals){
FloatBuffer buffer = BufferUtils.createFloatBuffer(vals.length);
buffer.put(vals);
buffer.flip();
return buffer;
}
private static FloatBuffer createBuffer(Matrix4f mat){
FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
mat.store(buffer);
buffer.flip();
return buffer;
}
private static ByteBuffer createBuffer(Texture tex){
ByteBuffer buffer = BufferUtils.createByteBuffer(tex.getTextureData().length);
buffer.put(tex.getTextureData());
buffer.flip();
return buffer;
}
private static int bindTextureData(Texture tex, ByteBuffer data){
int id = glGenTextures();
glBindTexture(GL_TEXTURE_2D, id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (int) tex.getWidth(), (int) tex.getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
return id;
}
private static int createVBO(FloatBuffer buffer, int location, int vectorSize){
int id = glGenBuffers();
glEnableVertexAttribArray(location);
glBindBuffer(GL_ARRAY_BUFFER, id);
glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
glVertexAttribPointer(location, vectorSize, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(location);
return id;
}
private void bind(){
glUniformMatrix4(modelMatrixLocation, false, modelBuffer);
tex.bind();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
glUniform1i(textureLocation, 0);
glEnableVertexAttribArray(vertexAttrib);
glBindBuffer(GL_ARRAY_BUFFER, vertexID);
glVertexAttribPointer(vertexAttrib, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(uvAttrib);
glBindBuffer(GL_ARRAY_BUFFER, uvID);
glVertexAttribPointer(uvAttrib, 2, GL_FLOAT, false, 0, 0);
}
private void unbind(){
glDisableVertexAttribArray(uvAttrib);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(vertexAttrib);
glBindTexture(GL_TEXTURE_2D, 0);
}
public void render(){
bind();
glDrawArrays(GL_TRIANGLES, 0, vertices.capacity() / 3);
unbind();
}
}
模型初始化代码:
model = new Model(new float[]{
-1, -1, -3,
1, -1, -3,
1, 1, -3
}, new float[]{
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f
}, program.getUniformLocation("model_matrix"), "res/tex/testTex.png", program.getUniformLocation("texture_sampler"));
顶点着色器:
#version 330 core
layout(location = 0) in vec3 position_modelspace;
layout(location = 1) in vec2 vertex_UV;
uniform mat4 model_matrix;
uniform mat4 view_matrix;
uniform mat4 projection_matrix;
out vec2 UV;
void main(){
vec4 vertex_MVP = projection_matrix * view_matrix * model_matrix * vec4(position_modelspace, 1.0);
gl_Position = vertex_MVP;
UV = vertex_UV;
}
片段着色器:
#version 330 core
uniform sampler2D texture_sampler;
in vec2 UV;
out vec3 color;
void main(){
color = texture(texture_sampler, UV).rgb;
}
我不太确定问题出在哪里。纹理加载没有任何问题,我已经查看了很多其他类似问题的问题,但我还没有找到解决这个问题的问题。
【问题讨论】:
-
这个
Texture类的实现是什么样的,为什么要绑定它在设置活动的纹理图像单元?我希望看到tex对象与glBindTexture (...)同时绑定,事实上我怀疑他们做同样的事情。 -
我正在使用 Slick Util 库的 Texture 类。我删除了 tex.bind(),但没有任何区别。
-
我不认为它会,但流浪绑定似乎很奇怪。此外,您的
createVBO (...)方法做了一些多余的事情,例如启用立即禁用属性指针。仅在您调用glDrawArrays (...)时,启用或禁用指针才真正重要。该状态不会影响其他任何东西。同样,将 VBO 绑定到GL_ARRAY_BUFFER也没有什么坏处。除非您使用基于非 VBO 的顶点数组,否则不需要绑定 0。 -
我查看了代码,并没有发现问题。我们可以尝试缩小对您有用的问题。第一个实验:从片段着色器输出一个固定的颜色。将着色器中的代码行更改为
color = vec3(1.0, 1.0, 0.0);。看到黄色三角形了吗?如果是,请将其更改为color = vec3(UV, 0.0);。三角形现在是否显示红色/绿色/黄色渐变?这将告诉我们几何体是否正确渲染,以及纹理坐标是否成功到达片段着色器。 -
第二次不行!出于某种原因,UV 坐标似乎没有到达着色器。
标签: opengl glsl lwjgl texture-mapping opengl-3