Photon Mapper
Publicado por Rafael 27/10/2008
[ Hits: 5.609 ]
Homepage: nenhum
Photon mapping em uma cena simples. A técnica de photon mapping foi desenvolvida por Henrik W. Jensen(http://graphics.ucsd.edu/~henrik/). Este algoritmo é no código de Grant Schindler 2007.
http://www.cc.gatech.edu/~phlosoft/
Para compilar use: gcc -o cornel cornel.c -lglut
/* * Copyright (C) 2008, 2008 Rafael Siqueira Telles Vieira * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * License: http://www.lia.ufc.br/~rafaelstv/licenca_GPL_pt.txt * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * */ #include <stdio.h> #include <math.h> #include <stdlib.h> #include <time.h> #include <GL/glut.h> /** Cenario **/ int tamImagem = 400; // lagura e alturas int nrTipos = 2; // tipos de objetos int nrObjetos[] = {2,5}; // 2 esferas, 5 planos float gOrigem[] = {0.0f,0.0f,0.0f}; float Luz[] = {0.0,1.2,3.75}; float esferas[][4] = {{1.0,0.0,4.0,0.5},{-0.6,1.0,4.5,0.5}}; // centro e raio float planos[][2] = {{0, 1.5},{1, -1.5},{0, -1.5},{1, 1.5},{2,5.0}}; // eixo e distancia para origem /** Globais do Photon Mapping **/ int nrPhotons = 1000; int nrQuiques = 3; float sqRadius = 0.70; float exposicao = 50.0; int numPhotons[][5] = {{0,0},{0,0,0,0,0}}; float photons[2][5][5000][3][3]; /** Globais do Raytracing **/ int gIntercepta = 0; int gTipo; int gId; float gQdDist, gDist = -1.0; float gPonto[] = {0.0, 0.0, 0.0}; /** Operações com Vetores **/ #define PROD_ESCALAR(vetor1, vetor2)\ ((vetor1[0]*vetor2[0]) + (vetor1[1]*vetor2[1]) + (vetor1[2]*vetor2[2])) #define MULT_ESCALAR(vetorS,vetorE, escalar)\ vetorS[0] = vetorE[0] * escalar;\ vetorS[1] = vetorE[1] * escalar;\ vetorS[2] = vetorE[2] * escalar; #define MULTIPLICA(resultado, vetor1, vetor2)\ resultado[0] = vetor1[0] * vetor2[0];\ resultado[1] = vetor1[1] * vetor2[1];\ resultado[2] = vetor1[2] * vetor2[2]; #define SUBTRAI(resultado, vetor1, vetor2)\ resultado[0] = vetor1[0] - vetor2[0];\ resultado[1] = vetor1[1] - vetor2[1];\ resultado[2] = vetor1[2] - vetor2[2]; #define SOMA(resultado, vetor1, vetor2)\ resultado[0] = vetor1[0] + vetor2[0];\ resultado[1] = vetor1[1] + vetor2[1];\ resultado[2] = vetor1[2] + vetor2[2]; void RAND3(float vetor[]) { double random; random = -1.0 + ((double)rand()/(double)RAND_MAX)*2.0f; vetor[0] = random; random = -1.0 + ((double)rand()/(double)RAND_MAX)*2.0f; vetor[1] = random; random = -1.0 + ((double)rand()/(double)RAND_MAX)*2.0f; vetor[2] = random; } void NORMALIZA(float vetor[]) { float valor = sqrt(PROD_ESCALAR(vetor,vetor)); vetor[0]/= valor; vetor[1]/= valor; vetor[2]/= valor; } int dentroRAIO(float a[], float b[], float sqraio) { float c; float d = 0.0f; c = a[0] - b[0]; d += c*c; if (d > sqraio) return 0; c = a[1] - b[1]; d += c*c; if (d > sqraio) return 0; c = a[2] - b[2]; d += c*c; if (d > sqraio) return 0; gQdDist = d; return 1; } /** Intersecoes **/ void verificaDistancia(float Dist, int tipo, int id) { if (Dist < gDist && Dist > 0.0) { gTipo = tipo; gDist = Dist; gId = id; gIntercepta = 1; } } void raioEsfera(int id, float direcao[], float origem[]) { float t[3]={0.0,0.0,0.0}; float raio = esferas[id][3]; SUBTRAI(t,esferas[id],origem); float A = PROD_ESCALAR(direcao,direcao); float B = -2.0f*PROD_ESCALAR(direcao,t); float C = PROD_ESCALAR(t,t) - (raio*raio); float D = B*B - 4*A*C; if (D > 0.0) { float sinal = (C < -0.0001) ? 1: -1; float Dist1 = (-B + sinal*sqrt(D))/(2*A); verificaDistancia(Dist1,0,id); } } void raioPlano(int id, float direcao[], float origem[]) { int eixo = (int) planos[id][0]; if (direcao[eixo] != 0.0) { float Dist = (planos[id][1] - origem[eixo]) / direcao[eixo]; verificaDistancia(Dist,1,id); } } void raioObjeto(int tipo, int id, float direcao[], float origem[]) { if (tipo == 0) raioEsfera(id,direcao,origem); else raioPlano(id,direcao,origem); } /** Normal **/ void esferaNormal(float normal[], int id, float P[]) { SUBTRAI(normal,P,esferas[id]); NORMALIZA(normal); } void planoNormal(float normal[], int id, float P[], float origem[]) { int eixo = (int) planos[id][0]; normal[0] = 0.0; normal[1] = 0.0; normal[2] = 0.0; normal[eixo] = origem[eixo] - planos[id][1]; NORMALIZA(normal); } void superficieNormal(float normal[], int tipo, int id, float P[], float dentro[]) { if (tipo == 0) esferaNormal(normal,id,P); else planoNormal(normal,id,P,dentro); } /** Raytracing **/ void tracarRaio(float raio[], float origem []) { int t,i; gIntercepta = 0; gDist = 9999.9; for (t=0; t<nrTipos;t++) for (i=0; i<nrObjetos[t];i++) raioObjeto(t,i,raio,origem); } void reflita(float rRefletido[], float rIncidente[], float pontoPartida[]) { float normal[3]={0.0,0.0,0.0}; float resultado[3]={0.0,0.0,0.0}; superficieNormal(normal,gTipo,gId,gPonto,pontoPartida); MULT_ESCALAR(resultado,normal,PROD_ESCALAR(normal,rIncidente)*2.0); SUBTRAI(rRefletido,rIncidente,resultado); NORMALIZA(rRefletido); } /** Photon Mapping **/ void armazenaPhoton(int tipo, int id, float localizacao[], float direcao[], float energia[]) { photons[tipo][id][numPhotons[tipo][id]][0][0] = localizacao[0]; photons[tipo][id][numPhotons[tipo][id]][0][1] = localizacao[1]; photons[tipo][id][numPhotons[tipo][id]][0][2] = localizacao[2]; photons[tipo][id][numPhotons[tipo][id]][1][0] = direcao[0]; photons[tipo][id][numPhotons[tipo][id]][1][1] = direcao[1]; photons[tipo][id][numPhotons[tipo][id]][1][2] = direcao[2]; photons[tipo][id][numPhotons[tipo][id]][2][0] = energia[0]; photons[tipo][id][numPhotons[tipo][id]][2][1] = energia[1]; photons[tipo][id][numPhotons[tipo][id]][2][2] = energia[2]; numPhotons[tipo][id]++; } void filtreCor(float corS[], float corE[], float r, float g, float b) { int c; corS[0] = r; corS[1] = g; corS[2] = b; for (c = 0; c < 3; c++) if (corS[c] > corE[c]) corS[c] = corE[c]; } void retCor(float corS[], float corE[], int tipo, int id) { if (tipo == 1 && id == 0) { filtreCor(corS, corE, 0.0, 1.0, 0.0); } else if (tipo == 1 && id == 2) { filtreCor(corS, corE, 1.0, 0.0, 0.0); } else { filtreCor(corS, corE, 1.0, 1.0, 1.0); } } void reunaPhotons(float cor[], float p[], int tipo, int id) { int i; cor[0] = 0.0; cor[1] = 0.0; cor[2] = 0.0; float N[3]; float resultado[3]; superficieNormal(N,tipo,id,p,gOrigem); for (i = 0; i < numPhotons[tipo][id]; i++) { if (dentroRAIO(p,photons[tipo][id][i][0],sqRadius)) { float max = PROD_ESCALAR(N,photons[tipo][id][i][1])*-1.0f; if (max < 0.0f) max = 0.0f; max *= ((1.0 - sqrt(gQdDist))/exposicao); resultado[0] = 0.0f; resultado[1] = 0.0f; resultado[2] = 0.0f; MULT_ESCALAR(resultado,photons[tipo][id][i][2],max); SOMA(cor, cor, resultado); } } } void shadowPhoton(float raio[]) { float shadow[] = {-0.25,-0.25,-0.25}; float ponto[] = {gPonto[0], gPonto[1], gPonto[2]}; int tipo = gTipo, id = gId, dist = gDist; float pontoMovido[3]={0.0,0.0,0.0},resultado[3]={0.0,0.0,0.0}; MULT_ESCALAR(resultado,raio,0.001); SOMA(pontoMovido,resultado,gPonto); tracarRaio(raio,pontoMovido); float pontoSombra[3]={0.0,0.0,0.0}; resultado[0] = 0.0f; resultado[1] = 0.0f; resultado[2] = 0.0f; MULT_ESCALAR(resultado,raio,gDist); SOMA(pontoSombra, resultado,pontoMovido); armazenaPhoton(gTipo,gId,pontoSombra,raio,shadow); gPonto[0]=ponto[0]; gPonto[1]=ponto[1]; gPonto[2]=ponto[2]; gTipo = tipo; gId = id; gDist = dist; } /** colorir **/ void computeCorPixel(float cor[], float x, float y) { float raio[3] = {(x/tamImagem)-0.5, -((y/tamImagem)-0.5),1.0}; int tipo; int id; tracarRaio(raio,gOrigem); if (gIntercepta) { MULT_ESCALAR(gPonto,raio,gDist); if (gTipo == 0 && gId == 1) { float refletido[3]={0.0f,0.0f,0.0f}; reflita(refletido,raio,gOrigem); tracarRaio(refletido,gPonto); if (gIntercepta) { float resultado[3]={0.0f,0.0f,0.0f}; MULT_ESCALAR(resultado,refletido,gDist); SOMA(gPonto,resultado,gPonto); } } reunaPhotons(cor,gPonto,gTipo,gId); } } void emitaPhotons() { int i,t; srand(time(0)); for (t = 0; t<nrTipos; t++) for (i=0;i<nrObjetos[t];i++) numPhotons[t][i] = 0; for (i=0;i<nrPhotons;i++) { int quiques = 1; float cor[] = {1.0,1.0,1.0}; float raio[3]; RAND3(raio); NORMALIZA(raio); float pontoAnt[] = { Luz[0], Luz[1], Luz[2] }; while (pontoAnt[1] >= Luz[1]) { float resultado[3]; RAND3(resultado); NORMALIZA(resultado); MULT_ESCALAR(resultado,resultado,0.75); SOMA(pontoAnt,Luz,resultado); } if (abs(pontoAnt[0]) > 1.5 || (abs(pontoAnt[1]) > 1.2) || dentroRAIO(pontoAnt, esferas[0],esferas[0][3]*esferas[0][3])) quiques = nrQuiques + 1; tracarRaio(raio,pontoAnt); float resultado[3]; while (gIntercepta && quiques <= nrQuiques) { resultado[0] = 0.0f; resultado[1] = 0.0f; resultado[2] = 0.0f; MULT_ESCALAR(resultado,raio,gDist); SOMA(gPonto,resultado,pontoAnt); retCor(cor,cor,gTipo,gId); MULT_ESCALAR(cor,cor,1.0/sqrt(quiques)); armazenaPhoton(gTipo,gId,gPonto,raio,cor); shadowPhoton(raio); float raioR[3]; reflita(raioR, raio, pontoAnt); tracarRaio(raioR,gPonto); pontoAnt[0] = gPonto[0]; pontoAnt[1] = gPonto[1]; pontoAnt[2] = gPonto[2]; quiques++; } } } void Inicia() { emitaPhotons(); } /** OpenGL **/ void desenha(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0,tamImagem,0,tamImagem); glClearColor(1.0f,1.0f,1.0f,1.0f); glClear(GL_COLOR_BUFFER_BIT); int x,y; float cor[3]; for (x=0;x<tamImagem;x++) for (y=0;y<tamImagem;y++) { cor[0]=0.0f; cor[1]=0.0f; cor[2]=0.0f; computeCorPixel(cor,x,y); glRasterPos2f(x,y); glDrawPixels(1,1,GL_RGB,GL_FLOAT,cor); } glFlush; } int main(int argc, char** argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(tamImagem,tamImagem); glutInitWindowPosition(0,0); glutCreateWindow("Photon Mapping"); glutDisplayFunc(desenha); Inicia(); glutMainLoop(); return 0; }
Controle de tráfego aéreo - filas dinâmicas
Método eficiente de armazenamento utilizando containers (Vector e Map)
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Como renomear arquivos de letras maiúsculas para minúsculas
Imprimindo no formato livreto no Linux
Vim - incrementando números em substituição
Efeito "livro" em arquivos PDF
Como resolver o erro no CUPS: Unable to get list of printer drivers
SysAdmin ou DevOps: Qual curso inicial pra essa área? (0)
Melhores Práticas de Nomenclatura: Pastas, Arquivos e Código (3)
[Python] Automação de scan de vulnerabilidades
[Python] Script para analise de superficie de ataque
[Shell Script] Novo script para redimensionar, rotacionar, converter e espelhar arquivos de imagem
[Shell Script] Iniciador de DOOM (DSDA-DOOM, Doom Retro ou Woof!)
[Shell Script] Script para adicionar bordas às imagens de uma pasta