| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 |
- mixin DepthOfFieldCommon
- {
- code
- {
- cbuffer DepthOfFieldParams
- {
- float gFocalPlaneDistance; // Distance to the in-focus plane, in world units
- float gApertureSize; // In meters, e.g. 50mm = 0.05m
- float gFocalLength; // In meters, e.g. 75mm = 0.075m
- float gInFocusRange; // Region totally in focus, starting at the in-focus plane (0 for physically based)
- float gSensorSize; // Camera sensor size in mm (shorter side)
- float gImageSize; // View size in pixels (side corresponding to shorter sensor side)
- float gMaxBokehSize; // Maximum size of the Bokeh shape in pixels
- float gNearTransitionRegion; // Region before the in-focus plane used to transition from in-focus to out-of-focus (non-physically based)
- float gFarTransitionRegion; // Region after the in-focus region used to transition from in-focus to out-of-focus (non-physically based)
- };
- // Computes for how in-focus should an object at a specific distance be.
- // Returns 0 for in-focus, and 1 for out-of-focus
- float circleOfConfusionPhysical(float distance)
- {
- // Force a region after the in-focus plane to be completely in focus (non-physically based)
- [flatten]
- if(distance > gFocalPlaneDistance)
- distance = gFocalPlaneDistance + max(0, distance - gFocalPlaneDistance - gInFocusRange);
-
- // Note: Simplify this equation to reduce the number of operations. Terms can probably cancel out,
- // and some terms can probably be pre-calculated.
- float imagePlaneFocus = gFocalPlaneDistance * gFocalLength / (gFocalPlaneDistance - gFocalLength);
- float imagePlaneObject = distance * gFocalLength / (distance - gFocalLength);
-
- float cocInMeters = gApertureSize * abs(imagePlaneObject - imagePlaneFocus) / imagePlaneFocus;
- float cocInMM = cocInMeters * 1000.0f;
- float cocInPixels = gImageSize * (cocInMM / gSensorSize);
-
- return saturate(cocInPixels / gMaxBokehSize);
- }
-
- // Has the same purpose as circleOfConfusionPhysical, but uses the explictly set near, far and in-focus regions for determining
- // the circle of confusion, rather than using physically based camera parameters.
- float circleOfConfusionArtistic(float distance)
- {
- // Force a region after the in-focus plane to be completely in focus
- [flatten]
- if(distance > gFocalPlaneDistance)
- distance = gFocalPlaneDistance + max(0, distance - gFocalPlaneDistance - gInFocusRange);
-
- float transitionRegion = (distance < gFocalPlaneDistance) ? gNearTransitionRegion : gFarTransitionRegion;
- return saturate(abs(distance - gFocalPlaneDistance) / transitionRegion);
- }
-
- float2 computeLayerContributions(float depth)
- {
- float near = saturate((gFocalPlaneDistance - depth) / gNearTransitionRegion);
- float far = saturate((depth - gFocalPlaneDistance - gInFocusRange) / gFarTransitionRegion);
- return float2(near, far);
- }
- };
- };
|