opengl纹理是由纹理组成的一种颜色

s5a0g9ez  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(253)

我的问题类似于这里提到的问题。
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纹理所需的部分。

isr3a4wc

isr3a4wc1#

你可以在renderdoc中清楚地看到你的着色器接收到的纹理坐标是完全错误的。如果你仔细观察,你甚至可以看到你的aTexCoord向量是你的法线的xy分量。
粘贴到这个问题中的代码看起来好像你的顶点格式是posX, posY, posZ, texU, texV, nrmX, nrmY, nrmZ,而这正是你用glVertexAttribPointer设置的。但是你遗漏了代码中的一个重要部分:实际写入缓冲区的数据是什么,缓冲区中的数据是:

std::vector<Vertex> cubevert;     
for (int i = 0; i < sizeof(cube_vertices) / szeof(float); i += 8) {       
  Vertex vert;
  vert.Position = glm::vec3(cube_vertices[i], cube_vertices[i + 1], cube_vertices[i + 2]);
  vert.TexCoords = glm::vec2(cube_vertices[i +> 3], cube_vertices[i + 4]);
  vert.Normal = glm::vec3(cube_vertices[i +> 5], cube_vertices[i + 6], cube_vertices[i + 7]);
  cubevert.push_back(vert);
}

因此,您实际上将这些数据重新组织为不同的格式,定义为:

struct Vertex {
  glm::vec3 Position;
  glm::vec3 Normal;
  glm::vec2 TexCoords;
};

这仅仅意味着您使用法线的前两个分量作为纹理坐标,并使用法线的第三个分量和纹理坐标作为法线。

相关问题