koblas@mips.COM (David Koblas) (10/01/88)
A better shading model for the MTV raytracer [I probably should have posted this a while back, while I was sure it all worked] The two big changes this has are a better shading model, including doing something diffrent with diffuse reflection. You can specify the color of a light, and surfaces have an ambiant and absorbance values [default: no ambiant and no absorbtion]. The "shine" value is now in the range from 0.0 -> 1.0 instead of 0 -> infinity. On balls I ran a sed script like this: '/^f/s/ 35 / 0.2 /' and got close the the same results. Also all componants of a surface can be specified with r,g,b values. Give it a try, and if you have any bugs/problems/sugestions, let me know and I'll give them a try/fix. name : David Koblas place: MIPS Computers Systems phone: 408-991-0287 uucp : {ames,decwrl,pyramid,wyse}!mips!koblas quote: I've began to wonder if X11 is really a competition to see who can create the largest copyright that says, "It's free." ----Patches Begin here------------------------------------------------------- diff -c mtv_raytracer/Makefile mtv_raytracer/ORIG/Makefile *** mtv_raytracer/Makefile Sat Sep 17 17:51:35 1988 --- mtv_raytracer/ORIG/Makefile Thu Sep 15 01:43:29 1988 *************** *** 7,18 **** # directly.... # - SUFFIX=.o PROG=ray CC=cc #CC=gcc ! CFLAGS=-O2 -DNO_VOID $(SYSFLAGS) ! #CFLAGS=-g -DNO_VOID #CFLAGS=-O -DFAST_MATH_PRIMS -finline-functions -g -p YFLAGS=-d --- 7,17 ---- # directly.... # PROG=ray CC=cc #CC=gcc ! CFLAGS=-O2 -DNO_VOID ! #CFLAGS=-O -f68881 #CFLAGS=-O -DFAST_MATH_PRIMS -finline-functions -g -p YFLAGS=-d *************** *** 19,29 **** CSRC=data.c main.c sphere.c vector.c shade.c trace.c intersect.c\ screen.c pic.c poly.c bound.c error.c pqueue.c cone.c\ color.c ! COBJ= data$(SUFFIX) main$(SUFFIX) sphere$(SUFFIX) vector$(SUFFIX) \ ! shade$(SUFFIX) trace$(SUFFIX) intersect$(SUFFIX) screen$(SUFFIX) \ ! pic$(SUFFIX) poly$(SUFFIX) bound$(SUFFIX) error$(SUFFIX) \ ! pqueue$(SUFFIX) cone$(SUFFIX) color$(SUFFIX) ! NFFFILES=balls.nff DOCFILES=README ray.1 COPYING BIBLIO ALGORITHMS OSRC=nff.y tokens.l --- 18,26 ---- CSRC=data.c main.c sphere.c vector.c shade.c trace.c intersect.c\ screen.c pic.c poly.c bound.c error.c pqueue.c cone.c\ color.c ! COBJ=data.o main.o sphere.o vector.o shade.o trace.o intersect.o\ ! screen.o pic.o poly.o bound.o error.o pqueue.o cone.o\ ! color.o NFFFILES=balls.nff DOCFILES=README ray.1 COPYING BIBLIO ALGORITHMS OSRC=nff.y tokens.l diff -c mtv_raytracer/balls.nff mtv_raytracer/ORIG/balls.nff *** mtv_raytracer/balls.nff Fri Sep 16 20:49:18 1988 --- mtv_raytracer/ORIG/balls.nff Thu Sep 15 01:42:52 1988 *************** *** 15,21 **** -12 12 -.5 -12 -12 -.5 12 -12 -.5 ! f SteelBlue .5 .5 0.05 0 0 s 0 0 0 .5 s .272166 .272166 .544331 .166667 s .643951 .172546 1.11022e-16 .166667 --- 15,21 ---- -12 12 -.5 -12 -12 -.5 12 -12 -.5 ! f SteelBlue .5 .5 3 0 0 s 0 0 0 .5 s .272166 .272166 .544331 .166667 s .643951 .172546 1.11022e-16 .166667 diff -c mtv_raytracer/config.h mtv_raytracer/ORIG/config.h *** mtv_raytracer/config.h Thu Sep 15 21:38:33 1988 --- mtv_raytracer/ORIG/config.h Thu Sep 15 01:42:53 1988 *************** *** 23,33 **** #define YMAX (1024) #define MAXLIGHTS (10) #define MAXPRIMS (40000) ! #define MAXLEVEL (9) ! ! #define NLAMBDA (3) ! #define FALSE (0) ! #define TRUE (1) /*********************************************************************** * If your compiler doesn't grok the void type, then define NO_VOID --- 23,29 ---- #define YMAX (1024) #define MAXLIGHTS (10) #define MAXPRIMS (40000) ! #define MAXLEVEL (5) /*********************************************************************** * If your compiler doesn't grok the void type, then define NO_VOID diff -c mtv_raytracer/data.c mtv_raytracer/ORIG/data.c *** mtv_raytracer/data.c Thu Sep 15 20:04:13 1988 --- mtv_raytracer/ORIG/data.c Thu Sep 15 01:42:53 1988 *************** *** 37,43 **** int totalQueues = 0 ; int totalQueueResets = 0 ; int tickflag = 0 ; - int depthflag = 0 ; int nChecked = 0 ; int nEnqueued = 0 ; int nShadowCacheHits = 0 ; --- 37,42 ---- Only in mtv_raytracer: data.o diff -c mtv_raytracer/defs.h mtv_raytracer/ORIG/defs.h *** mtv_raytracer/defs.h Sat Sep 17 17:52:36 1988 --- mtv_raytracer/ORIG/defs.h Thu Sep 15 01:42:54 1988 *************** *** 41,49 **** #define VecAddS(A,a,b,c) (c)[0]=(A)*(a)[0]+(b)[0];\ (c)[1]=(A)*(a)[1]+(b)[1];\ (c)[2]=(A)*(a)[2]+(b)[2] - #define VecMult(A,a,b) (b)[0]=(A)*(a)[0];\ - (b)[1]=(A)*(a)[1];\ - (b)[2]=(A)*(a)[2] #define VecCross(a,b,c) (c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1];\ (c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2];\ (c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0] --- 41,46 ---- *************** *** 59,73 **** Point D ; } Ray ; - typedef struct { - Vec origin,direction; - char flags[NLAMBDA]; - Flt weight[NLAMBDA]; - Flt ior[NLAMBDA]; - Flt trans[NLAMBDA]; - Flt intensity[NLAMBDA]; - } SuperRay; - #define RayPoint(ray,t,point) VecAddS(t,(ray)->D,(ray)->P,point) #define max(a,b) ((a)>(b)?(a):(b)) --- 56,61 ---- *************** *** 76,94 **** /*----------------------------------------------------------------------*/ typedef struct t_surface { ! Flt surf_color[NLAMBDA]; ! Flt surf_ambiant[NLAMBDA]; ! Flt surf_kd[NLAMBDA] ; ! Flt surf_ks[NLAMBDA] ; ! Flt surf_shine[NLAMBDA] ; ! Flt surf_kt[NLAMBDA] ; ! Flt trans[NLAMBDA] ; ! Flt ior[NLAMBDA] ; } Surface ; typedef struct t_light { Vec light_pos ; ! Flt intensity[NLAMBDA]; struct t_object * light_obj_cache[MAXLEVEL] ; } Light ; --- 64,80 ---- /*----------------------------------------------------------------------*/ typedef struct t_surface { ! Color surf_color ; ! Flt surf_kd ; ! Flt surf_ks ; ! Flt surf_shine ; ! Flt surf_kt ; ! Flt surf_ior ; } Surface ; typedef struct t_light { Vec light_pos ; ! Flt light_brightness ; struct t_object * light_obj_cache[MAXLEVEL] ; } Light ; diff -c mtv_raytracer/extern.h mtv_raytracer/ORIG/extern.h *** mtv_raytracer/extern.h Thu Sep 15 20:03:54 1988 --- mtv_raytracer/ORIG/extern.h Thu Sep 15 01:42:54 1988 *************** *** 23,29 **** extern int totalQueues ; extern int totalQueueResets ; extern int tickflag ; - extern int depthflag ; extern int nChecked ; extern int nEnqueued ; extern int nShadowCacheHits ; --- 23,28 ---- diff -c mtv_raytracer/main.c mtv_raytracer/ORIG/main.c *** mtv_raytracer/main.c Fri Sep 16 20:35:45 1988 --- mtv_raytracer/ORIG/main.c Thu Sep 15 01:42:55 1988 *************** *** 16,24 **** #include <sys/times.h> #include "defs.h" #include "extern.h" - #ifdef SYSV - #define rindex strrchr - #endif main(argc, argv) int argc ; --- 16,21 ---- *************** *** 27,33 **** extern int optind ; extern char *optarg ; int c ; - int resolution = -1 ; char * infilename = NULL ; char * outfilename = "out.pic" ; struct tms pbuf, tbuf ; --- 24,29 ---- *************** *** 37,43 **** else Progname ++ ; ! while ((c = getopt(argc, argv, "do:i:tr:")) != EOF) { switch (c) { case 'o': outfilename = optarg ; --- 33,39 ---- else Progname ++ ; ! while ((c = getopt(argc, argv, "o:i:t")) != EOF) { switch (c) { case 'o': outfilename = optarg ; *************** *** 45,56 **** case 'i': infilename = optarg ; break ; - case 'r': - resolution = atoi(optarg); - break; - case 'd': - depthflag = 1 ; - break; case 't': tickflag = 1 ; break ; --- 41,46 ---- *************** *** 61,68 **** } } ReadSceneFile(infilename) ; - if ( resolution > 0 ) - Xresolution = Yresolution = resolution ; InitSlabs() ; BuildBoundingSlabs() ; times(&pbuf) ; --- 51,56 ---- diff -c mtv_raytracer/nff.y mtv_raytracer/ORIG/nff.y *** mtv_raytracer/nff.y Sat Sep 17 20:12:48 1988 --- mtv_raytracer/ORIG/nff.y Thu Sep 15 01:42:57 1988 *************** *** 15,27 **** %union { Vec vec ; Vec * vecl ; - Flt rgbv[NLAMBDA]; double flt ; } ; %type <vec> point primcolor TOKEN %type <flt> num - %type <rgbv> rgbvec %% --- 15,25 ---- *************** *** 30,38 **** { int i, l ; for (l = 0 ; l < nLights ; l++) { ! for (i=0;i<NLAMBDA;i++) ! Lights[l].intensity[i] *= ! sqrt((Flt) nLights) / ((Flt)nLights) ; for (i = 0 ; i < MAXLEVEL ; i++) { Lights[l].light_obj_cache[i] = NULL ; } --- 28,35 ---- { int i, l ; for (l = 0 ; l < nLights ; l++) { ! Lights[l].light_brightness = sqrt((Flt) nLights) / ! ((Flt)nLights) ; for (i = 0 ; i < MAXLEVEL ; i++) { Lights[l].light_obj_cache[i] = NULL ; } *************** *** 73,102 **** } ; light: ! LIGHT point rgbvec { - int i; - - /* scale the brightness of the light, after we - * know the number of lights sources in the scene - */ VecCopy($2, Lights[nLights].light_pos) ; ! for (i=0;i<NLAMBDA;i++) { ! Lights[nLights].intensity[i] = $3[i] ; ! } ! nLights ++ ; ! } ! | LIGHT point ! { ! int i; ! ! /* scale the brightness of the light, after we * know the number of lights sources in the scene */ - VecCopy($2, Lights[nLights].light_pos) ; - for (i=0;i<NLAMBDA;i++) { - Lights[nLights].intensity[i]=1.0; - } nLights ++ ; } ; --- 70,81 ---- } ; light: ! LIGHT point { VecCopy($2, Lights[nLights].light_pos) ; ! /* fill in brightness of the light, after we * know the number of lights sources in the scene */ nLights ++ ; } ; *************** *** 107,146 **** } ; surface: ! SURFACE primcolor rgbvec rgbvec rgbvec rgbvec rgbvec rgbvec rgbvec { - int i; - CurrentSurface = (Surface *) malloc (sizeof(Surface)) ; VecCopy($2, CurrentSurface -> surf_color) ; ! for (i=0;i<NLAMBDA;i++) { ! CurrentSurface -> surf_kd[i] = $3[i] ; ! CurrentSurface -> surf_ks[i] = $4[i] ; ! CurrentSurface -> surf_shine[i] = $5[i] ; ! CurrentSurface -> surf_kt[i] = $6[i] ; ! CurrentSurface -> ior[i] = $7[i] ; ! CurrentSurface -> surf_ambiant[i] = $8[i] ; ! if ($9[i]==0.0) ! CurrentSurface -> trans[i]= 1.0 ; ! else ! CurrentSurface -> trans[i]= pow(0.5,1.0/$9[i]) ; ! } ! } ! | SURFACE primcolor rgbvec rgbvec rgbvec rgbvec rgbvec ! { /* this is the nff compatible line */ ! int i; ! ! CurrentSurface = (Surface *) malloc (sizeof(Surface)) ; ! VecCopy($2, CurrentSurface -> surf_color) ; ! for (i=0;i<NLAMBDA;i++) { ! CurrentSurface -> surf_kd[i] = $3[i] ; ! CurrentSurface -> surf_ks[i] = $4[i] ; ! CurrentSurface -> surf_shine[i] = $5[i] ; ! CurrentSurface -> surf_kt[i] = $6[i] ; ! CurrentSurface -> ior[i] = $7[i] ; ! CurrentSurface -> surf_ambiant[i] = 0.0 ; ! CurrentSurface -> trans[i] = 1.0 ; ! } } ; cone: --- 86,100 ---- } ; surface: ! SURFACE primcolor num num num num num { CurrentSurface = (Surface *) malloc (sizeof(Surface)) ; VecCopy($2, CurrentSurface -> surf_color) ; ! CurrentSurface -> surf_kd = $3 ; ! CurrentSurface -> surf_ks = $4 ; ! CurrentSurface -> surf_shine = $5 ; ! CurrentSurface -> surf_kt = $6 ; ! CurrentSurface -> surf_ior = $7 ; } ; cone: *************** *** 200,227 **** $$[0] = $1 ; $$[1] = $2 ; $$[2] = $3 ; - } ; - - rgbvec: - '{' num ',' num ',' num '}' - { - $$[0] = $2; - $$[1] = $4; - $$[2] = $6; - } - | TOKEN - { - char buf[80] ; - - if (LookupColorByName(yytext, $$) == 0) { - sprintf(buf, "cannot find color \"%s\"\n", - yytext) ; - yyerror(buf) ; - } - } - | num - { - $$[0] = $$[1] = $$[2] = $1 ; } ; pointlist: --- 154,159 ---- diff -c mtv_raytracer/ray.1 mtv_raytracer/ORIG/ray.1 *** mtv_raytracer/ray.1 Thu Sep 15 20:09:16 1988 --- mtv_raytracer/ORIG/ray.1 Thu Sep 15 01:43:00 1988 *************** *** 14,21 **** .B \-o outputfile ] [ .B \-t - ] [ - .B \-d ] .SH DESCRIPTION This program is an attempt at writing a reasonably useful --- 14,19 ---- *************** *** 30,39 **** .B \-t flag makes the ray tracer output a period after every scanline for those of you who get impatient, or who are wondering if it is still working. - .PP - The - .B \-d - flag prints onto 'stdout' a display of recursion depths. .PP Use .B \-i file --- 28,33 ---- diff -c mtv_raytracer/screen.c mtv_raytracer/ORIG/screen.c *** mtv_raytracer/screen.c Sat Sep 17 18:00:52 1988 --- mtv_raytracer/ORIG/screen.c Thu Sep 15 01:43:01 1988 *************** *** 23,37 **** char *picfile ; int xres, yres ; { ! Pixel *buf, *oldbuf, *curbuf, *tmp ; ! Pic *pic, *PicOpen(); ! Point viewvec, leftvec ; int red, green, blue ; ! Point dir ; ! SuperRay sray; ! Color color; ! Flt frustrumwidth ; ! int x, y, i, m ; /* * open the picture file... --- 23,37 ---- char *picfile ; int xres, yres ; { ! Pixel *buf, *oldbuf, *curbuf, *tmp ; ! Pic *pic, *PicOpen(); ! Point viewvec, leftvec ; int red, green, blue ; ! Point dir ; ! Ray ray ; ! Color color; ! Flt frustrumwidth ; ! int x, y ; /* * open the picture file... *************** *** 58,73 **** VecCross(view -> view_up, viewvec, leftvec); VecNormalize(leftvec); ! VecCopy(view -> view_from, sray.origin); frustrumwidth = (view -> view_dist) * ((Flt) tan(view -> view_angle)) ; - for (i=0;i<NLAMBDA;i++) { - sray.flags[i]=TRUE; - sray.weight[i]=1.0; - sray.ior[i] =1.0; /* should be runtime */ - sray.trans[i] =1.0; /* should be runtime */ - } for (y=0; y < yres + 1; y++) { for (x = 0; x < xres + 1; x++) { VecComb(-frustrumwidth*(2.0*(Flt)y/(Flt)(yres-1)-1.0), --- 58,67 ---- VecCross(view -> view_up, viewvec, leftvec); VecNormalize(leftvec); ! VecCopy(view -> view_from, ray.P); frustrumwidth = (view -> view_dist) * ((Flt) tan(view -> view_angle)) ; for (y=0; y < yres + 1; y++) { for (x = 0; x < xres + 1; x++) { VecComb(-frustrumwidth*(2.0*(Flt)y/(Flt)(yres-1)-1.0), *************** *** 74,91 **** view -> view_up, frustrumwidth*(2.0*(Flt)x/(Flt)(xres-1)-1.0), leftvec, dir); ! VecAdd(dir, viewvec, sray.direction); ! VecNormalize(sray.direction); ! for (i=0;i<NLAMBDA;i++) { ! sray.intensity[i]=0.0; ! } ! m=Trace(0,&sray); ! if (depthflag) printf("%d",m); - color[0] = sray.intensity[0]; - color[1] = sray.intensity[1]; - color[2] = sray.intensity[2]; - if (color[0] > 1.0) color[0] = 1.0 ; if (color[1] > 1.0) color[1] = 1.0 ; if (color[2] > 1.0) color[2] = 1.0 ; --- 68,77 ---- view -> view_up, frustrumwidth*(2.0*(Flt)x/(Flt)(xres-1)-1.0), leftvec, dir); ! VecAdd(dir, viewvec, ray.D); ! VecNormalize(ray.D); ! Trace(0, 1.0, &ray, color); if (color[0] > 1.0) color[0] = 1.0 ; if (color[1] > 1.0) color[1] = 1.0 ; if (color[2] > 1.0) color[2] = 1.0 ; *************** *** 117,124 **** curbuf = (Pixel *) malloc ((xres + 1) * sizeof (Pixel)) ; } - if (depthflag) - putchar('\n'); if (tickflag) fprintf(stderr, ".") ; } --- 103,108 ---- diff -c mtv_raytracer/shade.c mtv_raytracer/ORIG/shade.c *** mtv_raytracer/shade.c Sat Sep 17 19:54:09 1988 --- mtv_raytracer/ORIG/shade.c Thu Sep 15 01:43:01 1988 *************** *** 1,8 **** ! /* +------------------------------------------------------------------+ */ ! /* | Copyright 1988, David Koblas. | */ ! /* | You may copy this file in whole or in part as long as you | */ ! /* | don't try to make money off it, or pretend that you wrote it. | */ ! /* +------------------------------------------------------------------+ */ #include <stdio.h> #include <math.h> --- 1,23 ---- ! /*********************************************************************** ! * $Author: markv $ ! * $Revision: 1.2 $ ! * $Date: 88/09/12 12:58:01 $ ! * $Log: shade.c,v $ ! * Revision 1.2 88/09/12 12:58:01 markv ! * Added specular reflections and shadow caching. When a object ! * is found between a light source and the current point we are trying ! * to shade, that object is cached (indexed by recursion level) in the ! * lightsource. Next time we test a shadow against the light source, ! * we test this object first. If it is between us and the light source, ! * we can correctly shadow the object without calling Intersect(). ! * ! * Note: specular highlights call the unix pow() function, which seems ! * to be REALLY expensive. Optimizations could be made here. ! * ! * Revision 1.1 88/09/11 11:00:44 markv ! * Initial revision ! * ! ***********************************************************************/ #include <stdio.h> #include <math.h> *************** *** 9,325 **** #include "defs.h" #include "extern.h" ! /* ! ** ToDo: ! ** Currently the "shinieness" of a object is only dependant on 1st lambda ! ** ! ** Add SpecularTransmission (once I figure out exactly what it is) ! ** and DiffuseTransmission (once I figure out exactly what it is as well) ! ** ! */ ! /* ! ** And now for your viewing plesure some of the worst comments from another ! ** raytracer that I once knew [I shant tell you the author of this code] ! ** (these are included here, to show people how not to comment narly code) ! ** ! *** | I've not been looking forward to commenting this ! *** | please excuse it if it is ugly. (if it was hard ! *** | to write...) ! ** ! *** | gets amount of normal that has to be added to ! *** | incident ray to get the proper angle of ! *** | refraction by ancient mystical methods ! ** ! *** | gets amount of light transmitted ! *** | through ball by mystical methods mentioned ! *** | above. (see nasty physics text for details) ! ** ! ** ...his "mystical methods" were wrong... ! */ ! ! #define REFLECTION ! #define REFRACTION ! #define AMBIANT ! #define SPECULAR_REFLECTION ! #define DIFFUSE_REFLECTION ! #define ABSORBTION ! ! #ifndef lint ! static char rcsid[]="$Header: shade.c,v 1.1 88/09/17 19:53:45 koblas Locked $"; ! #endif ! ! /* ! ** Calculate the intensity of light at a given point. ! ** ! ** paramaters: ! ** level = recursion level ! ** sray = super ray, the ray that we are currently tracing ! ** P = point of contact with object ! ** N = unit normal with the object ! ** hit = object that was hit ! ** ! ** returns: ! ** maximum depth that was traced to (i.e. what the largest level was) ! ** ! */ ! ! Shade(level,sray,P,N,hit) ! int level; ! SuperRay *sray; ! Vec P,N; ! Isect *hit; { ! SuperRay newsray; ! Ray ray; ! Surface *surf = hit -> isect_prim -> o_surf; ! char lflags[NLAMBDA]; ! int i,j; ! Vec R,T; ! Flt beta[NLAMBDA],val[NLAMBDA]; ! Flt n_dot_v,t; ! Isect newhit; ! int count; ! int maxdepth,m; ! level ++; ! maxdepth=level; ! VecCopy(P,newsray.origin); ! ! /* Gee, does it look like someone messed up. ! ** [this should be fixed] ! */ ! for (i=0;i<NLAMBDA;i++) { ! if (surf->ior[i]==0.0) ! beta[i] = HUGE; ! else ! beta[i] = sray->ior[i] / surf->ior[i]; ! } ! fresnal(sray->direction,N,sray->flags,beta,val); ! for (i=0;i<NLAMBDA;i++) { ! if (sray->ior[i]==0.0) ! beta[i] = HUGE; ! else ! beta[i] = surf->ior[i] / sray->ior[i] ; ! } ! ! /* ! ** Reflected ray ! ** [look closely at the "if" before you touch] ! */ ! n_dot_v = VecDot(N,sray->direction); ! t = fabs(1.0/n_dot_v); ! VecMult(2.0,N,R); ! VecMult(t,sray->direction,newsray.direction); ! VecAdd(R,newsray.direction,newsray.direction); ! VecNormalize(newsray.direction); ! VecCopy(newsray.direction,R); ! #ifdef REFLECTION ! count=0; ! for (i=0;i<NLAMBDA;i++) { ! if (!(newsray.flags[i]= (sray->flags[i] && ! ((newsray.weight[i]= ! surf->surf_ks[i]*val[i]*sray->weight[i])>minweight)))) { ! continue; ! } ! newsray.ior[i] = sray->ior[i]; ! newsray.trans[i] = sray->trans[i]; ! newsray.intensity[i] = 0.0; ! count++; ! } ! if (count!=0) { ! nReflected++; ! m=Trace(level,&newsray); ! if (m>maxdepth) maxdepth=m; ! for (i=0;i<NLAMBDA;i++) { ! if (!newsray.flags[i]) continue; ! sray->intensity[i] += surf->surf_ks[i]* ! val[i]* ! newsray.intensity[i]; ! } ! } ! #endif ! #ifdef REFRACTION ! /* ! ** Refracted ray ! ** [look closely at the "if" before you touch] ! */ ! for (i=0;i<NLAMBDA;i++) { ! lflags[i]=sray->flags[i] && (val[i]!=1.0); ! newsray.intensity[i] = 0.0; ! newsray.ior[i] = surf->ior[i]; ! newsray.trans[i]= surf->trans[i]; ! } ! for (i=0;i<NLAMBDA;i++) { ! Flt b=beta[i],t,c2; ! ! if (!lflags[i]) continue; ! for (j=0;j<NLAMBDA;j++) { ! if (b==beta[j]) { ! if ((lflags[j]) && ! ((newsray.weight[j]=surf->surf_kt[i]* ! (1.0-val[j])*sray->weight[j])>minweight)) ! newsray.flags[j]=TRUE; ! lflags[j]=FALSE; } else { ! newsray.flags[j]=FALSE; } } - - c2 = 1.0 - (1.0 - n_dot_v*n_dot_v)*(b*b); - t = (-1.0*b)*n_dot_v-sqrt(c2); - VecComb(b,sray->direction,t,N,newsray.direction); - VecNormalize(newsray.direction); - - nRefracted++; - m=Trace(level,&newsray); - if (m>maxdepth) maxdepth=m; - for (j=0;j<NLAMBDA;j++) { - if (!newsray.flags[j]) continue; - sray->intensity[j] += surf->surf_kt[j]* - (1.0-val[j])* - newsray.intensity[j]; - } } - #endif - #ifdef AMBIANT - /* - ** Ambiant lighting - */ - for (i=0;i<NLAMBDA;i++) { - if (!sray->flags[i]) continue; - sray->intensity[i] += surf->surf_ambiant[i]* - surf->surf_color[i]; - } - #endif ! VecCopy(P,ray.P); ! for (j=0;j<nLights;j++) { ! Flt tmax,n_dot_l; ! VecSub(Lights[j].light_pos,P,ray.D); ! tmax = VecNormalize(ray.D); ! if ((n_dot_l=VecDot(N,ray.D)) < 0.0) continue; ! nShadows++; ! if (Shadow(&ray,&newhit,tmax)) { ! Vec H,Hp; ! Flt n_dot_h; ! Flt t,g; ! Flt sr,dt; ! ! VecAdd(sray->direction,ray.D,H); ! VecNormalize(H); ! n_dot_h=VecDot(N,H); ! /* (Blinn) + (Cook and Torrance) model for ! ** specular reflection ! */ ! t = 2.0*(n_dot_h/VecDot(sray->direction,H)); ! g = t*n_dot_l; ! t = t*n_dot_v; ! g = min(min(g,t),1.0); ! if ((surf->surf_shine[0]!=0.0) && (n_dot_l!=0.0)) { ! t=n_dot_l*n_dot_l* ! surf->surf_shine[0]*surf->surf_shine[0]; ! t= (t!=0.0) ? ! (exp((n_dot_l*n_dot_l-1.0)/t) / ! (t*n_dot_l*n_dot_l)) : 0.0 ; ! } else ! t=0.0; ! sr = (t*g)/(PI*n_dot_l*n_dot_v); ! ! #if 0 ! /* this need to be in the loop */ ! VecAddS(-beta[i],ray.D,sray->direction,Hp); ! VecMult(1.0/(beta[i]-1.0),Hp,Hp); ! VecNormalize(Hp); ! dt=pow(VecDot(Hp,N),5); ! #endif ! ! for (i=0;i<NLAMBDA;i++) { ! if (!sray->flags[i]) continue; ! ! #ifdef DIFFUSE_REFLECTION ! /* Diffuse Reflection ! */ ! sray->intensity[i]+= ! (surf->surf_kd[i]* ! surf->surf_color[i]* ! Lights[j].intensity[i]*n_dot_l); ! #endif ! #ifdef SPECULAR_REFLECTION ! /* Specular reflection ! */ ! sray->intensity[i]+= ! surf->surf_ks[i]* ! surf->surf_color[i]* ! val[i]* ! Lights[j].intensity[i]*sr; ! #endif ! #if 0 ! /* I've got a bug!, could be due the the piece missing from the loop */ ! /* Specular transmission ! */ ! sray->intensity[i]+= ! surf->surf_kt[i]* ! surf->surf_color[i]* ! val[i]* ! Lights[j].intensity[i]*dt; ! #endif ! } ! } } ! #ifdef ABSORBTION ! VecSub(sray->origin,P,T); ! t=VecLen(T); ! ! for (i=0;i<NLAMBDA;i++) { ! if (!sray->flags[i]) continue; ! sray->intensity[i]*=sray->trans[i]; } - #endif - - return maxdepth; } ! /* ! ** Fresnals law for transmission. ! ** total internal reflection when (*val == 1.0) [IEEE says ok (the compare)] ! ** ! ** Returns in val[] a set of values to determine the amount of light ! ** that is REFLECTED. The rest of the light (1.0-val[]) is ! ** transmitted/refracted/absorbed. ! ** ! */ ! fresnal(I,N,flag,index,val) ! Vec I,N; ! char *flag; ! Flt *index; ! Flt *val; { ! int i; ! Flt cosine2; ! Flt cosine,index2,sine2,TE,TM,temp; ! cosine2 = VecDot(I,N); ! cosine2 = cosine2*cosine2; ! sine2 = 1.0 - cosine2; ! cosine = sqrt(cosine2); ! for (i=0;i<NLAMBDA;i++) { ! if (!flag[i]) continue; ! index2 = index[i]*index[i]; ! if (sine2 >= index2) { ! val[i]=1.0; ! continue; ! } ! temp = sqrt(index2 - sine2); ! TE = (cosine - temp) / (cosine + temp); ! TM = (index2*cosine - temp) / (index2*cosine + temp); ! /* polerization is ignored...so average */ ! val[i]=(0.5*(TE*TE+TM*TM)); ! } } --- 24,165 ---- #include "defs.h" #include "extern.h" ! /*********************************************************************** ! * Shade(level, weight, P, N, I, hit, col) ! * ! * Wow! Too many parameters! ! * ! * Shade is the driving force of the raytracer. It calculates the actual ! * luminance at point P, given N, the normal, and I the incident vector. ! * We also pass in the hit, because the normal generating code might need it. ! * The color is returned in col. ! ***********************************************************************/ ! Shade(level, weight, P, N, I, hit, col) ! int level ; ! Flt weight ; ! Vec P, N, I ; ! Isect * hit; ! Color col ; { ! Ray tray ; ! Color tcol ; ! Vec L, H, R ; ! Flt t ; ! Flt diff ; ! Flt spec ; ! #ifdef SHADOW_CACHING ! Object * cached ; ! #endif /* SHADOW_CACHING */ ! Isect nhit ; ! Surface * surf ; ! int l ; ! col[0] = col[1] = col[2] = 0.0 ; ! surf = hit -> isect_prim -> o_surf ; ! for (l = 0; l < nLights; l++) { ! VecSub(Lights[l].light_pos, P, L); ! if (VecDot(N,L) >= 0.0) { ! t = VecNormalize(L); ! VecCopy(P, tray.P); ! VecCopy(L, tray.D); ! nShadows ++ ; ! #ifdef SHADOW_CACHING ! cached = Lights[l].light_obj_cache[level] ; ! if (cached ! && (cached -> o_procs -> intersect) ! (cached, &tray, &nhit) ! && nhit.isect_t < t) { ! /* ! * we are in shadow, continue... ! */ ! nShadowCacheHits ++ ; ! continue ; ! } ! #endif /* SHADOW_CACHING */ ! if (Shadow(&tray, &nhit, t)) { ! diff = VecDot(N,L) * surf -> surf_kd ! * Lights[l].light_brightness ; ! #ifdef SHADOW_CACHING ! Lights[l].light_obj_cache[level] = NULL ; ! #endif /* SHADOW_CACHING */ ! VecAddS(diff, surf -> surf_color, col, col) ; ! SpecularDirection(I, N, R) ; ! VecNormalize(R) ; ! if (surf -> surf_shine > rayeps) { ! spec = VecDot(R,L) ; ! if (spec > rayeps) { ! spec = pow(spec, surf -> surf_shine ) * Lights[l].light_brightness ; ! col[0] += spec ; ! col[1] += spec ; ! col[2] += spec ; ! } ! } } else { ! #ifdef SHADOW_CACHING ! Lights[l].light_obj_cache[level] = ! nhit.isect_prim ; ! #endif /* SHADOW_CACHING */ } + } } ! VecCopy(P, tray.P); ! if(surf -> surf_ks * weight > minweight) { ! nReflected ++ ; ! SpecularDirection(I, N, tray.D); ! VecNormalize(tray.D); ! Trace(level + 1, surf -> surf_ks * weight, &tray, tcol); ! VecAddS(surf -> surf_ks, tcol, col, col); } ! if (surf -> surf_kt * weight > minweight) { ! nRefracted ++ ; ! if (hit -> isect_enter) ! TransmissionDirection(NULL, surf, I, N, tray.D) ; ! else ! TransmissionDirection(surf, NULL, I, N, tray.D) ; ! Trace(level + 1, surf -> surf_kt * weight, &tray, tcol) ; ! VecAddS(surf -> surf_kt, tcol, col, col) ; } } ! /*********************************************************************** ! * SpecularDirection(I, N, R) ! * ! * Given an incident vector I, and the normal N, calculate the ! * direction of the reflected ray R. ! ***********************************************************************/ ! SpecularDirection(I, N, R) ! Vec I, N, R; { ! VecComb(1.0/fabs(VecDot(I,N)), I, 2.0, N, R); ! VecNormalize(R); ! } ! /*********************************************************************** ! * TransmissionDirection(m1, m2, I, N, T) ! * ! * calculates the direction of the transmitted ray ! ***********************************************************************/ ! TransmissionDirection(m1, m2, I, N, T) ! Surface *m1, *m2; ! Vec I, N, T ; ! { ! Flt n1, n2, eta, c1, cs2 ; ! n1 = m1 ? m1 -> surf_ior : 1.0 ; ! n2 = m2 ? m2 -> surf_ior : 1.0 ; ! eta = n1/n2 ; ! c1 = -VecDot(I,N); ! cs2 = 1.0 - eta * eta*(1.0 - c1*c1); ! if (cs2 < 0.0) ! return 0; ! VecComb(eta, I, eta*c1-sqrt(cs2), N, T); ! return(1); } *** mtv_raytracer/trace.c Sat Sep 17 19:56:07 1988 --- mtv_raytracer/ORIG/trace.c Thu Sep 15 01:43:03 1988 *************** *** 1,8 **** ! /* +------------------------------------------------------------------+ */ ! /* | Copyright 1988, David Koblas. | */ ! /* | You may copy this file in whole or in part as long as you | */ ! /* | don't try to make money off it, or pretend that you wrote it. | */ ! /* +------------------------------------------------------------------+ */ #include <stdio.h> #include <math.h> --- 1,15 ---- ! /*********************************************************************** ! * $Author: markv $ ! * $Revision: 1.2 $ ! * $Date: 88/09/12 13:01:15 $ ! * $Log: trace.c,v $ ! * Revision 1.2 88/09/12 13:01:15 markv ! * Fixed Trace to call Intersect with the max dist argument of HUGE. ! * ! * Revision 1.1 88/09/11 11:00:45 markv ! * Initial revision ! * ! ***********************************************************************/ #include <stdio.h> #include <math.h> *************** *** 9,54 **** #include "defs.h" #include "extern.h" ! #ifndef lint ! static char rcsid[]="$Header$"; ! #endif ! ! /* ! ** Trace a raytraced ray ! */ ! ! Trace(level, sray) ! int level; ! SuperRay *sray; { ! Ray ray; ! Vec P,N; ! Isect hit; ! int i; if (level >= maxlevel) { ! for (i=0;i<NLAMBDA;i++) ! if (sray->flags[i]) ! sray->intensity[i]=0.0; ! return level; } ! VecCopy(sray->origin ,ray.P); ! VecCopy(sray->direction,ray.D); ! ! nRays ++; ! ! if (Intersect(&ray,&hit,HUGE)) { ! VecAddS(hit.isect_t,ray.D,ray.P,P); ! (*hit.isect_prim->o_procs->normal)(hit.isect_prim,&hit,P,N); ! if ((VecDot(ray.D, N)) >= 0.0) { VecNegate(N); } ! return Shade(level,sray,P,N,&hit); } else { ! for (i=0;i<NLAMBDA;i++) ! if (sray->flags[i]) ! sray->intensity[i]=BackgroundColor[i]; ! return level; } } --- 16,47 ---- #include "defs.h" #include "extern.h" ! Trace(level, weight, ray, color) ! int level; ! Flt weight; ! Ray *ray ; ! Color color ; { ! Object *prim ; ! Vec P, N ; ! Isect hit ; if (level >= maxlevel) { ! color[0] = color[1] = color[2] = 0 ; ! return ; } + + nRays ++ ; ! if (Intersect(ray, &hit, HUGE)) { ! prim = hit.isect_prim ; ! RayPoint(ray, hit.isect_t, P); ! (*prim -> o_procs -> normal) (prim, &hit, P, N); ! if ((VecDot(ray->D, N)) >= 0.0) { VecNegate(N); } ! Shade(level, weight, P, N, ray -> D, &hit, color); } else { ! VecCopy(BackgroundColor, color) ; } } -- name : David Koblas place: MIPS Computers Systems phone: 408-991-0287 uucp : {ames,decwrl,pyramid,wyse}!mips!koblas quote: I've began to wonder if X11 is really a competition to see who can create the largest copyright that says, "It's free."
gould@rosemary.cs.reading.ac.uk (Adrian Gould) (10/07/88)
In article <4268@wright.mips.COM> koblas@mips.COM (David Koblas) writes: >A better shading model for the MTV raytracer [I probably should have >posted this a while back, while I was sure it all worked] Ok, So I was on Vacation at the time of this going up... anyone willing to post to me? "And God said, 'Let there be light.' And there was light." And so God gave his only Son to be the Light of the world. gould%{onion|sage|rosemary}.cs.reading.ac.uk@nss.cs.ucl.arpa
gould@reading.ac.uk (Adrian John Gould) (10/07/88)
I missed this... this was due to vacation??? Let us have a copy of the main proggy someone... PLEASE! Ta Adrian gould%{onion|rosemary|sage}.cs.reading.ac.uk@nss.cs.ucl.arpa (Prefer onion if possible!)