Tuesday, July 10, 2007

Raytracing e environment()

Usar a funcao gather() nao 'e a unica forma de conseguir uma reflexao
com blur , no manual do renderman vem um exemplo muito legal de como
usar o raytracing de outra forma , atraves da funcao environment().
environment() costuma ser usado para adicionar uma reflexao atraves
de um bitmap . mas o renderman aceita uma palavra reservada "raytracing"
com essa funcao .. repassar uma palavra reservada
para a funcao environment() forca o renderman a usar raytracing .

environment() tbm tem opcoes de samples, dir , maxdist , e no lugar de
angulo uma variacao para "blur" . nos meus testes environment() com raytracing
deu resultados mais rapidos e com melhor qualidade com um menor
numero de samples ..

segue um shader de teste :

/*----------------------------------------------------------------------------------------*/
surface envRayReflex (
float Kr = 1;
float samples = 1;
float blur = 0 ;
float maxdist = 1;
)
{
color Crefl ;

string envmap = "raytrace"; /* cria uma string para guardar a palavra reservada */


if (N.I <0){
normal Nn = normalize(N);
vector In = normalize(I);
vector reflDir = reflect(In,Nn);
Crefl = environment(envmap,reflDir,"samples",samples,"blur",blur,"maxdist",maxdist);

} else { /* pintar de preto onde nao tiver nada para fazer raytracing */
Crefl = 0;
}
Ci = Kr * Crefl;

Oi = 1;
}


/*-----------------------------------------------------------------------------------------*/


abaixo segue um exemplo com o mesmo setup do render anterior (64SAMPLES, 0.18
BLUR , MAXDIST 110)

a qualidade do blur 'e bem melhor com um render mais rapido
ainda nao sei exatamente porque fica tao mais rapido
ja que por debaixo dos panos pelo que eu entendi . o renderman
faz um gather() do mesmo modo .. bem ..



Raytracing e gather()

A funcao gather() produz um looping para capturar informacoes via raytracing , ele 'e usado para capturar informacoes do shader que o raio atinge a cada looping .. como ele tem uma emissao de multiplos raios em um certo angulo ele 'e ideal para produzir reflexoes com blur e outros truques com raytracing .

a sintaxe da funcao gather:
gather ( string category, point P, vector dir, float angle, float samples, ... ) {statements} [else {statements}]

a funcao gather envia um cone de raios(samples) a partir do ponto P para a direcao "dir"em um determinado angulo "angle" . O angulo dado em radianos 'e medido a partir de "dir" .quanto maior o cone mais blur nos dados ou cores capturados , a qualidade desse blur 'e calculado pelo valor de samples . Quando um raio atinge uma surface ele captura informacoes diversas que podem ser escolhidas entre as variaveis globais do renderman ou uma informacao customizada do shader, a cada looping ele acumula as informacoes sobre as superficies. Uma media total das informacoes desses loopings 'e feita fora do looping , e adicionado no resultado final do seu shader , como voce pode ver existem dois blocos de statements , o primeiro blocovai ser executado quando o raio atingir uma surface e o codigo no bloco do "else" vai ser executado quando nao for atingida nenhuma superficie , o parametro "maxdist" limita os raios em uma certa distancia excluindo objetos fora desse campo .. muito bom para
dar uma optimizada no desempenho do raytracing
abaixo segue o codigo usando gather() :

/*----------------------------------------------------------------------------------*/
surface gatherReflex(
float samples = 1;

float coneAngulo = 0;

float maxdist = 1
)
{
/* inicia as variaveis para a cptura de informacoessbre a superficie e a cor do reflexo */
color hitColor = 0;

vector In = normalize(I);

normal Nn = normalize(N);

normal Nf = faceforward(Nn, In);

float numhits = 0;
Ci = 0;

/* verifica o angulo da surface em relacao ao observador */
if(Nn.-In >= 0)
{
vector ReflexDir = reflect(In, Nn); /* acha a direcao do reflexo */

/* inicia o gathering com as informacoes adquiridas , "surface:ci" vai ser a informacao capturado pelo raio ao bater em uma surface e adicionada na variavel hitcolor */


gather("illuminance", P, ReflexDir,coneAngulo,samples,"maxdist", maxdist, "surface:Ci",
hitColor)

{ Ci += hitColor; /* adiciona a cor capturada em Ci */

numhits += 1; /* conta o numero de raios que atingiram uma surface */

} else { hitColor = 0 ; }

}


/* calcula a media das cores pelo raios atingidos assinalado em Ci */
Ci /= numhits;
Oi = 1;}
/*-------------------------------------------------------------------------------------*/


um teste com samples 64 cone angle 0.18 e distancia 110




Monday, July 09, 2007

trace() + etc..

segue um shader teste usando a trace() ambient() diffuse() specular()
o shader ainda nao me parece tao legal e tbm nao sei c a soma final das funcoes
esta feito do modo mais certo mas foi uma tentativa de juntar as funcoes

ai vai o shader :



surface mySurfReflex(
float Kspecular = .5 ;
float Kdifusse = .5 ;
float Kambiente = 1 ;
float Kroughness = .1;
float KReflex = 1 ;
color ambiente_color = 0 ;
color diffuse_color = .8 ;
color specular_color = .5 ;
)


{

/* cria variaveis para captura de informacoes sobre a superficie */
normal Nf;
vector V;
Nf = faceforward( normalize(N), I );
normal Nn = normalize(N);
vector In = normalize(I);
color Temp_reflex_color = 0 ;

/* inicializa os calculos difuse ambiente e especular e acha a direcao e cor da reflexao */
color Temp_ambiente_color = ambiente_color * Kambiente * ambient();
color Temp_diffuse_color = diffuse_color * Kdifusse * diffuse(Nf);
color Temp_specular_color = specular_color * Kspecular * specular(Nf,-In,Kroughness);

/* verifica o angulo entre a superficie e o observador */
if (Nn.-In >= 0) {
/* acha a direcao do reflexo entre a surface e o observador */
vector DirecaoReflex = reflect(Nn,In);
/*captura a cor do reflexo naquele ponto usando a funcao trace */
Temp_reflex_color = KReflex * trace(P, DirecaoReflex);
}

/* adiciona todas as informacoes achadas na cor final do shader*/
Oi = Os;
Ci = (Temp_ambiente_color + Temp_diffuse_color) + (Temp_specular_color + Temp_reflex_color);

/* premultiplica a cor final com a opacidade */
Ci *= Oi;

}





e uma imagem do shader aplicado :

Raytracing e a funcao Trace

trace() segundo o manual do renderman :P envia um raio a partir de um ponto em uma determinada direcao,e retorna a cor da superficie em que o raio atingio, que 'e determinada pelo shader da superficie atingida
uma coisa interessante da funcao shader 'e que quando voce assinala essa funcao dentro de uma variavel float ela vai retornar a distancia do ponto atingido ao inves da cor
para a funcao trace funcionar no seu RFM ou RAT voce precisar ligar o "RAYTRACING" no seu render globals

segue um exemplo de um shader com trace
uma simples bola com reflexo aplicado :


surface TraceReflex( ) {
/* captura as informacoes necessarias para o calculo da superficie */

normal NormalSurface = normalize(N);
vector Observador = normalize(I);
color TempColorReflex = 0;

/* verifica o angulo entre a superficie e o observador */

if (NormalSurface.Observador < 0) {

/* acha a direcao do reflexo entre a surface e o observador */
vector DirecaoReflex = reflect(NormalSurface,Observador);


/* captura a cor do reflexo naquele ponto usando a funcao trace */
TempColorReflex = trace(P, DirecaoReflex);

}
/* assinala a cor capturada pela funcao trace na cor final do objeto */

Ci = Os * TempColorReflex;
Oi = Os;
}




um exemplo do render :