GPGPU : first results
Here is a screenshot featuring cascaded image filters (fully defined inside a Cg fragment shader). Each filter can have any number of textures as input (typically one) and its output is done on one texture (but with some work, maybe I could get multiple output if needed). The only filter I have implemented so far is a generic convolution filter (with any possible kernel size and kernel values).
This seems to run pretty fast (25 fps with 5 filters applied at each frame) on my GeForce FX Go5200 (poor graphic card of my PowerBook 12″, with 64 MB VRAM).
Keep in mind that this framerate is achieved on a system, Mac OS X, that already makes an extensive use of the GPU !
Here is a sample Cg fragment shader that performs the sharpen filter above :
float4 ApplyKernel(
const float kernel[][],
const uniform samplerRECT texture,
const float2 sizeTexture,
const float2 position
) {
float4 result = float4(0.0,0.0,0.0,0.0);
const float2 kernelCenter = (float2(kernel.length,kernel[0].length)-float2(1,1))/2.0;
for (int i=0; i < kernel.length; i++) {
const float newPositionX = position.x + i - kernelCenter.x;
for (int j=0; j < kernel[0].length; j++) {
const float2 newPosition =
float2(
newPositionX,
position.y + j - kernelCenter.y
)
;
result +=
texRECT(
texture,
//(position+float2(i,j)-kernelCenter)
newPosition
) * kernel[i][j]
;
}
}
return result;
}
float4 ApplyLaplacian(
const uniform samplerRECT texture,
const float2 sizeTexture,
const float2 position
) {
const float norm = 6.8;
const float kernel[3][3] = {
{ -0.7/norm, -1.0/norm, -0.7/norm },
{ -1.0/norm, 6.8/norm, -1.0/norm },
{ -0.7/norm, -1.0/norm, -0.7/norm }
};
return ApplyKernel(
kernel,
//float2(1,1),
texture,
sizeTexture,
position
);
}
float4 ApplyGaussianBlur(
const uniform samplerRECT texture,
const float2 sizeTexture,
const float2 position
) {
const float norm = 16.0;
const float kernel[3][3] = {
{ 1.0/norm, 2.0/norm, 1.0/norm },
{ 2.0/norm, 4.0/norm, 2.0/norm },
{ 1.0/norm, 2.0/norm, 1.0/norm }
};
return ApplyKernel(
kernel,
//float2(1,1),
texture,
sizeTexture,
position
);
}
void fragmentMain(
in float2 texCoordIn : TEXCOORD0,
out float4 colorOut : COLOR,
uniform float intParameter1,
uniform float intParameter2,
uniform samplerRECT texture1,
uniform float2 sizeTexture1,
//uniform samplerRECT texture2,
uniform float2 sizeTexture2
) {
float4 original = texRECT(texture1, texCoordIn);
float4 result =
ApplyLaplacian
//ApplyGaussianBlur
(texture1, sizeTexture1, texCoordIn)
;
const float increaseFactor = intParameter1;
const float originalFactor = intParameter2;
colorOut = float4((
original * originalFactor +
increaseFactor * result
).rgb,1.0);
}