问题描述
我正在尝试在整个窗口上显示图像。 为此,我只绘制一个矩形,该矩形将整个窗口并为其应用纹理。
问题是图像根本无法填满整个屏幕: Output image
图像不是太小,因为它是5600 x3000。而且,我也不想重复图像。我不是我想念的东西,为什么它没有填满屏幕,为什么它只在左上角。我已经尝试过此解决方案,但无法正常工作:Texture does not fit in the square - OpenGL
这是我创建和绑定着色器的方法:
Shader::Shader(const char* vertSrcFile,const char* fragSrcFile,const char* texSrcFile) {
gluint vertShader = glCreateShader(GL_VERTEX_SHADER);
gluint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
GLint vlen;
GLint flen;
char* source = loadFile(vertSrcFile,vlen);
char* fragment = loadFile(fragSrcFile,flen);
glShaderSource(vertShader,1,&source,&vlen);
glShaderSource(fragShader,&fragment,&flen);
GLint compiled = 0;
glCompileShader(vertShader);
glGetShaderiv(vertShader,GL_COMPILE_STATUS,&compiled);
if (!compiled) {
GLint maxLength = 0;
glGetShaderiv(vertShader,GL_INFO_LOG_LENGTH,&maxLength);
// The maxLength includes the NULL character
std::vector<GLchar> infoLog(maxLength);
glGetShaderInfoLog(vertShader,maxLength,&maxLength,&infoLog[0]);
// We don't need the shader anymore.
glDeleteShader(vertShader);
Logger::GetSystemLogger()->error("Vertex shader compilation error");
Logger::GetSystemLogger()->error("{}",infoLog.data());
return;
}
glCompileShader(fragShader);
glGetShaderiv(fragShader,&compiled);
if (!compiled) {
GLint maxLength = 0;
glGetShaderiv(fragShader,&maxLength);
// The maxLength includes the NULL character
std::vector<GLchar> infoLog(maxLength);
glGetShaderInfoLog(fragShader,&infoLog[0]);
// We don't need the shader anymore.
glDeleteShader(fragShader);
Logger::GetSystemLogger()->error("Fragment shader compilation error");
Logger::GetSystemLogger()->error("{}",infoLog.data());
return;
}
prog = glCreateProgram();
glAttachShader(prog,vertShader);
glAttachShader(prog,fragShader);
glLinkProgram(prog);
GLint isLinked = 0;
glGetProgramiv(prog,GL_LINK_STATUS,(int*)&isLinked);
if (isLinked == GL_FALSE)
{
GLint maxLength = 0;
glGetProgramiv(prog,&maxLength);
// The maxLength includes the NULL character
std::vector<GLchar> infoLog(maxLength);
glGetProgramInfoLog(prog,&infoLog[0]);
// We don't need the program anymore.
glDeleteProgram(prog);
// Don't leak shaders either.
glDeleteShader(vertShader);
glDeleteShader(fragShader);
Logger::GetSystemLogger()->error("Program link error");
Logger::GetSystemLogger()->error("{}",infoLog.data());
return;
}
glDetachShader(prog,vertShader);
glDetachShader(prog,fragShader);
glGenTextures(1,&texID); // generate texture ID
glBindTexture(GL_TEXTURE_2D,texID);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_BORDER);
LoadTexture(texSrcFile);
}
这是我将图像加载为纹理的方式:
void Shader::LoadTexture(const char* texSrcFile) const {
int width,height,nrChannels;
unsigned char* data = stbi_load(texSrcFile,&width,&height,&nrChannels,0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D,GL_RGB,width,GL_UNSIGNED_BYTE,data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
Logger::GetSystemLogger()->error("Failed to load textures");
}
stbi_image_free(data);
}
这是我的着色器: 片段:
#version 330
precision highp float; // needed only for version 1.30
layout(location = 0) out vec4 out_Color;
in vec2 ex_Tex;
uniform sampler2D textureUnit0;
void main(void){
out_Color = texture(textureUnit0,ex_Tex);
}
顶点:
#version 330
layout (location = 0) in vec3 in_Position;
layout (location = 1) in vec2 in_Tex;
out vec2 ex_Tex;
void main(void){
gl_Position = vec4(in_Position,1.0);
ex_Tex = in_Tex;
}
这是主要代码:
glGenVertexArrays(1,&m_VAO);
glBindVertexArray(m_VAO);
glGenBuffers(1,&m_VBO);
glBindBuffer(GL_ARRAY_BUFFER,m_VBO);
GLfloat vertices[4 * 5]{
// Positions // Textures
-1.0f,-1.0f,0.0f,1.0f,0.0f
};
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
// Position
glEnabLevertexAttribArray(0);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,5 * sizeof(float),nullptr);
// Texture coord
glEnabLevertexAttribArray(1);
glVertexAttribPointer(1,2,nullptr);
glGenBuffers(1,&m_IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,m_IBO);
unsigned int indices[6] = { 0,3 };
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);
m_Shader = std::make_shared<Engine::Shader>("src/Shaders/Background.vert","src/Shaders/Background.frag","res/background.jpg");
这是主循环
while (m_Running) {
// clear the screen and set the background color to grey
glClearColor(0.5f,0.5f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
m_Shader->Bind();
glBindTexture(GL_TEXTURE_2D,m_Shader->GetTexID());
glBindVertexArray(m_VAO);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,nullptr);
m_Window->OnUpdate();
}
解决方法
尽管视口坐标从负1变为一[-1,1)
,但是纹理坐标从零变为1 [0,1)
。因此,根据GL_CLAMP_TO_BORDER
政策,视口的四分之三被黑色填充。
您需要按以下步骤修正VAO坐标:
GLfloat vertices[4 * 5]{
// Positions // Textures
-1.0f,-1.0f,0.0f,1.0f,0.0f
};
编辑:您的纹理坐标偏移也不正确。应该是:
// Texture coord
glEnableVertexAttribArray(1);
glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,5 * sizeof(float),(void*)(3*sizeof(float)));
如果没有适当的偏移,它将使用纹理坐标位置的X和Y。