当前位置: 动力学知识库 > 问答 > 编程问答 >

opengl - Interpolating/blending reflection and shinines in fragment shader

问题描述:

I am trying to implement a Blinn-Phong, Cool-Torrance, and GGX light models. I have implemented the first 2 light models but now I trying to fix and figure out how to do interpolation between diffuse and shininess.

My scene will consists of 3 rows (each row is one of the light model mentioned above) with 10 spheres where each sphere has shininess factor .1 bigger and a cube map as reflection/diffuse texture.

I am trying to find something useful on how to do this interpolation but I guess I am googling the wrong thing now.

My fragment shader code now looks like this. PS, I am sorry for all the comments left in the code but I believe it will help you see what I was trying to do.

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

}

网友答案:

After some reading about Hammersley Points on the Hemisphere and understanding them I managed to use the code provided in Real Shading in Unreal Engine 4 and sample the cube map, thus giving a much better result.

Things are going pretty slow but I am getting there eventually and hopefully I am doing the right thing so far with implementation.

This is how my function ended

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;
  }
分享给朋友:
您可能感兴趣的文章:
随机阅读: