Cycles Volume Render: support for rendering of homogeneous volume with absorption.
[blender.git] / intern / cycles / kernel / kernel_volume.h
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16
17 CCL_NAMESPACE_BEGIN
18
19 /* Volume shader properties
20  *
21  * extinction coefficient = absorption coefficient + scattering coefficient
22  * sigma_t = sigma_a + sigma_s */
23
24 ccl_device float3 volume_shader_get_extinction_coefficient(ShaderData *sd)
25 {
26         float3 sigma_t = make_float3(0.0f, 0.0f, 0.0f);
27
28         for(int i = 0; i < sd->num_closure; i++) {
29                 const ShaderClosure *sc = &sd->closure[i];
30
31                 if(CLOSURE_IS_VOLUME(sc->type))
32                         sigma_t += sc->weight;
33         }
34
35         return sigma_t;
36 }
37
38 ccl_device float3 volume_shader_get_scattering_coefficient(ShaderData *sd)
39 {
40         float3 sigma_s = make_float3(0.0f, 0.0f, 0.0f);
41
42         for(int i = 0; i < sd->num_closure; i++) {
43                 const ShaderClosure *sc = &sd->closure[i];
44
45                 if(CLOSURE_IS_VOLUME(sc->type) && sc->type != CLOSURE_VOLUME_ABSORPTION_ID)
46                         sigma_s += sc->weight;
47         }
48
49         return sigma_s;
50 }
51
52 ccl_device float3 volume_shader_get_absorption_coefficient(ShaderData *sd)
53 {
54         float3 sigma_a = make_float3(0.0f, 0.0f, 0.0f);
55
56         for(int i = 0; i < sd->num_closure; i++) {
57                 const ShaderClosure *sc = &sd->closure[i];
58
59                 if(sc->type == CLOSURE_VOLUME_ABSORPTION_ID)
60                         sigma_a += sc->weight;
61         }
62
63         return sigma_a;
64 }
65
66 /* evaluate shader to get extinction coefficient at P */
67 ccl_device float3 volume_extinction_sample(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx, float3 P)
68 {
69         sd->P = P;
70
71         shader_eval_volume(kg, sd, 0.0f, path_flag, ctx);
72
73         return volume_shader_get_extinction_coefficient(sd);
74 }
75
76 ccl_device float3 volume_color_attenuation(float3 sigma, float t)
77 {
78         return make_float3(expf(-sigma.x * t), expf(-sigma.y * t), expf(-sigma.z * t));
79 }
80
81 /* Volumetric Shadows */
82
83 /* get the volume attenuation over line segment defined by segment_ray, with the
84  * assumption that there are surfaces blocking light between the endpoints */
85 ccl_device float3 kernel_volume_get_shadow_attenuation(KernelGlobals *kg, PathState *state, Ray *segment_ray, int shader)
86 {
87         ShaderData sd;
88         shader_setup_from_volume(kg, &sd, segment_ray, shader, state->bounce);
89
90         /* do we have a volume shader? */
91         if(!(sd.flag & SD_HAS_VOLUME))
92                 return make_float3(1.0f, 1.0f, 1.0f);
93
94         /* single shader evaluation at the start */
95         ShaderContext ctx = SHADER_CONTEXT_SHADOW;
96         int path_flag = PATH_RAY_SHADOW;
97         float3 attenuation;
98
99         //if(sd.flag & SD_HOMOGENEOUS_VOLUME) {
100                 /* homogenous volume: assume shader evaluation at the starts gives
101                  * the extinction coefficient for the entire line segment */
102
103                 /* todo: could this use sigma_t_cache? */
104                 float3 sigma_t = volume_extinction_sample(kg, &sd, path_flag, ctx, segment_ray->P);
105
106                 attenuation = volume_color_attenuation(sigma_t, segment_ray->t);
107         //}
108
109         return attenuation;
110 }
111
112 /* Volume Stack */
113
114 /* todo: this assumes no overlapping volumes, needs to become a stack */
115 ccl_device void kernel_volume_enter_exit(KernelGlobals *kg, ShaderData *sd, int *volume_shader)
116 {
117         if(sd->flag & SD_BACKFACING)
118                 *volume_shader = kernel_data.background.volume_shader;
119         else
120                 *volume_shader = (sd->flag & SD_HAS_VOLUME)? sd->shader: SHADER_NO_ID;
121 }
122
123 CCL_NAMESPACE_END
124