-
Notifications
You must be signed in to change notification settings - Fork 83
TinyApp
The TinyApp sample application that is included with Lighthouse 2 demonstrates how the system can be used in a small application. It is also useful for starting your own application: to do this:
- copy the project folder
- rename the project files
- replace TinyApp with your own project name in the .vcxproj file
- add your project to the solution
- set your project dependencies.
At the top of main.cpp three variables are declared:
static RenderAPI* renderer = 0;
static GLTexture* renderTarget = 0;
static Shader* shader = 0;
The renderer refers to the RenderSystem, which will be our contact in the Lighthouse 2 system: it loads and stores the scene, accepts scene changes, and it communicates with the render core, which is the low-level rendering component. Variable renderer
is initialized in the main function:
renderer = RenderAPI::CreateRenderAPI( "rendercore_optixprime_b.dll" );
Any of the available dlls should work, but each of them may implement the API differently. In this case the optixprime_b render core is used, which implements a simple path tracer ('_b' stands for 'basic') and uses NVidia's Optix Prime to trace rays. Obviously Optix Prime requires an NVidia GPU. In practice not all cores will be compatible (or efficient) on your hardware.
The renderTarget is a GLTexture. The GLTexture object is a thin wrapper around an actual texture ID (GLuint), which also stores the texture width and height. All rendering will be done to this texture. This is important, because a texture resides in GPU memory, so rendering and displaying the rendering result does not involve any CPU-GPU traffic. For a real-time system this is absolutely essential.
The shader is the shading code that is executed when the texture is presented to the user. This can be a dummy shader that simply shows the texture on a full-screen quad, or it can be a simple post-processing shader. If you need anything more, you may want to setup your own post-processing pipeline.
Initialization
A scene is prepared in PrepareScene. For this, a mesh is added to the scene using the AddMesh method. In this case a gltf file is loaded; it is also possible to add obj files and fbx files. The final parameter of AddMesh is a scale, and the function returns an identifier for the loaded object.
The second mesh is a quad, which is not loaded but constructed from code. The material for this quad is light emitting: its color components exceed 1.
Meshes do not show up in the scene unless we add instances using the meshes. In this case, one instance of the worldID mesh and one instance of the lightQuad mesh are added.
Main
The application is a regular application which requires a main function. Lighthouse 2 does not take over your main loop, which also means that Lighthouse 2 can be added to an existing application, as long as you are able to provide it with a render target in the form of an OpenGL texture. In the TinyApp, a window is opened using GLFW, and a GLFW event loop is started, which runs until escape is pressed (this functionality is provided in main_tools.h).
Rendering
To render an image we need a few actions:
- We need to update the scene using SynchronizeSceneData. In TinyApp the scene doesn't change, so we could probably do this outside the loop, and just once.
- We need to call Render, with a boolean that tells the renderer to converge or not. Lighthouse 2 is built with path tracing in mind, and path tracers will generally want to average frames with earlier frames if the camera is not moving.
Closing down
Once we are done rendering we may shut down the RenderSystem properly using the Shutdown method.
Camera
The scene contains a camera, which is used for rendering. Basic camera movement is illustrated in the HandleInput function.