我正在使用LWJGL 3编写OpenGL应用程序。我能够很好地渲染纯色,但是当我尝试引入纹理采样器时,我看到的只是黑色。
具体来说,片段着色器中纹理(texUnit,DataIn.texCoord)返回的值始终为vec4(0,0,0,1)。
我甚至尝试用所有255s手动填充传递给glTexImage2D的缓冲区,但我得到了相同的结果。我完全被这个难过了!
初始化:
private void initGL() {
// Enable depth buffer
GL11.glEnable(GL11.GL_DEPTH_TEST);
// Set background colour
GL11.glClearColor(0.2f, 0.2f, 0.4f, 0.0f);
// Set viewport to the whole window
GL11.glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
// Enable alpha blending (transparency)
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
// Enable back-face culling
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glCullFace(GL11.GL_BACK);
// Use linear filtering for texture scaling
GL11.glTexParameteri(GL11.GL_TEXTURE_2D,
GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D,
GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
// Clamp texture co-ordinates between 0 and 1
GL11.glTexParameteri(GL11.GL_TEXTURE_2D,
GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D,
GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
int errorCode = GL11.glGetError();
if (errorCode != GL11.GL_NO_ERROR) {
throw new RuntimeException(
"OpenGL error " + String.valueOf(errorCode)
+ " during initialisation");
}
}
纹理加载:
String filename = "terrain.png";
// Read image into a ByteBuffer
IntBuffer w = BufferUtils.createIntBuffer(1);
IntBuffer h = BufferUtils.createIntBuffer(1);
IntBuffer comp = BufferUtils.createIntBuffer(1);
ByteBuffer texelData =
STBImage.stbi_load(GFX_DIR + filename, w, h, comp, 4);
if (texelData == null) {
throw new RuntimeException("Error loading " + filename + ": " +
STBImage.stbi_failure_reason());
}
int width = w.get();
int height = h.get();
// Generate texture ID
terrainTexId = GL11.glGenTextures();
// Pass our texture to the shader
GL11.glBindTexture(GL11.GL_TEXTURE_2D, terrainTexId);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, height,
0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, texelData);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); // Deselect
int errorCode = GL11.glGetError();
if (errorCode != GL11.GL_NO_ERROR) {
throw new RuntimeException(
"OpenGL error " + String.valueOf(errorCode)
+ " loading texture: " + filename);
}
渲染:
// Clear the screen and depth buffer
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
// Use our shader program
GL20.glUseProgram(Shaders.programId);
// Set the projection matrix
FloatBuffer fb = BufferUtils.createFloatBuffer(16);
projection.setPerspective(
camera.getFovY(),
window.getAspectRatio(),
Camera.Z_NEAR,
Camera.Z_FAR);
GL20.glUniformMatrix4fv(
Shaders.projectionLoc, false, projection.get(fb));
// Set the model-view matrix.
modelView.setLookAt(
camera.getPos(),
camera.getTarget(),
camera.getUpVector());
GL20.glUniformMatrix4fv(Shaders.modelViewLoc, false, modelView.get(fb));
// Bind our texture to texture unit 0
GL13.glActiveTexture(GL13.GL_TEXTURE0 + 0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, terrainTexId);
// Tell the shader to sample from texture unit 0.
// This is the default anyway.
GL20.glUniform1i(Shaders.texUnitLoc, 0);
// Pass the lighting information to the shader
fb = BufferUtils.createFloatBuffer(3);
GL20.glUniform3fv(Shaders.lightAmbientColourLoc,
lighting.getAmbientColour().get(fb));
GL20.glUniform1f(Shaders.lightAmbientIntensityLoc,
lighting.getAmbientIntensity());
GL20.glUniform3fv(Shaders.lightDiffuseColourLoc,
lighting.getDiffuseColour().get(fb));
GL20.glUniform3fv(Shaders.lightDiffuseAngleLoc,
lighting.getDiffuseVector().get(fb));
GL20.glUniform1f(Shaders.lightDiffuseIntensityLoc,
lighting.getDiffuseIntensity());
// Bind to the VAO that has all the information about the vertices
GL30.glBindVertexArray(terrainSection.getVaoId());
GL20.glEnableVertexAttribArray(Shaders.PARAM_VERTEX);
GL20.glEnableVertexAttribArray(Shaders.PARAM_VERTEX_NORMAL);
GL20.glEnableVertexAttribArray(Shaders.PARAM_MATERIAL_AMBIENT_COLOUR);
GL20.glEnableVertexAttribArray(Shaders.PARAM_MATERIAL_DIFFUSE_COLOUR);
GL20.glEnableVertexAttribArray(Shaders.PARAM_TEXTURE_COORDS);
// Draw the vertices
GL11.glDrawArrays(
GL11.GL_TRIANGLES, 0, TerrainSection.NUM_VERTICES_FOR_BUFFERS);
// Put everything back to default (deselect)
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
GL20.glDisableVertexAttribArray(Shaders.PARAM_VERTEX);
GL20.glDisableVertexAttribArray(Shaders.PARAM_VERTEX_NORMAL);
GL20.glDisableVertexAttribArray(Shaders.PARAM_MATERIAL_AMBIENT_COLOUR);
GL20.glDisableVertexAttribArray(Shaders.PARAM_MATERIAL_DIFFUSE_COLOUR);
GL30.glBindVertexArray(0);
GL20.glUseProgram(0);
顶点着色器:
#version 330
uniform mat4 projection;
uniform mat4 modelView;
uniform vec3 lightAmbientColour;
uniform float lightAmbientIntensity;
uniform vec3 lightDiffuseAngle;
uniform vec3 lightDiffuseColour;
uniform float lightDiffuseIntensity;
layout(location = 0) in vec3 vertex;
layout(location = 1) in vec3 vertexNormal;
layout(location = 2) in vec3 materialAmbientColour;
layout(location = 3) in vec3 materialDiffuseColour;
layout(location = 4) in vec2 texCoord;
out Data {
vec4 colour;
vec2 texCoord;
} DataOut;
void main(void) {
gl_Position = projection * modelView * vec4(vertex, 1.0);
vec3 ambientComponent = lightAmbientIntensity *
(lightAmbientColour * materialAmbientColour);
ambientComponent = clamp(ambientComponent, 0.0, 1.0);
// The dot product gives us a measure of how "aligned" 2 vectors are,
// between 0 and 1. If the light direction and the vertex normal are
// well-aligned, the vertex should appear more brightly-lit.
float dotProduct = dot(lightDiffuseAngle, vertexNormal);
if (dotProduct < 0){
dotProduct = 0;
}
vec3 diffuseComponent = lightDiffuseIntensity * dotProduct *
(lightDiffuseColour * materialDiffuseColour);
diffuseComponent = clamp(diffuseComponent, 0.0, 1.0);
vec3 colourResult = max(diffuseComponent, ambientComponent);
DataOut.colour = vec4(colourResult, 1.0);
DataOut.texCoord = texCoord;
}
片段着色器:
#version 330
uniform sampler2D texUnit;
in Data {
vec4 colour;
vec2 texCoord;
} DataIn;
out vec4 fragColour;
void main() {
if (DataIn.colour.w == 0.0){
// Discard transparent fragments, so they don't affect the depth buffer
discard;
}
vec4 texColour = texture(texUnit, DataIn.texCoord);
fragColour = DataIn.colour * texColour;
}
答案 0 :(得分:4)
你应该:
glTexParameteri
移动到纹理加载/初始化中,因为它是纹理的一部分。或者使用采样器glActiveTexture
之前调用glBindTexture
Shaders.texUnitLoc
!= -1 glVertexAttribPointer
glEnableVertexAttribArray
和glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
,因为这些是vao GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
当vao被绑定时,将导致绑定vao中的ebo / ibo unbind glDrawArrays
),则不必解除任何ebo / ibo绑定enableVertexAttribArray
,您还应致电glDisableVertexAttribArray(Shaders.PARAM_TEXTURE_COORDS);
在着色器中定义相同的语义,例如:
#define VERTEX 0
#define VERTEX_NORMAL 1
#define MATERIAL_AMBIENT_COLOUR 2
#define MATERIAL_DIFFUSE_COLOUR 3
#define TEXTURE_COORDS 4
并相应地将它们分配给各种location
s
fragColour = texColour