Article Index

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