PDA

View Full Version : How to improve my metal effect?



paul_g_griffiths
02-16-2017, 09:31 PM
https://s31.postimg.org/bdntzaeqj/metal.jpg

I think if I mix this with a cupemap effect then ill have something pretty good?

Here's the shader function, it's a mix from 2 different codes, I thought one was for metal so I played with it until it looked like metal though since then I have learned it was not for metal.
Not too bad for a first attempt? The gold looks good. :)
It turns white to silver and yellow to gold.


vec3 CalcMetalPointLight(Light light, vec3 normal, vec3 fragPos, vec3 viewDir, vec3 Diffuse, float Specular, float Shadow)
{
vec3 lightDir = normalize(light.Position - fragPos);
// Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);


// set important material values
float roughnessValue = 0.1; // 0 : smooth, 1: rough
float F0 = 0.0; // fresnel reflectance at normal incidence
float k = 1.0; // fraction of diffuse reflection (specular reflection = 1 - k)
// do the lighting calculation for each fragment.

float spec = 0.0;
if(diff > 0.0)
{
// calculate intermediary values
vec3 halfVector = normalize(lightDir + viewDir);
float NdotH = max(dot(normal, halfVector), 0.0);
float NdotV = max(dot(normal, viewDir), 0.0); // note: this could also be diff, which is the same value
float VdotH = max(dot(viewDir, halfVector), 0.0);
float mSquared = roughnessValue * roughnessValue;

// geometric attenuation
float NH2 = 2.0 * NdotH;
float g1 = (NH2 * NdotV) / VdotH;
float g2 = (NH2 * diff) / VdotH;
float geoAtt = min(1.0, min(g1, g2));

// roughness (or: microfacet distribution function)
// beckmann distribution function
float r1 = 1.0 / ( 4.0 * mSquared * pow(NdotH, 4.0));
float r2 = (NdotH * NdotH - 1.0) / (mSquared * NdotH * NdotH);
float roughness = r1 * exp(r2);

// fresnel
// Schlick approximation
float fresnel = pow(1.0 - VdotH, 5.0);
fresnel *= (1.0 - F0);
fresnel += F0;

// Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 1.0) * (fresnel * geoAtt * roughness) / (NdotV * diff * 3.14);
}

// Attenuation
float distance = length(light.Position - fragPos);
float attenuation = 1.0f / (1.0 + light.Linear * distance + light.Quadratic * (distance * distance));
// Combine results
vec3 ambient = light.Color * Diffuse;
vec3 diffuse = light.Color * Diffuse * diff;
vec3 specular = light.Specular * spec * Specular;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;

return (ambient + (1.0 - Shadow)) * diff * (k + spec * (1.0 - k)) + 2.0 * (diffuse + specular);
}

Silence
02-17-2017, 04:04 AM
The way people are generally doing it is something like this:

With the empirical method:

Have a material that matches metals (with setting ambient, diffuse, specular and shininess)
Use this material in the model
Render the model with Blinn/Phong lighting
Eventually add some extra effects

With some kind of physically accurate rendering, this would look like:

Measure how a metal object reacts to lighting. Store these information into some BRDF/BSDF...
Use these BRDF with a model
Render it threw some accurate lighting models (ie based on Cook Torrance function)

You can have more information for the latter by reading about PBR, global illumation and more generally optical books.

As a basis, notice that metal generally have black diffuse values.