OpenGL:在着色器中实现的Blinn-Phong模型给出错误的结果 [英] OpenGL: Blinn-Phong model implemented in shaders give wrong result

查看:120
本文介绍了OpenGL:在着色器中实现的Blinn-Phong模型给出错误的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

First of all I'm new with computer graphics, openGL and have a basic knowledge of c++ coding. I have struggled with the openGL project like a month and have come to a point where I have to implement shading with Blinn-Phong model. I have implemented calculations in vertex and fragment shaders. There is/are propably some minor error(s) in code because without shading everything works perfectly but after shading parts are added to shaders anything does not happen. I calculate surface normals in fragment shader and also use textures instead of just colors. I also use for every objects (in total 7 objects) own shader.

如果有人马上看到我做错的地方,我会很高兴.我不再遇到错误,因此错误可能是在实施中.

I would be very happy if someone see right away where I'm doing wrong. I don't get errors anymore so propably the mistake is in implementation.

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

Here are the code for one objects vertex and fragment shaders.

顶点着色器:

#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;
}

片段着色器:

#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;
}


已更改的着色器:

顶点着色器:

#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;
}

片段着色器:

#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;
}

推荐答案

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

You have to split the model view projection matrix to a model view matrix and a projection matrix. With the model view matrix the view position can be calculated and passed to the fragment shader. With the projection matrix the clip space position can be calculated.

#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;
}

有关计算布林犬灯光模型的信息,另请参见 GLSL固定函数片段程序替换

For calculating a blinn phong light model see also 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;
    }

    .....
}


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

When you do viewPos = (modelMat * vec4(in_Position, 1.0)).xyz; then viewPos is not a view position, but a model position. To calculate a view position you have to transform by the model matrix and the view matrix: 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;
}


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


Further I recommend to multiply the color of the texture by the light color:

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

这篇关于OpenGL:在着色器中实现的Blinn-Phong模型给出错误的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆