Saturday, May 19, 2012

Dels in HLSL


Today I implemented some of the del operators in HLSL.

To make the sampling look nicer, use the following macro:

#define sample(sampler, position, offset) tex2D(sampler, position + offset * pixelSize)

Here is a listing of the resulting functions:
  1. // Finite Difference Form of the Gradient operator
  2. float3 Gradient(sampler field, float3 u, float3 du)
  3. {
  4. // Note: we multiply the denominator of each partial derivative by 2 because we sample at -1 and +1

  5. // Partial derivative df/dx
  6. float f100 = sample(field, u, float3(-1.0f, 0.0f, 0.0f));
  7. float f200 = sample(field, u, float3(1.0f, 0.0f, 0.0f));
  8. float fd00 = (f200 - f100) / (2.0f * du.x);

  9. // Partial derivative df/dy
  10. float f010 = sample(field, u, float3(0.0f, -1.0f, 0.0f));
  11. float f020 = sample(field, u, float3(0.0f, 1.0f, 0.0f));
  12. float f0d0 = (f020 - f010) / (2.0f * du.y);

  13. // Partial derivative df/dz
  14. float f001 = sample(field, u, float3(0.0f, 0.0f, -1.0f));
  15. float f002 = sample(field, u, float3(0.0f, 0.0f, 1.0f));
  16. float f00d = (f002 - f001) / (2.0f * du.z);

  17. return float3(fd00, f0d0, f00d);
  18. }
  1. // Finite Difference Form of the Divergence operator
  2. float Divergence(sampler field, float3 u, float3 du)
  3. {
  4. // Note: we multiply the denominator of each partial derivative by 2 because we sample at -1 and +1

  5. // Partial derivative dvx/dx
  6. float3 v100 = sample(field, u, float3(-1.0f, 0.0f, 0.0f));
  7. float3 v200 = sample(field, u, float3(1.0f, 0.0f, 0.0f));
  8. float vd00 = (v200.x - v100.x) / (2.0f * du.x);

  9. // Partial derivative dvy/dy
  10. float3 v010 = sample(field, u, float3(0.0f, -1.0f, 0.0f));
  11. float3 v020 = sample(field, u, float3(0.0f, 1.0f, 0.0f));
  12. float v0d0 = (v020.y - v010.y) / (2.0f * du.y);

  13. // Partial derivative dvz/dz
  14. float3 v001 = sample(field, u, float3(0.0f, 0.0f, -1.0f));
  15. float3 v002 = sample(field, u, float3(0.0f, 0.0f, 1.0f));
  16. float v00d = (v002.z - v001.z) / (2.0f * du.z);

  17. return vd00 + v0d0 + v00d;
  18. }
  1. // Finite Difference Form of the Laplace operator
  2. float Laplacian(sampler field, float3 u, float3 du)
  3. {
  4. // Partial derivative d2f/dx2
  5. float f100 = sample(field, u, float3(-1.0f, 0.0f, 0.0f));
  6. float f200 = sample(field, u, float3(0.0f, 0.0f, 0.0f));
  7. float f300 = sample(field, u, float3(1.0f, 0.0f, 0.0f));
  8. float fd00 = (f100 + f300 - 2.0f * f200) / (du.x * du.x);

  9. // Partial derivative d2f/dy2
  10. float f010 = sample(field, u, float3(0.0f, -1.0f, 0.0f));
  11. float f020 = sample(field, u, float3(0.0f, 0.0f, 0.0f));
  12. float f030 = sample(field, u, float3(0.0f, 1.0f, 0.0f));
  13. float f0d0 = (f010 + f030 - 2.0f * f020) / (du.y * du.y);

  14. // Partial derivative d2f/dz2
  15. float f001 = sample(field, u, float3(0.0f, 0.0f, -1.0f));
  16. float f002 = sample(field, u, float3(0.0f, 0.0f, 0.0f));
  17. float f003 = sample(field, u, float3(0.0f, 0.0f, 1.0f));
  18. float f00d = (f001 + f003 - 2.0f * f002) / (du.z * du.z);

  19. return fd00 + f0d0 + f00d;
  20. }

If you spot any errors feel free to let me know ;-)