next up previous
Seguinte: Integradores Acima: Análise da Radiância em Anterior: Forma Integral

Processo de Dispersão Volumétrica

Há três importantes processos que afetam a distribuição da radiância em um ambiente com meio participativo: absorção, emissão e dispersão. Agora as características de estes processos são homogêneos e não homogêneos. Processos homogêneos: são constantes no espaço. Processos não homogêneos: podem variar em todas partes do espaço.

Observações.

  1. A função caminho de absorção ou transmissão tem as seguintes propriedades
  2. Lei de Beer
    Em um meio homogeneo $ \sigma$ é constante. Logo temos
    $ T(r\rightarrow r')= e^{-\sigma \Vert r' - r \Vert}$

  3. A função fase $ p$ é normalizada tal que

    $ \dfrac{1}{4\pi}\int_{\mathbb{S}^2}p_r(\omega\cdot\omega')d\omega' = 1$

    Agora lembremos que

    $ p_r(\omega\cdot\omega') =
4\pi\dfrac{k(r,\omega\cdot\omega')}{\sigma_s(r)}$

    Esta expresão tem uma vantagem de separar as noçes de probabilidade de colisão por unidade de comprimento e o resultado é uma distribuição de direções.
    A função fase frequentemente só depende do ângulo, $ \theta$, entre o raio de chegada $ \omega$ ao ponto de disperão $ r$, e raio de de dispersão $ \omega'$.
    Podemos escrever como $ p_r(\theta)$ onde
    $ \theta = 0$ é o (dispersão para frente) e
    $ \theta = \pi$ é $ backward$ (dispersão para atrais) [3].
    A forma como as funções fase podem ser caracterizadas é por o número

    $ g(r) =
\dfrac{1}{4\pi}\int_{\mathbb{S}^2}p_r(\omega\cdot\omega')cos\theta'd\omega'$

    é chamado de parametro $ anisotropico$ [2] ou $ antisemetrico$ [4] e varia entre 1 e -1, e 0 para disperperção isotropica.
    Alem o valor é sera positivo para dispersão para frente (forward scattering) e negativo para dispersão para atrais (backward scattering) [4].

    3.1 Função de Fase isotropica
    Descreve igual dispersão em todas as direções, ie, é independiente de qualquer dos sentidos.
    Porque as funções fase são normalizadas, existe soamente uma de tais funções

    Todas as outras funções fase são .

    3.2 Função fase de Rayleigh:
    descreve a dispersão de muitas e pequenas partículas (como as partículas da atmosfera). Se as partículas tem radio menor que o comprimento de onda da luz $ \lambda$, $ (\dfrac{r}{\lambda}<0.05)$, o modelo descreve con precisão a distribuição da dispersão da luz.
    A dependencia do comprimento de onda é a razão do que ceu é azul e os raios do por do sol vermelhos. E é

    $ p_r(x)=\dfrac{3}{4}(1 + x^2).\,\,\,\,\,\cite{Arvo}$



    3.3 Função fase de Mie:
    A teoria é derivada das equações de Maxwell, e podem descrever a dispersão de um rango amplo de tamano de partículas.
    É um bom modelo para dispersão na atmosfera devido as gotas de agua e bruma.

    3.4 Função fase mais usada é Henyey e Greenstein
    É usada para descrever dispersão em oceanos, nuvens, pele, pedra e mais, é

    $ p_r(\theta) = \dfrac{1 - g^2}{4\pi(1 + g^2 +
2gcos\theta)^{\frac{3}{2}}}$

    onde $ g$ é o parametro asimetrico (anisotropico).
    Blasi, e Schlick (1993) desenvolvieram uma aproximação eficiente à função de Henyey-Greenstein. Esta aproximação evita a função cara de powf()

Relação do Volume.

A abstração chave para descrever a dispersão volumétrica no pbrt [4] é a classe VolumeRegion. Todo VolumeRegion pode calcular sua caixa limitada com eixos alinhados ao espaço mundo. Este limite pode ser usado para calcular VolumeRegion em estruturas de aceleração.
Porque os VolumeIntegrators necessitam saber a escala paramétrica de um raio do espaço mundo que passa através de una região do volume, um VolumeRegion::IntersectP() separado do método retorna a escala paramétrica.

$ \langle VolumeRegion\ Interface \rangle= $

00035 virtual bool IntersectP(const Ray &ray, float *t0,
00036         float *t1) const = 0;

Dado um ponto e um sentido do espaço mundo, VolumeRegion::sigma_a(), VolumeRegion::sigma_s(), e VolumeRegion::sigma_ $ \sf {L}_{\sf {ve}}$() retornam a absorção, a dispersão e as propriedades correspondentes da emissão e o método VolumeRegion::p() retorna o valor da função fase em um ponto dado.


VolumeRegion::sigma_t() retorna o coeficiente de atenuação $ \sigma_t (= \sigma_a + \sigma_s)$ mas a maioria das execuções do VolumeRegion cancelarão esta suma e calcularão $ \sigma _t$ diretamente.

$ \langle VolumeRegion\ Interface \rangle= $

00037 virtual Spectrum sigma_a(const Point &,
00038      const Vector &) const = 0;
00039 virtual Spectrum sigma_s(const Point &,
00040      const Vector &) const = 0;
00041 virtual
00042      Spectrum Lve(const Point &, const Vector &) const = 0;
00043 virtual float p(const Point &, const Vector &,
00044      const Vector &) const = 0;
00045 virtual Spectrum sigma_t(const Point &,const Vector &) const;
00046 virtual Spectrum Tau(const Ray &ray,
00047      float step = 1.f, float offset = 0.5) const = 0;

O método VolumeRegion::Tau() calcula a espessura óptica do volume, entre dois pontos ray(ray.mint) e ray(ray.maxt).

$ \langle VolumeRegion\ Interface \rangle$

00046 virtual Spectrum Tau(const Ray &ray,
00047         float step = 1.f, float offset = 0.5) const = 0;



Volume Homogêneo

É a representação mais simples do volume. HomogeneousVolume descreve uma região box-shaped do espaço com propriedade de dispersão homogêneas. Os valores para $ \sigma_a$, $ \sigma_s$, o valor de $ g$ da função fase e a quantidade de emissão $ L_{ve}$ são passadas ao construtor.

O construtor inicializa as variáveis do membro copiando os parametros correspondentes.

$ \langle HomogeneousVolume\ Private\ Data\rangle=$

00057         Spectrum sig_a, sig_s, le;
00058         float g;
00059         BBox extent;
00060         Transform WorldToVolume;

Porque $ \sigma_a$ e $ \sigma_s$ são constantes em todas partes do volume, a espessura óptica que de um raio pode ser calculada usando a lei de Beer.

$ \langle HomogeneousVolume\ Public\ Methods\rangle=$

00050 Spectrum Tau(const Ray &ray, float, float) const {
00051         float t0, t1;
00052         if (!IntersectP(ray, &t0, &t1)) return 0.;
00053         return Distance(ray(t0), ray(t1)) * (sig_a + sig_s);


Volumes com densidade variada.

Suponhamos que as partículas tem as mesmas características de dispersão, mas sua densidade espacial varia no meio. Uma consequência desta suposição é que é possível descrever as propriedades de dispersão volumétrica em um ponto como produto da densidade nesse ponto e algum valor de dispersão.

Exemplo.
Seja $ \sigma _t$ o coeficiente de atenuação fixo, $ \sigma_t = 0.2$. Logo em regiões onde a densidade da partícula foi 1, então o valor de $ \sigma _t$ será 0.2. Agora se a densidade é 3, então o valor de $ \sigma _t$ será 0.6.

Definimos a classe DensityRegion que fornecera um novo método para obter a densidade da partícula em um ponto.

O construtor DensityRegion toma os valores básicos das propriedades de dispersão e as armazena nas variáveis correspondentes.

$ \langle DensityRegion\ Protected\ Data \rangle=$

00074         Transform WorldToVolume;
00075         Spectrum sig_a, sig_s, le;
00076         float g;

$ \langle Volume\ Scattering\ Definitions \rangle$

00048 DensityRegion::DensityRegion(const Spectrum &sa,
00049                 const Spectrum &ss, float gg,
00050                 const Spectrum &emit,
00051                 const Transform &VolumeToWorld)
00052         : sig_a(sa), sig_s(ss), le(emit), g(gg)  {
00053         WorldToVolume = VolumeToWorld.GetInverse();

O método de DensityRegion::Density, retorna a densidade do volume no ponto dado no espaço do objeto.
A densidade deve ser não negativa em toda parte porque é usada para medir os parametros básicos de dispersão.

$ \langle DensityRegion\ Public\ Methods\rangle= $

 00054 virtual float Density(const Point &Pobj) const = 0;

O método de DensityRegion::sigma_a() ilustra como DensityRegion trabalha.
DensityRegion::sigma_a() leva em conta a densidade local no ponto.

$ \langle DensityRegion\ Public\ Methods\rangle= $

00055 Spectrum sigma_a(const Point &p, const Vector &) const {
00056        return Density(WorldToVolume(p)) * sig_a;


Uma excepção é DensityRegion::p() o método não calcula o valor da função de fase pela densidade local. A quantidade de dispersão em um ponto estão já no valor de $ \sigma_s$.

$ \langle DensityRegion\ Public\ Methods\rangle= $

00067 float p(const Point &p, const Vector &w,
00068                 const Vector &wp) const {
00069         return PhaseHG(w, wp, g);


3D Grade

A classe VolumeGrid armazena densidades em uma grade 3D de posições. Estas amostras são interpoladas para calcular os valores de densidades. VolumeGrid é uma subclasse de DensityRegion. O construtor toma os valores de $ \sigma_a$, $ \sigma_s$,$ L_{ve}$ e $ g$. Armazena uma caixa limitada do espaço do objeto para a região, e faz uma copia local dos valores de densidade. A implemtação do VolumeGrid esta em volumes/volumegrid.cpp no pbrt [4].

$ \langle VolumeGrid \ Method \ Definitions \rangle =$

00040 VolumeGrid::VolumeGrid(const Spectrum &sa,
00041                 const Spectrum &ss, float gg,
00042                 const Spectrum &emit, const BBox &e,
00043                 const Transform &v2w,
00044                 int x, int y, int z, const float *d)
00045         : DensityRegion(sa, ss, gg, emit, v2w),
00046         nx(x), ny(y), nz(z), extent(e) {
00047         density = new float[nx*ny*nz];
00048         memcpy(density, d, nx*ny*nz*sizeof(float));
00049 }

$ \langle VolumeGrid \ Private \ Data\rangle= $

00035         float *density;
00036         const int nx, ny, nz;
00037         const BBox extent;

A tarefa do método de Density() do VolumeGrid é usar as amostras para reconstruir a função de densidade do volume no ponto dado.

$ \langle VolumeGrid \ Method \ Definitions \rangle =$

00050 float VolumeGrid::Density(const Point &Pobj) const {
00051         if (!extent.Inside(Pobj)) return 0;
$ \langle Compute\ voxel \ coordinates\ and\ offsets\ for \ \_Pobj\_
\rangle$
$ \langle Trilinearly\ interpolate\ density\ values\ to\ compute\
local\ density\rangle$

Dado os oito valores da amostra que cercam um ponto em 3D, este método interpola trilinearmente para calcular os valores da função densidade no ponto. Começa encontrando a amostra mais próxima do volume cujas coordenadas do interior são todas são menos do que posição da amostra e usam então as distancias de Manhattan ao longo de cada linha central, (dx,dy, e dz).

$ \langle Compute\ voxel \ coordinates\ and\ offsets\ for \ \_Pobj\_
\rangle =$

00053         float voxx = (Pobj.x - extent.pMin.x) /
00054                 (extent.pMax.x - extent.pMin.x) * nx - .5f;
00055         float voxy = (Pobj.y - extent.pMin.y) /
00056                 (extent.pMax.y - extent.pMin.y) * ny - .5f;
00057         float voxz = (Pobj.z - extent.pMin.z) /
00058                 (extent.pMax.z - extent.pMin.z) * nz - .5f;
00059         int vx = Floor2Int(voxx);
00060         int vy = Floor2Int(voxy);
00061         int vz = Floor2Int(voxz);
00062         float dx = voxx - vx, dy = voxy - vy, dz = voxz - vz;

Estas distancias podem ser usadas diretamente em uma serie de chamadas de lerp() para estimar a densidade em um ponto da amostra.

$ \langle Trilinearly\ interpolate\ density\ values\ to\ compute\
local\ density\rangle =$

00064 float d00 = Lerp(dx, D(vx, vy, vz),     D(vx+1, vy, vz));
00065 float d10 = Lerp(dx, D(vx, vy+1, vz),  D(vx+1, vy+1, vz));
00066 float d01 = Lerp(dx, D(vx, vy, vz+1),  D(vx+1, vy, vz+1));
00067 float d11 = Lerp(dx, D(vx, vy+1, vz+1),D(vx+1, vy+1, vz+1));
00068 float d0 = Lerp(dy, d00, d10);
00069 float d1 = Lerp(dy, d01, d11);
00070 return Lerp(dz, d0, d1);

O método D() retorna a densidade na posição dada da amostra.

$ \langle VolumeGrid \ Public \ Methods \rangle =$

00027         float D(int x, int y, int z) const {
00028                 x = Clamp(x, 0, nx-1);
00029                 y = Clamp(y, 0, ny-1);
00030                 z = Clamp(z, 0, nz-1);
00031                 return density[z*nx*ny + y*nx + x];



Densidade exponencial

A clase ExponentialDensity, que descreve uma densidade que varia como uma função exponencial da altura $ h$ dentro de uma região 3D dada:

$ d(h)=ae^{-bh}$

Os valores de $ a$ e de $ b$ são os parametros que controlam a densidade total e como rapidamente tem uma queda em função da altura, respectivamente.
Esta função da densidade é um modelo bom para a atmosfera visto da superfície da Terra, onde a curvatura da atmosfera pode generalmente ser omitida (Ebert et al 2003). Pode também ser usada para modelar névoa baixa encontrando se com o nível da Terra. E é definido em volumes/exponential.cpp no pbrt [4].

$ \langle ExponentialDensity\ Declarations \rangle$

00014 class ExponentialDensity : public DensityRegion {
00015 public:
00016
$ \langle ExponentialDensity\ Public\ Methods \rangle$
00035 private:
00036
$ \langle ExponentialDensity\ Private\ Data\rangle$


O construtor de ExponentialDensity inicializa suas variáveis do membro diretamente de seus argumentos. Além as propriedades de dispersão volumétrica passam ao construtor de DensityRegion, também a fronteira do volume, e os valores dos parametros de e de $ b$. Este construtor toma um vetor dado na direção ``acima'' que orienta o volume e é usado para calcular a altura de pontos para o calculo da densidade. Agora o sentido ascendente não é estritamente necessário, mas especificar um vetor para ``acima'' explicito pode ser mais fácil de entender.

$ \langle ExponentialDensity\ Public\ Methods \rangle =$

00017 ExponentialDensity(const Spectrum &sa, const Spectrum &ss,
00018                 float gg, const Spectrum &emit, const BBox &e,
00019                 const Transform &v2w, float aa, float bb,
00020                 const Vector &up)
00021         : DensityRegion(sa, ss, gg, emit, v2w),
00022           extent(e), a(aa), b(bb) {
00023         upDir = Normalize(up);
00024 }

00037         BBox extent;
00038         float a, b;
00039         Vector upDir;

Para a classe ExponecialDensity é necessário encontrar uma projeção perpendicular de um ponto sobre o vetor direção acima $ u$ e determinar a distancia ao longo de $ u$ do ponto de projeção. A distancia esta dada por o produto ponto $ (u\cdot v)$ onde $ v$ é o vetor esquina na caixa (e o vetor direção começa ali).

$ \langle ExponentialDensity\ Public\ Methods \rangle =$

00030 float Density(const Point &Pobj) const {
00031           if (!extent.Inside(Pobj)) return 0;
00032           float height = Dot(Pobj - extent.pMin, upDir);
00033           return a * expf(-b * height);
00034  }




next up previous
Seguinte: Integradores Acima: Análise da Radiância em Anterior: Forma Integral
Dalia Melissa Bonilla Correa 2006-09-08