Comment créer un filtre de filtre analogique analogique dans n'importe quel langage de pixel shading? (J'ai besoin d'au moins un algorithme de filtre ...)Comment créer un filtre de filtre analogique analogique dans n'importe quel langage de pixel shading?
1
A
Répondre
1
J'ai regardé le filtre de tampon dans Photoshop et il ressemble à un seuil et à un fort flou ajouté ensemble. J'ai utilisé le noyau HorizontalGaussianBlur trouvé Pixel Bender Basics Article on Devnet et j'ai juste ajouté un seuil bon marché. Voici comment mon noyau ressemble à:
<languageVersion : 1.0;>
kernel stamp
< namespace : "toMaterial";
vendor : "George Profenza";
version : 1;
description : "Attempt to simulate Photoshop Stamp Filter. Original blur code: http://www.adobe.com/devnet/flash/articles/pixel_bender_basics_05.html";
>
{
input image4 src;
output pixel4 dst;
parameter float threshold<
minValue: 0.0;
defaultValue:0.5;
maxValue:1.0;
>;
parameter int radius
<
minValue : 1;
maxValue : 6;
defaultValue : 6;
>;
void
evaluatePixel()
{
pixel4 center, band1, band2, band3, band4, band5, band6;
float2 pos = outCoord();
//Sample image in bands
if(radius > 5) {
pixel4 left = dst;
pixel4 right = dst;
left.x -= 6.0;
right.x += 6.0;
band6 = left+right;
}
if(radius > 4) {
pixel4 left = dst;
pixel4 right = dst;
left.x -= 5.0;
right.x += 5.0;
band5 = left+right;
}
if(radius > 3) {
pixel4 left = dst;
pixel4 right = dst;
left.x -= 4.0;
right.x += 4.0;
band4 = left+right;
}
if(radius > 2) {
pixel4 left = dst;
pixel4 right = dst;
left.x -= 3.0;
right.x += 3.0;
band3 = left+right;
}
if(radius > 1) {
pixel4 left = dst;
pixel4 right = dst;
left.x -= 2.0;
right.x += 2.0;
band2 = left+right;
}
pixel4 left = dst;
pixel4 right = dst;
left.x -= 1.0;
right.x += 1.0;
band1 = left+right;
dst = sampleNearest(src,pos);
//quick'n'dirty grayscale
dst.rgb = float3(dst.r + dst.g + dst.b) * 0.333333333;
//threshold
if(dst.r < threshold) dst.r = 0.0; else dst.r = 1.0;
if(dst.g < threshold) dst.g = 0.0; else dst.g = 1.0;
if(dst.b < threshold) dst.b = 0.0; else dst.b = 1.0;
center = dst;
//Apply weights and compute resulting pixel
if(radius == 6)
{
dst = (band6 + (band5 * 12.0) + (band4 * 66.0) + (band3 * 220.0) + (band2 * 495.0) + (band1 * 792.0) + (center * 924.0)) * 0.000244140625;//4096.0;
}
if(radius == 5)
{
dst = (band5 + (band4 * 10.0) + (band3 * 45.0) + (band2 * 120.0) + (band1 * 210.0) + (center * 252.0)) * 0.0009765625;//1024.0;
}
if(radius == 4)
{
dst = (band4 + (band3 * 8.0) + (band2 * 28.0) + (band1 * 56.0) + (center * 70.0)) * 0.00390625;//256.0;
}
if(radius == 3)
{
dst = (band3 + (band2 * 6.0) + (band1 * 15.0) + (center * 20.0)) * 0.015625;//64.0;
}
if(radius == 2)
{
dst = (band2 + (band1 * 4.0) + (center * 6.0)) * 0.0625;//16.0
}
if(radius == 1)
{
dst = (band1 + (center * 2.0)) * 0.25;//4.0
}
}
}
Ce qui est loin d'être parfait, il est ce que je pourrais pirater rapidement à cette heure. Cela devrait vous donner quelques idées cependant.
MISE À JOUR:
Voici une version mise à jour à l'aide en niveaux de gris approprié et le code flou gaussien est la plupart du temps de la Pixel Bender Guide.
<languageVersion : 1.0;>
kernel Stamp
< namespace : "gp";
vendor : "George Profenza";
version : 1;
description : "Attempt to do a filter similar to Photoshop's Stamp Filter, blur code mostly from the guide: http://www.adobe.com/go/pixelbender_devguide";
>
{
input image4 source;
output pixel4 result;
parameter int blur<
minValue:1;
defaultValue:3;
maxValue:8;
>;
parameter float threshold<
minValue:0.0;
maxValue:1.0;
defaultValue:0.5;
>;
void
evaluatePixel()
{
//blur
const float sigma = 2.0;
float c = 1.0/(sqrt(2.0 * 3.1415926535) * sigma);
float ec = 2.0 * sigma * sigma;
float weight0 = exp(-(0.0 * 0.0)/ec) * c;
float weight1 = exp(-(1.0 * 1.0)/ec) * c;
if(blur > 1) float weight2 = exp(-(2.0 * 2.0)/ec) * c;
if(blur > 2) float weight3 = exp(-(3.0 * 3.0)/ec) * c;
if(blur > 3) float weight4 = exp(-(4.0 * 4.0)/ec) * c;
if(blur > 4) float weight5 = exp(-(5.0 * 5.0)/ec) * c;
if(blur > 5) float weight6 = exp(-(6.0 * 6.0)/ec) * c;
if(blur > 6) float weight7 = exp(-(7.0 * 7.0)/ec) * c;
if(blur > 7) float weight8 = exp(-(8.0 * 7.0)/ec) * c;
float4 acc = float4(0.0);
acc += sampleNearest(source, outCoord()) * weight0;
acc += sampleNearest(source, outCoord() + float2(1.0, 0.0)) * weight1;
acc += sampleNearest(source, outCoord() + float2(-1.0, 0.0)) * weight1;
if(blur > 1) {
acc += sampleNearest(source, outCoord() + float2(2.0, 0.0)) * weight2;
acc += sampleNearest(source, outCoord() + float2(-2.0, 0.0)) * weight2;
}
if(blur > 2) {
acc += sampleNearest(source, outCoord() + float2(3.0, 0.0)) * weight3;
acc += sampleNearest(source, outCoord() + float2(-3.0, 0.0)) * weight3;
}
if(blur > 3) {
acc += sampleNearest(source, outCoord() + float2(4.0, 0.0)) * weight4;
acc += sampleNearest(source, outCoord() + float2(-4.0, 0.0)) * weight4;
}
if(blur > 4) {
acc += sampleNearest(source, outCoord() + float2(5.0, 0.0)) * weight5;
acc += sampleNearest(source, outCoord() + float2(-5.0, 0.0)) * weight5;
}
if(blur > 5) {
acc += sampleNearest(source, outCoord() + float2(6.0, 0.0)) * weight6;
acc += sampleNearest(source, outCoord() + float2(-6.0, 0.0)) * weight6;
}
if(blur > 6) {
acc += sampleNearest(source, outCoord() + float2(7.0, 0.0)) * weight7;
acc += sampleNearest(source, outCoord() + float2(-7.0, 0.0)) * weight7;
}
if(blur > 7) {
acc += sampleNearest(source, outCoord() + float2(8.0, 0.0)) * weight8;
acc += sampleNearest(source, outCoord() + float2(-8.0, 0.0)) * weight8;
}
//grayscale
float luma = 0.299 * acc.r + 0.587 * acc.g + 0.114 * acc.b;
acc = float4(luma,luma,luma,1.0);
//threshold
if(acc.r < threshold) acc.r = 0.0; else acc.r = 1.0;
if(acc.g < threshold) acc.g = 0.0; else acc.g = 1.0;
if(acc.b < threshold) acc.b = 0.0; else acc.b = 1.0;
result = acc;
}
}
Note: I a appliqué le seuil après le flou, de sorte que le résultat est pas exactement un filtre de timbre, mais à proximité.
HTH, George