LIGHTING.C 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307
  1. /****************************************************************************
  2. * lighting.c
  3. *
  4. * This module calculates lighting properties like ambient, diffuse, specular,
  5. * reflection, refraction, etc.
  6. *
  7. * from Persistence of Vision(tm) Ray Tracer
  8. * Copyright 1996,1999 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. * NOTICE: This source code file is provided so that users may experiment
  11. * with enhancements to POV-Ray and to port the software to platforms other
  12. * than those supported by the POV-Ray Team. There are strict rules under
  13. * which you are permitted to use this file. The rules are in the file
  14. * named POVLEGAL.DOC which should be distributed with this file.
  15. * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  16. * Team Coordinator by email to team-coord@povray.org or visit us on the web at
  17. * http://www.povray.org. The latest version of POV-Ray may be found at this site.
  18. *
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. * Modifications by Robert G. Smith & Andreas Dilger, March 1999, used with
  24. * permission
  25. *
  26. *****************************************************************************/
  27. #include "frame.h"
  28. #include "vector.h"
  29. #include "povproto.h"
  30. #include "blob.h"
  31. #include "bbox.h"
  32. #include "colour.h"
  33. #include "image.h"
  34. #include "interior.h"
  35. #include "lbuffer.h"
  36. #include "lighting.h"
  37. #include "media.h"
  38. #include "mesh.h"
  39. #include "normal.h"
  40. #include "objects.h"
  41. #include "octree.h"
  42. #include "pattern.h" /* [CEY 10/94] */
  43. #include "pigment.h"
  44. #include "povray.h"
  45. #include "radiosit.h"
  46. #include "ray.h"
  47. #include "render.h"
  48. #include "texture.h"
  49. /*****************************************************************************
  50. * Local preprocessor defines
  51. ******************************************************************************/
  52. #define BLACK_LEVEL 0.003
  53. /*
  54. * "Small_Tolerance" is just too tight for higher order polynomial equations.
  55. * this value should probably be a variable of some sort, but for now just
  56. * use a reasonably small value. If people render real small objects real
  57. * close to each other then there may be some shading problems. Otherwise
  58. * having SHADOW_TOLERANCE as large as this won't affect images.
  59. */
  60. #define SHADOW_TOLERANCE 1.0e-3
  61. /* Number of inital entries in the texture and weight list. */
  62. #define NUMBER_OF_ENTRIES 16
  63. /*****************************************************************************
  64. * Local typedefs
  65. ******************************************************************************/
  66. /*
  67. * List to store light colours during shadow testing
  68. * to avoid repeated testing with layered textures.
  69. */
  70. typedef struct Light_Tested_Struct LIGHT_TESTED;
  71. struct Light_Tested_Struct
  72. {
  73. int Tested;
  74. COLOUR Colour;
  75. };
  76. /*****************************************************************************
  77. * Local variables
  78. ******************************************************************************/
  79. static LIGHT_TESTED *Light_List;
  80. static TEXTURE **Texture_List;
  81. static DBL *Weight_List;
  82. static int Number_Of_Textures_And_Weights;
  83. /*****************************************************************************
  84. * Static functions
  85. ******************************************************************************/
  86. static void block_area_light (LIGHT_SOURCE *Light_Source,
  87. DBL *Light_Source_Depth, RAY *Light_Source_Ray, RAY *Eye_Ray,
  88. VECTOR IPoint, COLOUR Light_Colour, int u1, int v1, int u2, int v2, int Level);
  89. static void block_point_light (LIGHT_SOURCE *Light_Source,
  90. DBL *Light_Source_Depth, RAY *Light_Source_Ray, COLOUR Light_Colour);
  91. static void block_point_light_LBuffer (LIGHT_SOURCE *Light_Source,
  92. DBL *Light_Source_Depth, RAY *Light_Source_Ray, COLOUR Light_Colour);
  93. static void do_light (LIGHT_SOURCE *Light_Source,
  94. DBL *Light_Source_Depth, RAY *Light_Source_Ray, RAY *Eye_Ray, VECTOR IPoint,
  95. COLOUR Light_Colour);
  96. static int do_blocking (INTERSECTION *Local_Intersection,
  97. RAY *Light_Source_Ray, COLOUR Light_Colour, ISTACK *Local_Stack);
  98. static void do_phong (FINISH *Finish, RAY *Light_Source_Ray,
  99. VECTOR Eye, VECTOR Layer_Normal, COLOUR Colour, COLOUR Light_Colour,
  100. COLOUR Layer_Texture_Colour);
  101. static void do_specular (FINISH *Finish, RAY *Light_Source_Ray,
  102. VECTOR REye, VECTOR Layer_Normal, COLOUR Colour, COLOUR Light_Colour,
  103. COLOUR Layer_Pigment_Colour);
  104. static void do_diffuse (FINISH *Finish, RAY *Light_Source_Ray,
  105. VECTOR Layer_Normal, COLOUR Colour, COLOUR Light_Colour,
  106. COLOUR Layer_Pigment_Colour, DBL Attenuation);
  107. static void do_irid (FINISH *Finish, RAY *Light_Source_Ray,
  108. VECTOR Layer_Normal, VECTOR IPoint, COLOUR Colour);
  109. static void Diffuse (FINISH *Finish, VECTOR IPoint, RAY *Eye, VECTOR Layer_Normal,
  110. COLOUR Layer_Pigment_Colour, COLOUR Colour,DBL Attenuation, OBJECT *Object);
  111. static void Reflect (VECTOR, RAY*, VECTOR, VECTOR, COLOUR, DBL);
  112. static int Refract (INTERIOR*, VECTOR, RAY*, VECTOR, VECTOR, COLOUR, DBL);
  113. static void filter_shadow_ray (INTERSECTION *Ray_Intersection,
  114. RAY *Light_Source_Ray, COLOUR Colour);
  115. static int create_texture_list (INTERSECTION *Ray_Intersection);
  116. static void do_texture_map (COLOUR Result_Colour,
  117. TEXTURE *Texture, VECTOR IPoint, VECTOR Raw_Normal, RAY *Ray, DBL Weight,
  118. INTERSECTION *Ray_Intersection, int Shadow_Flag);
  119. static void average_textures (COLOUR Result_Colour,
  120. TEXTURE *Texture, VECTOR IPoint, VECTOR Raw_Normal, RAY *Ray, DBL Weight,
  121. INTERSECTION *Ray_Intersection, int Shadow_Flag);
  122. static void compute_lighted_texture (COLOUR Result_Colour,
  123. TEXTURE *Texture, VECTOR IPoint, VECTOR Raw_Normal, RAY *Ray, DBL Weight,
  124. INTERSECTION *Ray_Intersection);
  125. static void compute_shadow_texture (COLOUR Filter_Colour,
  126. TEXTURE *Texture, VECTOR IPoint, VECTOR Raw_Normal, RAY *Ray,
  127. INTERSECTION *Ray_Intersection);
  128. static void block_light_source (LIGHT_SOURCE *Light,
  129. DBL Depth, RAY *Light_Source_Ray, RAY *Eye_Ray, VECTOR P, COLOUR Colour);
  130. static void do_light_ray_atmosphere (RAY *Light_Source_Ray,
  131. INTERSECTION *Ray_Intersection, COLOUR Colour, int Valid_Object);
  132. /*****************************************************************************
  133. *
  134. * FUNCTION
  135. *
  136. * Initialize_Lighting_Code
  137. *
  138. * INPUT
  139. *
  140. * OUTPUT
  141. *
  142. * RETURNS
  143. *
  144. * AUTHOR
  145. *
  146. * Dieter Bayer
  147. *
  148. * DESCRIPTION
  149. *
  150. * Allocate lists needed during lighting calculations.
  151. *
  152. * CHANGES
  153. *
  154. * Sep 1994 : Creation.
  155. *
  156. * Okt 1994 : Added initialization of Light_List and test if there are
  157. * any light sources in the scene. [DB]
  158. *
  159. ******************************************************************************/
  160. void Initialize_Lighting_Code()
  161. {
  162. int i;
  163. Light_List = NULL;
  164. Texture_List = NULL;
  165. Weight_List = NULL;
  166. /* Allocate memory for light list. */
  167. if (Frame.Number_Of_Light_Sources > 0)
  168. {
  169. Light_List = (LIGHT_TESTED *)POV_MALLOC(Frame.Number_Of_Light_Sources*sizeof(LIGHT_TESTED), "temporary light list");
  170. for (i = 0; i < Frame.Number_Of_Light_Sources; i++)
  171. {
  172. Light_List[i].Tested = FALSE;
  173. Make_ColourA(Light_List[i].Colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  174. }
  175. }
  176. /* Allocate memory for texture and weight list. */
  177. Number_Of_Textures_And_Weights = NUMBER_OF_ENTRIES;
  178. Texture_List = (TEXTURE **)POV_MALLOC(Number_Of_Textures_And_Weights*sizeof(TEXTURE *), "texture list");
  179. Weight_List = (DBL *)POV_MALLOC(Number_Of_Textures_And_Weights*sizeof(DBL), "weight list");
  180. }
  181. /*****************************************************************************
  182. *
  183. * FUNCTION
  184. *
  185. * Reinitialize_Lighting_Code
  186. *
  187. * INPUT
  188. *
  189. * Number_Of_Entries - New number of entries in the texture/weight lists
  190. *
  191. * OUTPUT
  192. *
  193. * RETURNS
  194. *
  195. * AUTHOR
  196. *
  197. * Dieter Bayer
  198. *
  199. * DESCRIPTION
  200. *
  201. * Resize variable lists needed during lighting calculation.
  202. *
  203. * CHANGES
  204. *
  205. * Jul 1995 : Creation.
  206. *
  207. * Mar 1996 : We have to pass pointers to the lists to resize because during
  208. * resizing the pointers to the lists change and thus the calling
  209. * functions does not longer know where the lists are if the
  210. * pointers to the lists where passed to it using arguments. [DB]
  211. *
  212. ******************************************************************************/
  213. void Reinitialize_Lighting_Code(int Number_Of_Entries, TEXTURE ***Textures, DBL **Weights)
  214. {
  215. if (Number_Of_Entries > Number_Of_Textures_And_Weights)
  216. {
  217. if (Number_Of_Entries >= INT_MAX / 2)
  218. {
  219. Error("Too many entries in texture and weight lists.\n");
  220. }
  221. Number_Of_Textures_And_Weights = Number_Of_Entries;
  222. Texture_List = (TEXTURE **)POV_REALLOC(Texture_List, Number_Of_Textures_And_Weights*sizeof(TEXTURE *), "texture list");
  223. Weight_List = (DBL *)POV_REALLOC(Weight_List, Number_Of_Textures_And_Weights*sizeof(DBL), "weight list");
  224. *Textures = Texture_List;
  225. *Weights = Weight_List;
  226. }
  227. }
  228. /*****************************************************************************
  229. *
  230. * FUNCTION
  231. *
  232. * Deinitialize_Lighting_Code
  233. *
  234. * INPUT
  235. *
  236. * OUTPUT
  237. *
  238. * RETURNS
  239. *
  240. * AUTHOR
  241. *
  242. * Dieter Bayer
  243. *
  244. * DESCRIPTION
  245. *
  246. * Destroy all lists needed during lighting calculation.
  247. *
  248. * CHANGES
  249. *
  250. * Sep 1994 : Creation.
  251. *
  252. * Jul 1995 : Added code to free local texture and weight lists. [DB]
  253. *
  254. ******************************************************************************/
  255. void Deinitialize_Lighting_Code()
  256. {
  257. if (Light_List != NULL)
  258. {
  259. POV_FREE(Light_List);
  260. }
  261. if (Texture_List != NULL)
  262. {
  263. POV_FREE(Texture_List);
  264. }
  265. if (Weight_List != NULL)
  266. {
  267. POV_FREE(Weight_List);
  268. }
  269. Light_List = NULL;
  270. Texture_List = NULL;
  271. Weight_List = NULL;
  272. }
  273. /*****************************************************************************
  274. *
  275. * FUNCTION
  276. *
  277. * Determine_Apparent_Colour
  278. *
  279. * INPUT
  280. *
  281. * Ray_Intersection - info on where ray hit & object it hit
  282. * Ray - the ray from which object is seen
  283. * Weight - Automatic depth control value
  284. *
  285. * OUTPUT
  286. *
  287. * Colour - resulting color is added to given color. The RGB
  288. * components are significant. The transmittance channel
  289. * is used as an alpha channel.
  290. *
  291. * RETURNS
  292. *
  293. * AUTHOR
  294. *
  295. * POV-Ray Team
  296. *
  297. * DESCRIPTION
  298. *
  299. * Given an intersection point, a ray, add that point's visible color
  300. * to the given colour and return it. This routine just does preliminary
  301. * initializations and calls to set up the multi-texture blob list if any.
  302. * Then it calls do_texture_map which in turn calls compute_lighted_texture
  303. * to do the actual lighting calculations. These functions were seperated
  304. * from this function because do_texture_map may need to call itself
  305. * recursively.
  306. *
  307. * CHANGES
  308. *
  309. * Sep 1994 : Code for multi-textured blobs added. [DB]
  310. *
  311. * Nov 1994 : Moved calls to Fog and Rainbow into tracing functions. [DB]
  312. *
  313. * Jan 1995 : Moved much of code to do_texture_map and
  314. * compute_lighted_texture [CEY]
  315. *
  316. * Jul 1995 : Added code to support alpha channel. [DB]
  317. *
  318. * Mar 1996 : Fixed severe bug (weight and texture lists were not saved) [DB]
  319. *
  320. ******************************************************************************/
  321. void Determine_Apparent_Colour(INTERSECTION *Ray_Intersection, COLOUR Colour, RAY *Ray, DBL Weight)
  322. {
  323. int i, Texture_Count;
  324. size_t savelights_size, save_tw_size;
  325. DBL *save_Weights = NULL;
  326. DBL Normal_Direction;
  327. COLOUR C1;
  328. VECTOR Raw_Normal;
  329. VECTOR IPoint;
  330. TEXTURE *Texture, **save_Textures = NULL;
  331. LIGHT_TESTED *savelights = NULL;
  332. Assign_Vector(IPoint,Ray_Intersection->IPoint);
  333. /*
  334. * Save existing light list if any. If we are not top level in recursion
  335. * depth, this information may be reused by upper level of trace.
  336. */
  337. savelights_size = (size_t)(Frame.Number_Of_Light_Sources*sizeof(LIGHT_TESTED));
  338. if (savelights_size > 0)
  339. {
  340. savelights = (LIGHT_TESTED *)POV_MALLOC(savelights_size, "Light list stack");
  341. memcpy(savelights, Light_List, savelights_size);
  342. }
  343. /* Init light list. */
  344. for (i = 0; i < Frame.Number_Of_Light_Sources; i++)
  345. {
  346. Light_List[i].Tested = FALSE;
  347. }
  348. /* Get the normal to the surface */
  349. Normal(Raw_Normal, Ray_Intersection->Object, Ray_Intersection);
  350. /* If the surface normal points away, flip its direction. */
  351. VDot(Normal_Direction, Raw_Normal, Ray->Direction);
  352. if (Normal_Direction > 0.0)
  353. {
  354. VScaleEq(Raw_Normal, -1.0);
  355. }
  356. /*
  357. * Save texture and weight lists.
  358. */
  359. save_tw_size = (size_t)Number_Of_Textures_And_Weights;
  360. if (save_tw_size > 0)
  361. {
  362. save_Weights = (DBL *)POV_MALLOC(save_tw_size * sizeof(DBL), "Weight list stack");
  363. memcpy(save_Weights, Weight_List, save_tw_size * sizeof(DBL));
  364. save_Textures = (TEXTURE **)POV_MALLOC(save_tw_size * sizeof(TEXTURE *), "Weight list stack");
  365. memcpy(save_Textures, Texture_List, save_tw_size * sizeof(TEXTURE *));
  366. }
  367. /* Get texture list and weights. */
  368. Texture_Count = create_texture_list (Ray_Intersection);
  369. /*
  370. * Now, we perform the lighting calculations by stepping through
  371. * the list of textures and summing the weighted color.
  372. */
  373. for (i = 0; i < Texture_Count; i++)
  374. {
  375. /* If contribution of this texture is neglectable skip ahead. */
  376. if (Weight_List[i] < BLACK_LEVEL)
  377. {
  378. continue;
  379. }
  380. Texture = Texture_List[i];
  381. do_texture_map(C1, Texture, IPoint, Raw_Normal, Ray, Weight, Ray_Intersection, FALSE);
  382. Colour[RED] += Weight_List[i] * C1[RED];
  383. Colour[GREEN] += Weight_List[i] * C1[GREEN];
  384. Colour[BLUE] += Weight_List[i] * C1[BLUE];
  385. /* Use transmittance value for alpha channel support. [DB] */
  386. /*
  387. Colour[TRANSM] += Weight_List[i] * C1[TRANSM];
  388. */
  389. Colour[TRANSM] *= C1[TRANSM];
  390. }
  391. /* Restore the light list to its original form */
  392. if (savelights_size > 0)
  393. {
  394. memcpy(Light_List, savelights, savelights_size);
  395. POV_FREE(savelights);
  396. }
  397. /* Restore the weight and texture list. */
  398. if (save_tw_size > 0)
  399. {
  400. memcpy(Weight_List, save_Weights, save_tw_size * sizeof(DBL));
  401. memcpy(Texture_List, save_Textures, save_tw_size * sizeof(TEXTURE *));
  402. POV_FREE(save_Weights);
  403. POV_FREE(save_Textures);
  404. }
  405. }
  406. /*****************************************************************************
  407. *
  408. * FUNCTION
  409. *
  410. * Test_Shadow
  411. *
  412. * INPUT
  413. *
  414. * Light - Light source
  415. * P - Point to test
  416. *
  417. * OUTPUT
  418. *
  419. * Depth - Distance to light source
  420. * Light_Source_Ray - Light ray pointing towards the light source
  421. * Eye_Ray - Current viewing ray
  422. * Colour - Light color reaching point P
  423. *
  424. * RETURNS
  425. *
  426. * int - TRUE if point lies in shadow
  427. *
  428. * AUTHOR
  429. *
  430. * Dieter Bayer
  431. *
  432. * DESCRIPTION
  433. *
  434. * Test if a given point is in shadow in respect to the given light source.
  435. *
  436. * The viewing ray is used to initialize the ray containers of the
  437. * light source ray.
  438. *
  439. * CHANGES
  440. *
  441. * Nov 1994 : Creation.
  442. *
  443. ******************************************************************************/
  444. int Test_Shadow(LIGHT_SOURCE *Light, DBL *Depth, RAY *Light_Source_Ray, RAY *Eye_Ray, VECTOR P, COLOUR Colour)
  445. {
  446. do_light(Light, Depth, Light_Source_Ray, Eye_Ray, P, Colour);
  447. /*
  448. * There's no need to test for shadows if no light
  449. * is coming from the light source.
  450. */
  451. if ((Colour[X] < BLACK_LEVEL) && (Colour[Y] < BLACK_LEVEL) && (Colour[Z] < BLACK_LEVEL))
  452. {
  453. return(TRUE);
  454. }
  455. else
  456. {
  457. /* Test for shadows. */
  458. if ((opts.Quality_Flags & Q_SHADOW) && (Light->Light_Type != FILL_LIGHT_SOURCE))
  459. {
  460. block_light_source(Light, *Depth, Light_Source_Ray, Eye_Ray, P, Colour);
  461. if ((Colour[X] < BLACK_LEVEL) && (Colour[Y] < BLACK_LEVEL) && (Colour[Z] < BLACK_LEVEL))
  462. {
  463. return(TRUE);
  464. }
  465. }
  466. }
  467. return(FALSE);
  468. }
  469. /*****************************************************************************
  470. *
  471. * FUNCTION
  472. *
  473. * block_point_light_LBuffer
  474. *
  475. * INPUT
  476. *
  477. * Light_Source - Light source to test
  478. *
  479. * OUTPUT
  480. *
  481. * Light_Source_Depth - (Remaining) distance to the light source
  482. * Light_Source_Ray - (Remaining) ray to the light source
  483. * Colour - Color reaching initial point from light source
  484. *
  485. * RETURNS
  486. *
  487. * AUTHOR
  488. *
  489. * Dieter Bayer
  490. *
  491. * DESCRIPTION
  492. *
  493. * Determine how much light from the given light source arrives at the
  494. * given point (starting point of the light source ray). The light
  495. * is blocked by solid objects and/or attenuated by translucent objects.
  496. *
  497. * Note that both the distance to the light source and the light source
  498. * ray are modified. Thus after a call to this function one knows
  499. * how much distance remains to the light source and where the last
  500. * intersection point with a translucent object was (starting point
  501. * of light source ray after the call).
  502. *
  503. * This function uses the light buffer to speed up shadow calculation.
  504. *
  505. * CHANGES
  506. *
  507. * Jul 1994 : Creation.
  508. *
  509. ******************************************************************************/
  510. static void block_point_light_LBuffer(LIGHT_SOURCE *Light_Source, DBL *Light_Source_Depth, RAY *Light_Source_Ray, COLOUR Light_Colour)
  511. {
  512. int Quit_Looking, Not_Found_Shadow, Cache_Me;
  513. int u, v, axis;
  514. DBL ax, ay, az;
  515. VECTOR V1;
  516. OBJECT *Blocking_Object;
  517. ISTACK *Local_Stack;
  518. INTERSECTION *Local_Intersection, Bounded_Intersection;
  519. Local_Stack = open_istack();
  520. Quit_Looking = FALSE;
  521. /* First test the cached object (don't cache semi-transparent objects). */
  522. if (Light_Source->Shadow_Cached_Object != NULL)
  523. {
  524. Increase_Counter(stats[Shadow_Ray_Tests]);
  525. if (Ray_In_Bound(Light_Source_Ray, Light_Source->Shadow_Cached_Object->Bound))
  526. {
  527. if (All_Intersections(Light_Source->Shadow_Cached_Object, Light_Source_Ray, Local_Stack))
  528. {
  529. while ((Local_Intersection=pop_entry(Local_Stack)) != NULL)
  530. {
  531. if ((!Test_Flag(Local_Intersection->Object, NO_SHADOW_FLAG)) &&
  532. (Local_Intersection->Depth < *Light_Source_Depth-SHADOW_TOLERANCE) &&
  533. (Local_Intersection->Depth > SHADOW_TOLERANCE))
  534. {
  535. if (do_blocking(Local_Intersection, Light_Source_Ray, Light_Colour, Local_Stack))
  536. {
  537. Quit_Looking = TRUE;
  538. Increase_Counter(stats[Shadow_Cache_Hits]);
  539. break;
  540. }
  541. }
  542. }
  543. }
  544. }
  545. /* Exit if the cached object was hit. */
  546. if (Quit_Looking)
  547. {
  548. close_istack(Local_Stack);
  549. return;
  550. }
  551. }
  552. /*
  553. * Determine the side and the coordinates at which the ray
  554. * pierces the cube enclosing the light source.
  555. */
  556. V1[X] = -Light_Source_Ray->Direction[X];
  557. V1[Y] = -Light_Source_Ray->Direction[Y];
  558. V1[Z] = -Light_Source_Ray->Direction[Z];
  559. ax = fabs(V1[X]);
  560. ay = fabs(V1[Y]);
  561. az = fabs(V1[Z]);
  562. if ((ax>ay) && (ax>az))
  563. {
  564. if (V1[X]>0.0)
  565. {
  566. axis = XaxisP;
  567. }
  568. else
  569. {
  570. axis = XaxisM;
  571. }
  572. u = (int)(MAX_BUFFER_ENTRY * V1[Y]/ax);
  573. v = (int)(MAX_BUFFER_ENTRY * V1[Z]/ax);
  574. }
  575. else
  576. {
  577. if (ay>az)
  578. {
  579. if (V1[Y]>0.0)
  580. {
  581. axis = YaxisP;
  582. }
  583. else
  584. {
  585. axis = YaxisM;
  586. }
  587. u = (int)(MAX_BUFFER_ENTRY * V1[X]/ay);
  588. v = (int)(MAX_BUFFER_ENTRY * V1[Z]/ay);
  589. }
  590. else
  591. {
  592. if (V1[Z]>0.0)
  593. {
  594. axis = ZaxisP;
  595. }
  596. else
  597. {
  598. axis = ZaxisM;
  599. }
  600. u = (int)(MAX_BUFFER_ENTRY * V1[X]/az);
  601. v = (int)(MAX_BUFFER_ENTRY * V1[Y]/az);
  602. }
  603. }
  604. /* If there are no objects in the direction of the ray we can exit. */
  605. if (Light_Source->Light_Buffer[axis] == NULL)
  606. {
  607. close_istack(Local_Stack);
  608. return;
  609. }
  610. /* Look for shadows. */
  611. Not_Found_Shadow = TRUE;
  612. Cache_Me = FALSE;
  613. while (!Quit_Looking)
  614. {
  615. Increase_Counter(stats[Shadow_Ray_Tests]);
  616. Bounded_Intersection.Depth = *Light_Source_Depth;
  617. if (Intersect_Light_Tree(Light_Source_Ray, Light_Source->Light_Buffer[axis], u, v, &Bounded_Intersection, &Blocking_Object))
  618. {
  619. if (Bounded_Intersection.Depth > *Light_Source_Depth)
  620. {
  621. /* Intersection was beyond the light. */
  622. break;
  623. }
  624. if (!Test_Flag(Bounded_Intersection.Object, NO_SHADOW_FLAG))
  625. {
  626. if (Blocking_Object != Light_Source->Shadow_Cached_Object)
  627. {
  628. Increase_Counter(stats[Shadow_Rays_Succeeded]);
  629. filter_shadow_ray(&Bounded_Intersection, Light_Source_Ray, Light_Colour);
  630. if ((fabs(Light_Colour[RED]) < BLACK_LEVEL) &&
  631. (fabs(Light_Colour[GREEN]) < BLACK_LEVEL) &&
  632. (fabs(Light_Colour[BLUE]) < BLACK_LEVEL) &&
  633. (Test_Flag(Blocking_Object, OPAQUE_FLAG)))
  634. {
  635. Cache_Me = Not_Found_Shadow;
  636. break; /* from while */
  637. }
  638. }
  639. }
  640. /* Move the ray to the point of intersection, plus some */
  641. *Light_Source_Depth -= Bounded_Intersection.Depth;
  642. Assign_Vector(Light_Source_Ray->Initial, Bounded_Intersection.IPoint);
  643. Not_Found_Shadow = FALSE;
  644. }
  645. else
  646. {
  647. /* No intersections in the direction of the ray. */
  648. break;
  649. }
  650. }
  651. if (Cache_Me)
  652. {
  653. Light_Source->Shadow_Cached_Object = Blocking_Object;
  654. }
  655. close_istack(Local_Stack);
  656. }
  657. /*****************************************************************************
  658. *
  659. * FUNCTION
  660. *
  661. * block_point_light
  662. *
  663. * INPUT
  664. *
  665. * Light_Source - Light source to test
  666. * Eye_Ray - Current viewing ray
  667. *
  668. * OUTPUT
  669. *
  670. * Light_Source_Depth - (Remaining) distance to the light source
  671. * Light_Source_Ray - (Remaining) ray to the light source
  672. * Colour - Color reaching initial point from light source
  673. *
  674. * RETURNS
  675. *
  676. * AUTHOR
  677. *
  678. * POV-Ray Team
  679. *
  680. * DESCRIPTION
  681. *
  682. * See block_point_light_LBuffer for a description.
  683. *
  684. * This function uses the hierarchical bounding box volume to
  685. * speed up shadow testing.
  686. *
  687. * CHANGES
  688. *
  689. * -
  690. *
  691. ******************************************************************************/
  692. static void block_point_light (LIGHT_SOURCE *Light_Source, DBL *Light_Source_Depth, RAY *Light_Source_Ray, COLOUR Light_Colour)
  693. {
  694. OBJECT *Blocking_Object;
  695. int Quit_Looking, Not_Found_Shadow, Cache_Me, Maybe_Found;
  696. INTERSECTION *Local_Intersection, Bounded_Intersection, Temp_Intersection;
  697. ISTACK *Local_Stack;
  698. Local_Stack = open_istack ();
  699. Quit_Looking = FALSE;
  700. /* First test the cached object (don't cache semi-transparent objects). */
  701. if (Light_Source->Shadow_Cached_Object != NULL)
  702. {
  703. Increase_Counter(stats[Shadow_Ray_Tests]);
  704. if (Ray_In_Bound(Light_Source_Ray, Light_Source->Shadow_Cached_Object->Bound))
  705. {
  706. if (All_Intersections(Light_Source->Shadow_Cached_Object, Light_Source_Ray, Local_Stack))
  707. {
  708. while ((Local_Intersection = pop_entry(Local_Stack)) != NULL)
  709. {
  710. if ((!Test_Flag(Local_Intersection->Object, NO_SHADOW_FLAG)) &&
  711. (Local_Intersection->Depth < *Light_Source_Depth-SHADOW_TOLERANCE) &&
  712. (Local_Intersection->Depth > SHADOW_TOLERANCE))
  713. {
  714. if (do_blocking(Local_Intersection, Light_Source_Ray, Light_Colour, Local_Stack))
  715. {
  716. Quit_Looking = TRUE;
  717. Increase_Counter(stats[Shadow_Cache_Hits]);
  718. break;
  719. }
  720. }
  721. }
  722. }
  723. }
  724. if (Quit_Looking)
  725. {
  726. close_istack (Local_Stack);
  727. return;
  728. }
  729. }
  730. /* Look for shadows. */
  731. Not_Found_Shadow = TRUE;
  732. Cache_Me = FALSE;
  733. if (!opts.Use_Slabs)
  734. {
  735. while (!Quit_Looking)
  736. {
  737. /* Use brute force method to get shadows. */
  738. Maybe_Found = FALSE;
  739. Bounded_Intersection.Depth = *Light_Source_Depth;
  740. for (Blocking_Object = Frame.Objects; Blocking_Object != NULL; Blocking_Object = Blocking_Object->Sibling)
  741. {
  742. if (Blocking_Object != Light_Source->Shadow_Cached_Object)
  743. {
  744. if (!Test_Flag(Blocking_Object, NO_SHADOW_FLAG))
  745. {
  746. Increase_Counter(stats[Shadow_Ray_Tests]);
  747. if (Intersection(&Temp_Intersection, Blocking_Object, Light_Source_Ray))
  748. {
  749. if (Temp_Intersection.Depth < Bounded_Intersection.Depth)
  750. {
  751. Maybe_Found = TRUE;
  752. Bounded_Intersection = Temp_Intersection;
  753. }
  754. }
  755. }
  756. }
  757. }
  758. if (Maybe_Found)
  759. {
  760. Increase_Counter(stats[Shadow_Rays_Succeeded]);
  761. filter_shadow_ray(&Bounded_Intersection, Light_Source_Ray, Light_Colour);
  762. if ((fabs(Light_Colour[RED]) < BLACK_LEVEL) &&
  763. (fabs(Light_Colour[GREEN]) < BLACK_LEVEL) &&
  764. (fabs(Light_Colour[BLUE]) < BLACK_LEVEL) &&
  765. (Test_Flag(Bounded_Intersection.Object, OPAQUE_FLAG)))
  766. {
  767. Cache_Me = Not_Found_Shadow;
  768. break;
  769. }
  770. /* Move the ray to the point of intersection, plus some */
  771. *Light_Source_Depth -= Bounded_Intersection.Depth;
  772. Assign_Vector(Light_Source_Ray->Initial, Bounded_Intersection.IPoint);
  773. Not_Found_Shadow = FALSE;
  774. }
  775. else
  776. {
  777. /* No intersections in the direction of the ray. */
  778. break;
  779. }
  780. }
  781. }
  782. else
  783. {
  784. /* Use bounding slabs to look for shadows. */
  785. while (!Quit_Looking)
  786. {
  787. Increase_Counter(stats[Shadow_Ray_Tests]);
  788. Bounded_Intersection.Depth = *Light_Source_Depth;
  789. if (Intersect_BBox_Tree(Root_Object, Light_Source_Ray, &Bounded_Intersection, &Blocking_Object))
  790. {
  791. if (Bounded_Intersection.Depth > *Light_Source_Depth)
  792. {
  793. /* Intersection was beyond the light. */
  794. break;
  795. }
  796. if (!Test_Flag(Bounded_Intersection.Object, NO_SHADOW_FLAG))
  797. {
  798. if (Blocking_Object != Light_Source->Shadow_Cached_Object)
  799. {
  800. Increase_Counter(stats[Shadow_Rays_Succeeded]);
  801. filter_shadow_ray(&Bounded_Intersection, Light_Source_Ray, Light_Colour);
  802. if ((fabs(Light_Colour[RED]) < BLACK_LEVEL) &&
  803. (fabs(Light_Colour[GREEN]) < BLACK_LEVEL) &&
  804. (fabs(Light_Colour[BLUE]) < BLACK_LEVEL) &&
  805. (Test_Flag(Blocking_Object, OPAQUE_FLAG)))
  806. {
  807. Cache_Me = Not_Found_Shadow;
  808. break; /* from while */
  809. }
  810. }
  811. }
  812. /* Move the ray to the point of intersection, plus some */
  813. *Light_Source_Depth -= Bounded_Intersection.Depth;
  814. Assign_Vector(Light_Source_Ray->Initial, Bounded_Intersection.IPoint);
  815. Not_Found_Shadow = FALSE;
  816. }
  817. else
  818. {
  819. /* No intersections in the direction of the ray */
  820. break;
  821. }
  822. }
  823. }
  824. if (Cache_Me)
  825. {
  826. Light_Source->Shadow_Cached_Object = Blocking_Object;
  827. }
  828. close_istack (Local_Stack);
  829. }
  830. /*****************************************************************************
  831. *
  832. * FUNCTION
  833. *
  834. * block_area_light
  835. *
  836. * INPUT
  837. *
  838. * Light_Source - Light source to test
  839. * IPoint -
  840. * u1, v1, u2, v2 -
  841. * Level -
  842. *
  843. * OUTPUT
  844. *
  845. * Light_Source_Depth - (Remaining) distance to the light source
  846. * Light_Source_Ray - (Remaining) ray to the light source
  847. * Light_Colour - Color reaching initial point from light source
  848. *
  849. * RETURNS
  850. *
  851. * AUTHOR
  852. *
  853. * POV-Ray Team
  854. *
  855. * DESCRIPTION
  856. *
  857. * Get shadow for given area light source by recursively sampling
  858. * on the light source area.
  859. *
  860. * The viewing ray is used to initialize the ray containers of the
  861. * light source ray.
  862. *
  863. * CHANGES
  864. *
  865. * -
  866. *
  867. ******************************************************************************/
  868. static void block_area_light (LIGHT_SOURCE *Light_Source, DBL *Light_Source_Depth,
  869. RAY *Light_Source_Ray, RAY *Eye_Ray, VECTOR IPoint, COLOUR Light_Colour, int u1, int v1, int u2, int v2, int Level)
  870. {
  871. COLOUR Sample_Colour[4], Dummy_Colour;
  872. VECTOR Center_Save, NewAxis1, NewAxis2;
  873. int i, j, u, v, New_u1, New_v1, New_u2, New_v2;
  874. DBL Jitter_u, Jitter_v, ScaleFactor;
  875. /* First call, initialize */
  876. if ((u1 == 0) && (v1 == 0) && (u2 == 0) && (v2 == 0))
  877. {
  878. /* Flag uncalculated points with a negative value for Red */
  879. for (i = 0; i < Light_Source->Area_Size1; i++)
  880. {
  881. for (j = 0; j < Light_Source->Area_Size2; j++)
  882. {
  883. Light_Source->Light_Grid[i][j][RED] = -1.0;
  884. }
  885. }
  886. u1 = 0;
  887. v1 = 0;
  888. u2 = Light_Source->Area_Size1 - 1;
  889. v2 = Light_Source->Area_Size2 - 1;
  890. }
  891. /* Save the light source center since we'll be fiddling with it */
  892. Assign_Vector(Center_Save,Light_Source->Center);
  893. /* Sample the four corners of the region */
  894. for (i = 0; i < 4; i++)
  895. {
  896. switch (i)
  897. {
  898. case 0: u = u1; v = v1; break;
  899. case 1: u = u2; v = v1; break;
  900. case 2: u = u1; v = v2; break;
  901. case 3: u = u2; v = v2; break;
  902. default: u = v = 0; /* Should never happen! */
  903. }
  904. if (Light_Source->Light_Grid[u][v][RED] >= 0.0)
  905. {
  906. /* We've already calculated this point, reuse it */
  907. Assign_Colour(Sample_Colour[i],Light_Source->Light_Grid[u][v]);
  908. }
  909. else
  910. {
  911. Jitter_u = (DBL)u;
  912. Jitter_v = (DBL)v;
  913. if (Light_Source->Jitter)
  914. {
  915. Jitter_u += FRAND() - 0.5;
  916. Jitter_v += FRAND() - 0.5;
  917. }
  918. if (Light_Source->Area_Size1 > 1)
  919. {
  920. ScaleFactor = Jitter_u/(DBL)(Light_Source->Area_Size1 - 1) - 0.5;
  921. VScale (NewAxis1, Light_Source->Axis1, ScaleFactor)
  922. }
  923. else
  924. {
  925. Make_Vector(NewAxis1, 0.0, 0.0, 0.0);
  926. }
  927. if (Light_Source->Area_Size2 > 1)
  928. {
  929. ScaleFactor = Jitter_v/(DBL)(Light_Source->Area_Size2 - 1) - 0.5;
  930. VScale (NewAxis2, Light_Source->Axis2, ScaleFactor)
  931. }
  932. else
  933. {
  934. Make_Vector(NewAxis2, 0.0, 0.0, 0.0);
  935. }
  936. Assign_Vector(Light_Source->Center, Center_Save);
  937. VAddEq(Light_Source->Center, NewAxis1);
  938. VAddEq(Light_Source->Center, NewAxis2);
  939. /* Recalculate the light source ray but not the colour */
  940. do_light(Light_Source, Light_Source_Depth, Light_Source_Ray, Eye_Ray, IPoint, Dummy_Colour);
  941. Assign_Colour(Sample_Colour[i], Light_Colour);
  942. block_point_light(Light_Source, Light_Source_Depth, Light_Source_Ray, Sample_Colour[i]);
  943. Assign_Colour(Light_Source->Light_Grid[u][v], Sample_Colour[i]);
  944. }
  945. }
  946. Assign_Vector(Light_Source->Center,Center_Save);
  947. if ((u2 - u1 > 1) || (v2 - v1 > 1))
  948. {
  949. if ((Level < Light_Source->Adaptive_Level) ||
  950. (Colour_Distance(Sample_Colour[0], Sample_Colour[1]) > 0.1) ||
  951. (Colour_Distance(Sample_Colour[1], Sample_Colour[3]) > 0.1) ||
  952. (Colour_Distance(Sample_Colour[3], Sample_Colour[2]) > 0.1) ||
  953. (Colour_Distance(Sample_Colour[2], Sample_Colour[0]) > 0.1))
  954. {
  955. for (i = 0; i < 4; i++)
  956. {
  957. switch (i)
  958. {
  959. case 0:
  960. New_u1 = u1;
  961. New_v1 = v1;
  962. New_u2 = (int)floor ((u1 + u2)/2.0);
  963. New_v2 = (int)floor ((v1 + v2)/2.0);
  964. break;
  965. case 1:
  966. New_u1 = (int)ceil ((u1 + u2)/2.0);
  967. New_v1 = v1;
  968. New_u2 = u2;
  969. New_v2 = (int)floor ((v1 + v2)/2.0);
  970. break;
  971. case 2:
  972. New_u1 = u1;
  973. New_v1 = (int)ceil ((v1 + v2)/2.0);
  974. New_u2 = (int)floor ((u1 + u2)/2.0);
  975. New_v2 = v2;
  976. break;
  977. case 3:
  978. New_u1 = (int)ceil ((u1 + u2)/2.0);
  979. New_v1 = (int)ceil ((v1 + v2)/2.0);
  980. New_u2 = u2;
  981. New_v2 = v2;
  982. break;
  983. default: /* Should never happen! */
  984. New_u1 = New_u2 = New_v1 = New_v2 = 0;
  985. }
  986. /* Recalculate the light source ray but not the colour */
  987. do_light(Light_Source, Light_Source_Depth, Light_Source_Ray, Eye_Ray, IPoint, Dummy_Colour);
  988. Assign_Colour(Sample_Colour[i],Light_Colour);
  989. block_area_light (Light_Source, Light_Source_Depth, Light_Source_Ray, Eye_Ray,
  990. IPoint, Sample_Colour[i], New_u1, New_v1, New_u2, New_v2, Level+1);
  991. }
  992. }
  993. }
  994. /* Add up the light contributions */
  995. Make_Colour (Light_Colour, 0.0, 0.0, 0.0);
  996. for (i = 0; i < 4; i++)
  997. {
  998. Scale_Colour (Sample_Colour[i], Sample_Colour[i], 0.25);
  999. Add_Colour (Light_Colour, Light_Colour, Sample_Colour[i]);
  1000. }
  1001. }
  1002. /*****************************************************************************
  1003. *
  1004. * FUNCTION
  1005. *
  1006. * do_light
  1007. *
  1008. * INPUT
  1009. *
  1010. * Light_Source - Light source
  1011. * Light_Source_Depth - Distance from surface to light source
  1012. * Light_Source_Ray - Ray from surface to light source
  1013. * Eye_Ray - Current viewing ray
  1014. * IPoint - Intersection point in surface
  1015. * Colour - Light's colour
  1016. *
  1017. * OUTPUT
  1018. *
  1019. * Light_Source_Depth, Light_Source_Ray, Colour
  1020. *
  1021. * RETURNS
  1022. *
  1023. * AUTHOR
  1024. *
  1025. * POV-Ray Team
  1026. *
  1027. * DESCRIPTION
  1028. *
  1029. * The viewing ray is used to initialize the ray containers of the
  1030. * light source ray.
  1031. *
  1032. * CHANGES
  1033. *
  1034. * -
  1035. *
  1036. ******************************************************************************/
  1037. static void do_light(LIGHT_SOURCE *Light_Source, DBL *Light_Source_Depth, RAY *Light_Source_Ray, RAY *Eye_Ray, VECTOR IPoint, COLOUR Light_Colour)
  1038. {
  1039. DBL Attenuation;
  1040. /* Get the light source colour. */
  1041. Assign_Colour(Light_Colour, Light_Source->Colour);
  1042. /*
  1043. * Get the light ray starting at the intersection point and pointing
  1044. * towards the light source.
  1045. */
  1046. Assign_Vector(Light_Source_Ray->Initial, IPoint);
  1047. VSub(Light_Source_Ray->Direction,Light_Source->Center, IPoint);
  1048. VLength(*Light_Source_Depth, Light_Source_Ray->Direction);
  1049. VInverseScaleEq(Light_Source_Ray->Direction, *Light_Source_Depth);
  1050. /* Attenuate light source color. */
  1051. Attenuation = Attenuate_Light(Light_Source, Light_Source_Ray, *Light_Source_Depth);
  1052. /* Now scale the color by the attenuation */
  1053. VScaleEq(Light_Colour, Attenuation);
  1054. /* Init ray containers. */
  1055. Initialize_Ray_Containers(Light_Source_Ray);
  1056. Copy_Ray_Containers(Light_Source_Ray, Eye_Ray);
  1057. }
  1058. /*****************************************************************************
  1059. *
  1060. * FUNCTION
  1061. *
  1062. * do_diffuse
  1063. *
  1064. * INPUT
  1065. *
  1066. * OUTPUT
  1067. *
  1068. * RETURNS
  1069. *
  1070. * AUTHOR
  1071. *
  1072. * POV-Ray Team
  1073. *
  1074. * DESCRIPTION
  1075. *
  1076. * Calculate the diffuse color component I_d given by:
  1077. *
  1078. * I_d = a * d * I * C * (N . L) ^ b
  1079. *
  1080. * where d : surface's diffuse reflection coefficient
  1081. * b : surface's brilliance
  1082. * C : surface's color
  1083. * N : surface's normal vector
  1084. * L : light vector (pointing at the light)
  1085. * I : intensity of the incoming light
  1086. * a : attenuation factor
  1087. *
  1088. * CHANGES
  1089. *
  1090. * -
  1091. *
  1092. ******************************************************************************/
  1093. static void do_diffuse(FINISH *Finish, RAY *Light_Source_Ray, VECTOR Layer_Normal, COLOUR Colour, COLOUR Light_Colour, COLOUR Layer_Pigment_Colour, DBL Attenuation)
  1094. {
  1095. DBL Cos_Angle_Of_Incidence, Intensity;
  1096. VDot(Cos_Angle_Of_Incidence, Layer_Normal, Light_Source_Ray->Direction);
  1097. /* Brilliance is likely to be 1.0 (default value) */
  1098. if (Finish->Brilliance != 1.0)
  1099. {
  1100. Intensity = pow(fabs(Cos_Angle_Of_Incidence), Finish->Brilliance);
  1101. }
  1102. else
  1103. {
  1104. Intensity = fabs(Cos_Angle_Of_Incidence);
  1105. }
  1106. Intensity *= Finish->Diffuse * Attenuation;
  1107. if (Finish->Crand > 0.0)
  1108. {
  1109. Intensity -= FRAND() * Finish->Crand;
  1110. }
  1111. Colour[RED] += Intensity * Layer_Pigment_Colour[RED] * Light_Colour[RED];
  1112. Colour[GREEN] += Intensity * Layer_Pigment_Colour[GREEN] * Light_Colour[GREEN];
  1113. Colour[BLUE] += Intensity * Layer_Pigment_Colour[BLUE] * Light_Colour[BLUE];
  1114. }
  1115. /*****************************************************************************
  1116. *
  1117. * FUNCTION
  1118. *
  1119. * do_irid
  1120. *
  1121. * INPUT
  1122. *
  1123. * OUTPUT
  1124. *
  1125. * RETURNS
  1126. *
  1127. * AUTHOR
  1128. *
  1129. * Dan Farmer
  1130. *
  1131. * DESCRIPTION
  1132. *
  1133. * IRIDESCENCE:
  1134. * -----------
  1135. * Programmed by Dan Farmer.
  1136. *
  1137. * Based on Chapter 10.2.4 of Three-Dimensional Computer Graphics
  1138. * by Alan Watt.
  1139. *
  1140. * Modulates the diffuse coefficients as a function of wavelength, the angle
  1141. * between the light direction vector, and the surface normal. It models
  1142. * thin-film interference, as in a soap bubble or oilslick.
  1143. *
  1144. * Wavelength at which cancellation offurs is a function of the refractive
  1145. * index of the film, its thickness, and the angle of incidence of the
  1146. * incoming light. In this implementation, IOR is kept constant, while the
  1147. * thickness of the film is specified, as well as being modulated with a
  1148. * turbulence function.
  1149. *
  1150. * CHANGES
  1151. *
  1152. * -
  1153. *
  1154. ******************************************************************************/
  1155. static void do_irid(FINISH *Finish, RAY *Light_Source_Ray, VECTOR Layer_Normal, VECTOR IPoint, COLOUR Colour)
  1156. {
  1157. DBL rwl, gwl, bwl;
  1158. DBL Cos_Angle_Of_Incidence, interference;
  1159. DBL film_thickness;
  1160. DBL noise, intensity;
  1161. TURB Turb;
  1162. film_thickness = Finish->Irid_Film_Thickness;
  1163. if (Finish->Irid_Turb != 0)
  1164. {
  1165. /* Uses hardcoded octaves, lambda, omega */
  1166. Turb.Omega=0.5;
  1167. Turb.Lambda=2.0;
  1168. Turb.Octaves=5;
  1169. noise = Turbulence(IPoint, &Turb) * Finish->Irid_Turb;
  1170. film_thickness *= noise;
  1171. }
  1172. /*
  1173. * Approximate dominant wavelengths of primary hues.
  1174. * Source: 3D Computer Graphics by John Vince (Addison Wesely)
  1175. * These are initialized in parse.c (Parse_Frame)
  1176. * and are user-adjustable with the irid_wavelength keyword.
  1177. * Red = 700 nm Grn = 520 nm Blu = 480 nm
  1178. * Divided by 100 gives: rwl = 0.70; gwl = 0.52; bwl = 0.48;
  1179. *
  1180. * However... I originally "guessed" at the values and came up with
  1181. * the following, which I'm using as the defaults, since it seems
  1182. * to work better: rwl = 0.25; gwl = 0.18; bwl = 0.14;
  1183. */
  1184. /* Could avoid these assignments if we want to */
  1185. rwl = Frame.Irid_Wavelengths[RED];
  1186. gwl = Frame.Irid_Wavelengths[GREEN];
  1187. bwl = Frame.Irid_Wavelengths[BLUE];
  1188. /* NOTE: Shouldn't we compute Cos_Angle_Of_Incidence just once? */
  1189. VDot(Cos_Angle_Of_Incidence, Layer_Normal, Light_Source_Ray->Direction);
  1190. /* Calculate phase offset. */
  1191. interference = 4.0 * M_PI * film_thickness * Cos_Angle_Of_Incidence;
  1192. intensity = Cos_Angle_Of_Incidence * Finish->Irid;
  1193. /* Modify color by phase offset for each wavelength. */
  1194. Colour[RED] += Finish->Irid * (intensity * (1.0 - 0.5 * cos(interference/rwl)));
  1195. Colour[GREEN]+= Finish->Irid * (intensity * (1.0 - 0.5 * cos(interference/gwl)));
  1196. Colour[BLUE] += Finish->Irid * (intensity * (1.0 - 0.5 * cos(interference/bwl)));
  1197. }
  1198. /*****************************************************************************
  1199. *
  1200. * FUNCTION
  1201. *
  1202. * do_phong
  1203. *
  1204. * INPUT
  1205. *
  1206. * OUTPUT
  1207. *
  1208. * RETURNS
  1209. *
  1210. * AUTHOR
  1211. *
  1212. * POV-Ray Team
  1213. *
  1214. * DESCRIPTION
  1215. *
  1216. * Calculate the phong reflected color component I_p given by:
  1217. *
  1218. * I_p = p * C * (R . L) ^ s
  1219. *
  1220. * where p : surface's phong reflection coefficient
  1221. * s : surface's phong size
  1222. * C : surface's color/light color depending on the metallic flag
  1223. * R : reflection vector
  1224. * L : light vector (pointing at the light)
  1225. *
  1226. * The reflection vector is calculated from the surface normal and
  1227. * the viewing vector (looking at the surface point):
  1228. *
  1229. * R = -2 * (V . N) * N + V, with R . R = 1
  1230. *
  1231. * CHANGES
  1232. *
  1233. * Sep 1994 : Added improved color calculation for metallic surfaces. [DB]
  1234. *
  1235. ******************************************************************************/
  1236. static void do_phong(FINISH *Finish, RAY *Light_Source_Ray, VECTOR Eye, VECTOR Layer_Normal, COLOUR Colour, COLOUR Light_Colour, COLOUR Layer_Pigment_Colour)
  1237. {
  1238. DBL Cos_Angle_Of_Incidence, Intensity;
  1239. VECTOR Reflect_Direction;
  1240. DBL NdotL, x, F;
  1241. COLOUR Cs;
  1242. VDot(Cos_Angle_Of_Incidence, Eye, Layer_Normal);
  1243. Cos_Angle_Of_Incidence *= -2.0;
  1244. VLinComb2(Reflect_Direction, 1.0, Eye, Cos_Angle_Of_Incidence, Layer_Normal);
  1245. VDot(Cos_Angle_Of_Incidence, Reflect_Direction, Light_Source_Ray->Direction);
  1246. if (Cos_Angle_Of_Incidence > 0.0)
  1247. {
  1248. if ((Finish->Phong_Size < 60) || (Cos_Angle_Of_Incidence > .0008)) /* rgs */
  1249. Intensity = Finish->Phong * pow(Cos_Angle_Of_Incidence, Finish->Phong_Size);
  1250. else
  1251. Intensity = 0.0; /* ad */
  1252. if (Finish->Metallic > 0.0)
  1253. {
  1254. /*
  1255. * Calculate the reflected color by interpolating between
  1256. * the light source color and the surface color according
  1257. * to the (empirical) Fresnel reflectivity function. [DB 9/94]
  1258. */
  1259. VDot(NdotL, Layer_Normal, Light_Source_Ray->Direction);
  1260. x = fabs(acos(NdotL)) / M_PI_2;
  1261. F = 0.014567225 / Sqr(x - 1.12) - 0.011612903;
  1262. Cs[RED] = Light_Colour[RED] * (1.0 + Finish->Metallic * (1.0 - F) * (Layer_Pigment_Colour[RED] - 1.0));
  1263. Cs[GREEN] = Light_Colour[GREEN] * (1.0 + Finish->Metallic * (1.0 - F) * (Layer_Pigment_Colour[GREEN] - 1.0));
  1264. Cs[BLUE] = Light_Colour[BLUE] * (1.0 + Finish->Metallic * (1.0 - F) * (Layer_Pigment_Colour[BLUE] - 1.0));
  1265. VAddScaledEq(Colour, Intensity, Cs);
  1266. }
  1267. else
  1268. {
  1269. Colour[RED] += Intensity * Light_Colour[RED];
  1270. Colour[GREEN] += Intensity * Light_Colour[GREEN];
  1271. Colour[BLUE] += Intensity * Light_Colour[BLUE];
  1272. }
  1273. }
  1274. }
  1275. /*****************************************************************************
  1276. *
  1277. * FUNCTION
  1278. *
  1279. * do_specular
  1280. *
  1281. * INPUT
  1282. *
  1283. * OUTPUT
  1284. *
  1285. * INPUT
  1286. *
  1287. * OUTPUT
  1288. *
  1289. * RETURNS
  1290. *
  1291. * AUTHOR
  1292. *
  1293. * POV-Ray Team
  1294. *
  1295. * DESCRIPTION
  1296. *
  1297. * Calculate the specular reflected color component I_s given by:
  1298. *
  1299. * I_s = s * C * (H . N) ^ (1 / r)
  1300. *
  1301. * where s : surface's specular reflection coefficient
  1302. * r : surface's roughness
  1303. * C : surface's color/light color depending on the metallic flag
  1304. * N : surface's normal
  1305. * H : bisection vector between V and L
  1306. *
  1307. * The bisecting vector H is calculated by
  1308. *
  1309. * H = (L - V) / sqrt((L - V).(L - V))
  1310. *
  1311. * CHANGES
  1312. *
  1313. * Sep 1994 : Added improved color calculation for metallic surfaces. [DB]
  1314. *
  1315. ******************************************************************************/
  1316. static void do_specular(FINISH *Finish, RAY *Light_Source_Ray, VECTOR REye, VECTOR Layer_Normal, COLOUR Colour, COLOUR Light_Colour, COLOUR Layer_Pigment_Colour)
  1317. {
  1318. DBL Cos_Angle_Of_Incidence, Intensity, Halfway_Length;
  1319. VECTOR Halfway;
  1320. DBL NdotL, x, F;
  1321. COLOUR Cs;
  1322. VHalf(Halfway, REye, Light_Source_Ray->Direction);
  1323. VLength(Halfway_Length, Halfway);
  1324. if (Halfway_Length > 0.0)
  1325. {
  1326. VDot(Cos_Angle_Of_Incidence, Halfway, Layer_Normal);
  1327. Cos_Angle_Of_Incidence /= Halfway_Length;
  1328. if (Cos_Angle_Of_Incidence > 0.0)
  1329. {
  1330. Intensity = Finish->Specular * pow(Cos_Angle_Of_Incidence, Finish->Roughness);
  1331. if (Finish->Metallic > 0.0)
  1332. {
  1333. /*
  1334. * Calculate the reflected color by interpolating between
  1335. * the light source color and the surface color according
  1336. * to the (empirical) Fresnel reflectivity function. [DB 9/94]
  1337. */
  1338. VDot(NdotL, Layer_Normal, Light_Source_Ray->Direction);
  1339. x = fabs(acos(NdotL)) / M_PI_2;
  1340. F = 0.014567225 / Sqr(x - 1.12) - 0.011612903;
  1341. Cs[RED] = Light_Colour[RED] * (1.0 + Finish->Metallic * (1.0 - F) * (Layer_Pigment_Colour[RED] - 1.0));
  1342. Cs[GREEN] = Light_Colour[GREEN] * (1.0 + Finish->Metallic * (1.0 - F) * (Layer_Pigment_Colour[GREEN] - 1.0));
  1343. Cs[BLUE] = Light_Colour[BLUE] * (1.0 + Finish->Metallic * (1.0 - F) * (Layer_Pigment_Colour[BLUE] - 1.0));
  1344. VAddScaledEq(Colour, Intensity, Cs);
  1345. }
  1346. else
  1347. {
  1348. Colour[RED] += Intensity * Light_Colour[RED];
  1349. Colour[GREEN] += Intensity * Light_Colour[GREEN];
  1350. Colour[BLUE] += Intensity * Light_Colour[BLUE];
  1351. }
  1352. }
  1353. }
  1354. }
  1355. /*****************************************************************************
  1356. *
  1357. * FUNCTION
  1358. *
  1359. * Diffuse
  1360. *
  1361. * INPUT
  1362. *
  1363. * OUTPUT
  1364. *
  1365. * RETURNS
  1366. *
  1367. * AUTHOR
  1368. *
  1369. * POV-Ray Team
  1370. *
  1371. * DESCRIPTION
  1372. *
  1373. * -
  1374. *
  1375. * CHANGES
  1376. *
  1377. * -
  1378. *
  1379. ******************************************************************************/
  1380. static void Diffuse (FINISH *Finish, VECTOR IPoint, RAY *Eye, VECTOR Layer_Normal, COLOUR Layer_Pigment_Colour, COLOUR Colour, DBL Attenuation, OBJECT *Object)
  1381. {
  1382. int i;
  1383. DBL Light_Source_Depth, Cos_Shadow_Angle;
  1384. RAY Light_Source_Ray;
  1385. LIGHT_SOURCE *Light_Source;
  1386. VECTOR REye;
  1387. COLOUR Light_Colour;
  1388. if ((Finish->Diffuse == 0.0) && (Finish->Specular == 0.0) && (Finish->Phong == 0.0))
  1389. {
  1390. return;
  1391. }
  1392. if (Finish->Specular != 0.0)
  1393. {
  1394. REye[X] = -Eye->Direction[X];
  1395. REye[Y] = -Eye->Direction[Y];
  1396. REye[Z] = -Eye->Direction[Z];
  1397. }
  1398. for (i = 0, Light_Source = Frame.Light_Sources;
  1399. Light_Source != NULL;
  1400. Light_Source = Light_Source->Next_Light_Source, i++)
  1401. {
  1402. /* Get a colour and a ray. */
  1403. do_light(Light_Source, &Light_Source_Depth, &Light_Source_Ray, Eye, IPoint, Light_Colour);
  1404. /* Don't calculate spotlights when outside of the light's cone. */
  1405. if ((fabs(Light_Colour[RED]) < BLACK_LEVEL) &&
  1406. (fabs(Light_Colour[GREEN]) < BLACK_LEVEL) &&
  1407. (fabs(Light_Colour[BLUE]) < BLACK_LEVEL))
  1408. {
  1409. continue;
  1410. }
  1411. /* See if light on far side of surface from camera. */
  1412. if (!(Object->Type & DOUBLE_ILLUMINATE))
  1413. {
  1414. VDot(Cos_Shadow_Angle, Layer_Normal, Light_Source_Ray.Direction);
  1415. if (Cos_Shadow_Angle < EPSILON)
  1416. {
  1417. continue;
  1418. }
  1419. }
  1420. /*
  1421. * If light source was not blocked by any intervening object, then
  1422. * calculate it's contribution to the object's overall illumination.
  1423. */
  1424. if ((opts.Quality_Flags & Q_SHADOW) && (Light_Source->Light_Type != FILL_LIGHT_SOURCE))
  1425. {
  1426. /* If this surface point has already been tested use previous result. */
  1427. if (Light_List[i].Tested)
  1428. {
  1429. Assign_Colour(Light_Colour, Light_List[i].Colour);
  1430. }
  1431. else
  1432. {
  1433. block_light_source(Light_Source, Light_Source_Depth, &Light_Source_Ray, Eye, IPoint, Light_Colour);
  1434. /* Store light colour. */
  1435. Light_List[i].Tested = TRUE;
  1436. Assign_Colour(Light_List[i].Colour, Light_Colour);
  1437. }
  1438. }
  1439. if ((fabs(Light_Colour[RED]) > BLACK_LEVEL) ||
  1440. (fabs(Light_Colour[GREEN]) > BLACK_LEVEL) ||
  1441. (fabs(Light_Colour[BLUE]) > BLACK_LEVEL))
  1442. {
  1443. if (Finish->Diffuse > 0.0)
  1444. {
  1445. do_diffuse(Finish,&Light_Source_Ray,Layer_Normal,Colour,Light_Colour,Layer_Pigment_Colour, Attenuation);
  1446. }
  1447. if (Light_Source->Light_Type != FILL_LIGHT_SOURCE)
  1448. {
  1449. if (Finish->Phong > 0.0)
  1450. {
  1451. do_phong(Finish,&Light_Source_Ray,Eye->Direction,Layer_Normal,Colour,Light_Colour, Layer_Pigment_Colour);
  1452. }
  1453. if (Finish->Specular > 0.0)
  1454. {
  1455. do_specular(Finish,&Light_Source_Ray,REye,Layer_Normal,Colour,Light_Colour, Layer_Pigment_Colour);
  1456. }
  1457. }
  1458. if (Finish->Irid > 0.0)
  1459. {
  1460. do_irid(Finish,&Light_Source_Ray,Layer_Normal,IPoint,Colour);
  1461. }
  1462. }
  1463. }
  1464. }
  1465. /*****************************************************************************
  1466. *
  1467. * FUNCTION
  1468. *
  1469. * Reflect
  1470. *
  1471. * INPUT
  1472. *
  1473. * OUTPUT
  1474. *
  1475. * RETURNS
  1476. *
  1477. * AUTHOR
  1478. *
  1479. * POV-Ray Team
  1480. *
  1481. * DESCRIPTION
  1482. *
  1483. * Trace a ray along the direction of the reflected light and
  1484. * return light internsity coming from that direction.
  1485. *
  1486. * CHANGES
  1487. *
  1488. * JUN 1997 : Changed to return color coming along the reflected ray. [DB]
  1489. *
  1490. ******************************************************************************/
  1491. static void Reflect(VECTOR IPoint, RAY *Ray, VECTOR Normal, VECTOR Raw_Normal, COLOUR Colour, DBL Weight)
  1492. {
  1493. DBL n;
  1494. RAY NRay;
  1495. Increase_Counter(stats[Reflected_Rays_Traced]);
  1496. /* Get direction of reflected ray. */
  1497. VDot(n,Ray->Direction, Normal);
  1498. n *= -2.0;
  1499. VAddScaled(NRay.Direction, Ray->Direction, n, Normal);
  1500. /* Nathan Kopp & CEY 1998 - Reflection bugfix
  1501. if the new ray is going the opposet direction as raw normal, we
  1502. need to fix it.
  1503. */
  1504. VDot(n, NRay.Direction, Raw_Normal);
  1505. if (n < 0.0)
  1506. {
  1507. /* It needs fixing. Which kind? */
  1508. VDot(n,NRay.Direction,Normal);
  1509. if (n < 0.0)
  1510. {
  1511. /* reflected inside rear virtual surface. Reflect Ray using Raw_Normal */
  1512. VDot(n,Ray->Direction,Raw_Normal);
  1513. n *= -2.0;
  1514. VAddScaled(NRay.Direction, Ray->Direction, n,Raw_Normal);
  1515. }
  1516. else
  1517. {
  1518. /* Double reflect NRay using Raw_Normal */
  1519. VDot(n,NRay.Direction,Raw_Normal);
  1520. n *= -2.0;
  1521. VAddScaledEq(NRay.Direction, n, Raw_Normal);
  1522. }
  1523. }
  1524. VNormalizeEq(NRay.Direction);
  1525. /* NK & CEY ---- */
  1526. Assign_Vector(NRay.Initial, IPoint);
  1527. Copy_Ray_Containers(&NRay, Ray);
  1528. /* Trace reflected ray. */
  1529. Trace_Level++;
  1530. Trace(&NRay, Colour, Weight);
  1531. Trace_Level--;
  1532. }
  1533. /*****************************************************************************
  1534. *
  1535. * FUNCTION
  1536. *
  1537. * Refract
  1538. *
  1539. * INPUT
  1540. *
  1541. * Interior - interior of the current object containing the ior to use
  1542. * IPoint - current intersection point (here the new ray starts)
  1543. * Ray - current incoming ray that will be refracted, transmitted
  1544. * or reflected (due to total internal reflection)
  1545. * Normal - surface normal at the current intersection point
  1546. * Colour - current color emitted back along the ray
  1547. * Weight - current weight used by the adaptive tree depth control
  1548. *
  1549. * OUTPUT
  1550. *
  1551. * Colour - current color including the light due to refraction,
  1552. * transmission or total internal reflection
  1553. *
  1554. * RETURNS
  1555. *
  1556. * int - TRUE, if total internal reflection occured
  1557. *
  1558. * AUTHOR
  1559. *
  1560. * POV-Ray Team
  1561. *
  1562. * DESCRIPTION
  1563. *
  1564. * Trace a transmitted ray (either refracted or reflected due to total
  1565. * internal reflection) and return the light intesity coming from the
  1566. * direction of the transmitted ray.
  1567. *
  1568. * CHANGES
  1569. *
  1570. * Aug 1995 : Modified to correctly handle the contained texture
  1571. * list in the transmit only case. [DB]
  1572. *
  1573. * Jun 1997 : Rewritten to use interior structure. [DB]
  1574. *
  1575. ******************************************************************************/
  1576. static int Refract(INTERIOR *Interior, VECTOR IPoint, RAY *Ray, VECTOR Normal, VECTOR Raw_Normal, COLOUR Colour, DBL Weight)
  1577. {
  1578. int nr;
  1579. DBL n, t, ior;
  1580. VECTOR Local_Normal;
  1581. RAY NRay;
  1582. /* Set up new ray. */
  1583. Copy_Ray_Containers(&NRay, Ray);
  1584. Assign_Vector(NRay.Initial, IPoint);
  1585. /* Get ratio of iors depending on the interiors the ray is traversing. */
  1586. if (Ray->Index == -1)
  1587. {
  1588. /* The ray is entering from the atmosphere. */
  1589. Ray_Enter(&NRay, Interior);
  1590. ior = Frame.Atmosphere_IOR / Interior->IOR;
  1591. }
  1592. else
  1593. {
  1594. /* The ray is currently inside an object. */
  1595. if ((nr = Interior_In_Ray_Container(&NRay, Interior)) >= 0)
  1596. {
  1597. /* The ray is leaving the current object. */
  1598. Ray_Exit(&NRay, nr);
  1599. if (NRay.Index == -1)
  1600. {
  1601. /* The ray is leaving into the atmosphere. */
  1602. ior = Interior->IOR / Frame.Atmosphere_IOR;
  1603. }
  1604. else
  1605. {
  1606. /* The ray is leaving into another object. */
  1607. ior = Interior->IOR / NRay.Interiors[NRay.Index]->IOR;
  1608. }
  1609. }
  1610. else
  1611. {
  1612. /* The ray is entering a new object. */
  1613. ior = NRay.Interiors[NRay.Index]->IOR / Interior->IOR;
  1614. Ray_Enter(&NRay, Interior);
  1615. }
  1616. }
  1617. /* Do the two mediums traversed have the sampe indices of refraction? */
  1618. if (fabs(ior - 1.0) < EPSILON)
  1619. {
  1620. /* Only transmit the ray. */
  1621. Assign_Vector(NRay.Direction, Ray->Direction);
  1622. /* Trace a transmitted ray. */
  1623. Increase_Counter(stats[Transmitted_Rays_Traced]);
  1624. }
  1625. else
  1626. {
  1627. /* Refract the ray. */
  1628. VDot(n, Ray->Direction, Normal);
  1629. if (n <= 0.0)
  1630. {
  1631. Assign_Vector(Local_Normal, Normal);
  1632. n = -n;
  1633. }
  1634. else
  1635. {
  1636. Local_Normal[X] = -Normal[X];
  1637. Local_Normal[Y] = -Normal[Y];
  1638. Local_Normal[Z] = -Normal[Z];
  1639. }
  1640. /* Compute refrated ray direction using Heckbert's method. */
  1641. t = 1.0 + Sqr(ior) * (Sqr(n) - 1.0);
  1642. if (t < 0.0)
  1643. {
  1644. /* Total internal reflection occures. */
  1645. Increase_Counter(stats[Internal_Reflected_Rays_Traced]);
  1646. Reflect(IPoint, Ray, Normal, Raw_Normal, Colour, Weight);
  1647. return(1);
  1648. }
  1649. t = ior * n - sqrt(t);
  1650. VLinComb2(NRay.Direction, ior, Ray->Direction, t, Local_Normal);
  1651. /* Trace a refracted ray. */
  1652. Increase_Counter(stats[Refracted_Rays_Traced]);
  1653. }
  1654. Trace_Level++;
  1655. Trace(&NRay, Colour, Weight);
  1656. Trace_Level--;
  1657. return(0);
  1658. }
  1659. /*****************************************************************************
  1660. *
  1661. * FUNCTION
  1662. *
  1663. * create_texture_list
  1664. *
  1665. * INPUT
  1666. *
  1667. * OUTPUT
  1668. *
  1669. * RETURNS
  1670. *
  1671. * AUTHOR
  1672. *
  1673. * Chris Young based on Dieter Bayer code
  1674. *
  1675. * DESCRIPTION
  1676. *
  1677. * Get the list of textures used by current object and the list of
  1678. * appropriate weights for each texture. Only multi-colored objects
  1679. * will have more than one texture.
  1680. *
  1681. * CHANGES
  1682. *
  1683. * Feb 1995 : Added code for triangle mesh texturing. [DB]
  1684. *
  1685. * Jul 1995 : Modified code to use pre-allocated lists. [DB]
  1686. *
  1687. ******************************************************************************/
  1688. static int create_texture_list(INTERSECTION *Ray_Intersection)
  1689. {
  1690. int Texture_Count;
  1691. BLOB *Blob;
  1692. MESH_TRIANGLE *Triangle;
  1693. /* Test, if object is multi-textured. */
  1694. if (Test_Flag(Ray_Intersection->Object, MULTITEXTURE_FLAG))
  1695. {
  1696. /* Handle blobs. */
  1697. if (Ray_Intersection->Object->Methods == &Blob_Methods)
  1698. {
  1699. Blob = (BLOB *)Ray_Intersection->Object;
  1700. /* Get list of weighted textures. */
  1701. Determine_Blob_Textures(Blob, Ray_Intersection->IPoint, &Texture_Count, Texture_List, Weight_List);
  1702. }
  1703. /* Handle meshes. */
  1704. if (Ray_Intersection->Object->Methods == &Mesh_Methods)
  1705. {
  1706. /* Set texture to triangle's or object's texture. */
  1707. Triangle = (MESH_TRIANGLE *)Ray_Intersection->Pointer;
  1708. if (Triangle->Texture >= 0)
  1709. {
  1710. Texture_List[0] = ((MESH *)Ray_Intersection->Object)->Data->Textures[Triangle->Texture];
  1711. }
  1712. else
  1713. {
  1714. Texture_List[0] = Ray_Intersection->Object->Texture;
  1715. }
  1716. Weight_List[0] = 1.0;
  1717. Texture_Count = 1;
  1718. }
  1719. }
  1720. else
  1721. {
  1722. /* Set texture to object's texture. */
  1723. Texture_List[0] = Ray_Intersection->Object->Texture;
  1724. Weight_List[0] = 1.0;
  1725. Texture_Count = 1;
  1726. }
  1727. return(Texture_Count);
  1728. }
  1729. /*****************************************************************************
  1730. *
  1731. * FUNCTION
  1732. *
  1733. * do_texture_map
  1734. *
  1735. * INPUT
  1736. *
  1737. * Texture - possibly texture_mapped texture to be evaluated
  1738. * IPoint - point to be evaluated
  1739. * Raw_Normal - non-purturbed surface normal
  1740. * Ray - view ray needed for reflection and highlighs
  1741. * light source ray needed for caustics
  1742. * Weight - ADC control value
  1743. * Ray_Intersection - only Ray_Int..->Object->Type actually
  1744. * needed. Will clean-up later.
  1745. * Shadow_Flag - tells if computation should use
  1746. * compute_lighted_texture or compute_shadow_texture
  1747. *
  1748. * OUTPUT
  1749. *
  1750. * Result_Colour - If Shadow_Flag true then the illuminated
  1751. * color (RGB only) of IPoint is returned.
  1752. * If false, the amount by which a shadow ray is
  1753. * filtered and attenuated is returned.
  1754. * Includes RGB and T.
  1755. *
  1756. * RETURNS
  1757. *
  1758. * AUTHOR
  1759. *
  1760. * POV-Ray Team
  1761. *
  1762. * DESCRIPTION
  1763. *
  1764. * This routine recursively calls itself until it gets a
  1765. * non-texture_mapped texture that is potentially layered.
  1766. * It then calls compute_lighted_texture or compute_shadow_texture
  1767. * to compute the color which is returned in the argument Result_Colour.
  1768. *
  1769. * CHANGES
  1770. *
  1771. ******************************************************************************/
  1772. static void do_texture_map(COLOUR Result_Colour, TEXTURE *Texture, VECTOR IPoint, VECTOR Raw_Normal,
  1773. RAY *Ray, DBL Weight, INTERSECTION *Ray_Intersection, int Shadow_Flag)
  1774. {
  1775. BLEND_MAP *Blend_Map = Texture->Blend_Map;
  1776. BLEND_MAP_ENTRY *Prev, *Cur;
  1777. DBL value1, value2;
  1778. COLOUR C2;
  1779. VECTOR TPoint;
  1780. if (Texture->Type <= LAST_SPECIAL_PATTERN)
  1781. {
  1782. switch (Texture->Type)
  1783. {
  1784. case NO_PATTERN:
  1785. Make_ColourA(Result_Colour, 1.0, 1.0, 1.0, 1.0, 1.0);
  1786. break;
  1787. case AVERAGE_PATTERN:
  1788. Warp_EPoint(TPoint, IPoint, (TPATTERN *)Texture);
  1789. average_textures(Result_Colour, Texture, TPoint, Raw_Normal, Ray, Weight, Ray_Intersection, Shadow_Flag);
  1790. break;
  1791. case BITMAP_PATTERN:
  1792. Warp_EPoint (TPoint, IPoint, (TPATTERN *)Texture);
  1793. Texture = material_map(TPoint, Texture);
  1794. do_texture_map(Result_Colour, Texture, TPoint, Raw_Normal, Ray, Weight, Ray_Intersection, Shadow_Flag);
  1795. break;
  1796. case PLAIN_PATTERN:
  1797. if (Shadow_Flag)
  1798. {
  1799. compute_shadow_texture(Result_Colour, Texture, IPoint, Raw_Normal, Ray, Ray_Intersection);
  1800. }
  1801. else
  1802. {
  1803. compute_lighted_texture(Result_Colour, Texture, IPoint, Raw_Normal, Ray, Weight, Ray_Intersection);
  1804. }
  1805. break;
  1806. default:
  1807. Error("Bad texture type in do_texture_map()\n");
  1808. }
  1809. }
  1810. else
  1811. {
  1812. value1 = Evaluate_TPat ((TPATTERN *)Texture,IPoint);
  1813. Search_Blend_Map (value1, Blend_Map, &Prev, &Cur);
  1814. Warp_EPoint (TPoint, IPoint, (TPATTERN *)Texture);
  1815. do_texture_map(Result_Colour, Cur->Vals.Texture, TPoint, Raw_Normal, Ray, Weight, Ray_Intersection, Shadow_Flag);
  1816. if (Prev != Cur)
  1817. {
  1818. do_texture_map(C2, Prev->Vals.Texture, TPoint, Raw_Normal, Ray, Weight, Ray_Intersection, Shadow_Flag);
  1819. value1 = (value1 - Prev->value) / (Cur->value - Prev->value);
  1820. value2 = 1.0 - value1;
  1821. CLinComb2(Result_Colour,value1,Result_Colour,value2,C2);
  1822. }
  1823. }
  1824. }
  1825. /*****************************************************************************
  1826. *
  1827. * FUNCTION
  1828. *
  1829. * compute_lighted_texture
  1830. *
  1831. * INPUT
  1832. *
  1833. * Texture - a linked list of texture layers
  1834. * IPoint - point to be evaluated
  1835. * Raw_Normal - non-purturbed surface normal
  1836. * Ray - needed for reflection and highlighs
  1837. * Weight - ADC control value
  1838. * Intersection - current intersection (need object type and depth)
  1839. *
  1840. * OUTPUT
  1841. *
  1842. * ResCol - illuminated color of IPoint
  1843. *
  1844. * RETURNS
  1845. *
  1846. * AUTHOR
  1847. *
  1848. * POV-Ray Team
  1849. *
  1850. * DESCRIPTION
  1851. *
  1852. * This routine loops through all layers of a texture and computes
  1853. * the appearent color of the point with illumination, shadows,
  1854. * reflection, refraction... everything. This piece of code was broken out
  1855. * of Determine_Appearent_Colour because texture_map needs to call it twice.
  1856. *
  1857. * CHANGES
  1858. *
  1859. * Jul 1995 : Added code to support alpha channel. [DB]
  1860. *
  1861. * Jul 1995 : Moved code for save list allocation. [DB]
  1862. *
  1863. * Aug 1995 : Added code for distance based attenuation in translucent
  1864. * objects and halos. [DB]
  1865. *
  1866. * Oct 1996 : Replaced halo code by participating media code. [DB]
  1867. *
  1868. ******************************************************************************/
  1869. static void compute_lighted_texture(COLOUR ResCol, TEXTURE *Texture, VECTOR IPoint, VECTOR Raw_Normal, RAY *Ray, DBL Weight, INTERSECTION *Intersection)
  1870. {
  1871. int i, radiosity_done, radiosity_needed;
  1872. int layer_number;
  1873. int inside_hollow_object;
  1874. int one_colour_found, colour_found;
  1875. DBL w1, w2;
  1876. DBL Normal_Direction, New_Weight, TempWeight;
  1877. DBL Att, Trans, Max_Radiosity_Contribution;
  1878. VECTOR LayNormal, TopNormal;
  1879. COLOUR LayCol, RflCol, RfrCol, FilCol;
  1880. COLOUR TmpCol, AmbCol, Tmp;
  1881. INTERIOR *Interior;
  1882. IMEDIA **TmpMedia, **MediaList;
  1883. TEXTURE *Layer;
  1884. #define MAX_LAYERS 20
  1885. int TIR_occured;
  1886. DBL ListWeight[MAX_LAYERS];
  1887. SNGL ListReflEx[MAX_LAYERS];
  1888. VECTOR ListNormal[MAX_LAYERS];
  1889. COLOUR ListReflec[MAX_LAYERS];
  1890. /*
  1891. * ResCol builds up the apparent visible color of the point.
  1892. * Only RGB components are significant. You can't "see" transparency --
  1893. * you see the color of whatever is behind the transparent surface.
  1894. * This color includes the visible appearence of what is behind the
  1895. * transparency so only RGB is needed.
  1896. */
  1897. Make_ColourA(ResCol, 0.0, 0.0, 0.0, 0.0, 0.0);
  1898. /*
  1899. * FilCol serves two purposes. It accumulates the filter properties
  1900. * of a multi-layer texture so that if a ray makes it all the way through
  1901. * all layers, the color of object behind is filtered by this object.
  1902. * It also is used to attenuate how much of an underlayer you
  1903. * can see in a layered texture. Note that when computing the reflective
  1904. * properties of a layered texture, the upper layers don't filter the
  1905. * light from the lower layers -- the layer colors add together (even
  1906. * before we added additive transparency via the "transmit" 5th
  1907. * color channel). However when computing the transmitted rays, all layers
  1908. * filter the light from any objects behind this object. [CY 1/95]
  1909. */
  1910. Make_ColourA(FilCol, 1.0, 1.0, 1.0, 1.0, 1.0);
  1911. Trans = 1.0;
  1912. /* Add in radiosity (stochastic interreflection-based ambient light) if desired */
  1913. radiosity_done = FALSE;
  1914. /* Note that there is no gathering of filter or transparency */
  1915. Make_ColourA(AmbCol, 1., 1., 1., 0., 0.);
  1916. if ((opts.Options & RADIOSITY) &&
  1917. (Trace_Level == Radiosity_Trace_Level) &&
  1918. (Radiosity_Trace_Level <= opts.Radiosity_Recursion_Limit))
  1919. {
  1920. /*
  1921. * For "real" (physically-based) diffuse interreflections, the
  1922. * ambient light level is independent of any surface properties, so
  1923. * the light gathering is done only once. This block just sets up
  1924. * for the code inside the loop, which is first-time-through.
  1925. */
  1926. radiosity_needed = 1;
  1927. }
  1928. else
  1929. {
  1930. radiosity_needed = 0;
  1931. }
  1932. /*
  1933. * Loop through the layers and compute the ambient, diffuse,
  1934. * phong and specular for these textures.
  1935. */
  1936. one_colour_found = FALSE;
  1937. for (layer_number = 0, Layer = Texture;
  1938. (Layer != NULL) && (Trans > BLACK_LEVEL);
  1939. layer_number++, Layer = (TEXTURE *)Layer->Next)
  1940. {
  1941. /* Get perturbed surface normal. */
  1942. Assign_Vector(LayNormal, Raw_Normal);
  1943. if ((opts.Quality_Flags & Q_NORMAL) && (Layer->Tnormal != NULL))
  1944. {
  1945. Perturb_Normal(LayNormal, Layer->Tnormal, IPoint);
  1946. }
  1947. /* Store top layer normal.*/
  1948. if (!layer_number)
  1949. {
  1950. Assign_Vector(TopNormal, LayNormal);
  1951. }
  1952. /* Get surface colour. */
  1953. New_Weight = Weight * Trans;
  1954. colour_found = Compute_Pigment (LayCol, Layer->Pigment, IPoint);
  1955. /*
  1956. * If a valid color was returned set one_colour_found to TRUE.
  1957. * An invalid color is returned if a surface point is outside
  1958. * an image map used just once.
  1959. */
  1960. if (colour_found)
  1961. {
  1962. one_colour_found = TRUE;
  1963. }
  1964. /*
  1965. * This section of code used to be the routine Compute_Reflected_Colour.
  1966. * I copied it in here to rearrange some of it more easily and to
  1967. * see if we could eliminate passing a zillion parameters for no
  1968. * good reason. [CY 1/95]
  1969. */
  1970. if (opts.Quality_Flags & Q_FULL_AMBIENT)
  1971. {
  1972. /* Only use top layer and kill transparency if low quality. */
  1973. Assign_Colour(ResCol, LayCol);
  1974. ResCol[FILTER] =
  1975. ResCol[TRANSM] = 0.0;
  1976. }
  1977. else
  1978. {
  1979. Make_Colour (TmpCol, 0.0, 0.0, 0.0);
  1980. Att = Trans * (1.0 - min(1.0, LayCol[FILTER] + LayCol[TRANSM]));
  1981. /* if radiosity calculation needed, but not yet done, do it now */
  1982. if (radiosity_needed && !radiosity_done)
  1983. {
  1984. /* This check eliminates radiosity calculations on "luminous" objects with ambient=1 */
  1985. if ((Layer->Finish->Ambient[0] != 1.0) ||
  1986. (Layer->Finish->Ambient[1] != 1.0) ||
  1987. (Layer->Finish->Ambient[2] != 1.0))
  1988. {
  1989. /* calculate max possible contribution of radiosity, to see if calculating it is worthwhile */
  1990. Tmp[0] = Att * LayCol[0] * Layer->Finish->Ambient[0] * Frame.Ambient_Light[0];
  1991. Tmp[1] = Att * LayCol[1] * Layer->Finish->Ambient[1] * Frame.Ambient_Light[1];
  1992. Tmp[2] = Att * LayCol[2] * Layer->Finish->Ambient[2] * Frame.Ambient_Light[2];
  1993. Max_Radiosity_Contribution = Tmp[0] *.287 + Tmp[1] *.589 + Tmp[2] * .114;
  1994. if (Max_Radiosity_Contribution > BLACK_LEVEL * 3.0)
  1995. {
  1996. (void)Compute_Ambient(Intersection->IPoint, Raw_Normal, AmbCol, Weight * Max_Radiosity_Contribution);
  1997. radiosity_done = TRUE;
  1998. }
  1999. }
  2000. }
  2001. /* Add ambient contribution. */
  2002. TmpCol[0] += Att * LayCol[0] * Layer->Finish->Ambient[0] * Frame.Ambient_Light[0] * AmbCol[0];
  2003. TmpCol[1] += Att * LayCol[1] * Layer->Finish->Ambient[1] * Frame.Ambient_Light[1] * AmbCol[1];
  2004. TmpCol[2] += Att * LayCol[2] * Layer->Finish->Ambient[2] * Frame.Ambient_Light[2] * AmbCol[2];
  2005. /* Add diffuse, phong, specular, and iridescence contribution. */
  2006. Diffuse(Layer->Finish, Intersection->IPoint, Ray, LayNormal, LayCol, TmpCol, Att, Intersection->Object);
  2007. VAddEq(ResCol, TmpCol);
  2008. /* Store vital information for later reflection. */
  2009. if (layer_number == MAX_LAYERS)
  2010. {
  2011. Error("Too many texture layers.");
  2012. }
  2013. ListReflEx[layer_number] = Layer->Finish->Reflect_Exp;
  2014. ListWeight[layer_number] = New_Weight;
  2015. Assign_Vector(ListNormal[layer_number], LayNormal);
  2016. ListReflec[layer_number][0]=Layer->Finish->Reflection[0];
  2017. ListReflec[layer_number][1]=Layer->Finish->Reflection[1];
  2018. ListReflec[layer_number][2]=Layer->Finish->Reflection[2];
  2019. }
  2020. /* Get new filter color. */
  2021. if (colour_found)
  2022. {
  2023. FilCol[0] *= LayCol[0];
  2024. FilCol[1] *= LayCol[1];
  2025. FilCol[2] *= LayCol[2];
  2026. FilCol[3] *= LayCol[3];
  2027. FilCol[4] *= LayCol[4];
  2028. }
  2029. /* Get new remaining translucency. */
  2030. Trans = min(1.0, fabs(FilCol[FILTER]) + fabs(FilCol[TRANSM]));
  2031. }
  2032. /*
  2033. * Calculate transmitted component.
  2034. *
  2035. * If the surface is translucent a transmitted ray is traced
  2036. * and its contribution is added to the total ResCol after
  2037. * filtering it by FilCol.
  2038. */
  2039. TIR_occured = FALSE;
  2040. if (((Interior = Intersection->Object->Interior) != NULL) && (Trans > BLACK_LEVEL) && (opts.Quality_Flags & Q_REFRACT))
  2041. {
  2042. w1 = fabs(FilCol[FILTER]) * max3(FilCol[0], FilCol[1], FilCol[2]);
  2043. w2 = fabs(FilCol[TRANSM]);
  2044. New_Weight = Weight * max(w1, w2);
  2045. /* Trace refracted ray. */
  2046. TIR_occured = Refract(Interior, Intersection->IPoint, Ray, TopNormal, Raw_Normal, RfrCol, New_Weight);
  2047. /* Get distance based attenuation. */
  2048. Att = Interior->Old_Refract;
  2049. if ((Interior != NULL) && Interior_In_Ray_Container(Ray, Interior) >= 0)
  2050. {
  2051. if (fabs(Interior->Fade_Distance) > EPSILON)
  2052. {
  2053. Att /= (1.0 + pow(Intersection->Depth / Interior->Fade_Distance, Interior->Fade_Power));
  2054. }
  2055. }
  2056. /* If total internal reflection occured the transmitted light is not filtered. */
  2057. if (TIR_occured)
  2058. {
  2059. ResCol[0] += Att * RfrCol[0];
  2060. ResCol[1] += Att * RfrCol[1];
  2061. ResCol[2] += Att * RfrCol[2];
  2062. }
  2063. else
  2064. {
  2065. if (one_colour_found)
  2066. {
  2067. ResCol[0] += Att * RfrCol[0] * (FilCol[0] * FilCol[FILTER] + FilCol[TRANSM]);
  2068. ResCol[1] += Att * RfrCol[1] * (FilCol[1] * FilCol[FILTER] + FilCol[TRANSM]);
  2069. ResCol[2] += Att * RfrCol[2] * (FilCol[2] * FilCol[FILTER] + FilCol[TRANSM]);
  2070. }
  2071. else
  2072. {
  2073. ResCol[0] += Att * RfrCol[0];
  2074. ResCol[1] += Att * RfrCol[1];
  2075. ResCol[2] += Att * RfrCol[2];
  2076. }
  2077. }
  2078. /* We need to know the transmittance value for the alpha channel. [DB] */
  2079. ResCol[TRANSM] = Att * FilCol[TRANSM];
  2080. }
  2081. /*
  2082. * Calculate reflected component.
  2083. *
  2084. * If total internal reflection occured all reflections using
  2085. * TopNormal are skipped.
  2086. */
  2087. if (opts.Quality_Flags & Q_REFLECT)
  2088. {
  2089. for (i = 0; i < layer_number; i++)
  2090. {
  2091. if ((!TIR_occured) ||
  2092. (fabs(TopNormal[0]-ListNormal[i][0]) > EPSILON) ||
  2093. (fabs(TopNormal[1]-ListNormal[i][1]) > EPSILON) ||
  2094. (fabs(TopNormal[2]-ListNormal[i][2]) > EPSILON))
  2095. {
  2096. if ((ListReflec[i][0] != 0.0) ||
  2097. (ListReflec[i][1] != 0.0) ||
  2098. (ListReflec[i][2] != 0.0))
  2099. {
  2100. TempWeight = ListWeight[i] * max3(ListReflec[i][0], ListReflec[i][1], ListReflec[i][2]);
  2101. Reflect(Intersection->IPoint, Ray, ListNormal[i], Raw_Normal, RflCol, TempWeight);
  2102. if (ListReflEx[i] != 1.0)
  2103. {
  2104. ResCol[0] += ListReflec[i][0] * pow(RflCol[0],ListReflEx[i]);
  2105. ResCol[1] += ListReflec[i][1] * pow(RflCol[1],ListReflEx[i]);
  2106. ResCol[2] += ListReflec[i][2] * pow(RflCol[2],ListReflEx[i]);
  2107. }
  2108. else
  2109. {
  2110. ResCol[0] += ListReflec[i][0] * RflCol[0];
  2111. ResCol[1] += ListReflec[i][1] * RflCol[1];
  2112. ResCol[2] += ListReflec[i][2] * RflCol[2];
  2113. }
  2114. }
  2115. }
  2116. }
  2117. }
  2118. /*
  2119. * Calculate participating media effects.
  2120. */
  2121. if ((opts.Quality_Flags & Q_VOLUME) && (Ray->Index > -1))
  2122. {
  2123. inside_hollow_object = TRUE;
  2124. /* Test for any solid object. */
  2125. for (i = 0; i <= Ray->Index; i++)
  2126. {
  2127. if (!Ray->Interiors[i]->hollow)
  2128. {
  2129. inside_hollow_object = FALSE;
  2130. break;
  2131. }
  2132. }
  2133. /* Calculate effects of all media we're currently in. */
  2134. if (inside_hollow_object)
  2135. {
  2136. MediaList = (IMEDIA **)POV_MALLOC((Ray->Index+2)*sizeof(IMEDIA *), "temp media list");
  2137. TmpMedia = MediaList;
  2138. for (i = 0; i <= Ray->Index; i++)
  2139. {
  2140. if (Ray->Interiors[i]->hollow)
  2141. {
  2142. if (Ray->Interiors[i]->IMedia != NULL)
  2143. {
  2144. *TmpMedia = Ray->Interiors[i]->IMedia;
  2145. TmpMedia++;
  2146. }
  2147. }
  2148. }
  2149. *TmpMedia = NULL;
  2150. Simulate_Media(MediaList, Ray, Intersection, ResCol, FALSE);
  2151. POV_FREE(MediaList);
  2152. }
  2153. }
  2154. }
  2155. /*****************************************************************************
  2156. *
  2157. * FUNCTION
  2158. *
  2159. * compute_shadow_texture
  2160. *
  2161. * INPUT
  2162. *
  2163. * Texture - layered texture through which shadow ray passes
  2164. * IPoint - point through which shadow ray passes
  2165. * Raw_Normal - non-purturbed surface normal
  2166. * Ray - light source ray
  2167. * Ray_Intersection - current intersection (need intersection depth)
  2168. *
  2169. * OUTPUT
  2170. *
  2171. * Filter_Colour - returned filter for shadow ray
  2172. *
  2173. * RETURNS
  2174. *
  2175. * AUTHOR
  2176. *
  2177. * POV-Ray Team
  2178. *
  2179. * DESCRIPTION
  2180. *
  2181. * CHANGES
  2182. *
  2183. * Dec 1994 : Separated from filter_shadow_ray to do texture_map [CEY]
  2184. *
  2185. * May 1995 : Added caustic code by Steve Anger. [DB]
  2186. *
  2187. * Aug 1995 : Caustic code moved here from filter_shadow_ray. [CEY]
  2188. *
  2189. * Oct 1996 : Replaced halo code by participating media code. [DB]
  2190. *
  2191. ******************************************************************************/
  2192. static void compute_shadow_texture (COLOUR Filter_Colour, TEXTURE *Texture, VECTOR IPoint, VECTOR Raw_Normal, RAY *Ray, INTERSECTION *Ray_Intersection)
  2193. {
  2194. int i, inside_hollow_object, colour_found, one_colour_found;
  2195. DBL Caustics, dot, k, Refraction;
  2196. VECTOR Layer_Normal;
  2197. COLOUR Layer_Pigment_Colour;
  2198. IMEDIA **Media_List, **Tmp;
  2199. TEXTURE *Layer;
  2200. INTERIOR *Interior = Ray_Intersection->Object->Interior;
  2201. Make_ColourA(Filter_Colour, 1.0, 1.0, 1.0, 1.0, 1.0);
  2202. one_colour_found = FALSE;
  2203. for (Layer = Texture; (Layer != NULL) &&
  2204. (fabs(Filter_Colour[FILTER]) + fabs(Filter_Colour[TRANSM]) > BLACK_LEVEL);
  2205. Layer = (TEXTURE *)Layer->Next)
  2206. {
  2207. colour_found = Compute_Pigment (Layer_Pigment_Colour, Layer->Pigment, IPoint);
  2208. if (colour_found)
  2209. {
  2210. one_colour_found = TRUE;
  2211. Filter_Colour[RED] *= Layer_Pigment_Colour[RED];
  2212. Filter_Colour[GREEN] *= Layer_Pigment_Colour[GREEN];
  2213. Filter_Colour[BLUE] *= Layer_Pigment_Colour[BLUE];
  2214. Filter_Colour[FILTER] *= Layer_Pigment_Colour[FILTER];
  2215. Filter_Colour[TRANSM] *= Layer_Pigment_Colour[TRANSM];
  2216. }
  2217. /* Get normal for faked caustics. (Will rewrite later to cache) */
  2218. if ((Interior != NULL) && ((Caustics = Interior->Caustics) != 0.0))
  2219. {
  2220. Assign_Vector(Layer_Normal, Raw_Normal);
  2221. if ((opts.Quality_Flags & Q_NORMAL) && (Layer->Tnormal != NULL))
  2222. {
  2223. Perturb_Normal(Layer_Normal, Layer->Tnormal, IPoint);
  2224. }
  2225. /* Get new filter/transmit values. */
  2226. VDot (dot, Layer_Normal, Ray->Direction);
  2227. k = (1.0 + pow(fabs(dot), Caustics));
  2228. Filter_Colour[FILTER] *= k;
  2229. Filter_Colour[TRANSM] *= k;
  2230. }
  2231. }
  2232. /* Get distance based attenuation. */
  2233. if (Interior != NULL)
  2234. {
  2235. Refraction = 1.0;
  2236. if (Interior_In_Ray_Container(Ray, Interior) >= 0)
  2237. {
  2238. if ((Interior->Fade_Power > 0.0) && (fabs(Interior->Fade_Distance) > EPSILON))
  2239. {
  2240. Refraction /= 1.0 + pow(Ray_Intersection->Depth / Interior->Fade_Distance, Interior->Fade_Power);
  2241. }
  2242. }
  2243. }
  2244. else
  2245. {
  2246. Refraction = 0.0;
  2247. }
  2248. /* Get distance based attenuation. */
  2249. Filter_Colour[RED] *= Refraction;
  2250. Filter_Colour[GREEN] *= Refraction;
  2251. Filter_Colour[BLUE] *= Refraction;
  2252. Filter_Colour[FILTER] *= Refraction;
  2253. Filter_Colour[TRANSM] *= Refraction;
  2254. /*
  2255. * If no valid color was found we set the filtering channel
  2256. * to zero to make sure that no light amplification occures.
  2257. * That would happen if both the filter and transmit channel
  2258. * were used.
  2259. */
  2260. if (!one_colour_found)
  2261. {
  2262. Filter_Colour[FILTER] = 0.0;
  2263. }
  2264. /* Calculate participating media effects. */
  2265. if ((opts.Quality_Flags & Q_VOLUME) && (Ray->Index > -1))
  2266. {
  2267. inside_hollow_object = TRUE;
  2268. /* Test for any solid object. */
  2269. for (i = 0; i <= Ray->Index; i++)
  2270. {
  2271. if (!Ray->Interiors[i]->hollow)
  2272. {
  2273. inside_hollow_object = FALSE;
  2274. break;
  2275. }
  2276. }
  2277. /* Calculate effects of all participating media we're currently in. */
  2278. if (inside_hollow_object)
  2279. {
  2280. Media_List = (IMEDIA **)POV_MALLOC((Ray->Index+2)*sizeof(IMEDIA *), "temp media list");
  2281. Tmp = Media_List;
  2282. for (i = 0; i <= Ray->Index; i++)
  2283. {
  2284. if (Ray->Interiors[i]->hollow)
  2285. {
  2286. if (Ray->Interiors[i]->IMedia != NULL)
  2287. {
  2288. *Tmp = Ray->Interiors[i]->IMedia;
  2289. Tmp++;
  2290. }
  2291. }
  2292. }
  2293. *Tmp = NULL;
  2294. Simulate_Media(Media_List, Ray, Ray_Intersection, Filter_Colour, TRUE);
  2295. POV_FREE(Media_List);
  2296. }
  2297. }
  2298. }
  2299. /*****************************************************************************
  2300. *
  2301. * FUNCTION
  2302. *
  2303. * filter_shadow_ray
  2304. *
  2305. * INPUT
  2306. *
  2307. * OUTPUT
  2308. *
  2309. * RETURNS
  2310. *
  2311. * AUTHOR
  2312. *
  2313. * POV-Ray Team
  2314. *
  2315. * DESCRIPTION
  2316. *
  2317. * -
  2318. *
  2319. * CHANGES
  2320. *
  2321. * Aug 1994 : Code for early exit due to opaque object added. [DB]
  2322. *
  2323. * Sep 1994 : Code for multi-textured blobs added. [DB]
  2324. *
  2325. * May 1995 : Added caustic code by Steve Anger. [DB]
  2326. *
  2327. * Aug 1995 : Added code to attenuate light source color
  2328. * due to atmospheric effects. [DB]
  2329. *
  2330. ******************************************************************************/
  2331. static void filter_shadow_ray(INTERSECTION *Ray_Intersection, RAY *Light_Source_Ray, COLOUR Colour)
  2332. {
  2333. int i, Texture_Count;
  2334. VECTOR IPoint;
  2335. VECTOR Raw_Normal;
  2336. COLOUR FC1, Temp_Colour;
  2337. TEXTURE *Texture = NULL; /* To remove uninitialized use warning [AED] */
  2338. size_t save_tw_size;
  2339. DBL *save_Weights = NULL;
  2340. TEXTURE **save_Textures = NULL;
  2341. Assign_Vector(IPoint, Ray_Intersection->IPoint);
  2342. if (!(opts.Quality_Flags & Q_SHADOW))
  2343. {
  2344. return;
  2345. }
  2346. /* If the object is opaque there's no need to go any further. [DB 8/94] */
  2347. if (Test_Flag(Ray_Intersection->Object, OPAQUE_FLAG))
  2348. {
  2349. Make_Colour(Colour, 0.0, 0.0, 0.0);
  2350. return;
  2351. }
  2352. /* Get the normal to the surface */
  2353. Normal(Raw_Normal, Ray_Intersection->Object, Ray_Intersection);
  2354. /*
  2355. * Save texture and weight lists.
  2356. */
  2357. save_tw_size = (size_t)Number_Of_Textures_And_Weights;
  2358. if (save_tw_size > 0)
  2359. {
  2360. save_Weights = (DBL *)POV_MALLOC(save_tw_size * sizeof(DBL), "Weight list stack");
  2361. memcpy(save_Weights, Weight_List, save_tw_size * sizeof(DBL));
  2362. save_Textures = (TEXTURE **)POV_MALLOC(save_tw_size * sizeof(TEXTURE *), "Weight list stack");
  2363. memcpy(save_Textures, Texture_List, save_tw_size * sizeof(TEXTURE *));
  2364. }
  2365. /* Get texture list and weights. */
  2366. Texture_Count = create_texture_list(Ray_Intersection);
  2367. Make_ColourA(Temp_Colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  2368. for (i = 0; i < Texture_Count; i++)
  2369. {
  2370. /* If contribution of this texture is neglectable skip ahead. */
  2371. if (Weight_List[i] < BLACK_LEVEL)
  2372. {
  2373. continue;
  2374. }
  2375. Texture = Texture_List[i];
  2376. do_texture_map(FC1, Texture, IPoint, Raw_Normal, Light_Source_Ray, 0.0, Ray_Intersection, TRUE);
  2377. Temp_Colour[RED] += Weight_List[i] * FC1[RED];
  2378. Temp_Colour[GREEN] += Weight_List[i] * FC1[GREEN];
  2379. Temp_Colour[BLUE] += Weight_List[i] * FC1[BLUE];
  2380. Temp_Colour[FILTER] += Weight_List[i] * FC1[FILTER];
  2381. Temp_Colour[TRANSM] += Weight_List[i] * FC1[TRANSM];
  2382. }
  2383. /* Restore the weight and texture list. */
  2384. if (save_tw_size > 0)
  2385. {
  2386. memcpy(Weight_List, save_Weights, save_tw_size * sizeof(DBL));
  2387. memcpy(Texture_List, save_Textures, save_tw_size * sizeof(TEXTURE *));
  2388. POV_FREE(save_Weights);
  2389. POV_FREE(save_Textures);
  2390. }
  2391. if (fabs(Temp_Colour[FILTER]) + fabs(Temp_Colour[TRANSM]) < BLACK_LEVEL)
  2392. {
  2393. Make_Colour(Colour, 0.0, 0.0, 0.0);
  2394. }
  2395. else
  2396. {
  2397. Colour[RED] *= Temp_Colour[FILTER] * Temp_Colour[RED] + Temp_Colour[TRANSM];
  2398. Colour[GREEN] *= Temp_Colour[FILTER] * Temp_Colour[GREEN]+ Temp_Colour[TRANSM];
  2399. Colour[BLUE] *= Temp_Colour[FILTER] * Temp_Colour[BLUE] + Temp_Colour[TRANSM];
  2400. }
  2401. /* Get atmospheric attenuation. */
  2402. do_light_ray_atmosphere(Light_Source_Ray, Ray_Intersection, Colour, TRUE);
  2403. }
  2404. /*****************************************************************************
  2405. *
  2406. * FUNCTION
  2407. *
  2408. * do_blocking
  2409. *
  2410. * INPUT
  2411. *
  2412. * OUTPUT
  2413. *
  2414. * RETURNS
  2415. *
  2416. * AUTHOR
  2417. *
  2418. * POV-Ray Team
  2419. *
  2420. * DESCRIPTION
  2421. *
  2422. * -
  2423. *
  2424. * CHANGES
  2425. *
  2426. * -
  2427. *
  2428. ******************************************************************************/
  2429. static int do_blocking(INTERSECTION *Local_Intersection, RAY *Light_Source_Ray, COLOUR Light_Colour, ISTACK *Local_Stack)
  2430. {
  2431. Increase_Counter(stats[Shadow_Rays_Succeeded]);
  2432. filter_shadow_ray(Local_Intersection, Light_Source_Ray, Light_Colour);
  2433. if ((fabs(Light_Colour[RED]) < BLACK_LEVEL) &&
  2434. (fabs(Light_Colour[GREEN]) < BLACK_LEVEL) &&
  2435. (fabs(Light_Colour[BLUE]) < BLACK_LEVEL))
  2436. {
  2437. while ((Local_Intersection = pop_entry(Local_Stack)) != NULL)
  2438. {
  2439. }
  2440. return(TRUE);
  2441. }
  2442. return(FALSE);
  2443. }
  2444. /*****************************************************************************
  2445. *
  2446. * FUNCTION
  2447. *
  2448. * block_light_source
  2449. *
  2450. * INPUT
  2451. *
  2452. * Light - Light source
  2453. * Depth - Distance to light source
  2454. * Light_Source_Ray - Light ray
  2455. * Eye_Ray - Ray from eye to current intersection point
  2456. * P - Surface point to shade
  2457. *
  2458. * OUTPUT
  2459. *
  2460. * Colour - Light color reaching point P
  2461. *
  2462. * RETURNS
  2463. *
  2464. * AUTHOR
  2465. *
  2466. * Dieter Bayer
  2467. *
  2468. * DESCRIPTION
  2469. *
  2470. * Determine how much light from the given light source reaches
  2471. * the given point. This includes attenuation due to blocking
  2472. * and translucent objects and atmospheric effects.
  2473. *
  2474. * CHANGES
  2475. *
  2476. * Jan 1995 : Creation (Extracted from common code).
  2477. *
  2478. * Aug 1995 : Added code to support atmospheric effects. [DB]
  2479. *
  2480. ******************************************************************************/
  2481. static void block_light_source(LIGHT_SOURCE *Light, DBL Depth, RAY *Light_Source_Ray, RAY *Eye_Ray, VECTOR P, COLOUR Colour)
  2482. {
  2483. DBL New_Depth;
  2484. INTERSECTION Intersection;
  2485. RAY New_Ray;
  2486. /* Store current depth and ray because they will be modified. */
  2487. New_Depth = Depth;
  2488. New_Ray = *Light_Source_Ray;
  2489. /* Get shadows from current light source. */
  2490. if ((Light->Area_Light) && (opts.Quality_Flags & Q_AREA_LIGHT))
  2491. {
  2492. block_area_light(Light, &New_Depth, &New_Ray, Eye_Ray, P, Colour, 0, 0, 0, 0, 0);
  2493. }
  2494. else
  2495. {
  2496. if (opts.Options & USE_LIGHT_BUFFER)
  2497. {
  2498. block_point_light_LBuffer(Light, &New_Depth, &New_Ray, Colour);
  2499. }
  2500. else
  2501. {
  2502. block_point_light(Light, &New_Depth, &New_Ray, Colour);
  2503. }
  2504. }
  2505. /*
  2506. * If there's some distance left for the ray to reach the light source
  2507. * we have to apply atmospheric stuff to this part of the ray.
  2508. */
  2509. if ((New_Depth > SHADOW_TOLERANCE) &&
  2510. (Light->Media_Interaction) &&
  2511. (Light->Media_Attenuation))
  2512. {
  2513. Intersection.Depth = New_Depth;
  2514. do_light_ray_atmosphere(&New_Ray, &Intersection, Colour, FALSE);
  2515. }
  2516. }
  2517. /*****************************************************************************
  2518. *
  2519. * FUNCTION
  2520. *
  2521. * average_textures
  2522. *
  2523. * INPUT
  2524. *
  2525. * OUTPUT
  2526. *
  2527. * RETURNS
  2528. *
  2529. * AUTHOR
  2530. *
  2531. * POV-Ray Team
  2532. *
  2533. * DESCRIPTION
  2534. *
  2535. * -
  2536. *
  2537. * CHANGES
  2538. *
  2539. * -
  2540. *
  2541. ******************************************************************************/
  2542. static void average_textures (COLOUR Result_Colour, TEXTURE *Texture, VECTOR IPoint, VECTOR Raw_Normal,
  2543. RAY *Ray, DBL Weight, INTERSECTION *Ray_Intersection, int Shadow_Flag)
  2544. {
  2545. int i;
  2546. COLOUR LC;
  2547. BLEND_MAP *Map = Texture->Blend_Map;
  2548. SNGL Value;
  2549. SNGL Total = 0.0;
  2550. Make_Colour (Result_Colour, 0.0, 0.0, 0.0);
  2551. for (i = 0; i < Map->Number_Of_Entries; i++)
  2552. {
  2553. Value = Map->Blend_Map_Entries[i].value;
  2554. do_texture_map (LC,Map->Blend_Map_Entries[i].Vals.Texture, IPoint,Raw_Normal,Ray,Weight,Ray_Intersection,Shadow_Flag);
  2555. Result_Colour[RED] += LC[RED] *Value;
  2556. Result_Colour[GREEN] += LC[GREEN] *Value;
  2557. Result_Colour[BLUE] += LC[BLUE] *Value;
  2558. Result_Colour[FILTER]+= LC[FILTER]*Value;
  2559. Result_Colour[TRANSM]+= LC[TRANSM]*Value;
  2560. Total += Value;
  2561. }
  2562. Result_Colour[RED] /= Total;
  2563. Result_Colour[GREEN] /= Total;
  2564. Result_Colour[BLUE] /= Total;
  2565. Result_Colour[FILTER]/= Total;
  2566. Result_Colour[TRANSM]/= Total;
  2567. }
  2568. /*****************************************************************************
  2569. *
  2570. * FUNCTION
  2571. *
  2572. * do_light_ray_atmosphere
  2573. *
  2574. * INPUT
  2575. *
  2576. * Light_Source_Ray - Current ray towards light source
  2577. * Ray_Intersection - Current intersection with a blocking object
  2578. * Texture - Current PNFH texture
  2579. * Valid_Object - Flag: 1=a valid object is in the intersection struct
  2580. *
  2581. * OUTPUT
  2582. *
  2583. * Colour - Attenuated light source color
  2584. *
  2585. * RETURNS
  2586. *
  2587. * AUTHOR
  2588. *
  2589. * Dieter Bayer
  2590. *
  2591. * DESCRIPTION
  2592. *
  2593. * Determine the influence of atmospheric effects on a light source ray.
  2594. *
  2595. * CHANGES
  2596. *
  2597. * Aug 1995 : Creation.
  2598. *
  2599. ******************************************************************************/
  2600. static void do_light_ray_atmosphere(RAY *Light_Source_Ray, INTERSECTION *Ray_Intersection, COLOUR Colour, int Valid_Object)
  2601. {
  2602. int interior_nr;
  2603. int i, all_hollow;
  2604. /* Why are we here? */
  2605. if ((Colour[RED] < BLACK_LEVEL) && (Colour[GREEN] < BLACK_LEVEL) && (Colour[BLUE] < BLACK_LEVEL))
  2606. {
  2607. return;
  2608. }
  2609. all_hollow = TRUE;
  2610. for (i = 0; i <= Light_Source_Ray->Index; i++)
  2611. {
  2612. if (!Light_Source_Ray->Interiors[i]->hollow)
  2613. {
  2614. all_hollow = FALSE;
  2615. break;
  2616. }
  2617. }
  2618. /* Apply atmospheric effects inside and/or outside any object. */
  2619. if ((opts.Quality_Flags & Q_VOLUME) && (all_hollow || (Valid_Object && Ray_Intersection->Object->Interior != NULL)))
  2620. {
  2621. Do_Finite_Atmosphere(Light_Source_Ray, Ray_Intersection, Colour, TRUE);
  2622. }
  2623. /* Handle contained textures. */
  2624. if (Valid_Object)
  2625. {
  2626. if (Light_Source_Ray->Index == -1)
  2627. {
  2628. /* The ray is entering from the atmosphere */
  2629. Ray_Enter(Light_Source_Ray, Ray_Intersection->Object->Interior);
  2630. }
  2631. else
  2632. {
  2633. /* The ray is currently inside an object */
  2634. if ((interior_nr = Interior_In_Ray_Container(Light_Source_Ray, Ray_Intersection->Object->Interior)) >= 0)
  2635. {
  2636. /* The ray is leaving the current object */
  2637. Ray_Exit(Light_Source_Ray, interior_nr);
  2638. }
  2639. else
  2640. {
  2641. /* The ray is entering a new object */
  2642. Ray_Enter(Light_Source_Ray, Ray_Intersection->Object->Interior);
  2643. }
  2644. }
  2645. }
  2646. }