DepthOfFieldCommon.bslinc 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. mixin DepthOfFieldCommon
  2. {
  3. code
  4. {
  5. cbuffer DepthOfFieldParams
  6. {
  7. float gFocalPlaneDistance; // Distance to the in-focus plane, in world units
  8. float gApertureSize; // In meters, e.g. 50mm = 0.05m
  9. float gFocalLength; // In meters, e.g. 75mm = 0.075m
  10. float gInFocusRange; // Region totally in focus, starting at the in-focus plane (0 for physically based)
  11. float gSensorSize; // Camera sensor size in mm (shorter side)
  12. float gImageSize; // View size in pixels (side corresponding to shorter sensor side)
  13. float gMaxBokehSize; // Maximum size of the Bokeh shape in pixels
  14. float gNearTransitionRegion; // Region before the in-focus plane used to transition from in-focus to out-of-focus (non-physically based)
  15. float gFarTransitionRegion; // Region after the in-focus region used to transition from in-focus to out-of-focus (non-physically based)
  16. };
  17. // Computes for how in-focus should an object at a specific distance be.
  18. // Returns 0 for in-focus, and 1 for out-of-focus
  19. float circleOfConfusionPhysical(float distance)
  20. {
  21. // Force a region after the in-focus plane to be completely in focus (non-physically based)
  22. [flatten]
  23. if(distance > gFocalPlaneDistance)
  24. distance = gFocalPlaneDistance + max(0, distance - gFocalPlaneDistance - gInFocusRange);
  25. // Note: Simplify this equation to reduce the number of operations. Terms can probably cancel out,
  26. // and some terms can probably be pre-calculated.
  27. float imagePlaneFocus = gFocalPlaneDistance * gFocalLength / (gFocalPlaneDistance - gFocalLength);
  28. float imagePlaneObject = distance * gFocalLength / (distance - gFocalLength);
  29. float cocInMeters = gApertureSize * abs(imagePlaneObject - imagePlaneFocus) / imagePlaneFocus;
  30. float cocInMM = cocInMeters * 1000.0f;
  31. float cocInPixels = gImageSize * (cocInMM / gSensorSize);
  32. return saturate(cocInPixels / gMaxBokehSize);
  33. }
  34. // Has the same purpose as circleOfConfusionPhysical, but uses the explictly set near, far and in-focus regions for determining
  35. // the circle of confusion, rather than using physically based camera parameters.
  36. float circleOfConfusionArtistic(float distance)
  37. {
  38. // Force a region after the in-focus plane to be completely in focus
  39. [flatten]
  40. if(distance > gFocalPlaneDistance)
  41. distance = gFocalPlaneDistance + max(0, distance - gFocalPlaneDistance - gInFocusRange);
  42. float transitionRegion = (distance < gFocalPlaneDistance) ? gNearTransitionRegion : gFarTransitionRegion;
  43. return saturate(abs(distance - gFocalPlaneDistance) / transitionRegion);
  44. }
  45. float2 computeLayerContributions(float depth)
  46. {
  47. float near = saturate((gFocalPlaneDistance - depth) / gNearTransitionRegion);
  48. float far = saturate((depth - gFocalPlaneDistance - gInFocusRange) / gFarTransitionRegion);
  49. return float2(near, far);
  50. }
  51. };
  52. };