Implemented the fresnel in the multi-scatter GGX for the Disney BSDF
- The specular/metallic part uses the multi-scatter GGX - The fresnel of the metallic part is controlled by the specular value - The color of the reflection part when using transparency can be controlled by the specularTint value
This commit is contained in:
		| @@ -95,6 +95,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg, | ||||
| 			label = bsdf_microfacet_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, | ||||
| 				eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); | ||||
| 			break; | ||||
| 		case CLOSURE_BSDF_MICROFACET_MULTI_GGX_REFRACTION_ID: | ||||
| 		case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: | ||||
| 			label = bsdf_microfacet_multi_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, | ||||
| 			        eval, omega_in,  &domega_in->dx, &domega_in->dy, pdf, &ccl_fetch(sd, lcg_state)); | ||||
| @@ -295,6 +296,7 @@ float3 bsdf_eval(KernelGlobals *kg, | ||||
| 				eval = bsdf_microfacet_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); | ||||
| 				break; | ||||
| 			case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: | ||||
| 			case CLOSURE_BSDF_MICROFACET_MULTI_GGX_REFRACTION_ID: | ||||
| 				eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state)); | ||||
| 				break; | ||||
| 			case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID: | ||||
|   | ||||
| @@ -37,7 +37,7 @@ CCL_NAMESPACE_BEGIN | ||||
|  | ||||
| typedef ccl_addr_space struct MicrofacetExtra { | ||||
| 	float3 color, cspec0; | ||||
| 	bool use_fresnel, is_disney_clearcoat; | ||||
| 	bool use_fresnel, is_disney_clearcoat, initial_outside, only_refractions, only_reflections; | ||||
| } MicrofacetExtra; | ||||
|  | ||||
| typedef ccl_addr_space struct MicrofacetBsdf { | ||||
| @@ -410,7 +410,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons | ||||
| 		float3 F = make_float3(1.0f, 1.0f, 1.0f); | ||||
| 		if (bsdf->extra) { | ||||
| 			if (bsdf->extra->use_fresnel) { | ||||
| 				float FH = schlick_fresnel(dot(omega_in, m)); | ||||
| 				float FH = fresnel_dielectric_cos(dot(omega_in, m), bsdf->ior); | ||||
|  | ||||
| 				F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH); | ||||
| 			} | ||||
| @@ -485,7 +485,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con | ||||
| 	float3 F = make_float3(1.0f, 1.0f, 1.0f); | ||||
| 	if (bsdf->extra) { | ||||
| 		if (bsdf->extra->use_fresnel) { | ||||
| 			float FH = schlick_fresnel(dot(omega_in, Ht)); | ||||
| 			float FH = fresnel_dielectric_cos(dot(omega_in, Ht), bsdf->ior); | ||||
|  | ||||
| 			F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH); | ||||
| 		} | ||||
| @@ -599,7 +599,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure | ||||
| 						float3 F = make_float3(1.0f, 1.0f, 1.0f); | ||||
| 						if (bsdf->extra) { | ||||
| 							if (bsdf->extra->use_fresnel) { | ||||
| 								float FH = schlick_fresnel(dot(*omega_in, m)); | ||||
| 								float FH = fresnel_dielectric_cos(dot(*omega_in, m), bsdf->ior); | ||||
|  | ||||
| 								F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH); | ||||
| 							} | ||||
| @@ -670,7 +670,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure | ||||
| 					float3 F = make_float3(1.0f, 1.0f, 1.0f); | ||||
| 					if (bsdf->extra) { | ||||
| 						if (bsdf->extra->use_fresnel) { | ||||
| 							float FH = schlick_fresnel(dot(*omega_in, m)); | ||||
| 							float FH = fresnel_dielectric_cos(dot(*omega_in, m), bsdf->ior); | ||||
|  | ||||
| 							F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH); | ||||
| 						} | ||||
|   | ||||
| @@ -370,6 +370,13 @@ ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf, bool use_fr | ||||
| 	return bsdf_microfacet_multi_ggx_common_setup(bsdf, use_fresnel); | ||||
| } | ||||
|  | ||||
| ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(MicrofacetBsdf *bsdf, bool use_fresnel = false) | ||||
| { | ||||
| 	bsdf->alpha_y = bsdf->alpha_x; | ||||
|  | ||||
| 	return bsdf_microfacet_multi_ggx_common_setup(bsdf, use_fresnel); | ||||
| } | ||||
|  | ||||
| ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) { | ||||
| 	*pdf = 0.0f; | ||||
| 	return make_float3(0.0f, 0.0f, 0.0f); | ||||
| @@ -392,7 +399,7 @@ ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc | ||||
| 		*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y)); | ||||
| 	else | ||||
| 		*pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x); | ||||
| 	return mf_eval_glossy(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL); | ||||
| 	return mf_eval_glossy(localI, localO, true, bsdf->extra->color, bsdf->extra->cspec0, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL, bsdf->ior, bsdf->extra->use_fresnel); | ||||
| } | ||||
|  | ||||
| ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state) | ||||
| @@ -409,7 +416,7 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderC | ||||
| 	float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z)); | ||||
| 	float3 localO; | ||||
|  | ||||
| 	*eval = mf_sample_glossy(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL); | ||||
| 	*eval = mf_sample_glossy(localI, &localO, bsdf->extra->color, bsdf->extra->cspec0, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL, bsdf->ior, bsdf->extra->use_fresnel); | ||||
| 	if(is_aniso) | ||||
| 		*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y)); | ||||
| 	else | ||||
| @@ -426,7 +433,7 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderC | ||||
|  | ||||
| /* Multiscattering GGX Glass closure */ | ||||
|  | ||||
| ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf, bool use_fresnel = false) | ||||
| ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf, bool use_fresnel = false, bool initial_outside = true, bool only_refractions = false, bool only_reflections = false) | ||||
| { | ||||
| 	bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f); | ||||
| 	bsdf->alpha_y = bsdf->alpha_x; | ||||
| @@ -438,6 +445,9 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf, bool | ||||
| 	bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x); | ||||
| 	bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y); | ||||
| 	bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z); | ||||
| 	bsdf->extra->initial_outside = initial_outside; | ||||
| 	bsdf->extra->only_refractions = only_refractions; | ||||
| 	bsdf->extra->only_reflections = only_reflections; | ||||
|  | ||||
| 	bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID; | ||||
|  | ||||
| @@ -446,6 +456,10 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf, bool | ||||
|  | ||||
| ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) { | ||||
| 	const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc; | ||||
|  | ||||
| 	if (bsdf->extra->only_reflections) | ||||
| 		return make_float3(0.0f, 0.0f, 0.0f); | ||||
|  | ||||
| 	float3 X, Y, Z; | ||||
| 	Z = bsdf->N; | ||||
| 	make_orthonormals(Z, &X, &Y); | ||||
| @@ -454,11 +468,15 @@ ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClos | ||||
| 	float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z)); | ||||
|  | ||||
| 	*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior); | ||||
| 	return mf_eval_glass(localI, localO, false, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior); | ||||
| 	return mf_eval_glass(localI, localO, false, bsdf->extra->color, bsdf->extra->cspec0, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior); | ||||
| } | ||||
|  | ||||
| ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) { | ||||
| 	const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc; | ||||
|  | ||||
| 	if (bsdf->extra->only_refractions) | ||||
| 		return make_float3(0.0f, 0.0f, 0.0f); | ||||
|  | ||||
| 	float3 X, Y, Z; | ||||
| 	Z = bsdf->N; | ||||
| 	make_orthonormals(Z, &X, &Y); | ||||
| @@ -467,7 +485,7 @@ ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosu | ||||
| 	float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z)); | ||||
|  | ||||
| 	*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior); | ||||
| 	return mf_eval_glass(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior); | ||||
| 	return mf_eval_glass(localI, localO, true, bsdf->extra->color, bsdf->extra->cspec0, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, bsdf->extra->use_fresnel, bsdf->extra->initial_outside); | ||||
| } | ||||
|  | ||||
| ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state) | ||||
| @@ -480,7 +498,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, const S | ||||
| 	float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z)); | ||||
| 	float3 localO; | ||||
|  | ||||
| 	*eval = mf_sample_glass(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior); | ||||
| 	*eval = mf_sample_glass(localI, &localO, bsdf->extra->color, bsdf->extra->cspec0, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, bsdf->extra->use_fresnel, bsdf->extra->initial_outside, bsdf->extra->only_refractions, bsdf->extra->only_reflections); | ||||
| 	*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior); | ||||
| 	*eval *= *pdf; | ||||
|  | ||||
|   | ||||
| @@ -29,14 +29,19 @@ ccl_device_inline float3 MF_FUNCTION_FULL_NAME(mf_eval)( | ||||
|         float3 wi, | ||||
|         float3 wo, | ||||
|         const bool wo_outside, | ||||
|         const float3 color, | ||||
| 		const float3 color, | ||||
| 		const float3 cspec0, | ||||
|         const float alpha_x, | ||||
|         const float alpha_y, | ||||
|          ccl_addr_space uint *lcg_state | ||||
| #ifdef MF_MULTI_GLASS | ||||
|         , const float eta | ||||
| 		, bool use_fresnel = false | ||||
| 		, bool initial_outside = true | ||||
| #elif defined(MF_MULTI_GLOSSY) | ||||
|         , float3 *n, float3 *k | ||||
| 		 , float3 *n, float3 *k | ||||
| 		 , const float eta = 1.0f | ||||
| 		 , bool use_fresnel = false | ||||
| #endif | ||||
| ) | ||||
| { | ||||
| @@ -77,6 +82,18 @@ ccl_device_inline float3 MF_FUNCTION_FULL_NAME(mf_eval)( | ||||
| 		eval *= -lambda_r / (shadowing_lambda - lambda_r); | ||||
| 	else | ||||
| 		eval *= -lambda_r * beta(-lambda_r, shadowing_lambda+1.0f); | ||||
|  | ||||
| 	float3 eval2; | ||||
| 	float3 t_color = cspec0; | ||||
| 	float3 throughput2 = make_float3(1.0f, 1.0f, 1.0f); | ||||
| 	float F0 = fresnel_dielectric_cos(1.0f, eta); | ||||
| 	float F0_norm = 1.0f / (1.0f - F0); | ||||
| 	if (use_fresnel && initial_outside) { | ||||
| 		float FH = (fresnel_dielectric_cos(dot(wi, normalize(wi + wo)), eta) - F0) * F0_norm; //schlick_fresnel(dot(wi, normalize(wi + wo))); // | ||||
| 		throughput2 = cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; | ||||
|  | ||||
| 		eval2 = throughput2 * eval; | ||||
| 	} | ||||
| #elif defined(MF_MULTI_DIFFUSE) | ||||
| 	/* Diffuse has no special closed form for the single scattering bounce */ | ||||
| 	eval = make_float3(0.0f, 0.0f, 0.0f); | ||||
| @@ -94,6 +111,18 @@ ccl_device_inline float3 MF_FUNCTION_FULL_NAME(mf_eval)( | ||||
| 	else { | ||||
| 		eval = make_float3(val, val, val); | ||||
| 	} | ||||
|  | ||||
| 	float3 eval2; | ||||
| 	float3 t_color = cspec0; | ||||
| 	float3 throughput2 = make_float3(1.0f, 1.0f, 1.0f); | ||||
| 	float F0 = fresnel_dielectric_cos(1.0f, eta); | ||||
| 	float F0_norm = 1.0f / (1.0f - F0); | ||||
| 	if (use_fresnel) { | ||||
| 		float FH = (fresnel_dielectric_cos(dot(wi, normalize(wi + wo)), eta) - F0) * F0_norm; //schlick_fresnel(dot(wi, normalize(wi + wo))); // | ||||
| 		throughput2 = cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; | ||||
|  | ||||
| 		eval2 = throughput2 * val; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	float3 wr = -wi; | ||||
| @@ -116,6 +145,18 @@ ccl_device_inline float3 MF_FUNCTION_FULL_NAME(mf_eval)( | ||||
| 			const float G2_G1 = -lambda_r / (shadowing_lambda - lambda_r); | ||||
| 			eval += throughput * G2_G1 * mf_eval_phase_diffuse(wo, wm); | ||||
| 		} | ||||
| #endif | ||||
| #ifdef MF_MULTI_GLASS | ||||
| 		if (order == 0 && use_fresnel) { | ||||
| 			/* Evaluate amount of scattering towards wo on this microfacet. */ | ||||
| 			float3 phase; | ||||
| 			if (outside) | ||||
| 				phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta); | ||||
| 			else | ||||
| 				phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f / eta); | ||||
|  | ||||
| 			eval2 = throughput2 * phase * mf_G1(wo_outside ? wo : -wo, mf_C1((outside == wo_outside) ? hr : -hr), shadowing_lambda); | ||||
| 		} | ||||
| #endif | ||||
| 		if(order > 0) { | ||||
| 			/* Evaluate amount of scattering towards wo on this microfacet. */ | ||||
| @@ -125,10 +166,16 @@ ccl_device_inline float3 MF_FUNCTION_FULL_NAME(mf_eval)( | ||||
| 				phase = mf_eval_phase_glass(wr, lambda_r,  wo,  wo_outside, alpha, eta); | ||||
| 			else | ||||
| 				phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f/eta); | ||||
|  | ||||
| 			if (use_fresnel && initial_outside) | ||||
| 				eval2 += throughput2 * phase * mf_G1(wo_outside ? wo : -wo, mf_C1((outside == wo_outside) ? hr : -hr), shadowing_lambda); | ||||
| #elif defined(MF_MULTI_DIFFUSE) | ||||
| 			phase = mf_eval_phase_diffuse(wo, wm); | ||||
| #else /* MF_MULTI_GLOSSY */ | ||||
| 			phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha, n, k) * throughput; | ||||
|  | ||||
| 			if (use_fresnel) | ||||
| 				eval2 += throughput2 * phase * mf_G1(wo_outside ? wo : -wo, mf_C1((outside == wo_outside) ? hr : -hr), shadowing_lambda); | ||||
| #endif | ||||
| 			eval += throughput * phase * mf_G1(wo_outside? wo: -wo, mf_C1((outside == wo_outside)? hr: -hr), shadowing_lambda); | ||||
| 		} | ||||
| @@ -136,17 +183,39 @@ ccl_device_inline float3 MF_FUNCTION_FULL_NAME(mf_eval)( | ||||
| 			/* Bounce from the microfacet. */ | ||||
| #ifdef MF_MULTI_GLASS | ||||
| 			bool next_outside; | ||||
| 			float3 wi_prev = -wr; | ||||
| 			wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float_addrspace(lcg_state), &next_outside); | ||||
| 			if(!next_outside) { | ||||
| 				outside = !outside; | ||||
| 				wr = -wr; | ||||
| 				hr = -hr; | ||||
| 			} | ||||
|  | ||||
| 			if (use_fresnel && initial_outside && outside && next_outside) { | ||||
| 				float FH = (fresnel_dielectric_cos(dot(wi_prev, wm), eta) - F0) * F0_norm; //schlick_fresnel(dot(wi_prev, wm)); // | ||||
| 				t_color = cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; | ||||
|  | ||||
| 				if (order > 0) | ||||
| 					throughput2 *= t_color; | ||||
| 			} | ||||
| 			else { | ||||
| 				throughput2 *= color; | ||||
| 			} | ||||
| #elif defined(MF_MULTI_DIFFUSE) | ||||
| 			wr = mf_sample_phase_diffuse(wm, | ||||
| 			                             lcg_step_float_addrspace(lcg_state), | ||||
| 			                             lcg_step_float_addrspace(lcg_state)); | ||||
| #else /* MF_MULTI_GLOSSY */ | ||||
| 			if (use_fresnel) { | ||||
| 				float FH = (fresnel_dielectric_cos(dot(-wr, wm), eta) - F0) * F0_norm; //schlick_fresnel(dot(-wr, wm)); // | ||||
| 				t_color = cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; | ||||
|  | ||||
| 				if (order > 0) | ||||
| 					throughput2 *= t_color; | ||||
| 			} | ||||
| 			else { | ||||
| 				throughput2 *= color; | ||||
| 			} | ||||
| 			wr = mf_sample_phase_glossy(-wr, n, k, &throughput, wm); | ||||
| #endif | ||||
|  | ||||
| @@ -159,6 +228,15 @@ ccl_device_inline float3 MF_FUNCTION_FULL_NAME(mf_eval)( | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| #if defined(MF_MULTI_GLASS) || defined(MF_MULTI_GLOSSY) | ||||
| 	if (use_fresnel) { | ||||
| 		if (swapped) | ||||
| 			eval2 *= fabsf(wi.z / wo.z); | ||||
|  | ||||
| 		return eval2; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	if(swapped) | ||||
| 		eval *= fabsf(wi.z / wo.z); | ||||
| 	return eval; | ||||
| @@ -168,11 +246,17 @@ ccl_device_inline float3 MF_FUNCTION_FULL_NAME(mf_eval)( | ||||
|  * escaped the surface in wo. The function returns the throughput between wi and wo. | ||||
|  * Without reflection losses due to coloring or fresnel absorption in conductors, the sampling is optimal. | ||||
|  */ | ||||
| ccl_device float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3 *wo, const float3 color, const float alpha_x, const float alpha_y, ccl_addr_space uint *lcg_state | ||||
| ccl_device float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3 *wo, const float3 color, const float3 cspec0, const float alpha_x, const float alpha_y, ccl_addr_space uint *lcg_state | ||||
| #ifdef MF_MULTI_GLASS | ||||
| 	, const float eta | ||||
| 	, bool use_fresnel = false | ||||
| 	, bool initial_outside = true | ||||
| 	, bool only_refractions = false | ||||
| 	, bool only_reflections = false | ||||
| #elif defined(MF_MULTI_GLOSSY) | ||||
| 	, float3 *n, float3 *k | ||||
| 	, const float eta = 1.0f | ||||
| 	, bool use_fresnel = false | ||||
| #endif | ||||
| ) | ||||
| { | ||||
| @@ -185,13 +269,42 @@ ccl_device float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3 *wo, const | ||||
| 	float C1_r = 1.0f; | ||||
| 	float G1_r = 0.0f; | ||||
| 	bool outside = true; | ||||
| #ifdef MF_MULTI_GLASS | ||||
| 	float3 t_color = cspec0; | ||||
| 	float3 throughput2 = make_float3(1.0f, 1.0f, 1.0f); | ||||
| 	float F0 = fresnel_dielectric_cos(1.0f, eta); | ||||
| 	float F0_norm = 1.0f / (1.0f - F0); | ||||
| 	if (use_fresnel && initial_outside) { | ||||
| 		float FH = (fresnel_dielectric_cos(dot(wi, normalize(wi + wr)), eta) - F0) * F0_norm; //schlick_fresnel(dot(wi, normalize(wi + wr))); // | ||||
| 		throughput2 = cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; | ||||
| 	} | ||||
| #else defined(MF_MULTI_GLOSSY) | ||||
| 	float3 t_color = cspec0; | ||||
| 	float3 throughput2 = make_float3(1.0f, 1.0f, 1.0f); | ||||
| 	float F0 = fresnel_dielectric_cos(1.0f, eta); | ||||
| 	float F0_norm = 1.0f / (1.0f - F0); | ||||
| 	if (use_fresnel) { | ||||
| 		float FH = (fresnel_dielectric_cos(dot(wi, normalize(wi + wr)), eta) - F0) * F0_norm; //schlick_fresnel(dot(wi, normalize(wi + wr))); // | ||||
| 		throughput2 = cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	int order; | ||||
| 	for(order = 0; order < 10; order++) { | ||||
| 		/* Sample microfacet height. */ | ||||
| 		if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, lcg_step_float_addrspace(lcg_state))) { | ||||
| 			/* The random walk has left the surface. */ | ||||
| #ifdef MF_MULTI_GLASS | ||||
| 			if ((only_refractions && outside && initial_outside) || (only_reflections && !outside)) { | ||||
| 				*wo = make_float3(0.0f, 0.0f, 1.0f); | ||||
| 				return make_float3(0.0f, 0.0f, 0.0f); | ||||
| 			} | ||||
| #endif | ||||
| 			*wo = outside? wr: -wr; | ||||
| #if defined(MF_MULTI_GLASS) || defined(MF_MULTI_GLOSSY) | ||||
| 			if (use_fresnel) | ||||
| 				return throughput2; | ||||
| #endif | ||||
| 			return throughput; | ||||
| 		} | ||||
| 		/* Sample microfacet normal. */ | ||||
| @@ -205,17 +318,42 @@ ccl_device float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3 *wo, const | ||||
| 		/* Bounce from the microfacet. */ | ||||
| #ifdef MF_MULTI_GLASS | ||||
| 		bool next_outside; | ||||
| 		float3 wi_prev = -wr; | ||||
| 		wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float_addrspace(lcg_state), &next_outside); | ||||
| 		if(!next_outside) { | ||||
| 			hr = -hr; | ||||
| 			wr = -wr; | ||||
| 			outside = !outside; | ||||
| 		} | ||||
|  | ||||
| 		if (use_fresnel) { | ||||
| 			if (initial_outside && outside && next_outside) { | ||||
| 				float FH = (fresnel_dielectric_cos(dot(wi_prev, wm), eta) - F0) * F0_norm; //schlick_fresnel(dot(wi_prev, wm)); // | ||||
| 				t_color = cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; | ||||
|  | ||||
| 				if (order == 0) | ||||
| 					throughput2 = t_color; | ||||
| 				else | ||||
| 					throughput2 *= t_color; | ||||
| 			} | ||||
| 			else { | ||||
| 				throughput2 *= color; | ||||
| 			} | ||||
| 		} | ||||
| #elif defined(MF_MULTI_DIFFUSE) | ||||
| 		wr = mf_sample_phase_diffuse(wm, | ||||
| 		                             lcg_step_float_addrspace(lcg_state), | ||||
| 		                             lcg_step_float_addrspace(lcg_state)); | ||||
| #else /* MF_MULTI_GLOSSY */ | ||||
| 		if (use_fresnel) { | ||||
| 			float FH = (fresnel_dielectric_cos(dot(-wr, wm), eta) - F0) * F0_norm; //schlick_fresnel(dot(-wr, wm)); // | ||||
| 			t_color = cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; | ||||
|  | ||||
| 			if (order == 0) | ||||
| 				throughput2 = t_color; | ||||
| 			else | ||||
| 				throughput2 *= t_color; | ||||
| 		} | ||||
| 		wr = mf_sample_phase_glossy(-wr, n, k, &throughput, wm); | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -100,6 +100,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * | ||||
| 			float clearcoatGloss = stack_load_float(stack, clearcoatGloss_offset); | ||||
| 			float transparency = stack_load_float(stack, transparency_offset); | ||||
| 			float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset); | ||||
| 			float refraction_roughness = 1.0f; // TODO: add parameter for this! | ||||
| 			float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f); | ||||
|  | ||||
| 			/* rotate tangent */ | ||||
| @@ -236,14 +237,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * | ||||
| 			if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) { | ||||
| #endif | ||||
| 				if (specular != 0.0f || metallic != 0.0f) { | ||||
| 					float3 spec_weight = weight * specular_weight; | ||||
| 					float3 spec_weight = weight * specular_weight/* * (specular * (1.0f - metallic) + metallic)*/; | ||||
|  | ||||
| 					MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), spec_weight); | ||||
| 					MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra)); | ||||
|  | ||||
| 					if (bsdf && extra) { | ||||
| 						bsdf->N = N; | ||||
| 						bsdf->ior = 0.0f; | ||||
| 						bsdf->ior = (2.0f / (1.0f - safe_sqrtf(0.08f * specular))) - 1.0f; | ||||
| 						bsdf->T = T; | ||||
| 						bsdf->extra = extra; | ||||
|  | ||||
| @@ -257,15 +258,16 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * | ||||
| 						float3 m_ctint = m_cdlum > 0.0f ? baseColor / m_cdlum : make_float3(0.0f, 0.0f, 0.0f); // normalize lum. to isolate hue+sat | ||||
| 						float3 tmp_col = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specularTint) + m_ctint * specularTint; | ||||
|  | ||||
| 						bsdf->extra->cspec0 = (specular * 0.08f * tmp_col) * (1.0f - metallic) + baseColor * metallic; | ||||
| 						bsdf->extra->cspec0 = (/*fresnel_dielectric_cos(1.0f, ior)*/specular * 0.08f * tmp_col) * (1.0f - metallic) + baseColor * metallic; | ||||
| 						bsdf->extra->color = baseColor; | ||||
|  | ||||
| 						/* setup bsdf */ | ||||
| #ifdef __DISNEY_SPECULAR_MULTI_GGX__ | ||||
| //#define __DISNEY_SPECULAR_MULTI_GGX__ | ||||
| //#ifdef __DISNEY_SPECULAR_MULTI_GGX__ | ||||
| 						ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf, true); | ||||
| #else | ||||
| 						ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_aniso_setup(bsdf, true); | ||||
| #endif | ||||
| //#else | ||||
| //						ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_aniso_setup(bsdf, true); | ||||
| //#endif | ||||
| 					} | ||||
| 				} | ||||
| #ifdef __CAUSTICS_TRICKS__ | ||||
| @@ -277,24 +279,74 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * | ||||
| 			if (kernel_data.integrator.caustics_reflective || kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0) { | ||||
| #endif | ||||
| 				if (specular_weight < 1.0f) { | ||||
| 					float3 glass_weight = baseColor * weight * (1.0f - specular_weight); | ||||
| 					float3 glass_weight = /*baseColor */ weight * (1.0f - specular_weight); | ||||
| 					float3 cspec0 = baseColor * specularTint + make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specularTint); | ||||
| 					bool frontfacing = (ccl_fetch(sd, flag) & SD_BACKFACING) == 0; | ||||
|  | ||||
| 					MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight); | ||||
| 					MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra)); | ||||
| 					if (refraction_roughness == 0.0f) { | ||||
| 						MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight); | ||||
| 						MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra)); | ||||
|  | ||||
| 					if (bsdf && extra) { | ||||
| 						bsdf->N = N; | ||||
| 						bsdf->extra = extra; | ||||
| 						bsdf->T = make_float3(0.0f, 0.0f, 0.0f); | ||||
| 						if (bsdf && extra) { | ||||
| 							bsdf->N = N; | ||||
| 							bsdf->extra = extra; | ||||
| 							bsdf->T = make_float3(0.0f, 0.0f, 0.0f); | ||||
|  | ||||
| 						bsdf->alpha_x = roughness * roughness; | ||||
| 						bsdf->alpha_y = roughness * roughness; | ||||
| 						bsdf->ior = ior; | ||||
| 							bsdf->alpha_x = roughness * roughness; | ||||
| 							bsdf->alpha_y = roughness * roughness; | ||||
| 							bsdf->ior = ior; | ||||
|  | ||||
| 						bsdf->extra->color = baseColor; | ||||
| 							bsdf->extra->color = baseColor; | ||||
| 							bsdf->extra->cspec0 = cspec0; | ||||
|  | ||||
| 						/* setup bsdf */ | ||||
| 						ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_glass_setup(bsdf); | ||||
| 							/* setup bsdf */ | ||||
| 							ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_glass_setup(bsdf, true, frontfacing); | ||||
| 						} | ||||
| 					} | ||||
| 					else { | ||||
| 						{ | ||||
| 							MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight); | ||||
| 							MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra)); | ||||
|  | ||||
| 							if (bsdf && extra) { | ||||
| 								bsdf->N = N; | ||||
| 								bsdf->extra = extra; | ||||
| 								bsdf->T = make_float3(0.0f, 0.0f, 0.0f); | ||||
|  | ||||
| 								bsdf->alpha_x = roughness * roughness; | ||||
| 								bsdf->alpha_y = roughness * roughness; | ||||
| 								bsdf->ior = ior; | ||||
|  | ||||
| 								bsdf->extra->color = baseColor; | ||||
| 								bsdf->extra->cspec0 = cspec0; | ||||
|  | ||||
| 								/* setup bsdf */ | ||||
| 								ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_glass_setup(bsdf, true, frontfacing, false, true); | ||||
| 							} | ||||
| 						} | ||||
|  | ||||
| 						{ | ||||
| 							MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight * (1.0f - fresnel)); | ||||
| 							MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra)); | ||||
|  | ||||
| 							if (bsdf && extra) { | ||||
| 								bsdf->N = N; | ||||
| 								bsdf->extra = extra; | ||||
| 								bsdf->T = make_float3(0.0f, 0.0f, 0.0f); | ||||
|  | ||||
| 								refraction_roughness = 1.0f - (1.0f - roughness) * (1.0f - refraction_roughness); | ||||
|  | ||||
| 								bsdf->alpha_x = refraction_roughness * refraction_roughness; | ||||
| 								bsdf->alpha_y = refraction_roughness * refraction_roughness; | ||||
| 								bsdf->ior = ior; | ||||
|  | ||||
| 								bsdf->extra->color = baseColor; | ||||
| 								bsdf->extra->cspec0 = cspec0; | ||||
|  | ||||
| 								/* setup bsdf */ | ||||
| 								ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_glass_setup(bsdf, true, frontfacing, true); | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| #ifdef __CAUSTICS_TRICKS__ | ||||
|   | ||||
| @@ -417,6 +417,7 @@ typedef enum ClosureType { | ||||
| 	CLOSURE_BSDF_REFRACTION_ID, | ||||
| 	CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, | ||||
| 	CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, | ||||
| 	CLOSURE_BSDF_MICROFACET_MULTI_GGX_REFRACTION_ID, | ||||
| 	CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID, | ||||
| 	CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID, | ||||
| 	CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user