LuxCore - LuxRender Wiki
Luxrender GPL Physically Based Renderer

LuxCore

Personal tools

From LuxRender Wiki

Revision as of 10:47, 6 November 2015 by Dade (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Contents

Introduction

The plan for LuxRender 2.0 has been defined during the 2013 summer and one of the major components is going to be a new LuxRender C++ and Python API. The old C API suffers of many limitations when it comes to modern features like dynamic scene editing and iterative rendering so it has been decided to write a completely new API instead of improving the old one. LuxCore is the name of the new C++/Python API. It offers all the features shown by SLG in the past (in terms of dynamic camera, textures, materials, objects, etc. editing) and more. The forum discussion about this topic can be found here

Apache Licence 2.0

All the code included in LuxRays repository (i.e. LuxRays, LuxCore, LuxCore implementation aka SLG) has been released under a new license: Apache Licence 2.0. It is a very liberal license allowing the use of the code inside commercial products too.

PyLuxCore: the Python API

Python has become the de facto standard language for scripting in computer graphics. It has been recently adopted by AutoDesk 3Dsmax too and it was already in use by Blender, Maya, MODO, etc. For this reason the Python bindings of the API will be a first class passenger like C++ and they will be developed at the same time of the C++ API. However nothing stops anyone from writing Ruby, Java, etc. API bindings.

Known limitations

LuxCore doesn't yet support all features available in LuxRender. The forum discussion where you can read the news about new features can be found here.

Examples and Demos

LuxCore related examples and demos can be found in the LuxRays Mercurial repository under the samples directory.

PyLuxCoreDemo

A complete renderer in 50 lines of Python [1]:

import time
import sys
from array import *
sys.path.append("./lib")

import pyluxcore

pyluxcore.Init()

print("LuxCore %s\n" % pyluxcore.Version())

################################################################################
## RenderConfig and RenderSession examples
################################################################################

print("RenderConfig and RenderSession examples (requires scenes directory)...")

# Load the configuration from file
props = pyluxcore.Properties("scenes/luxball/luxball-hdr.cfg")

# Change the render engine to PATHCPU
props.Set(pyluxcore.Property("renderengine.type", ["PATHCPU"]))

config = pyluxcore.RenderConfig(props)
session = pyluxcore.RenderSession(config)

session.Start()

startTime = time.time()
while True:
	time.sleep(1)

	elapsedTime = time.time() - startTime

	# Print some information about the rendering progress

	# Update statistics
	session.UpdateStats()

	stats = session.GetStats();
	print("[Elapsed time: %3d/5sec][Samples %4d][Avg. samples/sec % 3.2fM on %.1fK tris]" % (
			stats.Get("stats.renderengine.time").GetFloat(),
			stats.Get("stats.renderengine.pass").GetInt(),
			(stats.Get("stats.renderengine.total.samplesec").GetFloat()  / 1000000.0),
			(stats.Get("stats.dataset.trianglecount").GetFloat() / 1000.0)))

	if elapsedTime > 5.0:
		# Time to stop the rendering
		break

session.Stop()

# Save the rendered image
session.GetFilm().Save()

print("Done.")

PySideLuxCoreDemo

Most of the LuxCore features (camera, textures, materials, objects editing, etc.) shown in 500 lines of Python code [2].

PySideLuxCoreDemo screenshot


Blender LuxCore Render Engine

A 250 lines long render engine for Blender based on PyLuxCore (source code here).

LuxCore Blender Engine screenshot


Supported GPUs

LuxCore will run on any OpenCL v1.1 compliant device (CPUs, GPUs, etc.). However some hardware may have driver bugs and resource limits preventing LuxCore from running correctly. Follow some guide line to select a good device:

  • AMD GPUs: anything older than HD7xxx family (first AMD GPUs with GCN architecture) is likely to have problems to render complex scenes. Anything smaller than a HD7850 is likely to not have enough resources to be used for renderings.
  • NVIDIA GPUs: anything older than GTX4xx family is likely to have problems to run LuxCore. Anything smaller than a GTX460/GTX560/etc. is likely to not have enough resources to be used for renderings.
  • Intel GPUs: even Intel very high-end GPUs (i.e. Iris Pro) may have problems to run LuxCore. Anything smaller (for instance an HD4600) is not able to be used for renderings at all.
  • Apple: Fully working OpenCL is included with OSX 10.10 Yosemite ( v1.2 ). All NVidia supporting OpenCL 1.1 and supported by the NV or Apple provided drivers should work. For AMD GCN gpu is recommended, VLIW gpu's from 5770 and higher work, but with resource limitations.
  • Apple sidenote: OpenCL 1.1 started with OSX 10.7.5 ( Lion ) but was never working reliable with AMD including 10.9.5. It is unlikely that the 10.10 drivers get backported to 10.9 ever. NVidia also gives the choice to install extra drivers, but it is unknown yet which OSX/driver combinations are working.
  • use Desktop PCs for renderings, not laptops. Laptops are usually not designed to the load required for renderings and to dissipate the heat (for extended periods of time). Only high-end mobile GPUs are likely to be able to run LuxCore.

Known working configuration with LuxCore:

OS GPU
Linux Ubuntu 14.04 AMD FirePro W8100
Linux Ubuntu 14.04 AMD HD7970
Windows 7 64bit AMD FirePro W8100
Windows 7 64bit AMD HD7970
Windows 7 64bit AMD GTX560
Windows 7 64bit AMD GTX780
Windows 7 64bit AMD GTX970
OSX 10.10 Yosemite AMD 79xx
OSX 10.10 Yosemite AMD FireProDxx
OSX 10.10 Yosemite NVidia GTX 780(ti/m)
OSX 10.10 Yosemite NVidia GTX 970/980

SDL (Scene Description Language)

The SDL is an integral part of the API and it is the very first component to learn in order know how to use LuxCore.

Property

A property is the very basic building block of the SDL. It is nothing else than a line of text:

this.is.the.name = value0 value1 ... valueN

"this.is.the.name" is the name of the property (sometime also referred as the key). Allowed values are integers, real numbers or strings separated by spaces. Strings should placed between quotes (" or ') in order to avoid problems with spaces.

Properties file

A Properties file is a text file with a list of Property entries. The "." can be used in names to conceptually group together different properties. For instance:

scene.materials.shell.type = glossy2
scene.materials.shell.kd = 0.5 0.0 0.0
scene.materials.shell.ks = 0.5 0.5 0.5
scene.materials.shell.uroughness = 0.1
scene.materials.shell.vroughness = 0.2

defines a material named "shell". The "scene.materials.shell" is the root of a node grouping together the ".type", ".kd", ".ks", etc. leafs.

The render configuration file

A render configuration file is what describe the rendering. It is a Properties file ending with the ".cfg" extension. It includes the definition of all properties related to the configuration of the rendering like:

  • render engine to use;
  • render engine specific options;
  • image resolution and outputs;
  • OpenCL settings;
  • reference to a scene file;
  • etc.

The reference to the scene file is defined by the "scene.file" property:

scene.file = scenes/luxball/luxball-hdr.scn

Film

Film related properties in the render configuration file starts with the "film." prefix.

AOVs (Arbitrary Output Variables)

AOVs (Arbitrary Output Variables) support provides a way to render different channels (i.e. the rendering output is not just a single image but many with different kind of information). The different output channels can later be used to achieve many kind of composting effects and tricks. The complete list of variables supported is available in LuxCore SDL reference manual.

The content of the channel should be easy to understand from the name. The syntax to enable AOVs is:

film.outputs.1.type = RGB_TONEMAPPED
film.outputs.1.filename = luxball_RGB_TONEMAPPED.png
film.outputs.2.type = DEPTH
film.outputs.2.filename = luxball_DEPTH.exr
film.outputs.3.type = POSITION
film.outputs.3.filename = luxball_POSITION.exr
film.outputs.4.type = SHADING_NORMAL
film.outputs.4.filename = luxball_SHADING_NORMAL.exr
film.outputs.5.type = MATERIAL_ID_MASK
film.outputs.5.id = 255
film.outputs.5.filename = luxball_MATERIAL_ID_MASK_255.png
film.outputs.6.type = MATERIAL_ID_MASK
film.outputs.6.id = 128
film.outputs.6.filename = luxball_MATERIAL_ID_MASK_128.png

This is the list of data types and size can be found in LuxCore SDL reference manual.

Light groups

LuxRender Light groups are supported. You can assign a light source to a group using ".id" property for sun/sky/infinitelight/etc. and ".emission.id" for materials, for instance:

scene.materials.whitelight.type = matte
scene.materials.whitelight.emission = 120.0 120.0 120.0
scene.materials.whitelight.emission.id = 0

scene.lights.infinitelight.file = scenes/simple-mat/arch.exr
scene.lights.infinitelight.gain = 4.0 4.0 4.0
scene.lights.infinitelight.id = 1

The default ID is 0 and IDs are supposed to be a sequence starting from 0 (otherwise memory is wasted for unused light groups). The output can be controlled with the following properties:

# Film outputs
film.outputs.1.type = RGB
film.outputs.1.filename = simple_RGB.exr
film.outputs.2.type = RADIANCE_GROUP
film.outputs.2.id = 0
film.outputs.2.filename = simple_LIGHT_GROUP_0.exr
film.outputs.3.type = RADIANCE_GROUP
film.outputs.3.id = 1
film.outputs.4.filename = simple_LIGHT_GROUP_1.exr

Note that the OpenCL renderengines (BIASPATHOCL and PATHOCL) have a limit of 8 lightgroups[3].

Image pipeline

Two Film output channels are not a direct result of the rendering but the product of the image pipeline (applied to the output of the rendering):

  • RGB_TONEMAPPED channel;
  • RGBA_TONEMAPPED channel (indeed, this channel is just the above output plus alpha information).

The image pipeline has an plug-in based and configurable architecture where any number of plug-in instances can be used to build the pipeline. For instance, this is the definition of the default pipeline:

film.imagepipeline.0.type = TONEMAP_AUTOLINEAR
film.imagepipeline.1.type = GAMMA_CORRECTION
film.imagepipeline.1.value = 2.2

The image pipeline is just built with 2 plugins: the autolinear tonemapper and a the comma correction.

The plug-ins

At the moment, this is the list of supported plug-ins:

  • linear tone mapper (TONEMAP_LINEAR);
  • LuxRender-like linear tone mapper(TONEMAP_LUXLINEAR);
  • autolinear tone mapper (TONEMAP_AUTOLINEAR);
  • Reinhard02 tone mapper (TONEMAP_REINHARD02);
  • gamma correction;
  • output switcher;

The internal names and parameters can be found here (useful for exporter developers): http://www.luxrender.net/forum/viewtopic.php?f=8&t=10656&p=109199#p109199

This is another example of pipeline:

film.imagepipeline.0.type = OUTPUT_SWITCHER
film.imagepipeline.0.channel = DEPTH
film.imagepipeline.1.type = TONEMAP_AUTOLINEAR
film.imagepipeline.2.type = GAMMA_CORRECTION
film.imagepipeline.2.value = 2.2

The OUTPUT_SWITCHER will overwrite RGB values with the one coming from the DEPTH buffer; TONEMAP_AUTOLINEAR will map the values between 0 and 1 and GAMMA_CORRECTION will gamma correct the values. The result is that the output will show the Z-Buffer (in shade of grays) instead of the normal RGB buffer. The same can be applied to any output channel like light groups, eye/light sampling in BiDir, etc.

Scene file

A scene file describes the scene to render. It is a Properties file ending with the ".scn" extension. It includes 4 main groups of properties:

  • texture definitions;
  • material definitions;
  • object definitions;
  • light definitions;
  • camera definition.

Textures definitions

The definition of all textures is under the prefix "scene.textures". For instance:

scene.textures.tex.type = imagemap
scene.textures.tex.file = scenes/bump/map.png
scene.textures.tex.gain = 0.6
scene.textures.tex.mapping.uvscale = 16 -16
scene.textures.check.type = checkerboard2d
scene.textures.check.texture1 = 0.7 0.0 0.0
scene.textures.check.texture2 = 0.7 0.7 0.0
scene.textures.check.mapping.uvscale = 16 -16

defines 2 textures named "tex" (an image map texture) and "check" (a procedural checkerboard) texture.

Material definitions

The definition of all materials is under the prefix "scene.materials". For instance:

scene.materials.shell.type = matte
scene.materials.shell.kd = check
scene.materials.whitematte.type = matte
scene.materials.whitematte.kd = 0.75 0.75 0.75

defines 2 materials named "shell" and "whitematte". Note how the ".kd" component of the "shell" material references a texture named "check". Every material parameter can be a constant (for instance "0.75 0.75 0.75" for a white RGB color) or the name of a texture defined in texture section of the scene file.

Object definitions

The definition of all objects is under the prefix "scene.objects". For instance:

scene.objects.luxtext.material = text
scene.objects.luxtext.ply = scenes/luxball/luxball-text.ply
scene.objects.luxshell.material = shell
scene.objects.luxshell.ply = scenes/luxball/luxball-shell.ply

defines 2 objects named "luxtext" and "luxshell". The first object uses the material named "text" and the second the material named "shell". The geometry definitions of the objects are in external PLY files. Triangle is the only kind of primitive supported.

Light definitions

There are 6 kind of light sources at the moment:

  • Area light
  • Infinite light
  • Sun light
  • Sky light
  • Point light
  • MapPoint light

The definition of all light sources is under the prefix "scene.lights". For instance:

scene.lights.infinitelight.type = infinite
scene.lights.infinitelight.file = scenes/simple-mat/sky.exr
scene.lights.infinitelight.gain = 0.9 0.9 0.9
scene.lights.sunlight.type = sun
scene.lights.sunlight.dir = 0.166974 -0.59908 0.783085
scene.lights.sunlight.turbidity = 2.2
scene.lights.sunlight.gain = 0.5 0.5 0.5

defines 2 lights named "infinitelight" and "sunlight". The definition of area lights is somewhat a special case because it is an attribute of material definition, for instance:

scene.materials.whitematte.kd = 0.75 0.75 0.75
scene.materials.whitelight.type = matte
scene.materials.whitelight.emission = 30.0 30.0 30.0

Area light

An area light is an object emitting light. The amount of light emitted is set in the material definition:

scene.materials.whitelight.type = matte
scene.materials.whitelight.emission = 40.0 40.0 40.0

Any material can emit light.

Infinite light

The infinite light encloses the scene entirely, lighting it all angles. It is normally used for environment mapping. For instance:

scene.lights.infinitelight.type = infinite
scene.lights.infinitelight.file = scenes/simple-mat/sky.exr
scene.lights.infinitelight.gain = 0.9 0.9 0.9

Sky light

Sky light source works like Infinite light but it is defined by a mathematical model of the sky instead of an image map. For instance:

scene.lights.skylight.type = sky
scene.lights.skylight.dir = 0.166974 -0.59908 0.783085
scene.lights.skylight.turbidity = 2.2
scene.lights.skylight.gain = 1. 1. 1.

Sun light

Sun light source is defined by a mathematical model of the sun. It can be combined with a Sky light or a with Infinite light for a realistic result. For instance:

scene.lights.skylight.type = sun
scene.lights.sunlight.dir = 0.166974 -0.59908 0.783085
scene.lights.sunlight.turbidity = 2.2
scene.lights.sunlight.gain = 1. 1. 1.

Point light

For instance:

scene.lights.l1.type = point
scene.lights.l1.position = -3.0 -5.0 7.0
scene.lights.l1.gain = 1.0 1.0 1.0

MapPoint light

A MapPoint light is a point light source emitting light according an emission map. The emission map can be an image or a IES profile. For instance:

scene.lights.l1.type = mappoint
scene.lights.l1.position = -3.0 -5.0 6.0
scene.lights.l1.gain = 1.0 1.0 1.0
scene.lights.l1.mapfile = scenes/bump/map.png
scene.lights.l1.iesfile = scenes/bigmonkey/ASA_15M_R2.ies
scene.lights.l1.flipz = 1
scene.lights.l1.map.width = 512
scene.lights.l1.map.height = 256

Spot light

Spot lights are infinitely small lights that emit light in a cone shape. Apart from colour and location, the width of the cone can be set (as the number of degrees of the centerline it will extend), and there is a setting to feather the intensity towards the edge. For instance:

scene.lights.l1.type = spot
scene.lights.l1.position = -3.0 -5.0 6.0
scene.lights.l1.target = -3.0 -5.0 0.0
scene.lights.l1.gain = 500.0 500.0 500.0
scene.lights.l1.coneangle = 60.0
scene.lights.l1.conedeltaangle = 50.0

SDL reference manual

The reference manual is available here.

C++ API

LuxCore Python and C++ API are, aside from few language related difference, the same. Check Python API for some explanation. C++ API is also documented with Doxygen comments in luxcore.h header.

Python API

LuxCore API is based on few objects:

  • Properties
  • Scene
  • RenderConfig
  • RenderSession
  • Film
  • Camera

Initialization

Before anything else, you have to call pyluxcore.Init() function:

import pyluxcore

def LogHandler(msg):
	print("[%s]%s" % (strftime("%Y-%m-%d %H:%M:%S", gmtime()), msg))

def main():
	pyluxcore.Init(LogHandler)
	print("LuxCore %s" % pyluxcore.Version())

pyluxcore.Init() accept an optional log handler where you can filter and/or redirect all LuxCore log messages.

Property and Properties

The Properties object is a container used mostly to store fragments of LuxCore SDL (Scene Description Language) language. For instance, a fragment with a material definition can be created with the following code:

props = pyluxcore.Properties().
	Set(pyluxcore.Property("scene.materials.shell.type", ["mirror"])).
	Set(pyluxcore.Property("scene.materials.shell.kr", [0.75, 0.75, 0.75]))

You can load Properties from a file with:

props = pyluxcore.Properties("scenes/luxball/luxball-hdr.cfg")

You can add or overwrite a single property with:

props.Set(pyluxcore.Property("renderengine.type", ["PATHCPU"]))

Scene

The Scene objects is a container for the following information:

  • image map cache (i.e. .png, .jpg, .exr, etc. files)
  • mesh cache (i.e. .ply files)
  • texture definitions
  • material definitions
  • object definitions
  • light definitions

A scene can be created from a file:

scene = pyluxcore.Scene("scenes/luxball/luxball-hdr.scn", 1.f)

where the first parameter is the name of a .scn file and the second is a uniform scale applied to all image map loaded (i.e. it is usually 1.0 but you can be smaller value in order to save precious GPU ram). A scene can be also created without the need of a file as an empty object:

scene = pyluxcore.Scene(1.f)

You can than add new definitions by using the Parse() method:

scene.Parse(pyluxcore.Properties().
	Set(pyluxcore.Property("scene.materials.shell.type", ["mirror"])).
	Set(pyluxcore.Property("scene.materials.shell.kr", [0.75, 0.75, 0.75])))

RenderConfig

The RenderConfig object include information on how render a scene like render engine type, image resolution, etc. It can be created with an existing Properties and a Scene:

scene = pyluxcore.Scene("scenes/luxball/luxball-hdr.scn", 1.f)
props = pyluxcore.Properties("scenes/luxball/luxball-hdr.cfg")
props.Set(pyluxcore.Property("renderengine.type", ["PATHCPU"]))
config = pyluxcore.RenderConfig(props, scene)

If the Properties object includes the definition of "scene.file", you can avoid to create the Scene, it will be read from the file:

props = pyluxcore.Properties("scenes/luxball/luxball-hdr.cfg")
config = pyluxcore.RenderConfig(props)

RenderSession

Once you have a RenderConfig, you need to create a RenderSession to effectively run the rendering. This is a complete example:

import time
import sys
from array import *
sys.path.append("./lib")

import pyluxcore

pyluxcore.Init()

print("LuxCore %s\n" % pyluxcore.Version())

################################################################################
## RenderConfig and RenderSession examples
################################################################################

print("RenderConfig and RenderSession examples (requires scenes directory)...")

# Load the configuration from file
props = pyluxcore.Properties("scenes/luxball/luxball-hdr.cfg")

# Change the render engine to PATHCPU
props.Set(pyluxcore.Property("renderengine.type", ["PATHCPU"]))

config = pyluxcore.RenderConfig(props)
session = pyluxcore.RenderSession(config)

session.Start()

startTime = time.time()
while True:
	time.sleep(1)

	elapsedTime = time.time() - startTime

	# Print some information about the rendering progress

	# Update statistics
	session.UpdateStats()

	stats = session.GetStats();
	print("[Elapsed time: %3d/5sec][Samples %4d][Avg. samples/sec % 3.2fM on %.1fK tris]" % (
			stats.Get("stats.renderengine.time").GetFloat(),
			stats.Get("stats.renderengine.pass").GetInt(),
			(stats.Get("stats.renderengine.total.samplesec").GetFloat()  / 1000000.0),
			(stats.Get("stats.dataset.trianglecount").GetFloat() / 1000.0)))

	if elapsedTime > 5.0:
		# Time to stop the rendering
		break

session.Stop()

# Save the rendered image
session.GetFilm().Save()

print("Done.")

After the creation of a RenderConfig and RenderSession, the rendering is started by calling the Start() method. The rendering will run asynchronously in background. UpdateStats() is used to update the statistics and GetStats() is used to retrieve them. Every 1 seconds, some statistics about the rendering is printed on screen and after 5 seconds, the rendering is stopped by calling Stop() method. From RenderSession object the Film can be retrieved and saved too.

Dynamic scene editing

During a rendering session, you can dynamically edit any aspect of the scene (textures, materials, objects, lights, etc.). For instance:

# Begin scene editing
session.BeginSceneEdit()

# Edit the material
scene.Parse(pyluxcore.Properties().
	Set(pyluxcore.Property("scene.materials.shell.type", ["glass"])).
	Set(pyluxcore.Property("scene.materials.shell.kr", [0.69, 0.78, 1.0])).
	Set(pyluxcore.Property("scene.materials.shell.kt", [0.69, 0.78, 1.0])).
	Set(pyluxcore.Property("scene.materials.shell.ioroutside", [1.0])).
	Set(pyluxcore.Property("scene.materials.shell.iorinside", [1.45]))
	)
		
# End scene editing
session.EndSceneEdit()
print("LuxBall material set to: Glass")

Before anything else you have to call the RenderSession.BeginSceneEdit() method. Than you can modify the Scene object as you like by using the Scene.Parse() method and close the editing session with RenderSession.EndSceneEdit(). Once you call EndSceneEdit(), the rendering will restart with the modified scene. LuxCore will minimize the amount of work required to update the scene and will transferred to the GPUs only the modified parts of the scene.

Dynamic render configuration editing

If you need to change one of the render configuration parameter, the sequence of commands is:

# Stop the rendering
session.Stop()
session = None

# Set the new size
config.Parse(pyluxcore.Properties().
	Set(pyluxcore.Property("film.width", [newFilmWidth])).
	Set(pyluxcore.Property("film.height", [newFilmHeight])))

# Re-start the rendering
session = pyluxcore.RenderSession(config)
session.Start()

This code will change stop the current rendering, change the rendering resolution to the values of newFilmWidth x newFilmHeight and restart the rendering with a new RenderSession.

Film

The Film object contains the results of the ongoing rendering in a RenderSession. The only way to obtain a Film is from a RenderSession. LuxCore supports AOVs (Arbitrary Output Variables). The AOVs related development forum thread can be found here. Film.Save() method can be use to save all the AOVs configured in the RenderConfig.

The image pipeline

The development forum thread can be found here.