私はプロジェクトで物理的なレンダリング(PBR)を実装しようとしています(アカデミックおよびラーニングの目的で小さなゲームエンジンを開始しました)、材料のメタリックに基づいて鏡面反射と拡散寄与を計算する正しい方法は何か分かりませんおよび粗さ。PBRのスペキュラ寄与を計算する方法は?
レンダリングにサードパーティライブラリ/エンジンを使用していません。すべてOpenGL 3.3で書かれています。
は、今私は(私は以下の完全なコードを入れます)、これを持っている:
// Calculate contribution based on metallicity
vec3 diffuseColor = baseColor - baseColor * metallic;
vec3 specularColor = mix(vec3(0.00), baseColor, metallic);
しかし、私は鏡面用語は何とか粗さによって依存する必要がある印象の下です。私はこれを次のように変更しようと考えていました。
vec3 specularColor = mix(vec3(0.00), baseColor, roughness);
もう一度、わかりません。それを行う正しい方法は何ですか?私は満足のいく結果を得るまで、正しい方法さえありますか、あるいは私はちょうど '試行錯誤'の方法を使うべきですか?ここで
は、完全なGLSLコードです:
// Calculates specular intensity according to the Cook - Torrance model
float CalcCookTorSpec(vec3 normal, vec3 lightDir, vec3 viewDir, float roughness, float F0)
{
// Calculate intermediary values
vec3 halfVector = normalize(lightDir + viewDir);
float NdotL = max(dot(normal, lightDir), 0.0);
float NdotH = max(dot(normal, halfVector), 0.0);
float NdotV = max(dot(normal, viewDir), 0.0); // Note: this could also be NdotL, which is the same value
float VdotH = max(dot(viewDir, halfVector), 0.0);
float specular = 0.0;
if(NdotL > 0.0)
{
float G = GeometricalAttenuation(NdotH, NdotV, VdotH, NdotL);
float D = BeckmannDistribution(roughness, NdotH);
float F = Fresnel(F0, VdotH);
specular = (D * F * G)/(NdotV * NdotL * 4);
}
return specular;
}
vec3 CalcLight(vec3 lightColor, vec3 normal, vec3 lightDir, vec3 viewDir, Material material, float shadowFactor)
{
// Helper variables
vec3 baseColor = material.diffuse;
vec3 specColor = material.specular;
vec3 emissive = material.emissive;
float roughness = material.roughness;
float fresnel = material.fresnel;
float metallic = material.metallic;
// Calculate contribution based on metallicity
vec3 diffuseColor = baseColor - baseColor * metallic;
vec3 specularColor = mix(vec3(0.00), baseColor, metallic);
// Lambertian reflectance
float Kd = DiffuseLambert(normal, lightDir);
// Specular shading (Cook-Torrance model)
float Ks = CalcCookTorSpec(normal, lightDir, viewDir, roughness, fresnel);
// Combine results
vec3 diffuse = diffuseColor * Kd;
vec3 specular = specularColor * Ks;
vec3 result = lightColor * (emissive + diffuse + specular);
return result * (1.0 - shadowFactor);
}
うん、まだ、どのように私は、材料の粗さと金属量に基づいてCookTorranceからの鏡面とランバートから拡散貢献をブレンドする必要がありますか? – TheCrafter
私はうまくいけば良い情報を提供するために答えを編集しました。 – adon
私はそれを取得し始めていると思う。 「メタリック/ラフネス」モデルと「スペキュラ/光沢」モデルの両方からアイデアを得るかもしれないようだと言っているときはどういう意味ですか? ? – TheCrafter