Fix T54278: volume artifacts with small density and color after recent changes.
[blender-staging.git] / intern / cycles / kernel / geom / geom_volume.h
index 963d6cbee9c61f254068b00fed60867e9ecf3606..a4e47384b25cbda9cf1fe43cceb0fd539720ef22 100644 (file)
@@ -11,7 +11,7 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
 
 /* Volume Primitive
@@ -29,44 +29,52 @@ CCL_NAMESPACE_BEGIN
 
 /* Return position normalized to 0..1 in mesh bounds */
 
-ccl_device float3 volume_normalized_position(KernelGlobals *kg, const ShaderData *sd, float3 P)
+ccl_device_inline float3 volume_normalized_position(KernelGlobals *kg,
+                                                    const ShaderData *sd,
+                                                    float3 P)
 {
        /* todo: optimize this so it's just a single matrix multiplication when
         * possible (not motion blur), or perhaps even just translation + scale */
-       AttributeElement attr_elem;
-       int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM, &attr_elem);
+       const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM);
 
        object_inverse_position_transform(kg, sd, &P);
 
-       if(attr_offset != ATTR_STD_NOT_FOUND) {
-               Transform tfm = primitive_attribute_matrix(kg, sd, attr_offset);
+       if(desc.offset != ATTR_STD_NOT_FOUND) {
+               Transform tfm = primitive_attribute_matrix(kg, sd, desc);
                P = transform_point(&tfm, P);
        }
 
        return P;
 }
 
-ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int id, float *dx, float *dy)
+ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
 {
        float3 P = volume_normalized_position(kg, sd, sd->P);
-       float4 r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z);
+       InterpolationType interp = (sd->flag & SD_VOLUME_CUBIC)? INTERPOLATION_CUBIC: INTERPOLATION_NONE;
+       float4 r = kernel_tex_image_interp_3d(kg, desc.offset, P.x, P.y, P.z, interp);
 
        if(dx) *dx = 0.0f;
-       if(dx) *dy = 0.0f;
+       if(dy) *dy = 0.0f;
 
-       /* todo: support float textures to lower memory usage for single floats */
        return average(float4_to_float3(r));
 }
 
-ccl_device float3 volume_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int id, float3 *dx, float3 *dy)
+ccl_device float3 volume_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy)
 {
        float3 P = volume_normalized_position(kg, sd, sd->P);
-       float4 r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z);
+       InterpolationType interp = (sd->flag & SD_VOLUME_CUBIC)? INTERPOLATION_CUBIC: INTERPOLATION_NONE;
+       float4 r = kernel_tex_image_interp_3d(kg, desc.offset, P.x, P.y, P.z, interp);
 
        if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
        if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
 
-       return float4_to_float3(r);
+       if(r.w > 1e-8f && r.w != 1.0f) {
+               /* For RGBA colors, unpremultiply after interpolation. */
+               return float4_to_float3(r) / r.w;
+       }
+       else {
+               return float4_to_float3(r);
+       }
 }
 
 #endif