Page 4 of 4
Example Substrate
vec3 computeMaterialInternal(Material material, vec2 texC, vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y) {
vec3 W = normalize(L + V);
vec2 alpha = getRoughness(material, texC);
vec3 Kd = getKd(material, texC);
vec3 Ks = getKs(material, texC);
float WdN = abs(dot(W, N));
float WdX = dot(W, X);
float WdY = dot(W, Y);
float WdV = max(dot(W, V), 0.f);
float WdL = max(dot(W, L), 0.f);
float NdV = abs(dot(V, N)) + 0.005f;
float NdL = max(dot(L, N), 0.f);
float D = GTR2_AnisotropicDistribution(WdN, WdX, WdY, alpha.x, alpha.y);
vec3 diff = (28.f / (23.f * Pi)) * Kd * (vec3(1.f) - Ks) *
(1.f - pow5(1.f - 0.5f*NdV)) * (1.f - pow5(1.f - 0.5f*NdL));
vec3 spec = D / (4 * abs(WdL) * max(NdV, NdL)) * FresnelShlick(WdL, Ks, vec3(1.0f));
return (diff + spec) * NdL;
}
Example Plastique
vec3 computeMaterialInternal(Material material, vec2 texC, vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y) {
vec3 W = normalize(L + V);
float alpha = getRoughness(material, texC).r;
float WdN = abs(dot(W, N));
float WdX = dot(W, X);
float WdY = dot(W, Y);
float WdV = max(dot(W, V), 0.f);
float WdL = max(dot(W, L), 0.f);
float NdV = abs(dot(V, N)) + 0.005f;
float NdL = max(dot(L, N), 0.f);
float D = GTR2_AnisotropicDistribution(WdN, WdX, WdY, alpha, alpha);
float G = GGX_GeometryTerm(WdV, NdV, alpha) * GGX_GeometryTerm(WdL, NdL, alpha);
float F = FresnelDielectric(WdL, 1.5f, 1.0f);
vec3 diff = getKd(material, texC) / Pi;
vec3 spec = getKs(material, texC) * D * G * F / (4 * NdL * NdV);
return (spec + diff) * NdL;
}
Example OrenNayar
float A(float sigma2) {
return 1.0 - 0.5 * (sigma2/(sigma2 + 0.33));
}
float B(float sigma2) {
return 0.45 * (sigma2/(sigma2 + 0.09));
}
float geomAtt(vec3 l, vec3 n, vec3 e) {
float NdotE = dot(n, e);
float NdotL = dot(n, l);
float maxnlne = max(NdotL, NdotE);
float minnlne = min(NdotL, NdotE);
float factor = sqrt( (1 - maxnlne*maxnlne) * (1 - minnlne*minnlne) );
factor = factor / maxnlne;
vec3 emn = normalize(e - n*NdotE);
vec3 lmn = normalize(l - n*NdotL);
return max( 0, dot(emn,lmn) )*factor;
}
vec3 computeMaterialInternal(Material material, vec2 texC, vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y) {
float costi = max(dot(N, L), 0);
float sigma2 = getSigma2(material, texC);
// is there an "intensity" parameter for lights ?
return (getKd(material, texC) * InvPi) * costi * ( A(sigma2) + B(sigma2) * geomAtt(L, N, V));
}
Example Metal
vec3 computeMaterialInternal(Material material, vec2 texC, vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y) {
vec3 W = normalize(L + V);
vec2 alpha = getRoughness(material, texC);
float WdN = abs(dot(W, N));
float WdX = dot(W, X);
float WdY = dot(W, Y);
float WdV = max(dot(W, V), 0.f);
float WdL = max(dot(W, L), 0.f);
float NdV = abs(dot(V, N)) + 0.005f;
float NdL = max(dot(L, N), 0.f);
float D = GTR2_AnisotropicDistribution(WdN, WdX, WdY, alpha.x, alpha.y);
float G = GGX_GeometryTerm(WdV, NdV, alpha.x) * GGX_GeometryTerm(WdL, NdL, alpha.x);
vec3 F = FresnelConductor(WdL, vec3(1.0f), getEta(material, texC), getK(material, texC));
vec3 spec = D * G * F / (4 * NdL * NdV);
return spec * NdL;
}
Example Disney
vec3 computeMaterialInternal(Material material, vec2 texC, vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y) {
vec3 W = normalize(L + V);
float WdN = max(dot(W, N), 0.f);
float WdX = dot(W, X);
float WdY = dot(W, Y);
float WdV = max(dot(W, V), 0.f);
float WdL = max(dot(W, L), 0.f);
float NdV = abs(dot(V, N)) + 0.005f;
float NdL = max(dot(L, N), 0.f);
vec3 color = getColor(material, texC);
int thin = material.thin;
float metallic = getMetallic(material, texC);
float flatness = getFlatness(material, texC);
float roughness = getRoughness(material, texC).x;
float sheen = getSheen(material, texC);
float sheenTint = getSheenTint(material, texC);
float ior = getIor(material, texC);
float clearcoat = getClearcoat(material, texC);
float gloss = getClearcoatGloss(material, texC);
float specTrans = getSpecTrans(material, texC);
float diffTrans = getDiffTrans(material, texC) / 2.f;
float specTint = getSpecularTint(material, texC);
//Diffuse Term-----------------------------------------------------------------------------------
vec3 diff = vec3(disneyDiffuse(NdV, NdL, WdL, roughness));
float diffWeight = (1.f - metallic) * (1.f - specTrans);
if (thin == 1) {
diff *= diffWeight * (1.f - diffTrans) * (1.f - flatness) * color;
diff += disneyFakeSS(diffWeight * (1.f - diffTrans) * flatness * color, roughness, WdL, NdV, NdL);
}
else {
diff *= diffWeight * color;
}
diff += disneyRetro(diffWeight * color, roughness, WdL, NdV, NdL);
//Calculatio of the diffuse sheen
diff += diffWeight * disneySheen(color, sheen, sheenTint, WdL);
//Specular Term---------------------------------------------------------------------------------
vec3 spec;
float aspect = sqrt( 1.f - getAnisotropic(material, texC) * 0.9f);
float ax = max(0.001f, sqr(roughness) / aspect);
float ay = max(0.001f, sqr(roughness) * aspect);
float nIor = sqr(ior - 1) / sqr(ior + 1);
vec3 Cspec0 = mix(nIor * mix(vec3(1.f), color, specTint), color, metallic);
float D = GTR2_AnisotropicDistribution(WdN, WdX, WdY, ax, ay);
float G = GGX_GeometryTerm(WdV, NdV, roughness) * GGX_GeometryTerm(WdL, NdL, roughness);
vec3 F = mix(vec3(FresnelDielectric(WdL, 1.f, ior)),
FresnelShlick(WdL, Cspec0, vec3(1.0f)),
metallic
);
spec = D * G * F / (4 * dot(N, L) * dot(N, V));
spec += disneyClearCoat(clearcoat, gloss, WdN, WdL, WdV, NdV, NdL);
return (diff + spec) * NdL;
}
code commun
float GTR2_AnisotropicDistribution(float NdH, float HdX, float HdY, float ax, float ay) {
return 1.0f / (Pi * ax*ay * sqr(sqr(HdX/ax) + sqr(HdY/ay) + NdH*NdH));
}
float chiGGX(float v) {
return v > 0.0f ? 1.0f : 0.0f;
}
float GGX_DistributionTerm( float NdotH , float m ) {
float m2 = m * m ;
float NdotH2 = NdotH * NdotH;
float f = NdotH2 * m2 + (1 - NdotH2);
return (chiGGX(NdotH) * m2) / (f * f * Pi);
}
float GGX_GeometryTerm(float VdH, float VdN, float alpha) {
float chi = chiGGX(VdH / VdN);
VdH = VdH * VdH;
float tan2 = (1-VdH)/VdH;
return (chi * 2) / (1 + sqrt(1+alpha*alpha*tan2));
}
vec3 FresnelShlick(float cosThetaI, vec3 F0, vec3 F90) {
return F0 + pow5(1 - cosThetaI) * (F90 - F0);
}
float FresnelDielectric(float cosThetaI, float etaI, float etaT) {
float sinThetaI = sqrt(max(0.f, 1 - cosThetaI * cosThetaI));
float sinThetaT = etaI / etaT * sinThetaI;
float cosThetaT = sqrt(max(0.f, 1.f - sinThetaT * sinThetaT));
float Rparl = ((etaT * cosThetaI) - (etaI * cosThetaT)) /
((etaT * cosThetaI) + (etaI * cosThetaT));
float Rperp = ((etaI * cosThetaI) - (etaT * cosThetaT)) /
((etaI * cosThetaI) + (etaT * cosThetaT));
return (Rparl * Rparl + Rperp * Rperp) / 2;
}
vec3 FresnelConductor(float cosThetaI, vec3 etaI, vec3 etaT, vec3 k) {
vec3 eta = etaT / etaI;
vec3 etak = k / etaI;
float cosThetaI2 = cosThetaI * cosThetaI;
float sinThetaI2 = 1. - cosThetaI2;
vec3 eta2 = eta * eta;
vec3 etak2 = etak * etak;
vec3 t0 = eta2 - etak2 - sinThetaI2;
vec3 a2plusb2 = sqrt(t0 * t0 + 4 * eta2 * etak2);
vec3 t1 = a2plusb2 + cosThetaI2;
vec3 a = sqrt(0.5f * (a2plusb2 + t0));
vec3 t2 = 2.f * cosThetaI * a;
vec3 Rs = (t1 - t2) / (t1 + t2);
vec3 t3 = cosThetaI2 * a2plusb2 + sinThetaI2 * sinThetaI2;
vec3 t4 = t2 * sinThetaI2;
vec3 Rp = Rs * (t3 - t4) / (t3 + t4);
return 0.5f * (Rp + Rs);
}
A vous de faire le reste ;)