2013-07-29 42 views
1

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的精度问题有关,或者我如何处理图形卡上的浮点运算。

+0

我现在相信我的图像没有被转化的原因就是与数字信号处理,而不是堆栈溢出更好DELT的问题。 – sav

+0

如果有人对GraphicsDevice.Textures [0] = null有解释,我会接受这个答案。 – sav

+0

我认为这是相关http://www.gamedev.net/topic/636388-float-precision-difference-between-hlsl-and-glsl/ – sav

回答

1

你正在申请关卡,但不画任何东西。

至少你应该有类似下面的代码:

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(); 
     quad.RenderFullScreenQuad(effect); 
    } 
} 
+0

我使用四边形来渲染图像。我的问题已被GraphicsDevice.Textures [0] = null修复;尽管我不确定为什么这会修复它。我也不确定它是否是解决问题的最佳方法。 – sav

+1

您无法从/在设备中设置纹理设置/设置数据 – Blau

相关问题