Commits

Frederic De Groef  committed 3be0638

new crytek impl

  • Participants
  • Parent commits 5ca4d8e

Comments (0)

Files changed (4)

File media/ssao/crytek/crytek_ssao.cg

     ,uniform float far
     ,uniform sampler2D geomMap : TEXUNIT0
 	,uniform sampler2D randMap : TEXUNIT1
-	,uniform float4 viewportSize
-    ,uniform float nearDistance
-	,uniform float farDistance
-	,uniform float sampleInScreenSpace
-	,uniform float sampleLengthScreenSpace
+	,uniform float4 cViewportSize
+    ,uniform float nearClipDistance
+	,uniform float farClipDistance
+    ,uniform float cFov
+	,uniform float cSampleInScreenSpace // whether to sample in screen or world space
+	,uniform float cSampleLengthScreenSpace // The sample length in screen space [0, 1]
+	,uniform float cSampleLengthWorldSpace // the sample length in world space in units
+	,uniform float cOffsetScale // [0, 1] The distance of the first sample. samples are the 
+								// placed in [cOffsetScale * cSampleLengthScreenSpace, cSampleLengthScreenSpace]
+	,uniform float cDefaultAccessibility // the default value used in the lerp() expression for invalid samples [0, 1]
+	,uniform float cEdgeHighlight // multiplicator for edge highlighting in [1, 2] 1 is full hightlighting 2 is off
     ,out float4 oColor)
 {
 
-    float4 sample = tex2D(geomMap, IN.pixelPos);
-    float z = sample.r;
-    
-    float3 P = float3(IN.pixelPos, z);
-    
-    float2 samples[8] = {
-        float2(1.0, 0.0),
-        float2(0.707106, 0.707106),
-        float2(0, 1.0),
-        float2(-0.707106, 0.707106),
-        float2(-1.0, 0),
-        float2(-0.707106, -0.707106),
-        float2(0, -1.0),
-        float2(0.707106, -0.707106)        
-    };
-    
+	const int nSampleNum = 32; // number of samples
 
-    int count = 0;	
-	float ao = 0.0f;
-   
-	const int num_samples =8;       
+	// compute the distance between the clipping planes to convert [0, 1] depth to world space units
+	const float clipDepth = farClipDistance - nearClipDistance;
 
-    for (int i=0 ; i<num_samples ; i++)
-    {
-        float x, y;
-         
-        float2 coords = samples[i];
-        
-        float2 neighbour_coords = IN.pixelPos + coords*0.003;
-        float sampled_depth = tex2D(geomMap,  neighbour_coords).r;
-        float3 Q = float3(neighbour_coords, sampled_depth);
-         
-        float len = length(P-Q);
-        
-        if(sampled_depth < z)
-        {
-            count += 1;
-			ao += 1.0 / (1.0 + (len*len));
-			//ao += len;	
-        }
-    }
+	// get the depth of the current pixel and convert into world space unit [0, inf]
+	float fragmentWorldDepth = tex2D(geomMap, IN.pixelPos).r * clipDepth;
 
-	ao /= (num_samples);
+	// get rotation vector, rotation is tiled every 4 screen pixels
+	float2 rotationTC = IN.pixelPos * cViewportSize.xy / 4;
+	float3 rotationVector = 2 * tex2D(randMap, rotationTC).xyz - 1; // [-1, 1]x[-1. 1]x[-1. 1]
+	
+	float rUV = 0; // radius of influence in screen space
+	float r = 0; // radius of influence in world space
+	if (cSampleInScreenSpace == 1)
+	{
+		rUV = cSampleLengthScreenSpace;
+		r = tan(rUV * cFov) * fragmentWorldDepth;
+	}
+	else
+	{
+		rUV = atan(cSampleLengthWorldSpace / fragmentWorldDepth) / cFov; // the radius of influence projected into screen space
+		r = cSampleLengthWorldSpace;
+	}
 
-	ao = 1.0-ao;	
+	float sampleLength = cOffsetScale; // the offset for the first sample
+	const float sampleLengthStep = pow((rUV / sampleLength), 1.0f/nSampleNum);
+	
+	float accessibility = 0;
 
-	//if(count >=4)
-		//oColor = float4(0, 0, 0, 1);
-	//else
-		//oColor = float4(ao, ao, ao, 1);
-//
-	oColor = float4(ao, ao, ao, 1);	
+
+	float3 sphereVectors[8] = {
+		float3(-1, -1, -1),
+		float3(-1, -1, 1),
+		float3(-1, 1, -1),
+		float3(-1, 1, 1),
+		float3(1, -1, -1),
+		float3(1, -1, 1),
+		float3(1, 1, -1),
+		float3(1, 1, 1)
+	};
+
+
+	// sample the sphere and accumulate acessability
+	for (int i = 0; i < (nSampleNum/8); i++)
+	{
+			//generate offset vector
+			float3 offset = normalize(sphereVectors[i]) * sampleLength;
+			
+			// update sample length
+			sampleLength *= sampleLengthStep;
+		
+			// reflect offset vector by random rotation sample (i.e. rotating it) 
+			float3 rotatedOffset = reflect(offset, rotationVector);
+					
+			float2 sampleTC = IN.pixelPos + rotatedOffset.xy * rUV;
+				
+			// read scene depth at sampling point and convert into world space units (m or whatever)
+			float sampleWorldDepth = tex2D(geomMap, sampleTC).r * clipDepth;
+			//float sampleWorldDepth = 0.005f * clipDepth;			
+
+			// check if depths of both pixles are close enough and sampling point should affect our center pixel
+			float fRangeIsInvalid = saturate((fragmentWorldDepth - sampleWorldDepth) / r);
+			
+			// accumulate accessibility, use default value of 0.5 if right computations are not possible
+			accessibility += lerp(sampleWorldDepth > (fragmentWorldDepth + rotatedOffset.z * r), cDefaultAccessibility, fRangeIsInvalid);
+
+			//accessibility += abs(sampleWorldDepth - fragmentWorldDepth);
+
+//			accessibility += (sampleWorldDepth > (fragmentWorldDepth + rotatedOffset.z * r)) + (fRangeIsInvalid);
+//			accessibility += fRangeIsInvalid;
+
+	}
+	
+	// get average value
+	accessibility /= nSampleNum;
+
+	// normalize, remove edge hightlighting
+	accessibility *= cEdgeHighlight;
+	
+	// amplify and saturate if necessary
+	oColor = float4(accessibility.xxx, 1);
+
+
+
 
 }

File media/ssao/crytek/crytek_ssao.material

 
       fragment_program_ref crytek_ssao_ps
       {
-		param_named_auto viewportSize viewport_size
-		param_named_auto farDistance far_clip_distance
-		param_named_auto nearDistance near_clip_distance
-		param_named_auto cFov fov
+		param_named_auto	cViewportSize		viewport_size
+		param_named_auto	farClipDistance		far_clip_distance
+		param_named_auto	nearClipDistance	near_clip_distance
+		param_named_auto	cFov				fov
+
+		param_named		cSampleInScreenSpace		float 1
+		param_named		cSampleLengthScreenSpace	float 0.06
+		param_named		cSampleLengthWorldSpace		float 2.0
+		param_named		cOffsetScale				float 0.01
+		param_named		cDefaultAccessibility		float 0.5
+		param_named		cEdgeHighlight				float 2	
+
       }
 
       texture_unit geomMap

File media/ssao/diffuse_gbuffer.cg

     OUT.color.gba = normalize(n);
 		        
     float clipDistance = cFarClipDistance - cNearClipDistance;
-    OUT.color.r = (length(p.z) - cNearClipDistance) / clipDistance; // norm to [0, 1]        
-    
+    OUT.color.r = (length(p.z) - cNearClipDistance) / clipDistance; // norm to [0, 1]        
 
     return OUT;
 }

File ogre-ssao/OgreApplication.cpp

     // get the vertex shader parameters
     Ogre::GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters();
     // set the camera's far-top-right corner
-    if (params->_findNamedConstantDefinition("farCorner"))
-        params->setNamedConstant("farCorner", farCorner);
+    //if (params->_findNamedConstantDefinition("farCorner"))
+    //    params->setNamedConstant("farCorner", farCorner);
     //else
     //    OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS
     //    , "Could not find parameter <farCorner> for vertex shader <"+pass->getVertexProgramName()+">in material <" + mat->getName()+">"
         0,      0,    0,    1);
 
   
-    if (params->_findNamedConstantDefinition("clip_to_image_matrix"))
+ /*   if (params->_findNamedConstantDefinition("clip_to_image_matrix"))
         params->setNamedConstant("clip_to_image_matrix", CLIP_SPACE_TO_IMAGE_SPACE * cam->getProjectionMatrixWithRSDepth());
-    //else
+ */   //else
     //    OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS
     //               , "Could not find parameter 'clip_to_image_matrix' in material " + mat->getName()
     //               , "Ogre::Application::notifyMaterialRenderer()");
                             
 
     float farDistance = cam->getFarClipDistance();
-    if (params->_findNamedConstantDefinition("farDistance"))    
-        params->setNamedConstant("farDistance", farDistance);
+    //if (params->_findNamedConstantDefinition("farDistance"))    
+    //    params->setNamedConstant("farDistance", farDistance);
    //else
    //     OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS
    //                , "Could not find parameter <farDistance> for fragment shader <"+pass->getFragmentProgramName()+"> in material <" + mat->getName()+">"
 
 
 
-    mOgreAppLog->logMessage(Ogre::StringConverter::toString(mCamera->getProjectionMatrix()));
+  /*  mOgreAppLog->logMessage(Ogre::StringConverter::toString(mCamera->getProjectionMatrix()));
     mOgreAppLog->logMessage(Ogre::StringConverter::toString(mCamera->getViewMatrix()));
-    mOgreAppLog->logMessage("-----------------");
+    mOgreAppLog->logMessage("-----------------");*/
 
 }