#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Transform.gdshaderinc" float getDepth( sampler2D _depthTexture, vec2 screenUV ) { return textureLod( _depthTexture, screenUV, 0.0 ).r; } vec3 getDepthViewPositiontAtScreen( sampler2D _depthTexture, vec2 screenUV, mat4 _INV_PROJECTION_MATRIX ) { float depthValue = getDepth( _depthTexture, screenUV ); return screenToView( screenUV, depthValue, _INV_PROJECTION_MATRIX ).xyz; } bool isVisibleAt( sampler2D _depthTexture, vec3 viewPosition, mat4 _PROJECTION_MATRIX, mat4 _INV_PROJECTION_MATRIX ) { vec2 screenPosition = viewToScreen( viewPosition, _PROJECTION_MATRIX ); vec3 depthViewPosition = getDepthViewPositiontAtScreen( _depthTexture, screenPosition, _INV_PROJECTION_MATRIX ); float visible = viewPosition.z - depthViewPosition.z; return visible > 0.0; } bool isInFrontOf( sampler2D _depthTexture, vec3 viewPosition, vec2 screenPosition, mat4 _INV_PROJECTION_MATRIX ) { vec3 depthViewPosition = getDepthViewPositiontAtScreen( _depthTexture, screenPosition, _INV_PROJECTION_MATRIX ); float visible = viewPosition.z - depthViewPosition.z; return visible > 0.0; } bool isInFrontOfDepth( sampler2D _depthTexture, float testDepth, vec2 screenPosition ) { float screenDepth = getDepth( _depthTexture, screenPosition ); float visible = testDepth - screenDepth; return visible > 0.0; } float getQuickOcclusionAt( sampler2D _depthTexture, vec3 viewPosition, vec2 uvPixelSize, int maxSteps, float stride, mat4 _PROJECTION_MATRIX, mat4 _INV_PROJECTION_MATRIX ) { vec4 clipPosition = viewToClip( viewPosition, _PROJECTION_MATRIX ); vec2 screenPosition = clipToScreen( clipPosition ); float depth = clipPosition.z; bool isOccludedAtCenter = ! isInFrontOfDepth( _depthTexture, depth, screenPosition ); if ( isOccludedAtCenter ) { return 0.0; } float offsetPerLevel = 1.0 / ( float( maxSteps ) + 1.0 ); float h2 = pow( 2.0, 0.5 ) / 2.0; vec2[] offsets = { // vec2( -h2, -h2 ), vec2( 0.0, -1.0 ), // vec2( h2, -h2 ), vec2( -1.0, 0.0 ), vec2( 1.0, 0.0 ), // vec2( -h2, h2 ), vec2( 0.0, 1.0 ) // vec2( h2, h2 ) }; int angles = 4; for ( int i = 0; i < maxSteps; i++ ) { float occluded = 0.0; vec2 rayScale = ( 1.0 + float( i ) ) * uvPixelSize * stride; for ( int j = 0; j < angles; j++ ) { vec2 rayOffset = offsets[ j ] * rayScale; vec2 uvTestPosition = screenPosition + rayOffset; bool stepVisible = isInFrontOfDepth( _depthTexture, depth, uvTestPosition ); occluded += stepVisible ? 0.0 : 1.0; } if ( occluded > 0.0 ) { float occludedSteps = occluded / float( angles ); float levelOffset = ( float( i ) + 2.0 ) * offsetPerLevel; return levelOffset - occludedSteps * offsetPerLevel; } } return 1.0; } float getOcclusionAt( sampler2D _depthTexture, vec3 viewPosition, vec2 uvPixelSize, int maxSteps, float stride, mat4 _PROJECTION_MATRIX, mat4 _INV_PROJECTION_MATRIX ) { vec4 clipPosition = viewToClip( viewPosition, _PROJECTION_MATRIX ); vec2 screenPosition = clipToScreen( clipPosition ); float depth = clipPosition.z; float maxOcclusion = 2.0 + float( maxSteps ) * 8.0; float occlusion = 0.0; bool centerVisible = isInFrontOfDepth( _depthTexture, depth, screenPosition ); if ( centerVisible ) { occlusion += 2.0; } float h2 = pow( 2.0, 0.5 ) / 2.0; vec2[] offsets = { vec2( -h2, -h2 ), vec2( 0.0, -1.0 ), vec2( h2, -h2 ), vec2( -1.0, 0.0 ), vec2( 1.0, 0.0 ), vec2( -h2, h2 ), vec2( 0.0, 1.0 ), vec2( h2, h2 ) }; for ( int i = 0; i < maxSteps; i++ ) { vec2 rayScale = ( 1.0 + float( i ) ) * uvPixelSize * stride; for ( int j = 0; j < 8; j++ ) { vec2 rayOffset = offsets[ j ] * rayScale; vec2 uvTestPosition = screenPosition + rayOffset; bool stepVisible = isInFrontOfDepth( _depthTexture, depth, uvTestPosition ); if ( stepVisible ) { occlusion += 1.0; } } } return occlusion / maxOcclusion; }