A Literate Ray Tracer

A Literate Ray Tracer

DRAFT (18 October 2001) — Do Not Distribute A LITERATE RAY TRACER Matt Pharr, Greg Humphreys, and Pat Hanrahan Copyright c 2001 Matt Pharr, Greg Humphreys, and Pat Hanrahan ii [Just as] other information should be available to those who want to learn and understand, program source code is the only means for programmers to learn the art from their predecessors. It would be unthinkable for play- wrights not to allow other playwrights to read their plays [and] only be present at theater performances where they would be barred even from taking notes. Likewise, any good author is well read, as every child who learns to write will read hundreds of times more than it writes. Program- mers, however, are expected to invent the alphabet and learn to write long novels all on their own. Programming cannot grow and learn unless the next generation of programmers have access to the knowledge and infor- mation gathered by other programmers before them. — Eric Naggum iii iv Preface This manuscript contains the documented source code for a reasonably complete ray tracing rendering system. It is written using a programming methodology called literate programming that intermingles text describing the system with the source code that implements it. This is a new approach to teaching the concepts embodied in a rendering system, from basic geometric computation to sophisticated light transport algorithms. By showing these ideas in the context of a complete and non-trivial program we also address some issues in the design and implementation of medium-sized rendering software systems. Overview and Goals lrt, the rendering system that we will describe in this book, was designed and implemented with two main goals in mind: it should be complete, and it should be illustrative. Completeness implies that the system should not lack important features found in high-end rendering systems; in particular, it means that important practical issues, such as anti-aliasing, be addressed thoroughly. It is often quite difficult to retrofit such functionality to a rendering system after it has been designed, as it can have subtle implications for all components of the system, and even the overall architectural design. In cases where lrt lacks a useful feature, we have attempted to design the architecture so that feature could be easily added without altering the overall system design. Exercises at the end of each chapter suggest programming projects that involve new features. Our second goal means that we tried to choose algorithms, data structures, and rendering techniques with care. Since their implementations will be examined by more readers than those in most rendering systems, we tried to select the best algorithms we were aware of. Clarity, simplicity, and elegance were our watchwords. Efficiency was only a tertiary goal. Since rendering systems often run for many minutes or hours in the course of generating an image, efficiency is clearly important. However, we have largely confined ourselves to v vi Preface algorithmic efficiency rather than low-level code optimization. In many cases, obvious micro-optimizations take a back seat to clear, well-organized code. For this reason as well as portability, lrt is not presented as a parallel or multi-threaded application. However, exploiting intra-frame parallelism in lrt would be straightforward in either a shared-memory or message-passing environment. In the course of presenting the implementation of lrt, we hope to convey some hard-learned lessons gleaned from experience with both commercial and academic rendering research and development. Writing a good renderer is much more complex than stringing together a set of fast algorithms; making the system robust is even harder. The system’s performance must degrade gracefully as more geometry is added to it, as more light sources are added, or as any of the other axes of complexity are pushed. Numeric stability must be handled carefully; stable algorithms that don’t waste floating-point precision are critical. A renderer is somewhat like an operating system: managing and ordering large amounts of data and computation is a critical task. RenderMan Although we won’t provide a detailed description here, lrt supports the RenderMan interface for spec- ifying scenes. RenderMan is the industry standard high quality rendering API, although the specification does not mandate the actual rendering technique to be used. Scan conversion based implementations of the RenderMan interface exist; the most notable is Pixar’s Photorealistic RenderMan, which is used for most special effects we see in movies today. Blue Moon Rendering Tools (BMRT) by Larry Gritz is a raytracing based implementation similar in spirit to lrt, but with different goals. Our ray tracer supports not only the programmatic RenderMan API, but also the Renderman Bytestream Interface (RIB). RIB is a text-file encoding of RenderMan API calls. A good introduction to the RenderMan interface is The Renderman Companion(?). Blue Moon Rendering Tools is available at http://www.bmrt.org. More information about the RIB format and detailed Renderman specifications can be found at Pixar’s web site: http://www.pixar.com. Literate Programming In the course of the development of the TEXtypesetting system, Donald Knuth developed a new program- ming methodology based on the simple idea that programs should be written more for people’s consump- tion than for computers’ consumption. He named this methodology literate programming. This manuscript (including the chapter you’re reading now) is a long literate program. Literate programs are written in a meta-language that mixes a document formatting language (e.g. LATEXand/or HTML) and a programming language (e.g. C++). The meta-language compiler then can transform the literate program into either a doc- ument suitable for typesetting (this process is generally called literate programming:weaving), or into source code suitable for compilation (literate programming:tangling). The literate programming meta-language provides two important features. The first is a set of mechanisms for mixing English text with source code. This makes the description of the program just as important as its actual source code, encouraging careful design and documentation on the part of the programmer. Second, the language provides mechanisms for presenting the program code to the reader in an entirely different order than it is supplied to the compiler. This feature makes it possible to describe the operation of the program in a very logical manner. Knuth named his literate programming system web since literate programs tend to have the form of a web: various pieces are defined and inter-related in a variety of ways and programs are written in a structure that is neither top-down nor bottom-up. As an example, consider a function InitGlobals() that is responsible for initializing all of the program’s global variables. If all of the variable initializations are presented at once, InitGlobals() may be a large collection of variable assignments whose meanings are unclear because they do not appear near the definition Literate Programming vii or use of the variables. A reader would need to search through the rest of the entire program to see where each particular variable was declared in order to understand the function and the meanings of the values it assigned to the variables. As far as the human reader is concerned, it would be better to present the initialization code near the code that actually declares the global. In a literate program, one can instead write InitGlobals like this: Function Definitions h void InitGlobals()i≡ { Initialize Global Variables } h i Here we have defined a literate progamming:fragment called Function Definitions . This fragment will be included in a source code file when the literate program is whoven for the C++ compiler;i which one isn’t important to the human reader. The fragment contains the definition of the InitGlobals function. The InitGlobals function itself includes another fragment, Initialize Global Variables . When we introduce a new global variable ErrorCount anywhere in the program,h we can now write: i Initialize Global Variables h ErrorCount = 0; i≡ Here we have started to define the contents of Initialize Global Variables . When our literate program is turned into source code suitable for compiling,h the literate programming systemi will substitute the code ErrorCount = 0; inside the definition of the InitGlobals function. Later on, we may introduce another global FragmentsProcessed, and we can append it to the fragment: Initialize Global Variables + h FragmentsProcessed =i 0;≡ The + symbol after the fragment name shows that we have added to a previously defined fragment. When woven,≡ the result of the above fragment definitions is the code: void InitGlobals() { ErrorCount = 0; FragmentsProcessed = 0; } The other main advantage of literate programming is that complex functions can be easily decomposed into logically-distinct parts. We can write a function as a series of fragments: Function Definitions + h int func(int x,i int≡ y, double *data) { int errorCount = 0; Check validity of arguments ifh (x < y) { i Swap parameter values } h i Do precomputation before loop hLoop through data array i returnh errorCount; i } viii Preface The text of each fragment is then expanded inline in func for the compiler. In the document, we can introduce each fragment and its implementation in turn–these fragments may of course include additional fragments, etc. An advantage of this style of programming is that by separating the function into logical fragments, each one can be written and verified independently–in general, we try to make each fragment less than ten lines or so of code, making it easier to understand the operation of the function as a whole. Of course, inline functions could be used similarly in a traditional programming environment, but using fragments to decompose functions has two advantages. The first is that all of the fragments can immediately refer to all of the parameters of the original function as well as any function-local variables that are declared.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    269 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us