我正在尝试使用 opengl 2.1 和 glsl 120 显示纹理(是的,它是一个锅),但我不确定如何做到这一点,我所能得到的只是一个黑色四边形,我一直在关注这个教程:纹理立方体,OpenGl - 纹理,我所理解的是我需要:
指定附加到每个顶点的纹理坐标(在我的例子中是 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
所以我尝试“转换”代码,还有这个教程:简单纹理 - LightHouse 解释了 gl_MultiTexCoord0
属性和 gl_TexCoord
数组是内置的,但这几乎与我正在做的事情相同。我想知道是否做得好,如果没有,我想知道如何使用 opengl 2.1 和 glsl 120 在屏幕上显示简单的 2d 纹理
您是否有特殊原因将 opengl 2.1 与 glsl 版本 1.2 一起使用?如果不坚持使用 openGl 3.0,因为恕我直言,它更容易理解。 我猜你有两个大问题:
首先获得一个黑色四边形:如果它的大小占据了您的孔应用程序,那么它的背景颜色。这意味着它根本不绘制任何东西。 我认为(通过测试这个)OpenGL有一个默认程序,即使你已经在gpu上设置了一个顶点数组/缓冲区对象,它也会激活。它应该在你的窗口中渲染为一个白色的四边形......所以这可能是你的第一个问题。我不知道 opengl 2.1 是否有顶点缓冲区数组,但 opengl 3.0 有,你应该充分利用它!
第二:你在渲染阶段不使用你的着色器程序; 在绘制四边形之前调用此函数:
glUseProgram(myProgram); // The myProgram variable is your compiled shader program
如果您希望我解释如何使用 OpegGL 3.0 ++ 绘制您的四边形,请告诉我:) ...这与您在代码中已经编写的内容相去不远。