This project is part of the thi.ng collection of Clojure & Clojurescript libraries.
Luxor is a Clojure based LXS scene graph compiler, generator & mesh exporter for Luxrender (v1.3+), an open source, physically based and unbiased rendering engine.
ALPHA quality, docs forthcoming. Note, only the most commonly used Lux functionality is implemented thus far, but more feature support is planned. All Lux entity generators use the same default values as specified in the official LXS syntax reference:
http://www.luxrender.net/wiki/Scene_file_format_dev
Since Luxrender has a lot of options for its various scene components, it is highly recommended to study the above reference in order to customize defaults and obtain high quality renders.
(require 'thi.ng.luxor.core)
;; TODO some magic
The code below is responsible for the example image above. To run, just clone this repo, tangle all files (see below), launch a REPL and load the example:
(load-file "examples/test-scene.clj")
The resulting LXS scene file and meshes are saved in the project root dir (additionally all scene components are saved as ZIP file too). Double click the LXS file to launch in Luxrender.
(require
'[thi.ng.luxor.core :refer :all]
'[thi.ng.luxor.io :as lio]
'[thi.ng.geom.core :as g]
'[thi.ng.geom.aabb :as a]
'[thi.ng.geom.rect :as r]
'[thi.ng.geom.polygon :as p]
'[thi.ng.math.core :as m])
;; see LXS syntax ref for description of these entities & options
;; http://www.luxrender.net/wiki/Scene_file_format_dev
(do ;; wrap in `do` form to avoid full scene dump in repl (optional/cosmetic)
(->
;; empty default lux scene
(lux-scene)
;; configure scene to collect meshes during serialization
;; (needed for ZIP export)
(configure-meshes-as-byte-arrays)
;; customize sampler & renderer
(renderer-sampler)
(sampler-ld {})
(integrator-bidir {})
;; camera setup
(camera
{:eye [5 -5 5] :target [0 0 0] :up [0 0 1]})
;; film size, color response profile, progress updates, stop condition (samples per pixel)
(film
{:width 1280 :height 720
:response :agfachrome-rsx2-200cd
:display-interval 5 :halt-spp 1000})
;; tonemap config (must be given after film)
(tonemap-linear
{:iso 100 :exposure 0.5 :f-stop 8 :gamma 2.2})
;; define medium with milky consistency (used for material below)
(volume
:inside {:type :clear :absorb [0.97 0.8 0.7] :abs-depth 0.2 :ior 2.04})
;; semi-translucent material w/ above medium as interior
(material-matte-translucent
:milk {:interior :inside :reflect [0.3 0.3 0.3] :transmit [0.8 0.7 0.6]})
;; standard matt white for background/room box
(material-matte :white {:diffuse [0.8 0.8 0.8]})
;; studio light setup: 1x top light, 2x left/right fillers
;; we assign them to light groups so they can be tweaked or disabled
;; in Luxrender during rendering...
(light-groups {:top {:gain 32.0} :fill {:gain 3.0}})
(area-light :top {:p [0 0 5] :size [8 8] :group :top})
(area-light :left {:p [0 0 4] :size [2 4] :group :fill
:tx {:translate [-3 0 0] :ry -30}})
(area-light :right {:p [0 0 4] :size [2 3] :group :fill
:tx {:translate [3 0 0] :ry 30}})
;; add scene geometries:
;; room box to trap light
(ply-mesh
:room {:material :white
:tx {:translate [0 0 8] :scale 16 :rz 45}
:mesh (-> (a/aabb 1) (g/center) (g/as-mesh))})
;; 16x16 grid of boxes
;; takes a single rect, subdivides it into 256 smaller rects
;; then extrudes each individually as walled mesh
;; and re-combines into single mesh
;; extrusion height and wall thickness is based on distance to center
;; and passed through cosine fn
(ply-mesh
:grid {:material :milk
:tx {:translate [0 0 0.1] :scale [2 2 1]}
:mesh (->> (-> (r/rect 5) (g/center) (g/subdivide {:num 16}))
(map
#(-> (g/scale-size % 0.9)
(g/as-polygon)
(g/extrude-shell
(let [d (-> (g/centroid %)
(g/mag)
(m/map-interval [0 3.75] [0 m/HALF_PI])
(Math/cos))]
{:depth (* 2 d) :wall (- 0.15 (* d 0.125))}))))
(reduce g/into))})
;; finally serialize & output LXS scene files and meshes
;; the `false` arg means materials, objects and volumes
;; are included in the main scene file and not written as separate files
(lio/serialize-scene "luxor-test" false)
;; export scene files
(lio/export-scene)
;; additionally export all scene components as zip
;; (useful for when creating animations, each frame exported as archive)
(lio/export-archived-scene "luxor-test.zip"))
(println "done."))
- thi.ng.luxor.core
- thi.ng.luxor.compiler
- thi.ng.luxor.io
- thi.ng.luxor.color
- thi.ng.luxor.config & presets
- thi.ng.luxor.primitives
- thi.ng.luxor.scenes
0.3.1
[org.clojure/clojure "1.7.0-RC1"]
[thi.ng/geom "0.0.815"]
[thi.ng/color "0.2.0"]
[thi.ng/math "0.1.2"]
[com.stuartsierra/dependency "0.1.1"]
[criterium "0.4.3"]
[thi.ng/luxor "0.3.1"]
This project is written in a literate programming format and requires
Emacs & Org-mode to generate usable source code. Assuming both tools
are installed, the easiest way to generate a working project is via
command line (make sure emacs
is on your path or else edit its path
in tangle.sh
):
git clone https://github.com/thi-ng/luxor.git
cd luxor
./tangle.sh src/*.org test/*.org
Tangling is the process of extracting & combining source blocks from
.org
files into an actual working project/source tree. Once tangling
is complete, you can cd
into the generated project directory
(babel
) and then use lein
as usual.
The project.clj
file defines an alias to trigger a complete build &
test run. Note: There are currently NO tests, though…
cd babel
lein cleantest
Re-loading & testing changes is quite trivial. Simply launch a REPL
(via lein
or Emacs) as usual. Everytime you’ve made changes to an
.org
file, re-tangle it from Emacs (C-c C-v t
) or tangle.sh
,
then reload the namespace in the REPL via (require
'thi.ng.luxor... :reload)
or similar.
(defproject thi.ng/luxor "<<version>>"
:description "Scene graph compiler, generator & mesh exporter for Luxrender"
:url "<<project-url>>"
:license {:name "Apache Software License 2.0"
:url "http://www.apache.org/licenses/LICENSE-2.0"
:distribution :repo}
:scm {:name "git"
:url "https://github.com/thi-ng/luxor"}
:dependencies [<<dep-clj>>
<<dep-geom>>
<<dep-color>>
<<dep-math>>
<<dep-depgraph>>]
:profiles {:dev {:dependencies [<<dep-criterium>>]
:aliases {"cleantest" ["do" "clean" "test"]}}}
:pom-addition [:developers [:developer
[:name "Karsten Schmidt"]
[:url "http://postspectacular.com"]
[:timezone "0"]]])
The autogenerated namespace thi.ng.luxor.version
contains a single
symbol version
holding the version string defined above:
(use '[thi.ng.luxor.version])
(prn version)
; "<<version>>"
Version | Released | Description | Lein coordinates | Tagged Github URL |
---|---|---|---|---|
0.3.1 | 2015-06-05 | update dependencies, bugfixes | [thi.ng/luxor "0.3.1"] | 0.3.1 |
0.3.0 | 2015-02-25 | Project restructure, API additions | [thi.ng/luxor "0.3.0"] | 0.3.0 |
0.2.0 | 2014-03-10 | 1st public release | [thi.ng/luxor "0.2.0"] | 0.2.0 |
Name | Role | Website |
---|---|---|
Karsten Schmidt | initiator & principal developer | http://postspectacular.com |
This project is open source and licensed under the Apache Software License 2.0.