HLSL新手问题:如何在HLSL中使用多个通行证?
我试图移植下面的MATLAB代码在显卡上工作。
function diff_im = anisodiff2D(im, num_iter, delta_t, kappa, option)
im = double(im);
% PDE (partial differential equation) initial condition.
diff_im = im;
% Center pixel distances.
dx = 1;
dy = 1;
dd = sqrt(2);
% 2D convolution masks - finite differences.
hN = [0 1 0; 0 -1 0; 0 0 0];
hS = [0 0 0; 0 -1 0; 0 1 0];
hE = [0 0 0; 0 -1 1; 0 0 0];
hW = [0 0 0; 1 -1 0; 0 0 0];
hNE = [0 0 1; 0 -1 0; 0 0 0];
hSE = [0 0 0; 0 -1 0; 0 0 1];
hSW = [0 0 0; 0 -1 0; 1 0 0];
hNW = [1 0 0; 0 -1 0; 0 0 0];
% Anisotropic diffusion.
for t = 1:num_iter
% Finite differences. [imfilter(.,.,'conv') can be replaced by conv2(.,.,'same')]
nablaN = imfilter(diff_im,hN,'conv');
nablaS = imfilter(diff_im,hS,'conv');
nablaW = imfilter(diff_im,hW,'conv');
nablaE = imfilter(diff_im,hE,'conv');
nablaNE = imfilter(diff_im,hNE,'conv');
nablaSE = imfilter(diff_im,hSE,'conv');
nablaSW = imfilter(diff_im,hSW,'conv');
nablaNW = imfilter(diff_im,hNW,'conv');
% Diffusion function.
if option == 1
cN = exp(-(nablaN/kappa).^2);
cS = exp(-(nablaS/kappa).^2);
cW = exp(-(nablaW/kappa).^2);
cE = exp(-(nablaE/kappa).^2);
cNE = exp(-(nablaNE/kappa).^2);
cSE = exp(-(nablaSE/kappa).^2);
cSW = exp(-(nablaSW/kappa).^2);
cNW = exp(-(nablaNW/kappa).^2);
elseif option == 2
cN = 1./(1 + (nablaN/kappa).^2);
cS = 1./(1 + (nablaS/kappa).^2);
cW = 1./(1 + (nablaW/kappa).^2);
cE = 1./(1 + (nablaE/kappa).^2);
cNE = 1./(1 + (nablaNE/kappa).^2);
cSE = 1./(1 + (nablaSE/kappa).^2);
cSW = 1./(1 + (nablaSW/kappa).^2);
cNW = 1./(1 + (nablaNW/kappa).^2);
end
% Discrete PDE solution.
diff_im = diff_im + ...
delta_t*(...
(1/(dy^2))*cN.*nablaN + (1/(dy^2))*cS.*nablaS + ...
(1/(dx^2))*cW.*nablaW + (1/(dx^2))*cE.*nablaE + ...
(1/(dd^2))*cNE.*nablaNE + (1/(dd^2))*cSE.*nablaSE + ...
(1/(dd^2))*cSW.*nablaSW + (1/(dd^2))*cNW.*nablaNW);
% Iteration warning.
fprintf('\rIteration %d\n',t);
end
它的那一刻我有一个通工作:
texture2D Input0;
sampler2D Input0Sampler = sampler_state
{
Texture = <Input0>;
MinFilter = Point;
MagFilter = Point;
MipFilter = Point;
AddressU = Clamp;
AddressV = Clamp;
};
struct VertexShaderInput
{
float4 Position : POSITION0;
float2 TextureCoordinate : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 TextureCoordinate : TEXCOORD0;
};
struct PixelShaderOutput
{
// TODO: Optionally add/remove output indices to match GPUProcessor.numOutputs
float4 Index0 : COLOR0;
};
// input texture dimensions
static float w = 1920 - 8;
static float h = 1080 - 8;
static const float2 pixel = float2(1.0/w, 1.0/h);
static const float2 halfPixel = float2(pixel.x/2, pixel.y/2);
static const float3x3 hN =
{
0, 1, 0,
0, -1, 0,
0, 0, 0
};
static const float3x3 hS =
{
0, 0, 0,
0, -1, 0,
0, 1, 0
};
static const float3x3 hE =
{
0, 0, 0,
0, -1, 1,
0, 0, 0
};
static const float3x3 hW =
{
0, 0, 0,
1, -1, 0,
0, 0, 0
};
static const float3x3 hNE =
{
0, 0, 1,
0, -1, 0,
0, 0, 0
};
static const float3x3 hSE =
{
0, 0, 0,
0, -1, 0,
0, 0, 1
};
static const float3x3 hSW =
{
0, 0, 0,
0, -1, 0,
1, 0, 0
};
static const float3x3 hNW =
{
1, 0, 0,
0, -1, 0,
0, 0, 0
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput vsInput)
{
//VertexShaderOutput output;
//output.Position = vsInput.Position;
//output.TextureCoordinate = vsInput.TextureCoordinate;
VertexShaderOutput output;
vsInput.Position.x = vsInput.Position.x - 2*halfPixel.x;
vsInput.Position.y = vsInput.Position.y + 2*halfPixel.y;
output.Position = vsInput.Position;
output.TextureCoordinate = vsInput.TextureCoordinate ;
return output;
//return output;
}
float4 Convolution(VertexShaderOutput input, float3x3 kernel)
{
//PixelShaderOutput output;
float4 pixel = float4(0.0f, 0.0f, 0.0f, 0.0f);
for (int i = -1; i <= 1; ++i)
{
for (int j = -1; j <= 1; ++j)
{
pixel += kernel[i+1][j+1] * tex2D(Input0Sampler, input.TextureCoordinate + float2(i,j));
};
};
return pixel;
}
PixelShaderOutput PixelShaderFunction(VertexShaderOutput psInput)
{
PixelShaderOutput output;
output.Index0 = tex2D(Input0Sampler, psInput.TextureCoordinate);
float dx, dy, dd;
dx = 1; dy = 1; dd = pow(2, 0.5);
float delta_t = 1/7;
float4 nablaN = Convolution(psInput, hN);
float4 nablaS = Convolution(psInput, hS);
float4 nablaW = Convolution(psInput, hW);
float4 nablaE = Convolution(psInput, hE);
float4 nablaNE = Convolution(psInput, hNE);
float4 nablaSE = Convolution(psInput, hSE);
float4 nablaSW = Convolution(psInput, hSW);
float4 nablaNW = Convolution(psInput, hNW);
float4 cN = 1/pow(1 + (nablaN/40), 2);
float4 cS = 1/pow(1 + (nablaS/40), 2);
float4 cW = 1/pow(1 + (nablaW/40), 2);
float4 cE = 1/pow(1 + (nablaE/40), 2);
float4 cNE = 1/pow(1 + (nablaNE/40), 2);
float4 cSE = 1/pow(1 + (nablaSE/40), 2);
float4 cSW = 1/pow(1 + (nablaSW/40), 2);
float4 cNW = 1/pow(1 + (nablaNW/40), 2);
output.Index0 += delta_t *
(
mul(cN, nablaN) + mul(cS, nablaS) + mul(cW, nablaW) + mul(cE, nablaE) + (dd*dd)*(mul(cNE, nablaNE) + mul(cSE, nablaSE) + mul(cSW, nablaSW) + mul(cNW, nablaNW))
);
return output;
}
technique PeronaMalik
{
pass pass1
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
的问题是我需要应用这种技术几次succesively如MATLAB代码。 我是否应该使用多个通行证来执行此操作?
编辑
如果我决定使用C#CONTROLL的通过,那么我可以尝试:
byte[] theBytes = TemplateMatch.Bytes;
for (int iters = 0; iters < 3; iters++)
{
t.SetData<byte>(theBytes);
GraphicsDevice.SetRenderTarget(renOutput);
effect.Parameters["Input0"].SetValue(t);
quad.RenderFullScreenQuad(effect);
for (int i = 0; i < effect.Techniques.Count; i++)
{
for (int j = 0; j < effect.Techniques[i].Passes.Count; j++)
{
effect.Techniques[i].Passes[j].Apply();
}
}
GraphicsDevice.SetRenderTarget(null);
renOutput.GetData<float>(arrayOutput);
Buffer.BlockCopy(arrayOutput, 0, theBytes, 0, theBytes.Length);
}
但在第二次迭代,我得到一个错误
您可能当它在 GraphicsDevice上被主动设置时,不会在资源上调用SetData。在调用SetData之前从设备中取消设置。
on line t.SetData(theBytes);
编辑
我已经试过
byte[] theBytes = TemplateMatch.Bytes;
for (int iters = 0; iters < 3; iters++)
{
t.SetData<byte>(theBytes);
GraphicsDevice.SetRenderTarget(renOutput);
effect.Parameters["Input0"].SetValue(t);
quad.RenderFullScreenQuad(effect);
for (int i = 0; i < effect.Techniques.Count; i++)
{
for (int j = 0; j < effect.Techniques[i].Passes.Count; j++)
{
effect.Techniques[i].Passes[j].Apply();
}
}
GraphicsDevice.SetRenderTarget(null);
renOutput.GetData<float>(arrayOutput);
Buffer.BlockCopy(arrayOutput, 0, theBytes, 0, theBytes.Length);
GraphicsDevice.Textures[0] = null;
}
这似乎解决了运行时错误,但是这给了我同样的未过滤的图像!
编辑
,使其在freemat运行我修改了上面的MATLAB代码。我已经通过了代码,我发现问题与这样的行相关:cN = exp( - (nablaN/kappa)。^ 2); 在freemat版本中,这些不计算为零(而我的HLSL版本)。这让我怀疑问题与HLSL的精度问题有关,或者我如何处理图形卡上的浮点运算。
我现在相信我的图像没有被转化的原因就是与数字信号处理,而不是堆栈溢出更好DELT的问题。 – sav
如果有人对GraphicsDevice.Textures [0] = null有解释,我会接受这个答案。 – sav
我认为这是相关http://www.gamedev.net/topic/636388-float-precision-difference-between-hlsl-and-glsl/ – sav