// original sources found at Game Developer Magazine March 2008 #include "HLSL_SM4Support.hlsl" SAMPLER2D(sNormal, 0); // xyz normal + depth [0, 1] SAMPLER2D(sPosition, 1); // view space position SAMPLER2D(sRandom, 1); // random texture sampler void CreaseShading_fp ( in float4 position : POSITION, in float2 uv : TEXCOORD0, out float4 oColor0 : COLOR0, uniform const float cRange, // the three(four) artistic parameters uniform const float cBias, uniform const float cAverager, uniform const float cMinimumCrease, uniform const float cKernelSize, // Bias for the kernel size, Hack for the fixed size 11x11 stipple kernel uniform const float4 cViewportSize // (width, height, 1/width, 1/height) ) { // get the view space position and normal of the fragment const float3 fragmentPosition = tex2D(sPosition, uv).xyz; const float3 fragmentNormal = tex2D(sNormal, uv).xyz; float totalGI = 0.0f; // a diamond shaped (45deg rotated square) stipple pattern around (0, 0) this will be used as offset for the samples // O // O O // O O O // O O O O // O O X O O // O O O O // O O O // O O // O // the algorith starts with the leftmost element and walks the diagonal to the topmost element // a stippleSize of n yields (((n - 1) / 2)^2) - 1 samples // the 'image' above has a stipple size of 11 'cuz it has 5 samples (minus // the current fragment position and 4 gaps = 11. const int stippleSize = 11; // must be odd for (int i = 0; i < (stippleSize + 1) / 2; i++) { float2 diagonalStart = float2(-(stippleSize - 1) / 2, 0) + i; for(int j = 0; j < (stippleSize + 1) / 2; j++) { float2 sampleOffset = diagonalStart + float2(j, -j); float2 sampleUV = uv + (sampleOffset * cViewportSize.zw * cKernelSize); float3 samplePos = tex2D(sPosition, sampleUV).xyz; float3 toCenter = samplePos - fragmentPosition; float distance = length(toCenter); toCenter = normalize(toCenter); float centerContrib = saturate((dot(toCenter, fragmentNormal) - cMinimumCrease) * cBias); float rangeAttenuation = 1.0f - saturate(distance / cRange); totalGI += centerContrib * rangeAttenuation; } } totalGI /= cAverager; oColor0 = 1 - float4(totalGI.xxx, 1); }