【发布时间】:2017-02-13 02:43:02
【问题描述】:
我正在尝试使用 opengl 2.1 和 glsl 120 显示纹理(是的,它是一个锅),但我不知道该怎么做,我只能得到一个黑色四边形,我一直遵循本教程:A Textured Cube,OpenGl - Textures,我的理解是我需要:
- 指定要附加到每个顶点的纹理坐标(在我的例子中是 6 个顶点,一个没有索引的立方体)
- 加载纹理并将其绑定到纹理单元中(默认为0)
调用 glDrawArrays
在着色器中我需要:
- 在顶点着色器的属性中接收纹理坐标,并通过可变变量将其传递给片段着色器
- 在片段着色器中,使用采样器对象在可变变量指定的位置从纹理中采样像素。
一切都正确吗?
这是我如何创建纹理 VBO 并加载纹理:
void Application::onStart(){
unsigned int format;
SDL_Surface* img;
float quadCoords[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f};
const float texCoords[] = {
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f};
//shader loading omitted ...
sprogram.bind(); // call glUseProgram(programId)
//set the sampler value to 0 -> use texture unit 0
sprogram.loadValue(sprogram.getUniformLocation(SAMPLER), 0);
//quad
glGenBuffers(1, &quadBuffer);
glBindBuffer(GL_ARRAY_BUFFER, quadBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*18, quadCoords, GL_STATIC_DRAW);
//texture
glGenBuffers(1, &textureBuffer);
glBindBuffer(GL_ARRAY_BUFFER, textureBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*12, texCoords, GL_STATIC_DRAW);
//load texture
img = IMG_Load("resources/images/crate.jpg");
if(img == nullptr)
throw std::runtime_error(SDL_GetError());
glGenTextures(1, &this->texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, this->texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->w, img->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, img->pixels);
SDL_FreeSurface(img);
}
渲染阶段:
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(COORDS);
glBindBuffer(GL_ARRAY_BUFFER, quadBuffer);
glVertexAttribPointer(COORDS, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(TEX_COORDS);
glBindBuffer(GL_ARRAY_BUFFER, textureBuffer);
glVertexAttribPointer(TEX_COORDS, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
//draw the vertices
glDrawArrays(GL_TRIANGLES, 0, 6);
顶点着色器:
#version 120
attribute vec3 coord;
attribute vec2 texCoord;
varying vec2 UV;
void main(){
gl_Position = vec4(coord.x, coord.y, coord.z, 1.0);
UV = texCoord;
}
片段着色器:
#version 120
uniform sampler2D tex;
varying vec2 UV;
void main(){
gl_FragColor.rgb = texture2D(tex, UV).rgb;
gl_FragColor.a = 1.0;
}
我知道教程使用 out 而不是 varying 所以我尝试“转换”代码,还有这个教程:Simple Texture - LightHouse 解释了 gl_MultiTexCoord0 属性和 gl_TexCoord 数组内置,但这几乎是我正在做的事情。我想知道是否做得很好,如果没有,我想知道如何使用 opengl 2.1 和 glsl 120 在屏幕上显示简单的 2d 纹理
【问题讨论】:
-
将纹理绑定到采样器的部分在哪里?
-
@immibis,在绑定我的纹理之前,我调用
glActiveTexture(GL_TEXTURE0)这是着色器中的默认采样器 -
不确定这是否是您的全部代码,但您似乎没有设置纹理过滤器。默认缩小过滤器带有 mipmap,并且您的纹理不是 mipmap 完整的(因此采样不起作用)。
-
@dehass,就是这样,我添加了
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);和glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);,它现在正在工作,我真的想做一个极简纹理渲染器测试,我决定使用这个函数调用离开。感谢您的解决方案