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