Compare commits
	
		
			165 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f5fa754e17 | |||
| 69a2bb1e7e | |||
| 5b86f32b51 | |||
| 590e6219d5 | |||
| 662981fa03 | |||
| a3866fb604 | |||
| fbf63e4f17 | |||
| a318e08072 | |||
| 7ae458a9dd | |||
| 9984615f8c | |||
| 0430e06acd | |||
| 9622f35b73 | |||
| da666e6d23 | |||
| 6ff7804ec1 | |||
| 0265ef5b64 | |||
| 53c5000975 | |||
| 7647231696 | |||
| 1e583a795d | |||
| da25d8c313 | |||
| 70695b3b31 | |||
| 858537d54c | |||
| 2998a5585e | |||
| c35c59e6a9 | |||
| 15ac833f2c | |||
| 8077f00ada | |||
| 58140ad583 | |||
| 9e2b601445 | |||
| 0439dde4a8 | |||
| 2e7ccb5151 | |||
| b89ebfd9c6 | |||
| a142b248ef | |||
| 1c648b0433 | |||
| 3103a976a6 | |||
| 82fa7bcfe3 | |||
| 709e0ed9cb | |||
| 7bcf985023 | |||
| d23232205b | |||
| 88c7c5b99e | |||
| 2434ad07f2 | |||
| 00493bed9c | |||
| 7b17633c28 | |||
| 1ef805eb0b | |||
| cb7b041fea | |||
| a0e8e1a1a6 | |||
| 846c3b2c11 | |||
| b5af208766 | |||
| 63565052e3 | |||
| 38eb66a0b5 | |||
| 908efdd554 | |||
| e014484d27 | |||
| 872433cafb | |||
| 74bbb6ca87 | |||
| cbbd6fe495 | |||
| 45a48acf8a | |||
| c769b3ca26 | |||
| c4378be891 | |||
| 6ad615a961 | |||
| 1e4510ba56 | |||
| a2714bf101 | |||
| 5639234eb9 | |||
| 1591ccdae5 | |||
| 9cb5232187 | |||
| 6b25d8c8ad | |||
| 13ca31f480 | |||
| d102e59040 | |||
| df0e24c307 | |||
| 2df86850f8 | |||
| 02ff259860 | |||
| 2e6de515ef | |||
| 41b840212c | |||
| 429e6d6768 | |||
| 2d8bfbf181 | |||
| 1ad7e0eaf4 | |||
| ae72401657 | |||
| 58b9000305 | |||
| 0cc86c41b8 | |||
| 25f8c5f64c | |||
| 109544cea9 | |||
| 4c92c4bcc9 | |||
| 3433afb1c3 | |||
| e22b522059 | |||
| 200af34740 | |||
| 6d7b0078b4 | |||
| fa501cb09b | |||
| 62a4bbb714 | |||
| eab3e3b30c | |||
| 3be7528a6c | |||
| c9dd46c5e3 | |||
| 99806b8069 | |||
| e98bfb125d | |||
| c4c0e2beaa | |||
| 36cbc934ba | |||
| 210d5ea532 | |||
| dab9a38424 | |||
| b7bbe40348 | |||
| 8b084156ff | |||
| 538c364f33 | |||
| 09eee93ac9 | |||
| 8b5a77c001 | |||
| 436b7fac02 | |||
| 9ef9f5a637 | |||
| b8ca4be56a | |||
| 29e4993f06 | |||
| 4134352688 | |||
| 25cf758a33 | |||
| 23af038a16 | |||
| 7f7878aaa6 | |||
| d7e076fb56 | |||
| dab915b60d | |||
| 74389ba76a | |||
| bd5afc797d | |||
| 27b4ec42a8 | |||
| ab7edaa9e3 | |||
| 27540ac7e9 | |||
| a5b512f20b | |||
| f8d0e67f33 | |||
| 915118617d | |||
| ea69511e67 | |||
| 3926a7f83e | |||
| 0eafd14ae2 | |||
| 08614512d7 | |||
| 08261a9335 | |||
| ce3c1cea6a | |||
| 392d12a816 | |||
| 6b423038d4 | |||
| 76628fc010 | |||
| 99f687b10c | |||
| 316441b954 | |||
| 9bf83bc49f | |||
| d88e1f0f42 | |||
| 96f4e29778 | |||
| 1d705d2ca2 | |||
| 0979cd976f | |||
| db6d786ee4 | |||
| 106e36e30d | |||
| 2bb296028f | |||
| 25d7ba3e72 | |||
| bf7b4416ec | |||
| a2d03cfe6e | |||
| 95f0ecfc54 | |||
| 07f59224fc | |||
| 02259985be | |||
| 6b8585c81a | |||
| 5d78eabf94 | |||
| 41c1459c4e | |||
| 304a497565 | |||
| 9fa399371a | |||
| 4625fdb6b2 | |||
| 79553927aa | |||
| 86661c1012 | |||
| 03967c7a2b | |||
| 61fd48a12f | |||
| 519039b8b6 | |||
| 5244b1b3e8 | |||
| 7ae3bbe496 | |||
| 001be2f8da | |||
| 6a25b3c5d7 | |||
| 8d4ac7251a | |||
| ae63b252c6 | |||
| ee73823206 | |||
| af2850e20c | |||
| bc4a31d415 | |||
| 5303ad3ac6 | |||
| 5153cff790 | |||
| abe17870ce | 
| @ -29,10 +29,11 @@ uniform sampler2D gbuffer1; | |||||||
| #ifdef _VoxelGI | #ifdef _VoxelGI | ||||||
| uniform sampler2D voxels_diffuse; | uniform sampler2D voxels_diffuse; | ||||||
| uniform sampler2D voxels_specular; | uniform sampler2D voxels_specular; | ||||||
| #endif | #else | ||||||
| #ifdef _VoxelAOvar | #ifdef _VoxelAOvar | ||||||
| uniform sampler2D voxels_ao; | uniform sampler2D voxels_ao; | ||||||
| #endif | #endif | ||||||
|  | #endif | ||||||
| #ifdef _VoxelShadow | #ifdef _VoxelShadow | ||||||
| uniform sampler3D voxels; | uniform sampler3D voxels; | ||||||
| uniform sampler3D voxelsSDF; | uniform sampler3D voxelsSDF; | ||||||
| @ -56,6 +57,10 @@ uniform vec3 backgroundCol; | |||||||
|  |  | ||||||
| #ifdef _SSAO | #ifdef _SSAO | ||||||
| uniform sampler2D ssaotex; | uniform sampler2D ssaotex; | ||||||
|  | #else | ||||||
|  | #ifdef _SSGI | ||||||
|  | uniform sampler2D ssaotex; | ||||||
|  | #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef _SSS | #ifdef _SSS | ||||||
| @ -113,11 +118,15 @@ uniform vec2 cameraPlane; | |||||||
| #ifdef _SinglePoint | #ifdef _SinglePoint | ||||||
| 	#ifdef _Spot | 	#ifdef _Spot | ||||||
| 	//!uniform sampler2DShadow shadowMapSpot[1]; | 	//!uniform sampler2DShadow shadowMapSpot[1]; | ||||||
|  | 	#ifdef _ShadowMapTransparent | ||||||
| 	//!uniform sampler2D shadowMapSpotTransparent[1]; | 	//!uniform sampler2D shadowMapSpotTransparent[1]; | ||||||
|  | 	#endif | ||||||
| 	//!uniform mat4 LWVPSpot[1]; | 	//!uniform mat4 LWVPSpot[1]; | ||||||
| 	#else | 	#else | ||||||
| 	//!uniform samplerCubeShadow shadowMapPoint[1]; | 	//!uniform samplerCubeShadow shadowMapPoint[1]; | ||||||
|  | 	#ifdef _ShadowMapTransparent | ||||||
| 	//!uniform samplerCube shadowMapPointTransparent[1]; | 	//!uniform samplerCube shadowMapPointTransparent[1]; | ||||||
|  | 	#endif | ||||||
| 	//!uniform vec2 lightProj; | 	//!uniform vec2 lightProj; | ||||||
| 	#endif | 	#endif | ||||||
| #endif | #endif | ||||||
| @ -125,30 +134,40 @@ uniform vec2 cameraPlane; | |||||||
| 	#ifdef _ShadowMapAtlas | 	#ifdef _ShadowMapAtlas | ||||||
| 		#ifdef _SingleAtlas | 		#ifdef _SingleAtlas | ||||||
| 		uniform sampler2DShadow shadowMapAtlas; | 		uniform sampler2DShadow shadowMapAtlas; | ||||||
|  | 		#ifdef _ShadowMapTransparent | ||||||
| 		uniform sampler2D shadowMapAtlasTransparent; | 		uniform sampler2D shadowMapAtlasTransparent; | ||||||
| 		#endif | 		#endif | ||||||
|  | 		#endif | ||||||
| 	#endif | 	#endif | ||||||
| 	#ifdef _ShadowMapAtlas | 	#ifdef _ShadowMapAtlas | ||||||
| 		#ifndef _SingleAtlas | 		#ifndef _SingleAtlas | ||||||
| 		//!uniform sampler2DShadow shadowMapAtlasPoint; | 		//!uniform sampler2DShadow shadowMapAtlasPoint; | ||||||
|  | 		#ifdef _ShadowMapTransparent | ||||||
| 		//!uniform sampler2D shadowMapAtlasPointTransparent; | 		//!uniform sampler2D shadowMapAtlasPointTransparent; | ||||||
| 		#endif | 		#endif | ||||||
| 		//!uniform vec4 pointLightDataArray[4]; | 		#endif | ||||||
|  | 		//!uniform vec4 pointLightDataArray[maxLightsCluster * 6]; | ||||||
| 	#else | 	#else | ||||||
| 		//!uniform samplerCubeShadow shadowMapPoint[4]; | 		//!uniform samplerCubeShadow shadowMapPoint[4]; | ||||||
|  | 		#ifdef _ShadowMapTransparent | ||||||
| 		//!uniform samplerCube shadowMapPointTransparent[4]; | 		//!uniform samplerCube shadowMapPointTransparent[4]; | ||||||
|  | 		#endif | ||||||
| 	#endif | 	#endif | ||||||
| 	//!uniform vec2 lightProj; | 	//!uniform vec2 lightProj; | ||||||
| 	#ifdef _Spot | 	#ifdef _Spot | ||||||
| 		#ifdef _ShadowMapAtlas | 		#ifdef _ShadowMapAtlas | ||||||
| 		#ifndef _SingleAtlas | 		#ifndef _SingleAtlas | ||||||
| 		//!uniform sampler2DShadow shadowMapAtlasSpot; | 		//!uniform sampler2DShadow shadowMapAtlasSpot; | ||||||
|  | 		#ifdef _ShadowMapTransparent | ||||||
| 		//!uniform sampler2D shadowMapAtlasSpotTransparent; | 		//!uniform sampler2D shadowMapAtlasSpotTransparent; | ||||||
| 		#endif | 		#endif | ||||||
|  | 		#endif | ||||||
| 		#else | 		#else | ||||||
| 		//!uniform sampler2DShadow shadowMapSpot[4]; | 		//!uniform sampler2DShadow shadowMapSpot[4]; | ||||||
|  | 		#ifdef _ShadowMapTransparent | ||||||
| 		//!uniform sampler2D shadowMapSpotTransparent[4]; | 		//!uniform sampler2D shadowMapSpotTransparent[4]; | ||||||
| 		#endif | 		#endif | ||||||
|  | 		#endif | ||||||
| 	//!uniform mat4 LWVPSpotArray[maxLightsCluster]; | 	//!uniform mat4 LWVPSpotArray[maxLightsCluster]; | ||||||
| 	#endif | 	#endif | ||||||
| #endif | #endif | ||||||
| @ -161,12 +180,16 @@ uniform vec3 sunCol; | |||||||
| 	#ifdef _ShadowMapAtlas | 	#ifdef _ShadowMapAtlas | ||||||
| 	#ifndef _SingleAtlas | 	#ifndef _SingleAtlas | ||||||
| 	uniform sampler2DShadow shadowMapAtlasSun; | 	uniform sampler2DShadow shadowMapAtlasSun; | ||||||
|  | 	#ifdef _ShadowMapTransparent | ||||||
| 	uniform sampler2D shadowMapAtlasSunTransparent; | 	uniform sampler2D shadowMapAtlasSunTransparent; | ||||||
| 	#endif | 	#endif | ||||||
|  | 	#endif | ||||||
| 	#else | 	#else | ||||||
| 	uniform sampler2DShadow shadowMap; | 	uniform sampler2DShadow shadowMap; | ||||||
|  | 	#ifdef _ShadowMapTransparent | ||||||
| 	uniform sampler2D shadowMapTransparent; | 	uniform sampler2D shadowMapTransparent; | ||||||
| 	#endif | 	#endif | ||||||
|  | 	#endif | ||||||
| 	uniform float shadowsBias; | 	uniform float shadowsBias; | ||||||
| 	#ifdef _CSM | 	#ifdef _CSM | ||||||
| 	//!uniform vec4 casData[shadowmapCascades * 4 + 4]; | 	//!uniform vec4 casData[shadowmapCascades * 4 + 4]; | ||||||
| @ -227,17 +250,22 @@ void main() { | |||||||
| 	vec4 g2 = textureLod(gbuffer2, texCoord, 0.0); | 	vec4 g2 = textureLod(gbuffer2, texCoord, 0.0); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| #ifdef _MicroShadowing | #ifdef _MicroShadowing | ||||||
| 	occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel | 	occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef _Brdf | #ifdef _Brdf | ||||||
| 	vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; | 	vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; | ||||||
|  | 	vec3 F = f0 * envBRDF.x + envBRDF.y; | ||||||
|  | #else | ||||||
|  | 	vec3 F = f0; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #ifndef _VoxelAOvar | ||||||
|  | #ifndef _VoxelGI | ||||||
| 	// Envmap | 	// Envmap | ||||||
| #ifdef _Irr | #ifdef _Irr | ||||||
|  |  | ||||||
| 	vec3 envl = shIrradiance(n, shirr); | 	vec3 envl = shIrradiance(n, shirr); | ||||||
|  |  | ||||||
| 	#ifdef _gbuffer2 | 	#ifdef _gbuffer2 | ||||||
| @ -271,33 +299,33 @@ void main() { | |||||||
| 	envl.rgb *= albedo; | 	envl.rgb *= albedo; | ||||||
|  |  | ||||||
| #ifdef _Brdf | #ifdef _Brdf | ||||||
| 	envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y); //LV: We should take refracted light into account | 	envl.rgb *= 1.0 - F; //LV: We should take refracted light into account | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef _Rad // Indirect specular | #ifdef _Rad // Indirect specular | ||||||
| 	envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y); //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT | 	envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT | ||||||
| #else | #else | ||||||
| 	#ifdef _EnvCol | 	#ifdef _EnvCol | ||||||
| 	envl.rgb += backgroundCol * (f0 * envBRDF.x + envBRDF.y); //LV: Eh, what's the point of weighting it only by F0? | 	envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0? | ||||||
| 	#endif | 	#endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	envl.rgb *= envmapStrength * occspec.x; | 	envl.rgb *= envmapStrength * occspec.x; | ||||||
|  |  | ||||||
| #ifdef _VoxelGI |  | ||||||
| 	vec4 indirect_diffuse = textureLod(voxels_diffuse, texCoord, 0.0); |  | ||||||
| 	fragColor.rgb = (indirect_diffuse.rgb * albedo + envl.rgb * (1.0 - indirect_diffuse.a)) * voxelgiDiff; |  | ||||||
| 	if(roughness < 1.0 && occspec.y > 0.0) |  | ||||||
| 		fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef _VoxelAOvar |  | ||||||
| 	envl.rgb *= textureLod(voxels_ao, texCoord, 0.0).r; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifndef _VoxelGI |  | ||||||
| 	fragColor.rgb = envl; | 	fragColor.rgb = envl; | ||||||
| #endif | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _VoxelGI | ||||||
|  | 	fragColor.rgb = textureLod(voxels_diffuse, texCoord, 0.0).rgb * voxelgiDiff; | ||||||
|  | 	if(roughness < 1.0 && occspec.y > 0.0) | ||||||
|  | 		fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl; | ||||||
|  | #else | ||||||
|  | #ifdef _VoxelAOvar | ||||||
|  | 	fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb * voxelgiOcc; | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	// Show voxels | 	// Show voxels | ||||||
| 	// vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99); | 	// vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99); | ||||||
| 	// vec3 direction = vec3(0.0, 0.0, -1.0); | 	// vec3 direction = vec3(0.0, 0.0, -1.0); | ||||||
| @ -317,6 +345,10 @@ void main() { | |||||||
| 	// #else | 	// #else | ||||||
| 	fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r; | 	fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r; | ||||||
| 	// #endif | 	// #endif | ||||||
|  | #else | ||||||
|  | #ifdef _SSGI | ||||||
|  | 	fragColor.rgb += textureLod(ssaotex, texCoord, 0.0).rgb; | ||||||
|  | #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef _EmissionShadeless | #ifdef _EmissionShadeless | ||||||
| @ -349,38 +381,68 @@ void main() { | |||||||
| 	#ifdef _ShadowMap | 	#ifdef _ShadowMap | ||||||
| 		#ifdef _CSM | 		#ifdef _CSM | ||||||
| 			svisibility = shadowTestCascade( | 			svisibility = shadowTestCascade( | ||||||
| 				#ifdef _ShadowMapAtlas | 											#ifdef _ShadowMapAtlas | ||||||
| 					#ifndef _SingleAtlas | 												#ifdef _ShadowMapTransparent | ||||||
| 					shadowMapAtlasSun, shadowMapAtlasSunTransparent | 												#ifndef _SingleAtlas | ||||||
| 					#else | 												shadowMapAtlasSun, shadowMapAtlasSunTransparent | ||||||
| 					shadowMapAtlas, shadowMapAtlasTransparent | 												#else | ||||||
| 					#endif | 												shadowMapAtlas, shadowMapAtlasTransparent | ||||||
| 				#else | 												#endif | ||||||
| 				shadowMap, shadowMapTransparent | 												#else | ||||||
| 				#endif | 												#ifndef _SingleAtlas | ||||||
| 				, eye, p + n * shadowsBias * 10, shadowsBias, false | 												shadowMapAtlasSun | ||||||
| 			); | 												#else | ||||||
|  | 												shadowMapAtlas | ||||||
|  | 												#endif | ||||||
|  | 												#endif | ||||||
|  | 											#else | ||||||
|  | 											#ifdef _ShadowMapTransparent | ||||||
|  | 											shadowMap, shadowMapTransparent | ||||||
|  | 											#else | ||||||
|  | 											shadowMap | ||||||
|  | 											#endif | ||||||
|  | 											#endif | ||||||
|  | 											, eye, p + n * shadowsBias * 10, shadowsBias | ||||||
|  | 											#ifdef _ShadowMapTransparent | ||||||
|  | 											, false | ||||||
|  | 											#endif | ||||||
|  | 											); | ||||||
| 		#else | 		#else | ||||||
| 			vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0); | 			vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0); | ||||||
| 			if (lPos.w > 0.0) { | 			if (lPos.w > 0.0) { | ||||||
| 				svisibility = shadowTest( | 				svisibility = shadowTest( | ||||||
| 					#ifdef _ShadowMapAtlas | 										#ifdef _ShadowMapAtlas | ||||||
| 						#ifndef _SingleAtlas | 											#ifdef _ShadowMapTransparent | ||||||
| 						shadowMapAtlasSun, shadowMapAtlasSunTransparent | 											#ifndef _SingleAtlas | ||||||
| 						#else | 											shadowMapAtlasSun, shadowMapAtlasSunTransparent | ||||||
| 						shadowMapAtlas, shadowMapAtlasTransparent | 											#else | ||||||
| 						#endif | 											shadowMapAtlas, shadowMapAtlasTransparent | ||||||
| 					#else | 											#endif | ||||||
| 					shadowMap, shadowMapTransparent | 											#else | ||||||
| 					#endif | 											#ifndef _SingleAtlas | ||||||
| 					, lPos.xyz / lPos.w, shadowsBias, false | 											shadowMapAtlasSun | ||||||
| 				); | 											#else | ||||||
|  | 											shadowMapAtlas | ||||||
|  | 											#endif | ||||||
|  | 											#endif | ||||||
|  | 										#else | ||||||
|  | 										#ifdef _ShadowMapTransparent | ||||||
|  | 										shadowMap, shadowMapTransparent | ||||||
|  | 										#else | ||||||
|  | 										shadowMap | ||||||
|  | 										#endif | ||||||
|  | 										#endif | ||||||
|  | 										, lPos.xyz / lPos.w, shadowsBias | ||||||
|  | 										#ifdef _ShadowMapTransparent | ||||||
|  | 										, false | ||||||
|  | 										#endif | ||||||
|  | 										); | ||||||
| 			} | 			} | ||||||
| 		#endif | 		#endif | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	#ifdef _VoxelShadow | 	#ifdef _VoxelShadow | ||||||
| 	svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy).r) * voxelgiShad; | 	svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, -g2.rg).r) * voxelgiShad; | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	#ifdef _SSRS | 	#ifdef _SSRS | ||||||
| @ -439,13 +501,16 @@ void main() { | |||||||
| 	fragColor.rgb += sampleLight( | 	fragColor.rgb += sampleLight( | ||||||
| 		p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0 | 		p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0 | ||||||
| 		#ifdef _ShadowMap | 		#ifdef _ShadowMap | ||||||
| 			, 0, pointBias, true, false | 			, 0, pointBias, true | ||||||
|  | 		#ifdef _ShadowMapTransparent | ||||||
|  | 			, false | ||||||
|  | 		#endif | ||||||
| 		#endif | 		#endif | ||||||
| 		#ifdef _Spot | 		#ifdef _Spot | ||||||
| 		, true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight | 		, true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight | ||||||
| 		#endif | 		#endif | ||||||
| 		#ifdef _VoxelShadow | 		#ifdef _VoxelShadow | ||||||
| 			, voxels, voxelsSDF, clipmaps | 			, voxels, voxelsSDF, clipmaps, -g2.rg | ||||||
| 		#endif | 		#endif | ||||||
| 		#ifdef _MicroShadowing | 		#ifdef _MicroShadowing | ||||||
| 		, occspec.x | 		, occspec.x | ||||||
| @ -492,7 +557,10 @@ void main() { | |||||||
| 			f0 | 			f0 | ||||||
| 			#ifdef _ShadowMap | 			#ifdef _ShadowMap | ||||||
| 				// light index, shadow bias, cast_shadows | 				// light index, shadow bias, cast_shadows | ||||||
| 				, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false | 				, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0 | ||||||
|  | 			#ifdef _ShadowMapTransparent | ||||||
|  | 				, false | ||||||
|  | 			#endif | ||||||
| 			#endif | 			#endif | ||||||
| 			#ifdef _Spot | 			#ifdef _Spot | ||||||
| 			, lightsArray[li * 3 + 2].y != 0.0 | 			, lightsArray[li * 3 + 2].y != 0.0 | ||||||
| @ -503,7 +571,7 @@ void main() { | |||||||
| 			, lightsArraySpot[li * 2 + 1].xyz // right | 			, lightsArraySpot[li * 2 + 1].xyz // right | ||||||
| 			#endif | 			#endif | ||||||
| 			#ifdef _VoxelShadow | 			#ifdef _VoxelShadow | ||||||
| 			, voxels, voxelsSDF, clipmaps | 			, voxels, voxelsSDF, clipmaps, -g2.rg | ||||||
| 			#endif | 			#endif | ||||||
| 			#ifdef _MicroShadowing | 			#ifdef _MicroShadowing | ||||||
| 			, occspec.x | 			, occspec.x | ||||||
| @ -514,14 +582,5 @@ void main() { | |||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
| #endif // _Clusters | #endif // _Clusters | ||||||
|  |  | ||||||
| /* |  | ||||||
| #ifdef _VoxelRefract |  | ||||||
| if(opac < 1.0) { |  | ||||||
| 	vec3 refraction = traceRefraction(p, n, voxels, v, ior, roughness, eye) * voxelgiRefr; |  | ||||||
| 	fragColor.rgb = mix(refraction, fragColor.rgb, opac); |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| */ |  | ||||||
| 	fragColor.a = 1.0; // Mark as opaque | 	fragColor.a = 1.0; // Mark as opaque | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,107 +1,506 @@ | |||||||
| #version 450 | #version 450 | ||||||
|  |  | ||||||
| #include "compiled.inc" | #include "compiled.inc" | ||||||
| #include "std/math.glsl" |  | ||||||
| #include "std/gbuffer.glsl" | #include "std/gbuffer.glsl" | ||||||
|  | #include "std/brdf.glsl" | ||||||
|  | #include "std/math.glsl" | ||||||
|  | #ifdef _Clusters | ||||||
|  | #include "std/clusters.glsl" | ||||||
|  | #endif | ||||||
|  | #ifdef _ShadowMap | ||||||
|  | #include "std/shadows.glsl" | ||||||
|  | #endif | ||||||
|  | #ifdef _LTC | ||||||
|  | #include "std/ltc.glsl" | ||||||
|  | #endif | ||||||
|  | #ifdef _LightIES | ||||||
|  | #include "std/ies.glsl" | ||||||
|  | #endif | ||||||
|  | #ifdef _Spot | ||||||
|  | #include "std/light_common.glsl" | ||||||
|  | #endif | ||||||
|  | #include "std/constants.glsl" | ||||||
|  |  | ||||||
|  | uniform sampler2D gbuffer0; | ||||||
|  | uniform sampler2D gbuffer1; | ||||||
| uniform sampler2D gbufferD; | uniform sampler2D gbufferD; | ||||||
| uniform sampler2D gbuffer0; // Normal | #ifdef _EmissionShaded | ||||||
| // #ifdef _RTGI | uniform sampler2D gbufferEmission; | ||||||
| // uniform sampler2D gbuffer1; // Basecol | #endif | ||||||
| // #endif | uniform sampler2D sveloc; | ||||||
| uniform mat4 P; |  | ||||||
| uniform mat3 V3; |  | ||||||
|  |  | ||||||
| uniform vec2 cameraProj; | uniform vec2 cameraProj; | ||||||
|  | uniform vec3 eye; | ||||||
|  | uniform vec3 eyeLook; | ||||||
|  | uniform vec2 screenSize; | ||||||
|  | uniform mat4 invVP; | ||||||
|  |  | ||||||
| const float angleMix = 0.5f; | in vec2 texCoord; | ||||||
| #ifdef _SSGICone9 | in vec3 viewRay; | ||||||
| const float strength = 2.0 * (1.0 / ssgiStrength); | out vec3 fragColor; | ||||||
| #else |  | ||||||
| const float strength = 2.0 * (1.0 / ssgiStrength) * 1.8; | float metallic; | ||||||
|  | uint matid; | ||||||
|  |  | ||||||
|  | #ifdef _SMSizeUniform | ||||||
|  | //!uniform vec2 smSizeUniform; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| in vec3 viewRay; | #ifdef _Clusters | ||||||
| in vec2 texCoord; | uniform vec4 lightsArray[maxLights * 3]; | ||||||
| out float fragColor; | 	#ifdef _Spot | ||||||
|  | 	uniform vec4 lightsArraySpot[maxLights * 2]; | ||||||
| vec3 hitCoord; |  | ||||||
| vec2 coord; |  | ||||||
| float depth; |  | ||||||
| // #ifdef _RTGI |  | ||||||
| // vec3 col = vec3(0.0); |  | ||||||
| // #endif |  | ||||||
| vec3 vpos; |  | ||||||
|  |  | ||||||
| vec2 getProjectedCoord(vec3 hitCoord) { |  | ||||||
| 	vec4 projectedCoord = P * vec4(hitCoord, 1.0); |  | ||||||
| 	projectedCoord.xy /= projectedCoord.w; |  | ||||||
| 	projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; |  | ||||||
| 	#ifdef _InvY |  | ||||||
| 	projectedCoord.y = 1.0 - projectedCoord.y; |  | ||||||
| 	#endif | 	#endif | ||||||
| 	return projectedCoord.xy; | uniform sampler2D clustersData; | ||||||
| } | uniform vec2 cameraPlane; | ||||||
|  | #endif | ||||||
|  |  | ||||||
| float getDeltaDepth(vec3 hitCoord) { | #ifdef _SinglePoint // Fast path for single light | ||||||
| 	coord = getProjectedCoord(hitCoord); | uniform vec3 pointPos; | ||||||
| 	depth = textureLod(gbufferD, coord, 0.0).r * 2.0 - 1.0; | uniform vec3 pointCol; | ||||||
| 	vec3 p = getPosView(viewRay, depth, cameraProj); | 	#ifdef _ShadowMap | ||||||
| 	return p.z - hitCoord.z; | 	uniform float pointBias; | ||||||
| } | 	#endif | ||||||
|  | 	#ifdef _Spot | ||||||
|  | 	uniform vec3 spotDir; | ||||||
|  | 	uniform vec3 spotRight; | ||||||
|  | 	uniform vec4 spotData; | ||||||
|  | 	#endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
| void rayCast(vec3 dir) { | #ifdef _CPostprocess | ||||||
| 	hitCoord = vpos; |     uniform vec3 PPComp12; | ||||||
| 	dir *= ssgiRayStep * 2; | #endif | ||||||
| 	float dist = 0.15; |  | ||||||
| 	for (int i = 0; i < ssgiMaxSteps; i++) { | #ifdef _ShadowMap | ||||||
| 		hitCoord += dir; | 	#ifdef _SinglePoint | ||||||
| 		float delta = getDeltaDepth(hitCoord); | 		#ifdef _Spot | ||||||
| 		if (delta > 0.0 && delta < 0.2) { | 			#ifndef _LTC | ||||||
| 			dist = distance(vpos, hitCoord); | 				uniform sampler2DShadow shadowMapSpot[1]; | ||||||
| 			break; | 				uniform sampler2D shadowMapSpotTransparent[1]; | ||||||
|  | 				uniform mat4 LWVPSpot[1]; | ||||||
|  | 			#endif | ||||||
|  | 		#else | ||||||
|  | 			uniform samplerCubeShadow shadowMapPoint[1]; | ||||||
|  | 			uniform samplerCube shadowMapPointTransparent[1]; | ||||||
|  | 			uniform vec2 lightProj; | ||||||
|  | 		#endif | ||||||
|  | 	#endif | ||||||
|  | 	#ifdef _Clusters | ||||||
|  | 		#ifdef _SingleAtlas | ||||||
|  | 		uniform sampler2DShadow shadowMapAtlas; | ||||||
|  | 		uniform sampler2D shadowMapAtlasTransparent; | ||||||
|  | 		#endif | ||||||
|  | 		uniform vec2 lightProj; | ||||||
|  | 		#ifdef _ShadowMapAtlas | ||||||
|  | 		#ifndef _SingleAtlas | ||||||
|  | 		uniform sampler2DShadow shadowMapAtlasPoint; | ||||||
|  | 		uniform sampler2D shadowMapAtlasPointTransparent; | ||||||
|  | 		//!uniform vec4 pointLightDataArray[maxLightsCluster * 6]; | ||||||
|  | 		#else | ||||||
|  | 		uniform samplerCubeShadow shadowMapPoint[4]; | ||||||
|  | 		uniform samplerCube shadowMapPointTransparent[4]; | ||||||
|  | 		#endif | ||||||
|  | 		#endif | ||||||
|  | 		#ifdef _Spot | ||||||
|  | 			#ifdef _ShadowMapAtlas | ||||||
|  | 			#ifndef _SingleAtlas | ||||||
|  | 			uniform sampler2DShadow shadowMapAtlasSpot; | ||||||
|  | 			uniform sampler2D shadowMapAtlasSpotTransparent; | ||||||
|  | 			#endif | ||||||
|  | 			#else | ||||||
|  | 			uniform sampler2DShadow shadowMapSpot[4]; | ||||||
|  | 			uniform sampler2D shadowMapSpotTransparent[4]; | ||||||
|  | 			#endif | ||||||
|  | 			uniform mat4 LWVPSpotArray[maxLightsCluster]; | ||||||
|  | 		#endif | ||||||
|  | 	#endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _LTC | ||||||
|  | uniform vec3 lightArea0; | ||||||
|  | uniform vec3 lightArea1; | ||||||
|  | uniform vec3 lightArea2; | ||||||
|  | uniform vec3 lightArea3; | ||||||
|  | uniform sampler2D sltcMat; | ||||||
|  | uniform sampler2D sltcMag; | ||||||
|  | #ifdef _ShadowMap | ||||||
|  | #ifndef _Spot | ||||||
|  | 	#ifdef _SinglePoint | ||||||
|  | 		uniform sampler2DShadow shadowMapSpot[1]; | ||||||
|  | 		uniform sampler2D shadowMapSpotTransparent[1]; | ||||||
|  | 		uniform mat4 LWVPSpot[1]; | ||||||
|  | 	#endif | ||||||
|  | 	#ifdef _Clusters | ||||||
|  | 		uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; | ||||||
|  | 		uniform mat4 LWVPSpotArray[maxLightsCluster]; | ||||||
|  | 	#endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _Sun | ||||||
|  | uniform vec3 sunDir; | ||||||
|  | uniform vec3 sunCol; | ||||||
|  | 	#ifdef _ShadowMap | ||||||
|  | 	#ifdef _ShadowMapAtlas | ||||||
|  | 	#ifndef _SingleAtlas | ||||||
|  | 	uniform sampler2DShadow shadowMapAtlasSun; | ||||||
|  | 	uniform sampler2D shadowMapAtlasSunTransparent; | ||||||
|  | 	#endif | ||||||
|  | 	#else | ||||||
|  | 	uniform sampler2DShadow shadowMap; | ||||||
|  | 	uniform sampler2D shadowMapTransparent; | ||||||
|  | 	#endif | ||||||
|  | 	uniform float shadowsBias; | ||||||
|  | 	#ifdef _CSM | ||||||
|  | 	//!uniform vec4 casData[shadowmapCascades * 4 + 4]; | ||||||
|  | 	#else | ||||||
|  | 	uniform mat4 LWVP; | ||||||
|  | 	#endif | ||||||
|  | 	#endif // _ShadowMap | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | vec3 sampleLight(const vec3 p, const vec3 n, const vec3 lp, const vec3 lightCol | ||||||
|  | 	#ifdef _ShadowMap | ||||||
|  | 		, int index, float bias, bool receiveShadow, bool transparent | ||||||
|  | 	#endif | ||||||
|  | 	#ifdef _Spot | ||||||
|  | 		, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right | ||||||
|  | 	#endif | ||||||
|  | 	) { | ||||||
|  |  | ||||||
|  | 	vec3 ld = lp - p; | ||||||
|  | 	vec3 l = normalize(ld); | ||||||
|  |  | ||||||
|  | 	vec3 visibility = lightCol; | ||||||
|  | 	visibility *= attenuate(distance(p, lp)); | ||||||
|  |  | ||||||
|  | 	#ifdef _LTC | ||||||
|  | 	#ifdef _ShadowMap | ||||||
|  | 		if (receiveShadow) { | ||||||
|  | 			#ifdef _SinglePoint | ||||||
|  | 			vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); | ||||||
|  | 			visibility *= shadowTest(shadowMapSpot[0], | ||||||
|  | 							shadowMapSpotTransparent[0], | ||||||
|  | 							lPos.xyz / lPos.w, bias, transparent); | ||||||
|  | 			#endif | ||||||
|  | 			#ifdef _Clusters | ||||||
|  | 			vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); | ||||||
|  | 			if (index == 0) visibility *= shadowTest(shadowMapSpot[0], | ||||||
|  | 					shadowMapSpotTransparent[0], | ||||||
|  | 					lPos.xyz / lPos.w, bias, transparent); | ||||||
|  | 			else if (index == 1) visibility *= shadowTest(shadowMapSpot[1], | ||||||
|  | 					shadowMapSpotTransparent[1], | ||||||
|  | 					, lPos.xyz / lPos.w, bias, transparent); | ||||||
|  | 			else if (index == 2) visibility *= shadowTest(shadowMapSpot[2], | ||||||
|  | 					shadowMapSpotTransparent[2], | ||||||
|  | 					lPos.xyz / lPos.w, bias, transparent); | ||||||
|  | 			else if (index == 3) visibility *= shadowTest(shadowMapSpot[3], | ||||||
|  | 					shadowMapSpotTransparent[3], | ||||||
|  | 					lPos.xyz / lPos.w, bias, transparent); | ||||||
|  | 			#endif | ||||||
| 		} | 		} | ||||||
|  | 	#endif | ||||||
|  | 	return visibility; | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
|  | 	#ifdef _Spot | ||||||
|  | 	if (isSpot) { | ||||||
|  | 		visibility *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend); | ||||||
|  |  | ||||||
|  | 		#ifdef _ShadowMap | ||||||
|  | 			if (receiveShadow) { | ||||||
|  | 				#ifdef _SinglePoint | ||||||
|  | 				vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); | ||||||
|  | 				visibility *= shadowTest(shadowMapSpot[0], | ||||||
|  | 									 shadowMapSpotTransparent[0], | ||||||
|  | 									lPos.xyz / lPos.w, bias, transparent); | ||||||
|  | 				#endif | ||||||
|  | 				#ifdef _Clusters | ||||||
|  | 					vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); | ||||||
|  | 					#ifdef _ShadowMapAtlas | ||||||
|  | 						visibility *= shadowTest( | ||||||
|  | 							#ifndef _SingleAtlas | ||||||
|  | 							shadowMapAtlasSpot, shadowMapAtlasSpotTransparent | ||||||
|  | 							#else | ||||||
|  | 							shadowMapAtlas, shadowMapAtlasTransparent | ||||||
|  | 							#endif | ||||||
|  | 							, lPos.xyz / lPos.w, bias, transparent | ||||||
|  | 						); | ||||||
|  | 					#else | ||||||
|  | 							 if (index == 0) visibility *= shadowTest(shadowMapSpot[0], | ||||||
|  | 									shadowMapSpotTransparent[0], | ||||||
|  | 									lPos.xyz / lPos.w, bias, transparent); | ||||||
|  | 						else if (index == 1) visibility *= shadowTest(shadowMapSpot[1], | ||||||
|  | 									shadowMapSpotTransparent[1], | ||||||
|  | 									lPos.xyz / lPos.w, bias, transparent); | ||||||
|  | 						else if (index == 2) visibility *= shadowTest(shadowMapSpot[2], | ||||||
|  | 									shadowMapSpotTransparent[2], | ||||||
|  | 									lPos.xyz / lPos.w, bias, transparent); | ||||||
|  | 						else if (index == 3) visibility *= shadowTest(shadowMapSpot[3], | ||||||
|  | 									shadowMapSpotTransparent[3], | ||||||
|  | 									lPos.xyz / lPos.w, bias, transparent); | ||||||
|  | 					#endif | ||||||
|  | 				#endif | ||||||
|  | 			} | ||||||
|  | 		#endif | ||||||
|  | 		return visibility; | ||||||
| 	} | 	} | ||||||
| 	fragColor += dist; | 	#endif | ||||||
| 	// #ifdef _RTGI |  | ||||||
| 	// col += textureLod(gbuffer1, coord, 0.0).rgb * ((ssgiRayStep * ssgiMaxSteps) - dist); | 	#ifdef _LightIES | ||||||
| 	// #endif | 	visibility *= iesAttenuation(-l); | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
|  | 	#ifdef _ShadowMap | ||||||
|  | 		if (receiveShadow) { | ||||||
|  | 			#ifdef _SinglePoint | ||||||
|  | 			#ifndef _Spot | ||||||
|  | 			visibility *= PCFCube(shadowMapPoint[0], | ||||||
|  | 							shadowMapPointTransparent[0], | ||||||
|  | 							ld, -l, bias, lightProj, n, transparent); | ||||||
|  | 			#endif | ||||||
|  | 			#endif | ||||||
|  | 			#ifdef _Clusters | ||||||
|  | 				#ifdef _ShadowMapAtlas | ||||||
|  | 				visibility *= PCFFakeCube( | ||||||
|  | 					#ifndef _SingleAtlas | ||||||
|  | 					shadowMapAtlasPoint, shadowMapAtlasPointTransparent | ||||||
|  | 					#else | ||||||
|  | 					shadowMapAtlas, shadowMapAtlasTransparent | ||||||
|  | 					#endif | ||||||
|  | 					, ld, -l, bias, lightProj, n, index, transparent | ||||||
|  | 				); | ||||||
|  | 				#else | ||||||
|  | 					 if (index == 0) visibility *= PCFCube(shadowMapPoint[0], | ||||||
|  | 								shadowMapPointTransparent[0], | ||||||
|  | 								ld, -l, bias, lightProj, n, transparent); | ||||||
|  | 				else if (index == 1) visibility *= PCFCube(shadowMapPoint[1], | ||||||
|  | 								shadowMapPointTransparent[1], | ||||||
|  | 								ld, -l, bias, lightProj, n, transparent); | ||||||
|  | 				else if (index == 2) visibility *= PCFCube(shadowMapPoint[2], | ||||||
|  | 								shadowMapPointTransparent[2], | ||||||
|  | 								ld, -l, bias, lightProj, n, transparent); | ||||||
|  | 				else if (index == 3) visibility *= PCFCube(shadowMapPoint[3], | ||||||
|  | 								shadowMapPointTransparent[3], | ||||||
|  | 								ld, -l, bias, lightProj, n, transparent); | ||||||
|  | 				#endif | ||||||
|  | 			#endif | ||||||
|  | 		} | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
|  | 	return visibility; | ||||||
| } | } | ||||||
|  |  | ||||||
| vec3 tangent(const vec3 n) { | vec3 getVisibility(vec3 p, vec3 n, float depth, vec2 uv) { | ||||||
| 	vec3 t1 = cross(n, vec3(0, 0, 1)); | 		vec3 visibility = vec3(0.0); | ||||||
| 	vec3 t2 = cross(n, vec3(0, 1, 0)); | #ifdef _Sun | ||||||
| 	if (length(t1) > length(t2)) return normalize(t1); | 	#ifdef _ShadowMap | ||||||
| 	else return normalize(t2); | 		#ifdef _CSM | ||||||
|  | 			visibility = shadowTestCascade( | ||||||
|  | 				#ifdef _ShadowMapAtlas | ||||||
|  | 					#ifndef _SingleAtlas | ||||||
|  | 					shadowMapAtlasSun, shadowMapAtlasSunTransparent | ||||||
|  | 					#else | ||||||
|  | 					shadowMapAtlas, shadowMapAtlasTransparent | ||||||
|  | 					#endif | ||||||
|  | 				#else | ||||||
|  | 				shadowMap, shadowMapTransparent | ||||||
|  | 				#endif | ||||||
|  | 				, eye, p + n * shadowsBias * 10, shadowsBias, false | ||||||
|  | 			); | ||||||
|  | 		#else | ||||||
|  | 			vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0); | ||||||
|  | 			if (lPos.w > 0.0) { | ||||||
|  | 				visibility = shadowTest( | ||||||
|  | 					#ifdef _ShadowMapAtlas | ||||||
|  | 						#ifndef _SingleAtlas | ||||||
|  | 						shadowMapAtlasSun, shadowMapAtlasSunTransparent | ||||||
|  | 						#else | ||||||
|  | 						shadowMapAtlas, shadowMapAtlasTransparent | ||||||
|  | 						#endif | ||||||
|  | 					#else | ||||||
|  | 					shadowMap, shadowMapTransparent | ||||||
|  | 					#endif | ||||||
|  | 					, lPos.xyz / lPos.w, shadowsBias, false | ||||||
|  | 				); | ||||||
|  | 			} | ||||||
|  | 		#endif | ||||||
|  | 	#endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _SinglePoint | ||||||
|  | 	visibility += sampleLight( | ||||||
|  | 		p, n, pointPos, pointCol | ||||||
|  | 		#ifdef _ShadowMap | ||||||
|  | 			, 0, pointBias, true, false | ||||||
|  | 		#endif | ||||||
|  | 		#ifdef _Spot | ||||||
|  | 		, true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight | ||||||
|  | 		#endif | ||||||
|  | 	); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _Clusters | ||||||
|  | 	float viewz = linearize(depth, cameraProj); | ||||||
|  | 	int clusterI = getClusterI(uv, viewz, cameraPlane); | ||||||
|  | 	int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255); | ||||||
|  |  | ||||||
|  | 	#ifdef HLSL | ||||||
|  | 	viewz += textureLod(clustersData, vec2(0.0), 0.0).r * 1e-9; // TODO: krafix bug, needs to generate sampler | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
|  | 	#ifdef _Spot | ||||||
|  | 	int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255); | ||||||
|  | 	int numPoints = numLights - numSpots; | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
|  | 	for (int i = 0; i < min(numLights, maxLightsCluster); i++) { | ||||||
|  | 		int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255); | ||||||
|  | 		visibility += sampleLight( | ||||||
|  | 			p, | ||||||
|  | 			n, | ||||||
|  | 			lightsArray[li * 3].xyz, // lp | ||||||
|  | 			lightsArray[li * 3 + 1].xyz // lightCol | ||||||
|  | 			#ifdef _ShadowMap | ||||||
|  | 				// light index, shadow bias, cast_shadows | ||||||
|  | 				, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false | ||||||
|  | 			#endif | ||||||
|  | 			#ifdef _Spot | ||||||
|  | 			, lightsArray[li * 3 + 2].y != 0.0 | ||||||
|  | 			, lightsArray[li * 3 + 2].y // spot size (cutoff) | ||||||
|  | 			, lightsArraySpot[li * 2].w // spot blend (exponent) | ||||||
|  | 			, lightsArraySpot[li * 2].xyz // spotDir | ||||||
|  | 			, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w) // scale | ||||||
|  | 			, lightsArraySpot[li * 2 + 1].xyz // right | ||||||
|  | 			#endif | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | #endif // _Clusters | ||||||
|  | 	return visibility; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | vec3 getWorldPos(vec2 uv, float depth) { | ||||||
|  |     vec4 pos = invVP * vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0); | ||||||
|  |     return pos.xyz / pos.w; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | vec3 getNormal(vec2 uv) { | ||||||
|  |     vec4 g0 = textureLod(gbuffer0, uv, 0.0); | ||||||
|  |     vec2 enc = g0.rg; | ||||||
|  |     vec3 n; | ||||||
|  |     n.z = 1.0 - abs(enc.x) - abs(enc.y); | ||||||
|  |     n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy); | ||||||
|  |     return normalize(n); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | vec3 calculateIndirectLight(vec2 uv, vec3 pos, vec3 normal, float depth) { | ||||||
|  |     // Simplified visibility - replace with your full visibility function if needed | ||||||
|  |     vec3 sampleColor = textureLod(gbuffer1, uv, 0.0).rgb * getVisibility(pos, normal, depth, uv); | ||||||
|  |  | ||||||
|  | 	#ifdef _EmissionShadeless | ||||||
|  | 		if (matid == 1) { // pure emissive material, color stored in basecol | ||||||
|  | 			sampleColor += textureLod(gbuffer1, uv, 0.0).rgb; | ||||||
|  | 		} | ||||||
|  | 	#endif | ||||||
|  | 	#ifdef _EmissionShaded | ||||||
|  | 		#ifdef _EmissionShadeless | ||||||
|  | 		else { | ||||||
|  | 		#endif | ||||||
|  | 			vec3 sampleEmission = textureLod(gbufferEmission, uv, 0.0).rgb; | ||||||
|  | 			sampleColor += sampleEmission; // Emission should be added directly | ||||||
|  | 		#ifdef _EmissionShadeless | ||||||
|  | 		} | ||||||
|  | 		#endif | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
|  | 	return sampleColor; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Improved sampling parameters | ||||||
|  | const float GOLDEN_ANGLE = 2.39996323; | ||||||
|  | const float MAX_DEPTH_DIFFERENCE = 0.9; // More conservative depth threshold | ||||||
|  | const float SAMPLE_BIAS = 0.01; // Small offset to avoid self-occlusion | ||||||
|  |  | ||||||
| void main() { | void main() { | ||||||
| 	fragColor = 0; |     float depth = textureLod(gbufferD, texCoord, 0.0).r; | ||||||
| 	vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); |     if (depth >= 1.0) { | ||||||
| 	float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; |         fragColor = vec3(0.0); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | 	vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid | ||||||
|  | 	unpackFloatInt16(g0.a, metallic, matid); | ||||||
|  |  | ||||||
|  | 	vec2 velocity = -textureLod(sveloc, texCoord, 0.0).rg; | ||||||
|  |  | ||||||
| 	vec2 enc = g0.rg; |  | ||||||
| 	vec3 n; | 	vec3 n; | ||||||
| 	n.z = 1.0 - abs(enc.x) - abs(enc.y); | 	n.z = 1.0 - abs(g0.x) - abs(g0.y); | ||||||
| 	n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy); | 	n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); | ||||||
| 	n = normalize(V3 * n); | 	n = normalize(n); | ||||||
|  |  | ||||||
| 	vpos = getPosView(viewRay, d, cameraProj); |     vec3 pos = getWorldPos(texCoord, depth); | ||||||
|  |     vec3 normal = getNormal(texCoord); | ||||||
|  |     vec3 centerColor = textureLod(gbuffer1, texCoord, 0.0).rgb; | ||||||
|  |  | ||||||
| 	rayCast(n); |     float radius = ssaoRadius; | ||||||
| 	vec3 o1 = normalize(tangent(n)); |  | ||||||
| 	vec3 o2 = (cross(o1, n)); |  | ||||||
| 	vec3 c1 = 0.5f * (o1 + o2); |  | ||||||
| 	vec3 c2 = 0.5f * (o1 - o2); |  | ||||||
| 	rayCast(mix(n, o1, angleMix)); |  | ||||||
| 	rayCast(mix(n, o2, angleMix)); |  | ||||||
| 	rayCast(mix(n, -c1, angleMix)); |  | ||||||
| 	rayCast(mix(n, -c2, angleMix)); |  | ||||||
|  |  | ||||||
| 	#ifdef _SSGICone9 |     vec3 gi = vec3(0.0); | ||||||
| 	rayCast(mix(n, -o1, angleMix)); |     float totalWeight = 0.0; | ||||||
| 	rayCast(mix(n, -o2, angleMix)); |     float angle = fract(sin(dot(texCoord, vec2(12.9898, 78.233))) * 100.0); | ||||||
| 	rayCast(mix(n, c1, angleMix)); |  | ||||||
| 	rayCast(mix(n, c2, angleMix)); | 	for (int i = 0; i < ssgiSamples; i++) { | ||||||
|  | 		// Use quasi-random sequence for better coverage | ||||||
|  | 		float r = sqrt((float(i) + 0.5) / float(ssgiSamples)) * radius; | ||||||
|  | 		float a = (float(i) * GOLDEN_ANGLE) + angle; | ||||||
|  |  | ||||||
|  | 		vec2 offset = vec2(cos(a), sin(a)) * r * radius; | ||||||
|  | 		vec2 sampleUV = clamp(texCoord + offset * (BayerMatrix8[int(gl_FragCoord.x + velocity.x) % 8][int(gl_FragCoord.y + velocity.y) % 8] - 0.5) / screenSize, vec2(0.001), vec2(0.999)); | ||||||
|  |  | ||||||
|  | 		float sampleDepth = textureLod(gbufferD, sampleUV, 0.0).r; | ||||||
|  | 		if (sampleDepth >= 1.0) continue; | ||||||
|  |  | ||||||
|  | 		vec3 samplePos = getWorldPos(sampleUV, sampleDepth); | ||||||
|  | 		vec3 sampleNormal = getNormal(sampleUV); | ||||||
|  |  | ||||||
|  | 		// Apply small bias to sample position to avoid self-occlusion | ||||||
|  | 		samplePos += sampleNormal * SAMPLE_BIAS; | ||||||
|  |  | ||||||
|  | 		vec3 dir = pos - samplePos; | ||||||
|  | 		float dist = length(dir); | ||||||
|  |  | ||||||
|  | 		if (abs(pos.z - samplePos.z) > MAX_DEPTH_DIFFERENCE) continue;; | ||||||
|  |  | ||||||
|  | 		vec3 sampleColor = calculateIndirectLight(sampleUV, samplePos, sampleNormal, sampleDepth); | ||||||
|  | 		float weight = 1.0 / (1.0 + dist * dist * 2.0) * max(dot(sampleNormal, n), 0.0); | ||||||
|  |  | ||||||
|  | 		gi += sampleColor * weight; | ||||||
|  | 		totalWeight += weight; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |     // Normalize and apply intensity | ||||||
|  |     if (totalWeight > 0.0) { | ||||||
|  |         gi /= totalWeight; | ||||||
|  |         #ifdef _CPostprocess | ||||||
|  |             gi *= PPComp12.x; | ||||||
|  |         #else | ||||||
|  |             gi *= ssaoStrength; | ||||||
|  |         #endif | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | 	#ifdef _EmissionShadeless | ||||||
|  | 		if (matid == 1) { // pure emissive material, color stored in basecol | ||||||
|  | 			gi += textureLod(gbuffer1, texCoord, 0.0).rgb; | ||||||
|  | 		} | ||||||
| 	#endif | 	#endif | ||||||
|  | 	#ifdef _EmissionShaded | ||||||
|  | 		#ifdef _EmissionShadeless | ||||||
|  | 		else { | ||||||
|  | 		#endif | ||||||
|  | 			gi += textureLod(gbufferEmission, texCoord, 0.0).rgb; | ||||||
|  | 		#ifdef _EmissionShadeless | ||||||
|  | 		} | ||||||
|  | 		#endif | ||||||
|  | 	#endif | ||||||
|  | 	fragColor = gi / (gi + vec3(1.0)); // Reinhard tone mapping | ||||||
| } | } | ||||||
|  | |||||||
| @ -6,6 +6,10 @@ | |||||||
| 			"compare_mode": "always", | 			"compare_mode": "always", | ||||||
| 			"cull_mode": "none", | 			"cull_mode": "none", | ||||||
| 			"links": [ | 			"links": [ | ||||||
|  | 				{ | ||||||
|  | 					"name": "invVP", | ||||||
|  | 					"link": "_inverseViewProjectionMatrix" | ||||||
|  | 				}, | ||||||
| 				{ | 				{ | ||||||
| 					"name": "P", | 					"name": "P", | ||||||
| 					"link": "_projectionMatrix" | 					"link": "_projectionMatrix" | ||||||
| @ -15,16 +19,180 @@ | |||||||
| 					"link": "_viewMatrix3" | 					"link": "_viewMatrix3" | ||||||
| 				}, | 				}, | ||||||
| 				{ | 				{ | ||||||
| 					"name": "invP", | 					"name": "eye", | ||||||
| 					"link": "_inverseProjectionMatrix" | 					"link": "_cameraPosition" | ||||||
|  | 				},				 | ||||||
|  | 				{ | ||||||
|  | 					"name": "eyeLook", | ||||||
|  | 					"link": "_cameraLook" | ||||||
| 				}, | 				}, | ||||||
| 				{ | 				{ | ||||||
| 					"name": "cameraProj", | 					"name": "cameraProj", | ||||||
| 					"link": "_cameraPlaneProj" | 					"link": "_cameraPlaneProj" | ||||||
|  |  | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "screenSize", | ||||||
|  | 					"link": "_screenSize" | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "PPComp12", | ||||||
|  | 					"link": "_PPComp12", | ||||||
|  | 					"ifdef": ["_CPostprocess"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "lightsArraySpot", | ||||||
|  | 					"link": "_lightsArraySpot", | ||||||
|  | 					"ifdef": ["_Clusters", "_Spot"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "lightsArray", | ||||||
|  | 					"link": "_lightsArray", | ||||||
|  | 					"ifdef": ["_Clusters"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "clustersData", | ||||||
|  | 					"link": "_clustersData", | ||||||
|  | 					"ifdef": ["_Clusters"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "cameraPlane", | ||||||
|  | 					"link": "_cameraPlane", | ||||||
|  | 					"ifdef": ["_Clusters"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "sunDir", | ||||||
|  | 					"link": "_sunDirection", | ||||||
|  | 					"ifdef": ["_Sun"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "sunCol", | ||||||
|  | 					"link": "_sunColor", | ||||||
|  | 					"ifdef": ["_Sun"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "shadowsBias", | ||||||
|  | 					"link": "_sunShadowsBias", | ||||||
|  | 					"ifdef": ["_Sun", "_ShadowMap"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "LWVP", | ||||||
|  | 					"link": "_biasLightWorldViewProjectionMatrixSun", | ||||||
|  | 					"ifndef": ["_CSM"], | ||||||
|  | 					"ifdef": ["_Sun", "_ShadowMap"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "casData", | ||||||
|  | 					"link": "_cascadeData", | ||||||
|  | 					"ifdef": ["_Sun", "_ShadowMap", "_CSM"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "lightArea0", | ||||||
|  | 					"link": "_lightArea0", | ||||||
|  | 					"ifdef": ["_LTC"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "lightArea1", | ||||||
|  | 					"link": "_lightArea1", | ||||||
|  | 					"ifdef": ["_LTC"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "lightArea2", | ||||||
|  | 					"link": "_lightArea2", | ||||||
|  | 					"ifdef": ["_LTC"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "lightArea3", | ||||||
|  | 					"link": "_lightArea3", | ||||||
|  | 					"ifdef": ["_LTC"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "sltcMat", | ||||||
|  | 					"link": "_ltcMat", | ||||||
|  | 					"ifdef": ["_LTC"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "sltcMag", | ||||||
|  | 					"link": "_ltcMag", | ||||||
|  | 					"ifdef": ["_LTC"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "smSizeUniform", | ||||||
|  | 					"link": "_shadowMapSize", | ||||||
|  | 					"ifdef": ["_SMSizeUniform"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "lightProj", | ||||||
|  | 					"link": "_lightPlaneProj", | ||||||
|  | 					"ifdef": ["_ShadowMap"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "pointPos", | ||||||
|  | 					"link": "_pointPosition", | ||||||
|  | 					"ifdef": ["_SinglePoint"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "pointCol", | ||||||
|  | 					"link": "_pointColor", | ||||||
|  | 					"ifdef": ["_SinglePoint"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "pointBias", | ||||||
|  | 					"link": "_pointShadowsBias", | ||||||
|  | 					"ifdef": ["_SinglePoint", "_ShadowMap"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "spotDir", | ||||||
|  | 					"link": "_spotDirection", | ||||||
|  | 					"ifdef": ["_SinglePoint", "_Spot"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "spotData", | ||||||
|  | 					"link": "_spotData", | ||||||
|  | 					"ifdef": ["_SinglePoint", "_Spot"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "spotRight", | ||||||
|  | 					"link": "_spotRight", | ||||||
|  | 					"ifdef": ["_SinglePoint", "_Spot"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "LWVPSpotArray", | ||||||
|  | 					"link": "_biasLightWorldViewProjectionMatrixSpotArray", | ||||||
|  | 					"ifdef": ["_Clusters", "_ShadowMap", "_Spot"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "pointLightDataArray", | ||||||
|  | 					"link": "_pointLightsAtlasArray", | ||||||
|  | 					"ifdef": ["_Clusters", "_ShadowMap", "_ShadowMapAtlas"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "LWVPSpot[0]", | ||||||
|  | 					"link": "_biasLightWorldViewProjectionMatrixSpot0", | ||||||
|  | 					"ifndef": ["_ShadowMapAtlas"], | ||||||
|  | 					"ifdef": ["_LTC", "_ShadowMap"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "LWVPSpot[1]", | ||||||
|  | 					"link": "_biasLightWorldViewProjectionMatrixSpot1", | ||||||
|  | 					"ifndef": ["_ShadowMapAtlas"], | ||||||
|  | 					"ifdef": ["_LTC", "_ShadowMap"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "LWVPSpot[2]", | ||||||
|  | 					"link": "_biasLightWorldViewProjectionMatrixSpot2", | ||||||
|  | 					"ifndef": ["_ShadowMapAtlas"], | ||||||
|  | 					"ifdef": ["_LTC", "_ShadowMap"] | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					"name": "LWVPSpot[3]", | ||||||
|  | 					"link": "_biasLightWorldViewProjectionMatrixSpot3", | ||||||
|  | 					"ifndef": ["_ShadowMapAtlas"], | ||||||
|  | 					"ifdef": ["_LTC", "_ShadowMap"] | ||||||
| 				} | 				} | ||||||
| 			], | 			], | ||||||
| 			"texture_params": [], | 			"texture_params": [], | ||||||
| 			"vertex_shader": "../include/pass_viewray2.vert.glsl", | 			"vertex_shader": "../include/pass_viewray.vert.glsl", | ||||||
| 			"fragment_shader": "ssgi_pass.frag.glsl" | 			"fragment_shader": "ssgi_pass.frag.glsl" | ||||||
| 		} | 		} | ||||||
| 	] | 	] | ||||||
|  | |||||||
| @ -72,10 +72,11 @@ void main() { | |||||||
|     float roughness = g0.z; |     float roughness = g0.z; | ||||||
|     vec4 gr = textureLod(gbuffer_refraction, texCoord, 0.0); |     vec4 gr = textureLod(gbuffer_refraction, texCoord, 0.0); | ||||||
|     float ior = gr.x; |     float ior = gr.x; | ||||||
|     float opac = gr.y; |     float opac = 1.0 - gr.y; | ||||||
|     float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; |     float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; | ||||||
|     if (d == 0.0 || d == 1.0 || opac == 1.0 || ior == 1.0) { |     if (d == 0.0 || d == 1.0 || opac == 1.0 || ior == 1.0) { | ||||||
|         fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb; |         fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb; | ||||||
|  | 		fragColor.a = opac; | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 	vec2 enc = g0.rg; | 	vec2 enc = g0.rg; | ||||||
| @ -98,9 +99,12 @@ void main() { | |||||||
| 						clamp(-refracted.z, 0.0, 1.0) * clamp((length(viewPos - hitCoord)), 0.0, 1.0) * coords.w; | 						clamp(-refracted.z, 0.0, 1.0) * clamp((length(viewPos - hitCoord)), 0.0, 1.0) * coords.w; | ||||||
| 	intensity = clamp(intensity, 0.0, 1.0); | 	intensity = clamp(intensity, 0.0, 1.0); | ||||||
|  |  | ||||||
| 	vec3 refractionCol = textureLod(tex1, coords.xy, 0.0).rgb; | 	vec4 refractionCol = textureLod(tex1, coords.xy, 0.0).rgba; | ||||||
| 	refractionCol *= intensity; | 	refractionCol.a = opac; | ||||||
| 	vec3 color = textureLod(tex, texCoord.xy, 0.0).rgb; | 	//refractionCol *= intensity; | ||||||
|  | 	vec4 color = textureLod(tex, texCoord.xy, 0.0).rgba; | ||||||
|  | 	color.a = opac; | ||||||
|  |  | ||||||
| 	fragColor.rgb = mix(refractionCol, color, opac); | 	fragColor.rgba = mix(refractionCol, color, opac); | ||||||
|  | 	fragColor.a = opac; | ||||||
| } | } | ||||||
|  | |||||||
| @ -5,6 +5,12 @@ | |||||||
| 			"depth_write": false, | 			"depth_write": false, | ||||||
| 			"compare_mode": "always", | 			"compare_mode": "always", | ||||||
| 			"cull_mode": "none", | 			"cull_mode": "none", | ||||||
|  | 			"blend_source": "source_alpha", | ||||||
|  | 			"blend_destination": "inverse_source_alpha", | ||||||
|  | 			"blend_operation": "add", | ||||||
|  | 			"alpha_blend_source": "blend_one", | ||||||
|  | 			"alpha_blend_destination": "blend_one", | ||||||
|  | 			"alpha_blend_operation": "add", | ||||||
| 			"links": [ | 			"links": [ | ||||||
| 				{ | 				{ | ||||||
| 					"name": "P", | 					"name": "P", | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| // | // | ||||||
| // Copyright (C) 2012 Jorge Jimenez (jorge@iryoku.com) | // Copyright (C) 2012 Jorge Jimenez (jorge@iryoku.com) | ||||||
| // Copyright (C) 2012 Diego Gutierrez (diegog@unizar.es) | // Copyright (C) 2012 Diego Gutierrez (diegog@unizar.es) | ||||||
|  | // Copyright (C) 2025 Onek8 (info@leenkx.com) | ||||||
| // All rights reserved. | // All rights reserved. | ||||||
| // | // | ||||||
| // Redistribution and use in source and binary forms, with or without | // Redistribution and use in source and binary forms, with or without | ||||||
| @ -33,6 +34,14 @@ | |||||||
| // policies, either expressed or implied, of the copyright holders. | // policies, either expressed or implied, of the copyright holders. | ||||||
| // | // | ||||||
|  |  | ||||||
|  | // TODO: | ||||||
|  | // Add real sss radius | ||||||
|  | // Add real sss scale | ||||||
|  | // Move temp hash, reorganize shader utility functions | ||||||
|  | // Add compiler flag for quality presets or with samples parameter | ||||||
|  | // Clean up + Document comment | ||||||
|  |  | ||||||
|  |  | ||||||
| #version 450 | #version 450 | ||||||
|  |  | ||||||
| #include "compiled.inc" | #include "compiled.inc" | ||||||
| @ -49,67 +58,93 @@ out vec4 fragColor; | |||||||
|  |  | ||||||
| const float SSSS_FOVY = 108.0; | const float SSSS_FOVY = 108.0; | ||||||
|  |  | ||||||
| // Separable SSS Reflectance | // Temp hash func -  | ||||||
| // const float sssWidth = 0.005; | float hash13(vec3 p3) { | ||||||
|  | 	p3 = fract(p3 * vec3(0.1031, 0.1030, 0.0973)); | ||||||
|  | 	p3 += dot(p3, p3.yzx + 33.33); | ||||||
|  | 	return fract((p3.x + p3.y) * p3.z); | ||||||
|  | } | ||||||
|  |  | ||||||
| vec4 SSSSBlur() { | vec4 SSSSBlur() { | ||||||
| 	// Quality = 0 | 	const int SSSS_N_SAMPLES = 15; | ||||||
| 	const int SSSS_N_SAMPLES  = 11; |  | ||||||
| 	vec4 kernel[SSSS_N_SAMPLES]; | 	vec4 kernel[SSSS_N_SAMPLES]; | ||||||
| 	kernel[0] = vec4(0.560479, 0.669086, 0.784728, 0); | 	 | ||||||
| 	kernel[1] = vec4(0.00471691, 0.000184771, 5.07566e-005, -2); | 	// color neutral kernel weights to prevent color shifting | ||||||
| 	kernel[2] = vec4(0.0192831, 0.00282018, 0.00084214, -1.28); | 	kernel[0] = vec4(0.2, 0.2, 0.2, 0.0); | ||||||
| 	kernel[3] = vec4(0.03639, 0.0130999, 0.00643685, -0.72); | 	kernel[1] = vec4(0.12, 0.12, 0.12, 0.2); | ||||||
| 	kernel[4] = vec4(0.0821904, 0.0358608, 0.0209261, -0.32); | 	kernel[2] = vec4(0.09, 0.09, 0.09, 0.4); | ||||||
| 	kernel[5] = vec4(0.0771802, 0.113491, 0.0793803, -0.08); | 	kernel[3] = vec4(0.06, 0.06, 0.06, 0.8); | ||||||
| 	kernel[6] = vec4(0.0771802, 0.113491, 0.0793803, 0.08); | 	kernel[4] = vec4(0.04, 0.04, 0.04, 1.2); | ||||||
| 	kernel[7] = vec4(0.0821904, 0.0358608, 0.0209261, 0.32); | 	kernel[5] = vec4(0.025, 0.025, 0.025, 1.6); | ||||||
| 	kernel[8] = vec4(0.03639, 0.0130999, 0.00643685, 0.72); | 	kernel[6] = vec4(0.015, 0.015, 0.015, 2.0); | ||||||
| 	kernel[9] = vec4(0.0192831, 0.00282018, 0.00084214, 1.28); | 	kernel[7] = vec4(0.005, 0.005, 0.005, 2.5); | ||||||
| 	kernel[10] = vec4(0.00471691, 0.000184771, 5.07565e-005, 2); | 	kernel[8] = vec4(0.12, 0.12, 0.12, -0.2); | ||||||
|  | 	kernel[9] = vec4(0.09, 0.09, 0.09, -0.4); | ||||||
|  | 	kernel[10] = vec4(0.06, 0.06, 0.06, -0.8); | ||||||
|  | 	kernel[11] = vec4(0.04, 0.04, 0.04, -1.2); | ||||||
|  | 	kernel[12] = vec4(0.025, 0.025, 0.025, -1.6); | ||||||
|  | 	kernel[13] = vec4(0.015, 0.015, 0.015, -2.0); | ||||||
|  | 	kernel[14] = vec4(0.005, 0.005, 0.005, -2.5); | ||||||
| 	 | 	 | ||||||
| 	vec4 colorM = textureLod(tex, texCoord, 0.0); | 	vec4 colorM = textureLod(tex, texCoord, 0.0); | ||||||
|  |  | ||||||
| 	// Fetch linear depth of current pixel |  | ||||||
| 	float depth = textureLod(gbufferD, texCoord, 0.0).r; | 	float depth = textureLod(gbufferD, texCoord, 0.0).r; | ||||||
| 	float depthM = cameraProj.y / (depth - cameraProj.x); | 	float depthM = cameraProj.y / (depth - cameraProj.x); | ||||||
|  |  | ||||||
| 	// Calculate the sssWidth scale (1.0 for a unit plane sitting on the projection window) |  | ||||||
| 	float distanceToProjectionWindow = 1.0 / tan(0.5 * radians(SSSS_FOVY)); | 	float distanceToProjectionWindow = 1.0 / tan(0.5 * radians(SSSS_FOVY)); | ||||||
| 	float scale = distanceToProjectionWindow / depthM; | 	float scale = distanceToProjectionWindow / depthM; | ||||||
|  |  | ||||||
| 	// Calculate the final step to fetch the surrounding pixels |  | ||||||
| 	vec2 finalStep = sssWidth * scale * dir; | 	vec2 finalStep = sssWidth * scale * dir; | ||||||
| 	finalStep *= 1.0;//SSSS_STREGTH_SOURCE; // Modulate it using the alpha channel. |  | ||||||
| 	finalStep *= 1.0 / 3.0; // Divide by 3 as the kernels range from -3 to 3. |  | ||||||
| 	finalStep *= 0.05; // |  | ||||||
| 	 | 	 | ||||||
| 	// Accumulate the center sample: |  | ||||||
| 	vec4 colorBlurred = colorM; |  | ||||||
| 	colorBlurred.rgb *= kernel[0].rgb; |  | ||||||
|  |  | ||||||
| 	// Accumulate the other samples | 	vec3 jitterSeed = vec3(texCoord.xy * 1000.0, fract(cameraProj.x * 0.0001)); | ||||||
|  | 	float jitterOffset = (hash13(jitterSeed) * 2.0 - 1.0) * 0.15; // 15% jitteR | ||||||
|  | 	 | ||||||
|  | 	finalStep *= (1.0 + jitterOffset); | ||||||
|  | 	finalStep *= 0.05;  | ||||||
|  | 	vec3 colorBlurred = vec3(0.0); | ||||||
|  | 	vec3 weightSum = vec3(0.0); | ||||||
|  | 	colorBlurred += colorM.rgb * kernel[0].rgb; | ||||||
|  | 	weightSum += kernel[0].rgb; | ||||||
|  | 	 | ||||||
|  | 	// Accumulate the other samples with per-pixel jittering to reduce banding | ||||||
| 	for (int i = 1; i < SSSS_N_SAMPLES; i++) { | 	for (int i = 1; i < SSSS_N_SAMPLES; i++) { | ||||||
| 		// Fetch color and depth for current sample | 		float sampleJitter = hash13(vec3(texCoord.xy * 720.0, float(i) * 37.45)) * 0.1 - 0.05; | ||||||
| 		vec2 offset = texCoord + kernel[i].a * finalStep; |  | ||||||
| 		vec4 color = textureLod(tex, offset, 0.0); |  | ||||||
| 		//#if SSSS_FOLLOW_SURFACE == 1 |  | ||||||
| 		// If the difference in depth is huge, we lerp color back to "colorM": |  | ||||||
| 		//float depth = textureLod(tex, offset, 0.0).r; |  | ||||||
| 		//float s = clamp(300.0f * distanceToProjectionWindow * sssWidth * abs(depthM - depth),0.0,1.0); |  | ||||||
| 		//color.rgb = mix(color.rgb, colorM.rgb, s); |  | ||||||
| 		//#endif |  | ||||||
| 		// Accumulate |  | ||||||
| 		colorBlurred.rgb += kernel[i].rgb * color.rgb; |  | ||||||
| 	} |  | ||||||
| 		 | 		 | ||||||
| 	return colorBlurred; | 		vec2 offset = texCoord + (kernel[i].a + sampleJitter) * finalStep; | ||||||
|  | 		vec4 color = textureLod(tex, offset, 0.0); | ||||||
|  | 		 | ||||||
|  | 		// ADJUST FOR SURFACE FOLLOWING | ||||||
|  | 		// 0.0 = disabled (maximum SSS but with bleeding), 1.0 = fully enabled (prevents bleeding but might reduce SSS effect) | ||||||
|  | 		const float SURFACE_FOLLOWING_STRENGTH = 0.15; // Reduced to preserve more SSS effect | ||||||
|  | 		 | ||||||
|  | 		if (SURFACE_FOLLOWING_STRENGTH > 0.0) { | ||||||
|  | 			float sampleDepth = textureLod(gbufferD, offset, 0.0).r; | ||||||
|  | 			float depthScale = 5.0;  | ||||||
|  | 			float depthDiff = abs(depth - sampleDepth) * depthScale; | ||||||
|  | 			if (depthDiff > 0.3) {  | ||||||
|  | 				float blendFactor = clamp(depthDiff - 0.3, 0.0, 1.0) * SURFACE_FOLLOWING_STRENGTH; | ||||||
|  | 				color.rgb = mix(color.rgb, colorM.rgb, blendFactor); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		colorBlurred += color.rgb * kernel[i].rgb; | ||||||
|  | 		weightSum += kernel[i].rgb; | ||||||
|  | 	} | ||||||
|  | 	vec3 normalizedColor = colorBlurred / max(weightSum, vec3(0.00001)); | ||||||
|  | 	float dither = hash13(vec3(texCoord * 1333.0, 0.0)) * 0.003 - 0.0015; | ||||||
|  | 	return vec4(normalizedColor + vec3(dither), colorM.a); | ||||||
| } | } | ||||||
|  |  | ||||||
| void main() { | void main() { | ||||||
|  | 	 | ||||||
| 	if (textureLod(gbuffer0, texCoord, 0.0).a == 8192.0) { | 	if (textureLod(gbuffer0, texCoord, 0.0).a == 8192.0) { | ||||||
| 		fragColor = clamp(SSSSBlur(), 0.0, 1.0); | 		vec4 originalColor = textureLod(tex, texCoord, 0.0); | ||||||
| 	} | 		vec4 blurredColor = SSSSBlur(); | ||||||
| 	else { | 		vec4 finalColor = mix(blurredColor, originalColor, 0.15); | ||||||
|  | 		 | ||||||
|  | 		fragColor = clamp(finalColor, 0.0, 1.0); | ||||||
|  | 	} else { | ||||||
| 		fragColor = textureLod(tex, texCoord, 0.0); | 		fragColor = textureLod(tex, texCoord, 0.0); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								leenkx/Shaders/std/aabb.glsl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								leenkx/Shaders/std/aabb.glsl
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | #ifndef _AABB_GLSL | ||||||
|  | #define _AABB_GLSL | ||||||
|  |  | ||||||
|  | bool IntersectAABB(vec3[2] a, vec3[2] b) { | ||||||
|  |     const float EPSILON = 0.001; // Small tolerance to prevent false negatives | ||||||
|  |     if (abs(a[0].x - b[0].x) > (a[1].x + b[1].x + EPSILON)) return false; | ||||||
|  |     if (abs(a[0].y - b[0].y) > (a[1].y + b[1].y + EPSILON)) return false; | ||||||
|  |     if (abs(a[0].z - b[0].z) > (a[1].z + b[1].z + EPSILON)) return false; | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AABBfromMinMax(inout vec3[2] aabb, vec3 _min, vec3 _max) | ||||||
|  | { | ||||||
|  | 	aabb[0] = (_min + _max) * 0.5f; | ||||||
|  | 	aabb[1] = abs(_max - aabb[0]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @ -22,7 +22,7 @@ THE SOFTWARE. | |||||||
| #ifndef _CONETRACE_GLSL_ | #ifndef _CONETRACE_GLSL_ | ||||||
| #define _CONETRACE_GLSL_ | #define _CONETRACE_GLSL_ | ||||||
|  |  | ||||||
| #include "std/voxels_constants.glsl" | #include "std/constants.glsl" | ||||||
|  |  | ||||||
| // References | // References | ||||||
| // https://github.com/Friduric/voxel-cone-tracing | // https://github.com/Friduric/voxel-cone-tracing | ||||||
| @ -92,7 +92,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori | |||||||
| 	float dist = voxelSize0; | 	float dist = voxelSize0; | ||||||
| 	float step_dist = dist; | 	float step_dist = dist; | ||||||
| 	vec3 samplePos; | 	vec3 samplePos; | ||||||
| 	vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; | 	vec3 start_pos = origin + n * voxelSize0; | ||||||
| 	int clipmap_index0 = 0; | 	int clipmap_index0 = 0; | ||||||
|  |  | ||||||
| 	vec3 aniso_direction = -dir; | 	vec3 aniso_direction = -dir; | ||||||
| @ -125,7 +125,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori | |||||||
|  |  | ||||||
| 		if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) { | 		if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) { | ||||||
| 			vec4 mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight); | 			vec4 mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight); | ||||||
| 			mipSample = mix(mipSample, mipSampleNext, smoothstep(0.0, 1.0, clipmap_blend)); | 			mipSample = mix(mipSample, mipSampleNext, clipmap_blend); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		sampleCol += (1.0 - sampleCol.a) * mipSample; | 		sampleCol += (1.0 - sampleCol.a) * mipSample; | ||||||
| @ -148,8 +148,9 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori | |||||||
| vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) { | vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) { | ||||||
| 	float sum = 0.0; | 	float sum = 0.0; | ||||||
| 	vec4 amount = vec4(0.0); | 	vec4 amount = vec4(0.0); | ||||||
|  | 	mat3 TBN = makeTangentBasis(normal); | ||||||
| 	for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) { | 	for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) { | ||||||
| 		vec3 coneDir = DIFFUSE_CONE_DIRECTIONS[i]; | 		vec3 coneDir = TBN * DIFFUSE_CONE_DIRECTIONS[i]; | ||||||
| 		const float cosTheta = dot(normal, coneDir); | 		const float cosTheta = dot(normal, coneDir); | ||||||
| 		if (cosTheta <= 0) | 		if (cosTheta <= 0) | ||||||
| 			continue; | 			continue; | ||||||
| @ -166,7 +167,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, | |||||||
| } | } | ||||||
|  |  | ||||||
| vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { | vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { | ||||||
| 	vec3 specularDir = reflect(-viewDir, normal); | 	vec3 specularDir = reflect(normalize(-viewDir), normal); | ||||||
| 	vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep; | 	vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep; | ||||||
| 	vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps); | 	vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps); | ||||||
|  |  | ||||||
| @ -176,9 +177,9 @@ vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, | |||||||
| 	return amount * voxelgiOcc; | 	return amount * voxelgiOcc; | ||||||
| } | } | ||||||
|  |  | ||||||
| vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { | vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity, const float opacity) { | ||||||
|  	const float transmittance = 1.0; |  	const float transmittance = 1.0 - opacity; | ||||||
|  	vec3 refractionDir = refract(-viewDir, normal, 1.0 / ior); |  	vec3 refractionDir = refract(normalize(-viewDir), normal, 1.0 / ior); | ||||||
|  	vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; |  	vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; | ||||||
| 	vec4 amount =  transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps); | 	vec4 amount =  transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps); | ||||||
|  |  | ||||||
| @ -196,7 +197,7 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const | |||||||
| 	float dist = voxelSize0; | 	float dist = voxelSize0; | ||||||
| 	float step_dist = dist; | 	float step_dist = dist; | ||||||
| 	vec3 samplePos; | 	vec3 samplePos; | ||||||
| 	vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; | 	vec3 start_pos = origin + n * voxelSize0; | ||||||
| 	int clipmap_index0 = 0; | 	int clipmap_index0 = 0; | ||||||
|  |  | ||||||
| 	vec3 aniso_direction = -dir; | 	vec3 aniso_direction = -dir; | ||||||
| @ -259,7 +260,6 @@ float traceAO(const vec3 origin, const vec3 normal, const sampler3D voxels, cons | |||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| #ifdef _VoxelShadow | #ifdef _VoxelShadow | ||||||
| float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 origin, const vec3 n, const vec3 dir, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) { | float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 origin, const vec3 n, const vec3 dir, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) { | ||||||
|     float sampleCol = 0.0; |     float sampleCol = 0.0; | ||||||
| @ -267,7 +267,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v | |||||||
| 	float dist = voxelSize0; | 	float dist = voxelSize0; | ||||||
| 	float step_dist = dist; | 	float step_dist = dist; | ||||||
| 	vec3 samplePos; | 	vec3 samplePos; | ||||||
| 	vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; | 	vec3 start_pos = origin + n * voxelSize0; | ||||||
| 	int clipmap_index0 = 0; | 	int clipmap_index0 = 0; | ||||||
|  |  | ||||||
| 	vec3 aniso_direction = -dir; | 	vec3 aniso_direction = -dir; | ||||||
| @ -287,7 +287,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v | |||||||
| 		float clipmap_blend = fract(lod); | 		float clipmap_blend = fract(lod); | ||||||
| 		vec3 p0 = start_pos + dir * dist; | 		vec3 p0 = start_pos + dir * dist; | ||||||
|  |  | ||||||
|         samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution.x); |         samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution); | ||||||
| 		samplePos = samplePos * 0.5 + 0.5; | 		samplePos = samplePos * 0.5 + 0.5; | ||||||
|  |  | ||||||
| 		if ((any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0))))) { | 		if ((any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0))))) { | ||||||
| @ -328,9 +328,9 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel) { | float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { | ||||||
|  	vec3 P = origin + dir * (BayerMatrix8[int(pixel.x) % 8][int(pixel.y) % 8] - 0.5) * voxelgiStep; |  	vec3 P = origin + dir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; | ||||||
| 	float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps); | 	float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, SHADOW_CONE_APERTURE, voxelgiStep, clipmaps); | ||||||
| 	amount = clamp(amount, 0.0, 1.0); | 	amount = clamp(amount, 0.0, 1.0); | ||||||
| 	return amount * voxelgiOcc; | 	return amount * voxelgiOcc; | ||||||
| } | } | ||||||
|  | |||||||
| @ -21,29 +21,49 @@ THE SOFTWARE. | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| const int DIFFUSE_CONE_COUNT = 16; | const int DIFFUSE_CONE_COUNT = 16; | ||||||
| const float DIFFUSE_CONE_APERTURE = radians(45.0); |  | ||||||
| 
 | 
 | ||||||
| const vec3 DIFFUSE_CONE_DIRECTIONS[16] = { | const float SHADOW_CONE_APERTURE = radians(15.0); | ||||||
| 	vec3(0.0000, 0.0000, 1.0000),   // Central direction |  | ||||||
| 	vec3(0.3827, 0.0000, 0.9239),   // Ring 1 |  | ||||||
| 	vec3(-0.3827, 0.0000, 0.9239), |  | ||||||
| 	vec3(0.0000, 0.3827, 0.9239), |  | ||||||
| 	vec3(0.0000, -0.3827, 0.9239), |  | ||||||
| 	vec3(0.2706, 0.2706, 0.9239),   // Ring 2 |  | ||||||
| 	vec3(-0.2706, 0.2706, 0.9239), |  | ||||||
| 	vec3(0.2706, -0.2706, 0.9239), |  | ||||||
| 	vec3(-0.2706, -0.2706, 0.9239), |  | ||||||
| 	vec3(0.1802, 0.3604, 0.9239),   // Ring 3 |  | ||||||
| 	vec3(-0.1802, 0.3604, 0.9239), |  | ||||||
| 	vec3(0.1802, -0.3604, 0.9239), |  | ||||||
| 	vec3(-0.1802, -0.3604, 0.9239), |  | ||||||
| 	vec3(0.3604, 0.1802, 0.9239), |  | ||||||
| 	vec3(-0.3604, 0.1802, 0.9239), |  | ||||||
| 	vec3(0.3604, -0.1802, 0.9239) |  | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
|  | const float DIFFUSE_CONE_APERTURE = 0.872665; // 50 degrees in radians | ||||||
| 
 | 
 | ||||||
| const float BayerMatrix8[8][8] = | mat3 makeTangentBasis(const vec3 normal) { | ||||||
|  |     // Create a tangent basis from normal vector | ||||||
|  |     vec3 tangent; | ||||||
|  |     vec3 bitangent; | ||||||
|  | 
 | ||||||
|  |     // Compute tangent (Frisvad's method) | ||||||
|  |     if (abs(normal.z) < 0.999) { | ||||||
|  |         tangent = normalize(cross(vec3(0, 1, 0), normal)); | ||||||
|  |     } else { | ||||||
|  |         tangent = normalize(cross(normal, vec3(1, 0, 0))); | ||||||
|  |     } | ||||||
|  |     bitangent = cross(normal, tangent); | ||||||
|  | 
 | ||||||
|  |     return mat3(tangent, bitangent, normal); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // 16 optimized cone directions for hemisphere sampling (Z-up, normalized) | ||||||
|  | const vec3 DIFFUSE_CONE_DIRECTIONS[16] = vec3[]( | ||||||
|  |     vec3(0.707107, 0.000000, 0.707107),  // Front | ||||||
|  |     vec3(-0.707107, 0.000000, 0.707107), // Back | ||||||
|  |     vec3(0.000000, 0.707107, 0.707107),  // Right | ||||||
|  |     vec3(0.000000, -0.707107, 0.707107), // Left | ||||||
|  |     vec3(0.500000, 0.500000, 0.707107),  // Front-right | ||||||
|  |     vec3(-0.500000, 0.500000, 0.707107), // Back-right | ||||||
|  |     vec3(0.500000, -0.500000, 0.707107), // Front-left | ||||||
|  |     vec3(-0.500000, -0.500000, 0.707107),// Back-left | ||||||
|  |     vec3(0.353553, 0.000000, 0.935414),  // Narrow front | ||||||
|  |     vec3(-0.353553, 0.000000, 0.935414), // Narrow back | ||||||
|  |     vec3(0.000000, 0.353553, 0.935414),  // Narrow right | ||||||
|  |     vec3(0.000000, -0.353553, 0.935414), // Narrow left | ||||||
|  |     vec3(0.270598, 0.270598, 0.923880),  // Narrow front-right | ||||||
|  |     vec3(-0.270598, 0.270598, 0.923880), // Narrow back-right | ||||||
|  |     vec3(0.270598, -0.270598, 0.923880), // Narrow front-left | ||||||
|  |     vec3(-0.270598, -0.270598, 0.923880) // Narrow back-left | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | // TO DO - Disabled momentarily instead of changing formulas | ||||||
|  | const float off_BayerMatrix8[8][8] = | ||||||
| { | { | ||||||
| 	{ 1.0 / 65.0, 49.0 / 65.0, 13.0 / 65.0, 61.0 / 65.0, 4.0 / 65.0, 52.0 / 65.0, 16.0 / 65.0, 64.0 / 65.0 }, | 	{ 1.0 / 65.0, 49.0 / 65.0, 13.0 / 65.0, 61.0 / 65.0, 4.0 / 65.0, 52.0 / 65.0, 16.0 / 65.0, 64.0 / 65.0 }, | ||||||
| 	{ 33.0 / 65.0, 17.0 / 65.0, 45.0 / 65.0, 29.0 / 65.0, 36.0 / 65.0, 20.0 / 65.0, 48.0 / 65.0, 32.0 / 65.0 }, | 	{ 33.0 / 65.0, 17.0 / 65.0, 45.0 / 65.0, 29.0 / 65.0, 36.0 / 65.0, 20.0 / 65.0, 48.0 / 65.0, 32.0 / 65.0 }, | ||||||
| @ -54,3 +74,15 @@ const float BayerMatrix8[8][8] = | |||||||
| 	{ 11.0 / 65.0, 59.0 / 65.0, 7.0 / 65.0, 55.0 / 65.0, 10.0 / 65.0, 58.0 / 65.0, 6.0 / 65.0, 54.0 / 65.0 }, | 	{ 11.0 / 65.0, 59.0 / 65.0, 7.0 / 65.0, 55.0 / 65.0, 10.0 / 65.0, 58.0 / 65.0, 6.0 / 65.0, 54.0 / 65.0 }, | ||||||
| 	{ 43.0 / 65.0, 27.0 / 65.0, 39.0 / 65.0, 23.0 / 65.0, 42.0 / 65.0, 26.0 / 65.0, 38.0 / 65.0, 22.0 / 65.0 } | 	{ 43.0 / 65.0, 27.0 / 65.0, 39.0 / 65.0, 23.0 / 65.0, 42.0 / 65.0, 26.0 / 65.0, 38.0 / 65.0, 22.0 / 65.0 } | ||||||
| }; | }; | ||||||
|  | const float BayerMatrix8[8][8] = | ||||||
|  | { | ||||||
|  | 	{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, | ||||||
|  | 	{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, | ||||||
|  | 	{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, | ||||||
|  | 	{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, | ||||||
|  | 	{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, | ||||||
|  | 	{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, | ||||||
|  | 	{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, | ||||||
|  | 	{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| @ -9,7 +9,6 @@ | |||||||
| #endif | #endif | ||||||
| #ifdef _VoxelShadow | #ifdef _VoxelShadow | ||||||
| #include "std/conetrace.glsl" | #include "std/conetrace.glsl" | ||||||
| //!uniform sampler2D voxels_shadows; |  | ||||||
| #endif | #endif | ||||||
| #ifdef _LTC | #ifdef _LTC | ||||||
| #include "std/ltc.glsl" | #include "std/ltc.glsl" | ||||||
| @ -23,46 +22,63 @@ | |||||||
| #ifdef _Spot | #ifdef _Spot | ||||||
| #include "std/light_common.glsl" | #include "std/light_common.glsl" | ||||||
| #endif | #endif | ||||||
|  | #ifdef _VoxelShadow | ||||||
|  | #include "std/conetrace.glsl" | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #ifdef _ShadowMap | #ifdef _ShadowMap | ||||||
| 	#ifdef _SinglePoint | 	#ifdef _SinglePoint | ||||||
| 		#ifdef _Spot | 		#ifdef _Spot | ||||||
| 			#ifndef _LTC | 			#ifndef _LTC | ||||||
| 				uniform sampler2DShadow shadowMapSpot[1]; | 				uniform sampler2DShadow shadowMapSpot[1]; | ||||||
|  | 				#ifdef _ShadowMapTransparent | ||||||
| 				uniform sampler2D shadowMapSpotTransparent[1]; | 				uniform sampler2D shadowMapSpotTransparent[1]; | ||||||
| 				uniform mat4 LWVPSpot[1]; | 				#endif | ||||||
|  | 				uniform mat4 LWVPSpotArray[1]; | ||||||
| 			#endif | 			#endif | ||||||
| 		#else | 		#else | ||||||
| 			uniform samplerCubeShadow shadowMapPoint[1]; | 			uniform samplerCubeShadow shadowMapPoint[1]; | ||||||
|  | 			#ifdef _ShadowMapTransparent | ||||||
| 			uniform samplerCube shadowMapPointTransparent[1]; | 			uniform samplerCube shadowMapPointTransparent[1]; | ||||||
|  | 			#endif | ||||||
| 			uniform vec2 lightProj; | 			uniform vec2 lightProj; | ||||||
| 		#endif | 		#endif | ||||||
| 	#endif | 	#endif | ||||||
| 	#ifdef _Clusters | 	#ifdef _Clusters | ||||||
| 		#ifdef _SingleAtlas | 		#ifdef _SingleAtlas | ||||||
| 		//!uniform sampler2DShadow shadowMapAtlas; | 		//!uniform sampler2DShadow shadowMapAtlas; | ||||||
|  | 		#ifdef _ShadowMapTransparent | ||||||
| 		//!uniform sampler2D shadowMapAtlasTransparent; | 		//!uniform sampler2D shadowMapAtlasTransparent; | ||||||
| 		#endif | 		#endif | ||||||
|  | 		#endif | ||||||
| 		uniform vec2 lightProj; | 		uniform vec2 lightProj; | ||||||
| 		#ifdef _ShadowMapAtlas | 		#ifdef _ShadowMapAtlas | ||||||
| 		#ifndef _SingleAtlas | 		#ifndef _SingleAtlas | ||||||
| 		uniform sampler2DShadow shadowMapAtlasPoint; | 		uniform sampler2DShadow shadowMapAtlasPoint; | ||||||
|  | 		#ifdef _ShadowMapTransparent | ||||||
| 		uniform sampler2D shadowMapAtlasPointTransparent; | 		uniform sampler2D shadowMapAtlasPointTransparent; | ||||||
| 		#endif | 		#endif | ||||||
|  | 		#endif | ||||||
| 		#else | 		#else | ||||||
| 		uniform samplerCubeShadow shadowMapPoint[4]; | 		uniform samplerCubeShadow shadowMapPoint[4]; | ||||||
|  | 		#ifdef _ShadowMapTransparent | ||||||
| 		uniform samplerCube shadowMapPointTransparent[4]; | 		uniform samplerCube shadowMapPointTransparent[4]; | ||||||
| 		#endif | 		#endif | ||||||
|  | 		#endif | ||||||
| 		#ifdef _Spot | 		#ifdef _Spot | ||||||
| 			#ifdef _ShadowMapAtlas | 			#ifdef _ShadowMapAtlas | ||||||
| 			#ifndef _SingleAtlas | 			#ifndef _SingleAtlas | ||||||
| 			uniform sampler2DShadow shadowMapAtlasSpot; | 			uniform sampler2DShadow shadowMapAtlasSpot; | ||||||
|  | 			#ifdef _ShadowMapTransparent | ||||||
| 			uniform sampler2D shadowMapAtlasSpotTransparent; | 			uniform sampler2D shadowMapAtlasSpotTransparent; | ||||||
| 			#endif | 			#endif | ||||||
|  | 			#endif | ||||||
| 			#else | 			#else | ||||||
| 			uniform sampler2DShadow shadowMapSpot[4]; | 			uniform sampler2DShadow shadowMapSpot[4]; | ||||||
|  | 			#ifdef _ShadowMapTransparent | ||||||
| 			uniform sampler2D shadowMapSpotTransparent[4]; | 			uniform sampler2D shadowMapSpotTransparent[4]; | ||||||
| 			#endif | 			#endif | ||||||
|  | 			#endif | ||||||
| 			uniform mat4 LWVPSpotArray[maxLightsCluster]; | 			uniform mat4 LWVPSpotArray[maxLightsCluster]; | ||||||
| 		#endif | 		#endif | ||||||
| 	#endif | 	#endif | ||||||
| @ -79,28 +95,35 @@ uniform sampler2D sltcMag; | |||||||
| #ifndef _Spot | #ifndef _Spot | ||||||
| 	#ifdef _SinglePoint | 	#ifdef _SinglePoint | ||||||
| 		uniform sampler2DShadow shadowMapSpot[1]; | 		uniform sampler2DShadow shadowMapSpot[1]; | ||||||
|  | 		#ifdef _ShadowMapTransparent | ||||||
| 		uniform sampler2D shadowMapSpotTransparent[1]; | 		uniform sampler2D shadowMapSpotTransparent[1]; | ||||||
| 		uniform mat4 LWVPSpot[1]; | 		#endif | ||||||
|  | 		uniform mat4 LWVPSpotArray[1]; | ||||||
| 	#endif | 	#endif | ||||||
| 	#ifdef _Clusters | 	#ifdef _Clusters | ||||||
| 		uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; | 		uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; | ||||||
|  | 		#ifdef _ShadowMapTransparent | ||||||
| 		uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; | 		uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; | ||||||
|  | 		#endif | ||||||
| 		uniform mat4 LWVPSpotArray[maxLightsCluster]; | 		uniform mat4 LWVPSpotArray[maxLightsCluster]; | ||||||
| 	#endif | 	#endif | ||||||
| 	#endif | #endif | ||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, | vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, | ||||||
| 	const vec3 albedo, const float rough, const float spec, const vec3 f0 | 	const vec3 albedo, const float rough, const float spec, const vec3 f0 | ||||||
| 	#ifdef _ShadowMap | 	#ifdef _ShadowMap | ||||||
| 		, int index, float bias, bool receiveShadow, bool transparent | 		, int index, float bias, bool receiveShadow | ||||||
|  | 	#ifdef _ShadowMapTransparent | ||||||
|  | 		, bool transparent | ||||||
|  | 	#endif | ||||||
| 	#endif | 	#endif | ||||||
| 	#ifdef _Spot | 	#ifdef _Spot | ||||||
| 		, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right | 		, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right | ||||||
| 	#endif | 	#endif | ||||||
| 	#ifdef _VoxelShadow | 	#ifdef _VoxelShadow | ||||||
| 		, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount] | 		, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount], vec2 velocity | ||||||
| 	#endif | 	#endif | ||||||
| 	#ifdef _MicroShadowing | 	#ifdef _MicroShadowing | ||||||
| 		, float occ | 		, float occ | ||||||
| @ -146,22 +169,67 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co | |||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	#ifdef _VoxelShadow | 	#ifdef _VoxelShadow | ||||||
| 	direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad; | 	vec3 lightDir = l; | ||||||
|  | 	#ifdef _Spot | ||||||
|  | 	if (isSpot) | ||||||
|  | 		lightDir = spotDir; | ||||||
|  | 	#endif | ||||||
|  | 	direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, lightDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad; | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	#ifdef _LTC | 	#ifdef _LTC | ||||||
| 	#ifdef _ShadowMap | 	#ifdef _ShadowMap | ||||||
| 		if (receiveShadow) { | 		if (receiveShadow) { | ||||||
| 			#ifdef _SinglePoint | 			#ifdef _SinglePoint | ||||||
| 			vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); | 			vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); | ||||||
| 			direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); | 			direct *= shadowTest(shadowMapSpot[0], | ||||||
|  | 								#ifdef _ShadowMapTransparent | ||||||
|  | 								shadowMapSpotTransparent[0], | ||||||
|  | 								#endif | ||||||
|  | 								lPos.xyz / lPos.w, bias | ||||||
|  | 								#ifdef _ShadowMapTransparent | ||||||
|  | 								, transparent | ||||||
|  | 								#endif | ||||||
|  | 								); | ||||||
| 			#endif | 			#endif | ||||||
| 			#ifdef _Clusters | 			#ifdef _Clusters | ||||||
| 			vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); | 			vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0); | ||||||
| 			if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); | 			if (index == 0) direct *= shadowTest(shadowMapSpot[0], | ||||||
| 			else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); | 												#ifdef _ShadowMapTransparent | ||||||
| 			else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); | 												shadowMapSpotTransparent[0], | ||||||
| 			else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); | 												#endif | ||||||
|  | 												lPos.xyz / lPos.w, bias | ||||||
|  | 												#ifdef _ShadowMapTransparent | ||||||
|  | 												, transparent | ||||||
|  | 												#endif | ||||||
|  | 												); | ||||||
|  | 			else if (index == 1) direct *= shadowTest(shadowMapSpot[1], | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													shadowMapSpotTransparent[1], | ||||||
|  | 													#endif | ||||||
|  | 													lPos.xyz / lPos.w, bias | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
|  | 			else if (index == 2) direct *= shadowTest(shadowMapSpot[2], | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													shadowMapSpotTransparent[2], | ||||||
|  | 													#endif | ||||||
|  | 													lPos.xyz / lPos.w, bias | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
|  | 			else if (index == 3) direct *= shadowTest(shadowMapSpot[3], | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													shadowMapSpotTransparent[3], | ||||||
|  | 													#endif | ||||||
|  | 													lPos.xyz / lPos.w, bias | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
| 			#endif | 			#endif | ||||||
| 		} | 		} | ||||||
| 	#endif | 	#endif | ||||||
| @ -175,25 +243,76 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co | |||||||
| 		#ifdef _ShadowMap | 		#ifdef _ShadowMap | ||||||
| 			if (receiveShadow) { | 			if (receiveShadow) { | ||||||
| 				#ifdef _SinglePoint | 				#ifdef _SinglePoint | ||||||
| 				vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); | 				vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); | ||||||
| 				direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); | 				direct *= shadowTest(shadowMapSpot[0], | ||||||
|  | 									#ifdef _ShadowMapTransparent | ||||||
|  | 									shadowMapSpotTransparent[0], | ||||||
|  | 									#endif | ||||||
|  | 									lPos.xyz / lPos.w, bias | ||||||
|  | 									#ifdef _ShadowMapTransparent | ||||||
|  | 									, transparent | ||||||
|  | 									#endif | ||||||
|  | 									); | ||||||
| 				#endif | 				#endif | ||||||
| 				#ifdef _Clusters | 				#ifdef _Clusters | ||||||
| 					vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); | 					vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); | ||||||
| 					#ifdef _ShadowMapAtlas | 					#ifdef _ShadowMapAtlas | ||||||
| 						direct *= shadowTest( | 						direct *= shadowTest( | ||||||
| 							#ifndef _SingleAtlas | 											#ifdef _ShadowMapTransparent | ||||||
| 							shadowMapAtlasSpot, shadowMapAtlasSpotTransparent | 											#ifndef _SingleAtlas | ||||||
| 							#else | 											shadowMapAtlasSpot, shadowMapAtlasSpotTransparent | ||||||
| 							shadowMapAtlas, shadowMapAtlasTransparent | 											#else | ||||||
| 							#endif | 											shadowMapAtlas, shadowMapAtlasTransparent | ||||||
| 							, lPos.xyz / lPos.w, bias, transparent | 											#endif | ||||||
| 						); | 											#else | ||||||
|  | 											#ifndef _SingleAtlas | ||||||
|  | 											shadowMapAtlasSpot | ||||||
|  | 											#else | ||||||
|  | 											shadowMapAtlas | ||||||
|  | 											#endif | ||||||
|  | 											#endif | ||||||
|  | 											, lPos.xyz / lPos.w, bias | ||||||
|  | 											#ifdef _ShadowMapTransparent | ||||||
|  | 											, transparent | ||||||
|  | 											#endif | ||||||
|  | 											); | ||||||
| 					#else | 					#else | ||||||
| 							 if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); | 							 if (index == 0) direct *= shadowTest(shadowMapSpot[0], | ||||||
| 						else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); | 																#ifdef _ShadowMapTransparent | ||||||
| 						else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); | 																shadowMapSpotTransparent[0], | ||||||
| 						else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); | 																#endif | ||||||
|  | 																lPos.xyz / lPos.w, bias | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																, transparent | ||||||
|  | 																#endif | ||||||
|  | 																); | ||||||
|  | 						else if (index == 1) direct *= shadowTest(shadowMapSpot[1], | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																shadowMapSpotTransparent[1], | ||||||
|  | 																#endif | ||||||
|  | 																lPos.xyz / lPos.w, bias | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																, transparent | ||||||
|  | 																#endif | ||||||
|  | 																); | ||||||
|  | 						else if (index == 2) direct *= shadowTest(shadowMapSpot[2], | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																shadowMapSpotTransparent[2], | ||||||
|  | 																#endif | ||||||
|  | 																lPos.xyz / lPos.w, bias | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																, transparent | ||||||
|  | 																#endif | ||||||
|  | 																); | ||||||
|  | 						else if (index == 3) direct *= shadowTest(shadowMapSpot[3], | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																shadowMapSpotTransparent[3], | ||||||
|  | 																#endif | ||||||
|  | 																lPos.xyz / lPos.w, bias | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																, transparent | ||||||
|  | 																#endif | ||||||
|  | 																); | ||||||
| 					#endif | 					#endif | ||||||
| 				#endif | 				#endif | ||||||
| 			} | 			} | ||||||
| @ -210,24 +329,75 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co | |||||||
| 		if (receiveShadow) { | 		if (receiveShadow) { | ||||||
| 			#ifdef _SinglePoint | 			#ifdef _SinglePoint | ||||||
| 			#ifndef _Spot | 			#ifndef _Spot | ||||||
| 			direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); | 			direct *= PCFCube(shadowMapPoint[0], | ||||||
|  | 							#ifdef _ShadowMapTransparent | ||||||
|  | 							shadowMapPointTransparent[0], | ||||||
|  | 							#endif | ||||||
|  | 							ld, -l, bias, lightProj, n | ||||||
|  | 							#ifdef _ShadowMapTransparent | ||||||
|  | 							, transparent | ||||||
|  | 							#endif | ||||||
|  | 							); | ||||||
| 			#endif | 			#endif | ||||||
| 			#endif | 			#endif | ||||||
| 			#ifdef _Clusters | 			#ifdef _Clusters | ||||||
| 				#ifdef _ShadowMapAtlas | 				#ifdef _ShadowMapAtlas | ||||||
| 				direct *= PCFFakeCube( | 				direct *= PCFFakeCube( | ||||||
| 					#ifndef _SingleAtlas | 									#ifdef _ShadowMapTransparent | ||||||
| 					shadowMapAtlasPoint, shadowMapAtlasPointTransparent | 									#ifndef _SingleAtlas | ||||||
| 					#else | 									shadowMapAtlasPoint, shadowMapAtlasPointTransparent | ||||||
| 					shadowMapAtlas, shadowMapAtlasTransparent | 									#else | ||||||
| 					#endif | 									shadowMapAtlas, shadowMapAtlasTransparent | ||||||
| 					, ld, -l, bias, lightProj, n, index, transparent | 									#endif | ||||||
| 				); | 									#else | ||||||
|  | 									#ifndef _SingleAtlas | ||||||
|  | 									shadowMapAtlasPoint | ||||||
|  | 									#else | ||||||
|  | 									shadowMapAtlas | ||||||
|  | 									#endif | ||||||
|  | 									#endif | ||||||
|  | 									, ld, -l, bias, lightProj, n, index | ||||||
|  | 									#ifdef _ShadowMapTransparent | ||||||
|  | 									, transparent | ||||||
|  | 									#endif | ||||||
|  | 									); | ||||||
| 				#else | 				#else | ||||||
| 					 if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); | 					 if (index == 0) direct *= PCFCube(shadowMapPoint[0], | ||||||
| 				else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent); | 													#ifdef _ShadowMapTransparent | ||||||
| 				else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent); | 													shadowMapPointTransparent[0], | ||||||
| 				else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent); | 													#endif | ||||||
|  | 													ld, -l, bias, lightProj, n | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
|  | 				else if (index == 1) direct *= PCFCube(shadowMapPoint[1], | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													shadowMapPointTransparent[1], | ||||||
|  | 													#endif | ||||||
|  | 													ld, -l, bias, lightProj, n | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
|  | 				else if (index == 2) direct *= PCFCube(shadowMapPoint[2], | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													shadowMapPointTransparent[2], | ||||||
|  | 													#endif | ||||||
|  | 													ld, -l, bias, lightProj, n | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
|  | 				else if (index == 3) direct *= PCFCube(shadowMapPoint[3], | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													shadowMapPointTransparent[3], | ||||||
|  | 													#endif | ||||||
|  | 													ld, -l, bias, lightProj, n | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
| 				#endif | 				#endif | ||||||
| 			#endif | 			#endif | ||||||
| 		} | 		} | ||||||
| @ -236,4 +406,274 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co | |||||||
| 	return direct; | 	return direct; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifdef _VoxelGI | ||||||
|  | vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, | ||||||
|  | 	const vec3 albedo, const float rough, const float spec, const vec3 f0 | ||||||
|  | 	#ifdef _ShadowMap | ||||||
|  | 		, int index, float bias, bool receiveShadow | ||||||
|  | 	#ifdef _ShadowMapTransparent | ||||||
|  | 		, bool transparent | ||||||
|  | 	#endif | ||||||
|  | 	#endif | ||||||
|  | 	#ifdef _Spot | ||||||
|  | 		, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right | ||||||
|  | 	#endif | ||||||
|  | 	) { | ||||||
|  | 	vec3 ld = lp - p; | ||||||
|  | 	vec3 l = normalize(ld); | ||||||
|  | 	vec3 h = normalize(v + l); | ||||||
|  | 	float dotNH = max(0.0, dot(n, h)); | ||||||
|  | 	float dotVH = max(0.0, dot(v, h)); | ||||||
|  | 	float dotNL = max(0.0, dot(n, l)); | ||||||
|  |  | ||||||
|  | 	#ifdef _LTC | ||||||
|  | 	float theta = acos(dotNV); | ||||||
|  | 	vec2 tuv = vec2(rough, theta / (0.5 * PI)); | ||||||
|  | 	tuv = tuv * LUT_SCALE + LUT_BIAS; | ||||||
|  | 	vec4 t = textureLod(sltcMat, tuv, 0.0); | ||||||
|  | 	mat3 invM = mat3( | ||||||
|  | 		vec3(1.0, 0.0, t.y), | ||||||
|  | 		vec3(0.0, t.z, 0.0), | ||||||
|  | 		vec3(t.w, 0.0, t.x)); | ||||||
|  | 	float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3); | ||||||
|  | 	ltcspec *= textureLod(sltcMag, tuv, 0.0).a; | ||||||
|  | 	float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3); | ||||||
|  | 	vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05; | ||||||
|  | 	#else | ||||||
|  | 	vec3 direct = lambertDiffuseBRDF(albedo, dotNL) + | ||||||
|  | 				  specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec; | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
|  | 	direct *= attenuate(distance(p, lp)); | ||||||
|  | 	direct *= lightCol; | ||||||
|  |  | ||||||
|  | 	#ifdef _LTC | ||||||
|  | 	#ifdef _ShadowMap | ||||||
|  | 		if (receiveShadow) { | ||||||
|  | 			#ifdef _SinglePoint | ||||||
|  | 			vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); | ||||||
|  | 			direct *= shadowTest(shadowMapSpot[0], | ||||||
|  | 								#ifdef _ShadowMapTransparent | ||||||
|  | 								shadowMapSpotTransparent[0], | ||||||
|  | 								#endif | ||||||
|  | 								lPos.xyz / lPos.w, bias | ||||||
|  | 								#ifdef _ShadowMapTransparent | ||||||
|  | 								, transparent | ||||||
|  | 								#endif | ||||||
|  | 								); | ||||||
|  | 			#endif | ||||||
|  | 			#ifdef _Clusters | ||||||
|  | 			vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0); | ||||||
|  | 			if (index == 0) direct *= shadowTest(shadowMapSpot[0], | ||||||
|  | 												#ifdef _ShadowMapTransparent | ||||||
|  | 												shadowMapSpotTransparent[0], | ||||||
|  | 												#endif | ||||||
|  | 												lPos.xyz / lPos.w, bias | ||||||
|  | 												#ifdef _ShadowMapTransparent | ||||||
|  | 												, transparent | ||||||
|  | 												#endif | ||||||
|  | 												); | ||||||
|  | 			else if (index == 1) direct *= shadowTest(shadowMapSpot[1], | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													shadowMapSpotTransparent[1], | ||||||
|  | 													#endif | ||||||
|  | 													lPos.xyz / lPos.w, bias | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
|  | 			else if (index == 2) direct *= shadowTest(shadowMapSpot[2], | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													shadowMapSpotTransparent[2], | ||||||
|  | 													#endif | ||||||
|  | 													lPos.xyz / lPos.w, bias | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
|  | 			else if (index == 3) direct *= shadowTest(shadowMapSpot[3], | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													shadowMapSpotTransparent[3], | ||||||
|  | 													#endif | ||||||
|  | 													lPos.xyz / lPos.w, bias | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
|  | 			#endif | ||||||
|  | 		} | ||||||
|  | 	#endif | ||||||
|  | 	return direct; | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
|  | 	#ifdef _Spot | ||||||
|  | 	if (isSpot) { | ||||||
|  | 		direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend); | ||||||
|  |  | ||||||
|  | 		#ifdef _ShadowMap | ||||||
|  | 			if (receiveShadow) { | ||||||
|  | 				#ifdef _SinglePoint | ||||||
|  | 				vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); | ||||||
|  | 				direct *= shadowTest(shadowMapSpot[0], | ||||||
|  | 									#ifdef _ShadowMapTransparent | ||||||
|  | 									shadowMapSpotTransparent[0], | ||||||
|  | 									#endif | ||||||
|  | 									lPos.xyz / lPos.w, bias | ||||||
|  | 									#ifdef _ShadowMapTransparent | ||||||
|  | 									, transparent | ||||||
|  | 									#endif | ||||||
|  | 									); | ||||||
|  | 				#endif | ||||||
|  | 				#ifdef _Clusters | ||||||
|  | 					vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); | ||||||
|  | 					#ifdef _ShadowMapAtlas | ||||||
|  | 						direct *= shadowTest( | ||||||
|  | 											#ifdef _ShadowMapTransparent | ||||||
|  | 											#ifndef _SingleAtlas | ||||||
|  | 											shadowMapAtlasSpot, shadowMapAtlasSpotTransparent | ||||||
|  | 											#else | ||||||
|  | 											shadowMapAtlas, shadowMapAtlasTransparent | ||||||
|  | 											#endif | ||||||
|  | 											#else | ||||||
|  | 											#ifndef _SingleAtlas | ||||||
|  | 											shadowMapAtlasSpot | ||||||
|  | 											#else | ||||||
|  | 											shadowMapAtlas | ||||||
|  | 											#endif | ||||||
|  | 											#endif | ||||||
|  | 											, lPos.xyz / lPos.w, bias | ||||||
|  | 											#ifdef _ShadowMapTransparent | ||||||
|  | 											, transparent | ||||||
|  | 											#endif | ||||||
|  | 											); | ||||||
|  | 					#else | ||||||
|  | 							 if (index == 0) direct *= shadowTest(shadowMapSpot[0], | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																shadowMapSpotTransparent[0], | ||||||
|  | 																#endif | ||||||
|  | 																lPos.xyz / lPos.w, bias | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																, transparent | ||||||
|  | 																#endif | ||||||
|  | 																); | ||||||
|  | 						else if (index == 1) direct *= shadowTest(shadowMapSpot[1], | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																shadowMapSpotTransparent[1], | ||||||
|  | 																#endif | ||||||
|  | 																lPos.xyz / lPos.w, bias | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																, transparent | ||||||
|  | 																#endif | ||||||
|  | 																); | ||||||
|  | 						else if (index == 2) direct *= shadowTest(shadowMapSpot[2], | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																shadowMapSpotTransparent[2], | ||||||
|  | 																#endif | ||||||
|  | 																lPos.xyz / lPos.w, bias | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																, transparent | ||||||
|  | 																#endif | ||||||
|  | 																); | ||||||
|  | 						else if (index == 3) direct *= shadowTest(shadowMapSpot[3], | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																shadowMapSpotTransparent[3], | ||||||
|  | 																#endif | ||||||
|  | 																lPos.xyz / lPos.w, bias | ||||||
|  | 																#ifdef _ShadowMapTransparent | ||||||
|  | 																, transparent | ||||||
|  | 																#endif | ||||||
|  | 																); | ||||||
|  | 					#endif | ||||||
|  | 				#endif | ||||||
|  | 			} | ||||||
|  | 		#endif | ||||||
|  | 		return direct; | ||||||
|  | 	} | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
|  | 	#ifdef _LightIES | ||||||
|  | 	direct *= iesAttenuation(-l); | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
|  | 	#ifdef _ShadowMap | ||||||
|  | 		if (receiveShadow) { | ||||||
|  | 			#ifdef _SinglePoint | ||||||
|  | 			#ifndef _Spot | ||||||
|  | 			direct *= PCFCube(shadowMapPoint[0], | ||||||
|  | 							#ifdef _ShadowMapTransparent | ||||||
|  | 							shadowMapPointTransparent[0], | ||||||
|  | 							#endif | ||||||
|  | 							ld, -l, bias, lightProj, n | ||||||
|  | 							#ifdef _ShadowMapTransparent | ||||||
|  | 							, transparent | ||||||
|  | 							#endif | ||||||
|  | 							); | ||||||
|  | 			#endif | ||||||
|  | 			#endif | ||||||
|  | 			#ifdef _Clusters | ||||||
|  | 				#ifdef _ShadowMapAtlas | ||||||
|  | 				direct *= PCFFakeCube( | ||||||
|  | 									#ifdef _ShadowMapTransparent | ||||||
|  | 									#ifndef _SingleAtlas | ||||||
|  | 									shadowMapAtlasPoint, shadowMapAtlasPointTransparent | ||||||
|  | 									#else | ||||||
|  | 									shadowMapAtlas, shadowMapAtlasTransparent | ||||||
|  | 									#endif | ||||||
|  | 									#else | ||||||
|  | 									#ifndef _SingleAtlas | ||||||
|  | 									shadowMapAtlasPoint | ||||||
|  | 									#else | ||||||
|  | 									shadowMapAtlas | ||||||
|  | 									#endif | ||||||
|  | 									#endif | ||||||
|  | 									, ld, -l, bias, lightProj, n, index | ||||||
|  | 									#ifdef _ShadowMapTransparent | ||||||
|  | 									, transparent | ||||||
|  | 									#endif | ||||||
|  | 									); | ||||||
|  | 				#else | ||||||
|  | 					 if (index == 0) direct *= PCFCube(shadowMapPoint[0], | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													shadowMapPointTransparent[0], | ||||||
|  | 													#endif | ||||||
|  | 													ld, -l, bias, lightProj, n | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
|  | 				else if (index == 1) direct *= PCFCube(shadowMapPoint[1], | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													shadowMapPointTransparent[1], | ||||||
|  | 													#endif | ||||||
|  | 													ld, -l, bias, lightProj, n | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
|  | 				else if (index == 2) direct *= PCFCube(shadowMapPoint[2], | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													shadowMapPointTransparent[2], | ||||||
|  | 													#endif | ||||||
|  | 													ld, -l, bias, lightProj, n | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
|  | 				else if (index == 3) direct *= PCFCube(shadowMapPoint[3], | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													shadowMapPointTransparent[3], | ||||||
|  | 													#endif | ||||||
|  | 													ld, -l, bias, lightProj, n | ||||||
|  | 													#ifdef _ShadowMapTransparent | ||||||
|  | 													, transparent | ||||||
|  | 													#endif | ||||||
|  | 													); | ||||||
|  | 				#endif | ||||||
|  | 			#endif | ||||||
|  | 		} | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
|  | 	return direct; | ||||||
|  | } | ||||||
|  | #endif | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -58,7 +58,15 @@ vec2 sampleCube(vec3 dir, out int faceIndex) { | |||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| vec3 PCF(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec2 uv, const float compare, const vec2 smSize, const bool transparent) { | vec3 PCF(sampler2DShadow shadowMap, | ||||||
|  | 		#ifdef _ShadowMapTransparent | ||||||
|  | 		sampler2D shadowMapTransparent, | ||||||
|  | 		#endif | ||||||
|  | 		const vec2 uv, const float compare, const vec2 smSize | ||||||
|  | 		#ifdef _ShadowMapTransparent | ||||||
|  | 		, const bool transparent | ||||||
|  | 		#endif | ||||||
|  | 		) { | ||||||
| 	vec3 result = vec3(0.0); | 	vec3 result = vec3(0.0); | ||||||
| 	result.x = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare)); | 	result.x = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare)); | ||||||
| 	result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare)); | 	result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare)); | ||||||
| @ -71,11 +79,13 @@ vec3 PCF(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec2 u | |||||||
| 	result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare)); | 	result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare)); | ||||||
| 	result = result.xxx / 9.0; | 	result = result.xxx / 9.0; | ||||||
|  |  | ||||||
|  | 	#ifdef _ShadowMapTransparent | ||||||
| 	if (transparent == false) { | 	if (transparent == false) { | ||||||
| 		vec4 shadowmap_transparent = texture(shadowMapTransparent, uv); | 		vec4 shadowmap_transparent = texture(shadowMapTransparent, uv); | ||||||
| 		if (shadowmap_transparent.a < compare) | 		if (shadowmap_transparent.a < compare) | ||||||
| 			result *= shadowmap_transparent.rgb; | 			result *= shadowmap_transparent.rgb; | ||||||
| 	} | 	} | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| @ -87,41 +97,15 @@ float lpToDepth(vec3 lp, const vec2 lightProj) { | |||||||
| 	return zcomp * 0.5 + 0.5; | 	return zcomp * 0.5 + 0.5; | ||||||
| } | } | ||||||
|  |  | ||||||
| #ifndef _ShadowMapAtlas | vec3 PCFCube(samplerCubeShadow shadowMapCube, | ||||||
| vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, vec3 lp, vec3 ml, float bias, vec2 lightProj, vec3 n, const bool transparent) { | 			#ifdef _ShadowMapTransparent | ||||||
|     const float s = shadowmapCubePcfSize; | 			samplerCube shadowMapCubeTransparent, | ||||||
|     float compare = lpToDepth(lp, lightProj) - bias * 1.5; | 			#endif | ||||||
|     ml = ml + n * bias * 20; | 			const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n | ||||||
|     #ifdef _InvY | 			#ifdef _ShadowMapTransparent | ||||||
|     ml.y = -ml.y; | 			, const bool transparent | ||||||
|     #endif | 			#endif | ||||||
|      | 			) { | ||||||
|     float shadowFactor = 0.0; |  | ||||||
|     shadowFactor = texture(shadowMapCube, vec4(ml, compare)); |  | ||||||
|     shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, s, s), compare)); |  | ||||||
|     shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, s, s), compare)); |  | ||||||
|     shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, -s, s), compare)); |  | ||||||
|     shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, s, -s), compare)); |  | ||||||
|     shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, -s, s), compare)); |  | ||||||
|     shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, -s, -s), compare)); |  | ||||||
|     shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, s, -s), compare)); |  | ||||||
|     shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare)); |  | ||||||
|     shadowFactor /= 9.0; |  | ||||||
|      |  | ||||||
|     vec3 result = vec3(shadowFactor); |  | ||||||
|      |  | ||||||
|     if (transparent == false) { |  | ||||||
|         vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml); |  | ||||||
|         if (shadowmap_transparent.a < compare) |  | ||||||
|             result *= shadowmap_transparent.rgb; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef _ShadowMapAtlas |  | ||||||
| vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const bool transparent) { |  | ||||||
| 	const float s = shadowmapCubePcfSize; // TODO: incorrect... | 	const float s = shadowmapCubePcfSize; // TODO: incorrect... | ||||||
| 	float compare = lpToDepth(lp, lightProj) - bias * 1.5; | 	float compare = lpToDepth(lp, lightProj) - bias * 1.5; | ||||||
| 	ml = ml + n * bias * 20; | 	ml = ml + n * bias * 20; | ||||||
| @ -140,16 +124,18 @@ vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTranspare | |||||||
| 	result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare)); | 	result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare)); | ||||||
| 	result = result.xxx / 9.0; | 	result = result.xxx / 9.0; | ||||||
|  |  | ||||||
|  | 	#ifdef _ShadowMapTransparent | ||||||
| 	if (transparent == false) { | 	if (transparent == false) { | ||||||
| 		vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml); | 		vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml); | ||||||
| 		if (shadowmap_transparent.a < compare) | 		if (shadowmap_transparent.a < compare) | ||||||
| 			result *= shadowmap_transparent.rgb; | 			result *= shadowmap_transparent.rgb; | ||||||
| 	} | 	} | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifdef _ShadowMapAtlas | ||||||
| // transform "out-of-bounds" coordinates to the correct face/coordinate system | // transform "out-of-bounds" coordinates to the correct face/coordinate system | ||||||
| // https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png | // https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png | ||||||
| vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) { | vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) { | ||||||
| @ -243,21 +229,31 @@ vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) { | |||||||
| 	return uv; | 	return uv; | ||||||
| } | } | ||||||
|  |  | ||||||
| vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index, const bool transparent) { | vec3 PCFFakeCube(sampler2DShadow shadowMap, | ||||||
|  | 				#ifdef _ShadowMapTransparent | ||||||
|  | 				sampler2D shadowMapTransparent, | ||||||
|  | 				#endif | ||||||
|  | 				const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index | ||||||
|  | 				#ifdef _ShadowMapTransparent | ||||||
|  | 				, const bool transparent | ||||||
|  | 				#endif | ||||||
|  | 				) { | ||||||
| 	const vec2 smSize = smSizeUniform; // TODO: incorrect... | 	const vec2 smSize = smSizeUniform; // TODO: incorrect... | ||||||
| 	const float compare = lpToDepth(lp, lightProj) - bias * 1.5; | 	const float compare = lpToDepth(lp, lightProj) - bias * 1.5; | ||||||
| 	ml = ml + n * bias * 20; | 	ml = ml + n * bias * 20; | ||||||
|  |  | ||||||
| 	int faceIndex = 0; | 	int faceIndex = 0; | ||||||
| 	const int lightIndex = index * 6; | 	const int lightIndex = index * 6; | ||||||
| 	const vec2 uv = sampleCube(ml, faceIndex); | 	const vec2 uv = sampleCube(ml, faceIndex); | ||||||
|  |  | ||||||
| 	vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas | 	vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas | ||||||
| 	vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; | 	vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; | ||||||
| 	#ifdef _FlipY | 	#ifdef _FlipY | ||||||
| 	uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system | 	uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
|  | 	if (any(lessThan(uvtiled, vec2(0.0))) || any(greaterThan(uvtiled, vec2(1.0)))) { | ||||||
|  | 		return vec3(1.0); // Handle edge cases by returning full light | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	vec3 result = vec3(0.0); | 	vec3 result = vec3(0.0); | ||||||
| 	result.x += texture(shadowMap, vec3(uvtiled, compare)); | 	result.x += texture(shadowMap, vec3(uvtiled, compare)); | ||||||
| 	// soft shadowing | 	// soft shadowing | ||||||
| @ -270,14 +266,6 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, cons | |||||||
| 	#endif | 	#endif | ||||||
| 	result.x += texture(shadowMap, vec3(uvtiled, compare)); | 	result.x += texture(shadowMap, vec3(uvtiled, compare)); | ||||||
|  |  | ||||||
| 	uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 1.0) / smSize))); |  | ||||||
| 	pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; |  | ||||||
| 	uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; |  | ||||||
| 	#ifdef _FlipY |  | ||||||
| 	uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system |  | ||||||
| 	#endif |  | ||||||
| 	result.x += texture(shadowMap, vec3(uvtiled, compare)); |  | ||||||
|  |  | ||||||
| 	uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize))); | 	uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize))); | ||||||
| 	pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; | 	pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; | ||||||
| 	uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; | 	uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; | ||||||
| @ -334,30 +322,47 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, cons | |||||||
| 	uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system | 	uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
|  | 	#ifdef _ShadowMapTransparent | ||||||
| 	if (transparent == false) { | 	if (transparent == false) { | ||||||
| 		vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled); | 		vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled); | ||||||
| 		if (shadowmap_transparent.a < compare) | 		if (shadowmap_transparent.a < compare) | ||||||
| 			result *= shadowmap_transparent.rgb; | 			result *= shadowmap_transparent.rgb; | ||||||
| 	} | 	} | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| vec3 shadowTest(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 lPos, const float shadowsBias, const bool transparent) { | vec3 shadowTest(sampler2DShadow shadowMap, | ||||||
|  | 				#ifdef _ShadowMapTransparent | ||||||
|  | 				sampler2D shadowMapTransparent, | ||||||
|  | 				#endif | ||||||
|  | 				const vec3 lPos, const float shadowsBias | ||||||
|  | 				#ifdef _ShadowMapTransparent | ||||||
|  | 				, const bool transparent | ||||||
|  | 				#endif | ||||||
|  | 				) { | ||||||
| 	#ifdef _SMSizeUniform | 	#ifdef _SMSizeUniform | ||||||
| 	vec2 smSize = smSizeUniform; | 	vec2 smSize = smSizeUniform; | ||||||
| 	#else | 	#else | ||||||
| 	const vec2 smSize = shadowmapSize; | 	const vec2 smSize = shadowmapSize; | ||||||
| 	#endif | 	#endif | ||||||
| 	if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return vec3(1.0); | 	if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return vec3(1.0); | ||||||
| 	return PCF(shadowMap, shadowMapTransparent, lPos.xy, lPos.z - shadowsBias, smSize, transparent); | 	return PCF(shadowMap, | ||||||
|  | 				#ifdef _ShadowMapTransparent | ||||||
|  | 				shadowMapTransparent, | ||||||
|  | 				#endif | ||||||
|  | 				lPos.xy, lPos.z - shadowsBias, smSize | ||||||
|  | 				#ifdef _ShadowMapTransparent | ||||||
|  | 				, transparent | ||||||
|  | 				#endif | ||||||
|  | 				); | ||||||
| } | } | ||||||
|  |  | ||||||
| #ifdef _CSM | #ifdef _CSM | ||||||
| mat4 getCascadeMat(const float d, out int casi, out int casIndex) { | mat4 getCascadeMat(const float d, out int casi, out int casIndex) { | ||||||
| 	const int c = shadowmapCascades; | 	const int c = shadowmapCascades; | ||||||
|  |  | ||||||
| 	// Get cascade index | 	// Get cascade index | ||||||
| 	// TODO: use bounding box slice selection instead of sphere | 	// TODO: use bounding box slice selection instead of sphere | ||||||
| 	const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3)); | 	const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3)); | ||||||
| @ -373,21 +378,26 @@ mat4 getCascadeMat(const float d, out int casi, out int casIndex) { | |||||||
| 		float(d > casData[c * 4].z), | 		float(d > casData[c * 4].z), | ||||||
| 		float(d > casData[c * 4].w)); | 		float(d > casData[c * 4].w)); | ||||||
| 	casi = int(min(dot(ci, comp), c)); | 	casi = int(min(dot(ci, comp), c)); | ||||||
|  |  | ||||||
| 	// Get cascade mat | 	// Get cascade mat | ||||||
| 	casIndex = casi * 4; | 	casIndex = casi * 4; | ||||||
|  |  | ||||||
| 	return mat4( | 	return mat4( | ||||||
| 		casData[casIndex    ], | 		casData[casIndex    ], | ||||||
| 		casData[casIndex + 1], | 		casData[casIndex + 1], | ||||||
| 		casData[casIndex + 2], | 		casData[casIndex + 2], | ||||||
| 		casData[casIndex + 3]); | 		casData[casIndex + 3]); | ||||||
|  |  | ||||||
| 	// if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]); | 	// if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]); | ||||||
| 	// .. | 	// .. | ||||||
| } | } | ||||||
|  |  | ||||||
| vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 eye, const vec3 p, const float shadowsBias, const bool transparent) { | vec3 shadowTestCascade(sampler2DShadow shadowMap, | ||||||
|  | 					   #ifdef _ShadowMapTransparent | ||||||
|  | 					   sampler2D shadowMapTransparent, | ||||||
|  | 					   #endif | ||||||
|  | 					   const vec3 eye, const vec3 p, const float shadowsBias | ||||||
|  | 					   #ifdef _ShadowMapTransparent | ||||||
|  | 					   , const bool transparent | ||||||
|  | 					   #endif | ||||||
|  | 					   ) { | ||||||
| 	#ifdef _SMSizeUniform | 	#ifdef _SMSizeUniform | ||||||
| 	vec2 smSize = smSizeUniform; | 	vec2 smSize = smSizeUniform; | ||||||
| 	#else | 	#else | ||||||
| @ -395,16 +405,22 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent | |||||||
| 	#endif | 	#endif | ||||||
| 	const int c = shadowmapCascades; | 	const int c = shadowmapCascades; | ||||||
| 	float d = distance(eye, p); | 	float d = distance(eye, p); | ||||||
|  |  | ||||||
| 	int casi; | 	int casi; | ||||||
| 	int casIndex; | 	int casIndex; | ||||||
| 	mat4 LWVP = getCascadeMat(d, casi, casIndex); | 	mat4 LWVP = getCascadeMat(d, casi, casIndex); | ||||||
|  |  | ||||||
| 	vec4 lPos = LWVP * vec4(p, 1.0); | 	vec4 lPos = LWVP * vec4(p, 1.0); | ||||||
| 	lPos.xyz /= lPos.w; | 	lPos.xyz /= lPos.w; | ||||||
|  |  | ||||||
| 	vec3 visibility = vec3(1.0); | 	vec3 visibility = vec3(1.0); | ||||||
| 	if (lPos.w > 0.0) visibility = PCF(shadowMap, shadowMapTransparent, lPos.xy, lPos.z - shadowsBias, smSize, transparent); | 	if (lPos.w > 0.0) visibility = PCF(shadowMap, | ||||||
|  | 									#ifdef _ShadowMapTransparent | ||||||
|  | 									shadowMapTransparent, | ||||||
|  | 									#endif | ||||||
|  | 									lPos.xy, lPos.z - shadowsBias, smSize | ||||||
|  | 									#ifdef _ShadowMapTransparent | ||||||
|  | 									, transparent | ||||||
|  | 									#endif | ||||||
|  | 									); | ||||||
|  |  | ||||||
| 	// Blend cascade | 	// Blend cascade | ||||||
| 	// https://github.com/TheRealMJP/Shadows | 	// https://github.com/TheRealMJP/Shadows | ||||||
| @ -423,13 +439,20 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent | |||||||
| 		vec4 lPos2 = LWVP2 * vec4(p, 1.0); | 		vec4 lPos2 = LWVP2 * vec4(p, 1.0); | ||||||
| 		lPos2.xyz /= lPos2.w; | 		lPos2.xyz /= lPos2.w; | ||||||
| 		vec3 visibility2 = vec3(1.0); | 		vec3 visibility2 = vec3(1.0); | ||||||
| 		if (lPos2.w > 0.0) visibility2 = PCF(shadowMap, shadowMapTransparent, lPos2.xy, lPos2.z - shadowsBias, smSize, transparent); | 		if (lPos2.w > 0.0) visibility2 = PCF(shadowMap, | ||||||
|  | 											#ifdef _ShadowMapTransparent | ||||||
|  | 											shadowMapTransparent, | ||||||
|  | 											#endif | ||||||
|  | 											lPos.xy, lPos.z - shadowsBias, smSize | ||||||
|  | 											#ifdef _ShadowMapTransparent | ||||||
|  | 											, transparent | ||||||
|  | 											#endif | ||||||
|  | 											); | ||||||
|  |  | ||||||
| 		float lerpAmt = smoothstep(0.0, blendThres, splitDist); | 		float lerpAmt = smoothstep(0.0, blendThres, splitDist); | ||||||
| 		return mix(visibility2, visibility, lerpAmt); | 		return mix(visibility2, visibility, lerpAmt); | ||||||
| 	} | 	} | ||||||
| 	return visibility; | 	return visibility; | ||||||
|  |  | ||||||
| 	// Visualize cascades | 	// Visualize cascades | ||||||
| 	// if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0); | 	// if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0); | ||||||
| 	// if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0); | 	// if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0); | ||||||
|  | |||||||
| @ -33,6 +33,7 @@ uniform layout(r32ui) uimage3D voxelsLight; | |||||||
|  |  | ||||||
| #ifdef _ShadowMap | #ifdef _ShadowMap | ||||||
| uniform sampler2DShadow shadowMap; | uniform sampler2DShadow shadowMap; | ||||||
|  | uniform sampler2D shadowMapTransparent; | ||||||
| uniform sampler2DShadow shadowMapSpot; | uniform sampler2DShadow shadowMapSpot; | ||||||
| #ifdef _ShadowMapAtlas | #ifdef _ShadowMapAtlas | ||||||
| uniform sampler2DShadow shadowMapPoint; | uniform sampler2DShadow shadowMapPoint; | ||||||
| @ -86,30 +87,28 @@ float lpToDepth(vec3 lp, const vec2 lightProj) { | |||||||
|  |  | ||||||
| void main() { | void main() { | ||||||
| 	int res = voxelgiResolution.x; | 	int res = voxelgiResolution.x; | ||||||
|  |  | ||||||
| 	ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); | 	ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); | ||||||
| 	dst.y += clipmapLevel * res; |  | ||||||
|  |  | ||||||
| 	vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution; | 	vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; | ||||||
| 	P = P * 2.0 - 1.0; | 	wposition = wposition * 2.0 - 1.0; | ||||||
| 	P *= clipmaps[int(clipmapLevel * 10)]; | 	wposition *= float(clipmaps[int(clipmapLevel * 10)]); | ||||||
| 	P *= voxelgiResolution; | 	wposition *= voxelgiResolution.x; | ||||||
| 	P += vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)]); | 	wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); | ||||||
|  |  | ||||||
| 	vec3 visibility; | 	float visibility; | ||||||
| 	vec3 lp = lightPos - P; | 	vec3 lp = lightPos -wposition; | ||||||
| 	vec3 l; | 	vec3 l; | ||||||
| 	if (lightType == 0) { l = lightDir; visibility = vec3(1.0); } | 	if (lightType == 0) { l = lightDir; visibility = 1.0; } | ||||||
| 	else { l = normalize(lp); visibility = vec3(attenuate(distance(P, lightPos))); } | 	else { l = normalize(lp); visibility = attenuate(distance(wposition, lightPos)); } | ||||||
|  |  | ||||||
| #ifdef _ShadowMap | #ifdef _ShadowMap | ||||||
| 	if (lightShadow == 1) { | 	if (lightShadow == 1) { | ||||||
| 		vec4 lightPosition = LVP * vec4(P, 1.0); | 		vec4 lightPosition = LVP * vec4(wposition, 1.0); | ||||||
| 		vec3 lPos = lightPosition.xyz / lightPosition.w; | 		vec3 lPos = lightPosition.xyz / lightPosition.w; | ||||||
| 		visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).rrr; | 		visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r; | ||||||
| 	} | 	} | ||||||
| 	else if (lightShadow == 2) { | 	else if (lightShadow == 2) { | ||||||
| 		vec4 lightPosition = LVP * vec4(P, 1.0); | 		vec4 lightPosition = LVP * vec4(wposition, 1.0); | ||||||
| 		vec3 lPos = lightPosition.xyz / lightPosition.w; | 		vec3 lPos = lightPosition.xyz / lightPosition.w; | ||||||
| 		visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; | 		visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; | ||||||
| 	} | 	} | ||||||
| @ -130,9 +129,7 @@ void main() { | |||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	vec3 light = visibility * lightColor; | 	imageAtomicAdd(voxelsLight, dst, uint(visibility * lightColor.r * 255)); | ||||||
|  | 	imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(visibility * lightColor.g * 255)); | ||||||
| 	imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, 0), uint(light.r * 255)); | 	imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(visibility * lightColor.b * 255)); | ||||||
| 	imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(light.g * 255)); |  | ||||||
| 	imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(light.b * 255)); |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -27,14 +27,14 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in; | |||||||
| #include "std/math.glsl" | #include "std/math.glsl" | ||||||
| #include "std/gbuffer.glsl" | #include "std/gbuffer.glsl" | ||||||
| #include "std/imageatomic.glsl" | #include "std/imageatomic.glsl" | ||||||
| #include "std/voxels_constants.glsl" | #include "std/constants.glsl" | ||||||
|  |  | ||||||
| #ifdef _VoxelGI | #ifdef _VoxelGI | ||||||
| uniform layout(rgba8) image3D voxelsB; | uniform layout(rgba8) image3D voxelsB; | ||||||
| uniform layout(rgba8) image3D voxelsOut; | uniform layout(rgba8) image3D voxelsOut; | ||||||
| #else | #else | ||||||
| uniform layout(r16) image3D voxelsB; | uniform layout(r8) image3D voxelsB; | ||||||
| uniform layout(r16) image3D voxelsOut; | uniform layout(r8) image3D voxelsOut; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| uniform int clipmapLevel; | uniform int clipmapLevel; | ||||||
|  | |||||||
| @ -29,19 +29,38 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; | |||||||
| #include "std/gbuffer.glsl" | #include "std/gbuffer.glsl" | ||||||
| #include "std/imageatomic.glsl" | #include "std/imageatomic.glsl" | ||||||
| #include "std/conetrace.glsl" | #include "std/conetrace.glsl" | ||||||
|  | #include "std/brdf.glsl" | ||||||
|  | #include "std/shirr.glsl" | ||||||
|  |  | ||||||
| uniform sampler3D voxels; | uniform sampler3D voxels; | ||||||
| uniform sampler2D gbufferD; | uniform sampler2D gbufferD; | ||||||
| uniform sampler2D gbuffer0; | uniform sampler2D gbuffer0; | ||||||
| uniform layout(r8) image2D voxels_ao; | uniform layout(rgba8) image2D voxels_ao; | ||||||
|  |  | ||||||
| uniform float clipmaps[voxelgiClipmapCount * 10]; | uniform float clipmaps[voxelgiClipmapCount * 10]; | ||||||
| uniform mat4 InvVP; | uniform mat4 InvVP; | ||||||
| uniform vec2 cameraProj; |  | ||||||
| uniform vec3 eye; | uniform vec3 eye; | ||||||
| uniform vec3 eyeLook; |  | ||||||
| uniform vec2 postprocess_resolution; | uniform vec2 postprocess_resolution; | ||||||
|  |  | ||||||
|  | uniform sampler2D gbuffer1; | ||||||
|  | #ifdef _gbuffer2 | ||||||
|  | uniform sampler2D gbuffer2; | ||||||
|  | #endif | ||||||
|  | uniform float envmapStrength; | ||||||
|  | #ifdef _Irr | ||||||
|  | uniform float shirr[7 * 4]; | ||||||
|  | #endif | ||||||
|  | #ifdef _Brdf | ||||||
|  | uniform sampler2D senvmapBrdf; | ||||||
|  | #endif | ||||||
|  | #ifdef _Rad | ||||||
|  | uniform sampler2D senvmapRadiance; | ||||||
|  | uniform int envmapNumMipmaps; | ||||||
|  | #endif | ||||||
|  | #ifdef _EnvCol | ||||||
|  | uniform vec3 backgroundCol; | ||||||
|  | #endif | ||||||
|  |  | ||||||
| void main() { | void main() { | ||||||
| 	const vec2 pixel = gl_GlobalInvocationID.xy; | 	const vec2 pixel = gl_GlobalInvocationID.xy; | ||||||
| 	vec2 uv = (pixel + 0.5) / postprocess_resolution; | 	vec2 uv = (pixel + 0.5) / postprocess_resolution; | ||||||
| @ -54,12 +73,11 @@ void main() { | |||||||
|  |  | ||||||
| 	float x = uv.x * 2 - 1; | 	float x = uv.x * 2 - 1; | ||||||
| 	float y = uv.y * 2 - 1; | 	float y = uv.y * 2 - 1; | ||||||
| 	vec4 v = vec4(x, y, 1.0, 1.0); | 	vec4 clipPos = vec4(x, y, depth, 1.0); | ||||||
| 	v = vec4(InvVP * v); |     vec4 worldPos = InvVP * clipPos; | ||||||
| 	v.xyz /= v.w; |     vec3 P = worldPos.xyz / worldPos.w; | ||||||
| 	vec3 viewRay = v.xyz - eye; |  | ||||||
|  |  | ||||||
| 	vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); | 	vec3 v = normalize(eye - P); | ||||||
|  |  | ||||||
| 	vec4 g0 = textureLod(gbuffer0, uv, 0.0); | 	vec4 g0 = textureLod(gbuffer0, uv, 0.0); | ||||||
| 	vec3 n; | 	vec3 n; | ||||||
| @ -67,7 +85,89 @@ void main() { | |||||||
| 	n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); | 	n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); | ||||||
| 	n = normalize(n); | 	n = normalize(n); | ||||||
|  |  | ||||||
| 	float occ = 1.0 - traceAO(P, n, voxels, clipmaps); | 	float roughness = g0.b; | ||||||
|  | 	float metallic; | ||||||
|  | 	uint matid; | ||||||
|  | 	unpackFloatInt16(g0.a, metallic, matid); | ||||||
|  |  | ||||||
| 	imageStore(voxels_ao, ivec2(pixel), vec4(occ)); | 	vec4 g1 = textureLod(gbuffer1, uv, 0.0); // Basecolor.rgb, spec/occ | ||||||
|  | 	vec2 occspec = unpackFloat2(g1.a); | ||||||
|  | 	vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor | ||||||
|  | 	vec3 f0 = surfaceF0(g1.rgb, metallic); | ||||||
|  | 	float dotNV = max(dot(n, v), 0.0); | ||||||
|  |  | ||||||
|  | #ifdef _gbuffer2 | ||||||
|  | 	vec4 g2 = textureLod(gbuffer2, uv, 0.0); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _MicroShadowing | ||||||
|  | 	occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _Brdf | ||||||
|  | 	vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; | ||||||
|  | 	vec3 F = f0 * envBRDF.x + envBRDF.y; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	// Envmap | ||||||
|  | #ifdef _Irr | ||||||
|  | 	vec4 shPacked[7]; | ||||||
|  |     for (int i = 0; i < 7; i++) { | ||||||
|  |         int base = i * 4; | ||||||
|  |         shPacked[i] = vec4( | ||||||
|  |             shirr[base], | ||||||
|  |             shirr[base + 1], | ||||||
|  |             shirr[base + 2], | ||||||
|  |             shirr[base + 3] | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 	vec3 envl = shIrradiance(n, shPacked); | ||||||
|  |  | ||||||
|  | 	#ifdef _gbuffer2 | ||||||
|  | 		if (g2.b < 0.5) { | ||||||
|  | 			envl = envl; | ||||||
|  | 		} else { | ||||||
|  | 			envl = vec3(0.0); | ||||||
|  | 		} | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
|  | 	#ifdef _EnvTex | ||||||
|  | 		envl /= PI; | ||||||
|  | 	#endif | ||||||
|  | #else | ||||||
|  | 	vec3 envl = vec3(0.0); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _Rad | ||||||
|  | 	vec3 reflectionWorld = reflect(-v, n); | ||||||
|  | 	float lod = getMipFromRoughness(roughness, envmapNumMipmaps); | ||||||
|  | 	vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _EnvLDR | ||||||
|  | 	envl.rgb = pow(envl.rgb, vec3(2.2)); | ||||||
|  | 	#ifdef _Rad | ||||||
|  | 		prefilteredColor = pow(prefilteredColor, vec3(2.2)); | ||||||
|  | 	#endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	envl.rgb *= albedo; | ||||||
|  |  | ||||||
|  | #ifdef _Brdf | ||||||
|  | 	envl.rgb *= 1.0 - F; //LV: We should take refracted light into account | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _Rad // Indirect specular | ||||||
|  | 	envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT | ||||||
|  | #else | ||||||
|  | 	#ifdef _EnvCol | ||||||
|  | 	envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0? | ||||||
|  | 	#endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	envl.rgb *= envmapStrength * occspec.x; | ||||||
|  |  | ||||||
|  | 	vec3 occ = envl * (1.0 - traceAO(P, n, voxels, clipmaps)); | ||||||
|  |  | ||||||
|  | 	imageStore(voxels_ao, ivec2(pixel), vec4(occ, 1.0)); | ||||||
| } | } | ||||||
|  | |||||||
| @ -29,6 +29,8 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; | |||||||
| #include "std/gbuffer.glsl" | #include "std/gbuffer.glsl" | ||||||
| #include "std/imageatomic.glsl" | #include "std/imageatomic.glsl" | ||||||
| #include "std/conetrace.glsl" | #include "std/conetrace.glsl" | ||||||
|  | #include "std/brdf.glsl" | ||||||
|  | #include "std/shirr.glsl" | ||||||
|  |  | ||||||
| uniform sampler3D voxels; | uniform sampler3D voxels; | ||||||
| uniform sampler2D gbufferD; | uniform sampler2D gbufferD; | ||||||
| @ -37,29 +39,44 @@ uniform layout(rgba8) image2D voxels_diffuse; | |||||||
|  |  | ||||||
| uniform float clipmaps[voxelgiClipmapCount * 10]; | uniform float clipmaps[voxelgiClipmapCount * 10]; | ||||||
| uniform mat4 InvVP; | uniform mat4 InvVP; | ||||||
| uniform vec2 cameraProj; |  | ||||||
| uniform vec3 eye; | uniform vec3 eye; | ||||||
| uniform vec3 eyeLook; |  | ||||||
| uniform vec2 postprocess_resolution; | uniform vec2 postprocess_resolution; | ||||||
|  |  | ||||||
|  | uniform sampler2D gbuffer1; | ||||||
|  | #ifdef _gbuffer2 | ||||||
|  | uniform sampler2D gbuffer2; | ||||||
|  | #endif | ||||||
|  | uniform float envmapStrength; | ||||||
|  | #ifdef _Irr | ||||||
|  | uniform float shirr[7 * 4]; | ||||||
|  | #endif | ||||||
|  | #ifdef _Brdf | ||||||
|  | uniform sampler2D senvmapBrdf; | ||||||
|  | #endif | ||||||
|  | #ifdef _Rad | ||||||
|  | uniform sampler2D senvmapRadiance; | ||||||
|  | uniform int envmapNumMipmaps; | ||||||
|  | #endif | ||||||
|  | #ifdef _EnvCol | ||||||
|  | uniform vec3 backgroundCol; | ||||||
|  | #endif | ||||||
|  |  | ||||||
| void main() { | void main() { | ||||||
| 	const vec2 pixel = gl_GlobalInvocationID.xy; | 	const vec2 pixel = gl_GlobalInvocationID.xy; | ||||||
| 	vec2 uv = (pixel + 0.5) / postprocess_resolution; | 	vec2 uv = (pixel + 0.5) / postprocess_resolution; | ||||||
| 	#ifdef _InvY | 	#ifdef _InvY | ||||||
| 	uv.y = 1.0 - uv.y | 	uv.y = 1.0 - uv.y; | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; | 	float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; | ||||||
| 	if (depth == 0) return; | 	if (depth == 0.0) return; | ||||||
|  |  | ||||||
| 	float x = uv.x * 2 - 1; | 	float x = uv.x * 2 - 1; | ||||||
| 	float y = uv.y * 2 - 1; | 	float y = uv.y * 2 - 1; | ||||||
| 	vec4 v = vec4(x, y, 1.0, 1.0); | 	vec4 clipPos = vec4(x, y, depth, 1.0); | ||||||
| 	v = vec4(InvVP * v); |     vec4 worldPos = InvVP * clipPos; | ||||||
| 	v.xyz /= v.w; |     vec3 P = worldPos.xyz / worldPos.w; | ||||||
| 	vec3 viewRay = v.xyz - eye; | 	vec3 v = normalize(eye - P); | ||||||
|  |  | ||||||
| 	vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); |  | ||||||
|  |  | ||||||
| 	vec4 g0 = textureLod(gbuffer0, uv, 0.0); | 	vec4 g0 = textureLod(gbuffer0, uv, 0.0); | ||||||
| 	vec3 n; | 	vec3 n; | ||||||
| @ -67,7 +84,94 @@ void main() { | |||||||
| 	n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); | 	n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); | ||||||
| 	n = normalize(n); | 	n = normalize(n); | ||||||
|  |  | ||||||
| 	vec4 color = traceDiffuse(P, n, voxels, clipmaps); | 	float roughness = g0.b; | ||||||
|  | 	float metallic; | ||||||
|  | 	uint matid; | ||||||
|  | 	unpackFloatInt16(g0.a, metallic, matid); | ||||||
|  |  | ||||||
| 	imageStore(voxels_diffuse, ivec2(pixel), color); | 	vec4 g1 = textureLod(gbuffer1, uv, 0.0); // Basecolor.rgb, spec/occ | ||||||
|  | 	vec2 occspec = unpackFloat2(g1.a); | ||||||
|  | 	vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor | ||||||
|  | 	vec3 f0 = surfaceF0(g1.rgb, metallic); | ||||||
|  | 	float dotNV = max(dot(n, v), 0.0); | ||||||
|  |  | ||||||
|  | #ifdef _gbuffer2 | ||||||
|  | 	vec4 g2 = textureLod(gbuffer2, uv, 0.0); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _MicroShadowing | ||||||
|  | 	occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _Brdf | ||||||
|  | 	vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; | ||||||
|  | 	vec3 F = f0 * envBRDF.x + envBRDF.y; | ||||||
|  | #else | ||||||
|  | 	vec3 F = f0; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	// Envmap | ||||||
|  | #ifdef _Irr | ||||||
|  | 	vec4 shPacked[7]; | ||||||
|  |     for (int i = 0; i < 7; i++) { | ||||||
|  |         int base = i * 4; | ||||||
|  |         shPacked[i] = vec4( | ||||||
|  |             shirr[base], | ||||||
|  |             shirr[base + 1], | ||||||
|  |             shirr[base + 2], | ||||||
|  |             shirr[base + 3] | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 	vec3 envl = shIrradiance(n, shPacked); | ||||||
|  |  | ||||||
|  | 	#ifdef _gbuffer2 | ||||||
|  | 		if (g2.b < 0.5) { | ||||||
|  | 			envl = envl; | ||||||
|  | 		} else { | ||||||
|  | 			envl = vec3(0.0); | ||||||
|  | 		} | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
|  | 	#ifdef _EnvTex | ||||||
|  | 		envl /= PI; | ||||||
|  | 	#endif | ||||||
|  | #else | ||||||
|  | 	vec3 envl = vec3(0.0); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _Rad | ||||||
|  | 	vec3 reflectionWorld = reflect(-v, n); | ||||||
|  | 	float lod = getMipFromRoughness(roughness, envmapNumMipmaps); | ||||||
|  | 	vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _EnvLDR | ||||||
|  | 	envl.rgb = pow(envl.rgb, vec3(2.2)); | ||||||
|  | 	#ifdef _Rad | ||||||
|  | 		prefilteredColor = pow(prefilteredColor, vec3(2.2)); | ||||||
|  | 	#endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	envl.rgb *= albedo; | ||||||
|  |  | ||||||
|  | #ifdef _Brdf | ||||||
|  | 	envl.rgb *= 1.0 - F; //LV: We should take refracted light into account | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _Rad // Indirect specular | ||||||
|  | 	envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT | ||||||
|  | #else | ||||||
|  | 	#ifdef _EnvCol | ||||||
|  | 	envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0? | ||||||
|  | 	#endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	envl.rgb *= envmapStrength * occspec.x; | ||||||
|  |  | ||||||
|  | 	vec4 trace = traceDiffuse(P, n, voxels, clipmaps); | ||||||
|  | 	vec3 color = trace.rgb * albedo * (1.0 - F); | ||||||
|  | 	color += envl * (1.0 - trace.a); | ||||||
|  |  | ||||||
|  | 	imageStore(voxels_diffuse, ivec2(pixel), vec4(color, 1.0)); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,79 +0,0 @@ | |||||||
| /* |  | ||||||
| Copyright (c) 2024 Turánszki János |  | ||||||
|  |  | ||||||
| Permission is hereby granted, free of charge, to any person obtaining a copy |  | ||||||
| of this software and associated documentation files (the "Software"), to deal |  | ||||||
| in the Software without restriction, including without limitation the rights |  | ||||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |  | ||||||
| copies of the Software, and to permit persons to whom the Software is |  | ||||||
| furnished to do so, subject to the following conditions: |  | ||||||
|  |  | ||||||
| The above copyright notice and this permission notice shall be included in |  | ||||||
| all copies or substantial portions of the Software. |  | ||||||
|  |  | ||||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |  | ||||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |  | ||||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE |  | ||||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |  | ||||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |  | ||||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |  | ||||||
| THE SOFTWARE. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #version 450 |  | ||||||
|  |  | ||||||
| layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; |  | ||||||
|  |  | ||||||
| #include "compiled.inc" |  | ||||||
| #include "std/math.glsl" |  | ||||||
| #include "std/gbuffer.glsl" |  | ||||||
| #include "std/imageatomic.glsl" |  | ||||||
| #include "std/conetrace.glsl" |  | ||||||
|  |  | ||||||
| uniform sampler2D gbufferD; |  | ||||||
| uniform sampler2D gbuffer0; |  | ||||||
| uniform sampler3D voxels; |  | ||||||
| uniform sampler3D voxelsSDF; |  | ||||||
| uniform sampler2D gbuffer_refraction; |  | ||||||
| uniform layout(rgba8) image2D voxels_refraction; |  | ||||||
|  |  | ||||||
| uniform float clipmaps[voxelgiClipmapCount * 10]; |  | ||||||
| uniform mat4 InvVP; |  | ||||||
| uniform vec2 cameraProj; |  | ||||||
| uniform vec3 eye; |  | ||||||
| uniform vec3 eyeLook; |  | ||||||
| uniform vec2 postprocess_resolution; |  | ||||||
|  |  | ||||||
| void main() { |  | ||||||
| 	const vec2 pixel = gl_GlobalInvocationID.xy; |  | ||||||
| 	vec2 uv = (pixel + 0.5) / postprocess_resolution; |  | ||||||
| 	#ifdef _InvY |  | ||||||
| 	uv.y = 1.0 - uv.y |  | ||||||
| 	#endif |  | ||||||
|  |  | ||||||
| 	float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; |  | ||||||
| 	if (depth == 0) return; |  | ||||||
|  |  | ||||||
| 	vec2 ior_opac = textureLod(gbuffer_refraction, uv, 0.0).xy; |  | ||||||
|  |  | ||||||
| 	float x = uv.x * 2 - 1; |  | ||||||
| 	float y = uv.y * 2 - 1; |  | ||||||
| 	vec4 v = vec4(x, y, 1.0, 1.0); |  | ||||||
| 	v = vec4(InvVP * v); |  | ||||||
| 	v.xyz /= v.w; |  | ||||||
| 	vec3 viewRay = v.xyz - eye; |  | ||||||
|  |  | ||||||
| 	vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); |  | ||||||
|  |  | ||||||
| 	vec4 g0 = textureLod(gbuffer0, uv, 0.0); |  | ||||||
| 	vec3 n; |  | ||||||
| 	n.z = 1.0 - abs(g0.x) - abs(g0.y); |  | ||||||
| 	n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); |  | ||||||
| 	n = normalize(n); |  | ||||||
|  |  | ||||||
| 	vec3 color = vec3(0.0); |  | ||||||
| 	if(ior_opac.y < 1.0) |  | ||||||
| 		color = traceRefraction(P, n, voxels, voxelsSDF, normalize(eye - P), ior_opac.x, g0.b, clipmaps, pixel).rgb; |  | ||||||
|  |  | ||||||
| 	imageStore(voxels_refraction, ivec2(pixel), vec4(color, 1.0)); |  | ||||||
| } |  | ||||||
| @ -1,75 +0,0 @@ | |||||||
| /* |  | ||||||
| Copyright (c) 2024 Turánszki János |  | ||||||
|  |  | ||||||
| Permission is hereby granted, free of charge, to any person obtaining a copy |  | ||||||
| of this software and associated documentation files (the "Software"), to deal |  | ||||||
| in the Software without restriction, including without limitation the rights |  | ||||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |  | ||||||
| copies of the Software, and to permit persons to whom the Software is |  | ||||||
| furnished to do so, subject to the following conditions: |  | ||||||
|  |  | ||||||
| The above copyright notice and this permission notice shall be included in |  | ||||||
| all copies or substantial portions of the Software. |  | ||||||
|  |  | ||||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |  | ||||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |  | ||||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE |  | ||||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |  | ||||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |  | ||||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |  | ||||||
| THE SOFTWARE. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #version 450 |  | ||||||
|  |  | ||||||
| layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; |  | ||||||
|  |  | ||||||
| #include "compiled.inc" |  | ||||||
| #include "std/math.glsl" |  | ||||||
| #include "std/gbuffer.glsl" |  | ||||||
| #include "std/imageatomic.glsl" |  | ||||||
| #include "std/conetrace.glsl" |  | ||||||
|  |  | ||||||
| uniform sampler3D voxels; |  | ||||||
| uniform sampler3D voxelsSDF; |  | ||||||
| uniform sampler2D gbufferD; |  | ||||||
| uniform sampler2D gbuffer0; |  | ||||||
| uniform layout(r16) image2D voxels_shadows; |  | ||||||
|  |  | ||||||
| uniform float clipmaps[voxelgiClipmapCount * 10]; |  | ||||||
| uniform mat4 InvVP; |  | ||||||
| uniform vec2 cameraProj; |  | ||||||
| uniform vec3 eye; |  | ||||||
| uniform vec3 eyeLook; |  | ||||||
| uniform vec2 postprocess_resolution; |  | ||||||
| uniform vec3 lPos; |  | ||||||
|  |  | ||||||
| void main() { |  | ||||||
| 	const vec2 pixel = gl_GlobalInvocationID.xy; |  | ||||||
| 	vec2 uv = (pixel + 0.5) / postprocess_resolution; |  | ||||||
| 	#ifdef _InvY |  | ||||||
| 	uv.y = 1.0 - uv.y; |  | ||||||
| 	#endif |  | ||||||
|  |  | ||||||
| 	float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; |  | ||||||
| 	if (depth == 0) return; |  | ||||||
|  |  | ||||||
| 	float x = uv.x * 2 - 1; |  | ||||||
| 	float y = uv.y * 2 - 1; |  | ||||||
| 	vec4 v = vec4(x, y, 1.0, 1.0); |  | ||||||
| 	v = vec4(InvVP * v); |  | ||||||
| 	v.xyz /= v.w; |  | ||||||
| 	vec3 viewRay = v.xyz - eye; |  | ||||||
|  |  | ||||||
| 	vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); |  | ||||||
|  |  | ||||||
| 	vec4 g0 = textureLod(gbuffer0, uv, 0.0); |  | ||||||
| 	vec3 n; |  | ||||||
| 	n.z = 1.0 - abs(g0.x) - abs(g0.y); |  | ||||||
| 	n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); |  | ||||||
| 	n = normalize(n); |  | ||||||
|  |  | ||||||
| 	float occ = 1.0 - traceShadow(P, n, voxels, voxelsSDF, normalize(lPos - P), clipmaps, pixel); |  | ||||||
|  |  | ||||||
| 	imageStore(voxels_shadows, ivec2(pixel), vec4(occ)); |  | ||||||
| } |  | ||||||
| @ -29,6 +29,7 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; | |||||||
| #include "std/gbuffer.glsl" | #include "std/gbuffer.glsl" | ||||||
| #include "std/imageatomic.glsl" | #include "std/imageatomic.glsl" | ||||||
| #include "std/conetrace.glsl" | #include "std/conetrace.glsl" | ||||||
|  | #include "std/brdf.glsl" | ||||||
|  |  | ||||||
| uniform sampler2D gbufferD; | uniform sampler2D gbufferD; | ||||||
| uniform sampler2D gbuffer0; | uniform sampler2D gbuffer0; | ||||||
| @ -38,9 +39,7 @@ uniform layout(rgba8) image2D voxels_specular; | |||||||
|  |  | ||||||
| uniform float clipmaps[voxelgiClipmapCount * 10]; | uniform float clipmaps[voxelgiClipmapCount * 10]; | ||||||
| uniform mat4 InvVP; | uniform mat4 InvVP; | ||||||
| uniform vec2 cameraProj; |  | ||||||
| uniform vec3 eye; | uniform vec3 eye; | ||||||
| uniform vec3 eyeLook; |  | ||||||
| uniform vec2 postprocess_resolution; | uniform vec2 postprocess_resolution; | ||||||
| uniform sampler2D sveloc; | uniform sampler2D sveloc; | ||||||
|  |  | ||||||
| @ -56,12 +55,10 @@ void main() { | |||||||
|  |  | ||||||
| 	float x = uv.x * 2 - 1; | 	float x = uv.x * 2 - 1; | ||||||
| 	float y = uv.y * 2 - 1; | 	float y = uv.y * 2 - 1; | ||||||
| 	vec4 v = vec4(x, y, 1.0, 1.0); | 	vec4 clipPos = vec4(x, y, depth, 1.0); | ||||||
| 	v = vec4(InvVP * v); |     vec4 worldPos = InvVP * clipPos; | ||||||
| 	v.xyz /= v.w; |     vec3 P = worldPos.xyz / worldPos.w; | ||||||
|  |  | ||||||
| 	vec3 viewRay = v.xyz - eye; |  | ||||||
| 	vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); |  | ||||||
| 	vec4 g0 = textureLod(gbuffer0, uv, 0.0); | 	vec4 g0 = textureLod(gbuffer0, uv, 0.0); | ||||||
|  |  | ||||||
| 	vec3 n; | 	vec3 n; | ||||||
| @ -71,7 +68,7 @@ void main() { | |||||||
|  |  | ||||||
| 	vec2 velocity = -textureLod(sveloc, uv, 0.0).rg; | 	vec2 velocity = -textureLod(sveloc, uv, 0.0).rg; | ||||||
|  |  | ||||||
| 	vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z, clipmaps, pixel, velocity).rgb; | 	vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z * g0.z, clipmaps, pixel, velocity).rgb; | ||||||
|  |  | ||||||
| 	imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0)); | 	imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0)); | ||||||
| } | } | ||||||
|  | |||||||
| @ -23,8 +23,8 @@ THE SOFTWARE. | |||||||
|  |  | ||||||
| #include "compiled.inc" | #include "compiled.inc" | ||||||
|  |  | ||||||
| uniform layout(r16) image3D input_sdf; | uniform layout(r8) image3D input_sdf; | ||||||
| uniform layout(r16) image3D output_sdf; | uniform layout(r8) image3D output_sdf; | ||||||
|  |  | ||||||
| uniform float jump_size; | uniform float jump_size; | ||||||
| uniform int clipmapLevel; | uniform int clipmapLevel; | ||||||
|  | |||||||
| @ -46,15 +46,15 @@ uniform layout(r32ui) uimage3D voxels; | |||||||
| uniform layout(r32ui) uimage3D voxelsLight; | uniform layout(r32ui) uimage3D voxelsLight; | ||||||
| uniform layout(rgba8) image3D voxelsB; | uniform layout(rgba8) image3D voxelsB; | ||||||
| uniform layout(rgba8) image3D voxelsOut; | uniform layout(rgba8) image3D voxelsOut; | ||||||
| uniform layout(r16) image3D SDF; | uniform layout(r8) image3D SDF; | ||||||
| #else | #else | ||||||
| #ifdef _VoxelAOvar | #ifdef _VoxelAOvar | ||||||
| #ifdef _VoxelShadow | #ifdef _VoxelShadow | ||||||
| uniform layout(r16) image3D SDF; | uniform layout(r8) image3D SDF; | ||||||
| #endif | #endif | ||||||
| uniform layout(r32ui) uimage3D voxels; | uniform layout(r32ui) uimage3D voxels; | ||||||
| uniform layout(r16) image3D voxelsB; | uniform layout(r8) image3D voxelsB; | ||||||
| uniform layout(r16) image3D voxelsOut; | uniform layout(r8) image3D voxelsOut; | ||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @ -74,14 +74,9 @@ void main() { | |||||||
| 	#endif | 	#endif | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	ivec3 src = ivec3(gl_GlobalInvocationID.xyz); | 	int nor_count = 0; | ||||||
| 	#ifdef _VoxelGI | 	vec3 avgNormal = vec3(0.0); | ||||||
| 	vec3 light = vec3(0.0); | 	mat3 TBN = mat3(0.0); | ||||||
| 	light.r = float(imageLoad(voxelsLight, src)) / 255; |  | ||||||
| 	light.g = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x))) / 255; |  | ||||||
| 	light.b = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; |  | ||||||
| 	light /= 3; |  | ||||||
| 	#endif |  | ||||||
|  |  | ||||||
| 	for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) | 	for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) | ||||||
| 	{ | 	{ | ||||||
| @ -91,7 +86,7 @@ void main() { | |||||||
| 		float aniso_colors[6]; | 		float aniso_colors[6]; | ||||||
| 		#endif | 		#endif | ||||||
|  |  | ||||||
| 		src = ivec3(gl_GlobalInvocationID.xyz); | 		ivec3 src = ivec3(gl_GlobalInvocationID.xyz); | ||||||
| 		src.x += i * res; | 		src.x += i * res; | ||||||
| 		ivec3 dst = src; | 		ivec3 dst = src; | ||||||
| 		dst.y += clipmapLevel * res; | 		dst.y += clipmapLevel * res; | ||||||
| @ -104,44 +99,67 @@ void main() { | |||||||
|  |  | ||||||
| 		if (i < 6) { | 		if (i < 6) { | ||||||
| 			#ifdef _VoxelGI | 			#ifdef _VoxelGI | ||||||
| 			vec4 basecol = vec4(0.0); | 			int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 15))); | ||||||
| 			basecol.r = float(imageLoad(voxels, src)) / 255; | 			if (count > 0) { | ||||||
| 			basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255; | 				vec4 basecol = vec4(0.0); | ||||||
| 			basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; | 				basecol.r = float(imageLoad(voxels, src)) / 255; | ||||||
| 			basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255; | 				basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255; | ||||||
| 			basecol /= 4; | 				basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; | ||||||
| 			vec3 emission = vec3(0.0); | 				basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255; | ||||||
| 			emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255; | 				basecol /= count; | ||||||
| 			emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 255; | 				vec3 emission = vec3(0.0); | ||||||
| 			emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255; | 				emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255; | ||||||
| 			emission /= 3; | 				emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 255; | ||||||
| 			vec3 N = vec3(0.0); | 				emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255; | ||||||
| 			N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 255; | 				emission /= count; | ||||||
| 			N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255; | 				vec3 N = vec3(0.0); | ||||||
| 			N /= 2; | 				N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 255; | ||||||
| 			vec3 wnormal = decode_oct(N.rg * 2 - 1); | 				N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255; | ||||||
| 			vec3 envl = vec3(0.0); | 				N /= count; | ||||||
| 			envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; | 				N = decode_oct(N.rg * 2.0 - 1.0); | ||||||
| 			envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; |  | ||||||
| 			envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; |  | ||||||
| 			envl /= 3; |  | ||||||
| 			envl *= 100; |  | ||||||
|  |  | ||||||
| 			//clipmap to world | 				if (abs(N.x) > 0) | ||||||
| 			vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; | 					avgNormal.x += N.x; | ||||||
| 			wposition = wposition * 2.0 - 1.0; | 				if (abs(N.y) > 0) | ||||||
| 			wposition *= float(clipmaps[int(clipmapLevel * 10)]); | 					avgNormal.y += N.y; | ||||||
| 			wposition *= voxelgiResolution.x; | 				if (abs(N.z) > 0) | ||||||
| 			wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); | 					avgNormal.z += N.z; | ||||||
|  | 				if (i == 5) | ||||||
|  | 				{ | ||||||
|  | 					avgNormal = normalize(avgNormal); | ||||||
|  | 					TBN = makeTangentBasis(avgNormal); | ||||||
|  | 				} | ||||||
|  |  | ||||||
| 			radiance = basecol; | 				vec3 envl = vec3(0.0); | ||||||
| 			vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps); | 				envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; | ||||||
| 			vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); | 				envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; | ||||||
| 			radiance.rgb *= light + indirect; | 				envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; | ||||||
| 			radiance.rgb += emission.rgb; | 				envl /= count; | ||||||
|  | 				vec3 light = vec3(0.0); | ||||||
|  | 				light.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 12))) / 255; | ||||||
|  | 				light.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 13))) / 255; | ||||||
|  | 				light.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 14))) / 255; | ||||||
|  | 				light /= count; | ||||||
|  |  | ||||||
|  | 				//clipmap to world | ||||||
|  | 				vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; | ||||||
|  | 				wposition = wposition * 2.0 - 1.0; | ||||||
|  | 				wposition *= float(clipmaps[int(clipmapLevel * 10)]); | ||||||
|  | 				wposition *= voxelgiResolution.x; | ||||||
|  | 				wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); | ||||||
|  |  | ||||||
|  | 				radiance = basecol; | ||||||
|  | 				vec4 trace = traceDiffuse(wposition, N, voxelsSampler, clipmaps); | ||||||
|  | 				vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); | ||||||
|  | 				radiance.rgb *= light + indirect; | ||||||
|  | 				radiance.rgb += emission.rgb; | ||||||
|  | 			} | ||||||
| 			#else | 			#else | ||||||
| 			opac = float(imageLoad(voxels, src)) / 255; | 			int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))); | ||||||
|  | 			if (count > 0) { | ||||||
|  | 				opac = float(imageLoad(voxels, src)) / 255; | ||||||
|  | 				opac /= count; | ||||||
|  | 			} | ||||||
| 			#endif | 			#endif | ||||||
|  |  | ||||||
| 			#ifdef _VoxelGI | 			#ifdef _VoxelGI | ||||||
| @ -195,7 +213,7 @@ void main() { | |||||||
| 		} | 		} | ||||||
| 		else { | 		else { | ||||||
| 			// precompute cone sampling: | 			// precompute cone sampling: | ||||||
| 			vec3 coneDirection = DIFFUSE_CONE_DIRECTIONS[i - 6]; | 			vec3 coneDirection = TBN * DIFFUSE_CONE_DIRECTIONS[i - 6]; | ||||||
| 			vec3 aniso_direction = -coneDirection; | 			vec3 aniso_direction = -coneDirection; | ||||||
| 			uvec3 face_offsets = uvec3( | 			uvec3 face_offsets = uvec3( | ||||||
| 				aniso_direction.x > 0 ? 0 : 1, | 				aniso_direction.x > 0 ? 0 : 1, | ||||||
|  | |||||||
| @ -75,16 +75,17 @@ vec4 binarySearch(vec3 dir) { | |||||||
| } | } | ||||||
|  |  | ||||||
| vec4 rayCast(vec3 dir) { | vec4 rayCast(vec3 dir) { | ||||||
| 	#ifdef _CPostprocess |     float ddepth; | ||||||
| 		dir *= PPComp9.x; |     dir *= ss_refractionRayStep; | ||||||
| 	#else |     for (int i = 0; i < maxSteps; i++) { | ||||||
| 		dir *= ssrRayStep; |         hitCoord += dir; | ||||||
| 	#endif |         ddepth = getDeltaDepth(hitCoord); | ||||||
| 	for (int i = 0; i < maxSteps; i++) { |         if (ddepth > 0.0) | ||||||
| 		hitCoord += dir; |             return binarySearch(dir); | ||||||
| 		if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir); |     } | ||||||
| 	} |     // No hit — fallback to projecting the ray to UV space | ||||||
| 	return vec4(0.0); |     vec2 fallbackUV = getProjectedCoord(hitCoord); | ||||||
|  |     return vec4(fallbackUV, 0.0, 0.5); // We set .w lower to indicate fallback | ||||||
| } | } | ||||||
| #endif //SSR | #endif //SSR | ||||||
|  |  | ||||||
|  | |||||||
| @ -181,11 +181,15 @@ class Uniforms { | |||||||
| 						// Multiple voxel volumes, always set params | 						// Multiple voxel volumes, always set params | ||||||
| 						g.setImageTexture(context.textureUnits[j], rt.image); // image2D/3D | 						g.setImageTexture(context.textureUnits[j], rt.image); // image2D/3D | ||||||
| 						if (rt.raw.name.startsWith("voxels_")) { | 						if (rt.raw.name.startsWith("voxels_")) { | ||||||
| 							g.setTextureParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.NoMipFilter); | 							g.setTextureParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.LinearMipFilter); | ||||||
|  | 						} | ||||||
|  | 						else if (rt.raw.name.startsWith("voxelsSDF")) | ||||||
|  | 						{ | ||||||
|  | 							g.setTexture3DParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.PointFilter, TextureFilter.PointFilter, MipMapFilter.NoMipFilter); | ||||||
| 						} | 						} | ||||||
| 						else if (rt.raw.name.startsWith("voxels")) | 						else if (rt.raw.name.startsWith("voxels")) | ||||||
| 						{ | 						{ | ||||||
| 							g.setTexture3DParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.NoMipFilter); | 							g.setTexture3DParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.PointMipFilter); | ||||||
| 						} | 						} | ||||||
| 						else | 						else | ||||||
| 						{ | 						{ | ||||||
|  | |||||||
| @ -34,10 +34,10 @@ class Inc { | |||||||
| 	#if (rp_voxels == "Voxel GI") | 	#if (rp_voxels == "Voxel GI") | ||||||
| 	static var voxel_td1:kha.compute.TextureUnit; | 	static var voxel_td1:kha.compute.TextureUnit; | ||||||
| 	static var voxel_te1:kha.compute.TextureUnit; | 	static var voxel_te1:kha.compute.TextureUnit; | ||||||
| 	static var voxel_tf1:kha.compute.TextureUnit; | 	static var voxel_cc1:kha.compute.ConstantLocation; | ||||||
| 	#else | 	#else | ||||||
| 	#if lnx_voxelgi_shadows | 	#if lnx_voxelgi_shadows | ||||||
| 	static var voxel_tf1:kha.compute.TextureUnit; | 	static var voxel_te1:kha.compute.TextureUnit; | ||||||
| 	#end | 	#end | ||||||
| 	#end | 	#end | ||||||
| 	#if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") | 	#if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") | ||||||
| @ -53,12 +53,28 @@ class Inc { | |||||||
| 	static var voxel_tb3:kha.compute.TextureUnit; | 	static var voxel_tb3:kha.compute.TextureUnit; | ||||||
| 	static var voxel_tc3:kha.compute.TextureUnit; | 	static var voxel_tc3:kha.compute.TextureUnit; | ||||||
| 	static var voxel_td3:kha.compute.TextureUnit; | 	static var voxel_td3:kha.compute.TextureUnit; | ||||||
|  | 	static var voxel_te3:kha.compute.TextureUnit; | ||||||
|  | 	static var voxel_tf3:kha.compute.TextureUnit; | ||||||
|  | 	#if lnx_brdf | ||||||
|  | 	static var voxel_tg3:kha.compute.TextureUnit; | ||||||
|  | 	#end | ||||||
|  | 	#if lnx_radiance | ||||||
|  | 	static var voxel_th3:kha.compute.TextureUnit; | ||||||
|  | 	#end | ||||||
| 	static var voxel_ca3:kha.compute.ConstantLocation; | 	static var voxel_ca3:kha.compute.ConstantLocation; | ||||||
| 	static var voxel_cb3:kha.compute.ConstantLocation; | 	static var voxel_cb3:kha.compute.ConstantLocation; | ||||||
| 	static var voxel_cc3:kha.compute.ConstantLocation; | 	static var voxel_cc3:kha.compute.ConstantLocation; | ||||||
| 	static var voxel_cd3:kha.compute.ConstantLocation; | 	static var voxel_cd3:kha.compute.ConstantLocation; | ||||||
| 	static var voxel_ce3:kha.compute.ConstantLocation; | 	static var voxel_ce3:kha.compute.ConstantLocation; | ||||||
|  | 	#if lnx_irradiance | ||||||
| 	static var voxel_cf3:kha.compute.ConstantLocation; | 	static var voxel_cf3:kha.compute.ConstantLocation; | ||||||
|  | 	#end | ||||||
|  | 	#if lnx_radiance | ||||||
|  | 	static var voxel_cg3:kha.compute.ConstantLocation; | ||||||
|  | 	#end | ||||||
|  | 	#if lnx_envcol | ||||||
|  | 	static var voxel_ch3:kha.compute.ConstantLocation; | ||||||
|  | 	#end | ||||||
| 	#if (rp_voxels == "Voxel GI") | 	#if (rp_voxels == "Voxel GI") | ||||||
| 	static var voxel_sh4:kha.compute.Shader = null; | 	static var voxel_sh4:kha.compute.Shader = null; | ||||||
| 	static var voxel_ta4:kha.compute.TextureUnit; | 	static var voxel_ta4:kha.compute.TextureUnit; | ||||||
| @ -71,33 +87,6 @@ class Inc { | |||||||
| 	static var voxel_cb4:kha.compute.ConstantLocation; | 	static var voxel_cb4:kha.compute.ConstantLocation; | ||||||
| 	static var voxel_cc4:kha.compute.ConstantLocation; | 	static var voxel_cc4:kha.compute.ConstantLocation; | ||||||
| 	static var voxel_cd4:kha.compute.ConstantLocation; | 	static var voxel_cd4:kha.compute.ConstantLocation; | ||||||
| 	static var voxel_ce4:kha.compute.ConstantLocation; |  | ||||||
| 	static var voxel_cf4:kha.compute.ConstantLocation; |  | ||||||
| 	#end |  | ||||||
| 	#if (rp_voxels == "Voxel GI") |  | ||||||
| 	static var voxel_sh5:kha.compute.Shader = null; |  | ||||||
| 	static var voxel_ta5:kha.compute.TextureUnit; |  | ||||||
| 	static var voxel_ca5:kha.compute.ConstantLocation; |  | ||||||
| 	static var voxel_cb5:kha.compute.ConstantLocation; |  | ||||||
| 	static var voxel_cc5:kha.compute.ConstantLocation; |  | ||||||
| 	static var voxel_cd5:kha.compute.ConstantLocation; |  | ||||||
| 	static var voxel_ce5:kha.compute.ConstantLocation; |  | ||||||
| 	static var voxel_cf5:kha.compute.ConstantLocation; |  | ||||||
| 	static var voxel_cg5:kha.compute.ConstantLocation; |  | ||||||
| 	#if rp_shadowmap |  | ||||||
| 	static var voxel_tb5:kha.compute.TextureUnit; |  | ||||||
| 	static var voxel_tc5:kha.compute.TextureUnit; |  | ||||||
| 	static var voxel_td5:kha.compute.TextureUnit; |  | ||||||
| 	static var voxel_ch5:kha.compute.ConstantLocation; |  | ||||||
| 	static var voxel_ci5:kha.compute.ConstantLocation; |  | ||||||
| 	static var voxel_cj5:kha.compute.ConstantLocation; |  | ||||||
| 	static var voxel_ck5:kha.compute.ConstantLocation; |  | ||||||
| 	static var voxel_cl5:kha.compute.ConstantLocation; |  | ||||||
| 	static var voxel_cm5:kha.compute.ConstantLocation; |  | ||||||
| 	#if lnx_shadowmap_atlas |  | ||||||
| 	static var m2 = iron.math.Mat4.identity(); |  | ||||||
| 	#end |  | ||||||
| 	#end |  | ||||||
| 	#end | 	#end | ||||||
| 	#end //rp_voxels | 	#end //rp_voxels | ||||||
|  |  | ||||||
| @ -163,9 +152,11 @@ class Inc { | |||||||
| 		for (atlas in ShadowMapAtlas.shadowMapAtlases) { | 		for (atlas in ShadowMapAtlas.shadowMapAtlases) { | ||||||
| 			path.bindTarget(atlas.target, atlas.target); | 			path.bindTarget(atlas.target, atlas.target); | ||||||
| 		} | 		} | ||||||
|  | 		#if rp_shadowmap_transparent | ||||||
| 		for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { | 		for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { | ||||||
| 			path.bindTarget(atlas.target, atlas.target); | 			path.bindTarget(atlas.target, atlas.target); | ||||||
| 		} | 		} | ||||||
|  | 		#end | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	static function getShadowMapAtlas(atlas:ShadowMapAtlas, transparent: Bool):String { | 	static function getShadowMapAtlas(atlas:ShadowMapAtlas, transparent: Bool):String { | ||||||
| @ -206,24 +197,30 @@ class Inc { | |||||||
| 		for (atlas in ShadowMapAtlas.shadowMapAtlases) { | 		for (atlas in ShadowMapAtlas.shadowMapAtlases) { | ||||||
| 			atlas.rejectedLights = []; | 			atlas.rejectedLights = []; | ||||||
| 		} | 		} | ||||||
|  | 		#if rp_shadowmap_transparent | ||||||
| 		for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { | 		for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { | ||||||
| 			atlas.rejectedLights = []; | 			atlas.rejectedLights = []; | ||||||
| 		} | 		} | ||||||
| 		#end | 		#end | ||||||
|  | 		#end | ||||||
|  |  | ||||||
| 		for (light in iron.Scene.active.lights) { | 		for (light in iron.Scene.active.lights) { | ||||||
| 			if (!light.lightInAtlas && !light.culledLight && light.visible && light.shadowMapScale > 0.0 | 			if (!light.lightInAtlas && !light.culledLight && light.visible && light.shadowMapScale > 0.0 | ||||||
| 				&& light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { | 				&& light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { | ||||||
| 				ShadowMapAtlas.addLight(light, false); | 				ShadowMapAtlas.addLight(light, false); | ||||||
| 			} | 			} | ||||||
|  | 			#if rp_shadowmap_transparent | ||||||
| 			if (!light.lightInAtlasTransparent && !light.culledLight && light.visible && light.shadowMapScale > 0.0 | 			if (!light.lightInAtlasTransparent && !light.culledLight && light.visible && light.shadowMapScale > 0.0 | ||||||
| 				&& light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { | 				&& light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { | ||||||
| 				ShadowMapAtlas.addLight(light, true); | 				ShadowMapAtlas.addLight(light, true); | ||||||
| 			} | 			} | ||||||
|  | 			#end | ||||||
| 		} | 		} | ||||||
| 		// update point light data before rendering | 		// update point light data before rendering | ||||||
| 		updatePointLightAtlasData(true); |  | ||||||
| 		updatePointLightAtlasData(false); | 		updatePointLightAtlasData(false); | ||||||
|  | 		#if rp_shadowmap_transparent | ||||||
|  | 		updatePointLightAtlasData(true); | ||||||
|  | 		#end | ||||||
|  |  | ||||||
| 		for (atlas in ShadowMapAtlas.shadowMapAtlases) { | 		for (atlas in ShadowMapAtlas.shadowMapAtlases) { | ||||||
| 			var tilesToRemove = []; | 			var tilesToRemove = []; | ||||||
| @ -301,6 +298,7 @@ class Inc { | |||||||
| 			path.endStream(); | 			path.endStream(); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		#if rp_shadowmap_transparent | ||||||
| 		for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { | 		for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { | ||||||
| 			var tilesToRemove = []; | 			var tilesToRemove = []; | ||||||
| 			#if lnx_shadowmap_atlas_lod | 			#if lnx_shadowmap_atlas_lod | ||||||
| @ -395,10 +393,8 @@ class Inc { | |||||||
| 				tile.freeTile(); | 				tile.freeTile(); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		#if lnx_debug |  | ||||||
| 		endShadowsLogicProfile(); |  | ||||||
| 		#end | 		#end | ||||||
| 		#end // rp_shadowmap | 		#end | ||||||
| 	} | 	} | ||||||
| 	#else | 	#else | ||||||
| 	public static function bindShadowMap() { | 	public static function bindShadowMap() { | ||||||
| @ -501,6 +497,7 @@ class Inc { | |||||||
| 			else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; | 			else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		#if rp_shadowmap_transparent | ||||||
| 		pointIndex = 0; | 		pointIndex = 0; | ||||||
| 		spotIndex = 0; | 		spotIndex = 0; | ||||||
| 		for (l in iron.Scene.active.lights) { | 		for (l in iron.Scene.active.lights) { | ||||||
| @ -522,6 +519,7 @@ class Inc { | |||||||
| 			if (l.data.raw.type == "point") pointIndex++; | 			if (l.data.raw.type == "point") pointIndex++; | ||||||
| 			else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; | 			else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; | ||||||
| 		} | 		} | ||||||
|  | 		#end | ||||||
| 		#end // rp_shadowmap | 		#end // rp_shadowmap | ||||||
| 	} | 	} | ||||||
| 	#end | 	#end | ||||||
| @ -589,7 +587,7 @@ class Inc { | |||||||
| 		t.width = 0; | 		t.width = 0; | ||||||
| 		t.height = 0; | 		t.height = 0; | ||||||
| 		t.displayp = getDisplayp(); | 		t.displayp = getDisplayp(); | ||||||
| 		t.format = "R32"; | 		t.format = "R16"; | ||||||
| 		t.scale = getSuperSampling(); | 		t.scale = getSuperSampling(); | ||||||
| 		t.depth_buffer = "main"; | 		t.depth_buffer = "main"; | ||||||
| 		path.createRenderTarget(t); | 		path.createRenderTarget(t); | ||||||
| @ -615,10 +613,14 @@ class Inc { | |||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| 		#if (rp_voxels != "Off") | 		#if (rp_voxels != "Off") | ||||||
| 		{ | 		path.bindTarget("voxelsOut", "voxels"); | ||||||
| 			path.bindTarget("voxelsOut", "voxels"); | 		#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) | ||||||
| 			path.bindTarget("voxelsSDF", "voxelsSDF"); | 		path.bindTarget("voxelsSDF", "voxelsSDF"); | ||||||
| 		} | 		#end | ||||||
|  | 		#end | ||||||
|  |  | ||||||
|  | 		#if rp_ssrs | ||||||
|  | 		path.bindTarget("_main", "gbufferD"); | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| 		path.drawMeshes("translucent"); | 		path.drawMeshes("translucent"); | ||||||
| @ -679,12 +681,11 @@ class Inc { | |||||||
| 			t.width = 0; | 			t.width = 0; | ||||||
| 			t.height = 0; | 			t.height = 0; | ||||||
| 			t.displayp = getDisplayp(); | 			t.displayp = getDisplayp(); | ||||||
| 			//t.scale = Inc.getSuperSampling(); | 			t.format = "RGBA32"; | ||||||
| 			t.format = t.name == "voxels_ao" ? "R8" : "RGBA32"; |  | ||||||
| 		} | 		} | ||||||
| 		else { | 		else { | ||||||
| 			if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { | 			if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { | ||||||
| 				t.format = "R16"; | 				t.format = "R8"; | ||||||
| 				t.width = res; | 				t.width = res; | ||||||
| 				t.height = res * Main.voxelgiClipmapCount; | 				t.height = res * Main.voxelgiClipmapCount; | ||||||
| 				t.depth = res; | 				t.depth = res; | ||||||
| @ -693,16 +694,16 @@ class Inc { | |||||||
| 				#if (rp_voxels == "Voxel AO") | 				#if (rp_voxels == "Voxel AO") | ||||||
| 				{ | 				{ | ||||||
| 					if (t.name == "voxelsOut" || t.name == "voxelsOutB") { | 					if (t.name == "voxelsOut" || t.name == "voxelsOutB") { | ||||||
| 						t.format = "R16"; | 						t.format = "R8"; | ||||||
| 						t.width = res * (6 + 16); | 						t.width = res * (6 + 16); | ||||||
| 						t.height = res * Main.voxelgiClipmapCount; | 						t.height = res * Main.voxelgiClipmapCount; | ||||||
| 						t.depth = res; | 						t.depth = res; | ||||||
| 					} | 					} | ||||||
| 					else { | 					else { | ||||||
| 						t.format = "R32"; | 						t.format = "R32UI"; | ||||||
| 						t.width = res * 6; | 						t.width = res * 6; | ||||||
| 						t.height = res; | 						t.height = res; | ||||||
| 						t.depth = res; | 						t.depth = res * 2; | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 				#else | 				#else | ||||||
| @ -713,17 +714,11 @@ class Inc { | |||||||
| 						t.height = res * Main.voxelgiClipmapCount; | 						t.height = res * Main.voxelgiClipmapCount; | ||||||
| 						t.depth = res; | 						t.depth = res; | ||||||
| 					} | 					} | ||||||
| 					else if (t.name == "voxelsLight") { |  | ||||||
| 						t.format = "R32"; |  | ||||||
| 						t.width = res; |  | ||||||
| 						t.height = res; |  | ||||||
| 						t.depth = res * 3; |  | ||||||
| 					} |  | ||||||
| 					else { | 					else { | ||||||
| 						t.format = "R32"; | 						t.format = "R32UI"; | ||||||
| 						t.width = res * 6; | 						t.width = res * 6; | ||||||
| 						t.height = res; | 						t.height = res; | ||||||
| 						t.depth = res * 12; | 						t.depth = res * 16; | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 				#end | 				#end | ||||||
| @ -835,14 +830,15 @@ class Inc { | |||||||
|  |  | ||||||
| 	 		voxel_ca1 = voxel_sh1.getConstantLocation("clipmaps"); | 	 		voxel_ca1 = voxel_sh1.getConstantLocation("clipmaps"); | ||||||
| 	 		voxel_cb1 = voxel_sh1.getConstantLocation("clipmapLevel"); | 	 		voxel_cb1 = voxel_sh1.getConstantLocation("clipmapLevel"); | ||||||
|  | 	 		voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength"); | ||||||
|  |  | ||||||
| 			#if (rp_voxels == "Voxel GI") | 			#if (rp_voxels == "Voxel GI") | ||||||
| 			voxel_td1 = voxel_sh1.getTextureUnit("voxelsSampler"); | 			voxel_td1 = voxel_sh1.getTextureUnit("voxelsSampler"); | ||||||
| 			voxel_te1 = voxel_sh1.getTextureUnit("voxelsLight"); | 			voxel_te1 = voxel_sh1.getTextureUnit("SDF"); | ||||||
| 			voxel_tf1 = voxel_sh1.getTextureUnit("SDF"); | 	 		voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength"); | ||||||
| 			#else | 			#else | ||||||
| 			#if lnx_voxelgi_shadows | 			#if lnx_voxelgi_shadows | ||||||
| 			voxel_tf1 = voxel_sh1.getTextureUnit("SDF"); | 			voxel_te1 = voxel_sh1.getTextureUnit("SDF"); | ||||||
| 			#end | 			#end | ||||||
| 			#end | 			#end | ||||||
| 		} | 		} | ||||||
| @ -873,12 +869,28 @@ class Inc { | |||||||
| 			#else | 			#else | ||||||
| 			voxel_td3 = voxel_sh3.getTextureUnit("voxels_diffuse"); | 			voxel_td3 = voxel_sh3.getTextureUnit("voxels_diffuse"); | ||||||
| 			#end | 			#end | ||||||
| 	 		voxel_ca3 = voxel_sh3.getConstantLocation("clipmaps"); | 			voxel_te3 = voxel_sh3.getTextureUnit("gbuffer1"); | ||||||
|  | 			voxel_tf3 = voxel_sh3.getTextureUnit("gbuffer2"); | ||||||
|  | 			#if lnx_brdf | ||||||
|  | 			voxel_tg3 = voxel_sh3.getTextureUnit("senvmapBrdf"); | ||||||
|  | 			#end | ||||||
|  | 			#if lnx_radiance | ||||||
|  | 			voxel_th3 = voxel_sh3.getTextureUnit("senvmapRadiance"); | ||||||
|  | 			#end | ||||||
|  | 			voxel_ca3 = voxel_sh3.getConstantLocation("clipmaps"); | ||||||
| 	 		voxel_cb3 = voxel_sh3.getConstantLocation("InvVP"); | 	 		voxel_cb3 = voxel_sh3.getConstantLocation("InvVP"); | ||||||
| 	 		voxel_cc3 = voxel_sh3.getConstantLocation("cameraProj"); | 	 		voxel_cc3 = voxel_sh3.getConstantLocation("eye"); | ||||||
| 	 		voxel_cd3 = voxel_sh3.getConstantLocation("eye"); | 	 		voxel_cd3 = voxel_sh3.getConstantLocation("postprocess_resolution"); | ||||||
| 	 		voxel_ce3 = voxel_sh3.getConstantLocation("eyeLook"); | 	 		voxel_ce3 = voxel_sh3.getConstantLocation("envmapStrength"); | ||||||
| 	 		voxel_cf3 = voxel_sh3.getConstantLocation("postprocess_resolution"); | 	 		#if lnx_irradiance | ||||||
|  | 	 		voxel_cf3 = voxel_sh3.getConstantLocation("shirr"); | ||||||
|  | 	 		#end | ||||||
|  | 	 		#if lnx_radiance | ||||||
|  | 	 		voxel_cg3 = voxel_sh3.getConstantLocation("envmapNumMipmaps"); | ||||||
|  | 	 		#end | ||||||
|  | 	 		#if lnx_envcol | ||||||
|  | 	 		voxel_ch3 = voxel_sh3.getConstantLocation("backgroundCol"); | ||||||
|  | 			#end | ||||||
| 		} | 		} | ||||||
| 		#if (rp_voxels == "Voxel GI") | 		#if (rp_voxels == "Voxel GI") | ||||||
| 		if (voxel_sh4 == null) | 		if (voxel_sh4 == null) | ||||||
| @ -892,40 +904,8 @@ class Inc { | |||||||
| 			voxel_tf4 = voxel_sh4.getTextureUnit("sveloc"); | 			voxel_tf4 = voxel_sh4.getTextureUnit("sveloc"); | ||||||
| 	 		voxel_ca4 = voxel_sh4.getConstantLocation("clipmaps"); | 	 		voxel_ca4 = voxel_sh4.getConstantLocation("clipmaps"); | ||||||
| 	 		voxel_cb4 = voxel_sh4.getConstantLocation("InvVP"); | 	 		voxel_cb4 = voxel_sh4.getConstantLocation("InvVP"); | ||||||
| 	 		voxel_cc4 = voxel_sh4.getConstantLocation("cameraProj"); | 	 		voxel_cc4 = voxel_sh4.getConstantLocation("eye"); | ||||||
| 	 		voxel_cd4 = voxel_sh4.getConstantLocation("eye"); | 	 		voxel_cd4 = voxel_sh4.getConstantLocation("postprocess_resolution"); | ||||||
| 	 		voxel_ce4 = voxel_sh4.getConstantLocation("eyeLook"); |  | ||||||
| 	 		voxel_cf4 = voxel_sh4.getConstantLocation("postprocess_resolution"); |  | ||||||
| 		} |  | ||||||
| 		#end |  | ||||||
| 		#if (rp_voxels == "Voxel GI") |  | ||||||
| 		if (voxel_sh5 == null) |  | ||||||
| 		{ |  | ||||||
| 			voxel_sh5 = path.getComputeShader("voxel_light"); |  | ||||||
| 			voxel_ta5 = voxel_sh5.getTextureUnit("voxelsLight"); |  | ||||||
|  |  | ||||||
| 	 		voxel_ca5 = voxel_sh5.getConstantLocation("clipmaps"); |  | ||||||
| 			voxel_cb5 = voxel_sh5.getConstantLocation("clipmapLevel"); |  | ||||||
|  |  | ||||||
| 	 		voxel_cc5 = voxel_sh5.getConstantLocation("lightPos"); |  | ||||||
| 	 		voxel_cd5 = voxel_sh5.getConstantLocation("lightColor"); |  | ||||||
| 	 		voxel_ce5 = voxel_sh5.getConstantLocation("lightType"); |  | ||||||
| 	 		voxel_cf5 = voxel_sh5.getConstantLocation("lightDir"); |  | ||||||
| 	 		voxel_cg5 = voxel_sh5.getConstantLocation("spotData"); |  | ||||||
| 	 		#if rp_shadowmap |  | ||||||
| 	 		voxel_tb5 = voxel_sh5.getTextureUnit("shadowMap"); |  | ||||||
| 	 		voxel_tc5 = voxel_sh5.getTextureUnit("shadowMapSpot"); |  | ||||||
| 	 		voxel_td5 = voxel_sh5.getTextureUnit("shadowMapPoint"); |  | ||||||
|  |  | ||||||
| 	 		voxel_ch5 = voxel_sh5.getConstantLocation("lightShadow"); |  | ||||||
| 	 		voxel_ci5 = voxel_sh5.getConstantLocation("lightProj"); |  | ||||||
| 	 		voxel_cj5 = voxel_sh5.getConstantLocation("LVP"); |  | ||||||
| 	 		voxel_ck5 = voxel_sh5.getConstantLocation("shadowsBias"); |  | ||||||
| 	 		#if lnx_shadowmap_atlas |  | ||||||
| 	 		voxel_cl5 = voxel_sh5.getConstantLocation("index"); |  | ||||||
| 	 		voxel_cm5 = voxel_sh5.getConstantLocation("pointLightDataArray"); |  | ||||||
| 	 		#end |  | ||||||
| 	 		#end |  | ||||||
| 		} | 		} | ||||||
| 		#end | 		#end | ||||||
| 	} | 	} | ||||||
| @ -976,11 +956,11 @@ class Inc { | |||||||
| 		kha.compute.Compute.setTexture(voxel_tc1, rts.get("voxelsOut").image, kha.compute.Access.Write); | 		kha.compute.Compute.setTexture(voxel_tc1, rts.get("voxelsOut").image, kha.compute.Access.Write); | ||||||
| 		#if (rp_voxels == "Voxel GI") | 		#if (rp_voxels == "Voxel GI") | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_td1, rts.get("voxelsOutB").image); | 		kha.compute.Compute.setSampledTexture(voxel_td1, rts.get("voxelsOutB").image); | ||||||
| 		kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsLight").image, kha.compute.Access.Read); | 		kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); | ||||||
| 		kha.compute.Compute.setTexture(voxel_tf1, rts.get("voxelsSDF").image, kha.compute.Access.Write); | 		kha.compute.Compute.setFloat(voxel_cc1, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); | ||||||
| 		#else | 		#else | ||||||
| 		#if lnx_voxelgi_shadows | 		#if lnx_voxelgi_shadows | ||||||
| 		kha.compute.Compute.setTexture(voxel_tf1, rts.get("voxelsSDF").image, kha.compute.Access.Write); | 		kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); | ||||||
| 		#end | 		#end | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| @ -1002,6 +982,8 @@ class Inc { | |||||||
|  |  | ||||||
| 		kha.compute.Compute.setInt(voxel_cb1, iron.RenderPath.clipmapLevel); | 		kha.compute.Compute.setInt(voxel_cb1, iron.RenderPath.clipmapLevel); | ||||||
|  |  | ||||||
|  | 		kha.compute.Compute.setFloat(voxel_cc1, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); | ||||||
|  |  | ||||||
| 		kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); | 		kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -1054,6 +1036,7 @@ class Inc { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	#end | 	#end | ||||||
|  |  | ||||||
| 	#if (rp_voxels == "Voxel AO") | 	#if (rp_voxels == "Voxel AO") | ||||||
| 	public static function resolveAO() { | 	public static function resolveAO() { | ||||||
| 		var rts = path.renderTargets; | 		var rts = path.renderTargets; | ||||||
| @ -1066,13 +1049,20 @@ class Inc { | |||||||
|  |  | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); | 		kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); | 		kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); | ||||||
| 		#if lnx_deferred |  | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); | 		kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); | ||||||
| 		#else |  | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("lbuffer1").image); |  | ||||||
| 		#end |  | ||||||
| 		kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_ao").image, kha.compute.Access.Write); | 		kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_ao").image, kha.compute.Access.Write); | ||||||
|  |  | ||||||
|  | 		kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); | ||||||
|  | 		#if rp_gbuffer2 | ||||||
|  | 		kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); | ||||||
|  | 		#end | ||||||
|  | 		#if lnx_brdf | ||||||
|  | 		kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); | ||||||
|  | 		#end | ||||||
|  | 		#if lnx_radiance | ||||||
|  | 		kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); | ||||||
|  | 		#end | ||||||
|  |  | ||||||
| 		var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); | 		var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); | ||||||
| 		for (i in 0...Main.voxelgiClipmapCount) { | 		for (i in 0...Main.voxelgiClipmapCount) { | ||||||
| 			fa[i * 10] = clipmaps[i].voxelSize; | 			fa[i * 10] = clipmaps[i].voxelSize; | ||||||
| @ -1099,18 +1089,7 @@ class Inc { | |||||||
|  |  | ||||||
| 		kha.compute.Compute.setMatrix(voxel_cb3, m.self); | 		kha.compute.Compute.setMatrix(voxel_cb3, m.self); | ||||||
|  |  | ||||||
| 		var near = camera.data.raw.near_plane; | 		kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); | ||||||
| 		var far = camera.data.raw.far_plane; |  | ||||||
| 		var v = new iron.math.Vec2(); |  | ||||||
| 		v.x = far / (far - near); |  | ||||||
| 		v.y = (-far * near) / (far - near); |  | ||||||
|  |  | ||||||
| 		kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 		kha.compute.Compute.setFloat3(voxel_cd3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); |  | ||||||
| 		var eyeLook = camera.lookWorld().normalize(); |  | ||||||
| 		kha.compute.Compute.setFloat3(voxel_ce3, eyeLook.x, eyeLook.y, eyeLook.z); |  | ||||||
|  |  | ||||||
| 		var width = iron.App.w(); | 		var width = iron.App.w(); | ||||||
| 		var height = iron.App.h(); | 		var height = iron.App.h(); | ||||||
| @ -1125,7 +1104,32 @@ class Inc { | |||||||
| 				width = Std.int(dp * Inc.getSuperSampling()); | 				width = Std.int(dp * Inc.getSuperSampling()); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		kha.compute.Compute.setFloat2(voxel_cf3, width, height); | 		kha.compute.Compute.setFloat2(voxel_cd3, width, height); | ||||||
|  |  | ||||||
|  | 		kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); | ||||||
|  | 		#if lnx_irradiance | ||||||
|  | 		var irradiance = iron.Scene.active.world == null ? | ||||||
|  | 		iron.data.WorldData.getEmptyIrradiance() : | ||||||
|  | 		iron.Scene.active.world.probe.irradiance; | ||||||
|  | 		kha.compute.Compute.setFloats(voxel_cf3, irradiance); | ||||||
|  | 		#end | ||||||
|  | 		#if lnx_radiance | ||||||
|  | 		kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); | ||||||
|  | 		#end | ||||||
|  |  | ||||||
|  | 		#if lnx_envcol | ||||||
|  | 		var x: kha.FastFloat = 0.0; | ||||||
|  | 		var y: kha.FastFloat = 0.0; | ||||||
|  | 		var z: kha.FastFloat = 0.0; | ||||||
|  |  | ||||||
|  | 		if (camera.data.raw.clear_color != null) { | ||||||
|  | 			x = camera.data.raw.clear_color[0]; | ||||||
|  | 			y = camera.data.raw.clear_color[1]; | ||||||
|  | 			z = camera.data.raw.clear_color[2]; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); | ||||||
|  | 		#end | ||||||
|  |  | ||||||
| 		kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); | 		kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); | ||||||
| 	} | 	} | ||||||
| @ -1141,12 +1145,18 @@ class Inc { | |||||||
|  |  | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); | 		kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); | 		kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); | ||||||
| 		#if lnx_deferred |  | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); | 		kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); | ||||||
| 		#else |  | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("lbuffer1").image); |  | ||||||
| 		#end |  | ||||||
| 		kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_diffuse").image, kha.compute.Access.Write); | 		kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_diffuse").image, kha.compute.Access.Write); | ||||||
|  | 		kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); | ||||||
|  | 		#if rp_gbuffer2 | ||||||
|  | 		kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); | ||||||
|  | 		#end | ||||||
|  | 		#if lnx_brdf | ||||||
|  | 		kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); | ||||||
|  | 		#end | ||||||
|  | 		#if lnx_radiance | ||||||
|  | 		kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); | ||||||
|  | 		#end | ||||||
|  |  | ||||||
| 		var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); | 		var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); | ||||||
| 		for (i in 0...Main.voxelgiClipmapCount) { | 		for (i in 0...Main.voxelgiClipmapCount) { | ||||||
| @ -1174,18 +1184,7 @@ class Inc { | |||||||
|  |  | ||||||
| 		kha.compute.Compute.setMatrix(voxel_cb3, m.self); | 		kha.compute.Compute.setMatrix(voxel_cb3, m.self); | ||||||
|  |  | ||||||
| 		var near = camera.data.raw.near_plane; | 		kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); | ||||||
| 		var far = camera.data.raw.far_plane; |  | ||||||
| 		var v = new iron.math.Vec2(); |  | ||||||
| 		v.x = far / (far - near); |  | ||||||
| 		v.y = (-far * near) / (far - near); |  | ||||||
|  |  | ||||||
| 		kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 		kha.compute.Compute.setFloat3(voxel_cd3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); |  | ||||||
| 		var eyeLook = camera.lookWorld().normalize(); |  | ||||||
| 		kha.compute.Compute.setFloat3(voxel_ce3, eyeLook.x, eyeLook.y, eyeLook.z); |  | ||||||
|  |  | ||||||
| 		var width = iron.App.w(); | 		var width = iron.App.w(); | ||||||
| 		var height = iron.App.h(); | 		var height = iron.App.h(); | ||||||
| @ -1200,7 +1199,32 @@ class Inc { | |||||||
| 				width = Std.int(dp * Inc.getSuperSampling()); | 				width = Std.int(dp * Inc.getSuperSampling()); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		kha.compute.Compute.setFloat2(voxel_cf3, width, height); | 		kha.compute.Compute.setFloat2(voxel_cd3, width, height); | ||||||
|  |  | ||||||
|  | 		kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); | ||||||
|  | 		#if lnx_irradiance | ||||||
|  | 		var irradiance = iron.Scene.active.world == null ? | ||||||
|  | 		iron.data.WorldData.getEmptyIrradiance() : | ||||||
|  | 		iron.Scene.active.world.probe.irradiance; | ||||||
|  | 		kha.compute.Compute.setFloats(voxel_cf3, irradiance); | ||||||
|  | 		#end | ||||||
|  | 		#if lnx_radiance | ||||||
|  | 		kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); | ||||||
|  | 		#end | ||||||
|  |  | ||||||
|  | 		#if lnx_envcol | ||||||
|  | 		var x: kha.FastFloat = 0.0; | ||||||
|  | 		var y: kha.FastFloat = 0.0; | ||||||
|  | 		var z: kha.FastFloat = 0.0; | ||||||
|  |  | ||||||
|  | 		if (camera.data.raw.clear_color != null) { | ||||||
|  | 			x = camera.data.raw.clear_color[0]; | ||||||
|  | 			y = camera.data.raw.clear_color[1]; | ||||||
|  | 			z = camera.data.raw.clear_color[2]; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); | ||||||
|  | 		#end | ||||||
|  |  | ||||||
| 		kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); | 		kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); | ||||||
| 	} | 	} | ||||||
| @ -1216,15 +1240,12 @@ class Inc { | |||||||
|  |  | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_ta4, rts.get("voxelsOut").image); | 		kha.compute.Compute.setSampledTexture(voxel_ta4, rts.get("voxelsOut").image); | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_tb4, rts.get("half").image); | 		kha.compute.Compute.setSampledTexture(voxel_tb4, rts.get("half").image); | ||||||
| 		#if lnx_deferred |  | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("gbuffer0").image); | 		kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("gbuffer0").image); | ||||||
| 		#else |  | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("lbuffer1").image); |  | ||||||
| 		#end |  | ||||||
| 		kha.compute.Compute.setSampledTexture(voxel_td4, rts.get("voxelsSDF").image); | 		kha.compute.Compute.setSampledTexture(voxel_td4, rts.get("voxelsSDF").image); | ||||||
| 		kha.compute.Compute.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write); | 		kha.compute.Compute.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write); | ||||||
|  | 		#if rp_gbuffer2 | ||||||
| 		//kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); | 		kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); | ||||||
|  | 		#end | ||||||
|  |  | ||||||
| 		var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); | 		var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); | ||||||
| 		for (i in 0...Main.voxelgiClipmapCount) { | 		for (i in 0...Main.voxelgiClipmapCount) { | ||||||
| @ -1252,18 +1273,7 @@ class Inc { | |||||||
|  |  | ||||||
| 		kha.compute.Compute.setMatrix(voxel_cb4, m.self); | 		kha.compute.Compute.setMatrix(voxel_cb4, m.self); | ||||||
|  |  | ||||||
| 		var near = camera.data.raw.near_plane; | 		kha.compute.Compute.setFloat3(voxel_cc4, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); | ||||||
| 		var far = camera.data.raw.far_plane; |  | ||||||
| 		var v = new iron.math.Vec2(); |  | ||||||
| 		v.x = far / (far - near); |  | ||||||
| 		v.y = (-far * near) / (far - near); |  | ||||||
|  |  | ||||||
| 		kha.compute.Compute.setFloat2(voxel_cc4, v.x, v.y); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 		kha.compute.Compute.setFloat3(voxel_cd4, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); |  | ||||||
| 		var eyeLook = camera.lookWorld().normalize(); |  | ||||||
| 		kha.compute.Compute.setFloat3(voxel_ce4, eyeLook.x, eyeLook.y, eyeLook.z); |  | ||||||
|  |  | ||||||
| 		var width = iron.App.w(); | 		var width = iron.App.w(); | ||||||
| 		var height = iron.App.h(); | 		var height = iron.App.h(); | ||||||
| @ -1278,146 +1288,10 @@ class Inc { | |||||||
| 				width = Std.int(dp * Inc.getSuperSampling()); | 				width = Std.int(dp * Inc.getSuperSampling()); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		kha.compute.Compute.setFloat2(voxel_cf4, width, height); | 		kha.compute.Compute.setFloat2(voxel_cd4, width, height); | ||||||
|  |  | ||||||
| 		kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); | 		kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); | ||||||
| 	} | 	} | ||||||
| 	public static function computeVoxelsLight() { |  | ||||||
| 		var rts = path.renderTargets; |  | ||||||
| 	 	var res = iron.RenderPath.getVoxelRes(); |  | ||||||
| 	 	var camera = iron.Scene.active.camera; |  | ||||||
| 	 	var clipmaps = iron.RenderPath.clipmaps; |  | ||||||
| 	 	var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; |  | ||||||
| 		var lights = iron.Scene.active.lights; |  | ||||||
|  |  | ||||||
| 	 	pointIndex = spotIndex = 0; |  | ||||||
| 	 	for (i in 0...lights.length) { |  | ||||||
| 	 		var l = lights[i]; |  | ||||||
| 	 		if (!l.visible) continue; |  | ||||||
| 	 		path.light = l; |  | ||||||
|  |  | ||||||
| 	 		kha.compute.Compute.setShader(voxel_sh5); |  | ||||||
|  |  | ||||||
| 			kha.compute.Compute.setTexture(voxel_ta5, rts.get("voxelsLight").image, kha.compute.Access.Write); |  | ||||||
|  |  | ||||||
| 			var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); |  | ||||||
| 			for (i in 0...Main.voxelgiClipmapCount) { |  | ||||||
| 				fa[i * 10] = clipmaps[i].voxelSize; |  | ||||||
| 				fa[i * 10 + 1] = clipmaps[i].extents.x; |  | ||||||
| 				fa[i * 10 + 2] = clipmaps[i].extents.y; |  | ||||||
| 				fa[i * 10 + 3] = clipmaps[i].extents.z; |  | ||||||
| 				fa[i * 10 + 4] = clipmaps[i].center.x; |  | ||||||
| 				fa[i * 10 + 5] = clipmaps[i].center.y; |  | ||||||
| 				fa[i * 10 + 6] = clipmaps[i].center.z; |  | ||||||
| 				fa[i * 10 + 7] = clipmaps[i].offset_prev.x; |  | ||||||
| 				fa[i * 10 + 8] = clipmaps[i].offset_prev.y; |  | ||||||
| 				fa[i * 10 + 9] = clipmaps[i].offset_prev.z; |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			kha.compute.Compute.setFloats(voxel_ca5, fa); |  | ||||||
|  |  | ||||||
| 			kha.compute.Compute.setInt(voxel_cb5, iron.RenderPath.clipmapLevel); |  | ||||||
|  |  | ||||||
| 	 		#if rp_shadowmap |  | ||||||
| 	 		if (l.data.raw.type == "sun") { |  | ||||||
| 				#if lnx_shadowmap_atlas |  | ||||||
| 				#if lnx_shadowmap_atlas_single_map |  | ||||||
| 	 			kha.compute.Compute.setSampledTexture(voxel_tb5, rts.get("shadowMapAtlas").image); |  | ||||||
| 	 			#else |  | ||||||
| 	 			kha.compute.Compute.setSampledTexture(voxel_tb5, rts.get("shadowMapAtlasSun").image); |  | ||||||
| 	 			#end |  | ||||||
| 	 			#else |  | ||||||
| 	 			kha.compute.Compute.setSampledTexture(voxel_tb5, rts.get("shadowMap").image); |  | ||||||
| 	 			#end |  | ||||||
| 	 			kha.compute.Compute.setInt(voxel_ch5, 1); // lightShadow |  | ||||||
| 	 		} |  | ||||||
| 	 		else if (l.data.raw.type == "spot" || l.data.raw.type == "area") { |  | ||||||
| 				#if lnx_shadowmap_atlas |  | ||||||
| 				#if lnx_shadowmap_atlas_single_map |  | ||||||
| 	 			kha.compute.Compute.setSampledTexture(voxel_tc5, rts.get("shadowMapAtlas").image); |  | ||||||
| 	 			#else |  | ||||||
| 	 			kha.compute.Compute.setSampledTexture(voxel_tc5, rts.get("shadowMapAtlasSpot").image); |  | ||||||
| 	 			#end |  | ||||||
| 	 			#else |  | ||||||
| 	 			kha.compute.Compute.setSampledTexture(voxel_tc5, rts.get("shadowMapSpot[" + spotIndex + "]").image); |  | ||||||
| 	 			spotIndex++; |  | ||||||
| 	 			#end |  | ||||||
| 	 			kha.compute.Compute.setInt(voxel_ch5, 2); |  | ||||||
| 	 		} |  | ||||||
| 	 		else { |  | ||||||
| 				#if lnx_shadowmap_atlas |  | ||||||
| 				#if lnx_shadowmap_atlas_single_map |  | ||||||
| 				kha.compute.Compute.setSampledTexture(voxel_td5, rts.get("shadowMapAtlas").image); |  | ||||||
| 				#else |  | ||||||
| 				kha.compute.Compute.setSampledTexture(voxel_td5, rts.get("shadowMapAtlasPoint").image); |  | ||||||
| 				kha.compute.Compute.setInt(voxel_cl5, i); |  | ||||||
| 				kha.compute.Compute.setFloats(voxel_cm5, iron.object.LightObject.pointLightsData); |  | ||||||
| 				#end |  | ||||||
| 				#else |  | ||||||
| 	 			kha.compute.Compute.setSampledCubeMap(voxel_td5, rts.get("shadowMapPoint[" + pointIndex + "]").cubeMap); |  | ||||||
| 	 			pointIndex++; |  | ||||||
| 	 			#end |  | ||||||
| 	 			kha.compute.Compute.setInt(voxel_ch5, 3); |  | ||||||
| 	 		} |  | ||||||
|  |  | ||||||
| 	 		// lightProj |  | ||||||
| 	 		var near = l.data.raw.near_plane; |  | ||||||
| 	 		var far = l.data.raw.far_plane; |  | ||||||
| 	 		var a:kha.FastFloat = far + near; |  | ||||||
| 	 		var b:kha.FastFloat = far - near; |  | ||||||
| 	 		var f2:kha.FastFloat = 2.0; |  | ||||||
| 	 		var c:kha.FastFloat = f2 * far * near; |  | ||||||
| 	 		var vx:kha.FastFloat = a / b; |  | ||||||
| 	 		var vy:kha.FastFloat = c / b; |  | ||||||
| 	 		kha.compute.Compute.setFloat2(voxel_ci5, vx, vy); |  | ||||||
| 	 		// LVP |  | ||||||
| 	 		m.setFrom(l.VP); |  | ||||||
| 	 		m.multmat(iron.object.Uniforms.biasMat); |  | ||||||
| 	 		#if lnx_shadowmap_atlas |  | ||||||
| 			if (l.data.raw.type == "sun") |  | ||||||
| 			{ |  | ||||||
| 				// tile matrix |  | ||||||
| 				m.setIdentity(); |  | ||||||
| 				// scale [0-1] coords to [0-tilescale] |  | ||||||
| 				m2._00 = l.tileScale[0]; |  | ||||||
| 				m2._11 = l.tileScale[0]; |  | ||||||
| 				// offset coordinate start from [0, 0] to [tile-start-x, tile-start-y] |  | ||||||
| 				m2._30 = l.tileOffsetX[0]; |  | ||||||
| 				m2._31 = l.tileOffsetY[0]; |  | ||||||
| 				m.multmat(m2); |  | ||||||
| 				#if (!kha_opengl) |  | ||||||
| 				m2.setIdentity(); |  | ||||||
| 				m2._11 = -1.0; |  | ||||||
| 				m2._31 = 1.0; |  | ||||||
| 				m.multmat(m2); |  | ||||||
| 				#end |  | ||||||
| 			} |  | ||||||
| 			#end |  | ||||||
| 	 		kha.compute.Compute.setMatrix(voxel_cj5, m.self); |  | ||||||
| 	 		// shadowsBias |  | ||||||
| 	 		kha.compute.Compute.setFloat(voxel_ck5, l.data.raw.shadows_bias); |  | ||||||
| 			#end // rp_shadowmap |  | ||||||
|  |  | ||||||
| 	 		// lightPos |  | ||||||
| 	 		kha.compute.Compute.setFloat3(voxel_cc5, l.transform.worldx(), l.transform.worldy(), l.transform.worldz()); |  | ||||||
| 	 		// lightCol |  | ||||||
| 	 		var f = l.data.raw.strength; |  | ||||||
| 	 		kha.compute.Compute.setFloat3(voxel_cd5, l.data.raw.color[0] * f, l.data.raw.color[1] * f, l.data.raw.color[2] * f); |  | ||||||
| 	 		// lightType |  | ||||||
| 	 		kha.compute.Compute.setInt(voxel_ce5, iron.data.LightData.typeToInt(l.data.raw.type)); |  | ||||||
| 	 		// lightDir |  | ||||||
| 	 		var v = l.look(); |  | ||||||
| 	 		kha.compute.Compute.setFloat3(voxel_cf5, v.x, v.y, v.z); |  | ||||||
| 	 		// spotData |  | ||||||
| 	 		if (l.data.raw.type == "spot") { |  | ||||||
| 	 			var vx = l.data.raw.spot_size; |  | ||||||
| 	 			var vy = vx - l.data.raw.spot_blend; |  | ||||||
| 	 			kha.compute.Compute.setFloat2(voxel_cg5, vx, vy); |  | ||||||
| 	 		} |  | ||||||
|  |  | ||||||
| 	 		kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	#end // GI | 	#end // GI | ||||||
| 	#end // Voxels | 	#end // Voxels | ||||||
| } | } | ||||||
|  | |||||||
| @ -15,6 +15,11 @@ class RenderPathDeferred { | |||||||
| 	static var bloomUpsampler: Upsampler; | 	static var bloomUpsampler: Upsampler; | ||||||
| 	#end | 	#end | ||||||
|  |  | ||||||
|  | 	#if (rp_ssgi == "SSGI") | ||||||
|  | 	static var ssgitex = "singleb"; | ||||||
|  | 	static var ssgitexb = "singleb"; | ||||||
|  | 	#end | ||||||
|  |  | ||||||
| 	public static inline function setTargetMeshes() { | 	public static inline function setTargetMeshes() { | ||||||
| 		//Always keep the order of render targets the same as defined in compiled.inc | 		//Always keep the order of render targets the same as defined in compiled.inc | ||||||
| 		path.setTarget("gbuffer0", [ | 		path.setTarget("gbuffer0", [ | ||||||
| @ -57,12 +62,11 @@ class RenderPathDeferred { | |||||||
| 			Inc.initGI("voxels"); | 			Inc.initGI("voxels"); | ||||||
| 			Inc.initGI("voxelsOut"); | 			Inc.initGI("voxelsOut"); | ||||||
| 			Inc.initGI("voxelsOutB"); | 			Inc.initGI("voxelsOutB"); | ||||||
| 			#if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") | 			#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) | ||||||
| 			Inc.initGI("voxelsSDF"); | 			Inc.initGI("voxelsSDF"); | ||||||
| 			Inc.initGI("voxelsSDFtmp"); | 			Inc.initGI("voxelsSDFtmp"); | ||||||
| 			#end | 			#end | ||||||
| 			#if (rp_voxels == "Voxel GI") | 			#if (rp_voxels == "Voxel GI") | ||||||
| 			Inc.initGI("voxelsLight"); |  | ||||||
| 			Inc.initGI("voxels_diffuse"); | 			Inc.initGI("voxels_diffuse"); | ||||||
| 			Inc.initGI("voxels_specular"); | 			Inc.initGI("voxels_specular"); | ||||||
| 			#else | 			#else | ||||||
| @ -195,24 +199,94 @@ class RenderPathDeferred { | |||||||
| 			path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); | 			path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); | ||||||
| 			path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); | 			path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); | ||||||
| 		} | 		} | ||||||
|  | 		#elseif (rp_ssgi == "SSGI") | ||||||
|  | 		{ | ||||||
|  | 			path.loadShader("shader_datas/ssgi_pass/ssgi_pass"); | ||||||
|  | 			path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); | ||||||
|  | 			path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); | ||||||
|  | 		} | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| 		#if ((rp_ssgi != "Off") || rp_volumetriclight) | 		#if (rp_ssgi != "Off") | ||||||
| 		{ | 		{ | ||||||
| 			var t = new RenderTargetRaw(); | 			var t = new RenderTargetRaw(); | ||||||
| 			t.name = "singlea"; | 			t.name = "singlea"; | ||||||
| 			t.width = 0; | 			t.width = 0; | ||||||
| 			t.height = 0; | 			t.height = 0; | ||||||
| 			t.displayp = Inc.getDisplayp(); | 			t.displayp = Inc.getDisplayp(); | ||||||
|  | 			#if (rp_ssgi == "SSGI") | ||||||
|  | 			t.format = "RGBA32"; | ||||||
|  | 			#else | ||||||
|  | 			t.format = "R8"; | ||||||
|  | 			#end | ||||||
|  | 			t.scale = Inc.getSuperSampling(); | ||||||
|  | 			#if rp_ssgi_half | ||||||
|  | 			t.scale *= 0.5; | ||||||
|  | 			#end | ||||||
|  | 			path.createRenderTarget(t); | ||||||
|  |  | ||||||
|  | 			var t = new RenderTargetRaw(); | ||||||
|  | 			t.name = "singleb"; | ||||||
|  | 			t.width = 0; | ||||||
|  | 			t.height = 0; | ||||||
|  | 			t.displayp = Inc.getDisplayp(); | ||||||
|  | 			#if (rp_ssgi == "SSGI") | ||||||
|  | 			t.format = "RGBA32"; | ||||||
|  | 			#else | ||||||
|  | 			t.format = "R8"; | ||||||
|  | 			#end | ||||||
|  | 			t.scale = Inc.getSuperSampling(); | ||||||
|  | 			#if rp_ssgi_half | ||||||
|  | 			t.scale *= 0.5; | ||||||
|  | 			#end | ||||||
|  | 			path.createRenderTarget(t); | ||||||
|  | 		} | ||||||
|  | 		#end | ||||||
|  |  | ||||||
|  | 		#if rp_volumetriclight | ||||||
|  | 		{ | ||||||
|  | 			var t = new RenderTargetRaw(); | ||||||
|  | 			t.name = "volumetrica"; | ||||||
|  | 			t.width = 0; | ||||||
|  | 			t.height = 0; | ||||||
|  | 			t.displayp = Inc.getDisplayp(); | ||||||
|  | 			t.format = "R8"; | ||||||
|  | 			t.scale = Inc.getSuperSampling(); | ||||||
|  | 			#if rp_ssgi_half // Do we keep this ? | ||||||
|  | 			t.scale *= 0.5; | ||||||
|  | 			#end | ||||||
|  | 			path.createRenderTarget(t); | ||||||
|  |  | ||||||
|  | 			var t = new RenderTargetRaw(); | ||||||
|  | 			t.name = "volumetricb"; | ||||||
|  | 			t.width = 0; | ||||||
|  | 			t.height = 0; | ||||||
|  | 			t.displayp = Inc.getDisplayp(); | ||||||
| 			t.format = "R8"; | 			t.format = "R8"; | ||||||
| 			t.scale = Inc.getSuperSampling(); | 			t.scale = Inc.getSuperSampling(); | ||||||
| 			#if rp_ssgi_half | 			#if rp_ssgi_half | ||||||
| 			t.scale *= 0.5; | 			t.scale *= 0.5; | ||||||
| 			#end | 			#end | ||||||
| 			path.createRenderTarget(t); | 			path.createRenderTarget(t); | ||||||
|  | 		} | ||||||
|  | 		#end | ||||||
|  |  | ||||||
|  | 		#if rp_volumetriclight | ||||||
|  | 		{ | ||||||
|  | 			var t = new RenderTargetRaw(); | ||||||
|  | 			t.name = "volumetrica"; | ||||||
|  | 			t.width = 0; | ||||||
|  | 			t.height = 0; | ||||||
|  | 			t.displayp = Inc.getDisplayp(); | ||||||
|  | 			t.format = "R8"; | ||||||
|  | 			t.scale = Inc.getSuperSampling(); | ||||||
|  | 			#if rp_ssgi_half // Do we keep this ? | ||||||
|  | 			t.scale *= 0.5; | ||||||
|  | 			#end | ||||||
|  | 			path.createRenderTarget(t); | ||||||
|  |  | ||||||
| 			var t = new RenderTargetRaw(); | 			var t = new RenderTargetRaw(); | ||||||
| 			t.name = "singleb"; | 			t.name = "volumetricb"; | ||||||
| 			t.width = 0; | 			t.width = 0; | ||||||
| 			t.height = 0; | 			t.height = 0; | ||||||
| 			t.displayp = Inc.getDisplayp(); | 			t.displayp = Inc.getDisplayp(); | ||||||
| @ -368,7 +442,7 @@ class RenderPathDeferred { | |||||||
| 			t.scale = Inc.getSuperSampling(); | 			t.scale = Inc.getSuperSampling(); | ||||||
| 			path.createRenderTarget(t); | 			path.createRenderTarget(t); | ||||||
|  |  | ||||||
| 			// holds background depth | 			// holds background color | ||||||
| 			var t = new RenderTargetRaw(); | 			var t = new RenderTargetRaw(); | ||||||
| 			t.name = "refr"; | 			t.name = "refr"; | ||||||
| 			t.width = 0; | 			t.width = 0; | ||||||
| @ -461,7 +535,7 @@ class RenderPathDeferred { | |||||||
|  |  | ||||||
| 		#if (rp_ssrefr || lnx_voxelgi_refract) | 		#if (rp_ssrefr || lnx_voxelgi_refract) | ||||||
| 		{ | 		{ | ||||||
| 			path.setTarget("gbuffer_refraction"); // Only clear gbuffer0 | 			path.setTarget("gbuffer_refraction"); | ||||||
| 			path.clearTarget(0xffffff00); | 			path.clearTarget(0xffffff00); | ||||||
| 		} | 		} | ||||||
| 		#end | 		#end | ||||||
| @ -517,30 +591,16 @@ class RenderPathDeferred { | |||||||
| 		path.drawShader("shader_datas/downsample_depth/downsample_depth"); | 		path.drawShader("shader_datas/downsample_depth/downsample_depth"); | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| 		#if ((rp_ssgi == "RTGI") || (rp_ssgi == "RTAO")) | 		#if (rp_shadowmap) | ||||||
| 		{ | 		// atlasing is exclusive for now | ||||||
| 			if (leenkx.data.Config.raw.rp_ssgi != false) { | 		#if lnx_shadowmap_atlas | ||||||
| 				path.setTarget("singlea"); | 		Inc.drawShadowMapAtlas(); | ||||||
| 				#if rp_ssgi_half | 		#else | ||||||
| 				path.bindTarget("half", "gbufferD"); | 		Inc.drawShadowMap(); | ||||||
| 				#else | 		#end | ||||||
| 				path.bindTarget("_main", "gbufferD"); | 		#end | ||||||
| 				#end |  | ||||||
| 				path.bindTarget("gbuffer0", "gbuffer0"); |  | ||||||
| 				path.drawShader("shader_datas/ssgi_pass/ssgi_pass"); |  | ||||||
|  |  | ||||||
| 				path.setTarget("singleb"); | 		#if (rp_ssgi == "SSAO") | ||||||
| 				path.bindTarget("singlea", "tex"); |  | ||||||
| 				path.bindTarget("gbuffer0", "gbuffer0"); |  | ||||||
| 				path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); |  | ||||||
|  |  | ||||||
| 				path.setTarget("singlea"); |  | ||||||
| 				path.bindTarget("singleb", "tex"); |  | ||||||
| 				path.bindTarget("gbuffer0", "gbuffer0"); |  | ||||||
| 				path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		#elseif (rp_ssgi == "SSAO") |  | ||||||
| 		{ | 		{ | ||||||
| 			if (leenkx.data.Config.raw.rp_ssgi != false) { | 			if (leenkx.data.Config.raw.rp_ssgi != false) { | ||||||
| 				path.setTarget("singlea"); | 				path.setTarget("singlea"); | ||||||
| @ -559,15 +619,43 @@ class RenderPathDeferred { | |||||||
| 				path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); | 				path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		#end | 		#elseif (rp_ssgi == "SSGI") | ||||||
|  | 		{ | ||||||
|  | 			if (leenkx.data.Config.raw.rp_ssgi != false) { | ||||||
|  | 				path.setTarget("singlea"); | ||||||
|  | 				path.bindTarget("_main", "gbufferD"); | ||||||
|  | 				path.bindTarget("gbuffer0", "gbuffer0"); | ||||||
|  | 				path.bindTarget("gbuffer1", "gbuffer1"); | ||||||
|  | 				#if rp_gbuffer_emission | ||||||
|  | 				{ | ||||||
|  | 					path.bindTarget("gbuffer_emission", "gbufferEmission"); | ||||||
|  | 				} | ||||||
|  | 				#end | ||||||
|  | 				#if rp_gbuffer2 | ||||||
|  | 				path.bindTarget("gbuffer2", "sveloc"); | ||||||
|  | 				#end | ||||||
|  | 				#if rp_shadowmap | ||||||
|  | 				{ | ||||||
|  | 					#if lnx_shadowmap_atlas | ||||||
|  | 					Inc.bindShadowMapAtlas(); | ||||||
|  | 					#else | ||||||
|  | 					Inc.bindShadowMap(); | ||||||
|  | 					#end | ||||||
|  | 				} | ||||||
|  | 				#end | ||||||
|  |  | ||||||
| 		#if (rp_shadowmap) | 				path.drawShader("shader_datas/ssgi_pass/ssgi_pass"); | ||||||
| 		// atlasing is exclusive for now | 				path.setTarget("singleb"); | ||||||
| 		#if lnx_shadowmap_atlas | 				path.bindTarget("singlea", "tex"); | ||||||
| 		Inc.drawShadowMapAtlas(); | 				path.bindTarget("gbuffer0", "gbuffer0"); | ||||||
| 		#else | 				path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); | ||||||
| 		Inc.drawShadowMap(); |  | ||||||
| 		#end | 				path.setTarget("singlea"); | ||||||
|  | 				path.bindTarget("singleb", "tex"); | ||||||
|  | 				path.bindTarget("gbuffer0", "gbuffer0"); | ||||||
|  | 				path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| 		// Voxels | 		// Voxels | ||||||
| @ -580,9 +668,6 @@ class RenderPathDeferred { | |||||||
|  |  | ||||||
| 			if (iron.RenderPath.pre_clear == true) | 			if (iron.RenderPath.pre_clear == true) | ||||||
| 			{ | 			{ | ||||||
| 				#if (rp_voxels == "Voxel GI") |  | ||||||
| 				path.clearImage("voxelsLight", 0x00000000); |  | ||||||
| 				#end |  | ||||||
| 				path.clearImage("voxels", 0x00000000); | 				path.clearImage("voxels", 0x00000000); | ||||||
| 				path.clearImage("voxelsOut", 0x00000000); | 				path.clearImage("voxelsOut", 0x00000000); | ||||||
| 				path.clearImage("voxelsOutB", 0x00000000); | 				path.clearImage("voxelsOutB", 0x00000000); | ||||||
| @ -594,26 +679,30 @@ class RenderPathDeferred { | |||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				#if (rp_voxels == "Voxel GI") |  | ||||||
| 				path.clearImage("voxelsLight", 0x00000000); |  | ||||||
| 				#end |  | ||||||
| 				path.clearImage("voxels", 0x00000000); | 				path.clearImage("voxels", 0x00000000); | ||||||
| 				Inc.computeVoxelsOffsetPrev(); | 				Inc.computeVoxelsOffsetPrev(); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			path.setTarget(""); | 			path.setTarget(""); | ||||||
|  | 			path.bindTarget("voxels", "voxels"); | ||||||
|  | 			#if rp_shadowmap | ||||||
|  | 			{ | ||||||
|  | 				#if lnx_shadowmap_atlas | ||||||
|  | 				Inc.bindShadowMapAtlas(); | ||||||
|  | 				#else | ||||||
|  | 				Inc.bindShadowMap(); | ||||||
|  | 				#end | ||||||
|  | 			} | ||||||
|  | 			#end | ||||||
|  |  | ||||||
| 			var res = iron.RenderPath.getVoxelRes(); | 			var res = iron.RenderPath.getVoxelRes(); | ||||||
| 			path.setViewport(res, res); | 			path.setViewport(res, res); | ||||||
|  |  | ||||||
| 			path.bindTarget("voxels", "voxels"); |  | ||||||
| 			path.drawMeshes("voxel"); | 			path.drawMeshes("voxel"); | ||||||
| 			#if (rp_voxels == "Voxel GI") |  | ||||||
| 			Inc.computeVoxelsLight(); |  | ||||||
| 			#end |  | ||||||
|  |  | ||||||
| 			Inc.computeVoxelsTemporal(); | 			Inc.computeVoxelsTemporal(); | ||||||
|  |  | ||||||
| 			#if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") | 			#if (rp_voxels == "Voxel GI") | ||||||
| 			Inc.computeVoxelsSDF(); | 			Inc.computeVoxelsSDF(); | ||||||
| 			#end | 			#end | ||||||
|  |  | ||||||
| @ -628,7 +717,6 @@ class RenderPathDeferred { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| 		// --- | 		// --- | ||||||
| 		// Deferred light | 		// Deferred light | ||||||
| 		// --- | 		// --- | ||||||
| @ -760,15 +848,9 @@ class RenderPathDeferred { | |||||||
| 		} | 		} | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| 		#if (rp_translucency && !rp_ssrefr) |  | ||||||
| 		{ |  | ||||||
| 			Inc.drawTranslucency("tex"); |  | ||||||
| 		} |  | ||||||
| 		#end |  | ||||||
|  |  | ||||||
| 		#if rp_volumetriclight | 		#if rp_volumetriclight | ||||||
| 		{ | 		{ | ||||||
| 			path.setTarget("singlea"); | 			path.setTarget("volumetrica"); | ||||||
| 			path.bindTarget("_main", "gbufferD"); | 			path.bindTarget("_main", "gbufferD"); | ||||||
| 			#if lnx_shadowmap_atlas | 			#if lnx_shadowmap_atlas | ||||||
| 			Inc.bindShadowMapAtlas(); | 			Inc.bindShadowMapAtlas(); | ||||||
| @ -777,85 +859,16 @@ class RenderPathDeferred { | |||||||
| 			#end | 			#end | ||||||
| 			path.drawShader("shader_datas/volumetric_light/volumetric_light"); | 			path.drawShader("shader_datas/volumetric_light/volumetric_light"); | ||||||
|  |  | ||||||
| 			path.setTarget("singleb"); | 			path.setTarget("volumetricb"); | ||||||
| 			path.bindTarget("singlea", "tex"); | 			path.bindTarget("volumetrica", "tex"); | ||||||
| 			path.drawShader("shader_datas/blur_bilat_pass/blur_bilat_pass_x"); | 			path.drawShader("shader_datas/blur_bilat_pass/blur_bilat_pass_x"); | ||||||
|  |  | ||||||
| 			path.setTarget("tex"); | 			path.setTarget("tex"); | ||||||
| 			path.bindTarget("singleb", "tex"); | 			path.bindTarget("volumetricb", "tex"); | ||||||
| 			path.drawShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y"); | 			path.drawShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y"); | ||||||
| 		} | 		} | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| 		#if rp_bloom |  | ||||||
| 		{ |  | ||||||
| 			inline Inc.drawBloom("tex", bloomDownsampler, bloomUpsampler); |  | ||||||
| 		} |  | ||||||
| 		#end |  | ||||||
|  |  | ||||||
| 		#if rp_sss |  | ||||||
| 		{ |  | ||||||
| 			#if (!kha_opengl) |  | ||||||
| 			path.setDepthFrom("tex", "gbuffer1"); // Unbind depth so we can read it |  | ||||||
| 			#end |  | ||||||
|  |  | ||||||
| 			path.setTarget("buf"); |  | ||||||
| 			path.bindTarget("tex", "tex"); |  | ||||||
| 			path.bindTarget("_main", "gbufferD"); |  | ||||||
| 			path.bindTarget("gbuffer0", "gbuffer0"); |  | ||||||
| 			path.drawShader("shader_datas/sss_pass/sss_pass_x"); |  | ||||||
|  |  | ||||||
| 			path.setTarget("tex"); |  | ||||||
| 			path.bindTarget("buf", "tex"); |  | ||||||
| 			path.bindTarget("_main", "gbufferD"); |  | ||||||
| 			path.bindTarget("gbuffer0", "gbuffer0"); |  | ||||||
| 			path.drawShader("shader_datas/sss_pass/sss_pass_y"); |  | ||||||
|  |  | ||||||
| 			#if (!kha_opengl) |  | ||||||
| 			path.setDepthFrom("tex", "gbuffer0"); |  | ||||||
| 			#end |  | ||||||
| 		} |  | ||||||
| 		#end |  | ||||||
|  |  | ||||||
| 		#if rp_ssrefr |  | ||||||
| 		{ |  | ||||||
| 			if (leenkx.data.Config.raw.rp_ssrefr != false) |  | ||||||
| 			{ |  | ||||||
| 				//save depth |  | ||||||
| 				path.setTarget("gbufferD1"); |  | ||||||
| 				path.bindTarget("_main", "tex"); |  | ||||||
| 				path.drawShader("shader_datas/copy_pass/copy_pass"); |  | ||||||
|  |  | ||||||
| 				//save background color |  | ||||||
| 				path.setTarget("refr"); |  | ||||||
| 				path.bindTarget("tex", "tex"); |  | ||||||
| 				path.drawShader("shader_datas/copy_pass/copy_pass"); |  | ||||||
|  |  | ||||||
| 				path.setTarget("gbuffer0", ["tex", "gbuffer_refraction"]); |  | ||||||
|  |  | ||||||
| 				#if (rp_voxels != "Off") |  | ||||||
| 				{ |  | ||||||
| 					path.bindTarget("voxelsOut", "voxels"); |  | ||||||
| 					path.bindTarget("voxelsSDF", "voxelsSDF"); |  | ||||||
| 					path.bindTarget("gbuffer2", "sveloc"); |  | ||||||
| 				} |  | ||||||
| 				#end |  | ||||||
|  |  | ||||||
| 				path.drawMeshes("refraction"); |  | ||||||
|  |  | ||||||
| 				path.setTarget("tex"); |  | ||||||
| 				path.bindTarget("tex", "tex"); |  | ||||||
| 				path.bindTarget("refr", "tex1"); |  | ||||||
| 				path.bindTarget("_main", "gbufferD"); |  | ||||||
| 				path.bindTarget("gbufferD1", "gbufferD1"); |  | ||||||
| 				path.bindTarget("gbuffer0", "gbuffer0"); |  | ||||||
| 				path.bindTarget("gbuffer_refraction", "gbuffer_refraction"); |  | ||||||
|  |  | ||||||
| 				path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass"); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		#end |  | ||||||
|  |  | ||||||
| 		#if rp_ssr | 		#if rp_ssr | ||||||
| 		{ | 		{ | ||||||
| 			if (leenkx.data.Config.raw.rp_ssr != false) { | 			if (leenkx.data.Config.raw.rp_ssr != false) { | ||||||
| @ -900,6 +913,88 @@ class RenderPathDeferred { | |||||||
| 		} | 		} | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
|  | 		#if rp_sss | ||||||
|  | 		{ | ||||||
|  | 			#if (!kha_opengl) | ||||||
|  | 			path.setDepthFrom("tex", "gbuffer1"); // Unbind depth so we can read it | ||||||
|  | 			#end | ||||||
|  |  | ||||||
|  | 			path.setTarget("buf"); | ||||||
|  | 			path.bindTarget("tex", "tex"); | ||||||
|  | 			path.bindTarget("_main", "gbufferD"); | ||||||
|  | 			path.bindTarget("gbuffer0", "gbuffer0"); | ||||||
|  | 			path.drawShader("shader_datas/sss_pass/sss_pass_x"); | ||||||
|  |  | ||||||
|  | 			path.setTarget("tex"); | ||||||
|  | 			path.bindTarget("buf", "tex"); | ||||||
|  | 			path.bindTarget("_main", "gbufferD"); | ||||||
|  | 			path.bindTarget("gbuffer0", "gbuffer0"); | ||||||
|  | 			path.drawShader("shader_datas/sss_pass/sss_pass_y"); | ||||||
|  |  | ||||||
|  | 			#if (!kha_opengl) | ||||||
|  | 			path.setDepthFrom("tex", "gbuffer0"); | ||||||
|  | 			#end | ||||||
|  | 		} | ||||||
|  | 		#end | ||||||
|  |  | ||||||
|  | 		#if (rp_translucency && !rp_ssrefr) | ||||||
|  | 		{ | ||||||
|  | 			Inc.drawTranslucency("tex"); | ||||||
|  | 		} | ||||||
|  | 		#end | ||||||
|  |  | ||||||
|  | 		#if rp_ssrefr | ||||||
|  | 		{ | ||||||
|  | 			if (leenkx.data.Config.raw.rp_ssrefr != false) | ||||||
|  | 			{ | ||||||
|  | 				//save depth | ||||||
|  | 				path.setTarget("gbufferD1"); | ||||||
|  | 				path.bindTarget("_main", "tex"); | ||||||
|  | 				path.drawShader("shader_datas/copy_pass/copy_pass"); | ||||||
|  |  | ||||||
|  | 				//save background color | ||||||
|  | 				path.setTarget("refr"); | ||||||
|  | 				path.bindTarget("tex", "tex"); | ||||||
|  | 				path.drawShader("shader_datas/copy_pass/copy_pass"); | ||||||
|  |  | ||||||
|  | 				path.setTarget("gbuffer0", ["tex", "gbuffer_refraction"]); | ||||||
|  |  | ||||||
|  | 				#if rp_shadowmap | ||||||
|  | 				{ | ||||||
|  | 					#if lnx_shadowmap_atlas | ||||||
|  | 					Inc.bindShadowMapAtlas(); | ||||||
|  | 					#else | ||||||
|  | 					Inc.bindShadowMap(); | ||||||
|  | 					#end | ||||||
|  | 				} | ||||||
|  | 				#end | ||||||
|  |  | ||||||
|  | 				#if (rp_voxels != "Off") | ||||||
|  | 				path.bindTarget("voxelsOut", "voxels"); | ||||||
|  | 				#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) | ||||||
|  | 				path.bindTarget("voxelsSDF", "voxelsSDF"); | ||||||
|  | 				#end | ||||||
|  | 				#end | ||||||
|  |  | ||||||
|  | 				#if rp_ssrs | ||||||
|  | 				path.bindTarget("_main", "gbufferD"); | ||||||
|  | 				#end | ||||||
|  |  | ||||||
|  | 				path.drawMeshes("refraction"); | ||||||
|  |  | ||||||
|  | 				path.setTarget("tex"); | ||||||
|  | 				path.bindTarget("tex", "tex"); | ||||||
|  | 				path.bindTarget("refr", "tex1"); | ||||||
|  | 				path.bindTarget("_main", "gbufferD"); | ||||||
|  | 				path.bindTarget("gbufferD1", "gbufferD1"); | ||||||
|  | 				path.bindTarget("gbuffer0", "gbuffer0"); | ||||||
|  | 				path.bindTarget("gbuffer_refraction", "gbuffer_refraction"); | ||||||
|  |  | ||||||
|  | 				path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		#end | ||||||
|  |  | ||||||
| 		#if ((rp_motionblur == "Camera") || (rp_motionblur == "Object")) | 		#if ((rp_motionblur == "Camera") || (rp_motionblur == "Object")) | ||||||
| 		{ | 		{ | ||||||
| 			if (leenkx.data.Config.raw.rp_motionblur != false) { | 			if (leenkx.data.Config.raw.rp_motionblur != false) { | ||||||
| @ -964,6 +1059,12 @@ class RenderPathDeferred { | |||||||
| 		} | 		} | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
|  | 		#if rp_bloom | ||||||
|  | 		{ | ||||||
|  | 			inline Inc.drawBloom("tex", bloomDownsampler, bloomUpsampler); | ||||||
|  | 		} | ||||||
|  | 		#end | ||||||
|  |  | ||||||
| 		#if (rp_supersampling == 4) | 		#if (rp_supersampling == 4) | ||||||
| 		var framebuffer = "buf"; | 		var framebuffer = "buf"; | ||||||
| 		#else | 		#else | ||||||
|  | |||||||
| @ -142,16 +142,17 @@ class RenderPathForward { | |||||||
| 				t.width = 0; | 				t.width = 0; | ||||||
| 				t.height = 0; | 				t.height = 0; | ||||||
| 				t.displayp = Inc.getDisplayp(); | 				t.displayp = Inc.getDisplayp(); | ||||||
| 				t.format = "R32"; | 				t.format = "DEPTH24"; | ||||||
| 				t.scale = Inc.getSuperSampling(); | 				t.scale = Inc.getSuperSampling(); | ||||||
| 				path.createRenderTarget(t); | 				path.createRenderTarget(t); | ||||||
|  |  | ||||||
|  | 				//holds colors before refractive meshes are drawn | ||||||
| 				var t = new RenderTargetRaw(); | 				var t = new RenderTargetRaw(); | ||||||
| 				t.name = "refr"; | 				t.name = "refr"; | ||||||
| 				t.width = 0; | 				t.width = 0; | ||||||
| 				t.height = 0; | 				t.height = 0; | ||||||
| 				t.displayp = Inc.getDisplayp(); | 				t.displayp = Inc.getDisplayp(); | ||||||
| 				t.format = "RGBA64"; | 				t.format = Inc.getHdrFormat(); | ||||||
| 				t.scale = Inc.getSuperSampling(); | 				t.scale = Inc.getSuperSampling(); | ||||||
| 				path.createRenderTarget(t); | 				path.createRenderTarget(t); | ||||||
| 			} | 			} | ||||||
| @ -200,17 +201,10 @@ class RenderPathForward { | |||||||
| 			Inc.initGI("voxels"); | 			Inc.initGI("voxels"); | ||||||
| 			Inc.initGI("voxelsOut"); | 			Inc.initGI("voxelsOut"); | ||||||
| 			Inc.initGI("voxelsOutB"); | 			Inc.initGI("voxelsOutB"); | ||||||
| 			#if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) | 			#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) | ||||||
| 			Inc.initGI("voxelsSDF"); | 			Inc.initGI("voxelsSDF"); | ||||||
| 			Inc.initGI("voxelsSDFtmp"); | 			Inc.initGI("voxelsSDFtmp"); | ||||||
| 			#end | 			#end | ||||||
| 			#if (rp_voxels == "Voxel GI") |  | ||||||
| 			Inc.initGI("voxelsLight"); |  | ||||||
| 			Inc.initGI("voxels_diffuse"); |  | ||||||
| 			Inc.initGI("voxels_specular"); |  | ||||||
| 			#else |  | ||||||
| 			Inc.initGI("voxels_ao"); |  | ||||||
| 			#end |  | ||||||
| 			iron.RenderPath.clipmaps = new Array<Clipmap>(); | 			iron.RenderPath.clipmaps = new Array<Clipmap>(); | ||||||
| 			for (i in 0...Main.voxelgiClipmapCount) { | 			for (i in 0...Main.voxelgiClipmapCount) { | ||||||
| 				var clipmap = new iron.object.Clipmap(); | 				var clipmap = new iron.object.Clipmap(); | ||||||
| @ -257,18 +251,25 @@ class RenderPathForward { | |||||||
| 			#end | 			#end | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| 		#if rp_volumetriclight | 		#if (rp_volumetriclight || rp_ssgi != "Off") | ||||||
| 		{ | 		{ | ||||||
|  | 			#if (rp_volumetriclight) | ||||||
| 			path.loadShader("shader_datas/volumetric_light/volumetric_light"); | 			path.loadShader("shader_datas/volumetric_light/volumetric_light"); | ||||||
| 			path.loadShader("shader_datas/blur_bilat_pass/blur_bilat_pass_x"); | 			path.loadShader("shader_datas/blur_bilat_pass/blur_bilat_pass_x"); | ||||||
| 			path.loadShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y"); | 			path.loadShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y"); | ||||||
|  | 			#end | ||||||
|  |  | ||||||
|  |  | ||||||
| 			var t = new RenderTargetRaw(); | 			var t = new RenderTargetRaw(); | ||||||
| 			t.name = "singlea"; | 			t.name = "singlea"; | ||||||
| 			t.width = 0; | 			t.width = 0; | ||||||
| 			t.height = 0; | 			t.height = 0; | ||||||
| 			t.displayp = Inc.getDisplayp(); | 			t.displayp = Inc.getDisplayp(); | ||||||
|  | 			#if (rp_ssgi == "SSGI") | ||||||
|  | 			t.format = "RGBA32"; | ||||||
|  | 			#else | ||||||
| 			t.format = "R8"; | 			t.format = "R8"; | ||||||
|  | 			#end | ||||||
| 			t.scale = Inc.getSuperSampling(); | 			t.scale = Inc.getSuperSampling(); | ||||||
| 			path.createRenderTarget(t); | 			path.createRenderTarget(t); | ||||||
|  |  | ||||||
| @ -277,7 +278,11 @@ class RenderPathForward { | |||||||
| 			t.width = 0; | 			t.width = 0; | ||||||
| 			t.height = 0; | 			t.height = 0; | ||||||
| 			t.displayp = Inc.getDisplayp(); | 			t.displayp = Inc.getDisplayp(); | ||||||
|  | 			#if (rp_ssgi == "SSGI") | ||||||
|  | 			t.format = "RGBA32"; | ||||||
|  | 			#else | ||||||
| 			t.format = "R8"; | 			t.format = "R8"; | ||||||
|  | 			#end | ||||||
| 			t.scale = Inc.getSuperSampling(); | 			t.scale = Inc.getSuperSampling(); | ||||||
| 			path.createRenderTarget(t); | 			path.createRenderTarget(t); | ||||||
| 		} | 		} | ||||||
| @ -374,9 +379,6 @@ class RenderPathForward { | |||||||
|  |  | ||||||
| 			if (iron.RenderPath.pre_clear == true) | 			if (iron.RenderPath.pre_clear == true) | ||||||
| 			{ | 			{ | ||||||
| 				#if (rp_voxels == "Voxel GI") |  | ||||||
| 				path.clearImage("voxelsLight", 0x00000000); |  | ||||||
| 				#end |  | ||||||
| 				path.clearImage("voxels", 0x00000000); | 				path.clearImage("voxels", 0x00000000); | ||||||
| 				path.clearImage("voxelsOut", 0x00000000); | 				path.clearImage("voxelsOut", 0x00000000); | ||||||
| 				path.clearImage("voxelsOutB", 0x00000000); | 				path.clearImage("voxelsOutB", 0x00000000); | ||||||
| @ -388,9 +390,6 @@ class RenderPathForward { | |||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				#if (rp_voxels == "Voxel GI") |  | ||||||
| 				path.clearImage("voxelsLight", 0x00000000); |  | ||||||
| 				#end |  | ||||||
| 				path.clearImage("voxels", 0x00000000); | 				path.clearImage("voxels", 0x00000000); | ||||||
| 				Inc.computeVoxelsOffsetPrev(); | 				Inc.computeVoxelsOffsetPrev(); | ||||||
| 			} | 			} | ||||||
| @ -400,27 +399,12 @@ class RenderPathForward { | |||||||
| 			path.setViewport(res, res); | 			path.setViewport(res, res); | ||||||
|  |  | ||||||
| 			path.bindTarget("voxels", "voxels"); | 			path.bindTarget("voxels", "voxels"); | ||||||
| 			path.drawMeshes("voxel"); |  | ||||||
|  |  | ||||||
| 			#if (rp_voxels == "Voxel GI") |  | ||||||
| 			Inc.computeVoxelsLight(); |  | ||||||
| 			#end |  | ||||||
| 			Inc.computeVoxelsTemporal(); | 			Inc.computeVoxelsTemporal(); | ||||||
|  |  | ||||||
| 			#if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) | 			#if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) | ||||||
| 			Inc.computeVoxelsSDF(); | 			Inc.computeVoxelsSDF(); | ||||||
| 			#end | 			#end | ||||||
|  |  | ||||||
| 			if (iron.RenderPath.res_pre_clear == true) |  | ||||||
| 			{ |  | ||||||
| 				iron.RenderPath.res_pre_clear = false; |  | ||||||
| 				#if (rp_voxels == "Voxel GI") |  | ||||||
| 				path.clearImage("voxels_diffuse", 0x00000000); |  | ||||||
| 				path.clearImage("voxels_specular", 0x00000000); |  | ||||||
| 				#else |  | ||||||
| 				path.clearImage("voxels_ao", 0x00000000); |  | ||||||
| 				#end |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| @ -439,7 +423,7 @@ class RenderPathForward { | |||||||
| 		#if (rp_ssrefr || lnx_voxelgi_refract) | 		#if (rp_ssrefr || lnx_voxelgi_refract) | ||||||
| 		{ | 		{ | ||||||
| 			path.setTarget("gbuffer_refraction"); // Only clear gbuffer0 | 			path.setTarget("gbuffer_refraction"); // Only clear gbuffer0 | ||||||
| 			path.clearTarget(0xff000000); | 			path.clearTarget(0xffffff00); | ||||||
| 		} | 		} | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| @ -449,13 +433,6 @@ class RenderPathForward { | |||||||
| 		} | 		} | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| 		#if rp_ssrefr |  | ||||||
| 		{ |  | ||||||
| 			path.setTarget("gbuffer_refraction"); |  | ||||||
| 			path.clearTarget(0xffffff00); |  | ||||||
| 		} |  | ||||||
| 		#end |  | ||||||
|  |  | ||||||
| 		RenderPathCreator.setTargetMeshes(); | 		RenderPathCreator.setTargetMeshes(); | ||||||
|  |  | ||||||
| 		#if rp_shadowmap | 		#if rp_shadowmap | ||||||
| @ -472,19 +449,12 @@ class RenderPathForward { | |||||||
| 		#if (rp_voxels != "Off") | 		#if (rp_voxels != "Off") | ||||||
| 		if (leenkx.data.Config.raw.rp_gi != false) | 		if (leenkx.data.Config.raw.rp_gi != false) | ||||||
| 		{ | 		{ | ||||||
| 			#if (rp_voxels == "Voxel AO") | 			#if (rp_voxels != "Off") | ||||||
| 			Inc.resolveAO(); |  | ||||||
| 			path.bindTarget("voxels_ao", "voxels_ao"); |  | ||||||
| 			#else |  | ||||||
| 			Inc.resolveDiffuse(); |  | ||||||
| 			Inc.resolveSpecular(); |  | ||||||
| 			path.bindTarget("voxels_diffuse", "voxels_diffuse"); |  | ||||||
| 			path.bindTarget("voxels_specular", "voxels_specular"); |  | ||||||
| 			#end |  | ||||||
| 			#if lnx_voxelgi_shadows |  | ||||||
| 			path.bindTarget("voxelsOut", "voxels"); | 			path.bindTarget("voxelsOut", "voxels"); | ||||||
|  | 			#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) | ||||||
| 			path.bindTarget("voxelsSDF", "voxelsSDF"); | 			path.bindTarget("voxelsSDF", "voxelsSDF"); | ||||||
| 			#end | 			#end | ||||||
|  | 			#end | ||||||
| 		} | 		} | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| @ -522,14 +492,31 @@ class RenderPathForward { | |||||||
|  |  | ||||||
| 					path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]); | 					path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]); | ||||||
|  |  | ||||||
|  | 					#if rp_shadowmap | ||||||
|  | 					{ | ||||||
|  | 						#if lnx_shadowmap_atlas | ||||||
|  | 						Inc.bindShadowMapAtlas(); | ||||||
|  | 						#else | ||||||
|  | 						Inc.bindShadowMap(); | ||||||
|  | 						#end | ||||||
|  | 					} | ||||||
|  | 					#end | ||||||
|  |  | ||||||
| 					#if (rp_voxels != "Off") | 					#if (rp_voxels != "Off") | ||||||
| 					path.bindTarget("voxelsOut", "voxels"); | 					path.bindTarget("voxelsOut", "voxels"); | ||||||
|  | 					#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) | ||||||
| 					path.bindTarget("voxelsSDF", "voxelsSDF"); | 					path.bindTarget("voxelsSDF", "voxelsSDF"); | ||||||
| 					#end | 					#end | ||||||
|  | 					#end | ||||||
|  |  | ||||||
|  | 					#if rp_ssrs | ||||||
|  | 					path.bindTarget("_main", "gbufferD"); | ||||||
|  | 					#end | ||||||
|  |  | ||||||
| 					path.drawMeshes("refraction"); | 					path.drawMeshes("refraction"); | ||||||
|  |  | ||||||
| 					path.setTarget("lbuffer0"); | 					path.setTarget("lbuffer0"); | ||||||
|  |  | ||||||
| 					path.bindTarget("lbuffer0", "tex"); | 					path.bindTarget("lbuffer0", "tex"); | ||||||
| 					path.bindTarget("refr", "tex1"); | 					path.bindTarget("refr", "tex1"); | ||||||
| 					path.bindTarget("_main", "gbufferD"); | 					path.bindTarget("_main", "gbufferD"); | ||||||
| @ -577,6 +564,50 @@ class RenderPathForward { | |||||||
| 			} | 			} | ||||||
| 			#end | 			#end | ||||||
|  |  | ||||||
|  | 			#if rp_ssrefr | ||||||
|  | 			{ | ||||||
|  | 				if (leenkx.data.Config.raw.rp_ssrefr != false) | ||||||
|  | 				{ | ||||||
|  | 					path.setTarget("gbufferD1"); | ||||||
|  | 					path.bindTarget("_main", "tex"); | ||||||
|  | 					path.drawShader("shader_datas/copy_pass/copy_pass"); | ||||||
|  |  | ||||||
|  | 					path.setTarget("refr"); | ||||||
|  | 					path.bindTarget("lbuffer0", "tex"); | ||||||
|  | 					path.drawShader("shader_datas/copy_pass/copy_pass"); | ||||||
|  |  | ||||||
|  | 					path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]); | ||||||
|  |  | ||||||
|  | 					#if rp_shadowmap | ||||||
|  | 					{ | ||||||
|  | 						#if lnx_shadowmap_atlas | ||||||
|  | 						Inc.bindShadowMapAtlas(); | ||||||
|  | 						#else | ||||||
|  | 						Inc.bindShadowMap(); | ||||||
|  | 						#end | ||||||
|  | 					} | ||||||
|  | 					#end | ||||||
|  |  | ||||||
|  | 					#if (rp_voxels != "Off") | ||||||
|  | 					path.bindTarget("voxelsOut", "voxels"); | ||||||
|  | 					path.bindTarget("voxelsSDF", "voxelsSDF"); | ||||||
|  | 					#end | ||||||
|  |  | ||||||
|  | 					path.drawMeshes("refraction"); | ||||||
|  |  | ||||||
|  | 					path.setTarget("lbuffer0"); | ||||||
|  | 					path.bindTarget("lbuffer0", "tex"); | ||||||
|  | 					path.bindTarget("refr", "tex1"); | ||||||
|  | 					path.bindTarget("_main", "gbufferD"); | ||||||
|  | 					path.bindTarget("gbufferD1", "gbufferD1"); | ||||||
|  | 					path.bindTarget("lbuffer1", "gbuffer0"); | ||||||
|  | 					path.bindTarget("gbuffer_refraction", "gbuffer_refraction"); | ||||||
|  |  | ||||||
|  | 					path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			#end | ||||||
|  |  | ||||||
| 			#if rp_bloom | 			#if rp_bloom | ||||||
| 			{ | 			{ | ||||||
| 				inline Inc.drawBloom("lbuffer0", bloomDownsampler, bloomUpsampler); | 				inline Inc.drawBloom("lbuffer0", bloomDownsampler, bloomUpsampler); | ||||||
|  | |||||||
| @ -41,7 +41,11 @@ class Starter { | |||||||
| 			try { | 			try { | ||||||
| 			#end | 			#end | ||||||
|  |  | ||||||
| 			kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: {mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) { | 			kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: { | ||||||
|  | 			#if lnx_render_viewport | ||||||
|  | 			visible: false, | ||||||
|  | 			#end | ||||||
|  | 			mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) { | ||||||
|  |  | ||||||
| 				iron.App.init(function() { | 				iron.App.init(function() { | ||||||
| 					#if lnx_loadscreen | 					#if lnx_loadscreen | ||||||
|  | |||||||
| @ -59,6 +59,9 @@ def add_world_defs(): | |||||||
|         if rpdat.rp_shadowmap_cascades != '1': |         if rpdat.rp_shadowmap_cascades != '1': | ||||||
|             wrd.world_defs += '_CSM' |             wrd.world_defs += '_CSM' | ||||||
|             assets.add_khafile_def('lnx_csm') |             assets.add_khafile_def('lnx_csm') | ||||||
|  |         if rpdat.rp_shadowmap_transparent: | ||||||
|  |             wrd.world_defs += '_ShadowMapTransparent' | ||||||
|  |             assets.add_khafile_def('rp_shadowmap_transparent') | ||||||
|         if rpdat.rp_shadowmap_atlas: |         if rpdat.rp_shadowmap_atlas: | ||||||
|             assets.add_khafile_def('lnx_shadowmap_atlas') |             assets.add_khafile_def('lnx_shadowmap_atlas') | ||||||
|             wrd.world_defs += '_ShadowMapAtlas' |             wrd.world_defs += '_ShadowMapAtlas' | ||||||
| @ -119,17 +122,15 @@ def add_world_defs(): | |||||||
|         if rpdat.lnx_voxelgi_shadows and (point_lights > 0 or '_Sun' in wrd.world_defs): |         if rpdat.lnx_voxelgi_shadows and (point_lights > 0 or '_Sun' in wrd.world_defs): | ||||||
|             wrd.world_defs += '_VoxelShadow' |             wrd.world_defs += '_VoxelShadow' | ||||||
|             assets.add_khafile_def('lnx_voxelgi_shadows') |             assets.add_khafile_def('lnx_voxelgi_shadows') | ||||||
|             #assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_shadows/voxel_resolve_shadows.comp.glsl') |  | ||||||
|  |  | ||||||
|         if voxelgi: |         if voxelgi: | ||||||
|             assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_light/voxel_light.comp.glsl') |  | ||||||
|             assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl') |             assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl') | ||||||
|             assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl') |             assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl') | ||||||
|  |             assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_light/voxel_light.comp.glsl') | ||||||
|             wrd.world_defs += '_VoxelGI' |             wrd.world_defs += '_VoxelGI' | ||||||
|             if rpdat.lnx_voxelgi_refract: |             if rpdat.lnx_voxelgi_refract: | ||||||
|                 wrd.world_defs += '_VoxelRefract' |                 wrd.world_defs += '_VoxelRefract' | ||||||
|                 assets.add_khafile_def('lnx_voxelgi_refract') |                 assets.add_khafile_def('lnx_voxelgi_refract') | ||||||
|                 #assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_refraction/voxel_resolve_refraction.comp.glsl') |  | ||||||
|  |  | ||||||
|         elif voxelao: |         elif voxelao: | ||||||
|             assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl') |             assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl') | ||||||
| @ -307,10 +308,14 @@ def build(): | |||||||
|  |  | ||||||
|         assets.add_khafile_def('rp_ssgi={0}'.format(rpdat.rp_ssgi)) |         assets.add_khafile_def('rp_ssgi={0}'.format(rpdat.rp_ssgi)) | ||||||
|         if rpdat.rp_ssgi != 'Off': |         if rpdat.rp_ssgi != 'Off': | ||||||
|             wrd.world_defs += '_SSAO' |  | ||||||
|             if rpdat.rp_ssgi == 'SSAO': |             if rpdat.rp_ssgi == 'SSAO': | ||||||
|  |                 wrd.world_defs += '_SSAO' | ||||||
|                 assets.add_shader_pass('ssao_pass') |                 assets.add_shader_pass('ssao_pass') | ||||||
|                 assets.add_shader_pass('blur_edge_pass') |                 assets.add_shader_pass('blur_edge_pass') | ||||||
|  |             elif rpdat.rp_ssgi == 'SSGI': | ||||||
|  |                 wrd.world_defs += '_SSGI' | ||||||
|  |                 assets.add_shader_pass('ssgi_pass') | ||||||
|  |                 assets.add_shader_pass('blur_edge_pass') | ||||||
|             else: |             else: | ||||||
|                 assets.add_shader_pass('ssgi_pass') |                 assets.add_shader_pass('ssgi_pass') | ||||||
|                 assets.add_shader_pass('blur_edge_pass') |                 assets.add_shader_pass('blur_edge_pass') | ||||||
| @ -457,7 +462,8 @@ def build(): | |||||||
|     if ignoreIrr: |     if ignoreIrr: | ||||||
|         wrd.world_defs += '_IgnoreIrr' |         wrd.world_defs += '_IgnoreIrr' | ||||||
|  |  | ||||||
|     gbuffer2 = '_Veloc' in wrd.world_defs or '_IgnoreIrr' in wrd.world_defs |     gbuffer2 = '_Veloc' in wrd.world_defs or '_IgnoreIrr' in wrd.world_defs or '_VoxelGI' in wrd.world_defs or '_VoxelShadow' in wrd.world_defs or '_SSGI' in wrd.world_defs | ||||||
|  |  | ||||||
|     if gbuffer2: |     if gbuffer2: | ||||||
|         assets.add_khafile_def('rp_gbuffer2') |         assets.add_khafile_def('rp_gbuffer2') | ||||||
|         wrd.world_defs += '_gbuffer2' |         wrd.world_defs += '_gbuffer2' | ||||||
|  | |||||||
| @ -199,6 +199,7 @@ def build_node_tree(world: bpy.types.World, frag: Shader, vert: Shader, con: Sha | |||||||
|         world.lnx_envtex_color = [col[0], col[1], col[2], 1.0] |         world.lnx_envtex_color = [col[0], col[1], col[2], 1.0] | ||||||
|         world.lnx_envtex_strength = 1.0 |         world.lnx_envtex_strength = 1.0 | ||||||
|         world.world_defs += '_EnvCol' |         world.world_defs += '_EnvCol' | ||||||
|  |         assets.add_khafile_def("lnx_envcol") | ||||||
|  |  | ||||||
|     # Clouds enabled |     # Clouds enabled | ||||||
|     if rpdat.lnx_clouds and world.lnx_use_clouds: |     if rpdat.lnx_clouds and world.lnx_use_clouds: | ||||||
| @ -280,6 +281,7 @@ def parse_surface(world: bpy.types.World, node_surface: bpy.types.Node, frag: Sh | |||||||
|         # Append irradiance define |         # Append irradiance define | ||||||
|         if rpdat.lnx_irradiance and not solid_mat: |         if rpdat.lnx_irradiance and not solid_mat: | ||||||
|             wrd.world_defs += '_Irr' |             wrd.world_defs += '_Irr' | ||||||
|  |             assets.add_khafile_def("lnx_irradiance") | ||||||
|  |  | ||||||
|         # Extract environment strength |         # Extract environment strength | ||||||
|         # Todo: follow/parse strength input |         # Todo: follow/parse strength input | ||||||
| @ -293,6 +295,7 @@ def parse_surface(world: bpy.types.World, node_surface: bpy.types.Node, frag: Sh | |||||||
|             solid_mat = rpdat.lnx_material_model == 'Solid' |             solid_mat = rpdat.lnx_material_model == 'Solid' | ||||||
|             if rpdat.lnx_irradiance and not solid_mat: |             if rpdat.lnx_irradiance and not solid_mat: | ||||||
|                 world.world_defs += '_Irr' |                 world.world_defs += '_Irr' | ||||||
|  |                 assets.add_khafile_def("lnx_irradiance") | ||||||
|             world.lnx_envtex_color = node_surface.inputs[0].default_value |             world.lnx_envtex_color = node_surface.inputs[0].default_value | ||||||
|             world.lnx_envtex_strength = 1.0 |             world.lnx_envtex_strength = 1.0 | ||||||
|  |  | ||||||
|  | |||||||
| @ -252,7 +252,7 @@ def parse_bsdfglass(node: bpy.types.ShaderNodeBsdfGlass, out_socket: NodeSocket, | |||||||
|         c.write_normal(node.inputs[3]) |         c.write_normal(node.inputs[3]) | ||||||
|         state.out_roughness = c.parse_value_input(node.inputs[1]) |         state.out_roughness = c.parse_value_input(node.inputs[1]) | ||||||
|     if state.parse_opacity: |     if state.parse_opacity: | ||||||
|         state.out_opacity = '0.1' |         state.out_opacity = '1.0' | ||||||
|         state.out_ior = c.parse_value_input(node.inputs[2]) |         state.out_ior = c.parse_value_input(node.inputs[2]) | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -272,7 +272,7 @@ def parse_bsdfrefraction(node: bpy.types.ShaderNodeBsdfRefraction, out_socket: N | |||||||
|         c.write_normal(node.inputs[3]) |         c.write_normal(node.inputs[3]) | ||||||
|         state.out_roughness = c.parse_value_input(node.inputs[1]) |         state.out_roughness = c.parse_value_input(node.inputs[1]) | ||||||
|     if state.parse_opacity: |     if state.parse_opacity: | ||||||
|         state.out_opacity = '0.0' |         state.out_opacity = '1.0' | ||||||
|         state.out_ior = c.parse_value_input(node.inputs[2]) |         state.out_ior = c.parse_value_input(node.inputs[2]) | ||||||
|  |  | ||||||
| def parse_subsurfacescattering(node: bpy.types.ShaderNodeSubsurfaceScattering, out_socket: NodeSocket, state: ParserState) -> None: | def parse_subsurfacescattering(node: bpy.types.ShaderNodeSubsurfaceScattering, out_socket: NodeSocket, state: ParserState) -> None: | ||||||
|  | |||||||
| @ -342,9 +342,6 @@ def parse_sky_hosekwilkie(node: bpy.types.ShaderNodeTexSky, state: ParserState) | |||||||
|     world = state.world |     world = state.world | ||||||
|     curshader = state.curshader |     curshader = state.curshader | ||||||
|  |  | ||||||
|     # Match to cycles |  | ||||||
|     world.lnx_envtex_strength *= 0.1 |  | ||||||
|  |  | ||||||
|     assets.add_khafile_def('lnx_hosek') |     assets.add_khafile_def('lnx_hosek') | ||||||
|     curshader.add_uniform('vec3 A', link="_hosekA") |     curshader.add_uniform('vec3 A', link="_hosekA") | ||||||
|     curshader.add_uniform('vec3 B', link="_hosekB") |     curshader.add_uniform('vec3 B', link="_hosekB") | ||||||
|  | |||||||
| @ -19,6 +19,7 @@ def write(vert: shader.Shader, frag: shader.Shader): | |||||||
|     parse_opacity = blend or mat_utils.is_transluc(mat_state.material) |     parse_opacity = blend or mat_utils.is_transluc(mat_state.material) | ||||||
|     is_mobile = rpdat.lnx_material_model == 'Mobile' |     is_mobile = rpdat.lnx_material_model == 'Mobile' | ||||||
|     is_shadows = '_ShadowMap' in wrd.world_defs |     is_shadows = '_ShadowMap' in wrd.world_defs | ||||||
|  |     is_transparent_shadows = '_ShadowMapTransparent' in wrd.world_defs | ||||||
|     is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs |     is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs | ||||||
|     is_single_atlas = '_SingleAtlas' in wrd.world_defs |     is_single_atlas = '_SingleAtlas' in wrd.world_defs | ||||||
|  |  | ||||||
| @ -33,14 +34,17 @@ def write(vert: shader.Shader, frag: shader.Shader): | |||||||
|         if is_shadows_atlas: |         if is_shadows_atlas: | ||||||
|             if not is_single_atlas: |             if not is_single_atlas: | ||||||
|                 frag.add_uniform('sampler2DShadow shadowMapAtlasPoint', included=True) |                 frag.add_uniform('sampler2DShadow shadowMapAtlasPoint', included=True) | ||||||
|                 frag.add_uniform('sampler2D shadowMapAtlasPointTransparent', included=True) |                 if is_transparent_shadows: | ||||||
|  |                     frag.add_uniform('sampler2D shadowMapAtlasPointTransparent', included=True) | ||||||
|             else: |             else: | ||||||
|                 frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) |                 frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) | ||||||
|                 frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) |                 if is_transparent_shadows: | ||||||
|  |                     frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) | ||||||
|             frag.add_uniform('vec4 pointLightDataArray[maxLightsCluster]', link='_pointLightsAtlasArray', included=True) |             frag.add_uniform('vec4 pointLightDataArray[maxLightsCluster]', link='_pointLightsAtlasArray', included=True) | ||||||
|         else: |         else: | ||||||
|             frag.add_uniform('samplerCubeShadow shadowMapPoint[4]', included=True) |             frag.add_uniform('samplerCubeShadow shadowMapPoint[4]', included=True) | ||||||
|             frag.add_uniform('samplerCube shadowMapPointTransparent[4]', included=True) |             if is_transparent_shadows: | ||||||
|  |                 frag.add_uniform('samplerCube shadowMapPointTransparent[4]', included=True) | ||||||
|  |  | ||||||
|     if not '_VoxelAOvar' in wrd.world_defs and not '_VoxelGI' in wrd.world_defs or ((parse_opacity or '_VoxelShadow' in wrd.world_defs) and ('_VoxelAOvar' in wrd.world_defs or '_VoxelGI' in wrd.world_defs)): |     if not '_VoxelAOvar' in wrd.world_defs and not '_VoxelGI' in wrd.world_defs or ((parse_opacity or '_VoxelShadow' in wrd.world_defs) and ('_VoxelAOvar' in wrd.world_defs or '_VoxelGI' in wrd.world_defs)): | ||||||
|         vert.add_out('vec4 wvpposition') |         vert.add_out('vec4 wvpposition') | ||||||
| @ -62,13 +66,16 @@ def write(vert: shader.Shader, frag: shader.Shader): | |||||||
|             if is_shadows_atlas: |             if is_shadows_atlas: | ||||||
|                 if not is_single_atlas: |                 if not is_single_atlas: | ||||||
|                     frag.add_uniform('sampler2DShadow shadowMapAtlasSpot', included=True) |                     frag.add_uniform('sampler2DShadow shadowMapAtlasSpot', included=True) | ||||||
|                     frag.add_uniform('sampler2D shadowMapAtlasSpotTransparent', included=True) |                     if is_transparent_shadows: | ||||||
|  |                         frag.add_uniform('sampler2D shadowMapAtlasSpotTransparent', included=True) | ||||||
|                 else: |                 else: | ||||||
|                     frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) |                     frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) | ||||||
|                     frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) |                     if is_transparent_shadows: | ||||||
|  |                         frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) | ||||||
|             else: |             else: | ||||||
|                 frag.add_uniform('sampler2DShadow shadowMapSpot[4]', included=True) |                 frag.add_uniform('sampler2DShadow shadowMapSpot[4]', included=True) | ||||||
|                 frag.add_uniform('sampler2D shadowMapSpotTransparent[4]', included=True) |                 if is_transparent_shadows: | ||||||
|  |                     frag.add_uniform('sampler2D shadowMapSpotTransparent[4]', included=True) | ||||||
|             frag.add_uniform('mat4 LWVPSpotArray[maxLightsCluster]', link='_biasLightWorldViewProjectionMatrixSpotArray', included=True) |             frag.add_uniform('mat4 LWVPSpotArray[maxLightsCluster]', link='_biasLightWorldViewProjectionMatrixSpotArray', included=True) | ||||||
|  |  | ||||||
|     frag.write('for (int i = 0; i < min(numLights, maxLightsCluster); i++) {') |     frag.write('for (int i = 0; i < min(numLights, maxLightsCluster); i++) {') | ||||||
| @ -84,12 +91,10 @@ def write(vert: shader.Shader, frag: shader.Shader): | |||||||
|     frag.write('    roughness,') |     frag.write('    roughness,') | ||||||
|     frag.write('    specular,') |     frag.write('    specular,') | ||||||
|     frag.write('    f0') |     frag.write('    f0') | ||||||
|  |  | ||||||
|     if is_shadows: |     if is_shadows: | ||||||
|         if parse_opacity: |         frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0') # bias | ||||||
|             frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, opacity != 1.0') # bias |     if is_transparent_shadows: | ||||||
|         else: |         frag.write('\t, opacity != 1.0') | ||||||
|             frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false') # bias |  | ||||||
|     if '_Spot' in wrd.world_defs: |     if '_Spot' in wrd.world_defs: | ||||||
|         frag.write('\t, lightsArray[li * 3 + 2].y != 0.0') |         frag.write('\t, lightsArray[li * 3 + 2].y != 0.0') | ||||||
|         frag.write('\t, lightsArray[li * 3 + 2].y') # spot size (cutoff) |         frag.write('\t, lightsArray[li * 3 + 2].y') # spot size (cutoff) | ||||||
| @ -98,13 +103,13 @@ def write(vert: shader.Shader, frag: shader.Shader): | |||||||
|         frag.write('\t, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w)') # scale |         frag.write('\t, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w)') # scale | ||||||
|         frag.write('\t, lightsArraySpot[li * 2 + 1].xyz') # right |         frag.write('\t, lightsArraySpot[li * 2 + 1].xyz') # right | ||||||
|     if '_VoxelShadow' in wrd.world_defs: |     if '_VoxelShadow' in wrd.world_defs: | ||||||
|             frag.write(', voxels, voxelsSDF, clipmaps') |         frag.write(', voxels, voxelsSDF, clipmaps, velocity') | ||||||
|     if '_MicroShadowing' in wrd.world_defs and not is_mobile: |     if '_MicroShadowing' in wrd.world_defs and not is_mobile: | ||||||
|         frag.write('\t, occlusion') |         frag.write('\t, occlusion') | ||||||
|     if '_SSRS' in wrd.world_defs: |     if '_SSRS' in wrd.world_defs: | ||||||
|  |         frag.add_uniform('sampler2D gbufferD') | ||||||
|         frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') |         frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') | ||||||
|         frag.add_uniform('vec3 eye', '_cameraPosition') |         frag.add_uniform('vec3 eye', '_cameraPosition') | ||||||
|         frag.add_uniform('sampler2D gbufferD', link='_gbufferD', top=True) |  | ||||||
|         frag.write(', gbufferD, invVP, eye') |         frag.write(', gbufferD, invVP, eye') | ||||||
|     frag.write(');') |     frag.write(');') | ||||||
|  |  | ||||||
|  | |||||||
| @ -50,6 +50,17 @@ def make(con_mesh: ShaderContext): | |||||||
|                 vertex_elems.append({'name': 'nor', 'data': 'short2norm'}) |                 vertex_elems.append({'name': 'nor', 'data': 'short2norm'}) | ||||||
|  |  | ||||||
|     write_wpos = False |     write_wpos = False | ||||||
|  |     export_wpos = False | ||||||
|  |     if frag.contains('wposition') and not frag.contains('vec3 wposition'): | ||||||
|  |         export_wpos = True | ||||||
|  |     if tese is not None: | ||||||
|  |         export_wpos = True | ||||||
|  |     if vert.contains('wposition'): | ||||||
|  |         write_wpos = True | ||||||
|  |  | ||||||
|  |  | ||||||
|  |      | ||||||
|  |      | ||||||
|     if frag.contains('vVec') and not frag.contains('vec3 vVec'): |     if frag.contains('vVec') and not frag.contains('vec3 vVec'): | ||||||
|         if tese is not None: |         if tese is not None: | ||||||
|             tese.add_out('vec3 eyeDir') |             tese.add_out('vec3 eyeDir') | ||||||
| @ -64,22 +75,17 @@ def make(con_mesh: ShaderContext): | |||||||
|             vert.write('eyeDir = eye - wposition;') |             vert.write('eyeDir = eye - wposition;') | ||||||
|         frag.write_attrib('vec3 vVec = normalize(eyeDir);') |         frag.write_attrib('vec3 vVec = normalize(eyeDir);') | ||||||
|  |  | ||||||
|     export_wpos = False |  | ||||||
|     if frag.contains('wposition') and not frag.contains('vec3 wposition'): |  | ||||||
|         export_wpos = True |  | ||||||
|     if tese is not None: |  | ||||||
|         export_wpos = True |  | ||||||
|     if vert.contains('wposition'): |  | ||||||
|         write_wpos = True |  | ||||||
|  |  | ||||||
|     if export_wpos: |     if export_wpos: | ||||||
|         vert.add_uniform('mat4 W', '_worldMatrix') |         vert.add_uniform('mat4 W', '_worldMatrix') | ||||||
|         vert.add_out('vec3 wposition') |         vert.add_out('vec3 wposition') | ||||||
|         vert.write('wposition = vec4(W * spos).xyz;') |         vert.write_attrib('wposition = vec4(W * spos).xyz;') | ||||||
|     elif write_wpos: |     elif write_wpos: | ||||||
|         vert.add_uniform('mat4 W', '_worldMatrix') |         vert.add_uniform('mat4 W', '_worldMatrix') | ||||||
|         vert.write_attrib('vec3 wposition = vec4(W * spos).xyz;') |         vert.write_attrib('vec3 wposition = vec4(W * spos).xyz;') | ||||||
|  |  | ||||||
|  |     if frag.contains('dotNV') and not frag.contains('float dotNV'): | ||||||
|  |         frag.write_attrib('float dotNV = max(dot(n, vVec), 0.0);') | ||||||
|  |  | ||||||
|     frag_mpos = (frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition') |     frag_mpos = (frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition') | ||||||
|     if frag_mpos: |     if frag_mpos: | ||||||
|         vert.add_out('vec3 mposition') |         vert.add_out('vec3 mposition') | ||||||
|  | |||||||
| @ -559,7 +559,7 @@ def make_forward(con_mesh): | |||||||
|             frag.write('fragColor[0] = vec4(direct + indirect, packFloat2(occlusion, specular));') |             frag.write('fragColor[0] = vec4(direct + indirect, packFloat2(occlusion, specular));') | ||||||
|             frag.write('fragColor[1] = vec4(n.xy, roughness, metallic);') |             frag.write('fragColor[1] = vec4(n.xy, roughness, metallic);') | ||||||
|             if rpdat.rp_ss_refraction or rpdat.lnx_voxelgi_refract: |             if rpdat.rp_ss_refraction or rpdat.lnx_voxelgi_refract: | ||||||
|                 frag.write(f'fragColor[2] = vec4(1.0, 1.0, 0.0, 1.0);') |                 frag.write(f'fragColor[2] = vec4(1.0, 1.0, 0.0, 0.0);') | ||||||
|  |  | ||||||
|         else: |         else: | ||||||
|             frag.add_out('vec4 fragColor[1]') |             frag.add_out('vec4 fragColor[1]') | ||||||
| @ -613,10 +613,42 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | |||||||
|     sh = tese if tese is not None else vert |     sh = tese if tese is not None else vert | ||||||
|     sh.add_out('vec3 eyeDir') |     sh.add_out('vec3 eyeDir') | ||||||
|     sh.add_uniform('vec3 eye', '_cameraPosition') |     sh.add_uniform('vec3 eye', '_cameraPosition') | ||||||
|     sh.write('eyeDir = eye - spos.xyz;') |     sh.write('eyeDir = eye - wposition;') | ||||||
|  |     if '_VoxelGI' in wrd.world_defs or '_VoxelShadow' in wrd.world_defs: | ||||||
|  |         if '_gbuffer2' in wrd.world_defs: | ||||||
|  |             if '_Veloc' in wrd.world_defs: | ||||||
|  |                 if tese is None: | ||||||
|  |                     vert.add_uniform('mat4 prevWVP', link='_prevWorldViewProjectionMatrix') | ||||||
|  |                     vert.add_out('vec4 wvpposition') | ||||||
|  |                     vert.add_out('vec4 prevwvpposition') | ||||||
|  |                     vert.write('wvpposition = gl_Position;') | ||||||
|  |                     if is_displacement: | ||||||
|  |                         vert.add_uniform('mat4 invW', link='_inverseWorldMatrix') | ||||||
|  |                         vert.write('prevwvpposition = prevWVP * (invW * vec4(wposition, 1.0));') | ||||||
|  |                     else: | ||||||
|  |                         vert.write('prevwvpposition = prevWVP * spos;') | ||||||
|  |                 else: | ||||||
|  |                     tese.add_out('vec4 wvpposition') | ||||||
|  |                     tese.add_out('vec4 prevwvpposition') | ||||||
|  |                     tese.write('wvpposition = gl_Position;') | ||||||
|  |                     if is_displacement: | ||||||
|  |                         tese.add_uniform('mat4 invW', link='_inverseWorldMatrix') | ||||||
|  |                         tese.add_uniform('mat4 prevWVP', '_prevWorldViewProjectionMatrix') | ||||||
|  |                         tese.write('prevwvpposition = prevWVP * (invW * vec4(wposition, 1.0));') | ||||||
|  |                     else: | ||||||
|  |                         vert.add_uniform('mat4 prevW', link='_prevWorldMatrix') | ||||||
|  |                         vert.add_out('vec3 prevwposition') | ||||||
|  |                         vert.write('prevwposition = vec4(prevW * spos).xyz;') | ||||||
|  |                         tese.add_uniform('mat4 prevVP', '_prevViewProjectionMatrix') | ||||||
|  |                         make_tess.interpolate(tese, 'prevwposition', 3) | ||||||
|  |                         tese.write('prevwvpposition = prevVP * vec4(prevwposition, 1.0);') | ||||||
|  |                 frag.write('vec2 posa = (wvpposition.xy / wvpposition.w) * 0.5 + 0.5;') | ||||||
|  |                 frag.write('vec2 posb = (prevwvpposition.xy / prevwvpposition.w) * 0.5 + 0.5;') | ||||||
|  |                 frag.write('vec2 velocity = -vec2(posa - posb);') | ||||||
|  |  | ||||||
|     frag.add_include('std/light.glsl') |     frag.add_include('std/light.glsl') | ||||||
|     is_shadows = '_ShadowMap' in wrd.world_defs |     is_shadows = '_ShadowMap' in wrd.world_defs | ||||||
|  |     is_transparent_shadows = '_ShadowMapTransparent' in wrd.world_defs | ||||||
|     is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs |     is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs | ||||||
|     is_single_atlas = is_shadows_atlas and '_SingleAtlas' in wrd.world_defs |     is_single_atlas = is_shadows_atlas and '_SingleAtlas' in wrd.world_defs | ||||||
|     shadowmap_sun = 'shadowMap' |     shadowmap_sun = 'shadowMap' | ||||||
| @ -632,6 +664,9 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | |||||||
|     if '_Brdf' in wrd.world_defs: |     if '_Brdf' in wrd.world_defs: | ||||||
|         frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') |         frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') | ||||||
|         frag.write('vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;') |         frag.write('vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;') | ||||||
|  |         frag.write('vec3 F = f0 * envBRDF.x + envBRDF.y;') | ||||||
|  |     else: | ||||||
|  |         frag.write('vec3 F = f0;') | ||||||
|          |          | ||||||
|     if '_Irr' in wrd.world_defs: |     if '_Irr' in wrd.world_defs: | ||||||
|         frag.add_include('std/shirr.glsl') |         frag.add_include('std/shirr.glsl') | ||||||
| @ -657,30 +692,24 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | |||||||
|     frag.write('envl *= albedo;') |     frag.write('envl *= albedo;') | ||||||
|  |  | ||||||
|     if '_Brdf' in wrd.world_defs: |     if '_Brdf' in wrd.world_defs: | ||||||
|         frag.write('envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y);') |         frag.write('envl.rgb *= 1.0 - F;') | ||||||
|     if '_Rad' in wrd.world_defs: |     if '_Rad' in wrd.world_defs: | ||||||
|         frag.write('envl += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);') |         frag.write('envl += prefilteredColor * F;') | ||||||
|     elif '_EnvCol' in wrd.world_defs: |     elif '_EnvCol' in wrd.world_defs: | ||||||
|         frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') |         frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') | ||||||
|         frag.write('envl += backgroundCol * (f0 * envBRDF.x + envBRDF.y);') |         frag.write('envl += backgroundCol * F;') | ||||||
|  |  | ||||||
|     frag.add_uniform('float envmapStrength', link='_envmapStrength') |     frag.add_uniform('float envmapStrength', link='_envmapStrength') | ||||||
|     frag.write('envl *= envmapStrength * occlusion;') |     frag.write('envl *= envmapStrength * occlusion;') | ||||||
|  |  | ||||||
|     if '_VoxelAOvar' in wrd.world_defs or '_VoxelGI' in wrd.world_defs: |     if '_VoxelAOvar' in wrd.world_defs or '_VoxelGI' in wrd.world_defs: | ||||||
|         if parse_opacity or '_VoxelShadow' in wrd.world_defs: |         frag.add_include('std/conetrace.glsl') | ||||||
|             frag.add_include('std/conetrace.glsl') |         frag.add_uniform('sampler3D voxels') | ||||||
|             frag.add_uniform('sampler3D voxels') |         frag.add_uniform('sampler3D voxelsSDF') | ||||||
|             frag.add_uniform('sampler3D voxelsSDF') |         frag.add_uniform('float clipmaps[10 * voxelgiClipmapCount]', '_clipmaps') | ||||||
|             frag.add_uniform('vec3 eye', "_cameraPosition") |  | ||||||
|             frag.add_uniform('float clipmaps[10 * voxelgiClipmapCount]', '_clipmaps') |  | ||||||
|         vert.add_out('vec4 wvpposition') |  | ||||||
|         vert.write('wvpposition = gl_Position;') |  | ||||||
|         frag.write('vec2 texCoord = (wvpposition.xy / wvpposition.w) * 0.5 + 0.5;') |  | ||||||
|  |  | ||||||
|     if '_VoxelAOvar' in wrd.world_defs and not parse_opacity: |     if '_VoxelAOvar' in wrd.world_defs: | ||||||
|         frag.add_uniform("sampler2D voxels_ao"); |         frag.write('envl *= (1.0 - traceAO(wposition, n, voxels, clipmaps));') | ||||||
|         frag.write('envl *= textureLod(voxels_ao, texCoord, 0.0).rrr;') |  | ||||||
|  |  | ||||||
|     if '_VoxelGI' in wrd.world_defs: |     if '_VoxelGI' in wrd.world_defs: | ||||||
|         frag.write('vec3 indirect = vec3(0.0);') |         frag.write('vec3 indirect = vec3(0.0);') | ||||||
| @ -688,20 +717,12 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | |||||||
|         frag.write('vec3 indirect = envl;') |         frag.write('vec3 indirect = envl;') | ||||||
|  |  | ||||||
|     if '_VoxelGI' in wrd.world_defs: |     if '_VoxelGI' in wrd.world_defs: | ||||||
|         if parse_opacity: |         frag.write('vec2 velocity = gl_FragCoord.xy;') | ||||||
|             frag.write('vec4 trace = traceDiffuse(wposition, wnormal, voxels, clipmaps);') |         frag.write('vec4 diffuse_indirect = traceDiffuse(wposition, n, voxels, clipmaps);') | ||||||
|             frag.write('indirect = ((trace.rgb * albedo + envl * (1.0 - trace.a)) * voxelgiDiff);') |         frag.write('indirect = (diffuse_indirect.rgb * albedo * (1.0 - F) + envl * (1.0 - diffuse_indirect.a)) * voxelgiDiff;') | ||||||
|             frag.write('if (roughness < 1.0 && specular > 0.0){') |         frag.write('if (roughness < 1.0 && specular > 0.0) {') | ||||||
|             frag.add_uniform('sampler2D sveloc') |         frag.write('    indirect += traceSpecular(wposition, n, voxels, voxelsSDF, vVec, roughness * roughness, clipmaps, gl_FragCoord.xy, velocity).rgb * F * voxelgiRefl;') | ||||||
|             frag.write('    vec2 velocity = -textureLod(sveloc, gl_FragCoord.xy, 0.0).rg;') |         frag.write('}') | ||||||
|             frag.write('    indirect += traceSpecular(wposition, n, voxels, voxelsSDF, vVec, roughness, clipmaps, gl_FragCoord.xy, velocity).rgb * specular * voxelgiRefl;}') |  | ||||||
|         else: |  | ||||||
|             frag.add_uniform("sampler2D voxels_diffuse") |  | ||||||
|             frag.add_uniform("sampler2D voxels_specular") |  | ||||||
|             frag.write("indirect = textureLod(voxels_diffuse, texCoord, 0.0).rgb * albedo * voxelgiDiff;") |  | ||||||
|             frag.write("if (roughness < 1.0 && specular > 0.0)") |  | ||||||
|             frag.write("    indirect += textureLod(voxels_specular, texCoord, 0.0).rgb * specular * voxelgiRefl;") |  | ||||||
|  |  | ||||||
|     frag.write('vec3 direct = vec3(0.0);') |     frag.write('vec3 direct = vec3(0.0);') | ||||||
|  |  | ||||||
|     if '_Sun' in wrd.world_defs: |     if '_Sun' in wrd.world_defs: | ||||||
| @ -715,18 +736,21 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | |||||||
|         if is_shadows: |         if is_shadows: | ||||||
|             frag.add_uniform('bool receiveShadow') |             frag.add_uniform('bool receiveShadow') | ||||||
|             frag.add_uniform(f'sampler2DShadow {shadowmap_sun}', top=True) |             frag.add_uniform(f'sampler2DShadow {shadowmap_sun}', top=True) | ||||||
|             frag.add_uniform(f'sampler2D {shadowmap_sun_tr}', top=True) |             if is_transparent_shadows: | ||||||
|  |                 frag.add_uniform(f'sampler2D {shadowmap_sun_tr}', top=True) | ||||||
|             frag.add_uniform('float shadowsBias', '_sunShadowsBias') |             frag.add_uniform('float shadowsBias', '_sunShadowsBias') | ||||||
|             frag.write('if (receiveShadow) {') |             frag.write('if (receiveShadow) {') | ||||||
|             if '_CSM' in wrd.world_defs: |             if '_CSM' in wrd.world_defs: | ||||||
|                 frag.add_include('std/shadows.glsl') |                 frag.add_include('std/shadows.glsl') | ||||||
|                 frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) |                 frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) | ||||||
|                 frag.add_uniform('vec3 eye', '_cameraPosition') |                 frag.add_uniform('vec3 eye', '_cameraPosition') | ||||||
|                 if parse_opacity: |                 frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') | ||||||
|                     frag.write(f'svisibility = shadowTestCascade({shadowmap_sun}, {shadowmap_sun_tr}, eye, wposition + n * shadowsBias * 10, shadowsBias, true);') |                 if is_transparent_shadows: | ||||||
|                 else: |                     frag.write(f'{shadowmap_sun_tr},') | ||||||
|                     frag.write(f'svisibility = shadowTestCascade({shadowmap_sun}, {shadowmap_sun_tr}, eye, wposition + n * shadowsBias * 10, shadowsBias, false);') |                 frag.write('eye, wposition + n * shadowsBias * 10, shadowsBias') | ||||||
|  |                 if is_transparent_shadows: | ||||||
|  |                     frag.write(', false') | ||||||
|  |                 frag.write(');') | ||||||
|             else: |             else: | ||||||
|                 if tese is not None: |                 if tese is not None: | ||||||
|                     tese.add_out('vec4 lightPosition') |                     tese.add_out('vec4 lightPosition') | ||||||
| @ -740,15 +764,18 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | |||||||
|                     else: |                     else: | ||||||
|                         vert.add_out('vec4 lightPosition') |                         vert.add_out('vec4 lightPosition') | ||||||
|                         vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrixSun') |                         vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrixSun') | ||||||
|                         vert.write('lightPosition = LWVP * lightPosition;') |                         vert.write('lightPosition = LWVP * pos;') | ||||||
|                 frag.write('vec3 lPos = lightPosition.xyz / lightPosition.w;') |                 frag.write('vec3 lPos = lightPosition.xyz / lightPosition.w;') | ||||||
|                 frag.write('const vec2 smSize = shadowmapSize;') |                 frag.write('const vec2 smSize = shadowmapSize;') | ||||||
|                 if parse_opacity: |                 frag.write(f'svisibility = PCF({shadowmap_sun},') | ||||||
|                     frag.write(f'svisibility = PCF({shadowmap_sun}, {shadowmap_sun_tr}, lPos.xy, lPos.z - shadowsBias, smSize, true);') |                 if is_transparent_shadows: | ||||||
|                 else: |                     frag.write(f'{shadowmap_sun_tr},') | ||||||
|                     frag.write(f'svisibility = PCF({shadowmap_sun}, {shadowmap_sun_tr}, lPos.xy, lPos.z - shadowsBias, smSize, false);') |                 frag.write('lPos.xy, lPos.z - shadowsBias, smSize') | ||||||
|  |                 if is_transparent_shadows: | ||||||
|  |                     frag.write(', false') | ||||||
|  |                 frag.write(');') | ||||||
|             if '_VoxelShadow' in wrd.world_defs: |             if '_VoxelShadow' in wrd.world_defs: | ||||||
|                 frag.write('svisibility *= (1.0 - traceShadow(wposition, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;') |                 frag.write('svisibility *= (1.0 - traceShadow(wposition, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad;') | ||||||
|             frag.write('}') # receiveShadow |             frag.write('}') # receiveShadow | ||||||
|         frag.write('direct += (lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;') |         frag.write('direct += (lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;') | ||||||
|         # sun |         # sun | ||||||
| @ -767,7 +794,8 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | |||||||
|                 # Skip world matrix, already in world-space |                 # Skip world matrix, already in world-space | ||||||
|                 frag.add_uniform('mat4 LWVPSpot[1]', link='_biasLightViewProjectionMatrixSpotArray', included=True) |                 frag.add_uniform('mat4 LWVPSpot[1]', link='_biasLightViewProjectionMatrixSpotArray', included=True) | ||||||
|                 frag.add_uniform('sampler2DShadow shadowMapSpot[1]', included=True) |                 frag.add_uniform('sampler2DShadow shadowMapSpot[1]', included=True) | ||||||
|                 frag.add_uniform('sampler2D shadowMapSpotTransparent[1]', included=True) |                 if is_transparent_shadows: | ||||||
|  |                     frag.add_uniform('sampler2D shadowMapSpotTransparent[1]', included=True) | ||||||
|             else: |             else: | ||||||
|                 frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) |                 frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) | ||||||
|                 frag.add_uniform('samplerCubeShadow shadowMapPoint[1]', included=True) |                 frag.add_uniform('samplerCubeShadow shadowMapPoint[1]', included=True) | ||||||
| @ -775,18 +803,19 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | |||||||
|         frag.write('direct += sampleLight(') |         frag.write('direct += sampleLight(') | ||||||
|         frag.write('  wposition, n, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') |         frag.write('  wposition, n, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') | ||||||
|         if is_shadows: |         if is_shadows: | ||||||
|             if parse_opacity: |             frag.write(', 0, pointBias, receiveShadow') | ||||||
|                 frag.write(', 0, pointBias, receiveShadow, opacity != 1.0') |             if is_transparent_shadows: | ||||||
|             else: |                 frag.write(', opacity != 1.0') | ||||||
|                 frag.write(', 0, pointBias, receiveShadow, false') |  | ||||||
|         if '_Spot' in wrd.world_defs: |         if '_Spot' in wrd.world_defs: | ||||||
|             frag.write(', true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight') |             frag.write(', true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight') | ||||||
|         if '_VoxelShadow' in wrd.world_defs: |         if '_VoxelShadow' in wrd.world_defs: | ||||||
|             frag.write(', voxels, voxelsSDF, clipmaps') |             frag.write(', voxels, voxelsSDF, clipmaps') | ||||||
|  |         if '_Veloc' in wrd.world_defs or '_VoxelShadow' in wrd.world_defs: | ||||||
|  |             frag.write(', velocity')       | ||||||
|         if '_MicroShadowing' in wrd.world_defs: |         if '_MicroShadowing' in wrd.world_defs: | ||||||
|             frag.write(', occlusion') |             frag.write(', occlusion') | ||||||
|         if '_SSRS' in wrd.world_defs: |         if '_SSRS' in wrd.world_defs: | ||||||
|             frag.add_uniform('sampler2D gbufferD', top=True) |             frag.add_uniform('sampler2D gbufferD') | ||||||
|             frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') |             frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') | ||||||
|             frag.add_uniform('vec3 eye', '_cameraPosition') |             frag.add_uniform('vec3 eye', '_cameraPosition') | ||||||
|             frag.write(', gbufferD, invVP, eye') |             frag.write(', gbufferD, invVP, eye') | ||||||
| @ -802,10 +831,9 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | |||||||
|  |  | ||||||
|     if '_VoxelRefract' in wrd.world_defs and parse_opacity: |     if '_VoxelRefract' in wrd.world_defs and parse_opacity: | ||||||
|         frag.write('if (opacity < 1.0) {') |         frag.write('if (opacity < 1.0) {') | ||||||
|         frag.write('    vec2 velocity = -textureLod(sveloc, gl_FragCoord.xy, 0.0).rg;') |         frag.write('    vec3 refraction = traceRefraction(wposition, n, voxels, voxelsSDF, vVec, ior, roughness * roughness, clipmaps, gl_FragCoord.xy, velocity, opacity).rgb * (1.0 - F) * voxelgiRefr;') | ||||||
|         frag.write('    vec3 refraction = traceRefraction(wposition, n, voxels, voxelsSDF, vVec, ior, roughness, clipmaps, gl_FragCoord.xy,velocity).rgb;') |         frag.write('    indirect = mix(refraction, indirect, opacity);') | ||||||
|         frag.write('    indirect = mix(refraction, indirect, opacity) * voxelgiRefr;') |         frag.write('    direct = mix(refraction, direct, opacity);') | ||||||
|         frag.write('    direct = mix(refraction, direct, opacity) * voxelgiRefr;') |  | ||||||
|         frag.write('}') |         frag.write('}') | ||||||
|  |  | ||||||
| def _write_material_attribs_default(frag: shader.Shader, parse_opacity: bool): | def _write_material_attribs_default(frag: shader.Shader, parse_opacity: bool): | ||||||
| @ -819,4 +847,4 @@ def _write_material_attribs_default(frag: shader.Shader, parse_opacity: bool): | |||||||
|     frag.write('vec3 emissionCol;') |     frag.write('vec3 emissionCol;') | ||||||
|     if parse_opacity: |     if parse_opacity: | ||||||
|         frag.write('float opacity;') |         frag.write('float opacity;') | ||||||
|         frag.write('float ior;') |         frag.write('float ior = 1.45;') | ||||||
|  | |||||||
| @ -58,6 +58,7 @@ def make(context_id): | |||||||
|         frag.write('fragColor[1] = vec4(n.xy, roughness, metallic);') |         frag.write('fragColor[1] = vec4(n.xy, roughness, metallic);') | ||||||
|  |  | ||||||
|     frag.write('fragColor[2] = vec4(ior, opacity, 0.0, 1.0);') |     frag.write('fragColor[2] = vec4(ior, opacity, 0.0, 1.0);') | ||||||
|  |     # frag.write('fragColor[2] = vec4(ior, opacity, packFloat2(basecol.r, basecol.g), basecol.b);') | ||||||
|  |  | ||||||
|     make_finalize.make(con_refract) |     make_finalize.make(con_refract) | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,49 +0,0 @@ | |||||||
| import bpy |  | ||||||
|  |  | ||||||
| import lnx |  | ||||||
| import lnx.material.cycles as cycles |  | ||||||
| import lnx.material.mat_state as mat_state |  | ||||||
| import lnx.material.mat_utils as mat_utils |  | ||||||
| import lnx.material.make_mesh as make_mesh |  | ||||||
| import lnx.material.make_finalize as make_finalize |  | ||||||
| import lnx.assets as assets |  | ||||||
|  |  | ||||||
| if lnx.is_reload(__name__): |  | ||||||
| 	cycles = lnx.reload_module(cycles) |  | ||||||
| 	mat_state = lnx.reload_module(mat_state) |  | ||||||
| 	make_mesh = lnx.reload_module(make_mesh) |  | ||||||
| 	make_finalize = lnx.reload_module(make_finalize) |  | ||||||
| 	assets = lnx.reload_module(assets) |  | ||||||
| else: |  | ||||||
| 	lnx.enable_reload(__name__) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def make(context_id): |  | ||||||
|     con_refraction_buffer = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'less', 'cull_mode': 'clockwise' }) |  | ||||||
|  |  | ||||||
|     lnx_discard = mat_state.material.lnx_discard |  | ||||||
|     blend = mat_state.material.lnx_blending |  | ||||||
|     parse_opacity = blend or mat_utils.is_transluc(mat_state.material) or lnx_discard |  | ||||||
|  |  | ||||||
|     make_mesh.make_base(con_refraction_buffer, parse_opacity) |  | ||||||
|  |  | ||||||
|     vert = con_refraction_buffer.vert |  | ||||||
|     frag = con_refraction_buffer.frag |  | ||||||
|  |  | ||||||
|     frag.add_out('vec4 fragColor') |  | ||||||
|  |  | ||||||
|     # Remove fragColor = ...; |  | ||||||
|     frag.main = frag.main[:frag.main.rfind('fragColor')] |  | ||||||
|     frag.write('\n') |  | ||||||
|  |  | ||||||
|     if parse_opacity: |  | ||||||
|         frag.write('fragColor = vec4(ior, opacity, 0.0, 1.0);') |  | ||||||
|     else: |  | ||||||
|         frag.write('fragColor = vec4(1.0, 1.0, 0.0, 1.0);') |  | ||||||
|  |  | ||||||
|     make_finalize.make(con_refraction_buffer) |  | ||||||
|  |  | ||||||
|     # assets.vs_equal(con_refract, assets.shader_cons['transluc_vert']) # shader_cons has no transluc yet |  | ||||||
|     # assets.fs_equal(con_refract, assets.shader_cons['transluc_frag']) |  | ||||||
|  |  | ||||||
|     return con_refraction_buffer |  | ||||||
| @ -68,6 +68,7 @@ def make_gi(context_id): | |||||||
|     frag.add_include('std/imageatomic.glsl') |     frag.add_include('std/imageatomic.glsl') | ||||||
|     frag.add_include('std/gbuffer.glsl') |     frag.add_include('std/gbuffer.glsl') | ||||||
|     frag.add_include('std/brdf.glsl') |     frag.add_include('std/brdf.glsl') | ||||||
|  |     frag.add_include('std/aabb.glsl') | ||||||
|  |  | ||||||
|     rpdat = lnx.utils.get_rp() |     rpdat = lnx.utils.get_rp() | ||||||
|     frag.add_uniform('layout(r32ui) uimage3D voxels') |     frag.add_uniform('layout(r32ui) uimage3D voxels') | ||||||
| @ -88,7 +89,6 @@ def make_gi(context_id): | |||||||
|     else: |     else: | ||||||
|         frag.write('float opacity = 1.0;') |         frag.write('float opacity = 1.0;') | ||||||
|  |  | ||||||
|     frag.write('float dotNV = 0.0;') |  | ||||||
|     cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True) |     cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True) | ||||||
|  |  | ||||||
|     # Voxelized particles |     # Voxelized particles | ||||||
| @ -139,10 +139,12 @@ def make_gi(context_id): | |||||||
|  |  | ||||||
|     geom.add_out('vec4 voxposition[3]') |     geom.add_out('vec4 voxposition[3]') | ||||||
|     geom.add_out('vec3 P') |     geom.add_out('vec3 P') | ||||||
|     geom.add_out('vec3 voxnormal') |     geom.add_out('vec3 wnormal') | ||||||
|     geom.add_out('vec4 lightPosition') |     geom.add_out('vec4 lightPosition') | ||||||
|     geom.add_out('vec4 spotPosition') |  | ||||||
|     geom.add_out('vec4 wvpposition') |     geom.add_out('vec4 wvpposition') | ||||||
|  |     geom.add_out('vec3 eyeDir') | ||||||
|  |     geom.add_out('vec3 aabb_min') | ||||||
|  |     geom.add_out('vec3 aabb_max') | ||||||
|  |  | ||||||
|     if con_voxel.is_elem('col'): |     if con_voxel.is_elem('col'): | ||||||
|         geom.add_out('vec3 vcolor') |         geom.add_out('vec3 vcolor') | ||||||
| @ -160,6 +162,9 @@ def make_gi(context_id): | |||||||
|     geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') |     geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') | ||||||
|     geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') |     geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') | ||||||
|  |  | ||||||
|  |     geom.write('aabb_min = min(voxpositionGeom[0].xyz, min(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') | ||||||
|  |     geom.write('aabb_max = max(voxpositionGeom[0].xyz, max(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') | ||||||
|  |  | ||||||
|     geom.write('for (uint i = 0; i < 3; ++i) {') |     geom.write('for (uint i = 0; i < 3; ++i) {') | ||||||
|     geom.write('    voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') |     geom.write('    voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') | ||||||
|     geom.write('    if (maxi == 0)') |     geom.write('    if (maxi == 0)') | ||||||
| @ -172,11 +177,18 @@ def make_gi(context_id): | |||||||
|     geom.write('    }') |     geom.write('    }') | ||||||
|     geom.write('}') |     geom.write('}') | ||||||
|  |  | ||||||
|  |     geom.write('vec2 side0N = normalize(voxposition[1].xy - voxposition[0].xy);') | ||||||
|  |     geom.write('vec2 side1N = normalize(voxposition[2].xy - voxposition[1].xy);') | ||||||
|  |     geom.write('vec2 side2N = normalize(voxposition[0].xy - voxposition[2].xy);') | ||||||
|  |     geom.write('voxposition[0].xy += normalize(side2N - side0N);') | ||||||
|  |     geom.write('voxposition[1].xy += normalize(side0N - side1N);') | ||||||
|  |     geom.write('voxposition[2].xy += normalize(side1N - side2N);') | ||||||
|  |  | ||||||
|     geom.write('for (uint i = 0; i < 3; ++i) {') |     geom.write('for (uint i = 0; i < 3; ++i) {') | ||||||
|     geom.write('    voxposition[i].xy /= voxelgiResolution.xy;') |     geom.write('    voxposition[i].xy /= voxelgiResolution.xy;') | ||||||
|     geom.write('    voxposition[i].zw = vec2(1.0);') |     geom.write('    voxposition[i].zw = vec2(1.0);') | ||||||
|     geom.write('    P = voxpositionGeom[i];') |     geom.write('    P = voxpositionGeom[i];') | ||||||
|     geom.write('    voxnormal = voxnormalGeom[i];') |     geom.write('    wnormal = voxnormalGeom[i];') | ||||||
|     if con_voxel.is_elem('col'): |     if con_voxel.is_elem('col'): | ||||||
|         geom.write('vcolor = vcolorGeom[i];') |         geom.write('vcolor = vcolorGeom[i];') | ||||||
|     if con_voxel.is_elem('tex'): |     if con_voxel.is_elem('tex'): | ||||||
| @ -185,6 +197,11 @@ def make_gi(context_id): | |||||||
|         geom.write('mposition = mpositionGeom[i];') |         geom.write('mposition = mpositionGeom[i];') | ||||||
|     if export_bpos: |     if export_bpos: | ||||||
|         geom.write('bposition = bpositionGeom[i];') |         geom.write('bposition = bpositionGeom[i];') | ||||||
|  |     geom.write('    eyeDir = eyeDirGeom[i];') | ||||||
|  |     if '_Sun' in wrd.world_defs and not '_CSM' in wrd.world_defs and '_ShadowMap' in wrd.world_defs: | ||||||
|  |         geom.write('    lightPosition = lightPositionGeom[i];') | ||||||
|  |     if '_Clusters' in wrd.world_defs and '_ShadowMap' in wrd.world_defs: | ||||||
|  |         geom.write('    wvpposition = wvppositionGeom[i];') | ||||||
|     geom.write('    gl_Position = voxposition[i];') |     geom.write('    gl_Position = voxposition[i];') | ||||||
|     geom.write('    EmitVertex();') |     geom.write('    EmitVertex();') | ||||||
|     geom.write('}') |     geom.write('}') | ||||||
| @ -195,9 +212,10 @@ def make_gi(context_id): | |||||||
|  |  | ||||||
|     frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') |     frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') | ||||||
|     frag.write('uvw = (uvw * 0.5 + 0.5);') |     frag.write('uvw = (uvw * 0.5 + 0.5);') | ||||||
|  |  | ||||||
|     frag.write('if(any(notEqual(uvw, clamp(uvw, 0.0, 1.0)))) return;') |     frag.write('if(any(notEqual(uvw, clamp(uvw, 0.0, 1.0)))) return;') | ||||||
|     frag.write('vec3 writecoords = floor(uvw * voxelgiResolution);') |     frag.write('vec3 writecoords = floor(uvw * voxelgiResolution);') | ||||||
|     frag.write_attrib('vec3 N = normalize(voxnormal);') |     frag.write_attrib('vec3 N = normalize(wnormal);') | ||||||
|     frag.write('vec3 aniso_direction = N;') |     frag.write('vec3 aniso_direction = N;') | ||||||
|     frag.write('uvec3 face_offsets = uvec3(') |     frag.write('uvec3 face_offsets = uvec3(') | ||||||
|     frag.write('    aniso_direction.x > 0 ? 0 : 1,') |     frag.write('    aniso_direction.x > 0 ? 0 : 1,') | ||||||
| @ -206,11 +224,33 @@ def make_gi(context_id): | |||||||
|     frag.write('    ) * voxelgiResolution;') |     frag.write('    ) * voxelgiResolution;') | ||||||
|     frag.write('vec3 direction_weights = abs(N);') |     frag.write('vec3 direction_weights = abs(N);') | ||||||
|  |  | ||||||
|  |     frag.write('vec3 clipmap_pixel = uvw * voxelgiResolution;') | ||||||
|  |     frag.write('vec3 clipmap_uvw_center = (clipmap_pixel + 0.5) / voxelgiResolution;') | ||||||
|  |     frag.write('vec3 voxel_center = clipmap_uvw_center * 2.0 - 1.0;') | ||||||
|  |     frag.write('float voxel_size = float(clipmaps[int(clipmapLevel * 10)]);') | ||||||
|  |     frag.write('voxel_center *= voxel_size;') | ||||||
|  |     frag.write('voxel_center *= voxelgiResolution.x;') | ||||||
|  |     frag.write('voxel_center += vec3(') | ||||||
|  |     frag.write('    clipmaps[clipmapLevel * 10 + 4],') | ||||||
|  |     frag.write('    clipmaps[clipmapLevel * 10 + 5],') | ||||||
|  |     frag.write('    clipmaps[clipmapLevel * 10 + 6]);') | ||||||
|  |  | ||||||
|  |     frag.write('vec3 voxel_aabb[2];') | ||||||
|  |     frag.write('voxel_aabb[0] = voxel_center;') | ||||||
|  |     frag.write('voxel_aabb[1] = vec3(voxel_size);') | ||||||
|  |     frag.write('vec3 triangle_aabb[2];') | ||||||
|  |     frag.write('AABBfromMinMax(triangle_aabb, aabb_min, aabb_max);') | ||||||
|  |     frag.write('if (!IntersectAABB(voxel_aabb, triangle_aabb))') | ||||||
|  |     frag.write('    return;') | ||||||
|  |  | ||||||
|     frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);') |     frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);') | ||||||
|     frag.write('vec3 f0 = surfaceF0(basecol, metallic);') |     frag.write('vec3 f0 = surfaceF0(basecol, metallic);') | ||||||
|  |  | ||||||
|     frag.add_uniform('vec3 eye', '_cameraPosition') |     vert.add_uniform('vec3 eye', '_cameraPosition') | ||||||
|     frag.write('vec3 eyeDir = eye - wposition;') |     vert.add_out('vec3 eyeDirGeom') | ||||||
|  |     vert.write('eyeDirGeom = eye - voxpositionGeom;') | ||||||
|  |     frag.write_attrib('vec3 vVec = normalize(eyeDir);') | ||||||
|  |     frag.write_attrib('float dotNV = max(dot(N, vVec), 0.0);') | ||||||
|  |  | ||||||
|     if '_Brdf' in wrd.world_defs: |     if '_Brdf' in wrd.world_defs: | ||||||
|         frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') |         frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') | ||||||
| @ -219,7 +259,7 @@ def make_gi(context_id): | |||||||
|     if '_Irr' in wrd.world_defs: |     if '_Irr' in wrd.world_defs: | ||||||
|         frag.add_include('std/shirr.glsl') |         frag.add_include('std/shirr.glsl') | ||||||
|         frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance') |         frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance') | ||||||
|         frag.write('vec3 envl = shIrradiance(n, shirr);') |         frag.write('vec3 envl = shIrradiance(N, shirr);') | ||||||
|         if '_EnvTex' in wrd.world_defs: |         if '_EnvTex' in wrd.world_defs: | ||||||
|             frag.write('envl /= PI;') |             frag.write('envl /= PI;') | ||||||
|     else: |     else: | ||||||
| @ -228,7 +268,7 @@ def make_gi(context_id): | |||||||
|     if '_Rad' in wrd.world_defs: |     if '_Rad' in wrd.world_defs: | ||||||
|         frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance') |         frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance') | ||||||
|         frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps') |         frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps') | ||||||
|         frag.write('vec3 reflectionWorld = reflect(-eyeDir, n);') |         frag.write('vec3 reflectionWorld = reflect(-vVec, N);') | ||||||
|         frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);') |         frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);') | ||||||
|         frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;') |         frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;') | ||||||
|  |  | ||||||
| @ -240,21 +280,193 @@ def make_gi(context_id): | |||||||
|     frag.write('envl *= albedo;') |     frag.write('envl *= albedo;') | ||||||
|  |  | ||||||
|     if '_Brdf' in wrd.world_defs: |     if '_Brdf' in wrd.world_defs: | ||||||
|         frag.write('envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y);') |         frag.write('vec3 F = f0 + (vec3(1.0) - f0) * pow(1.0 - abs(dot(N, vVec)), 5.0);') | ||||||
|  |         frag.write('envl.rgb *= 1.0 - F;') | ||||||
|     if '_Rad' in wrd.world_defs: |     if '_Rad' in wrd.world_defs: | ||||||
|         frag.write('envl += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);') |         frag.write('envl += prefilteredColor * F;') | ||||||
|     elif '_EnvCol' in wrd.world_defs: |     elif '_EnvCol' in wrd.world_defs: | ||||||
|         frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') |         frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') | ||||||
|         frag.write('envl += backgroundCol * (f0 * envBRDF.x + envBRDF.y);') |         frag.write('envl += backgroundCol * F;') | ||||||
|  |  | ||||||
|     frag.add_uniform('float envmapStrength', link='_envmapStrength') |     frag.add_uniform('float envmapStrength', link='_envmapStrength') | ||||||
|     frag.write('envl *= envmapStrength * occlusion;') |     frag.write('envl *= envmapStrength * occlusion;') | ||||||
|  |  | ||||||
|     frag.write('if (direction_weights.x > 0) {') |     frag.add_include('std/light.glsl') | ||||||
|     frag.write('    vec4 basecol_direction = vec4(min(basecol * direction_weights.x, vec3(1.0)), 1.0);') |     is_shadows = '_ShadowMap' in wrd.world_defs | ||||||
|  |     is_transparent_shadows = '_ShadowMapTransparent' in wrd.world_defs | ||||||
|  |     is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs | ||||||
|  |     is_single_atlas = is_shadows_atlas and '_SingleAtlas' in wrd.world_defs | ||||||
|  |     shadowmap_sun = 'shadowMap' | ||||||
|  |     shadowmap_sun_tr = 'shadowMapTransparent' | ||||||
|  |     if is_shadows_atlas: | ||||||
|  |         shadowmap_sun = 'shadowMapAtlasSun' if not is_single_atlas else 'shadowMapAtlas' | ||||||
|  |         shadowmap_sun_tr = 'shadowMapAtlasSunTransparent' if not is_single_atlas else 'shadowMapAtlasTransparent' | ||||||
|  |         frag.add_uniform('vec2 smSizeUniform', '_shadowMapSize', included=True) | ||||||
|  |  | ||||||
|  |     frag.write('vec3 direct = vec3(0.0);') | ||||||
|  |  | ||||||
|  |     if '_Sun' in wrd.world_defs: | ||||||
|  |         frag.add_uniform('vec3 sunCol', '_sunColor') | ||||||
|  |         frag.add_uniform('vec3 sunDir', '_sunDirection') | ||||||
|  |         frag.write('vec3 svisibility = vec3(1.0);') | ||||||
|  |         frag.write('vec3 sh = normalize(vVec + sunDir);') | ||||||
|  |         frag.write('float sdotNL = dot(N, sunDir);') | ||||||
|  |         frag.write('float sdotNH = dot(N, sh);') | ||||||
|  |         frag.write('float sdotVH = dot(vVec, sh);') | ||||||
|  |         if is_shadows: | ||||||
|  |             frag.add_uniform('bool receiveShadow') | ||||||
|  |             frag.add_uniform(f'sampler2DShadow {shadowmap_sun}', top=True) | ||||||
|  |             if is_transparent_shadows: | ||||||
|  |                 frag.add_uniform(f'sampler2D {shadowmap_sun_tr}', top=True) | ||||||
|  |             frag.add_uniform('float shadowsBias', '_sunShadowsBias') | ||||||
|  |             frag.write('if (receiveShadow) {') | ||||||
|  |             if '_CSM' in wrd.world_defs: | ||||||
|  |                 frag.add_include('std/shadows.glsl') | ||||||
|  |                 frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) | ||||||
|  |                 frag.add_uniform('vec3 eye', '_cameraPosition') | ||||||
|  |                 frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') | ||||||
|  |                 if is_transparent_shadows: | ||||||
|  |                     frag.write(f'{shadowmap_sun_tr},') | ||||||
|  |                 frag.write('eye, P + N * shadowsBias * 10, shadowsBias') | ||||||
|  |                 if is_transparent_shadows: | ||||||
|  |                     frag.write(', false') | ||||||
|  |                 frag.write(');') | ||||||
|  |             else: | ||||||
|  |                 vert.add_out('vec4 lightPositionGeom') | ||||||
|  |                 vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrixSun') | ||||||
|  |                 vert.write('lightPositionGeom = LWVP * vec4(pos.xyz, 1.0);') | ||||||
|  |                 frag.write('vec3 lPos = lightPosition.xyz / lightPosition.w;') | ||||||
|  |                 frag.write('const vec2 smSize = shadowmapSize;') | ||||||
|  |                 frag.write(f'svisibility = PCF({shadowmap_sun},') | ||||||
|  |                 if is_transparent_shadows: | ||||||
|  |                     frag.write(f'{shadowmap_sun_tr},') | ||||||
|  |                 frag.write('lPos.xy, lPos.z - shadowsBias, smSize') | ||||||
|  |                 if is_transparent_shadows: | ||||||
|  |                     frag.write(', false') | ||||||
|  |                 frag.write(');') | ||||||
|  |             frag.write('}') # receiveShadow | ||||||
|  |         frag.write('direct += (lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;') | ||||||
|  |         # sun | ||||||
|  |  | ||||||
|  |     if '_SinglePoint' in wrd.world_defs: | ||||||
|  |         frag.add_uniform('vec3 pointPos', link='_pointPosition') | ||||||
|  |         frag.add_uniform('vec3 pointCol', link='_pointColor') | ||||||
|  |         if '_Spot' in wrd.world_defs: | ||||||
|  |             frag.add_uniform('vec3 spotDir', link='_spotDirection') | ||||||
|  |             frag.add_uniform('vec3 spotRight', link='_spotRight') | ||||||
|  |             frag.add_uniform('vec4 spotData', link='_spotData') | ||||||
|  |         if is_shadows: | ||||||
|  |             frag.add_uniform('bool receiveShadow') | ||||||
|  |             frag.add_uniform('float pointBias', link='_pointShadowsBias') | ||||||
|  |             if '_Spot' in wrd.world_defs: | ||||||
|  |                 # Skip world matrix, already in world-space | ||||||
|  |                 frag.add_uniform('mat4 LWVPSpot[1]', link='_biasLightViewProjectionMatrixSpotArray', included=True) | ||||||
|  |                 frag.add_uniform('sampler2DShadow shadowMapSpot[1]', included=True) | ||||||
|  |                 if is_transparent_shadows: | ||||||
|  |                     frag.add_uniform('sampler2D shadowMapSpotTransparent[1]', included=True) | ||||||
|  |             else: | ||||||
|  |                 frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) | ||||||
|  |                 frag.add_uniform('samplerCubeShadow shadowMapPoint[1]', included=True) | ||||||
|  |                 if is_transparent_shadows: | ||||||
|  |                     frag.add_uniform('samplerCube shadowMapPointTransparent[1]', included=True) | ||||||
|  |         frag.write('direct += sampleLight(') | ||||||
|  |         frag.write('  P, N, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') | ||||||
|  |         if is_shadows: | ||||||
|  |             frag.write(', 0, pointBias, receiveShadow') | ||||||
|  |         if is_transparent_shadows: | ||||||
|  |             frag.write(', opacity != 1.0') | ||||||
|  |         if '_Spot' in wrd.world_defs: | ||||||
|  |             frag.write(', true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight') | ||||||
|  |         frag.write(');') | ||||||
|  |  | ||||||
|  |     if '_Clusters' in wrd.world_defs: | ||||||
|  |         frag.add_include_front('std/clusters.glsl') | ||||||
|  |         frag.add_uniform('vec2 cameraProj', link='_cameraPlaneProj') | ||||||
|  |         frag.add_uniform('vec2 cameraPlane', link='_cameraPlane') | ||||||
|  |         frag.add_uniform('vec4 lightsArray[maxLights * 3]', link='_lightsArray') | ||||||
|  |         frag.add_uniform('sampler2D clustersData', link='_clustersData') | ||||||
|  |         if is_shadows: | ||||||
|  |             frag.add_uniform('bool receiveShadow') | ||||||
|  |             frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) | ||||||
|  |             if is_shadows_atlas: | ||||||
|  |                 if not is_single_atlas: | ||||||
|  |                     frag.add_uniform('sampler2DShadow shadowMapAtlasPoint', included=True) | ||||||
|  |                     if is_transparent_shadows: | ||||||
|  |                         frag.add_uniform('sampler2D shadowMapAtlasPointTransparent', included=True) | ||||||
|  |                 else: | ||||||
|  |                     frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) | ||||||
|  |                     if is_transparent_shadows: | ||||||
|  |                         frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) | ||||||
|  |                 frag.add_uniform('vec4 pointLightDataArray[maxLightsCluster]', link='_pointLightsAtlasArray', included=True) | ||||||
|  |             else: | ||||||
|  |                 frag.add_uniform('samplerCubeShadow shadowMapPoint[4]', included=True) | ||||||
|  |                 frag.add_uniform('samplerCube shadowMapPointTransparent[4]', included=True) | ||||||
|  |  | ||||||
|  |         vert.add_out('vec4 wvppositionGeom') | ||||||
|  |         vert.add_uniform('mat4 VP', '_viewProjectionMatrix') | ||||||
|  |         vert.write('wvppositionGeom = VP * vec4(voxpositionGeom, 1.0);') | ||||||
|  |         # wvpposition.z / wvpposition.w | ||||||
|  |         frag.write('float viewz = linearize((wvpposition.z / wvpposition.w) * 0.5 + 0.5, cameraProj);') | ||||||
|  |         frag.write('int clusterI = getClusterI((wvpposition.xy / wvpposition.w) * 0.5 + 0.5, viewz, cameraPlane);') | ||||||
|  |         frag.write('int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255);') | ||||||
|  |  | ||||||
|  |         frag.write('#ifdef HLSL') | ||||||
|  |         frag.write('viewz += texture(clustersData, vec2(0.0)).r * 1e-9;') # TODO: krafix bug, needs to generate sampler | ||||||
|  |         frag.write('#endif') | ||||||
|  |  | ||||||
|  |         if '_Spot' in wrd.world_defs: | ||||||
|  |             frag.add_uniform('vec4 lightsArraySpot[maxLights * 2]', link='_lightsArraySpot') | ||||||
|  |             frag.write('int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255);') | ||||||
|  |             frag.write('int numPoints = numLights - numSpots;') | ||||||
|  |             if is_shadows: | ||||||
|  |                 if is_shadows_atlas: | ||||||
|  |                     if not is_single_atlas: | ||||||
|  |                         frag.add_uniform('sampler2DShadow shadowMapAtlasSpot', included=True) | ||||||
|  |                         if is_transparent_shadows: | ||||||
|  |                             frag.add_uniform('sampler2D shadowMapAtlasSpotTransparent', included=True) | ||||||
|  |                     else: | ||||||
|  |                         frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) | ||||||
|  |                         if is_transparent_shadows: | ||||||
|  |                             frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) | ||||||
|  |                 else: | ||||||
|  |                     frag.add_uniform('sampler2DShadow shadowMapSpot[4]', included=True) | ||||||
|  |                     if is_transparent_shadows: | ||||||
|  |                         frag.add_uniform('sampler2D shadowMapSpotTransparent[4]', included=True) | ||||||
|  |                 frag.add_uniform('mat4 LWVPSpotArray[maxLightsCluster]', link='_biasLightWorldViewProjectionMatrixSpotArray', included=True) | ||||||
|  |  | ||||||
|  |         frag.write('for (int i = 0; i < min(numLights, maxLightsCluster); i++) {') | ||||||
|  |         frag.write('int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255);') | ||||||
|  |         frag.write('direct += sampleLightVoxels(') | ||||||
|  |         frag.write('    P,') | ||||||
|  |         frag.write('    N,') | ||||||
|  |         frag.write('    vVec,') | ||||||
|  |         frag.write('    dotNV,') | ||||||
|  |         frag.write('    lightsArray[li * 3].xyz,') # lp | ||||||
|  |         frag.write('    lightsArray[li * 3 + 1].xyz,') # lightCol | ||||||
|  |         frag.write('    albedo,') | ||||||
|  |         frag.write('    roughness,') | ||||||
|  |         frag.write('    specular,') | ||||||
|  |         frag.write('    f0') | ||||||
|  |         if is_shadows: | ||||||
|  |             frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0') # bias | ||||||
|  |         if is_transparent_shadows: | ||||||
|  |             frag.write('\t, opacity != 1.0') | ||||||
|  |         if '_Spot' in wrd.world_defs: | ||||||
|  |             frag.write('\t, lightsArray[li * 3 + 2].y != 0.0') | ||||||
|  |             frag.write('\t, lightsArray[li * 3 + 2].y') # spot size (cutoff) | ||||||
|  |             frag.write('\t, lightsArraySpot[li * 2].w') # spot blend (exponent) | ||||||
|  |             frag.write('\t, lightsArraySpot[li * 2].xyz') # spotDir | ||||||
|  |             frag.write('\t, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w)') # scale | ||||||
|  |             frag.write('\t, lightsArraySpot[li * 2 + 1].xyz') # right | ||||||
|  |         frag.write('    );') | ||||||
|  |         frag.write('}') | ||||||
|  |  | ||||||
|  |     frag.write('if (direction_weights.x > 0.0) {') | ||||||
|  |     frag.write('    vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.x;') | ||||||
|     frag.write('    vec3 emission_direction = emissionCol * direction_weights.x;') |     frag.write('    vec3 emission_direction = emissionCol * direction_weights.x;') | ||||||
|     frag.write('    vec2 normal_direction = encode_oct(N * direction_weights.x) * 0.5 + 0.5;') |     frag.write('    vec2 normal_direction = encode_oct(N * direction_weights.x) * 0.5 + 0.5;') | ||||||
|     frag.write('    vec3 envl_direction = envl * direction_weights.x;') |     frag.write('    vec3 envl_direction = envl * direction_weights.x;') | ||||||
|  |     frag.write('    vec3 light_direction = direct * direction_weights.x;') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(basecol_direction.r * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(basecol_direction.r * 255));') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') | ||||||
| @ -267,13 +479,18 @@ def make_gi(context_id): | |||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 15)), uint(1));') | ||||||
|     frag.write('}') |     frag.write('}') | ||||||
|  |  | ||||||
|     frag.write('if (direction_weights.y > 0) {') |     frag.write('if (direction_weights.y > 0.0) {') | ||||||
|     frag.write('    vec4 basecol_direction = vec4(min(basecol * direction_weights.y, vec3(1.0)), 1.0);') |     frag.write('    vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.y;') | ||||||
|     frag.write('    vec3 emission_direction = emissionCol * direction_weights.y;') |     frag.write('    vec3 emission_direction = emissionCol * direction_weights.y;') | ||||||
|     frag.write('    vec2 normal_direction = encode_oct(N * direction_weights.y) * 0.5 + 0.5;') |     frag.write('    vec2 normal_direction = encode_oct(N * direction_weights.y) * 0.5 + 0.5;') | ||||||
|     frag.write('    vec3 envl_direction = envl * direction_weights.y;') |     frag.write('    vec3 envl_direction = envl * direction_weights.y;') | ||||||
|  |     frag.write('    vec3 light_direction = direct * direction_weights.y;') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(basecol_direction.r * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(basecol_direction.r * 255));') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') | ||||||
| @ -286,13 +503,18 @@ def make_gi(context_id): | |||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 15)), uint(1));') | ||||||
|     frag.write('}') |     frag.write('}') | ||||||
|  |  | ||||||
|     frag.write('if (direction_weights.z > 0) {') |     frag.write('if (direction_weights.z > 0.0) {') | ||||||
|     frag.write('    vec4 basecol_direction = vec4(min(basecol * direction_weights.z, vec3(1.0)), 1.0);') |     frag.write('    vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.z;') | ||||||
|     frag.write('    vec3 emission_direction = emissionCol * direction_weights.z;') |     frag.write('    vec3 emission_direction = emissionCol * direction_weights.z;') | ||||||
|     frag.write('    vec2 normal_direction = encode_oct(n * direction_weights.z) * 0.5 + 0.5;') |     frag.write('    vec2 normal_direction = encode_oct(N * direction_weights.z) * 0.5 + 0.5;') | ||||||
|     frag.write('    vec3 envl_direction = envl * direction_weights.z;') |     frag.write('    vec3 envl_direction = envl * direction_weights.z;') | ||||||
|  |     frag.write('    vec3 light_direction = direct * direction_weights.z;') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(basecol_direction.r * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(basecol_direction.r * 255));') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') | ||||||
| @ -305,6 +527,10 @@ def make_gi(context_id): | |||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 15)), uint(1));') | ||||||
|     frag.write('}') |     frag.write('}') | ||||||
|  |  | ||||||
|     return con_voxel |     return con_voxel | ||||||
| @ -328,6 +554,7 @@ def make_ao(context_id): | |||||||
|     geom.add_include('compiled.inc') |     geom.add_include('compiled.inc') | ||||||
|     frag.add_include('std/math.glsl') |     frag.add_include('std/math.glsl') | ||||||
|     frag.add_include('std/imageatomic.glsl') |     frag.add_include('std/imageatomic.glsl') | ||||||
|  |     frag.add_include('std/aabb.glsl') | ||||||
|     frag.write_header('#extension GL_ARB_shader_image_load_store : enable') |     frag.write_header('#extension GL_ARB_shader_image_load_store : enable') | ||||||
|  |  | ||||||
|     vert.add_include('compiled.inc') |     vert.add_include('compiled.inc') | ||||||
| @ -447,9 +674,15 @@ def make_ao(context_id): | |||||||
|     geom.add_out('vec4 voxposition[3]') |     geom.add_out('vec4 voxposition[3]') | ||||||
|     geom.add_out('vec3 P') |     geom.add_out('vec3 P') | ||||||
|     geom.add_out('vec3 voxnormal') |     geom.add_out('vec3 voxnormal') | ||||||
|  |     geom.add_out('vec3 aabb_min') | ||||||
|  |     geom.add_out('vec3 aabb_max') | ||||||
|  |  | ||||||
|     geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') |     geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') | ||||||
|     geom.add_uniform('int clipmapLevel', '_clipmapLevel') |     geom.add_uniform('int clipmapLevel', '_clipmapLevel') | ||||||
|  |  | ||||||
|  |     geom.write('aabb_min = min(voxpositionGeom[0].xyz, min(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') | ||||||
|  |     geom.write('aabb_max = max(voxpositionGeom[0].xyz, max(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') | ||||||
|  |  | ||||||
|     geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') |     geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') | ||||||
|     geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') |     geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') | ||||||
|     geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') |     geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') | ||||||
| @ -466,6 +699,13 @@ def make_ao(context_id): | |||||||
|     geom.write('    }') |     geom.write('    }') | ||||||
|     geom.write('}') |     geom.write('}') | ||||||
|  |  | ||||||
|  |     geom.write('vec2 side0N = normalize(voxposition[1].xy - voxposition[0].xy);') | ||||||
|  |     geom.write('vec2 side1N = normalize(voxposition[2].xy - voxposition[1].xy);') | ||||||
|  |     geom.write('vec2 side2N = normalize(voxposition[0].xy - voxposition[2].xy);') | ||||||
|  |     geom.write('voxposition[0].xy += normalize(side2N - side0N);') | ||||||
|  |     geom.write('voxposition[1].xy += normalize(side0N - side1N);') | ||||||
|  |     geom.write('voxposition[2].xy += normalize(side1N - side2N);') | ||||||
|  |  | ||||||
|     geom.write('for (uint i = 0; i < 3; ++i) {') |     geom.write('for (uint i = 0; i < 3; ++i) {') | ||||||
|     geom.write('    voxposition[i].xy /= voxelgiResolution.xy;') |     geom.write('    voxposition[i].xy /= voxelgiResolution.xy;') | ||||||
|     geom.write('    voxposition[i].zw = vec2(1.0);') |     geom.write('    voxposition[i].zw = vec2(1.0);') | ||||||
| @ -476,7 +716,6 @@ def make_ao(context_id): | |||||||
|     geom.write('}') |     geom.write('}') | ||||||
|     geom.write('EndPrimitive();') |     geom.write('EndPrimitive();') | ||||||
|  |  | ||||||
|  |  | ||||||
|     frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') |     frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') | ||||||
|     frag.add_uniform('int clipmapLevel', '_clipmapLevel') |     frag.add_uniform('int clipmapLevel', '_clipmapLevel') | ||||||
|  |  | ||||||
| @ -493,16 +732,38 @@ def make_ao(context_id): | |||||||
|     frag.write('    ) * voxelgiResolution;') |     frag.write('    ) * voxelgiResolution;') | ||||||
|     frag.write('vec3 direction_weights = abs(N);') |     frag.write('vec3 direction_weights = abs(N);') | ||||||
|  |  | ||||||
|     frag.write('if (direction_weights.x > 0) {') |     frag.write('vec3 clipmap_pixel = uvw * voxelgiResolution;') | ||||||
|  |     frag.write('vec3 clipmap_uvw_center = (clipmap_pixel + 0.5) / voxelgiResolution;') | ||||||
|  |     frag.write('vec3 voxel_center = clipmap_uvw_center * 2.0 - 1.0;') | ||||||
|  |     frag.write('float voxel_size = float(clipmaps[int(clipmapLevel * 10)]);') | ||||||
|  |     frag.write('voxel_center *= voxel_size;') | ||||||
|  |     frag.write('voxel_center *= voxelgiResolution.x;') | ||||||
|  |     frag.write('voxel_center += vec3(') | ||||||
|  |     frag.write('    clipmaps[clipmapLevel * 10 + 4],') | ||||||
|  |     frag.write('    clipmaps[clipmapLevel * 10 + 5],') | ||||||
|  |     frag.write('    clipmaps[clipmapLevel * 10 + 6]);') | ||||||
|  |  | ||||||
|  |     frag.write('vec3 voxel_aabb[2];') | ||||||
|  |     frag.write('voxel_aabb[0] = voxel_center;') | ||||||
|  |     frag.write('voxel_aabb[1] = vec3(voxel_size);') | ||||||
|  |     frag.write('vec3 triangle_aabb[2];') | ||||||
|  |     frag.write('AABBfromMinMax(triangle_aabb, aabb_min, aabb_max);') | ||||||
|  |     frag.write('if (!IntersectAABB(voxel_aabb, triangle_aabb))') | ||||||
|  |     frag.write('    return;') | ||||||
|  |  | ||||||
|  |     frag.write('if (direction_weights.x > 0.0) {') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(direction_weights.x * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(direction_weights.x * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(1));') | ||||||
|     frag.write('}') |     frag.write('}') | ||||||
|  |  | ||||||
|     frag.write('if (direction_weights.y > 0) {') |     frag.write('if (direction_weights.y > 0.0) {') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(direction_weights.y * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(direction_weights.y * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(1));') | ||||||
|     frag.write('}') |     frag.write('}') | ||||||
|  |  | ||||||
|     frag.write('if (direction_weights.z > 0) {') |     frag.write('if (direction_weights.z > 0.0) {') | ||||||
|     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(direction_weights.z * 255));') |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(direction_weights.z * 255));') | ||||||
|  |     frag.write('    imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(1));') | ||||||
|     frag.write('}') |     frag.write('}') | ||||||
|  |  | ||||||
|     return con_voxel |     return con_voxel | ||||||
|  | |||||||
| @ -305,6 +305,7 @@ def init_properties(): | |||||||
|         name="Assertion Level", description="Ignore all assertions below this level (assertions are turned off completely for published builds)", default='Warning', update=assets.invalidate_compiler_cache) |         name="Assertion Level", description="Ignore all assertions below this level (assertions are turned off completely for published builds)", default='Warning', update=assets.invalidate_compiler_cache) | ||||||
|     bpy.types.World.lnx_assert_quit = BoolProperty(name="Quit On Assertion Fail", description="Whether to close the game when an 'Error' level assertion fails", default=False, update=assets.invalidate_compiler_cache) |     bpy.types.World.lnx_assert_quit = BoolProperty(name="Quit On Assertion Fail", description="Whether to close the game when an 'Error' level assertion fails", default=False, update=assets.invalidate_compiler_cache) | ||||||
|     bpy.types.World.lnx_live_patch = BoolProperty(name="Live Patch", description="Live patching for Krom", default=False) |     bpy.types.World.lnx_live_patch = BoolProperty(name="Live Patch", description="Live patching for Krom", default=False) | ||||||
|  |     bpy.types.World.lnx_render_viewport = BoolProperty(name="Viewport Render", description="Viewport rendering", default=False) | ||||||
|     bpy.types.World.lnx_clear_on_compile = BoolProperty(name="Clear Console", description="Clears the system console on compile", default=False) |     bpy.types.World.lnx_clear_on_compile = BoolProperty(name="Clear Console", description="Clears the system console on compile", default=False) | ||||||
|     bpy.types.World.lnx_play_camera = EnumProperty( |     bpy.types.World.lnx_play_camera = EnumProperty( | ||||||
|         items=[('Scene', 'Scene', 'Scene'), |         items=[('Scene', 'Scene', 'Scene'), | ||||||
|  | |||||||
| @ -65,8 +65,8 @@ def update_preset(self, context): | |||||||
|         rpdat.rp_background = 'World' |         rpdat.rp_background = 'World' | ||||||
|         rpdat.rp_stereo = False |         rpdat.rp_stereo = False | ||||||
|         rpdat.rp_voxelgi_resolution = '32' |         rpdat.rp_voxelgi_resolution = '32' | ||||||
|         rpdat.lnx_voxelgi_size = 0.25 |         rpdat.lnx_voxelgi_size = 0.125 | ||||||
|         rpdat.rp_voxels = 'Voxel AO' |         rpdat.rp_voxels = 'Voxel GI' | ||||||
|         rpdat.rp_render_to_texture = True |         rpdat.rp_render_to_texture = True | ||||||
|         rpdat.rp_supersampling = '1' |         rpdat.rp_supersampling = '1' | ||||||
|         rpdat.rp_antialiasing = 'SMAA' |         rpdat.rp_antialiasing = 'SMAA' | ||||||
| @ -142,8 +142,8 @@ def update_preset(self, context): | |||||||
|         rpdat.rp_stereo = False |         rpdat.rp_stereo = False | ||||||
|         rpdat.rp_voxels = 'Voxel GI' |         rpdat.rp_voxels = 'Voxel GI' | ||||||
|         rpdat.rp_voxelgi_resolution = '64' |         rpdat.rp_voxelgi_resolution = '64' | ||||||
|         rpdat.lnx_voxelgi_size = 0.25 |         rpdat.lnx_voxelgi_size = 0.125 | ||||||
|         rpdat.lnx_voxelgi_step = 0.25 |         rpdat.lnx_voxelgi_step = 0.01 | ||||||
|         rpdat.lnx_voxelgi_revoxelize = False |         rpdat.lnx_voxelgi_revoxelize = False | ||||||
|         rpdat.lnx_voxelgi_camera = False |         rpdat.lnx_voxelgi_camera = False | ||||||
|         rpdat.rp_voxelgi_emission = False |         rpdat.rp_voxelgi_emission = False | ||||||
| @ -152,7 +152,7 @@ def update_preset(self, context): | |||||||
|         rpdat.rp_antialiasing = 'TAA' |         rpdat.rp_antialiasing = 'TAA' | ||||||
|         rpdat.rp_compositornodes = True |         rpdat.rp_compositornodes = True | ||||||
|         rpdat.rp_volumetriclight = False |         rpdat.rp_volumetriclight = False | ||||||
|         rpdat.rp_ssgi = 'RTAO' |         rpdat.rp_ssgi = 'SSGI' | ||||||
|         rpdat.lnx_ssrs = False |         rpdat.lnx_ssrs = False | ||||||
|         rpdat.lnx_micro_shadowing = True |         rpdat.lnx_micro_shadowing = True | ||||||
|         rpdat.rp_ssr = True |         rpdat.rp_ssr = True | ||||||
| @ -330,6 +330,7 @@ class LnxRPListItem(bpy.types.PropertyGroup): | |||||||
|     rp_shadowmap_atlas: BoolProperty(name="Shadow Map Atlasing", description="Group shadow maps of lights of the same type in the same texture", default=False, update=update_renderpath) |     rp_shadowmap_atlas: BoolProperty(name="Shadow Map Atlasing", description="Group shadow maps of lights of the same type in the same texture", default=False, update=update_renderpath) | ||||||
|     rp_shadowmap_atlas_single_map: BoolProperty(name="Shadow Map Atlas single map", description="Use a single texture for all different light types.", default=False, update=update_renderpath) |     rp_shadowmap_atlas_single_map: BoolProperty(name="Shadow Map Atlas single map", description="Use a single texture for all different light types.", default=False, update=update_renderpath) | ||||||
|     rp_shadowmap_atlas_lod: BoolProperty(name="Shadow Map Atlas LOD (Experimental)", description="When enabled, the size of the shadow map will be determined on runtime based on the distance of the light to the camera", default=False, update=update_renderpath) |     rp_shadowmap_atlas_lod: BoolProperty(name="Shadow Map Atlas LOD (Experimental)", description="When enabled, the size of the shadow map will be determined on runtime based on the distance of the light to the camera", default=False, update=update_renderpath) | ||||||
|  |     rp_shadowmap_transparent: BoolProperty(name="Transparency", description="Enable shadows for transparent objects", default=False, update=update_renderpath) | ||||||
|     rp_shadowmap_atlas_lod_subdivisions: EnumProperty( |     rp_shadowmap_atlas_lod_subdivisions: EnumProperty( | ||||||
|         items=[('2', '2', '2'), |         items=[('2', '2', '2'), | ||||||
|                ('3', '3', '3'), |                ('3', '3', '3'), | ||||||
| @ -391,7 +392,8 @@ class LnxRPListItem(bpy.types.PropertyGroup): | |||||||
|     rp_ssgi: EnumProperty( |     rp_ssgi: EnumProperty( | ||||||
|         items=[('Off', 'No AO', 'Off'), |         items=[('Off', 'No AO', 'Off'), | ||||||
|                ('SSAO', 'SSAO', 'Screen space ambient occlusion'), |                ('SSAO', 'SSAO', 'Screen space ambient occlusion'), | ||||||
|                ('RTAO', 'RTAO', 'Ray-traced ambient occlusion') |                ('SSGI', 'SSGI', 'Screen space global illumination') | ||||||
|  |                #('RTAO', 'RTAO', 'Ray-traced ambient occlusion') | ||||||
|                # ('RTGI', 'RTGI', 'Ray-traced global illumination') |                # ('RTGI', 'RTGI', 'Ray-traced global illumination') | ||||||
|                ], |                ], | ||||||
|         name="SSGI", description="Screen space global illumination", default='SSAO', update=update_renderpath) |         name="SSGI", description="Screen space global illumination", default='SSAO', update=update_renderpath) | ||||||
| @ -508,7 +510,7 @@ class LnxRPListItem(bpy.types.PropertyGroup): | |||||||
|         	   ('1', '1', '1'), |         	   ('1', '1', '1'), | ||||||
|                ('2', '2', '2')], |                ('2', '2', '2')], | ||||||
|         name="Bounces", description="Trace multiple light bounces", default='1', update=update_renderpath) |         name="Bounces", description="Trace multiple light bounces", default='1', update=update_renderpath) | ||||||
|     lnx_voxelgi_clipmap_count: IntProperty(name="Clipmap count", description="Number of clipmaps", default=3, update=assets.invalidate_compiled_data) |     lnx_voxelgi_clipmap_count: IntProperty(name="Clipmap count", description="Number of clipmaps", default=5, update=assets.invalidate_compiled_data) | ||||||
|     lnx_voxelgi_temporal: BoolProperty(name="Temporal Filter", description="Use temporal filtering to stabilize voxels", default=False, update=assets.invalidate_shader_cache) |     lnx_voxelgi_temporal: BoolProperty(name="Temporal Filter", description="Use temporal filtering to stabilize voxels", default=False, update=assets.invalidate_shader_cache) | ||||||
|     lnx_voxelgi_shadows: BoolProperty(name="Shadows", description="Use voxels to render shadows", default=False, update=update_renderpath) |     lnx_voxelgi_shadows: BoolProperty(name="Shadows", description="Use voxels to render shadows", default=False, update=update_renderpath) | ||||||
|     lnx_samples_per_pixel: EnumProperty( |     lnx_samples_per_pixel: EnumProperty( | ||||||
| @ -530,9 +532,10 @@ class LnxRPListItem(bpy.types.PropertyGroup): | |||||||
|     lnx_voxelgi_spec: FloatProperty(name="Reflection", description="", default=1.0, update=assets.invalidate_shader_cache) |     lnx_voxelgi_spec: FloatProperty(name="Reflection", description="", default=1.0, update=assets.invalidate_shader_cache) | ||||||
|     lnx_voxelgi_refr: FloatProperty(name="Refraction", description="", default=1.0, update=assets.invalidate_shader_cache) |     lnx_voxelgi_refr: FloatProperty(name="Refraction", description="", default=1.0, update=assets.invalidate_shader_cache) | ||||||
|     lnx_voxelgi_shad: FloatProperty(name="Shadows", description="Contrast for voxels shadows", default=1.0, update=assets.invalidate_shader_cache) |     lnx_voxelgi_shad: FloatProperty(name="Shadows", description="Contrast for voxels shadows", default=1.0, update=assets.invalidate_shader_cache) | ||||||
|  |     lnx_voxelgi_env: FloatProperty(name="Environment", description="", default=1.0, update=assets.invalidate_shader_cache) | ||||||
|     lnx_voxelgi_occ: FloatProperty(name="Occlusion", description="", default=1.0, update=assets.invalidate_shader_cache) |     lnx_voxelgi_occ: FloatProperty(name="Occlusion", description="", default=1.0, update=assets.invalidate_shader_cache) | ||||||
|     lnx_voxelgi_size: FloatProperty(name="Size", description="Voxel size", default=0.25, update=assets.invalidate_shader_cache) |     lnx_voxelgi_size: FloatProperty(name="Size", description="Voxel size", default=0.25, update=assets.invalidate_shader_cache) | ||||||
|     lnx_voxelgi_step: FloatProperty(name="Step", description="Step size", default=0.25, update=assets.invalidate_shader_cache) |     lnx_voxelgi_step: FloatProperty(name="Step", description="Step size", default=1.0, update=assets.invalidate_shader_cache) | ||||||
|     lnx_voxelgi_range: FloatProperty(name="Range", description="Maximum range", default=100.0, update=assets.invalidate_shader_cache) |     lnx_voxelgi_range: FloatProperty(name="Range", description="Maximum range", default=100.0, update=assets.invalidate_shader_cache) | ||||||
|     lnx_voxelgi_offset: FloatProperty(name="Offset", description="Multiplicative Offset for dealing with self occlusion", default=1.0, update=assets.invalidate_shader_cache) |     lnx_voxelgi_offset: FloatProperty(name="Offset", description="Multiplicative Offset for dealing with self occlusion", default=1.0, update=assets.invalidate_shader_cache) | ||||||
|     lnx_voxelgi_aperture: FloatProperty(name="Aperture", description="Cone aperture for shadow trace", default=0.0, update=assets.invalidate_shader_cache) |     lnx_voxelgi_aperture: FloatProperty(name="Aperture", description="Cone aperture for shadow trace", default=0.0, update=assets.invalidate_shader_cache) | ||||||
| @ -545,15 +548,17 @@ class LnxRPListItem(bpy.types.PropertyGroup): | |||||||
|     lnx_water_density: FloatProperty(name="Density", default=1.0, update=assets.invalidate_shader_cache) |     lnx_water_density: FloatProperty(name="Density", default=1.0, update=assets.invalidate_shader_cache) | ||||||
|     lnx_water_refract: FloatProperty(name="Refract", default=1.0, update=assets.invalidate_shader_cache) |     lnx_water_refract: FloatProperty(name="Refract", default=1.0, update=assets.invalidate_shader_cache) | ||||||
|     lnx_water_reflect: FloatProperty(name="Reflect", default=1.0, update=assets.invalidate_shader_cache) |     lnx_water_reflect: FloatProperty(name="Reflect", default=1.0, update=assets.invalidate_shader_cache) | ||||||
|     lnx_ssgi_strength: FloatProperty(name="Strength", default=1.0, update=assets.invalidate_shader_cache) |     lnx_ssgi_strength: FloatProperty(name="Strength", default=1.250, update=assets.invalidate_shader_cache) | ||||||
|     lnx_ssgi_radius: FloatProperty(name="Radius", default=1.0, update=assets.invalidate_shader_cache) |     lnx_ssgi_radius: FloatProperty(name="Radius", default=0.750, update=assets.invalidate_shader_cache) | ||||||
|     lnx_ssgi_step: FloatProperty(name="Step", default=2.0, update=assets.invalidate_shader_cache) |     lnx_ssgi_step: FloatProperty(name="Step", default=2.0, update=assets.invalidate_shader_cache) | ||||||
|     lnx_ssgi_max_steps: IntProperty(name="Max Steps", default=8, update=assets.invalidate_shader_cache) |     lnx_ssgi_samples: IntProperty(name="Samples", default=32, update=assets.invalidate_shader_cache) | ||||||
|  |     """ | ||||||
|     lnx_ssgi_rays: EnumProperty( |     lnx_ssgi_rays: EnumProperty( | ||||||
|         items=[('9', '9', '9'), |         items=[('9', '9', '9'), | ||||||
|                ('5', '5', '5'), |                ('5', '5', '5'), | ||||||
|                ], |                ], | ||||||
|         name="Rays", description="Number of rays to trace for RTAO", default='5', update=assets.invalidate_shader_cache) |         name="Rays", description="Number of rays to trace for RTAO", default='5', update=assets.invalidate_shader_cache) | ||||||
|  |     """ | ||||||
|     lnx_ssgi_half_res: BoolProperty(name="Half Res", description="Trace in half resolution", default=False, update=assets.invalidate_shader_cache) |     lnx_ssgi_half_res: BoolProperty(name="Half Res", description="Trace in half resolution", default=False, update=assets.invalidate_shader_cache) | ||||||
|     lnx_bloom_threshold: FloatProperty(name="Threshold", description="Brightness above which a pixel is contributing to the bloom effect", min=0, default=0.8, update=assets.invalidate_shader_cache) |     lnx_bloom_threshold: FloatProperty(name="Threshold", description="Brightness above which a pixel is contributing to the bloom effect", min=0, default=0.8, update=assets.invalidate_shader_cache) | ||||||
|     lnx_bloom_knee: FloatProperty(name="Knee", description="Smoothen transition around the threshold (higher values = smoother transition)", min=0, max=1, default=0.5, update=assets.invalidate_shader_cache) |     lnx_bloom_knee: FloatProperty(name="Knee", description="Smoothen transition around the threshold (higher values = smoother transition)", min=0, max=1, default=0.5, update=assets.invalidate_shader_cache) | ||||||
|  | |||||||
| @ -1730,6 +1730,7 @@ class LNX_PT_RenderPathShadowsPanel(bpy.types.Panel): | |||||||
|         col.prop(rpdat, 'rp_shadowmap_cube') |         col.prop(rpdat, 'rp_shadowmap_cube') | ||||||
|         layout.prop(rpdat, 'rp_shadowmap_cascade') |         layout.prop(rpdat, 'rp_shadowmap_cascade') | ||||||
|         layout.prop(rpdat, 'rp_shadowmap_cascades') |         layout.prop(rpdat, 'rp_shadowmap_cascades') | ||||||
|  |         layout.prop(rpdat, 'rp_shadowmap_transparent') | ||||||
|         col = layout.column() |         col = layout.column() | ||||||
|         col2 = col.column() |         col2 = col.column() | ||||||
|         col2.enabled = rpdat.rp_shadowmap_cascades != '1' |         col2.enabled = rpdat.rp_shadowmap_cascades != '1' | ||||||
| @ -1861,7 +1862,7 @@ class LNX_PT_RenderPathVoxelsPanel(bpy.types.Panel): | |||||||
|         col3.enabled = rpdat.rp_voxels == 'Voxel AO' |         col3.enabled = rpdat.rp_voxels == 'Voxel AO' | ||||||
|         col.prop(rpdat, 'lnx_voxelgi_shadows', text='Shadows') |         col.prop(rpdat, 'lnx_voxelgi_shadows', text='Shadows') | ||||||
|         col2.prop(rpdat, 'lnx_voxelgi_refract', text='Refraction') |         col2.prop(rpdat, 'lnx_voxelgi_refract', text='Refraction') | ||||||
|         col.prop(rpdat, 'lnx_voxelgi_clipmap_count') |         #col.prop(rpdat, 'lnx_voxelgi_clipmap_count') | ||||||
|         #col.prop(rpdat, 'lnx_voxelgi_cones') |         #col.prop(rpdat, 'lnx_voxelgi_cones') | ||||||
|         col.prop(rpdat, 'rp_voxelgi_resolution') |         col.prop(rpdat, 'rp_voxelgi_resolution') | ||||||
|         col.prop(rpdat, 'lnx_voxelgi_size') |         col.prop(rpdat, 'lnx_voxelgi_size') | ||||||
| @ -1875,9 +1876,10 @@ class LNX_PT_RenderPathVoxelsPanel(bpy.types.Panel): | |||||||
|         col2.prop(rpdat, 'lnx_voxelgi_spec') |         col2.prop(rpdat, 'lnx_voxelgi_spec') | ||||||
|         col2.prop(rpdat, 'lnx_voxelgi_refr') |         col2.prop(rpdat, 'lnx_voxelgi_refr') | ||||||
|         col.prop(rpdat, 'lnx_voxelgi_shad') |         col.prop(rpdat, 'lnx_voxelgi_shad') | ||||||
|  |         col.prop(rpdat, 'lnx_voxelgi_env') | ||||||
|         col.prop(rpdat, 'lnx_voxelgi_occ') |         col.prop(rpdat, 'lnx_voxelgi_occ') | ||||||
|         col.label(text="Ray") |         col.label(text="Ray") | ||||||
|         col.prop(rpdat, 'lnx_voxelgi_offset') |         #col.prop(rpdat, 'lnx_voxelgi_offset') | ||||||
|         col.prop(rpdat, 'lnx_voxelgi_step') |         col.prop(rpdat, 'lnx_voxelgi_step') | ||||||
|         col.prop(rpdat, 'lnx_voxelgi_range') |         col.prop(rpdat, 'lnx_voxelgi_range') | ||||||
|         #col.prop(rpdat, 'lnx_voxelgi_aperture') |         #col.prop(rpdat, 'lnx_voxelgi_aperture') | ||||||
| @ -1968,10 +1970,10 @@ class LNX_PT_RenderPathPostProcessPanel(bpy.types.Panel): | |||||||
|         sub = col.column() |         sub = col.column() | ||||||
|         sub.enabled = rpdat.rp_ssgi != 'Off' |         sub.enabled = rpdat.rp_ssgi != 'Off' | ||||||
|         sub.prop(rpdat, 'lnx_ssgi_half_res') |         sub.prop(rpdat, 'lnx_ssgi_half_res') | ||||||
|         sub.prop(rpdat, 'lnx_ssgi_rays') |         #sub.prop(rpdat, 'lnx_ssgi_rays') | ||||||
|         sub.prop(rpdat, 'lnx_ssgi_radius') |         sub.prop(rpdat, 'lnx_ssgi_radius') | ||||||
|         sub.prop(rpdat, 'lnx_ssgi_strength') |         sub.prop(rpdat, 'lnx_ssgi_strength') | ||||||
|         sub.prop(rpdat, 'lnx_ssgi_max_steps') |         sub.prop(rpdat, 'lnx_ssgi_samples') | ||||||
|         layout.separator() |         layout.separator() | ||||||
|  |  | ||||||
|         row = layout.row() |         row = layout.row() | ||||||
|  | |||||||
| @ -207,6 +207,8 @@ project.addSources('Sources'); | |||||||
|                 # get instantiated |                 # get instantiated | ||||||
|                 khafile.write("""project.addParameter("--macro include('leenkx.logicnode')");\n""") |                 khafile.write("""project.addParameter("--macro include('leenkx.logicnode')");\n""") | ||||||
|  |  | ||||||
|  |         if wrd.lnx_render_viewport: | ||||||
|  |             assets.add_khafile_def('lnx_render_viewport') | ||||||
|         import_traits = list(set(import_traits)) |         import_traits = list(set(import_traits)) | ||||||
|         for i in range(0, len(import_traits)): |         for i in range(0, len(import_traits)): | ||||||
|             khafile.write("project.addParameter('" + import_traits[i] + "');\n") |             khafile.write("project.addParameter('" + import_traits[i] + "');\n") | ||||||
| @ -625,32 +627,18 @@ def write_compiledglsl(defs, make_variants): | |||||||
|  |  | ||||||
|             idx_emission = 2 |             idx_emission = 2 | ||||||
|             idx_refraction = 2 |             idx_refraction = 2 | ||||||
|  |              | ||||||
|             if '_gbuffer2' in wrd.world_defs: |             if '_gbuffer2' in wrd.world_defs: | ||||||
|                 f.write('#define GBUF_IDX_2 2\n') |                 f.write('#define GBUF_IDX_2 2\n') | ||||||
|                 idx_emission += 1 |                 idx_emission += 1 | ||||||
|                 idx_refraction += 1 |                 idx_refraction += 1 | ||||||
|  |  | ||||||
|             # Special case for WebGL with both TAA and SSRefraction |             if '_EmissionShaded' in wrd.world_defs: | ||||||
|             webgl_with_taa_refr = ('_kha_webgl' in wrd.world_defs and  |                 f.write(f'#define GBUF_IDX_EMISSION {idx_emission}\n') | ||||||
|                                  ('_SSRefraction' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs) and  |                 idx_refraction += 1 | ||||||
|                                  ('_TAA' in wrd.world_defs or '_SMAA' in wrd.world_defs)) |  | ||||||
|  |  | ||||||
|             if webgl_with_taa_refr: |             if '_SSRefraction' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs: | ||||||
|                 # WebGL needs refraction to come before emission for correct rendering |                 f.write(f'#define GBUF_IDX_REFRACTION {idx_refraction}\n') | ||||||
|                 if '_SSRefraction' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs: |  | ||||||
|                     f.write(f'#define GBUF_IDX_REFRACTION {idx_emission}\n') |  | ||||||
|                     idx_emission += 1 |  | ||||||
|                  |  | ||||||
|                 if '_EmissionShaded' in wrd.world_defs: |  | ||||||
|                     f.write(f'#define GBUF_IDX_EMISSION {idx_emission}\n') |  | ||||||
|             else: |  | ||||||
|                 # Standard order for all other platforms |  | ||||||
|                 if '_EmissionShaded' in wrd.world_defs: |  | ||||||
|                     f.write(f'#define GBUF_IDX_EMISSION {idx_emission}\n') |  | ||||||
|                     idx_refraction += 1 |  | ||||||
|  |  | ||||||
|                 if '_SSRefraction' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs: |  | ||||||
|                     f.write(f'#define GBUF_IDX_REFRACTION {idx_refraction}\n') |  | ||||||
|  |  | ||||||
|         f.write("""#if defined(HLSL) || defined(METAL) |         f.write("""#if defined(HLSL) || defined(METAL) | ||||||
| #define _InvY | #define _InvY | ||||||
| @ -684,16 +672,16 @@ const float waterReflect = """ + str(round(rpdat.lnx_water_reflect * 100) / 100) | |||||||
|                 f'const float ditherStrengthValue = {rpdat.lnx_dithering_strength};\n' |                 f'const float ditherStrengthValue = {rpdat.lnx_dithering_strength};\n' | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         if rpdat.rp_ssgi == 'SSAO' or rpdat.rp_ssgi == 'RTAO' or rpdat.rp_volumetriclight: |         if rpdat.rp_ssgi == 'SSAO' or rpdat.rp_ssgi == 'SSGI' or rpdat.rp_ssgi == 'RTAO' or rpdat.rp_volumetriclight: | ||||||
|             f.write( |             f.write( | ||||||
| """const float ssaoRadius = """ + str(round(rpdat.lnx_ssgi_radius * 100) / 100) + """; | """const float ssaoRadius = """ + str(round(rpdat.lnx_ssgi_radius * 100) / 100) + """; | ||||||
| const float ssaoStrength = """ + str(round(rpdat.lnx_ssgi_strength * 100) / 100) + """; | const float ssaoStrength = """ + str(round(rpdat.lnx_ssgi_strength * 100) / 100) + """; | ||||||
| const float ssaoScale = """ + ("2.0" if rpdat.lnx_ssgi_half_res else "20.0") + """; | const float ssaoScale = """ + ("2.0" if rpdat.lnx_ssgi_half_res else "20.0") + """; | ||||||
| """) | """) | ||||||
|  |  | ||||||
|         if rpdat.rp_ssgi == 'RTGI' or rpdat.rp_ssgi == 'RTAO': |         if rpdat.rp_ssgi == 'RTGI' or rpdat.rp_ssgi == 'RTAO' or rpdat.rp_ssgi == 'SSGI' : | ||||||
|             f.write( |             f.write( | ||||||
| """const int ssgiMaxSteps = """ + str(rpdat.lnx_ssgi_max_steps) + """; | """const int ssgiSamples = """ + str(rpdat.lnx_ssgi_samples) + """; | ||||||
| const float ssgiRayStep = 0.005 * """ + str(round(rpdat.lnx_ssgi_step * 100) / 100) + """; | const float ssgiRayStep = 0.005 * """ + str(round(rpdat.lnx_ssgi_step * 100) / 100) + """; | ||||||
| const float ssgiStrength = """ + str(round(rpdat.lnx_ssgi_strength * 100) / 100) + """; | const float ssgiStrength = """ + str(round(rpdat.lnx_ssgi_strength * 100) / 100) + """; | ||||||
| """) | """) | ||||||
| @ -840,6 +828,7 @@ const float voxelgiRange = """ + str(round(rpdat.lnx_voxelgi_range * 100) / 100) | |||||||
| const float voxelgiOffset = """ + str(round(rpdat.lnx_voxelgi_offset * 1000) / 1000) + """; | const float voxelgiOffset = """ + str(round(rpdat.lnx_voxelgi_offset * 1000) / 1000) + """; | ||||||
| const float voxelgiAperture = """ + str(round(rpdat.lnx_voxelgi_aperture * 100) / 100) + """; | const float voxelgiAperture = """ + str(round(rpdat.lnx_voxelgi_aperture * 100) / 100) + """; | ||||||
| const float voxelgiShad = """ + str(round(rpdat.lnx_voxelgi_shad * 100) / 100) + """; | const float voxelgiShad = """ + str(round(rpdat.lnx_voxelgi_shad * 100) / 100) + """; | ||||||
|  | const float voxelgiEnv = """ + str(round(rpdat.lnx_voxelgi_env * 100) / 100) + """; | ||||||
| """) | """) | ||||||
|         if rpdat.rp_voxels == 'Voxel GI': |         if rpdat.rp_voxels == 'Voxel GI': | ||||||
|             f.write(""" |             f.write(""" | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user