为什么这个纹理显示全黑?
Why is this texture displaying all black?
这是我调用所有绘制操作的函数。我还在函数中内联编译着色器。当我只为每个顶点使用颜色但纹理根本不想工作时,它会正确显示四边形。
代码如下:
void doGL2() {
glTranslatef(0.f, 0.f, 0.f);
const GLchar* vertShader[] = { R"glsl(
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexPos;
out vec3 col;
out vec2 texturePos;
void main()
{
gl_Position = vec4(aPos, 1.0);
col = aColor;
texturePos = aTexPos;
}
)glsl" };
const GLchar* fragShader[] = { R"glsl(
#version 330 core
out vec4 FragColor;
in vec3 col;
in vec2 texturePos;
uniform sampler2D t;
uniform vec2 iResolution;
void main()
{
vec2 uv = gl_FragCoord.xy / iResolution;
//FragColor = vec4(iResolution, 1., 1.);
FragColor = mix(vec4(col, 1.0f), texture(t, gl_FragCoord.xy / vec2(1200., 675.)), 1.);
}
)glsl" };
vShader2 = glCreateShader(GL_VERTEX_SHADER);
fShader2 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vShader2, 1, vertShader, NULL);
glCompileShader(vShader2);
GLint success;
GLchar infoLog[1024];
glGetShaderiv(vShader2, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vShader2, 1024, NULL, infoLog);
throw std::runtime_error("\noh no vert\n");
}
glShaderSource(fShader2, 1, fragShader, NULL);
glCompileShader(fShader2);
glGetShaderiv(fShader2, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fShader2, 1024, NULL, infoLog);
throw std::runtime_error("\noh no frag\n");
}
shaderProgram2 = glCreateProgram();
glAttachShader(shaderProgram2, vShader2);
glAttachShader(shaderProgram2, fShader2);
glLinkProgram(shaderProgram2);
GLfloat screen[2] = { 1200.0f, 675.0f };
glUseProgram(shaderProgram2);
glUniform2fv(glGetUniformLocation(shaderProgram2, "iResolution"), 2, screen);
glUniform1i(glGetUniformLocation(shaderProgram2, "t"), 10);
//not sure if I should do this on cleanup or now
glDeleteShader(vShader2);
glDeleteShader(fShader2);
//lets make a temporary test texture
int width, height, channels;
unsigned char* data = stbi_load("tex2.jpg", &width, &height, &channels, 0);
GLuint tempT = 1;
glActiveTexture(GL_TEXTURE10);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tempT);
glBindTexture(GL_TEXTURE_2D, tempT);
// set texture options
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
GLfloat vertices[] = {
// positions // colors // texture positions
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom left
1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f // top right
,
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom left
0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top left
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f // top right
};
glGenVertexArrays(1, &VAO2);
glGenBuffers(1, &VBO2);
glBindVertexArray(VAO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//positions
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
//colors
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
//texture positions
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
float initTime = glutGet(GLUT_ELAPSED_TIME);
float prevTime = initTime;
float dt = 0.0f;
while (prevTime - initTime < 1000.0f) {
dt = (glutGet(GLUT_ELAPSED_TIME) - prevTime) / 1000.0f;
prevTime = glutGet(GLUT_ELAPSED_TIME);
glClearColor(1.f, 1.f, 1.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO2);
glBindTexture(GL_TEXTURE_2D, tempT);
glDrawArrays(GL_TRIANGLES, 0, 6);
SwapBuffers(GetDC(w));
glFlush();
}
}
出于某种原因,当我将纹理绑定到 GL_TEXTURE0
时,它会显示纹理。
编辑:
我正在做进一步的编辑,因为我原来的问题的内容没有正确解决问题。似乎我无法将任何纹理绑定到 GL_TEXTURE0
以外的任何纹理。我在其他论坛上看到过这个问题,但这些问题的答案都解决了这里没有的其他问题。如您所见,我正在尝试将此纹理绑定到 GL_TEXTURE10
,但输出全是黑色。但是,当我绑定到 GL_TEXTURE0
时,纹理显示正常。我更改了代码以反映 Rabbid 的回答,因为这些确实是错误,但不是影响此问题的错误;代码是最新的,反映了当前的问题。
此外,我打印了 tempT
,它总是 returns 为 1,这意味着它每次都绑定到 GL_TEXTURE0
,尽管我在 glActiveTexture()
.
如果您不生成 mipmaps (with glGenerateMipmap
),设置 GL_TEXTURE_MIN_FILTER
很重要。由于默认过滤器是 GL_NEAREST_MIPMAP_LINEAR
,如果您不将最小化函数更改为 GL_NEAREST
或 GL_LINEAR
.
,则纹理将是“Mipmap Incomplete”
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
此外,必须指定图片的大小(with
, height
)而不是(1, 1):
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
不保证stbi_load
生成具有4个颜色通道的纹理。通过显式将 4 传递给最后一个参数,强制 stbi_load
生成具有 4 个颜色通道的图像:
unsigned char* data = stbi_load("tex2.jpg", &width, &height, &channels, 0);
unsigned char* data = stbi_load("tex2.jpg", &width, &height, &channels, 4);
如果您使用着色器程序,则不需要启用纹理。是否使用纹理是在着色器程序中决定的。 glEnable(GL_TEXTURE_2D);
是遗留的 OpenGL,删除它。
除了您的代码工作正常外,我还对其进行了测试。但是,纹理单元的数量是有限的。确保使用系统范围内的纹理单元。您可以使用 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
获取纹理单元的数量。例如:
int max_units;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_units);
std::cout << "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS " << max_units << std::endl;
Also, I printed tempT
and it always returns as 1, meaning it is binding to GL_TEXTURE0 every time despite what I call in glActiveTexture()
.
纹理单元与纹理对象ID无关。 tempT
的值不表示纹理将在其中绑定的纹理单元。用glBindTexture
绑定贴图前必须先设置贴图单元,但对glGenTextures
没有影响。您可以将纹理绑定到多个纹理单元,或在不同时间绑定到不同的纹理单元。纹理单元是纹理对象和纹理采样器统一之间的绑定点。
如果你想在着色器程序中使用纹理,你需要确保纹理绑定到纹理单元并且该单元设置为纹理采样器统一。
我建议在绑定纹理并使用它来绘制对象之前设置纹理单元:
GLint t_location = glGetUniformLocation(shaderProgram2, "t")
glUseProgram(shaderProgram2);
glUniform1i(t_location, 10);
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D, tempT);
glDrawArrays(GL_TRIANGLES, 0, 6);
这是我调用所有绘制操作的函数。我还在函数中内联编译着色器。当我只为每个顶点使用颜色但纹理根本不想工作时,它会正确显示四边形。
代码如下:
void doGL2() {
glTranslatef(0.f, 0.f, 0.f);
const GLchar* vertShader[] = { R"glsl(
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexPos;
out vec3 col;
out vec2 texturePos;
void main()
{
gl_Position = vec4(aPos, 1.0);
col = aColor;
texturePos = aTexPos;
}
)glsl" };
const GLchar* fragShader[] = { R"glsl(
#version 330 core
out vec4 FragColor;
in vec3 col;
in vec2 texturePos;
uniform sampler2D t;
uniform vec2 iResolution;
void main()
{
vec2 uv = gl_FragCoord.xy / iResolution;
//FragColor = vec4(iResolution, 1., 1.);
FragColor = mix(vec4(col, 1.0f), texture(t, gl_FragCoord.xy / vec2(1200., 675.)), 1.);
}
)glsl" };
vShader2 = glCreateShader(GL_VERTEX_SHADER);
fShader2 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vShader2, 1, vertShader, NULL);
glCompileShader(vShader2);
GLint success;
GLchar infoLog[1024];
glGetShaderiv(vShader2, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vShader2, 1024, NULL, infoLog);
throw std::runtime_error("\noh no vert\n");
}
glShaderSource(fShader2, 1, fragShader, NULL);
glCompileShader(fShader2);
glGetShaderiv(fShader2, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fShader2, 1024, NULL, infoLog);
throw std::runtime_error("\noh no frag\n");
}
shaderProgram2 = glCreateProgram();
glAttachShader(shaderProgram2, vShader2);
glAttachShader(shaderProgram2, fShader2);
glLinkProgram(shaderProgram2);
GLfloat screen[2] = { 1200.0f, 675.0f };
glUseProgram(shaderProgram2);
glUniform2fv(glGetUniformLocation(shaderProgram2, "iResolution"), 2, screen);
glUniform1i(glGetUniformLocation(shaderProgram2, "t"), 10);
//not sure if I should do this on cleanup or now
glDeleteShader(vShader2);
glDeleteShader(fShader2);
//lets make a temporary test texture
int width, height, channels;
unsigned char* data = stbi_load("tex2.jpg", &width, &height, &channels, 0);
GLuint tempT = 1;
glActiveTexture(GL_TEXTURE10);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tempT);
glBindTexture(GL_TEXTURE_2D, tempT);
// set texture options
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
GLfloat vertices[] = {
// positions // colors // texture positions
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom left
1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f // top right
,
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom left
0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top left
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f // top right
};
glGenVertexArrays(1, &VAO2);
glGenBuffers(1, &VBO2);
glBindVertexArray(VAO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//positions
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
//colors
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
//texture positions
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
float initTime = glutGet(GLUT_ELAPSED_TIME);
float prevTime = initTime;
float dt = 0.0f;
while (prevTime - initTime < 1000.0f) {
dt = (glutGet(GLUT_ELAPSED_TIME) - prevTime) / 1000.0f;
prevTime = glutGet(GLUT_ELAPSED_TIME);
glClearColor(1.f, 1.f, 1.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO2);
glBindTexture(GL_TEXTURE_2D, tempT);
glDrawArrays(GL_TRIANGLES, 0, 6);
SwapBuffers(GetDC(w));
glFlush();
}
}
出于某种原因,当我将纹理绑定到 GL_TEXTURE0
时,它会显示纹理。
编辑:
我正在做进一步的编辑,因为我原来的问题的内容没有正确解决问题。似乎我无法将任何纹理绑定到 GL_TEXTURE0
以外的任何纹理。我在其他论坛上看到过这个问题,但这些问题的答案都解决了这里没有的其他问题。如您所见,我正在尝试将此纹理绑定到 GL_TEXTURE10
,但输出全是黑色。但是,当我绑定到 GL_TEXTURE0
时,纹理显示正常。我更改了代码以反映 Rabbid 的回答,因为这些确实是错误,但不是影响此问题的错误;代码是最新的,反映了当前的问题。
此外,我打印了 tempT
,它总是 returns 为 1,这意味着它每次都绑定到 GL_TEXTURE0
,尽管我在 glActiveTexture()
.
如果您不生成 mipmaps (with glGenerateMipmap
),设置 GL_TEXTURE_MIN_FILTER
很重要。由于默认过滤器是 GL_NEAREST_MIPMAP_LINEAR
,如果您不将最小化函数更改为 GL_NEAREST
或 GL_LINEAR
.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
此外,必须指定图片的大小(with
, height
)而不是(1, 1):
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
不保证stbi_load
生成具有4个颜色通道的纹理。通过显式将 4 传递给最后一个参数,强制 stbi_load
生成具有 4 个颜色通道的图像:
unsigned char* data = stbi_load("tex2.jpg", &width, &height, &channels, 0);
unsigned char* data = stbi_load("tex2.jpg", &width, &height, &channels, 4);
如果您使用着色器程序,则不需要启用纹理。是否使用纹理是在着色器程序中决定的。 glEnable(GL_TEXTURE_2D);
是遗留的 OpenGL,删除它。
除了您的代码工作正常外,我还对其进行了测试。但是,纹理单元的数量是有限的。确保使用系统范围内的纹理单元。您可以使用 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
获取纹理单元的数量。例如:
int max_units;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_units);
std::cout << "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS " << max_units << std::endl;
Also, I printed
tempT
and it always returns as 1, meaning it is binding to GL_TEXTURE0 every time despite what I call inglActiveTexture()
.
纹理单元与纹理对象ID无关。 tempT
的值不表示纹理将在其中绑定的纹理单元。用glBindTexture
绑定贴图前必须先设置贴图单元,但对glGenTextures
没有影响。您可以将纹理绑定到多个纹理单元,或在不同时间绑定到不同的纹理单元。纹理单元是纹理对象和纹理采样器统一之间的绑定点。
如果你想在着色器程序中使用纹理,你需要确保纹理绑定到纹理单元并且该单元设置为纹理采样器统一。
我建议在绑定纹理并使用它来绘制对象之前设置纹理单元:
GLint t_location = glGetUniformLocation(shaderProgram2, "t")
glUseProgram(shaderProgram2);
glUniform1i(t_location, 10);
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D, tempT);
glDrawArrays(GL_TRIANGLES, 0, 6);