forked from LeenkxTeam/LNXSDK
		
	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 | ||||
| uniform sampler2D voxels_diffuse; | ||||
| uniform sampler2D voxels_specular; | ||||
| #endif | ||||
| #else | ||||
| #ifdef _VoxelAOvar | ||||
| uniform sampler2D voxels_ao; | ||||
| #endif | ||||
| #endif | ||||
| #ifdef _VoxelShadow | ||||
| uniform sampler3D voxels; | ||||
| uniform sampler3D voxelsSDF; | ||||
| @ -56,6 +57,10 @@ uniform vec3 backgroundCol; | ||||
|  | ||||
| #ifdef _SSAO | ||||
| uniform sampler2D ssaotex; | ||||
| #else | ||||
| #ifdef _SSGI | ||||
| uniform sampler2D ssaotex; | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #ifdef _SSS | ||||
| @ -113,11 +118,15 @@ uniform vec2 cameraPlane; | ||||
| #ifdef _SinglePoint | ||||
| 	#ifdef _Spot | ||||
| 	//!uniform sampler2DShadow shadowMapSpot[1]; | ||||
| 	#ifdef _ShadowMapTransparent | ||||
| 	//!uniform sampler2D shadowMapSpotTransparent[1]; | ||||
| 	#endif | ||||
| 	//!uniform mat4 LWVPSpot[1]; | ||||
| 	#else | ||||
| 	//!uniform samplerCubeShadow shadowMapPoint[1]; | ||||
| 	#ifdef _ShadowMapTransparent | ||||
| 	//!uniform samplerCube shadowMapPointTransparent[1]; | ||||
| 	#endif | ||||
| 	//!uniform vec2 lightProj; | ||||
| 	#endif | ||||
| #endif | ||||
| @ -125,30 +134,40 @@ uniform vec2 cameraPlane; | ||||
| 	#ifdef _ShadowMapAtlas | ||||
| 		#ifdef _SingleAtlas | ||||
| 		uniform sampler2DShadow shadowMapAtlas; | ||||
| 		#ifdef _ShadowMapTransparent | ||||
| 		uniform sampler2D shadowMapAtlasTransparent; | ||||
| 		#endif | ||||
| 		#endif | ||||
| 	#endif | ||||
| 	#ifdef _ShadowMapAtlas | ||||
| 		#ifndef _SingleAtlas | ||||
| 		//!uniform sampler2DShadow shadowMapAtlasPoint; | ||||
| 		#ifdef _ShadowMapTransparent | ||||
| 		//!uniform sampler2D shadowMapAtlasPointTransparent; | ||||
| 		#endif | ||||
| 		//!uniform vec4 pointLightDataArray[4]; | ||||
| 		#endif | ||||
| 		//!uniform vec4 pointLightDataArray[maxLightsCluster * 6]; | ||||
| 	#else | ||||
| 		//!uniform samplerCubeShadow shadowMapPoint[4]; | ||||
| 		#ifdef _ShadowMapTransparent | ||||
| 		//!uniform samplerCube shadowMapPointTransparent[4]; | ||||
| 		#endif | ||||
| 	#endif | ||||
| 	//!uniform vec2 lightProj; | ||||
| 	#ifdef _Spot | ||||
| 		#ifdef _ShadowMapAtlas | ||||
| 		#ifndef _SingleAtlas | ||||
| 		//!uniform sampler2DShadow shadowMapAtlasSpot; | ||||
| 		#ifdef _ShadowMapTransparent | ||||
| 		//!uniform sampler2D shadowMapAtlasSpotTransparent; | ||||
| 		#endif | ||||
| 		#endif | ||||
| 		#else | ||||
| 		//!uniform sampler2DShadow shadowMapSpot[4]; | ||||
| 		#ifdef _ShadowMapTransparent | ||||
| 		//!uniform sampler2D shadowMapSpotTransparent[4]; | ||||
| 		#endif | ||||
| 		#endif | ||||
| 	//!uniform mat4 LWVPSpotArray[maxLightsCluster]; | ||||
| 	#endif | ||||
| #endif | ||||
| @ -161,12 +180,16 @@ uniform vec3 sunCol; | ||||
| 	#ifdef _ShadowMapAtlas | ||||
| 	#ifndef _SingleAtlas | ||||
| 	uniform sampler2DShadow shadowMapAtlasSun; | ||||
| 	#ifdef _ShadowMapTransparent | ||||
| 	uniform sampler2D shadowMapAtlasSunTransparent; | ||||
| 	#endif | ||||
| 	#endif | ||||
| 	#else | ||||
| 	uniform sampler2DShadow shadowMap; | ||||
| 	#ifdef _ShadowMapTransparent | ||||
| 	uniform sampler2D shadowMapTransparent; | ||||
| 	#endif | ||||
| 	#endif | ||||
| 	uniform float shadowsBias; | ||||
| 	#ifdef _CSM | ||||
| 	//!uniform vec4 casData[shadowmapCascades * 4 + 4]; | ||||
| @ -227,17 +250,22 @@ void main() { | ||||
| 	vec4 g2 = textureLod(gbuffer2, texCoord, 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 | ||||
|  | ||||
| #ifndef _VoxelAOvar | ||||
| #ifndef _VoxelGI | ||||
| 	// Envmap | ||||
| #ifdef _Irr | ||||
|  | ||||
| 	vec3 envl = shIrradiance(n, shirr); | ||||
|  | ||||
| 	#ifdef _gbuffer2 | ||||
| @ -271,33 +299,33 @@ void main() { | ||||
| 	envl.rgb *= albedo; | ||||
|  | ||||
| #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 | ||||
|  | ||||
| #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 | ||||
| 	#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 | ||||
|  | ||||
| 	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; | ||||
| #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 | ||||
| 	// vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99); | ||||
| 	// vec3 direction = vec3(0.0, 0.0, -1.0); | ||||
| @ -317,6 +345,10 @@ void main() { | ||||
| 	// #else | ||||
| 	fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r; | ||||
| 	// #endif | ||||
| #else | ||||
| #ifdef _SSGI | ||||
| 	fragColor.rgb += textureLod(ssaotex, texCoord, 0.0).rgb; | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #ifdef _EmissionShadeless | ||||
| @ -349,40 +381,70 @@ void main() { | ||||
| 	#ifdef _ShadowMap | ||||
| 		#ifdef _CSM | ||||
| 			svisibility = shadowTestCascade( | ||||
| 				#ifdef _ShadowMapAtlas | ||||
| 					#ifndef _SingleAtlas | ||||
| 					shadowMapAtlasSun, shadowMapAtlasSunTransparent | ||||
| 					#else | ||||
| 					shadowMapAtlas, shadowMapAtlasTransparent | ||||
| 					#endif | ||||
| 				#else | ||||
| 				shadowMap, shadowMapTransparent | ||||
| 				#endif | ||||
| 				, eye, p + n * shadowsBias * 10, shadowsBias, false | ||||
| 			); | ||||
| 											#ifdef _ShadowMapAtlas | ||||
| 												#ifdef _ShadowMapTransparent | ||||
| 												#ifndef _SingleAtlas | ||||
| 												shadowMapAtlasSun, shadowMapAtlasSunTransparent | ||||
| 												#else | ||||
| 												shadowMapAtlas, shadowMapAtlasTransparent | ||||
| 												#endif | ||||
| 												#else | ||||
| 												#ifndef _SingleAtlas | ||||
| 												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 | ||||
| 			vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0); | ||||
| 			if (lPos.w > 0.0) { | ||||
| 				svisibility = shadowTest( | ||||
| 					#ifdef _ShadowMapAtlas | ||||
| 						#ifndef _SingleAtlas | ||||
| 						shadowMapAtlasSun, shadowMapAtlasSunTransparent | ||||
| 						#else | ||||
| 						shadowMapAtlas, shadowMapAtlasTransparent | ||||
| 						#endif | ||||
| 					#else | ||||
| 					shadowMap, shadowMapTransparent | ||||
| 					#endif | ||||
| 					, lPos.xyz / lPos.w, shadowsBias, false | ||||
| 				); | ||||
| 										#ifdef _ShadowMapAtlas | ||||
| 											#ifdef _ShadowMapTransparent | ||||
| 											#ifndef _SingleAtlas | ||||
| 											shadowMapAtlasSun, shadowMapAtlasSunTransparent | ||||
| 											#else | ||||
| 											shadowMapAtlas, shadowMapAtlasTransparent | ||||
| 											#endif | ||||
| 											#else | ||||
| 											#ifndef _SingleAtlas | ||||
| 											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 | ||||
|  | ||||
| 	#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 | ||||
| 	 | ||||
|  | ||||
| 	#ifdef _SSRS | ||||
| 	// vec2 coords = getProjectedCoord(hitCoord); | ||||
| 	// vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy); | ||||
| @ -439,13 +501,16 @@ void main() { | ||||
| 	fragColor.rgb += sampleLight( | ||||
| 		p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0 | ||||
| 		#ifdef _ShadowMap | ||||
| 			, 0, pointBias, true, false | ||||
| 			, 0, pointBias, true | ||||
| 		#ifdef _ShadowMapTransparent | ||||
| 			, false | ||||
| 		#endif | ||||
| 		#endif | ||||
| 		#ifdef _Spot | ||||
| 		, true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight | ||||
| 		#endif | ||||
| 		#ifdef _VoxelShadow | ||||
| 			, voxels, voxelsSDF, clipmaps | ||||
| 			, voxels, voxelsSDF, clipmaps, -g2.rg | ||||
| 		#endif | ||||
| 		#ifdef _MicroShadowing | ||||
| 		, occspec.x | ||||
| @ -492,7 +557,10 @@ void main() { | ||||
| 			f0 | ||||
| 			#ifdef _ShadowMap | ||||
| 				// 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 | ||||
| 			#ifdef _Spot | ||||
| 			, lightsArray[li * 3 + 2].y != 0.0 | ||||
| @ -503,7 +571,7 @@ void main() { | ||||
| 			, lightsArraySpot[li * 2 + 1].xyz // right | ||||
| 			#endif | ||||
| 			#ifdef _VoxelShadow | ||||
| 			, voxels, voxelsSDF, clipmaps | ||||
| 			, voxels, voxelsSDF, clipmaps, -g2.rg | ||||
| 			#endif | ||||
| 			#ifdef _MicroShadowing | ||||
| 			, occspec.x | ||||
| @ -514,14 +582,5 @@ void main() { | ||||
| 		); | ||||
| 	} | ||||
| #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 | ||||
| } | ||||
|  | ||||
| @ -1,107 +1,506 @@ | ||||
| #version 450 | ||||
|  | ||||
| #include "compiled.inc" | ||||
| #include "std/math.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 gbuffer0; // Normal | ||||
| // #ifdef _RTGI | ||||
| // uniform sampler2D gbuffer1; // Basecol | ||||
| // #endif | ||||
| uniform mat4 P; | ||||
| uniform mat3 V3; | ||||
|  | ||||
| #ifdef _EmissionShaded | ||||
| uniform sampler2D gbufferEmission; | ||||
| #endif | ||||
| uniform sampler2D sveloc; | ||||
| uniform vec2 cameraProj; | ||||
| uniform vec3 eye; | ||||
| uniform vec3 eyeLook; | ||||
| uniform vec2 screenSize; | ||||
| uniform mat4 invVP; | ||||
|  | ||||
| const float angleMix = 0.5f; | ||||
| #ifdef _SSGICone9 | ||||
| const float strength = 2.0 * (1.0 / ssgiStrength); | ||||
| #else | ||||
| const float strength = 2.0 * (1.0 / ssgiStrength) * 1.8; | ||||
| in vec2 texCoord; | ||||
| in vec3 viewRay; | ||||
| out vec3 fragColor; | ||||
|  | ||||
| float metallic; | ||||
| uint matid; | ||||
|  | ||||
| #ifdef _SMSizeUniform | ||||
| //!uniform vec2 smSizeUniform; | ||||
| #endif | ||||
|  | ||||
| in vec3 viewRay; | ||||
| in vec2 texCoord; | ||||
| out float fragColor; | ||||
|  | ||||
| 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; | ||||
| #ifdef _Clusters | ||||
| uniform vec4 lightsArray[maxLights * 3]; | ||||
| 	#ifdef _Spot | ||||
| 	uniform vec4 lightsArraySpot[maxLights * 2]; | ||||
| 	#endif | ||||
| 	return projectedCoord.xy; | ||||
| } | ||||
| uniform sampler2D clustersData; | ||||
| uniform vec2 cameraPlane; | ||||
| #endif | ||||
|  | ||||
| float getDeltaDepth(vec3 hitCoord) { | ||||
| 	coord = getProjectedCoord(hitCoord); | ||||
| 	depth = textureLod(gbufferD, coord, 0.0).r * 2.0 - 1.0; | ||||
| 	vec3 p = getPosView(viewRay, depth, cameraProj); | ||||
| 	return p.z - hitCoord.z; | ||||
| } | ||||
| #ifdef _SinglePoint // Fast path for single light | ||||
| uniform vec3 pointPos; | ||||
| uniform vec3 pointCol; | ||||
| 	#ifdef _ShadowMap | ||||
| 	uniform float pointBias; | ||||
| 	#endif | ||||
| 	#ifdef _Spot | ||||
| 	uniform vec3 spotDir; | ||||
| 	uniform vec3 spotRight; | ||||
| 	uniform vec4 spotData; | ||||
| 	#endif | ||||
| #endif | ||||
|  | ||||
| void rayCast(vec3 dir) { | ||||
| 	hitCoord = vpos; | ||||
| 	dir *= ssgiRayStep * 2; | ||||
| 	float dist = 0.15; | ||||
| 	for (int i = 0; i < ssgiMaxSteps; i++) { | ||||
| 		hitCoord += dir; | ||||
| 		float delta = getDeltaDepth(hitCoord); | ||||
| 		if (delta > 0.0 && delta < 0.2) { | ||||
| 			dist = distance(vpos, hitCoord); | ||||
| 			break; | ||||
| #ifdef _CPostprocess | ||||
|     uniform vec3 PPComp12; | ||||
| #endif | ||||
|  | ||||
| #ifdef _ShadowMap | ||||
| 	#ifdef _SinglePoint | ||||
| 		#ifdef _Spot | ||||
| 			#ifndef _LTC | ||||
| 				uniform sampler2DShadow shadowMapSpot[1]; | ||||
| 				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; | ||||
| 	// #ifdef _RTGI | ||||
| 	// col += textureLod(gbuffer1, coord, 0.0).rgb * ((ssgiRayStep * ssgiMaxSteps) - dist); | ||||
| 	// #endif | ||||
| 	#endif | ||||
|  | ||||
| 	#ifdef _LightIES | ||||
| 	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 t1 = cross(n, vec3(0, 0, 1)); | ||||
| 	vec3 t2 = cross(n, vec3(0, 1, 0)); | ||||
| 	if (length(t1) > length(t2)) return normalize(t1); | ||||
| 	else return normalize(t2); | ||||
| vec3 getVisibility(vec3 p, vec3 n, float depth, vec2 uv) { | ||||
| 		vec3 visibility = vec3(0.0); | ||||
| #ifdef _Sun | ||||
| 	#ifdef _ShadowMap | ||||
| 		#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() { | ||||
| 	fragColor = 0; | ||||
| 	vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); | ||||
| 	float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; | ||||
|     float depth = textureLod(gbufferD, texCoord, 0.0).r; | ||||
|     if (depth >= 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; | ||||
| 	n.z = 1.0 - abs(enc.x) - abs(enc.y); | ||||
| 	n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy); | ||||
| 	n = normalize(V3 * 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); | ||||
|  | ||||
| 	vpos = getPosView(viewRay, d, cameraProj); | ||||
|     vec3 pos = getWorldPos(texCoord, depth); | ||||
|     vec3 normal = getNormal(texCoord); | ||||
|     vec3 centerColor = textureLod(gbuffer1, texCoord, 0.0).rgb; | ||||
|  | ||||
| 	rayCast(n); | ||||
| 	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)); | ||||
|     float radius = ssaoRadius; | ||||
|  | ||||
| 	#ifdef _SSGICone9 | ||||
| 	rayCast(mix(n, -o1, angleMix)); | ||||
| 	rayCast(mix(n, -o2, angleMix)); | ||||
| 	rayCast(mix(n, c1, angleMix)); | ||||
| 	rayCast(mix(n, c2, angleMix)); | ||||
|     vec3 gi = vec3(0.0); | ||||
|     float totalWeight = 0.0; | ||||
|     float angle = fract(sin(dot(texCoord, vec2(12.9898, 78.233))) * 100.0); | ||||
|  | ||||
| 	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 | ||||
| 	#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", | ||||
| 			"cull_mode": "none", | ||||
| 			"links": [ | ||||
| 				{ | ||||
| 					"name": "invVP", | ||||
| 					"link": "_inverseViewProjectionMatrix" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"name": "P", | ||||
| 					"link": "_projectionMatrix" | ||||
| @ -15,16 +19,180 @@ | ||||
| 					"link": "_viewMatrix3" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"name": "invP", | ||||
| 					"link": "_inverseProjectionMatrix" | ||||
| 					"name": "eye", | ||||
| 					"link": "_cameraPosition" | ||||
| 				},				 | ||||
| 				{ | ||||
| 					"name": "eyeLook", | ||||
| 					"link": "_cameraLook" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"name": "cameraProj", | ||||
| 					"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": [], | ||||
| 			"vertex_shader": "../include/pass_viewray2.vert.glsl", | ||||
| 			"vertex_shader": "../include/pass_viewray.vert.glsl", | ||||
| 			"fragment_shader": "ssgi_pass.frag.glsl" | ||||
| 		} | ||||
| 	] | ||||
|  | ||||
| @ -72,10 +72,11 @@ void main() { | ||||
|     float roughness = g0.z; | ||||
|     vec4 gr = textureLod(gbuffer_refraction, texCoord, 0.0); | ||||
|     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; | ||||
|     if (d == 0.0 || d == 1.0 || opac == 1.0 || ior == 1.0) { | ||||
|         fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb; | ||||
| 		fragColor.a = opac; | ||||
|         return; | ||||
|     } | ||||
| 	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; | ||||
| 	intensity = clamp(intensity, 0.0, 1.0); | ||||
|  | ||||
| 	vec3 refractionCol = textureLod(tex1, coords.xy, 0.0).rgb; | ||||
| 	refractionCol *= intensity; | ||||
| 	vec3 color = textureLod(tex, texCoord.xy, 0.0).rgb; | ||||
| 	vec4 refractionCol = textureLod(tex1, coords.xy, 0.0).rgba; | ||||
| 	refractionCol.a = opac; | ||||
| 	//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, | ||||
| 			"compare_mode": "always", | ||||
| 			"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": [ | ||||
| 				{ | ||||
| 					"name": "P", | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| // | ||||
| // Copyright (C) 2012 Jorge Jimenez (jorge@iryoku.com) | ||||
| // Copyright (C) 2012 Diego Gutierrez (diegog@unizar.es) | ||||
| // Copyright (C) 2025 Onek8 (info@leenkx.com) | ||||
| // All rights reserved. | ||||
| // | ||||
| // Redistribution and use in source and binary forms, with or without | ||||
| @ -33,6 +34,14 @@ | ||||
| // 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 | ||||
|  | ||||
| #include "compiled.inc" | ||||
| @ -49,67 +58,93 @@ out vec4 fragColor; | ||||
|  | ||||
| const float SSSS_FOVY = 108.0; | ||||
|  | ||||
| // Separable SSS Reflectance | ||||
| // const float sssWidth = 0.005; | ||||
| // Temp hash func -  | ||||
| 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() { | ||||
| 	// Quality = 0 | ||||
| 	const int SSSS_N_SAMPLES  = 11; | ||||
| 	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); | ||||
| 	kernel[2] = vec4(0.0192831, 0.00282018, 0.00084214, -1.28); | ||||
| 	kernel[3] = vec4(0.03639, 0.0130999, 0.00643685, -0.72); | ||||
| 	kernel[4] = vec4(0.0821904, 0.0358608, 0.0209261, -0.32); | ||||
| 	kernel[5] = vec4(0.0771802, 0.113491, 0.0793803, -0.08); | ||||
| 	kernel[6] = vec4(0.0771802, 0.113491, 0.0793803, 0.08); | ||||
| 	kernel[7] = vec4(0.0821904, 0.0358608, 0.0209261, 0.32); | ||||
| 	kernel[8] = vec4(0.03639, 0.0130999, 0.00643685, 0.72); | ||||
| 	kernel[9] = vec4(0.0192831, 0.00282018, 0.00084214, 1.28); | ||||
| 	kernel[10] = vec4(0.00471691, 0.000184771, 5.07565e-005, 2); | ||||
| 	const int SSSS_N_SAMPLES = 15; | ||||
| 	vec4 kernel[SSSS_N_SAMPLES]; | ||||
| 	 | ||||
| 	// color neutral kernel weights to prevent color shifting | ||||
| 	kernel[0] = vec4(0.2, 0.2, 0.2, 0.0); | ||||
| 	kernel[1] = vec4(0.12, 0.12, 0.12, 0.2); | ||||
| 	kernel[2] = vec4(0.09, 0.09, 0.09, 0.4); | ||||
| 	kernel[3] = vec4(0.06, 0.06, 0.06, 0.8); | ||||
| 	kernel[4] = vec4(0.04, 0.04, 0.04, 1.2); | ||||
| 	kernel[5] = vec4(0.025, 0.025, 0.025, 1.6); | ||||
| 	kernel[6] = vec4(0.015, 0.015, 0.015, 2.0); | ||||
| 	kernel[7] = vec4(0.005, 0.005, 0.005, 2.5); | ||||
| 	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); | ||||
|  | ||||
| 	// Fetch linear depth of current pixel | ||||
| 	float depth = textureLod(gbufferD, texCoord, 0.0).r; | ||||
| 	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 scale = distanceToProjectionWindow / depthM; | ||||
|  | ||||
| 	// Calculate the final step to fetch the surrounding pixels | ||||
| 	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++) { | ||||
| 		// Fetch color and depth for current sample | ||||
| 		vec2 offset = texCoord + kernel[i].a * finalStep; | ||||
| 		float sampleJitter = hash13(vec3(texCoord.xy * 720.0, float(i) * 37.45)) * 0.1 - 0.05; | ||||
| 		 | ||||
| 		vec2 offset = texCoord + (kernel[i].a + sampleJitter) * 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; | ||||
| 		 | ||||
| 		// 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; | ||||
| 	} | ||||
|  | ||||
| 	return colorBlurred; | ||||
| 	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() { | ||||
| 	 | ||||
| 	if (textureLod(gbuffer0, texCoord, 0.0).a == 8192.0) { | ||||
| 		fragColor = clamp(SSSSBlur(), 0.0, 1.0); | ||||
| 	} | ||||
| 	else { | ||||
| 		vec4 originalColor = textureLod(tex, texCoord, 0.0); | ||||
| 		vec4 blurredColor = SSSSBlur(); | ||||
| 		vec4 finalColor = mix(blurredColor, originalColor, 0.15); | ||||
| 		 | ||||
| 		fragColor = clamp(finalColor, 0.0, 1.0); | ||||
| 	} else { | ||||
| 		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_ | ||||
| #define _CONETRACE_GLSL_ | ||||
|  | ||||
| #include "std/voxels_constants.glsl" | ||||
| #include "std/constants.glsl" | ||||
|  | ||||
| // References | ||||
| // 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 step_dist = dist; | ||||
| 	vec3 samplePos; | ||||
| 	vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; | ||||
| 	vec3 start_pos = origin + n * voxelSize0; | ||||
| 	int clipmap_index0 = 0; | ||||
|  | ||||
| 	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) { | ||||
| 			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; | ||||
| @ -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]) { | ||||
| 	float sum = 0.0; | ||||
| 	vec4 amount = vec4(0.0); | ||||
| 	mat3 TBN = makeTangentBasis(normal); | ||||
| 	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); | ||||
| 		if (cosTheta <= 0) | ||||
| 			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) { | ||||
| 	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; | ||||
| 	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; | ||||
| } | ||||
|  | ||||
| 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 transmittance = 1.0; | ||||
|  	vec3 refractionDir = refract(-viewDir, normal, 1.0 / ior); | ||||
| 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 - opacity; | ||||
|  	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; | ||||
| 	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 step_dist = dist; | ||||
| 	vec3 samplePos; | ||||
| 	vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; | ||||
| 	vec3 start_pos = origin + n * voxelSize0; | ||||
| 	int clipmap_index0 = 0; | ||||
|  | ||||
| 	vec3 aniso_direction = -dir; | ||||
| @ -259,7 +260,6 @@ float traceAO(const vec3 origin, const vec3 normal, const sampler3D voxels, cons | ||||
| } | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #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 sampleCol = 0.0; | ||||
| @ -267,7 +267,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v | ||||
| 	float dist = voxelSize0; | ||||
| 	float step_dist = dist; | ||||
| 	vec3 samplePos; | ||||
| 	vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; | ||||
| 	vec3 start_pos = origin + n * voxelSize0; | ||||
| 	int clipmap_index0 = 0; | ||||
|  | ||||
| 	vec3 aniso_direction = -dir; | ||||
| @ -287,7 +287,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v | ||||
| 		float clipmap_blend = fract(lod); | ||||
| 		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; | ||||
|  | ||||
| 		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) { | ||||
|  	vec3 P = origin + dir * (BayerMatrix8[int(pixel.x) % 8][int(pixel.y) % 8] - 0.5) * voxelgiStep; | ||||
| 	float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps); | ||||
| 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 + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; | ||||
| 	float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, SHADOW_CONE_APERTURE, voxelgiStep, clipmaps); | ||||
| 	amount = clamp(amount, 0.0, 1.0); | ||||
| 	return amount * voxelgiOcc; | ||||
| } | ||||
|  | ||||
| @ -21,29 +21,49 @@ THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| const int DIFFUSE_CONE_COUNT = 16; | ||||
| const float DIFFUSE_CONE_APERTURE = radians(45.0); | ||||
| 
 | ||||
| const vec3 DIFFUSE_CONE_DIRECTIONS[16] = { | ||||
| 	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 SHADOW_CONE_APERTURE = radians(15.0); | ||||
| 
 | ||||
| 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 }, | ||||
| 	{ 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 }, | ||||
| 	{ 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 } | ||||
| }; | ||||
| 
 | ||||
| @ -1,239 +1,679 @@ | ||||
| #ifndef _LIGHT_GLSL_ | ||||
| #define _LIGHT_GLSL_ | ||||
|  | ||||
| #include "compiled.inc" | ||||
| #include "std/brdf.glsl" | ||||
| #include "std/math.glsl" | ||||
| #ifdef _ShadowMap | ||||
| #include "std/shadows.glsl" | ||||
| #endif | ||||
| #ifdef _VoxelShadow | ||||
| #include "std/conetrace.glsl" | ||||
| //!uniform sampler2D voxels_shadows; | ||||
| #endif | ||||
| #ifdef _LTC | ||||
| #include "std/ltc.glsl" | ||||
| #endif | ||||
| #ifdef _LightIES | ||||
| #include "std/ies.glsl" | ||||
| #endif | ||||
| #ifdef _SSRS | ||||
| #include "std/ssrs.glsl" | ||||
| #endif | ||||
| #ifdef _Spot | ||||
| #include "std/light_common.glsl" | ||||
| #endif | ||||
|  | ||||
| #ifdef _ShadowMap | ||||
| 	#ifdef _SinglePoint | ||||
| 		#ifdef _Spot | ||||
| 			#ifndef _LTC | ||||
| 				uniform sampler2DShadow shadowMapSpot[1]; | ||||
| 				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; | ||||
| 		#endif | ||||
| 		#else | ||||
| 		uniform samplerCubeShadow shadowMapPoint[4]; | ||||
| 		uniform samplerCube shadowMapPointTransparent[4]; | ||||
| 		#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 sampler2D shadowMapSpotTransparent[maxLightsCluster]; | ||||
| 		uniform mat4 LWVPSpotArray[maxLightsCluster]; | ||||
| 	#endif | ||||
| 	#endif | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| 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 | ||||
| 	#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 | ||||
| 	#ifdef _VoxelShadow | ||||
| 		, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount] | ||||
| 	#endif | ||||
| 	#ifdef _MicroShadowing | ||||
| 		, float occ | ||||
| 	#endif | ||||
| 	#ifdef _SSRS | ||||
| 		, sampler2D gbufferD, mat4 invVP, vec3 eye | ||||
| 	#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 _MicroShadowing | ||||
| 	direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0); | ||||
| 	#endif | ||||
|  | ||||
| 	#ifdef _SSRS | ||||
| 	direct *= traceShadowSS(l, p, gbufferD, invVP, eye); | ||||
| 	#endif | ||||
|  | ||||
| 	#ifdef _VoxelShadow | ||||
| 	direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad; | ||||
| 	#endif | ||||
|  | ||||
| 	#ifdef _LTC | ||||
| 	#ifdef _ShadowMap | ||||
| 		if (receiveShadow) { | ||||
| 			#ifdef _SinglePoint | ||||
| 			vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); | ||||
| 			direct *= 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) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); | ||||
| 			else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); | ||||
| 			else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); | ||||
| 			else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); | ||||
| 			#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 = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); | ||||
| 				direct *= 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 | ||||
| 						direct *= shadowTest( | ||||
| 							#ifndef _SingleAtlas | ||||
| 							shadowMapAtlasSpot, shadowMapAtlasSpotTransparent | ||||
| 							#else | ||||
| 							shadowMapAtlas, shadowMapAtlasTransparent | ||||
| 							#endif | ||||
| 							, lPos.xyz / lPos.w, bias, transparent | ||||
| 						); | ||||
| 					#else | ||||
| 							 if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); | ||||
| 						else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); | ||||
| 						else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); | ||||
| 						else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); | ||||
| 					#endif | ||||
| 				#endif | ||||
| 			} | ||||
| 		#endif | ||||
| 		return direct; | ||||
| 	} | ||||
| 	#endif | ||||
|  | ||||
| 	#ifdef _LightIES | ||||
| 	direct *= iesAttenuation(-l); | ||||
| 	#endif | ||||
|  | ||||
| 	#ifdef _ShadowMap | ||||
| 		if (receiveShadow) { | ||||
| 			#ifdef _SinglePoint | ||||
| 			#ifndef _Spot | ||||
| 			direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); | ||||
| 			#endif | ||||
| 			#endif | ||||
| 			#ifdef _Clusters | ||||
| 				#ifdef _ShadowMapAtlas | ||||
| 				direct *= PCFFakeCube( | ||||
| 					#ifndef _SingleAtlas | ||||
| 					shadowMapAtlasPoint, shadowMapAtlasPointTransparent | ||||
| 					#else | ||||
| 					shadowMapAtlas, shadowMapAtlasTransparent | ||||
| 					#endif | ||||
| 					, ld, -l, bias, lightProj, n, index, transparent | ||||
| 				); | ||||
| 				#else | ||||
| 					 if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); | ||||
| 				else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent); | ||||
| 				else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent); | ||||
| 				else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent); | ||||
| 				#endif | ||||
| 			#endif | ||||
| 		} | ||||
| 	#endif | ||||
|  | ||||
| 	return direct; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| #ifndef _LIGHT_GLSL_ | ||||
| #define _LIGHT_GLSL_ | ||||
|  | ||||
| #include "compiled.inc" | ||||
| #include "std/brdf.glsl" | ||||
| #include "std/math.glsl" | ||||
| #ifdef _ShadowMap | ||||
| #include "std/shadows.glsl" | ||||
| #endif | ||||
| #ifdef _VoxelShadow | ||||
| #include "std/conetrace.glsl" | ||||
| #endif | ||||
| #ifdef _LTC | ||||
| #include "std/ltc.glsl" | ||||
| #endif | ||||
| #ifdef _LightIES | ||||
| #include "std/ies.glsl" | ||||
| #endif | ||||
| #ifdef _SSRS | ||||
| #include "std/ssrs.glsl" | ||||
| #endif | ||||
| #ifdef _Spot | ||||
| #include "std/light_common.glsl" | ||||
| #endif | ||||
| #ifdef _VoxelShadow | ||||
| #include "std/conetrace.glsl" | ||||
| #endif | ||||
|  | ||||
| #ifdef _ShadowMap | ||||
| 	#ifdef _SinglePoint | ||||
| 		#ifdef _Spot | ||||
| 			#ifndef _LTC | ||||
| 				uniform sampler2DShadow shadowMapSpot[1]; | ||||
| 				#ifdef _ShadowMapTransparent | ||||
| 				uniform sampler2D shadowMapSpotTransparent[1]; | ||||
| 				#endif | ||||
| 				uniform mat4 LWVPSpotArray[1]; | ||||
| 			#endif | ||||
| 		#else | ||||
| 			uniform samplerCubeShadow shadowMapPoint[1]; | ||||
| 			#ifdef _ShadowMapTransparent | ||||
| 			uniform samplerCube shadowMapPointTransparent[1]; | ||||
| 			#endif | ||||
| 			uniform vec2 lightProj; | ||||
| 		#endif | ||||
| 	#endif | ||||
| 	#ifdef _Clusters | ||||
| 		#ifdef _SingleAtlas | ||||
| 		//!uniform sampler2DShadow shadowMapAtlas; | ||||
| 		#ifdef _ShadowMapTransparent | ||||
| 		//!uniform sampler2D shadowMapAtlasTransparent; | ||||
| 		#endif | ||||
| 		#endif | ||||
| 		uniform vec2 lightProj; | ||||
| 		#ifdef _ShadowMapAtlas | ||||
| 		#ifndef _SingleAtlas | ||||
| 		uniform sampler2DShadow shadowMapAtlasPoint; | ||||
| 		#ifdef _ShadowMapTransparent | ||||
| 		uniform sampler2D shadowMapAtlasPointTransparent; | ||||
| 		#endif | ||||
| 		#endif | ||||
| 		#else | ||||
| 		uniform samplerCubeShadow shadowMapPoint[4]; | ||||
| 		#ifdef _ShadowMapTransparent | ||||
| 		uniform samplerCube shadowMapPointTransparent[4]; | ||||
| 		#endif | ||||
| 		#endif | ||||
| 		#ifdef _Spot | ||||
| 			#ifdef _ShadowMapAtlas | ||||
| 			#ifndef _SingleAtlas | ||||
| 			uniform sampler2DShadow shadowMapAtlasSpot; | ||||
| 			#ifdef _ShadowMapTransparent | ||||
| 			uniform sampler2D shadowMapAtlasSpotTransparent; | ||||
| 			#endif | ||||
| 			#endif | ||||
| 			#else | ||||
| 			uniform sampler2DShadow shadowMapSpot[4]; | ||||
| 			#ifdef _ShadowMapTransparent | ||||
| 			uniform sampler2D shadowMapSpotTransparent[4]; | ||||
| 			#endif | ||||
| 			#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]; | ||||
| 		#ifdef _ShadowMapTransparent | ||||
| 		uniform sampler2D shadowMapSpotTransparent[1]; | ||||
| 		#endif | ||||
| 		uniform mat4 LWVPSpotArray[1]; | ||||
| 	#endif | ||||
| 	#ifdef _Clusters | ||||
| 		uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; | ||||
| 		#ifdef _ShadowMapTransparent | ||||
| 		uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; | ||||
| 		#endif | ||||
| 		uniform mat4 LWVPSpotArray[maxLightsCluster]; | ||||
| 	#endif | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| 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 | ||||
| 	#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 | ||||
| 	#ifdef _VoxelShadow | ||||
| 		, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount], vec2 velocity | ||||
| 	#endif | ||||
| 	#ifdef _MicroShadowing | ||||
| 		, float occ | ||||
| 	#endif | ||||
| 	#ifdef _SSRS | ||||
| 		, sampler2D gbufferD, mat4 invVP, vec3 eye | ||||
| 	#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 _MicroShadowing | ||||
| 	direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0); | ||||
| 	#endif | ||||
|  | ||||
| 	#ifdef _SSRS | ||||
| 	direct *= traceShadowSS(l, p, gbufferD, invVP, eye); | ||||
| 	#endif | ||||
|  | ||||
| 	#ifdef _VoxelShadow | ||||
| 	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 | ||||
|  | ||||
| 	#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; | ||||
| } | ||||
|  | ||||
| #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 | ||||
|  | ||||
| @ -58,7 +58,15 @@ vec2 sampleCube(vec3 dir, out int faceIndex) { | ||||
| } | ||||
| #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); | ||||
| 	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)); | ||||
| @ -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 = result.xxx / 9.0; | ||||
|  | ||||
| 	#ifdef _ShadowMapTransparent | ||||
| 	if (transparent == false) { | ||||
| 		vec4 shadowmap_transparent = texture(shadowMapTransparent, uv); | ||||
| 		if (shadowmap_transparent.a < compare) | ||||
| 			result *= shadowmap_transparent.rgb; | ||||
| 	} | ||||
| 	#endif | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
| @ -87,41 +97,15 @@ float lpToDepth(vec3 lp, const vec2 lightProj) { | ||||
| 	return zcomp * 0.5 + 0.5; | ||||
| } | ||||
|  | ||||
| #ifndef _ShadowMapAtlas | ||||
| vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, vec3 lp, vec3 ml, float bias, vec2 lightProj, vec3 n, const bool transparent) { | ||||
|     const float s = shadowmapCubePcfSize; | ||||
|     float compare = lpToDepth(lp, lightProj) - bias * 1.5; | ||||
|     ml = ml + n * bias * 20; | ||||
|     #ifdef _InvY | ||||
|     ml.y = -ml.y; | ||||
|     #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) { | ||||
| vec3 PCFCube(samplerCubeShadow shadowMapCube, | ||||
| 			#ifdef _ShadowMapTransparent | ||||
| 			samplerCube shadowMapCubeTransparent, | ||||
| 			#endif | ||||
| 			const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n | ||||
| 			#ifdef _ShadowMapTransparent | ||||
| 			, const bool transparent | ||||
| 			#endif | ||||
| 			) { | ||||
| 	const float s = shadowmapCubePcfSize; // TODO: incorrect... | ||||
| 	float compare = lpToDepth(lp, lightProj) - bias * 1.5; | ||||
| 	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 = result.xxx / 9.0; | ||||
|  | ||||
| 	#ifdef _ShadowMapTransparent | ||||
| 	if (transparent == false) { | ||||
| 		vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml); | ||||
| 		if (shadowmap_transparent.a < compare) | ||||
| 			result *= shadowmap_transparent.rgb; | ||||
| 	} | ||||
| 	#endif | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
|  | ||||
| #ifdef _ShadowMapAtlas | ||||
| // transform "out-of-bounds" coordinates to the correct face/coordinate system | ||||
| // https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png | ||||
| 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; | ||||
| } | ||||
|  | ||||
| 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 float compare = lpToDepth(lp, lightProj) - bias * 1.5; | ||||
| 	ml = ml + n * bias * 20; | ||||
|  | ||||
| 	int faceIndex = 0; | ||||
| 	const int lightIndex = index * 6; | ||||
| 	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 | ||||
| 	vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; | ||||
| 	#ifdef _FlipY | ||||
| 	uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system | ||||
| 	#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); | ||||
| 	result.x += texture(shadowMap, vec3(uvtiled, compare)); | ||||
| 	// soft shadowing | ||||
| @ -270,14 +266,6 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, cons | ||||
| 	#endif | ||||
| 	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))); | ||||
| 	pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; | ||||
| 	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 | ||||
| 	#endif | ||||
|  | ||||
| 	#ifdef _ShadowMapTransparent | ||||
| 	if (transparent == false) { | ||||
| 		vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled); | ||||
| 		if (shadowmap_transparent.a < compare) | ||||
| 			result *= shadowmap_transparent.rgb; | ||||
| 	} | ||||
| 	#endif | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
| #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 | ||||
| 	vec2 smSize = smSizeUniform; | ||||
| 	#else | ||||
| 	const vec2 smSize = shadowmapSize; | ||||
| 	#endif | ||||
| 	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 | ||||
| mat4 getCascadeMat(const float d, out int casi, out int casIndex) { | ||||
| 	const int c = shadowmapCascades; | ||||
|  | ||||
| 	// Get cascade index | ||||
| 	// 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)); | ||||
| @ -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].w)); | ||||
| 	casi = int(min(dot(ci, comp), c)); | ||||
|  | ||||
| 	// Get cascade mat | ||||
| 	casIndex = casi * 4; | ||||
|  | ||||
| 	return mat4( | ||||
| 		casData[casIndex    ], | ||||
| 		casData[casIndex + 1], | ||||
| 		casData[casIndex + 2], | ||||
| 		casData[casIndex + 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 | ||||
| 	vec2 smSize = smSizeUniform; | ||||
| 	#else | ||||
| @ -395,16 +405,22 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent | ||||
| 	#endif | ||||
| 	const int c = shadowmapCascades; | ||||
| 	float d = distance(eye, p); | ||||
|  | ||||
| 	int casi; | ||||
| 	int casIndex; | ||||
| 	mat4 LWVP = getCascadeMat(d, casi, casIndex); | ||||
|  | ||||
| 	vec4 lPos = LWVP * vec4(p, 1.0); | ||||
| 	lPos.xyz /= lPos.w; | ||||
|  | ||||
| 	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 | ||||
| 	// https://github.com/TheRealMJP/Shadows | ||||
| @ -423,13 +439,20 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent | ||||
| 		vec4 lPos2 = LWVP2 * vec4(p, 1.0); | ||||
| 		lPos2.xyz /= lPos2.w; | ||||
| 		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); | ||||
| 		return mix(visibility2, visibility, lerpAmt); | ||||
| 	} | ||||
| 	return visibility; | ||||
|  | ||||
| 	// Visualize cascades | ||||
| 	// if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0); | ||||
| 	// if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0); | ||||
| @ -437,4 +460,4 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent | ||||
| 	// if (ci == 12) albedo.rgb = vec3(1.0, 1.0, 0.0); | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
| @ -33,6 +33,7 @@ uniform layout(r32ui) uimage3D voxelsLight; | ||||
|  | ||||
| #ifdef _ShadowMap | ||||
| uniform sampler2DShadow shadowMap; | ||||
| uniform sampler2D shadowMapTransparent; | ||||
| uniform sampler2DShadow shadowMapSpot; | ||||
| #ifdef _ShadowMapAtlas | ||||
| uniform sampler2DShadow shadowMapPoint; | ||||
| @ -86,30 +87,28 @@ float lpToDepth(vec3 lp, const vec2 lightProj) { | ||||
|  | ||||
| void main() { | ||||
| 	int res = voxelgiResolution.x; | ||||
|  | ||||
| 	ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); | ||||
| 	dst.y += clipmapLevel * res; | ||||
|  | ||||
| 	vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution; | ||||
| 	P = P * 2.0 - 1.0; | ||||
| 	P *= clipmaps[int(clipmapLevel * 10)]; | ||||
| 	P *= voxelgiResolution; | ||||
| 	P += vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)]); | ||||
| 	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]); | ||||
|  | ||||
| 	vec3 visibility; | ||||
| 	vec3 lp = lightPos - P; | ||||
| 	float visibility; | ||||
| 	vec3 lp = lightPos -wposition; | ||||
| 	vec3 l; | ||||
| 	if (lightType == 0) { l = lightDir; visibility = vec3(1.0); } | ||||
| 	else { l = normalize(lp); visibility = vec3(attenuate(distance(P, lightPos))); } | ||||
| 	if (lightType == 0) { l = lightDir; visibility = 1.0; } | ||||
| 	else { l = normalize(lp); visibility = attenuate(distance(wposition, lightPos)); } | ||||
|  | ||||
| #ifdef _ShadowMap | ||||
| 	if (lightShadow == 1) { | ||||
| 		vec4 lightPosition = LVP * vec4(P, 1.0); | ||||
| 		vec4 lightPosition = LVP * vec4(wposition, 1.0); | ||||
| 		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) { | ||||
| 		vec4 lightPosition = LVP * vec4(P, 1.0); | ||||
| 		vec4 lightPosition = LVP * vec4(wposition, 1.0); | ||||
| 		vec3 lPos = lightPosition.xyz / lightPosition.w; | ||||
| 		visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; | ||||
| 	} | ||||
| @ -130,9 +129,7 @@ void main() { | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	vec3 light = visibility * lightColor; | ||||
|  | ||||
| 	imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, 0), uint(light.r * 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)); | ||||
| 	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, voxelgiResolution.x * 2), uint(visibility * lightColor.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/gbuffer.glsl" | ||||
| #include "std/imageatomic.glsl" | ||||
| #include "std/voxels_constants.glsl" | ||||
| #include "std/constants.glsl" | ||||
|  | ||||
| #ifdef _VoxelGI | ||||
| uniform layout(rgba8) image3D voxelsB; | ||||
| uniform layout(rgba8) image3D voxelsOut; | ||||
| #else | ||||
| uniform layout(r16) image3D voxelsB; | ||||
| uniform layout(r16) image3D voxelsOut; | ||||
| uniform layout(r8) image3D voxelsB; | ||||
| uniform layout(r8) image3D voxelsOut; | ||||
| #endif | ||||
|  | ||||
| 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/imageatomic.glsl" | ||||
| #include "std/conetrace.glsl" | ||||
| #include "std/brdf.glsl" | ||||
| #include "std/shirr.glsl" | ||||
|  | ||||
| uniform sampler3D voxels; | ||||
| uniform sampler2D gbufferD; | ||||
| uniform sampler2D gbuffer0; | ||||
| uniform layout(r8) image2D voxels_ao; | ||||
| uniform layout(rgba8) image2D voxels_ao; | ||||
|  | ||||
| uniform float clipmaps[voxelgiClipmapCount * 10]; | ||||
| uniform mat4 InvVP; | ||||
| uniform vec2 cameraProj; | ||||
| uniform vec3 eye; | ||||
| uniform vec3 eyeLook; | ||||
| 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() { | ||||
| 	const vec2 pixel = gl_GlobalInvocationID.xy; | ||||
| 	vec2 uv = (pixel + 0.5) / postprocess_resolution; | ||||
| @ -54,12 +73,11 @@ void main() { | ||||
|  | ||||
| 	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; | ||||
| 	vec4 clipPos = vec4(x, y, depth, 1.0); | ||||
|     vec4 worldPos = InvVP * clipPos; | ||||
|     vec3 P = worldPos.xyz / worldPos.w; | ||||
|  | ||||
| 	vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); | ||||
| 	vec3 v = normalize(eye - P); | ||||
|  | ||||
| 	vec4 g0 = textureLod(gbuffer0, uv, 0.0); | ||||
| 	vec3 n; | ||||
| @ -67,7 +85,89 @@ void main() { | ||||
| 	n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); | ||||
| 	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/imageatomic.glsl" | ||||
| #include "std/conetrace.glsl" | ||||
| #include "std/brdf.glsl" | ||||
| #include "std/shirr.glsl" | ||||
|  | ||||
| uniform sampler3D voxels; | ||||
| uniform sampler2D gbufferD; | ||||
| @ -37,29 +39,44 @@ uniform layout(rgba8) image2D voxels_diffuse; | ||||
|  | ||||
| uniform float clipmaps[voxelgiClipmapCount * 10]; | ||||
| uniform mat4 InvVP; | ||||
| uniform vec2 cameraProj; | ||||
| uniform vec3 eye; | ||||
| uniform vec3 eyeLook; | ||||
| 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() { | ||||
| 	const vec2 pixel = gl_GlobalInvocationID.xy; | ||||
| 	vec2 uv = (pixel + 0.5) / postprocess_resolution; | ||||
| 	#ifdef _InvY | ||||
| 	uv.y = 1.0 - uv.y | ||||
| 	uv.y = 1.0 - uv.y; | ||||
| 	#endif | ||||
|  | ||||
| 	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 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 clipPos = vec4(x, y, depth, 1.0); | ||||
|     vec4 worldPos = InvVP * clipPos; | ||||
|     vec3 P = worldPos.xyz / worldPos.w; | ||||
| 	vec3 v = normalize(eye - P); | ||||
|  | ||||
| 	vec4 g0 = textureLod(gbuffer0, uv, 0.0); | ||||
| 	vec3 n; | ||||
| @ -67,7 +84,94 @@ void main() { | ||||
| 	n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); | ||||
| 	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/imageatomic.glsl" | ||||
| #include "std/conetrace.glsl" | ||||
| #include "std/brdf.glsl" | ||||
|  | ||||
| uniform sampler2D gbufferD; | ||||
| uniform sampler2D gbuffer0; | ||||
| @ -38,9 +39,7 @@ uniform layout(rgba8) image2D voxels_specular; | ||||
|  | ||||
| uniform float clipmaps[voxelgiClipmapCount * 10]; | ||||
| uniform mat4 InvVP; | ||||
| uniform vec2 cameraProj; | ||||
| uniform vec3 eye; | ||||
| uniform vec3 eyeLook; | ||||
| uniform vec2 postprocess_resolution; | ||||
| uniform sampler2D sveloc; | ||||
|  | ||||
| @ -56,12 +55,10 @@ void main() { | ||||
|  | ||||
| 	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; | ||||
| 	vec4 clipPos = vec4(x, y, depth, 1.0); | ||||
|     vec4 worldPos = InvVP * clipPos; | ||||
|     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); | ||||
|  | ||||
| 	vec3 n; | ||||
| @ -71,7 +68,7 @@ void main() { | ||||
|  | ||||
| 	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)); | ||||
| } | ||||
|  | ||||
| @ -23,8 +23,8 @@ THE SOFTWARE. | ||||
|  | ||||
| #include "compiled.inc" | ||||
|  | ||||
| uniform layout(r16) image3D input_sdf; | ||||
| uniform layout(r16) image3D output_sdf; | ||||
| uniform layout(r8) image3D input_sdf; | ||||
| uniform layout(r8) image3D output_sdf; | ||||
|  | ||||
| uniform float jump_size; | ||||
| uniform int clipmapLevel; | ||||
|  | ||||
| @ -46,15 +46,15 @@ uniform layout(r32ui) uimage3D voxels; | ||||
| uniform layout(r32ui) uimage3D voxelsLight; | ||||
| uniform layout(rgba8) image3D voxelsB; | ||||
| uniform layout(rgba8) image3D voxelsOut; | ||||
| uniform layout(r16) image3D SDF; | ||||
| uniform layout(r8) image3D SDF; | ||||
| #else | ||||
| #ifdef _VoxelAOvar | ||||
| #ifdef _VoxelShadow | ||||
| uniform layout(r16) image3D SDF; | ||||
| uniform layout(r8) image3D SDF; | ||||
| #endif | ||||
| uniform layout(r32ui) uimage3D voxels; | ||||
| uniform layout(r16) image3D voxelsB; | ||||
| uniform layout(r16) image3D voxelsOut; | ||||
| uniform layout(r8) image3D voxelsB; | ||||
| uniform layout(r8) image3D voxelsOut; | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -74,14 +74,9 @@ void main() { | ||||
| 	#endif | ||||
| 	#endif | ||||
|  | ||||
| 	ivec3 src = ivec3(gl_GlobalInvocationID.xyz); | ||||
| 	#ifdef _VoxelGI | ||||
| 	vec3 light = vec3(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 | ||||
| 	int nor_count = 0; | ||||
| 	vec3 avgNormal = vec3(0.0); | ||||
| 	mat3 TBN = mat3(0.0); | ||||
|  | ||||
| 	for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) | ||||
| 	{ | ||||
| @ -91,7 +86,7 @@ void main() { | ||||
| 		float aniso_colors[6]; | ||||
| 		#endif | ||||
|  | ||||
| 		src = ivec3(gl_GlobalInvocationID.xyz); | ||||
| 		ivec3 src = ivec3(gl_GlobalInvocationID.xyz); | ||||
| 		src.x += i * res; | ||||
| 		ivec3 dst = src; | ||||
| 		dst.y += clipmapLevel * res; | ||||
| @ -104,44 +99,67 @@ void main() { | ||||
|  | ||||
| 		if (i < 6) { | ||||
| 			#ifdef _VoxelGI | ||||
| 			vec4 basecol = vec4(0.0); | ||||
| 			basecol.r = float(imageLoad(voxels, src)) / 255; | ||||
| 			basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255; | ||||
| 			basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; | ||||
| 			basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255; | ||||
| 			basecol /= 4; | ||||
| 			vec3 emission = vec3(0.0); | ||||
| 			emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255; | ||||
| 			emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 255; | ||||
| 			emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255; | ||||
| 			emission /= 3; | ||||
| 			vec3 N = vec3(0.0); | ||||
| 			N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 255; | ||||
| 			N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255; | ||||
| 			N /= 2; | ||||
| 			vec3 wnormal = decode_oct(N.rg * 2 - 1); | ||||
| 			vec3 envl = vec3(0.0); | ||||
| 			envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; | ||||
| 			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; | ||||
| 			int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 15))); | ||||
| 			if (count > 0) { | ||||
| 				vec4 basecol = vec4(0.0); | ||||
| 				basecol.r = float(imageLoad(voxels, src)) / 255; | ||||
| 				basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255; | ||||
| 				basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; | ||||
| 				basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255; | ||||
| 				basecol /= count; | ||||
| 				vec3 emission = vec3(0.0); | ||||
| 				emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255; | ||||
| 				emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 255; | ||||
| 				emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255; | ||||
| 				emission /= count; | ||||
| 				vec3 N = vec3(0.0); | ||||
| 				N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 255; | ||||
| 				N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255; | ||||
| 				N /= count; | ||||
| 				N = decode_oct(N.rg * 2.0 - 1.0); | ||||
|  | ||||
| 			//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]); | ||||
| 				if (abs(N.x) > 0) | ||||
| 					avgNormal.x += N.x; | ||||
| 				if (abs(N.y) > 0) | ||||
| 					avgNormal.y += N.y; | ||||
| 				if (abs(N.z) > 0) | ||||
| 					avgNormal.z += N.z; | ||||
| 				if (i == 5) | ||||
| 				{ | ||||
| 					avgNormal = normalize(avgNormal); | ||||
| 					TBN = makeTangentBasis(avgNormal); | ||||
| 				} | ||||
|  | ||||
| 			radiance = basecol; | ||||
| 			vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps); | ||||
| 			vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); | ||||
| 			radiance.rgb *= light + indirect; | ||||
| 			radiance.rgb += emission.rgb; | ||||
| 				vec3 envl = vec3(0.0); | ||||
| 				envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; | ||||
| 				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 /= 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 | ||||
| 			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 | ||||
|  | ||||
| 			#ifdef _VoxelGI | ||||
| @ -195,7 +213,7 @@ void main() { | ||||
| 		} | ||||
| 		else { | ||||
| 			// precompute cone sampling: | ||||
| 			vec3 coneDirection = DIFFUSE_CONE_DIRECTIONS[i - 6]; | ||||
| 			vec3 coneDirection = TBN * DIFFUSE_CONE_DIRECTIONS[i - 6]; | ||||
| 			vec3 aniso_direction = -coneDirection; | ||||
| 			uvec3 face_offsets = uvec3( | ||||
| 				aniso_direction.x > 0 ? 0 : 1, | ||||
| @ -236,4 +254,4 @@ void main() { | ||||
| 	imageStore(SDF, dst_sdf, vec4(sdf)); | ||||
| 	#endif | ||||
| 	#endif | ||||
| } | ||||
| } | ||||
| @ -75,16 +75,17 @@ vec4 binarySearch(vec3 dir) { | ||||
| } | ||||
|  | ||||
| vec4 rayCast(vec3 dir) { | ||||
| 	#ifdef _CPostprocess | ||||
| 		dir *= PPComp9.x; | ||||
| 	#else | ||||
| 		dir *= ssrRayStep; | ||||
| 	#endif | ||||
| 	for (int i = 0; i < maxSteps; i++) { | ||||
| 		hitCoord += dir; | ||||
| 		if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir); | ||||
| 	} | ||||
| 	return vec4(0.0); | ||||
|     float ddepth; | ||||
|     dir *= ss_refractionRayStep; | ||||
|     for (int i = 0; i < maxSteps; i++) { | ||||
|         hitCoord += dir; | ||||
|         ddepth = getDeltaDepth(hitCoord); | ||||
|         if (ddepth > 0.0) | ||||
|             return binarySearch(dir); | ||||
|     } | ||||
|     // No hit — fallback to projecting the ray to UV space | ||||
|     vec2 fallbackUV = getProjectedCoord(hitCoord); | ||||
|     return vec4(fallbackUV, 0.0, 0.5); // We set .w lower to indicate fallback | ||||
| } | ||||
| #endif //SSR | ||||
|  | ||||
|  | ||||
| @ -181,11 +181,15 @@ class Uniforms { | ||||
| 						// Multiple voxel volumes, always set params | ||||
| 						g.setImageTexture(context.textureUnits[j], rt.image); // image2D/3D | ||||
| 						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")) | ||||
| 						{ | ||||
| 							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 | ||||
| 						{ | ||||
|  | ||||
| @ -34,10 +34,10 @@ class Inc { | ||||
| 	#if (rp_voxels == "Voxel GI") | ||||
| 	static var voxel_td1: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 | ||||
| 	#if lnx_voxelgi_shadows | ||||
| 	static var voxel_tf1:kha.compute.TextureUnit; | ||||
| 	static var voxel_te1:kha.compute.TextureUnit; | ||||
| 	#end | ||||
| 	#end | ||||
| 	#if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") | ||||
| @ -53,12 +53,28 @@ class Inc { | ||||
| 	static var voxel_tb3:kha.compute.TextureUnit; | ||||
| 	static var voxel_tc3: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_cb3:kha.compute.ConstantLocation; | ||||
| 	static var voxel_cc3:kha.compute.ConstantLocation; | ||||
| 	static var voxel_cd3:kha.compute.ConstantLocation; | ||||
| 	static var voxel_ce3:kha.compute.ConstantLocation; | ||||
| 	#if lnx_irradiance | ||||
| 	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") | ||||
| 	static var voxel_sh4:kha.compute.Shader = null; | ||||
| 	static var voxel_ta4:kha.compute.TextureUnit; | ||||
| @ -71,33 +87,6 @@ class Inc { | ||||
| 	static var voxel_cb4:kha.compute.ConstantLocation; | ||||
| 	static var voxel_cc4: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 //rp_voxels | ||||
|  | ||||
| @ -163,9 +152,11 @@ class Inc { | ||||
| 		for (atlas in ShadowMapAtlas.shadowMapAtlases) { | ||||
| 			path.bindTarget(atlas.target, atlas.target); | ||||
| 		} | ||||
| 		#if rp_shadowmap_transparent | ||||
| 		for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { | ||||
| 			path.bindTarget(atlas.target, atlas.target); | ||||
| 		} | ||||
| 		#end | ||||
| 	} | ||||
|  | ||||
| 	static function getShadowMapAtlas(atlas:ShadowMapAtlas, transparent: Bool):String { | ||||
| @ -206,24 +197,30 @@ class Inc { | ||||
| 		for (atlas in ShadowMapAtlas.shadowMapAtlases) { | ||||
| 			atlas.rejectedLights = []; | ||||
| 		} | ||||
| 		#if rp_shadowmap_transparent | ||||
| 		for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { | ||||
| 			atlas.rejectedLights = []; | ||||
| 		} | ||||
| 		#end | ||||
| 		#end | ||||
|  | ||||
| 		for (light in iron.Scene.active.lights) { | ||||
| 			if (!light.lightInAtlas && !light.culledLight && light.visible && light.shadowMapScale > 0.0 | ||||
| 				&& light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { | ||||
| 				ShadowMapAtlas.addLight(light, false); | ||||
| 			} | ||||
| 			#if rp_shadowmap_transparent | ||||
| 			if (!light.lightInAtlasTransparent && !light.culledLight && light.visible && light.shadowMapScale > 0.0 | ||||
| 				&& light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { | ||||
| 				ShadowMapAtlas.addLight(light, true); | ||||
| 			} | ||||
| 			#end | ||||
| 		} | ||||
| 		// update point light data before rendering | ||||
| 		updatePointLightAtlasData(true); | ||||
| 		updatePointLightAtlasData(false); | ||||
| 		#if rp_shadowmap_transparent | ||||
| 		updatePointLightAtlasData(true); | ||||
| 		#end | ||||
|  | ||||
| 		for (atlas in ShadowMapAtlas.shadowMapAtlases) { | ||||
| 			var tilesToRemove = []; | ||||
| @ -301,6 +298,7 @@ class Inc { | ||||
| 			path.endStream(); | ||||
| 		} | ||||
|  | ||||
| 		#if rp_shadowmap_transparent | ||||
| 		for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { | ||||
| 			var tilesToRemove = []; | ||||
| 			#if lnx_shadowmap_atlas_lod | ||||
| @ -395,10 +393,8 @@ class Inc { | ||||
| 				tile.freeTile(); | ||||
| 			} | ||||
| 		} | ||||
| 		#if lnx_debug | ||||
| 		endShadowsLogicProfile(); | ||||
| 		#end | ||||
| 		#end // rp_shadowmap | ||||
| 		#end | ||||
| 	} | ||||
| 	#else | ||||
| 	public static function bindShadowMap() { | ||||
| @ -501,6 +497,7 @@ class Inc { | ||||
| 			else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; | ||||
| 		} | ||||
|  | ||||
| 		#if rp_shadowmap_transparent | ||||
| 		pointIndex = 0; | ||||
| 		spotIndex = 0; | ||||
| 		for (l in iron.Scene.active.lights) { | ||||
| @ -522,6 +519,7 @@ class Inc { | ||||
| 			if (l.data.raw.type == "point") pointIndex++; | ||||
| 			else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; | ||||
| 		} | ||||
| 		#end | ||||
| 		#end // rp_shadowmap | ||||
| 	} | ||||
| 	#end | ||||
| @ -589,7 +587,7 @@ class Inc { | ||||
| 		t.width = 0; | ||||
| 		t.height = 0; | ||||
| 		t.displayp = getDisplayp(); | ||||
| 		t.format = "R32"; | ||||
| 		t.format = "R16"; | ||||
| 		t.scale = getSuperSampling(); | ||||
| 		t.depth_buffer = "main"; | ||||
| 		path.createRenderTarget(t); | ||||
| @ -615,10 +613,14 @@ class Inc { | ||||
| 		#end | ||||
|  | ||||
| 		#if (rp_voxels != "Off") | ||||
| 		{ | ||||
| 			path.bindTarget("voxelsOut", "voxels"); | ||||
| 			path.bindTarget("voxelsSDF", "voxelsSDF"); | ||||
| 		} | ||||
| 		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("translucent"); | ||||
| @ -679,12 +681,11 @@ class Inc { | ||||
| 			t.width = 0; | ||||
| 			t.height = 0; | ||||
| 			t.displayp = getDisplayp(); | ||||
| 			//t.scale = Inc.getSuperSampling(); | ||||
| 			t.format = t.name == "voxels_ao" ? "R8" : "RGBA32"; | ||||
| 			t.format = "RGBA32"; | ||||
| 		} | ||||
| 		else { | ||||
| 			if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { | ||||
| 				t.format = "R16"; | ||||
| 				t.format = "R8"; | ||||
| 				t.width = res; | ||||
| 				t.height = res * Main.voxelgiClipmapCount; | ||||
| 				t.depth = res; | ||||
| @ -693,16 +694,16 @@ class Inc { | ||||
| 				#if (rp_voxels == "Voxel AO") | ||||
| 				{ | ||||
| 					if (t.name == "voxelsOut" || t.name == "voxelsOutB") { | ||||
| 						t.format = "R16"; | ||||
| 						t.format = "R8"; | ||||
| 						t.width = res * (6 + 16); | ||||
| 						t.height = res * Main.voxelgiClipmapCount; | ||||
| 						t.depth = res; | ||||
| 					} | ||||
| 					else { | ||||
| 						t.format = "R32"; | ||||
| 						t.format = "R32UI"; | ||||
| 						t.width = res * 6; | ||||
| 						t.height = res; | ||||
| 						t.depth = res; | ||||
| 						t.depth = res * 2; | ||||
| 					} | ||||
| 				} | ||||
| 				#else | ||||
| @ -713,17 +714,11 @@ class Inc { | ||||
| 						t.height = res * Main.voxelgiClipmapCount; | ||||
| 						t.depth = res; | ||||
| 					} | ||||
| 					else if (t.name == "voxelsLight") { | ||||
| 						t.format = "R32"; | ||||
| 						t.width = res; | ||||
| 						t.height = res; | ||||
| 						t.depth = res * 3; | ||||
| 					} | ||||
| 					else { | ||||
| 						t.format = "R32"; | ||||
| 						t.format = "R32UI"; | ||||
| 						t.width = res * 6; | ||||
| 						t.height = res; | ||||
| 						t.depth = res * 12; | ||||
| 						t.depth = res * 16; | ||||
| 					} | ||||
| 				} | ||||
| 				#end | ||||
| @ -835,14 +830,15 @@ class Inc { | ||||
|  | ||||
| 	 		voxel_ca1 = voxel_sh1.getConstantLocation("clipmaps"); | ||||
| 	 		voxel_cb1 = voxel_sh1.getConstantLocation("clipmapLevel"); | ||||
| 	 		voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength"); | ||||
|  | ||||
| 			#if (rp_voxels == "Voxel GI") | ||||
| 			voxel_td1 = voxel_sh1.getTextureUnit("voxelsSampler"); | ||||
| 			voxel_te1 = voxel_sh1.getTextureUnit("voxelsLight"); | ||||
| 			voxel_tf1 = voxel_sh1.getTextureUnit("SDF"); | ||||
| 			voxel_te1 = voxel_sh1.getTextureUnit("SDF"); | ||||
| 	 		voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength"); | ||||
| 			#else | ||||
| 			#if lnx_voxelgi_shadows | ||||
| 			voxel_tf1 = voxel_sh1.getTextureUnit("SDF"); | ||||
| 			voxel_te1 = voxel_sh1.getTextureUnit("SDF"); | ||||
| 			#end | ||||
| 			#end | ||||
| 		} | ||||
| @ -873,12 +869,28 @@ class Inc { | ||||
| 			#else | ||||
| 			voxel_td3 = voxel_sh3.getTextureUnit("voxels_diffuse"); | ||||
| 			#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_cc3 = voxel_sh3.getConstantLocation("cameraProj"); | ||||
| 	 		voxel_cd3 = voxel_sh3.getConstantLocation("eye"); | ||||
| 	 		voxel_ce3 = voxel_sh3.getConstantLocation("eyeLook"); | ||||
| 	 		voxel_cf3 = voxel_sh3.getConstantLocation("postprocess_resolution"); | ||||
| 	 		voxel_cc3 = voxel_sh3.getConstantLocation("eye"); | ||||
| 	 		voxel_cd3 = voxel_sh3.getConstantLocation("postprocess_resolution"); | ||||
| 	 		voxel_ce3 = voxel_sh3.getConstantLocation("envmapStrength"); | ||||
| 	 		#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 (voxel_sh4 == null) | ||||
| @ -892,40 +904,8 @@ class Inc { | ||||
| 			voxel_tf4 = voxel_sh4.getTextureUnit("sveloc"); | ||||
| 	 		voxel_ca4 = voxel_sh4.getConstantLocation("clipmaps"); | ||||
| 	 		voxel_cb4 = voxel_sh4.getConstantLocation("InvVP"); | ||||
| 	 		voxel_cc4 = voxel_sh4.getConstantLocation("cameraProj"); | ||||
| 	 		voxel_cd4 = voxel_sh4.getConstantLocation("eye"); | ||||
| 	 		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 | ||||
| 	 		voxel_cc4 = voxel_sh4.getConstantLocation("eye"); | ||||
| 	 		voxel_cd4 = voxel_sh4.getConstantLocation("postprocess_resolution"); | ||||
| 		} | ||||
| 		#end | ||||
| 	} | ||||
| @ -976,11 +956,11 @@ class Inc { | ||||
| 		kha.compute.Compute.setTexture(voxel_tc1, rts.get("voxelsOut").image, kha.compute.Access.Write); | ||||
| 		#if (rp_voxels == "Voxel GI") | ||||
| 		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_tf1, rts.get("voxelsSDF").image, kha.compute.Access.Write); | ||||
| 		kha.compute.Compute.setTexture(voxel_te1, 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 | ||||
| 		#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 | ||||
|  | ||||
| @ -1002,6 +982,8 @@ class Inc { | ||||
|  | ||||
| 		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)); | ||||
| 	} | ||||
|  | ||||
| @ -1054,6 +1036,7 @@ class Inc { | ||||
| 		} | ||||
| 	} | ||||
| 	#end | ||||
|  | ||||
| 	#if (rp_voxels == "Voxel AO") | ||||
| 	public static function resolveAO() { | ||||
| 		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_tb3, rts.get("half").image); | ||||
| 		#if lnx_deferred | ||||
| 		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.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); | ||||
| 		for (i in 0...Main.voxelgiClipmapCount) { | ||||
| 			fa[i * 10] = clipmaps[i].voxelSize; | ||||
| @ -1099,18 +1089,7 @@ class Inc { | ||||
|  | ||||
| 		kha.compute.Compute.setMatrix(voxel_cb3, m.self); | ||||
|  | ||||
| 		var near = camera.data.raw.near_plane; | ||||
| 		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); | ||||
| 		kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); | ||||
|  | ||||
| 		var width = iron.App.w(); | ||||
| 		var height = iron.App.h(); | ||||
| @ -1125,7 +1104,32 @@ class Inc { | ||||
| 				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); | ||||
| 	} | ||||
| @ -1141,12 +1145,18 @@ class Inc { | ||||
|  | ||||
| 		kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); | ||||
| 		kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); | ||||
| 		#if lnx_deferred | ||||
| 		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.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); | ||||
| 		for (i in 0...Main.voxelgiClipmapCount) { | ||||
| @ -1174,18 +1184,7 @@ class Inc { | ||||
|  | ||||
| 		kha.compute.Compute.setMatrix(voxel_cb3, m.self); | ||||
|  | ||||
| 		var near = camera.data.raw.near_plane; | ||||
| 		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); | ||||
| 		kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); | ||||
|  | ||||
| 		var width = iron.App.w(); | ||||
| 		var height = iron.App.h(); | ||||
| @ -1200,7 +1199,32 @@ class Inc { | ||||
| 				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); | ||||
| 	} | ||||
| @ -1216,15 +1240,12 @@ class Inc { | ||||
|  | ||||
| 		kha.compute.Compute.setSampledTexture(voxel_ta4, rts.get("voxelsOut").image); | ||||
| 		kha.compute.Compute.setSampledTexture(voxel_tb4, rts.get("half").image); | ||||
| 		#if lnx_deferred | ||||
| 		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.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write); | ||||
|  | ||||
| 		//kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); | ||||
| 		#if rp_gbuffer2 | ||||
| 		kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); | ||||
| 		#end | ||||
|  | ||||
| 		var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); | ||||
| 		for (i in 0...Main.voxelgiClipmapCount) { | ||||
| @ -1252,18 +1273,7 @@ class Inc { | ||||
|  | ||||
| 		kha.compute.Compute.setMatrix(voxel_cb4, m.self); | ||||
|  | ||||
| 		var near = camera.data.raw.near_plane; | ||||
| 		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); | ||||
| 		kha.compute.Compute.setFloat3(voxel_cc4, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); | ||||
|  | ||||
| 		var width = iron.App.w(); | ||||
| 		var height = iron.App.h(); | ||||
| @ -1278,146 +1288,10 @@ class Inc { | ||||
| 				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); | ||||
| 	} | ||||
| 	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 // Voxels | ||||
| } | ||||
|  | ||||
| @ -15,6 +15,11 @@ class RenderPathDeferred { | ||||
| 	static var bloomUpsampler: Upsampler; | ||||
| 	#end | ||||
|  | ||||
| 	#if (rp_ssgi == "SSGI") | ||||
| 	static var ssgitex = "singleb"; | ||||
| 	static var ssgitexb = "singleb"; | ||||
| 	#end | ||||
|  | ||||
| 	public static inline function setTargetMeshes() { | ||||
| 		//Always keep the order of render targets the same as defined in compiled.inc | ||||
| 		path.setTarget("gbuffer0", [ | ||||
| @ -57,12 +62,11 @@ class RenderPathDeferred { | ||||
| 			Inc.initGI("voxels"); | ||||
| 			Inc.initGI("voxelsOut"); | ||||
| 			Inc.initGI("voxelsOutB"); | ||||
| 			#if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") | ||||
| 			#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) | ||||
| 			Inc.initGI("voxelsSDF"); | ||||
| 			Inc.initGI("voxelsSDFtmp"); | ||||
| 			#end | ||||
| 			#if (rp_voxels == "Voxel GI") | ||||
| 			Inc.initGI("voxelsLight"); | ||||
| 			Inc.initGI("voxels_diffuse"); | ||||
| 			Inc.initGI("voxels_specular"); | ||||
| 			#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_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 | ||||
|  | ||||
| 		#if ((rp_ssgi != "Off") || rp_volumetriclight) | ||||
| 		#if (rp_ssgi != "Off") | ||||
| 		{ | ||||
| 			var t = new RenderTargetRaw(); | ||||
| 			t.name = "singlea"; | ||||
| 			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); | ||||
|  | ||||
| 			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.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 = "singleb"; | ||||
| 			t.name = "volumetricb"; | ||||
| 			t.width = 0; | ||||
| 			t.height = 0; | ||||
| 			t.displayp = Inc.getDisplayp(); | ||||
| @ -368,7 +442,7 @@ class RenderPathDeferred { | ||||
| 			t.scale = Inc.getSuperSampling(); | ||||
| 			path.createRenderTarget(t); | ||||
|  | ||||
| 			// holds background depth | ||||
| 			// holds background color | ||||
| 			var t = new RenderTargetRaw(); | ||||
| 			t.name = "refr"; | ||||
| 			t.width = 0; | ||||
| @ -461,7 +535,7 @@ class RenderPathDeferred { | ||||
|  | ||||
| 		#if (rp_ssrefr || lnx_voxelgi_refract) | ||||
| 		{ | ||||
| 			path.setTarget("gbuffer_refraction"); // Only clear gbuffer0 | ||||
| 			path.setTarget("gbuffer_refraction"); | ||||
| 			path.clearTarget(0xffffff00); | ||||
| 		} | ||||
| 		#end | ||||
| @ -517,30 +591,16 @@ class RenderPathDeferred { | ||||
| 		path.drawShader("shader_datas/downsample_depth/downsample_depth"); | ||||
| 		#end | ||||
|  | ||||
| 		#if ((rp_ssgi == "RTGI") || (rp_ssgi == "RTAO")) | ||||
| 		{ | ||||
| 			if (leenkx.data.Config.raw.rp_ssgi != false) { | ||||
| 				path.setTarget("singlea"); | ||||
| 				#if rp_ssgi_half | ||||
| 				path.bindTarget("half", "gbufferD"); | ||||
| 				#else | ||||
| 				path.bindTarget("_main", "gbufferD"); | ||||
| 				#end | ||||
| 				path.bindTarget("gbuffer0", "gbuffer0"); | ||||
| 				path.drawShader("shader_datas/ssgi_pass/ssgi_pass"); | ||||
| 		#if (rp_shadowmap) | ||||
| 		// atlasing is exclusive for now | ||||
| 		#if lnx_shadowmap_atlas | ||||
| 		Inc.drawShadowMapAtlas(); | ||||
| 		#else | ||||
| 		Inc.drawShadowMap(); | ||||
| 		#end | ||||
| 		#end | ||||
|  | ||||
| 				path.setTarget("singleb"); | ||||
| 				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 (rp_ssgi == "SSAO") | ||||
| 		{ | ||||
| 			if (leenkx.data.Config.raw.rp_ssgi != false) { | ||||
| 				path.setTarget("singlea"); | ||||
| @ -559,15 +619,43 @@ class RenderPathDeferred { | ||||
| 				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) | ||||
| 		// atlasing is exclusive for now | ||||
| 		#if lnx_shadowmap_atlas | ||||
| 		Inc.drawShadowMapAtlas(); | ||||
| 		#else | ||||
| 		Inc.drawShadowMap(); | ||||
| 		#end | ||||
| 				path.drawShader("shader_datas/ssgi_pass/ssgi_pass"); | ||||
| 				path.setTarget("singleb"); | ||||
| 				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"); | ||||
| 			} | ||||
| 		} | ||||
| 		#end | ||||
|  | ||||
| 		// Voxels | ||||
| @ -580,9 +668,6 @@ class RenderPathDeferred { | ||||
|  | ||||
| 			if (iron.RenderPath.pre_clear == true) | ||||
| 			{ | ||||
| 				#if (rp_voxels == "Voxel GI") | ||||
| 				path.clearImage("voxelsLight", 0x00000000); | ||||
| 				#end | ||||
| 				path.clearImage("voxels", 0x00000000); | ||||
| 				path.clearImage("voxelsOut", 0x00000000); | ||||
| 				path.clearImage("voxelsOutB", 0x00000000); | ||||
| @ -594,26 +679,30 @@ class RenderPathDeferred { | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				#if (rp_voxels == "Voxel GI") | ||||
| 				path.clearImage("voxelsLight", 0x00000000); | ||||
| 				#end | ||||
| 				path.clearImage("voxels", 0x00000000); | ||||
| 				Inc.computeVoxelsOffsetPrev(); | ||||
| 			} | ||||
|  | ||||
| 			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(); | ||||
| 			path.setViewport(res, res); | ||||
|  | ||||
| 			path.bindTarget("voxels", "voxels"); | ||||
| 			path.drawMeshes("voxel"); | ||||
| 			#if (rp_voxels == "Voxel GI") | ||||
| 			Inc.computeVoxelsLight(); | ||||
| 			#end | ||||
|  | ||||
| 			Inc.computeVoxelsTemporal(); | ||||
|  | ||||
| 			#if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") | ||||
| 			#if (rp_voxels == "Voxel GI") | ||||
| 			Inc.computeVoxelsSDF(); | ||||
| 			#end | ||||
|  | ||||
| @ -628,7 +717,6 @@ class RenderPathDeferred { | ||||
| 			} | ||||
| 		} | ||||
| 		#end | ||||
|  | ||||
| 		// --- | ||||
| 		// Deferred light | ||||
| 		// --- | ||||
| @ -760,15 +848,9 @@ class RenderPathDeferred { | ||||
| 		} | ||||
| 		#end | ||||
|  | ||||
| 		#if (rp_translucency && !rp_ssrefr) | ||||
| 		{ | ||||
| 			Inc.drawTranslucency("tex"); | ||||
| 		} | ||||
| 		#end | ||||
|  | ||||
| 		#if rp_volumetriclight | ||||
| 		{ | ||||
| 			path.setTarget("singlea"); | ||||
| 			path.setTarget("volumetrica"); | ||||
| 			path.bindTarget("_main", "gbufferD"); | ||||
| 			#if lnx_shadowmap_atlas | ||||
| 			Inc.bindShadowMapAtlas(); | ||||
| @ -777,85 +859,16 @@ class RenderPathDeferred { | ||||
| 			#end | ||||
| 			path.drawShader("shader_datas/volumetric_light/volumetric_light"); | ||||
|  | ||||
| 			path.setTarget("singleb"); | ||||
| 			path.bindTarget("singlea", "tex"); | ||||
| 			path.setTarget("volumetricb"); | ||||
| 			path.bindTarget("volumetrica", "tex"); | ||||
| 			path.drawShader("shader_datas/blur_bilat_pass/blur_bilat_pass_x"); | ||||
|  | ||||
| 			path.setTarget("tex"); | ||||
| 			path.bindTarget("singleb", "tex"); | ||||
| 			path.bindTarget("volumetricb", "tex"); | ||||
| 			path.drawShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y"); | ||||
| 		} | ||||
| 		#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 (leenkx.data.Config.raw.rp_ssr != false) { | ||||
| @ -900,6 +913,88 @@ class RenderPathDeferred { | ||||
| 		} | ||||
| 		#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 (leenkx.data.Config.raw.rp_motionblur != false) { | ||||
| @ -964,6 +1059,12 @@ class RenderPathDeferred { | ||||
| 		} | ||||
| 		#end | ||||
|  | ||||
| 		#if rp_bloom | ||||
| 		{ | ||||
| 			inline Inc.drawBloom("tex", bloomDownsampler, bloomUpsampler); | ||||
| 		} | ||||
| 		#end | ||||
|  | ||||
| 		#if (rp_supersampling == 4) | ||||
| 		var framebuffer = "buf"; | ||||
| 		#else | ||||
|  | ||||
| @ -142,16 +142,17 @@ class RenderPathForward { | ||||
| 				t.width = 0; | ||||
| 				t.height = 0; | ||||
| 				t.displayp = Inc.getDisplayp(); | ||||
| 				t.format = "R32"; | ||||
| 				t.format = "DEPTH24"; | ||||
| 				t.scale = Inc.getSuperSampling(); | ||||
| 				path.createRenderTarget(t); | ||||
|  | ||||
| 				//holds colors before refractive meshes are drawn | ||||
| 				var t = new RenderTargetRaw(); | ||||
| 				t.name = "refr"; | ||||
| 				t.width = 0; | ||||
| 				t.height = 0; | ||||
| 				t.displayp = Inc.getDisplayp(); | ||||
| 				t.format = "RGBA64"; | ||||
| 				t.format = Inc.getHdrFormat(); | ||||
| 				t.scale = Inc.getSuperSampling(); | ||||
| 				path.createRenderTarget(t); | ||||
| 			} | ||||
| @ -200,17 +201,10 @@ class RenderPathForward { | ||||
| 			Inc.initGI("voxels"); | ||||
| 			Inc.initGI("voxelsOut"); | ||||
| 			Inc.initGI("voxelsOutB"); | ||||
| 			#if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) | ||||
| 			#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) | ||||
| 			Inc.initGI("voxelsSDF"); | ||||
| 			Inc.initGI("voxelsSDFtmp"); | ||||
| 			#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>(); | ||||
| 			for (i in 0...Main.voxelgiClipmapCount) { | ||||
| 				var clipmap = new iron.object.Clipmap(); | ||||
| @ -257,18 +251,25 @@ class RenderPathForward { | ||||
| 			#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/blur_bilat_pass/blur_bilat_pass_x"); | ||||
| 			path.loadShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y"); | ||||
| 			#end | ||||
|  | ||||
|  | ||||
| 			var t = new RenderTargetRaw(); | ||||
| 			t.name = "singlea"; | ||||
| 			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(); | ||||
| 			path.createRenderTarget(t); | ||||
|  | ||||
| @ -277,7 +278,11 @@ class RenderPathForward { | ||||
| 			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(); | ||||
| 			path.createRenderTarget(t); | ||||
| 		} | ||||
| @ -374,9 +379,6 @@ class RenderPathForward { | ||||
|  | ||||
| 			if (iron.RenderPath.pre_clear == true) | ||||
| 			{ | ||||
| 				#if (rp_voxels == "Voxel GI") | ||||
| 				path.clearImage("voxelsLight", 0x00000000); | ||||
| 				#end | ||||
| 				path.clearImage("voxels", 0x00000000); | ||||
| 				path.clearImage("voxelsOut", 0x00000000); | ||||
| 				path.clearImage("voxelsOutB", 0x00000000); | ||||
| @ -388,9 +390,6 @@ class RenderPathForward { | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				#if (rp_voxels == "Voxel GI") | ||||
| 				path.clearImage("voxelsLight", 0x00000000); | ||||
| 				#end | ||||
| 				path.clearImage("voxels", 0x00000000); | ||||
| 				Inc.computeVoxelsOffsetPrev(); | ||||
| 			} | ||||
| @ -400,27 +399,12 @@ class RenderPathForward { | ||||
| 			path.setViewport(res, res); | ||||
|  | ||||
| 			path.bindTarget("voxels", "voxels"); | ||||
| 			path.drawMeshes("voxel"); | ||||
|  | ||||
| 			#if (rp_voxels == "Voxel GI") | ||||
| 			Inc.computeVoxelsLight(); | ||||
| 			#end | ||||
| 			Inc.computeVoxelsTemporal(); | ||||
|  | ||||
| 			#if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) | ||||
| 			Inc.computeVoxelsSDF(); | ||||
| 			#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 | ||||
|  | ||||
| @ -439,7 +423,7 @@ class RenderPathForward { | ||||
| 		#if (rp_ssrefr || lnx_voxelgi_refract) | ||||
| 		{ | ||||
| 			path.setTarget("gbuffer_refraction"); // Only clear gbuffer0 | ||||
| 			path.clearTarget(0xff000000); | ||||
| 			path.clearTarget(0xffffff00); | ||||
| 		} | ||||
| 		#end | ||||
|  | ||||
| @ -449,13 +433,6 @@ class RenderPathForward { | ||||
| 		} | ||||
| 		#end | ||||
|  | ||||
| 		#if rp_ssrefr | ||||
| 		{ | ||||
| 			path.setTarget("gbuffer_refraction"); | ||||
| 			path.clearTarget(0xffffff00); | ||||
| 		} | ||||
| 		#end | ||||
|  | ||||
| 		RenderPathCreator.setTargetMeshes(); | ||||
|  | ||||
| 		#if rp_shadowmap | ||||
| @ -472,19 +449,12 @@ class RenderPathForward { | ||||
| 		#if (rp_voxels != "Off") | ||||
| 		if (leenkx.data.Config.raw.rp_gi != false) | ||||
| 		{ | ||||
| 			#if (rp_voxels == "Voxel AO") | ||||
| 			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 | ||||
| 			#if (rp_voxels != "Off") | ||||
| 			path.bindTarget("voxelsOut", "voxels"); | ||||
| 			#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) | ||||
| 			path.bindTarget("voxelsSDF", "voxelsSDF"); | ||||
| 			#end | ||||
| 			#end | ||||
| 		} | ||||
| 		#end | ||||
|  | ||||
| @ -522,14 +492,31 @@ class RenderPathForward { | ||||
|  | ||||
| 					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"); | ||||
| 					#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("lbuffer0"); | ||||
|  | ||||
| 					path.bindTarget("lbuffer0", "tex"); | ||||
| 					path.bindTarget("refr", "tex1"); | ||||
| 					path.bindTarget("_main", "gbufferD"); | ||||
| @ -577,6 +564,50 @@ class RenderPathForward { | ||||
| 			} | ||||
| 			#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 | ||||
| 			{ | ||||
| 				inline Inc.drawBloom("lbuffer0", bloomDownsampler, bloomUpsampler); | ||||
|  | ||||
| @ -41,7 +41,11 @@ class Starter { | ||||
| 			try { | ||||
| 			#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() { | ||||
| 					#if lnx_loadscreen | ||||
|  | ||||
| @ -59,6 +59,9 @@ def add_world_defs(): | ||||
|         if rpdat.rp_shadowmap_cascades != '1': | ||||
|             wrd.world_defs += '_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: | ||||
|             assets.add_khafile_def('lnx_shadowmap_atlas') | ||||
|             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): | ||||
|             wrd.world_defs += '_VoxelShadow' | ||||
|             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: | ||||
|             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_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' | ||||
|             if rpdat.lnx_voxelgi_refract: | ||||
|                 wrd.world_defs += '_VoxelRefract' | ||||
|                 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: | ||||
|             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)) | ||||
|         if rpdat.rp_ssgi != 'Off': | ||||
|             wrd.world_defs += '_SSAO' | ||||
|             if rpdat.rp_ssgi == 'SSAO': | ||||
|                 wrd.world_defs += '_SSAO' | ||||
|                 assets.add_shader_pass('ssao_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: | ||||
|                 assets.add_shader_pass('ssgi_pass') | ||||
|                 assets.add_shader_pass('blur_edge_pass') | ||||
| @ -457,7 +462,8 @@ def build(): | ||||
|     if 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: | ||||
|         assets.add_khafile_def('rp_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_strength = 1.0 | ||||
|         world.world_defs += '_EnvCol' | ||||
|         assets.add_khafile_def("lnx_envcol") | ||||
|  | ||||
|     # Clouds enabled | ||||
|     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 | ||||
|         if rpdat.lnx_irradiance and not solid_mat: | ||||
|             wrd.world_defs += '_Irr' | ||||
|             assets.add_khafile_def("lnx_irradiance") | ||||
|  | ||||
|         # Extract environment strength | ||||
|         # 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' | ||||
|             if rpdat.lnx_irradiance and not solid_mat: | ||||
|                 world.world_defs += '_Irr' | ||||
|                 assets.add_khafile_def("lnx_irradiance") | ||||
|             world.lnx_envtex_color = node_surface.inputs[0].default_value | ||||
|             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]) | ||||
|         state.out_roughness = c.parse_value_input(node.inputs[1]) | ||||
|     if state.parse_opacity: | ||||
|         state.out_opacity = '0.1' | ||||
|         state.out_opacity = '1.0' | ||||
|         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]) | ||||
|         state.out_roughness = c.parse_value_input(node.inputs[1]) | ||||
|     if state.parse_opacity: | ||||
|         state.out_opacity = '0.0' | ||||
|         state.out_opacity = '1.0' | ||||
|         state.out_ior = c.parse_value_input(node.inputs[2]) | ||||
|  | ||||
| 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 | ||||
|     curshader = state.curshader | ||||
|  | ||||
|     # Match to cycles | ||||
|     world.lnx_envtex_strength *= 0.1 | ||||
|  | ||||
|     assets.add_khafile_def('lnx_hosek') | ||||
|     curshader.add_uniform('vec3 A', link="_hosekA") | ||||
|     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) | ||||
|     is_mobile = rpdat.lnx_material_model == 'Mobile' | ||||
|     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 = '_SingleAtlas' in wrd.world_defs | ||||
|  | ||||
| @ -33,14 +34,17 @@ def write(vert: shader.Shader, frag: shader.Shader): | ||||
|         if is_shadows_atlas: | ||||
|             if not is_single_atlas: | ||||
|                 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: | ||||
|                 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) | ||||
|         else: | ||||
|             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)): | ||||
|         vert.add_out('vec4 wvpposition') | ||||
| @ -62,13 +66,16 @@ def write(vert: shader.Shader, frag: shader.Shader): | ||||
|             if is_shadows_atlas: | ||||
|                 if not is_single_atlas: | ||||
|                     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: | ||||
|                     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: | ||||
|                 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.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('    specular,') | ||||
|     frag.write('    f0') | ||||
|  | ||||
|     if is_shadows: | ||||
|         if parse_opacity: | ||||
|             frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, opacity != 1.0') # bias | ||||
|         else: | ||||
|             frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false') # bias | ||||
|         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) | ||||
| @ -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, lightsArraySpot[li * 2 + 1].xyz') # right | ||||
|     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: | ||||
|         frag.write('\t, occlusion') | ||||
|     if '_SSRS' in wrd.world_defs: | ||||
|         frag.add_uniform('sampler2D gbufferD') | ||||
|         frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') | ||||
|         frag.add_uniform('vec3 eye', '_cameraPosition') | ||||
|         frag.add_uniform('sampler2D gbufferD', link='_gbufferD', top=True) | ||||
|         frag.write(', gbufferD, invVP, eye') | ||||
|     frag.write(');') | ||||
|  | ||||
|  | ||||
| @ -1,155 +1,161 @@ | ||||
| import bpy | ||||
|  | ||||
| import lnx | ||||
| import lnx.material.mat_state as mat_state | ||||
| import lnx.material.make_tess as make_tess | ||||
| from lnx.material.shader import ShaderContext | ||||
|  | ||||
| if lnx.is_reload(__name__): | ||||
|     mat_state = lnx.reload_module(mat_state) | ||||
|     make_tess = lnx.reload_module(make_tess) | ||||
|     lnx.material.shader = lnx.reload_module(lnx.material.shader) | ||||
|     from lnx.material.shader import ShaderContext | ||||
| else: | ||||
|     lnx.enable_reload(__name__) | ||||
|  | ||||
|  | ||||
| def make(con_mesh: ShaderContext): | ||||
|     vert = con_mesh.vert | ||||
|     frag = con_mesh.frag | ||||
|     geom = con_mesh.geom | ||||
|     tesc = con_mesh.tesc | ||||
|     tese = con_mesh.tese | ||||
|  | ||||
|     # Additional values referenced in cycles | ||||
|     # TODO: enable from cycles.py | ||||
|     if frag.contains('dotNV') and not frag.contains('float dotNV'): | ||||
|         frag.write_init('float dotNV = max(dot(n, vVec), 0.0);') | ||||
|  | ||||
|         # n is not always defined yet (in some shadowmap shaders e.g.) | ||||
|         if not frag.contains('vec3 n'): | ||||
|             vert.add_out('vec3 wnormal') | ||||
|             billboard = mat_state.material.lnx_billboard | ||||
|             if billboard == 'spherical': | ||||
|                 vert.add_uniform('mat3 N', '_normalMatrixSphere') | ||||
|             elif billboard == 'cylindrical': | ||||
|                 vert.add_uniform('mat3 N', '_normalMatrixCylinder') | ||||
|             else: | ||||
|                 vert.add_uniform('mat3 N', '_normalMatrix') | ||||
|             vert.write_attrib('wnormal = normalize(N * vec3(nor.xy, pos.w));') | ||||
|             frag.write_attrib('vec3 n = normalize(wnormal);') | ||||
|  | ||||
|             # If not yet added, add nor vertex data | ||||
|             vertex_elems = con_mesh.data['vertex_elements'] | ||||
|             has_normals = False | ||||
|             for elem in vertex_elems: | ||||
|                 if elem['name'] == 'nor': | ||||
|                     has_normals = True | ||||
|                     break | ||||
|             if not has_normals: | ||||
|                 vertex_elems.append({'name': 'nor', 'data': 'short2norm'}) | ||||
|  | ||||
|     write_wpos = False | ||||
|     if frag.contains('vVec') and not frag.contains('vec3 vVec'): | ||||
|         if tese is not None: | ||||
|             tese.add_out('vec3 eyeDir') | ||||
|             tese.add_uniform('vec3 eye', '_cameraPosition') | ||||
|             tese.write('eyeDir = eye - wposition;') | ||||
|  | ||||
|         else: | ||||
|             if not vert.contains('wposition'): | ||||
|                 write_wpos = True | ||||
|             vert.add_out('vec3 eyeDir') | ||||
|             vert.add_uniform('vec3 eye', '_cameraPosition') | ||||
|             vert.write('eyeDir = eye - wposition;') | ||||
|         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: | ||||
|         vert.add_uniform('mat4 W', '_worldMatrix') | ||||
|         vert.add_out('vec3 wposition') | ||||
|         vert.write('wposition = vec4(W * spos).xyz;') | ||||
|     elif write_wpos: | ||||
|         vert.add_uniform('mat4 W', '_worldMatrix') | ||||
|         vert.write_attrib('vec3 wposition = vec4(W * spos).xyz;') | ||||
|  | ||||
|     frag_mpos = (frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition') | ||||
|     if frag_mpos: | ||||
|         vert.add_out('vec3 mposition') | ||||
|         vert.add_uniform('float posUnpack', link='_posUnpack') | ||||
|         vert.write_attrib('mposition = spos.xyz * posUnpack;') | ||||
|  | ||||
|     if tese is not None: | ||||
|         if frag_mpos: | ||||
|             make_tess.interpolate(tese, 'mposition', 3, declare_out=True) | ||||
|         elif tese.contains('mposition') and not tese.contains('vec3 mposition'): | ||||
|             vert.add_out('vec3 mposition') | ||||
|             vert.write_pre = True | ||||
|             vert.add_uniform('float posUnpack', link='_posUnpack') | ||||
|             vert.write('mposition = spos.xyz * posUnpack;') | ||||
|             vert.write_pre = False | ||||
|             make_tess.interpolate(tese, 'mposition', 3, declare_out=False) | ||||
|  | ||||
|     frag_bpos = (frag.contains('bposition') and not frag.contains('vec3 bposition')) or vert.contains('bposition') | ||||
|     if frag_bpos: | ||||
|         vert.add_out('vec3 bposition') | ||||
|         vert.add_uniform('vec3 dim', link='_dim') | ||||
|         vert.add_uniform('vec3 hdim', link='_halfDim') | ||||
|         vert.add_uniform('float posUnpack', link='_posUnpack') | ||||
|         vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') | ||||
|         vert.write_attrib('if (dim.z == 0) bposition.z = 0;') | ||||
|         vert.write_attrib('if (dim.y == 0) bposition.y = 0;') | ||||
|         vert.write_attrib('if (dim.x == 0) bposition.x = 0;') | ||||
|  | ||||
|     if tese is not None: | ||||
|         if frag_bpos: | ||||
|             make_tess.interpolate(tese, 'bposition', 3, declare_out=True) | ||||
|         elif tese.contains('bposition') and not tese.contains('vec3 bposition'): | ||||
|             vert.add_out('vec3 bposition') | ||||
|             vert.add_uniform('vec3 dim', link='_dim') | ||||
|             vert.add_uniform('vec3 hdim', link='_halfDim') | ||||
|             vert.add_uniform('float posUnpack', link='_posUnpack') | ||||
|             vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') | ||||
|             make_tess.interpolate(tese, 'bposition', 3, declare_out=False) | ||||
|  | ||||
|     frag_wtan = (frag.contains('wtangent') and not frag.contains('vec3 wtangent')) or vert.contains('wtangent') | ||||
|     if frag_wtan: | ||||
|         # Indicate we want tang attrib in finalizer to prevent TBN generation | ||||
|         con_mesh.add_elem('tex', 'short2norm') | ||||
|         con_mesh.add_elem('tang', 'short4norm') | ||||
|         vert.add_out('vec3 wtangent') | ||||
|         vert.write_pre = True | ||||
|         vert.write('wtangent = normalize(N * tang.xyz);') | ||||
|         vert.write_pre = False | ||||
|  | ||||
|     if tese is not None: | ||||
|         if frag_wtan: | ||||
|             make_tess.interpolate(tese, 'wtangent', 3, declare_out=True) | ||||
|         elif tese.contains('wtangent') and not tese.contains('vec3 wtangent'): | ||||
|             vert.add_out('vec3 wtangent') | ||||
|             vert.write_pre = True | ||||
|             vert.write('wtangent = normalize(N * tang.xyz);') | ||||
|             vert.write_pre = False | ||||
|             make_tess.interpolate(tese, 'wtangent', 3, declare_out=False) | ||||
|  | ||||
|     if frag.contains('vVecCam'): | ||||
|         vert.add_out('vec3 eyeDirCam') | ||||
|         vert.add_uniform('mat4 WV', '_worldViewMatrix') | ||||
|         vert.write('eyeDirCam = vec4(WV * spos).xyz; eyeDirCam.z *= -1;') | ||||
|         frag.write_attrib('vec3 vVecCam = normalize(eyeDirCam);') | ||||
|  | ||||
|     if frag.contains('nAttr'): | ||||
|         vert.add_out('vec3 nAttr') | ||||
|         vert.write_attrib('nAttr = vec3(nor.xy, pos.w);') | ||||
|  | ||||
|     wrd = bpy.data.worlds['Lnx'] | ||||
|     if '_Legacy' in wrd.world_defs: | ||||
|         frag.replace('sampler2DShadow', 'sampler2D') | ||||
|         frag.replace('samplerCubeShadow', 'samplerCube') | ||||
| import bpy | ||||
|  | ||||
| import lnx | ||||
| import lnx.material.mat_state as mat_state | ||||
| import lnx.material.make_tess as make_tess | ||||
| from lnx.material.shader import ShaderContext | ||||
|  | ||||
| if lnx.is_reload(__name__): | ||||
|     mat_state = lnx.reload_module(mat_state) | ||||
|     make_tess = lnx.reload_module(make_tess) | ||||
|     lnx.material.shader = lnx.reload_module(lnx.material.shader) | ||||
|     from lnx.material.shader import ShaderContext | ||||
| else: | ||||
|     lnx.enable_reload(__name__) | ||||
|  | ||||
|  | ||||
| def make(con_mesh: ShaderContext): | ||||
|     vert = con_mesh.vert | ||||
|     frag = con_mesh.frag | ||||
|     geom = con_mesh.geom | ||||
|     tesc = con_mesh.tesc | ||||
|     tese = con_mesh.tese | ||||
|  | ||||
|     # Additional values referenced in cycles | ||||
|     # TODO: enable from cycles.py | ||||
|     if frag.contains('dotNV') and not frag.contains('float dotNV'): | ||||
|         frag.write_init('float dotNV = max(dot(n, vVec), 0.0);') | ||||
|  | ||||
|         # n is not always defined yet (in some shadowmap shaders e.g.) | ||||
|         if not frag.contains('vec3 n'): | ||||
|             vert.add_out('vec3 wnormal') | ||||
|             billboard = mat_state.material.lnx_billboard | ||||
|             if billboard == 'spherical': | ||||
|                 vert.add_uniform('mat3 N', '_normalMatrixSphere') | ||||
|             elif billboard == 'cylindrical': | ||||
|                 vert.add_uniform('mat3 N', '_normalMatrixCylinder') | ||||
|             else: | ||||
|                 vert.add_uniform('mat3 N', '_normalMatrix') | ||||
|             vert.write_attrib('wnormal = normalize(N * vec3(nor.xy, pos.w));') | ||||
|             frag.write_attrib('vec3 n = normalize(wnormal);') | ||||
|  | ||||
|             # If not yet added, add nor vertex data | ||||
|             vertex_elems = con_mesh.data['vertex_elements'] | ||||
|             has_normals = False | ||||
|             for elem in vertex_elems: | ||||
|                 if elem['name'] == 'nor': | ||||
|                     has_normals = True | ||||
|                     break | ||||
|             if not has_normals: | ||||
|                 vertex_elems.append({'name': 'nor', 'data': 'short2norm'}) | ||||
|  | ||||
|     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 tese is not None: | ||||
|             tese.add_out('vec3 eyeDir') | ||||
|             tese.add_uniform('vec3 eye', '_cameraPosition') | ||||
|             tese.write('eyeDir = eye - wposition;') | ||||
|  | ||||
|         else: | ||||
|             if not vert.contains('wposition'): | ||||
|                 write_wpos = True | ||||
|             vert.add_out('vec3 eyeDir') | ||||
|             vert.add_uniform('vec3 eye', '_cameraPosition') | ||||
|             vert.write('eyeDir = eye - wposition;') | ||||
|         frag.write_attrib('vec3 vVec = normalize(eyeDir);') | ||||
|  | ||||
|     if export_wpos: | ||||
|         vert.add_uniform('mat4 W', '_worldMatrix') | ||||
|         vert.add_out('vec3 wposition') | ||||
|         vert.write_attrib('wposition = vec4(W * spos).xyz;') | ||||
|     elif write_wpos: | ||||
|         vert.add_uniform('mat4 W', '_worldMatrix') | ||||
|         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') | ||||
|     if frag_mpos: | ||||
|         vert.add_out('vec3 mposition') | ||||
|         vert.add_uniform('float posUnpack', link='_posUnpack') | ||||
|         vert.write_attrib('mposition = spos.xyz * posUnpack;') | ||||
|  | ||||
|     if tese is not None: | ||||
|         if frag_mpos: | ||||
|             make_tess.interpolate(tese, 'mposition', 3, declare_out=True) | ||||
|         elif tese.contains('mposition') and not tese.contains('vec3 mposition'): | ||||
|             vert.add_out('vec3 mposition') | ||||
|             vert.write_pre = True | ||||
|             vert.add_uniform('float posUnpack', link='_posUnpack') | ||||
|             vert.write('mposition = spos.xyz * posUnpack;') | ||||
|             vert.write_pre = False | ||||
|             make_tess.interpolate(tese, 'mposition', 3, declare_out=False) | ||||
|  | ||||
|     frag_bpos = (frag.contains('bposition') and not frag.contains('vec3 bposition')) or vert.contains('bposition') | ||||
|     if frag_bpos: | ||||
|         vert.add_out('vec3 bposition') | ||||
|         vert.add_uniform('vec3 dim', link='_dim') | ||||
|         vert.add_uniform('vec3 hdim', link='_halfDim') | ||||
|         vert.add_uniform('float posUnpack', link='_posUnpack') | ||||
|         vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') | ||||
|         vert.write_attrib('if (dim.z == 0) bposition.z = 0;') | ||||
|         vert.write_attrib('if (dim.y == 0) bposition.y = 0;') | ||||
|         vert.write_attrib('if (dim.x == 0) bposition.x = 0;') | ||||
|  | ||||
|     if tese is not None: | ||||
|         if frag_bpos: | ||||
|             make_tess.interpolate(tese, 'bposition', 3, declare_out=True) | ||||
|         elif tese.contains('bposition') and not tese.contains('vec3 bposition'): | ||||
|             vert.add_out('vec3 bposition') | ||||
|             vert.add_uniform('vec3 dim', link='_dim') | ||||
|             vert.add_uniform('vec3 hdim', link='_halfDim') | ||||
|             vert.add_uniform('float posUnpack', link='_posUnpack') | ||||
|             vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') | ||||
|             make_tess.interpolate(tese, 'bposition', 3, declare_out=False) | ||||
|  | ||||
|     frag_wtan = (frag.contains('wtangent') and not frag.contains('vec3 wtangent')) or vert.contains('wtangent') | ||||
|     if frag_wtan: | ||||
|         # Indicate we want tang attrib in finalizer to prevent TBN generation | ||||
|         con_mesh.add_elem('tex', 'short2norm') | ||||
|         con_mesh.add_elem('tang', 'short4norm') | ||||
|         vert.add_out('vec3 wtangent') | ||||
|         vert.write_pre = True | ||||
|         vert.write('wtangent = normalize(N * tang.xyz);') | ||||
|         vert.write_pre = False | ||||
|  | ||||
|     if tese is not None: | ||||
|         if frag_wtan: | ||||
|             make_tess.interpolate(tese, 'wtangent', 3, declare_out=True) | ||||
|         elif tese.contains('wtangent') and not tese.contains('vec3 wtangent'): | ||||
|             vert.add_out('vec3 wtangent') | ||||
|             vert.write_pre = True | ||||
|             vert.write('wtangent = normalize(N * tang.xyz);') | ||||
|             vert.write_pre = False | ||||
|             make_tess.interpolate(tese, 'wtangent', 3, declare_out=False) | ||||
|  | ||||
|     if frag.contains('vVecCam'): | ||||
|         vert.add_out('vec3 eyeDirCam') | ||||
|         vert.add_uniform('mat4 WV', '_worldViewMatrix') | ||||
|         vert.write('eyeDirCam = vec4(WV * spos).xyz; eyeDirCam.z *= -1;') | ||||
|         frag.write_attrib('vec3 vVecCam = normalize(eyeDirCam);') | ||||
|  | ||||
|     if frag.contains('nAttr'): | ||||
|         vert.add_out('vec3 nAttr') | ||||
|         vert.write_attrib('nAttr = vec3(nor.xy, pos.w);') | ||||
|  | ||||
|     wrd = bpy.data.worlds['Lnx'] | ||||
|     if '_Legacy' in wrd.world_defs: | ||||
|         frag.replace('sampler2DShadow', 'sampler2D') | ||||
|         frag.replace('samplerCubeShadow', 'samplerCube') | ||||
|  | ||||
| @ -559,7 +559,7 @@ def make_forward(con_mesh): | ||||
|             frag.write('fragColor[0] = vec4(direct + indirect, packFloat2(occlusion, specular));') | ||||
|             frag.write('fragColor[1] = vec4(n.xy, roughness, metallic);') | ||||
|             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: | ||||
|             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.add_out('vec3 eyeDir') | ||||
|     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') | ||||
|     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' | ||||
| @ -632,7 +664,10 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | ||||
|     if '_Brdf' in wrd.world_defs: | ||||
|         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('vec3 F = f0 * envBRDF.x + envBRDF.y;') | ||||
|     else: | ||||
|         frag.write('vec3 F = f0;') | ||||
|          | ||||
|     if '_Irr' in wrd.world_defs: | ||||
|         frag.add_include('std/shirr.glsl') | ||||
|         frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance') | ||||
| @ -657,51 +692,37 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | ||||
|     frag.write('envl *= albedo;') | ||||
|  | ||||
|     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: | ||||
|         frag.write('envl += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);') | ||||
|         frag.write('envl += prefilteredColor * F;') | ||||
|     elif '_EnvCol' in wrd.world_defs: | ||||
|         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.write('envl *= envmapStrength * occlusion;') | ||||
|  | ||||
|     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_uniform('sampler3D voxels') | ||||
|             frag.add_uniform('sampler3D voxelsSDF') | ||||
|             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;') | ||||
|         frag.add_include('std/conetrace.glsl') | ||||
|         frag.add_uniform('sampler3D voxels') | ||||
|         frag.add_uniform('sampler3D voxelsSDF') | ||||
|         frag.add_uniform('float clipmaps[10 * voxelgiClipmapCount]', '_clipmaps') | ||||
|  | ||||
|     if '_VoxelAOvar' in wrd.world_defs and not parse_opacity: | ||||
|         frag.add_uniform("sampler2D voxels_ao"); | ||||
|         frag.write('envl *= textureLod(voxels_ao, texCoord, 0.0).rrr;') | ||||
|     if '_VoxelAOvar' in wrd.world_defs: | ||||
|         frag.write('envl *= (1.0 - traceAO(wposition, n, voxels, clipmaps));') | ||||
|  | ||||
|     if '_VoxelGI' in wrd.world_defs: | ||||
|         frag.write('vec3 indirect = vec3(0.0);') | ||||
|     else: | ||||
|         frag.write('vec3 indirect = envl;') | ||||
|          | ||||
|     if '_VoxelGI' in wrd.world_defs: | ||||
|         if parse_opacity: | ||||
|             frag.write('vec4 trace = traceDiffuse(wposition, wnormal, voxels, clipmaps);') | ||||
|             frag.write('indirect = ((trace.rgb * albedo + envl * (1.0 - trace.a)) * voxelgiDiff);') | ||||
|             frag.write('if (roughness < 1.0 && specular > 0.0){') | ||||
|             frag.add_uniform('sampler2D sveloc') | ||||
|             frag.write('    vec2 velocity = -textureLod(sveloc, gl_FragCoord.xy, 0.0).rg;') | ||||
|             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;") | ||||
|  | ||||
|     if '_VoxelGI' in wrd.world_defs: | ||||
|         frag.write('vec2 velocity = gl_FragCoord.xy;') | ||||
|         frag.write('vec4 diffuse_indirect = traceDiffuse(wposition, n, voxels, clipmaps);') | ||||
|         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('    indirect += traceSpecular(wposition, n, voxels, voxelsSDF, vVec, roughness * roughness, clipmaps, gl_FragCoord.xy, velocity).rgb * F * voxelgiRefl;') | ||||
|         frag.write('}') | ||||
|     frag.write('vec3 direct = vec3(0.0);') | ||||
|  | ||||
|     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: | ||||
|             frag.add_uniform('bool receiveShadow') | ||||
|             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.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') | ||||
|                 if parse_opacity: | ||||
|                     frag.write(f'svisibility = shadowTestCascade({shadowmap_sun}, {shadowmap_sun_tr}, eye, wposition + n * shadowsBias * 10, shadowsBias, true);') | ||||
|                 else: | ||||
|                     frag.write(f'svisibility = shadowTestCascade({shadowmap_sun}, {shadowmap_sun_tr}, eye, wposition + n * shadowsBias * 10, shadowsBias, false);') | ||||
|  | ||||
|                 frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') | ||||
|                 if is_transparent_shadows: | ||||
|                     frag.write(f'{shadowmap_sun_tr},') | ||||
|                 frag.write('eye, wposition + n * shadowsBias * 10, shadowsBias') | ||||
|                 if is_transparent_shadows: | ||||
|                     frag.write(', false') | ||||
|                 frag.write(');') | ||||
|             else: | ||||
|                 if tese is not None: | ||||
|                     tese.add_out('vec4 lightPosition') | ||||
| @ -740,15 +764,18 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | ||||
|                     else: | ||||
|                         vert.add_out('vec4 lightPosition') | ||||
|                         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('const vec2 smSize = shadowmapSize;') | ||||
|                 if parse_opacity: | ||||
|                     frag.write(f'svisibility = PCF({shadowmap_sun}, {shadowmap_sun_tr}, lPos.xy, lPos.z - shadowsBias, smSize, true);') | ||||
|                 else: | ||||
|                     frag.write(f'svisibility = PCF({shadowmap_sun}, {shadowmap_sun_tr}, lPos.xy, lPos.z - shadowsBias, smSize, false);') | ||||
|                 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(');') | ||||
|             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('direct += (lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;') | ||||
|         # sun | ||||
| @ -767,7 +794,8 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | ||||
|                 # 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) | ||||
|                 frag.add_uniform('sampler2D shadowMapSpotTransparent[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) | ||||
| @ -775,18 +803,19 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): | ||||
|         frag.write('direct += sampleLight(') | ||||
|         frag.write('  wposition, n, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') | ||||
|         if is_shadows: | ||||
|             if parse_opacity: | ||||
|                 frag.write(', 0, pointBias, receiveShadow, opacity != 1.0') | ||||
|             else: | ||||
|                 frag.write(', 0, pointBias, receiveShadow, false') | ||||
|             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') | ||||
|         if '_VoxelShadow' in wrd.world_defs: | ||||
|             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: | ||||
|             frag.write(', occlusion') | ||||
|         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('vec3 eye', '_cameraPosition') | ||||
|             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: | ||||
|         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, clipmaps, gl_FragCoord.xy,velocity).rgb;') | ||||
|         frag.write('    indirect = mix(refraction, indirect, opacity) * voxelgiRefr;') | ||||
|         frag.write('    direct = mix(refraction, direct, opacity) * voxelgiRefr;') | ||||
|         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('    indirect = mix(refraction, indirect, opacity);') | ||||
|         frag.write('    direct = mix(refraction, direct, opacity);') | ||||
|         frag.write('}') | ||||
|  | ||||
| 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;') | ||||
|     if parse_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[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) | ||||
|  | ||||
|  | ||||
| @ -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 | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -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) | ||||
|     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_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_play_camera = EnumProperty( | ||||
|         items=[('Scene', 'Scene', 'Scene'), | ||||
|  | ||||
| @ -65,8 +65,8 @@ def update_preset(self, context): | ||||
|         rpdat.rp_background = 'World' | ||||
|         rpdat.rp_stereo = False | ||||
|         rpdat.rp_voxelgi_resolution = '32' | ||||
|         rpdat.lnx_voxelgi_size = 0.25 | ||||
|         rpdat.rp_voxels = 'Voxel AO' | ||||
|         rpdat.lnx_voxelgi_size = 0.125 | ||||
|         rpdat.rp_voxels = 'Voxel GI' | ||||
|         rpdat.rp_render_to_texture = True | ||||
|         rpdat.rp_supersampling = '1' | ||||
|         rpdat.rp_antialiasing = 'SMAA' | ||||
| @ -142,8 +142,8 @@ def update_preset(self, context): | ||||
|         rpdat.rp_stereo = False | ||||
|         rpdat.rp_voxels = 'Voxel GI' | ||||
|         rpdat.rp_voxelgi_resolution = '64' | ||||
|         rpdat.lnx_voxelgi_size = 0.25 | ||||
|         rpdat.lnx_voxelgi_step = 0.25 | ||||
|         rpdat.lnx_voxelgi_size = 0.125 | ||||
|         rpdat.lnx_voxelgi_step = 0.01 | ||||
|         rpdat.lnx_voxelgi_revoxelize = False | ||||
|         rpdat.lnx_voxelgi_camera = False | ||||
|         rpdat.rp_voxelgi_emission = False | ||||
| @ -152,7 +152,7 @@ def update_preset(self, context): | ||||
|         rpdat.rp_antialiasing = 'TAA' | ||||
|         rpdat.rp_compositornodes = True | ||||
|         rpdat.rp_volumetriclight = False | ||||
|         rpdat.rp_ssgi = 'RTAO' | ||||
|         rpdat.rp_ssgi = 'SSGI' | ||||
|         rpdat.lnx_ssrs = False | ||||
|         rpdat.lnx_micro_shadowing = 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_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_transparent: BoolProperty(name="Transparency", description="Enable shadows for transparent objects", default=False, update=update_renderpath) | ||||
|     rp_shadowmap_atlas_lod_subdivisions: EnumProperty( | ||||
|         items=[('2', '2', '2'), | ||||
|                ('3', '3', '3'), | ||||
| @ -391,7 +392,8 @@ class LnxRPListItem(bpy.types.PropertyGroup): | ||||
|     rp_ssgi: EnumProperty( | ||||
|         items=[('Off', 'No AO', 'Off'), | ||||
|                ('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') | ||||
|                ], | ||||
|         name="SSGI", description="Screen space global illumination", default='SSAO', update=update_renderpath) | ||||
| @ -508,7 +510,7 @@ class LnxRPListItem(bpy.types.PropertyGroup): | ||||
|         	   ('1', '1', '1'), | ||||
|                ('2', '2', '2')], | ||||
|         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_shadows: BoolProperty(name="Shadows", description="Use voxels to render shadows", default=False, update=update_renderpath) | ||||
|     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_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_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_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_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) | ||||
| @ -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_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_ssgi_strength: FloatProperty(name="Strength", default=1.0, update=assets.invalidate_shader_cache) | ||||
|     lnx_ssgi_radius: FloatProperty(name="Radius", 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=0.750, 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( | ||||
|         items=[('9', '9', '9'), | ||||
|                ('5', '5', '5'), | ||||
|                ], | ||||
|         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_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) | ||||
|  | ||||
| @ -1730,6 +1730,7 @@ class LNX_PT_RenderPathShadowsPanel(bpy.types.Panel): | ||||
|         col.prop(rpdat, 'rp_shadowmap_cube') | ||||
|         layout.prop(rpdat, 'rp_shadowmap_cascade') | ||||
|         layout.prop(rpdat, 'rp_shadowmap_cascades') | ||||
|         layout.prop(rpdat, 'rp_shadowmap_transparent') | ||||
|         col = layout.column() | ||||
|         col2 = col.column() | ||||
|         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' | ||||
|         col.prop(rpdat, 'lnx_voxelgi_shadows', text='Shadows') | ||||
|         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, 'rp_voxelgi_resolution') | ||||
|         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_refr') | ||||
|         col.prop(rpdat, 'lnx_voxelgi_shad') | ||||
|         col.prop(rpdat, 'lnx_voxelgi_env') | ||||
|         col.prop(rpdat, 'lnx_voxelgi_occ') | ||||
|         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_range') | ||||
|         #col.prop(rpdat, 'lnx_voxelgi_aperture') | ||||
| @ -1968,10 +1970,10 @@ class LNX_PT_RenderPathPostProcessPanel(bpy.types.Panel): | ||||
|         sub = col.column() | ||||
|         sub.enabled = rpdat.rp_ssgi != 'Off' | ||||
|         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_strength') | ||||
|         sub.prop(rpdat, 'lnx_ssgi_max_steps') | ||||
|         sub.prop(rpdat, 'lnx_ssgi_samples') | ||||
|         layout.separator() | ||||
|  | ||||
|         row = layout.row() | ||||
|  | ||||
| @ -207,6 +207,8 @@ project.addSources('Sources'); | ||||
|                 # get instantiated | ||||
|                 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)) | ||||
|         for i in range(0, len(import_traits)): | ||||
|             khafile.write("project.addParameter('" + import_traits[i] + "');\n") | ||||
| @ -625,32 +627,18 @@ def write_compiledglsl(defs, make_variants): | ||||
|  | ||||
|             idx_emission = 2 | ||||
|             idx_refraction = 2 | ||||
|              | ||||
|             if '_gbuffer2' in wrd.world_defs: | ||||
|                 f.write('#define GBUF_IDX_2 2\n') | ||||
|                 idx_emission += 1 | ||||
|                 idx_refraction += 1 | ||||
|                  | ||||
|             # Special case for WebGL with both TAA and SSRefraction | ||||
|             webgl_with_taa_refr = ('_kha_webgl' in wrd.world_defs and  | ||||
|                                  ('_SSRefraction' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs) and  | ||||
|                                  ('_TAA' in wrd.world_defs or '_SMAA' in wrd.world_defs)) | ||||
|              | ||||
|             if webgl_with_taa_refr: | ||||
|                 # WebGL needs refraction to come before emission for correct rendering | ||||
|                 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') | ||||
|             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) | ||||
| #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' | ||||
|             ) | ||||
|  | ||||
|         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( | ||||
| """const float ssaoRadius = """ + str(round(rpdat.lnx_ssgi_radius * 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") + """; | ||||
| """) | ||||
|  | ||||
|         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( | ||||
| """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 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 voxelgiAperture = """ + str(round(rpdat.lnx_voxelgi_aperture * 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': | ||||
|             f.write(""" | ||||
|  | ||||
		Reference in New Issue
	
	Block a user