在片段着色器中插入/混合反射和光泽

时间:2016-02-06 23:41:38

标签: opengl interpolation fragment-shader

我正在尝试实施Blinn-Phong,Cool-Torrance和GGX灯光模型。我已经实现了前2个光模型,但现在我试图修复并弄清楚如何在漫反射和光泽之间进行插值。

我的场景将包含3行(每行是上面提到的灯光模型之一),其中10个球体,每个球体都有光泽因子.1更大,立方体贴图作为反射/漫反射纹理。

我正在尝试找到有关如何进行插值的有用信息,但我想我现在正在搜索错误的内容。

我的片段着色器代码现在看起来像这样。 PS,我很抱歉代码中留下的所有评论,但我相信它会帮助你看到我想要做的事情。

#version 410 core

#include "../Global/GlobalShader.inc"
#include "../Global/GlobalMesh.inc"
#include "../Global/GlobalLight.inc"

in vec3 Position;
in vec3 Normal;
in vec2 TexCoord;

uniform vec3 cameraPosition;
uniform samplerCube skybox;
uniform DirectionalLight directionalLight;

float specularStrength = 16.0; // to be implemented and be send at parameter

out vec4 gl_FragColor;

vec4 calculateDirectionalLight1(Light light, vec3 direction, vec3 normal, vec3 worldPosition, float specularIntensity, vec3 eyePosition, Material material, vec2 texCoord, vec4 diffuse)
{
    vec3 diffuseFactor = (light.color * diffuse * (light.intensity * clamp(dot(normal, direction), 0.0, 1.0)));

    vec3 viewDir = normalize(eyePosition - worldPosition);
    vec3 reflectDir = normalize(reflect(-direction, normal));

    float shininess = (material.shininess / 1000.0);
    float specularFactor = pow(clamp(dot(viewDir, reflectDir), 0.0, 1.0), specularIntensity);
    vec3 specularColor = (light.color * material.specular) * (specularFactor * shininess);

    //return vec4(pow((diffuseFactor + specularColor + light.ambient), GAMMA), 1.0);
    return vec4(pow((diffuseFactor + specularColor), GAMMA), 1.0);

    //return specularColor;
    //return diffuseFactor;
    //return shininess;
    //return diffuse;
}

void main() {

    vec4 tempColor = vec4(0.2);
    //vec4 tempColor = vec4(1.0, 0.0, 0.0, 0.0);

    //vec4 diffuse = vec4(texture(material.texture.diffuse, TexCoord.st).rgb, 1.0); // *material.diffuse) - vec4(1.0 - material.specular);

    vec3 I = normalize(Position - cameraPosition);
    vec3 R = reflect(I, normalize(Normal));
    vec4 reflection = texture(skybox, R);

    // fix blending/interpolation for light
    float shininess = (material.shininess / 1000.0);
    //gl_FragColor = diffuse * (reflection * shininess) * material.specular;
    //vec4 tempFinalDiffuse = mix(diffuse, reflection, shininess);
    vec4 tempFinalDiffuse = mix(tempColor, reflection, shininess);

    vec4 light = vec4(1.0);
    light = calculateDirectionalLight1(directionalLight.light, directionalLight.position, Normal, Position, specularStrength, cameraPosition, material, TexCoord, tempFinalDiffuse);

    //gl_FragColor = mix(tempFinalDiffuse, light, shininess);
    //gl_FragColor = diffuse;
    //gl_FragColor = vec4(shininess);
    //gl_FragColor = tempFinalDiffuse * light;
    //gl_FragColor = reflection;
    gl_FragColor = light;
    //gl_FragColor = tempFinalDiffuse;
}

enter image description here

1 个答案:

答案 0 :(得分:0)

在阅读了Hammersley Points on the Hemisphere并了解它们之后,我设法使用了虚幻引擎4中Real Shading中提供的代码并对立方体贴图进行了采样,从而获得了更好的结果。

事情进展缓慢,但我最终到达那里,希望到目前为止,我正在做正确的事情。

这是我的功能结束的方式

vec4 brdf_GGX(Light light, vec3 direction, vec3 normal) {

    float specular = 0.0;

    float matShininess = 1.0 - (material.shininess / 1000.0);

    vec2 randomPoint;
    vec4 finalColor = vec4(0.0);
    vec4 totalLambert = vec4(0.0);

    const uint numberSamples = 32;
    for (uint sampleIndex = 0; sampleIndex < numberSamples; sampleIndex++)
    {
        randomPoint = hammersley2d(sampleIndex, numberSamples);

        vec3 H = ImportanceSampleGGX(randomPoint, matShininess, vec3(0.0, 1.0, 0.0));
        vec3 L = 2.0 * dot(normal, H) * H - normal;

        vec3 R = reflect(L, normalize(normal));
        totalLambert += texture(skybox, L);
    }

    totalLambert = totalLambert / numberSamples;

    float NdotL = max(dot(normal, direction), 0.0);
    if (NdotL > 0.0)
    {
        vec3 eyeDir = normalize(cameraPosition);

        // calculate intermediary values
        vec3 halfVector = normalize(direction + eyeDir);
        float NdotH = max(dot(normal, halfVector), 0.0);
        float NdotV = max(dot(normal, eyeDir), 0.0);
        float VdotH = max(dot(eyeDir, halfVector), 0.0);

        float mSquared = clamp(matShininess * matShininess, 0.01, 0.99);

        float geoAtt = G(NdotH, NdotV, VdotH, NdotL);

        float roughness = D_Beckmann(NdotH, mSquared);
        float fresnel = R_Fresnel(VdotH);

        specular = (fresnel * geoAtt * roughness) / (NdotV * NdotL * PI);
    }   
        vec3 finalValue = light.color * NdotL * (k + specular * (1.0 - k));

        return vec4(finalValue, 1.0) * totalLambert;
}

            vec3 finalValue = light.color * NdotL * (k + specular * (1.0 - k));
            return vec4(finalValue, 1.0) * totalLambert;
  }