Prerequisites
Welcome to your first Graphics Codex Project!
In this project you'll create 3D scenes from simple cubes in three ways, by directly editing a data file, by using a GUI scene editor, and by programmatically generating a data file. Programmatically constructing a scene in memory at run time is a fourth way, which you won't take on just yet.
All projects in this series each have a five major sections:
Motivation for the project and your practical and educational goals. | |
Precisely what you should implement, stated in a formal manner. | |
Questions to answer that will ensure you've figured out both the basic and some advanced elements of the challenge. | |
Implementation tips using the recommended tools. This is optional, but very helpful if you are using those tools. | |
Images showing examples of what others have created for this project. |
In this project, you'll gain familiarity with:
To achieve that excellence and deep knowledge instead of just learning a few tricks, it is important that you approach the work with the right expectations. You can simply trust me that it is worth spending time focusing on mathematical fundamentals, the details of physics, software design, and development workflow in order to produce 3D graphics. Or, you can read the optional Pedagogy section of this document, in which I explain the overarching educational goals of the project series and why I designed them this way.
This walkthrough will guide you through the usual workflow for the specific tools that I recommend for these projects, particularly the G3D Innovation Engine, C++, and Subversion version control. Just doing the typing and clicking as directed will give you enough familiarity to then apply the information from the related chapters you've read. (If you're using a different toolset, make sure that you can perform equivalent tasks. If you prefer git to Subversion, the Graphics Codex version control chapter gives a listing of the git commands that you'll need.)
Where this walkthrough says to enter specific code, please actually type it—do not copy from this document and paste it into your editor. Typing the code yourself should prompt you think about what it means, and if you make a mistake will give you an opportunity to debug it.
Create local repository/snapshot and workspace for your project, as discussed in the Graphics
Codex Version Control Basics chapter. In TortoiseSVN, right click in a folder and select “SVN
checkout”, then type in the remote URL of your project. Or, at the command line, use "svn co
url".
Create a new project as described in the
G3D Creating a New Project
documentation: If you're using Visual Studio, copy the contents of the G3D starter
project directory. If you're using iCompile, run icompile
in your project directory and
respond to the prompts.
You should now have a directory with subdirectories for data-files
, source
, and so on. In
the root directory are ice.txt
and/or the Visual Studio project files with names ending in
.sln
and .vxproj
.
Verify that your program is working and your system is configured correctly. Using Visual
Studio, load the .sln
file and press F5. With iCompile, run
icompile --run
The program should compile, launch, and display a 3D scene. You can exit with the ESC key. If it didn't run correctly, debug your environment to ensure that it conforms to the one described in the tools document.
By default,
G3D::GApp
creates a
G3D::FirstPersonManipulator
that allows you to move the 3D camera. I'm telling you the name of the class right now so that
you'll know how to find and configure it later, but right now all that you need to know
is...video game controls work.
G3D initially launches with a scene's built-in cameras selected. Press F2 to switch to the Debug Camera.
The manipulator on the camera uses common first-person PC video game controls. The W
, A
,
S
, and D
keys on the keyboard will translate the camera forward, left, back, and right
relative to its own axes. Try this now.
If you press the right mouse button (or press “control” and the mouse button for a single-button mouse under OS X), then the mouse rotates the yaw and pitch of the camera. It requires you to press a button because otherwise using the mouse with the GUI would also move your viewpoint.
There are some other modifiers; run the G3D viewer or read the documentation to find out about them. You can also use a USB game pad to navigate. G3D contains other manipulators with different control styles, and you can write your own or use none at all. This is only the default.
Move the camera around a bit to get a feel for the controls. Exit your program by pressing the “ESC” key.
The G3D starter project has two build targets: Debug and Release. The Debug target allows detailed inspection of your code in the debugger and enables many consistency checks. The Release build runs much faster.
You can switch between targets in Visual Studio from the (unlabelled) Solution Configurations list box. With iCompile:
icompile --opt --run
builds and runs the Release build and the absence of --opt
defaults to the Debug build.
In general, it is safe to run in Release mode for most of development. You should immediately drop back to the debug build whenever something goes wrong with your program because it contains many assertions and input checks.
Experiment with the developer tools provided within your window, and particularly try loading
other scenes (via the SceneEditorWindow
's scene drop-down list). Exit the program when you're
ready.
Your project is in version control, but your files are just sitting in the local workspace right now. Following the process described in the Version Control Basics chapter, you'll now add and commit the files.
When you add the source files to version control, you must be careful not to add the generated files. Generated files would consume too much space in the repository and create frequent merge conflicts. The easiest way to do this is to delete everything that you don't want added and then execute a recursive command on the whole tree.
Delete the temp
, build
, x64
, Debug
, Release
, .vs
, or any other build
directories.
From the data-files
directory, delete log.txt
and g3d-license.txt
.
Delete any IDE temporary files, such as ones beginning with #
or ending in ~
, and the
Visual Studio .pdb
or .opendb
files. You can keep the ice.csv
file, which is a
spreadsheet tracking your program's growth if you're using iCompile
.
Recursively add the remaining files. At the command line, execute:
svn add *
or, for TortoiseSVN, select all files and subdirectories in Explorer and right click to add. You can also simply right click and select “Commit” and then select the files that you wish to add from the dialog that will appear.
Commit these files with:
svn commit -m "Initial checkin"
on the command line or right-clicking using TortoiseSVN and selecting “commit”. Recall that Subversion automatically pushes each commit to the remote repository, so your files are now without an explicit “push” step.
The App
class in your program inherits from G3D::GApp
, which creates a
G3D::Scene
during initialization. That Scene
parses files ending with the extension .Scene.Any
, which
are human-readable files with syntax similar to C++ code, JSON, and Python literals. These
files can be produced by hand, by another program, or using the GUI provided by
G3D::SceneEditorWindow
in the default G3D::GApp
. We'll begin by creating a scene by hand.
In your editor, create a new file data-files/scene/whiteCube.Scene.Any
with the contents:
// -*- c++ -*-
{
name = "White Cube";
models = {
cubeModel = ArticulatedModel::Specification {
filename = "model/cube/cube.obj";
preprocess = {
setMaterial(all(), Color3(1, 1, 0));
};
};
};
entities = {
skybox = Skybox {
texture = "cubemap/whiteroom/whiteroom-*.png";
};
sun = Light {
attenuation = ( 0, 0, 1 );
bulbPower = Power3(4e+006);
frame = CFrame::fromXYZYPRDegrees(-15, 207, -41, -164, -77, 77);
shadowMapSize = Vector2int16(2048, 2048);
spotHalfAngleDegrees = 5;
rectangular = true;
type = "SPOT";
};
cube0 = VisibleEntity {
model = "cubeModel";
frame = CFrame::fromXYZYPRDegrees(0, 0, 0, 0, 0, 0);
};
camera = Camera {
frame = CFrame::fromXYZYPRDegrees(0, 0, 5);
};
};
};
Launch your program and the new “White Cube” scene should appear in the scene drop down box of the GUI.
When you load the scene, you'll notice that cube in this scene is actually yellow and not
white. You should fix that. You can either guess how, or look at the
G3D::UniversalMaterial::Specification
documentation to see the arguments that can provided in the scene data file for constructing
materials. When you've made your changes, press the reload button in the Scene Editor Window
without ever exiting your program.
Whenever you create a new file, it is a good idea to add it to revision control right away so that you don't later forget. Execute:
svn add data-files/scene/whiteCube.Scene.Any
or the TortoiseSVN equivalent. This command will mark the file for addition to your repository.
You can see this by running svn status
. However, they haven't actually been added yet. To
do that, commit your changes with:
svn commit -m "Added single cube scene"
or the TortoiseSVN commit dialog.
Now your file is in the remote repository. If you modify the file, then you will need to commit the new version. But you never need to add this file again. (From now on, I'm going to assume that you know to add and commit as necessary.)
End your program with the “ESC” key and open App.cpp
in your editor. In the App::onInit
method about 50 lines from the top, add this code:
debugPrint("Target frame rate = %f Hz\n", 1.0f / realTimeTargetDuration());
Compile your program. You should see an error that looks something like:
App.cpp(58): error C3861: 'debugPrint': identifier not found
The exact wording of the error will depend on your compiler. The error is telling you that the code I told you to add is broken.
Look at the API index and you'll see
that the correct function name is G3D::debugPrintf
.
You don't need to type the G3D::
part. That's a C++ namespace, and I list it in the projects only
so that you'll know when I'm referring to a G3D function, a built-in C++ function, or something
that you're writing.
Change the code to call debugPrintf
instead of debugPrint
, compile, and run. Look for the output
of this command. It will appear in the console if you're compiling on a Unix system (OS X or Linux)
and in the Debug pane of the Output window in Visual Studio.
Edit your App::onInit
method again and add this line of code (anywhere):
const shared_ptr< Entity >& sphere = scene()->entity("Sphere");
sphere->setFrame(Point3(0.0f, 1.5f, 0.0f));
This line of code will move the object named “Sphere” to the coordinate (0, 1.5, 0) in meters. The only problem will be that there is no object named “Sphere” in the scene. When you compile and run your program, there will be an error (if you're in Release mode, it will probably crash).
To debug the program, run it under the debugger in Debug mode. In Visual Studio, select “Debug”
on the dropdown and press F5. With iCompile, run "icompile --lldb
" and then press “r” when
the debugger starts.
When the program crashes while a debugger is attached, the debugger presents the error. It
should be something like "e_Ptr was nullptr
". In this case, we know exactly where the problem
is. Pretend that we don't know, and let's see how you could figure it out on your own.
In Visual Studio, look at the Call Stack window. In lldb, type bt
. The call stack will
look something like:
App::onInit() Line 63
G3D::GApp::beginRun() Line 1424
G3D::GApp::onRun() Line 785
G3D::GApp:run() Line 768
main(int argc, const char** argv) Line 42
followed by some operating system level call frames. This says that when your program crashed,
it had started with main
, which called GApp::run
, and so on, until at line 63 the problem
occured.
In Visual Studio, double-clicking on the App::onInit
line in the Visual Studio Call Stack window
will bring up that line of code in your program. You can hover the mouse over the sphere
variable
to see its value...which is empty
. That's why the program crashed. There was no sphere, so
the sphere pointer is null. You can also look at the Autos or Locals window to see the values of
other variables. The this
pointer refers to your App
instance. Expand the tree control for it
so that you can see the current values of all of its properties.
In lldb, the f
command allows you to select a call frame by number. We're already on the top
call frame, so there is no need to use it right now. The command fr v -a
shows all local
variables, and p sphere
prints the value of the sphere variable.
The program will break and enter the debugger whenever an exception, stack overflow, or segmentation fault occurs. You can also force entry to the debugger by setting a breakpoint (“F9" in Visual Studio, “break” in lldb) or breaking the program during execution (Ctrl-Break in Visual Studio, Ctrl-C in lldb).
Remove the broken code that I told you to add for this exercise before continuing.
Generate documentation for your project using the Doxygen tool. On Windows, run:
builddoc
in the same directory as your project files and the Doxyfile
. On Unix platforms, run:
icompile --doc
The documentation will appear in build/doc
. It contains the contents of your doc-files
directory and a series of HTML files that describe every class, method, and function. The
index.html
file is the starting point for reading the documentation.
Wherever code is preceeded by a Doxygen style comment of the form /** ... */
in the header,
those comments will appear in the generated documentation. Try adding documentation to your
App
class and then re-running the documentation generator. Within Doxygen comments you can
use a subset of Markdeep formatting and HTML.
The G3D Developer Tools document summarizes the built-in features of G3D for supporting development of your program (versus supporting the program's own features). One of the most useful ones is the automatic journalling feature.
Press the “F4" key to take a screenshot in any G3D program. This brings up a dialog that allows
you to add a caption and descriptive text. It will then add the image to your journal and even
add it to version control. You'll still want to write text and add diagrams and code listing
directly in journal.md.html
, but this tool makes it easy to document your features and
debugging process.
Track how much time you spend on this project. You're required to include this in your final report.
data-files
— Files needed for running your program
source
— Your .cpp
and .h
source code
doc-files
— Files needed when viewing your documentation and report
journal
— Log of your software development progress
.Scene.Any
data files, using only the files
models/crate/*
, cubemap/whiteroom/whiteroom-*.png
, and texture maps (images):
journal/journal.md.html
separate from the report that demonstrates
your progress, particularly describing key design decisions and changes and bug symptoms and
solutions.Your solution stored in the remote repository should not have any unused files, dead code, or “TODO” comments. You are not required to remove empty or unnecessarily overridden methods (e.g.,
onGraphics3D
) for this project, although you may with to remove them to simplify your
code.
Prepare your report as a Markdeep document in doc-files/report.md.html
.
The report will appear in the build/doc
directory when read. Knowing this allows you to
insert relative links to Doyxgen-generated files (which will be in the same directory) and to
embed images that you have stored in doc-files
.
Your report should be as brief as possible while covering the following points.
There are two kinds of visual results one might present in a report:
Scientific results demonstrate correctness (or not) of a system. They may be cropped and have their histogram adjusted in Photoshop, and you can draw obvious annotations on them (such as text and arrows that clearly are not part of the result). You may not resize them, paint on them, or otherwise modify them in a way that is misleading about the actual pixels produced by your program. This is an important science/engineering issue.
Art results can be manipulated as much as you wish. In fact, and important part of creating such results is knowing how much to program and how much to manually adjust. You may end up manually correcting every frame of an animation or compositing elements of different sequences together. If it is ambiguous whether an image is intended as art, just label clearly how you manipulated it.
df(x)dx=limh→0[f(x+h)−f(x−h)2h]
Scene*
and shared_ptr<scene>
data types in C++?
App::onInit
instead of constructor
App::App
? (Tip: There are many reasons. Try throwing an exception from each, and consider
the implications of throwing an exception from a class's constructor.)
App::onGraphics3D
?
cube.obj
stored on the file system? How did the Scene
parser know
to load it from there?
Color3
. There are many more ways to
construct a G3D material, however. One of these takes separate lambertian
, glossy
,
emissive
, and transmissive
values. Speculate on why a homogeneous material (i.e., one
without a pattern or image) would require four separate “colors” in its specification.
I've mentored hundreds of people through this project and other introductory projects similar to it, from high school students through professional programmers learning about computer graphics for the first time. I've found that programmers with some expertise working on large systems, whether in school or at a company, complete it in under two hours. That's for people with no prior C++, G3D, or graphics experience.
However, students with no significant systems programming experience typically average 14 hours to complete this project left on their own. That's way too much time! If you've never spent at least three months intensively programming on some system, never worked with version control or an integrated development environment, or never worked from specifications and wrote computer-science lab reports, then you are at risk for being in this group.
Here's some advice for less-experienced systems programmers. Monitor your time investment. When it looks like you're going to take more than five hours at your current rate of progress to complete the project, immediately stop and seek advice or consider how your workflow could be improved. (And don't wait until five hours have passed! If you've spent two hours and aren't at least one third of the way through the project, stop then and consider how you're going to get across the finish line in another three hours.)
Target the minimal interpretation of the specification that you can get away with. You naturally want to do more, but finish the minimal version first and then return to areas you'd like to polish more.
Always work from a single, persistent IDE instance. This will keep you from accidentally opening the same file in two different sessions. More importantly, it will reduce your development time. I've seen students who opened a source file, found the line they needed to change, edited it, closed the editor, and then compiled. The compiler would report an error on the very next line, so they re-opened the same file, searched for the line, etc...it took those students more than twice as long to debug a program as the ones who simply kept their files open and on the right line.
Learn the keyboard shortcuts for your IDE. You're going to be copying and pasting, compiling, setting breakpoints, single-stepping, stoping your program, searching in files, etc. a lot while working on these projects. If it takes you five seconds to scroll a window, select some text, pull down a menu, and then select a command to run on the text, you've just taken five seconds for something that takes a good programmer half a second. Every time that you re-type something instead of copying and pasting or using command completion, you're incuring more overhead and giving yourself an opportunity for errors that will consume more time to correct. Saved seconds on each small task add up to hours of saved time over the course of several projects.
When trying to understand a library or language feature, imagine yourself in the API or compiler writer's place. How would you have implemented it? What constraints force that design?
Draft your report immediately, before you've accomplished much of the specification. As part of your deliverable, it will guide you in how to spend your implementation effort. When your programs become larger, trying to explain how they work before you implement them will also guide you to cleaner and simpler designs. Make very quick answers to the report questions at the beginning of the project. This will prime you to recognize the real answers as you encounter them while working on the project. Return at the end with those insights to make final answers.
The Cornell Box is a real-world box at Cornell University that has been long used for photorealistic rendering experiments. The idea is that by constructing a real scene containing only well-measured geometric primitives, we can create a perfect virtual replica and then measure rendered results against real photographs. There have been many variations on the Cornell Box. We'll model the specific one shown in Figure 2, and estimate the geometry rather than working from measurements.
|
|
This Cornell Box can be modeled using seven instances of rotated, translated, and scaled cubes. When creating your Cornell Box, scale the models, but don't rotate and translate them. Instead rotate and translate the entity placement. Were we animating the scene, that design would give us more intuitive control of the objects. It also lets us reuse objects. For example, all three white walls should be different entities that use the same model.
The setMaterial
command is one of many preprocessing options that
can appear in a G3D::ArticulatedModel::Specification
in a scene file.
To change the dimensions of a cube, you can use the transformGeometry
command, which might make part of your data file look like:
squishedCube = ArticulatedModel::Specification {
filename = "models/cube/cube.obj";
preprocess = {
setMaterial(all(), Color3(1, 0, 0));
transformGeometry(all(), Matrix4::scale(0.5, 1.0, 2.0));
};
};
You can chose the scale and need not worry about the precise colors and angles. Ensure that the walls have nonzero thickness. I chose 2 cm-thick walls for a 1 m3 box, which is about the scale of the real-world Cornell Box.
You now need to create a staircase. Specifically, a staircase with some plausible material. To make a cube appear to be made out of wood instead of solid-colored plastic, we'll vary the surface color in a wood-like pattern. The easiest way to do this is to simply take a picture of some wood seen head on and paste it onto the faces of the cube. This process is called texture mapping and the images are called textures for historical reasons.
It is very easy to texture map your cube. First, instead of the plain cube file, load
model/crate/crate.obj
into your staircase scene. You'll see that it is a staple video game
asset: a cube with images painted on it, so that it looks like a shipping crate. To make it
look like a solid block of color, you know that you can invoke the setMaterial
command in the
data file and pass a color as the third argument. You can also apply a texture by specifying a
filename (as a string) instead of a color.
Now, you just need to write code to generate a .Scene.Any
file. There are many ways to write
to disk from C++. I used the
G3D::TextOutput
class because it made it easy to embed large strings of text (e.g., for materials) that wasn't
really being generated so much as dumped out to the file. Another good option is to directly
construct a G3D::Any
and allow it to serialize directly to file.
The single cube was my example to show the parameters you can adjust and how to initialize certain classes. The Cornell Box is a classic rendering test. It demonstrates that you have sufficient control of the coordinate system and features classes to model a given scene. The staircase demonstrates that you can make your process scale and understand it well enough to automate it, as well as introducing materials.
For any rendering project you'd probably make simple scenes like this as test cases and benchmarks. Then you'd make a more interesting scene to produce visually compelling results and measure performance on more realistic data. In future projects I assume that you're using these techniques as needed to create test and benchmark scenes without it being explicitly required.
You must now design an interesting scene of your own and model it using optionally texture-mapped cubes, lights, and a sky box. Have some fun. Experiment with materials and all of the options in the scene editor GUI, even though you might not know what most of them are intended for. For example, I decided to create the dog shown in Figure 1. (You should not make the dog—you should make something else.)
I'm expecting something of about the complexity of my dog, although you're welcome to go beyond that if you enjoy the process, I'm not expecting the Taj Mahal for the first project; it just has to be more interesting than the Cornell Box!
The crate.obj
file forces you to have a single material on all cube faces because it is
modeled as a single part. The crate-unique-materials.obj
file instead defines unique
materials for each face, allowing you to create a more complex texture mapping. You can see the
names of each of the parts by clicking on them and then looking at the Info pane of the
SceneEditorWindow
. (setMaterial(all(), ...)
sets the material for all parts,
setMaterial("crate/front", ...)
sets the material for the part named "crate/front"
, and so on.)
If you're stumped for artistic inspiration, note that legos, Lincoln logs, and most other building toys, let alone most houses and other buildings are just scaled cubes. Look at the examples from previous years in the gallery section.
Visual communication and presenting your work effectively are important in any field. Learning how to compose images that read clearly, with good color palettes, camera positions, overlap, and lines is a valuable skill, and one that anyone can acquire with practice.
In computational graphics in particular, it is important to leverage visual communication skills to present algorithms in a compelling way. On one hand, we'd like like algorithms to be judged by quantitative results and analysis. On the other hand, following such analysis is a large investment on the part of the audience, and a single image can prove that an algorithm is indeed sufficient for a task. As an audience member, if someone can't show you a picture demonstrating that his or her algorithm does what you want it to, why would you bother following an analysis of just how poorly suited it is?
Most computer graphics papers and talks therefore begin with a single, visually compelling image, often called a teaser. If the teaser grabs you, then you will investigate the rest of the work to see how well the technique applies under specific targeted experiments. Those targeted experiments isolate a single phenomenon and explore how parameters and specific input scenarios affect it. They typically employ common datasets to allow comparison with previous techniques, the results of which are often shown side-by-side.
The same process is also applied outside of pure research in the context of production and engineering. Say that a technical director at a film company is investigating new shadowing methods. He or she would render a few scenes from that company's previous film with the new method to show everyone what to expect from the new algorithms. He or she would then make specific images to investigate the algorithm more carefully. For example, the hard shadow of a single edge under a point light, the soft shadow of that edge under an area light, shadows from translucent objects, cast by and on curved surfaces and so on.
For your inspiration and to set your expectations, here are some results that my students produced for this assignment:
Below are some videos that I found inspirational for this project:
I've structured these projects to be rewarding and maximize your learning. I hope that you'll enjoy them as well as increase your knowledge and skill set. I also respect your time and believe this is the fastest route to making you an excellent graphics programmer. A decade of data indicate that each project takes between three and twelve hours (depending on the project and your development pace) to complete. For most, you'll write between 100 and 400 lines of code.
These projects are not the fastest way for you to learn to make 3D scenes, images, movies, and games. There are plenty of online tutorials that will help you to accomplish that with much less effort on your part. There's a lot of value in following a “Unity 3D videos” or “DirectX in 30 days” course. But it is a different value than the one you're getting from the Graphics Codex projects.
The value that you're getting from the thorough approach of the Graphics Codex Programming Projects is comprehensive understanding from first principles. Although you need specific tools to complete the exercises, what you're learning is real computational graphics, computer science, and software development. Your knowledge will then transcend any particular API, algorithm, or toolset.
This gives you freedom and makes your skills applicable to new graphics ideas that haven't even been invented yet. It is also why I emphasize core physics, numerical methods, and algorithms over the latest real-time techniques, even though many of us are motivated by the power of real-time 3D graphics experiences.
I've worked in this field for over two decades, including shipping many video games and core technologies and publishing many research papers. In that time, I've seen many low-level optimizations and APIs rise and fall in popularity. I recall the heydays of SGI, Gouraud and Phong shading, Glide, DOT3 bump mapping, WinG, register combiners, shadow volumes, parallax mapping, GGX, D3D, and Vulkan. Hopefully, you haven't heard of most of these, and never will. As solutions highly-optimized for a specific time, they don't have much value in the future.
The hottest rendering trick of the moment often becomes embarassing old news by the following year. Only one trend has remained stable from the dawn of modern computational graphics in the 1960's through today: the increasing sophistication of both offline and real-time techniques at approximating real physics and core aesthic principles. I guarantee that techniques such as monte carlo sampling and local contrast will be more relevant for premiere graphics development in a decade than the current version of any game engine or hardware API.
You'll note that these projects provide terse specifications instead of implementation plans or programming tutorials. Working from specifications gives you many advantages in return for the effort that it requires of you.
Part of the overall educational value of these projects is you learning to solve graphics problems on your own. By specifying the properties of your program but giving you the space to decide how to achieve them, I'm teaching you to design. The point of learning graphics programming is not to make a picture (which is the goal of art), but to solve the problem of how to make the picture. I give hints as to useful topics in the documentation and code in the G3D sample projects to guide you in the right direction. You'll quickly learn to navigate the documentation, library source code, and sample source code on your own.
The advice sections give extensive design suggestions as well. But don't attempt to turn them into walkthroughs! They are intended as advice to help you solve design problems once you've already encountered them. If I've done a good job, then the advice won't make sense until you've tackled the program on your own. When you get stuck or wonder if there's a better way to approach a specific design point, that's when you should consult the advice section. Think of these as a sort of transcript of a professor's office hours or senior developer's code review.
A significant amount of a computer scientist's work in industry or academia is communication in natural language with other people. This comes in many forms, but technical precision is always to your advantage.
The projects and Graphics Codex as a whole use technical language carefully. This avoids ambiguity and allows concise communication. I hope that they also have a certain warmth that conveys my excitement about graphics and encouragement for your exploration of the field.
The specifications that I provide in the reports that you write for them also use technical language precisely. In pursuit of brevity and professionalism, they intentionally lack the warmth and personality, however. The specifications look like documents you'd find within an industry contract or engineering description.
Writing the report has many purposes. It helps ensure that you haven't missed something in your implementation. It teaches you how to test your implementation, with results that you'd demonstrate at an industry meeting or in an academic research paper to show that your program is correct. If you are using these projects in a course, then your instructor will probably also grade the report.
Good software developers are massively more productive than average ones. While this is a topic of some political debate within the field, in practice I've never seen a software company in which everyone didn't know who the top developers were and recognize that they accomplished much more than their less-experienced colleagues. That's a positive sign. It would be very concerning for our discipline if people who worked hard for many years weren't able to outperform newer developers. Every field has its masters.
These projects encourage you to learn to use your editor, debugger, profiler, documentation, and version control system with the facility that a master carpenter employs their tools or a professional musician their instrument. Invest time in accomplishing simple tasks quickly and complex tasks cleanly and without stress.
One of the goals of writing the report is to reflect on your process. That's why I ask you about time spent. In the course of working through these projects, most people get much faster. The Meshes project takes some people five hours to complete. By the end of the sequence, they can return to it and complete it in about an hour.
The craft of software development is, like most others, best learned through an in-person mentor. Unless you're enrolled in one of my courses, that is unfortunately something I can't provide in these projects. So, if you are working through these projects on your own (instead of in a course) and are relatively new to software development, then I recommend seeking out such a mentor and discussing the projects with them.
Graphics Codex Projects © 2018 Morgan McGuire
This document is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. You may redistribute this document, including modifications, for noncommercial purposes as long as this copyright statement remains unmodified and your work is indicated as a derivative work.
This document is written in Markdeep to make it easy for teachers to modify it for use in their own courses. Just view the source in a browser and then save it.
All C++ and GLSL source code in this document is released into the public domain to avoid IP concerns on your own project solutions. That code may be used in any project, including commercially without attribution.
Images by others, the G3D Innovation Engine, the Graphics Codex are not covered by this document's copyright and license.
Images with citations are property of their respective owners.
The G3D Innovation Engine © 2000-2018 Morgan McGuire, available under the 2-clause BSD license.
The Graphics Codex © 2011-2018 Morgan McGuire. All rights reserved.