我的问题类似于这里提到的问题。
Question 1
Question 2
我的Github提交:
Commit here
当我尝试用C++在windows上用opengl 3.3绘制一个立方体时,glfw很高兴我遇到了这个问题,它只显示了一个基于原始纹理的纯色(颜色?)。这似乎是一个没有应用纹理坐标的问题。着色器和cpp代码,还有RenderDoc。如果你需要的话,可以要求更多。
顶点着色器:
# version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
layout (location = 2) in vec3 aNormal;
out vec3 FragPos;
out vec2 TexCoord;
out vec3 Normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
gl_Position = projection * view * model * vec4(aPos, 1.0f);
FragPos = vec3(model * vec4(aPos, 1.0));
TexCoord = aTexCoord;
Normal = aNormal;
};
片段着色器
- 只有制服和主要功能是重要的
- 在vec4中的注解只改变了照明并使其看起来是3d的
# version 330 core
in vec3 FragPos;
in vec2 TexCoord;
in vec3 Normal;
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform DirLight dirLight;
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
struct PointLight {
vec3 position;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
# define NR_POINT_LIGHTS 1
uniform PointLight pointLights[NR_POINT_LIGHTS];
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
struct Material {
vec3 specular;
float shininess;
};
uniform Material material;
uniform sampler2D tex_sampler;
uniform vec3 viewPos;
out vec4 FragColor;
void main()
{
// properties
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
// phase 1: Directional lighting
vec3 result = CalcDirLight(dirLight, norm, viewDir);
// phase 2: Point lights
for(int i = 0; i < NR_POINT_LIGHTS; i++)
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
FragColor = texture(tex_sampler, TexCoord);// * vec4(result, 1.0);
}
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// combine results
vec3 ambient = light.ambient * vec3(texture(tex_sampler, TexCoord));
vec3 diffuse = light.diffuse * diff * vec3(texture(tex_sampler, TexCoord));
vec3 specular = light.specular * spec * vec3(1.0f, 0.0f, 0.0f);
//return (ambient + diffuse + specular);
return (ambient + diffuse);
}
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance +
light.quadratic * (distance * distance));
// combine results
vec3 ambient = light.ambient * vec3(texture(tex_sampler, TexCoord));
vec3 diffuse = light.diffuse * diff * vec3(texture(tex_sampler, TexCoord));
vec3 specular = light.specular * spec * vec3(1.0f, 1.0f, 1.0f);
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular);
}
我加载纹理并绘制立方体:
第一个
buffers.cpp:
//VAO
VAO::VAO() {
glGenVertexArrays(1, &this->vaoID);
}
void VAO::bind(){
glBindVertexArray(this->vaoID);
}
void VAO::fillFirst() {
this->bind();
this->vbos[0].fillBuffer();
this->setAttribPointer(0, 3, GL_FLOAT, false, 8, 0);
this->setAttribPointer(1, 2, GL_FLOAT, false, 8, 3);
this->setAttribPointer(2, 3, GL_FLOAT, false, 8, 5);
if (this->ebos.size() > 0) {
this->ebos[0].fillBuffer();
}
}
void VAO::setAttribPointer(int attribID, int length, int type, bool normalized, int stride, int offset) {
this->bind();
glVertexAttribPointer(
attribID,
length,
type,
normalized,
stride * sizeof(float),
(void*)(offset * sizeof(float))
);
glEnableVertexAttribArray(attribID);
}
//VBO
VBO::VBO(std::vector<Vertex> vertices) {
glGenBuffers(1, &this->vboID);
this->vertices = vertices;
}
void VBO::fillBuffer() {
glBindBuffer(GL_ARRAY_BUFFER, this->vboID);
std::cout << sizeof(this->vertices[0]) << ":" << sizeof(&this->vertices[0]) << std::endl;
glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(this->vertices[0]), &this->vertices[0], GL_STATIC_DRAW);
}
渲染文件:
编辑1:我用FragColor = vec4(TexCoord.x * TexCoord.x, TexCoord.y * TexCoord.y, 1.0, 1.0);
替换了fragment shader中的FragColor = texture(tex_sampler, TexCoord);// * vec4(result, 1.0);
,这导致了颜色的规则变化,并暗示了纹理坐标被传递到fragment shader。似乎有错误或缺少使用opengl纹理所需的部分。
1条答案
按热度按时间isr3a4wc1#
你可以在renderdoc中清楚地看到你的着色器接收到的纹理坐标是完全错误的。如果你仔细观察,你甚至可以看到你的
aTexCoord
向量是你的法线的x
和y
分量。粘贴到这个问题中的代码看起来好像你的顶点格式是
posX, posY, posZ, texU, texV, nrmX, nrmY, nrmZ
,而这正是你用glVertexAttribPointer
设置的。但是你遗漏了代码中的一个重要部分:实际写入缓冲区的数据是什么,缓冲区中的数据是:因此,您实际上将这些数据重新组织为不同的格式,定义为:
这仅仅意味着您使用法线的前两个分量作为纹理坐标,并使用法线的第三个分量和纹理坐标作为法线。