Blender PT

Blender 3D, Modelação, Renderização, Arte tudo em Português

Você não está autenticado.

#1 2014-10-07 00:25:29

MPorces
Membro
Registado: 2014-09-11
Mensagens: 35

Malhas de Difracção - OSL shader

Nos últimos tempos, tenho andado a estudar as várias formas de iridescencia que vários materiais conseguem apresentar.

Um dos processos que provoca iridescencia são as malhas de difracção.

Casos como os hologramas das nossas notas de euro ou os reflexos coloridos dos CD's e DVD's, são bons exemplos deste fenómeno.

Como resultado, consegui criar este pequeno Shader OSL, que partilho aqui com a malta.

/*
 * Diffraction Grating Reflection
 *
 * by Miguel Porces
 * 2014
 *
 * random generator by Brecht
 *
 */



#include "stdosl.h"

void rng_seed(output int rng, int seed)
{
    int chash = seed;
    if (chash == 0) chash = 1;
    rng = chash * 891694213;
}

float rng_uniform(output int rng)
{
    float res = rng / float(2137483647) * 0.5 + 0.5;
    rng *= 891694213;
    return res;
}

float randomInterval(float minval, float maxval,point ipt)
{
    int rng;
    float f=0;
    float delta=maxval-minval;
    f = fmod(cellnoise(ipt*12345.0), 1.0);
    rng_seed(rng, int(f * 2137483647));

    return delta*rng_uniform(rng)+minval;
}

void rotateVector(output vector v, vector axis, float angle)
{
    float sf=0, cf=0;
    sincos(angle, sf, cf);
    v=(normalize(cross(axis,v))*sf)+(v*cf);
}


shader Diffraction
(
color Color=1.0,
float Distance=1200,
float Roughness=0.0,
float Rotation=0.0,
normal Normal = N,
normal Tangent = normal(0.0,0.0,0.0),
output closure color BRDF=reflection(N)
)

{
    float Rg=clamp(Roughness,0,1);
    
    /* setup Tangent direction */
    normal Tg=Tangent;
    if (Tangent==normal(0.0,0.0,0.0))
    {
        normal Zaxis=normal(0.0,0.0,1.0);
        Zaxis = transform("object", "world", Zaxis);
        Tg=normalize(cross(Zaxis,Normal));
    }
    rotateVector(Tg, Normal, Rotation*M_2PI);
    
    /* setup loop */
    color cl;
    BRDF=0;
    
    vector rht=cross(I,Normal);
    float dtr=dot(Tg,rht);
    float sTheta=length(rht) * dtr;
    
    float wave=randomInterval(380, 780,P);
    float wldst=wave/Distance;

    int ordmin=int(floor(Distance * (-1+sTheta)/wave));
    int ordmax=int(ceil(Distance * (1-sTheta)/wave));
 
    float orddif;
    
    orddif=abs(ordmax-ordmin-1);

    /* sample wavelenght */
    for(int order=ordmin; order<=ordmax;order++){
        if(order!=0){
            /* calculate angle */
            float wfac=order*wldst+sTheta;
            float angle= asin(wfac);


            /*  rotate normal  */
            normal NN=Normal;
            rotateVector(NN, Tg, angle);

            cl=wavelength_color(wave)*(Color)/orddif;

            if(Rg==0.0)
            {
                BRDF += (cl * reflection(NN));
            } else {
                BRDF += (cl * microfacet_beckmann(NN,Rg));
            }
        }
    }
}

Não é muito lógico de usar, porque os mecanismos que estão por trás desta iridescencia também não são muito do senso comum. Mas o shader está quase* 100% correcto a nível da óptica envolvida, e produz resultados interessantes.

Qualquer questão sobre o funcionamento do mesmo, terei todo o gosto de responder.

*-A função wavelenght() não dá um valor exacto da intensidade lumínica de cada frequência.. aparte disso, o shader está correcto. smile

Última edição por MPorces (2014-10-07 00:29:56)

Offline

Rodapé do site