首页 文章

OpenGL:在着色器中实现的Blinn-Phong模型给出了错误的结果

提问于
浏览
1

首先,我是计算机图形学,openGL的新手,并具有c编码的基本知识 . 我已经和openGL项目一样挣扎了一个月,并且已经到了我必须用Blinn-Phong模型实现着色的地步 . 我已经在顶点和片段着色器中实现了计算 . 在代码中存在/可能存在一些小错误,因为没有着色一切都可以完美地工作但是在着色部分被添加到着色器后,任何事情都不会发生 . 我在片段着色器中计算表面法线,也使用纹理而不仅仅是颜色 . 我还使用每个对象(总共7个对象)自己的着色器 .

如果有人立刻看到我做错了,我会很高兴的 . 我不再犯错误,所以错误就是实施 .

以下是一个对象顶点和片段着色器的代码 .

Vertex shader:

#version 330 core
layout (location=0) in vec3 in_Position;
layout (location=3) in vec2 in_TexCoord0;

// mvpmatrix is the result of multiplying the model, view, and projection matrices
uniform mat4 mvpmatrix;

// Texture coordinate for the fragment shader
out vec2 f_TexCoord0;
out vec3 out_Position;

void main(void)
{
    gl_Position = mvpmatrix * vec4(in_Position, 1.0);
    out_Position = in_Position;

    f_TexCoord0 = in_TexCoord0;
}

Fragment shader:

#version 330 core
uniform sampler2D texture1;
in vec2 f_TexCoord0;
in vec3 out_Position;
layout (location=0) out vec4 fragColor;

uniform vec4 ambientMaterial2, diffuseMaterial2, specularMaterial2;
uniform vec4 ambientLight, diffuseLight, specularLight;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform vec4 lightPosition;
uniform float shininess;

void main(void)
{
    vec4 ambientProduct = ambientLight * ambientMaterial2;
    vec4 diffuseProduct = diffuseLight * diffuseMaterial2;
    vec4 specularProduct = specularLight * specularMaterial2;

    vec3 pos = out_Position.xyz;
    vec3 nv = cross(dFdx(pos),dFdy(pos));
    nv = nv * sign(nv.z);
    vec3 L = normalize(lightPosition.xyz - nv);
    vec3 E = normalize(-nv); 
    vec3 H = normalize(L + E);
    vec3 N = nv;

    float Kd = max(dot(L, N), 0.0);
    vec4 diffuse = Kd * diffuseProduct;

    vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
    if (Kd > 0.0f)
    {
        float Ks = dot(H, N);
        if (Ks > 0.0f)
            {
            specular = pow(Ks, shininess) * specularProduct;
            }
    }
    vec4 fragColor_lightning = (ambientProduct + diffuse + specular);
    vec4 fragColor_texture = texture2D(texture1, vec2(f_TexCoord0.x, f_TexCoord0.y));
    fragColor = fragColor_lightning + fragColor_texture;
}

Edit:

更改着色器:

Vertex shader:

#version 330 core
layout (location=0) in vec3 in_Position;
layout (location=3) in vec2 in_TexCoord0;

// mvpmatrix is the result of multiplying the model, view, and projection matrices
uniform mat4 mvpmatrix;
uniform mat4 modelMat;

// Texture coordinate for the fragment shader
out vec2 f_TexCoord0;
out vec3 viewPos;

void main(void)
{
    gl_Position = mvpmatrix * vec4(in_Position, 1.0);
    viewPos = (modelMat * vec4(in_Position, 1.0)).xyz;
    f_TexCoord0 = in_TexCoord0;
}

Fragment shader:

#version 330 core
uniform sampler2D texture1;
in vec2 f_TexCoord0;
in vec3 viewPos;
layout (location=0) out vec4 fragColor;

uniform vec4 ambientMaterial2, diffuseMaterial2, specularMaterial2;
uniform vec4 ambientLight, diffuseLight, specularLight;
uniform mat4 viewMat;
uniform vec4 lightPosition;
uniform float shininess;

void main(void)
{
    vec4 ambientProduct = ambientLight * ambientMaterial2;
    vec4 diffuseProduct = diffuseLight * diffuseMaterial2;
    vec4 specularProduct = specularLight * specularMaterial2;

    vec3 pos = viewPos;
    vec3 nv = cross(dFdx(pos),dFdy(pos));
    nv = nv * sign(nv.z);
    vec3 L = normalize((viewMat*lightPosition).xyz - pos);
    vec3 E = normalize(-pos); 
    vec3 H = normalize(L + E);
    vec3 N = normalize(nv);

    float Kd = max(dot(L, N), 0.0);
    vec4 diffuse = Kd * diffuseProduct;

    vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
    if (Kd > 0.0f)
    {
        float Ks = pow(max(dot(H, N),1.0),shininess);
        specular = Ks * specularProduct;
    }
    vec4 fragColor_lightning = (ambientProduct + diffuse + specular);
    vec4 fragColor_texture = texture2D(texture1, vec2(f_TexCoord0.x, f_TexCoord0.y));
    fragColor = fragColor_lightning + fragColor_texture;
}

1 回答

  • 2

    您必须将模型视图投影矩阵拆分为模型视图矩阵和投影矩阵 . 使用模型视图矩阵,可以计算视图位置并将其传递给片段着色器 . 利用投影矩阵,可以计算剪辑空间位置 .

    #version 330 core
    layout (location=0) in vec3 in_Position;
    layout (location=3) in vec2 in_TexCoord0;
    
    uniform mat4 modelview;
    uniform mat4 projection;
    
    out vec2 f_TexCoord0;
    out vec3 viewPos;
    
    void main(void)
    {
        vec4 pos = modelview * vec4(in_Position, 1.0);;
    
        f_TexCoord0 = in_TexCoord0;
        viewPos     = pos.xyz;
        gl_Position = projection * pos;
    }
    

    要计算blinn phong灯模型,请参阅GLSL fixed function fragment program replacement

    像这样改变你的代码:

    in vec3 viewPos;
    
    uniform vec4 lightPosition; // this has to be a view space position
    uniform float shininess;
    
    void main()
    {
        ....
    
        vec3 N = cross(dFdx(viewPos.xyz),dFdy(viewPos.xyz));
        N = normalize(N * sign(N.z));
    
        vec3 L = normalize(lightPosition.xyz - viewPos.xyz);
        vec3 E = normalize(-viewPos.xyz); 
        vec3 H = normalize(L + E);
    
        float Kd = max(dot(L, N), 0.0);
        vec4 diffuse = Kd * diffuseProduct;
    
        vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
        if (Kd > 0.0f)
        {
            float Ks = max(0.0, dot(H, N));
            specular = pow(Ks, shininess) * specularProduct;
        }
    
        .....
    }
    

    Edit:

    当你执行 viewPos = (modelMat * vec4(in_Position, 1.0)).xyz; 时, viewPos 不是视图位置,而是模型位置 . 要计算视图位置,您必须通过模型矩阵和视图矩阵进行变换: viewPos = (viewMat * modelMat * vec4(in_Position, 1.0)).xyz; .

    #version 330 core
    layout (location=0) in vec3 in_Position;
    layout (location=3) in vec2 in_TexCoord0;
    
    // mvpmatrix is the result of multiplying the model, view, and projection matrices
    uniform mat4 mvpmatrix;
    uniform mat4 viewMat;
    uniform mat4 modelMat;
    
    // Texture coordinate for the fragment shader
    out vec2 f_TexCoord0;
    out vec3 viewPos;
    
    void main(void)
    {
        gl_Position = mvpmatrix * vec4(in_Position, 1.0);
        viewPos = (viewMat * modelMat * vec4(in_Position, 1.0)).xyz;
        f_TexCoord0 = in_TexCoord0;
    }
    

    此外,我建议将纹理的颜色乘以浅色:

    fragColor = vec4(fragColor_lightning.rgb * fragColor_texture.rgb, fragColor_texture.a);
    

相关问题