[comp.graphics] Better Lighting model for MTV raytracer

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!)