docs: First stab at ReadTheDocs (#1736)
Convert the LaTeX docs to Sphinx + Myst Markdown extension I think this is in decent shape. It's going to need a lot of thorough proofreading to ensure that thing got lost or mangled on the way from the original docs. I suspect we will have several follow-up PRs to fix thing. After we're reasonably happy with it, we'll eventually remove the .tex and the pdf. Signed-off-by: Larry Gritz <lg@larrygritz.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# .readthedocs.yml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Set the OS, Python version and other tools you might need
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
|
||||
|
||||
# Build documentation with Sphinx
|
||||
sphinx:
|
||||
configuration: src/doc/conf.py
|
||||
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF and ePub
|
||||
formats:
|
||||
- pdf
|
||||
- htmlzip
|
||||
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
install:
|
||||
- requirements: src/doc/requirements.txt
|
||||
+2556
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@@ -30,3 +30,35 @@ clean:
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
|
||||
doxygen:
|
||||
echo "make doxygen TBD"
|
||||
doxygen Doxyfile
|
||||
touch doxygen.turd
|
||||
|
||||
doxygen.turd: doxygen
|
||||
|
||||
doxygenclean:
|
||||
cmake -E remove_directory ../../build/doxygen
|
||||
cmake -E remove doxygen.turd
|
||||
cmake -E remove_directory ../../build/sphinx
|
||||
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
SOURCEDIR = .
|
||||
SPHINXBUILDDIR = ../../build/sphinx
|
||||
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
sphinx : Makefile conf.py
|
||||
# @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(SPHINXBUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
$(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(SPHINXBUILDDIR)" $(SPHINXOPTS)
|
||||
|
||||
sphinxpdf : Makefile conf.py
|
||||
# @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(SPHINXBUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
$(SPHINXBUILD) -b latex "$(SOURCEDIR)" "$(SPHINXBUILDDIR)/latex" $(SPHINXOPTS)
|
||||
$(MAKE) -C $(SPHINXBUILDDIR)/latex all-pdf
|
||||
# $(SPHINXBUILD) -b latexpdf "$(SOURCEDIR)" "$(SPHINXBUILDDIR)/latex" $(SPHINXOPTS)
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
(chap-bigpicture=)
|
||||
# The Big Picture
|
||||
|
||||
|
||||
This chapter attempts to lay out the major concepts of OSL,
|
||||
define key nomenclature, and sketch out how individual shaders fit
|
||||
together in the context of a renderer as a whole.
|
||||
|
||||
<!--
|
||||
Other than the background material of this chapter, the rest of this
|
||||
specification deals strictly with the language itself. In the future,
|
||||
there will be separate (shorter) documents explaining in detail the use
|
||||
of the language compiler, the renderer-side issues, the library and APIs
|
||||
for how a renderer actually causes shaders to be evaluated, and so on.
|
||||
-->
|
||||
|
||||
#### A shader is code that performs a discrete task
|
||||
|
||||
A shader is a program, with inputs and outputs, that performs a specific
|
||||
task when rendering a scene, such as determining the appearance behavior
|
||||
of a material or light. The program code is written in OSL, the
|
||||
specification of which comprises this document.
|
||||
|
||||
For example, here is a simple `gamma` shader that performs
|
||||
simple gamma correction on is `Cin` input, storing the result
|
||||
in its output `Cout`:
|
||||
|
||||
```{image} Figures/shaderschematic.png
|
||||
:width: 6.0in
|
||||
```
|
||||
|
||||
The shader's inputs and outputs are called *shader parameters*.
|
||||
Parameters have default values, specified in the shader code, but may
|
||||
also be given new values by the renderer at runtime.
|
||||
|
||||
#### Shader instances
|
||||
|
||||
A particular shader may be used many times in a scene, on different
|
||||
objects or as different layers in a shader group. Each separate use of
|
||||
a shader is called a *shader instance*. Although all instances of
|
||||
a shader are comprised of the same program code, each instance may
|
||||
override any or all of its default parameter values with its own set of
|
||||
*instance values*.
|
||||
|
||||
Below is a schematic showing a `gamma` instance with the `gam` parameter
|
||||
overridden with an instance-specific value of `2.2`.
|
||||
|
||||
```{image} Figures/instanceschematic.png
|
||||
:width: 200px
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### Shader groups, layers, and connections
|
||||
|
||||
A *shader group* is an ordered sequence of individual shaders called *layers*
|
||||
that are executed in turn. Output parameters of an earlier-executed layer may
|
||||
be *connected* to an input parameter of a later-executed layer. This connected
|
||||
network of layers is sometimes called a *shader network* or a *shader DAG*
|
||||
(directed acyclic graph). Of course, it is fine for the shader group to
|
||||
consist of a single shader layer.
|
||||
|
||||
Below is a schematic showing how several shader instances may be
|
||||
connected to form a shader group.
|
||||
|
||||
|
||||
|
||||
```{image} Figures/groupschematic.png
|
||||
:width: 6.0in
|
||||
```
|
||||
|
||||
|
||||
|
||||
And here is sample pseudo-code shows how the above network may be assembled
|
||||
using an API in the renderer [^rendererapi]:
|
||||
|
||||
```
|
||||
ShaderGroupBegin ()
|
||||
Shader ("texturemap", /* shader name */
|
||||
"tex1", /* layer name */
|
||||
"string name", "rings.tx") /* instance variable */
|
||||
Shader ("texturemap", "tex2", "string name", "grain.tx")
|
||||
Shader ("gamma", "gam1", "float gam", 2.2)
|
||||
Shader ("gamma", "gam2", "float gam", 1)
|
||||
Shader ("wood", "wood1")
|
||||
ConnectShaders ("tex1", /* layer name A */
|
||||
"Cout", /* an output parameter of A */
|
||||
"gam1", /* layer name B */
|
||||
"Cin") /* Connect this layer of B to A's Cout */
|
||||
ConnectShaders ("tex2", "Cout", "gam2", "Cin")
|
||||
ConnectShaders ("gam1", "Cout", "wood1", "rings")
|
||||
ConnectShaders ("gam2", "Cout", "wood1", "grain")
|
||||
ShaderGroupEnd ()
|
||||
```
|
||||
|
||||
Or, expressed as serialized text (as detailed in Chapter [](chap-shader-groups):
|
||||
|
||||
param string name "rings.tx" ;
|
||||
shader "texturemap" "tex1" ;
|
||||
param string name "grain.tx" ;
|
||||
shader "texturemap" "tex2" ;
|
||||
param float gam 2.2 ;
|
||||
shader "gamma" "gam1" ;
|
||||
param float gam 1.0 ;
|
||||
shader "gamma" "gam2" ;
|
||||
shader "wood" "wood1" ;
|
||||
connect tex1.Cout gam1.Cin ;
|
||||
connect tex2.Cout gam2.Cin ;
|
||||
connect gam1.Cout wood1.rings ;
|
||||
connect gam2.Cout wood1.grain ;
|
||||
|
||||
The rules for which data types may be connected are generally the same as
|
||||
the rules determining which variables may be assigned to each other in OSL
|
||||
source code:
|
||||
|
||||
* `source` and `dest` are the same data type.
|
||||
* `source` and `dest` are both *triples* (`color`, `point`,
|
||||
`vector`, or `normal`), even if they are not the same kind of triple.
|
||||
* `source` is an `int` and `dest` is a `float`.
|
||||
* `source` is a `float` or `int` and `dest` is a
|
||||
*triple* (the scalar value will be replicated for all three components
|
||||
of the triple).
|
||||
* `source` is a single component of an aggregate type (e.g. one
|
||||
channel of a `color`) and `dest` is a `float` (or vice versa).
|
||||
|
||||
#### Geometric primitives
|
||||
|
||||
The *scene* consists of primarily of geometric primitives,
|
||||
light sources, and cameras.
|
||||
|
||||
*Geometric primitives* are shapes such as NURBS, subdivision surfaces,
|
||||
polygons, and curves. The exact set of supported primitives may vary
|
||||
from renderer to renderer.
|
||||
|
||||
Each geometric primitive carries around a set of named *primitive
|
||||
variables* (also sometimes called *interpolated values* or
|
||||
*user data*). Nearly all shape types will have, among their primitive
|
||||
variables, control point positions that, when interpolated, actually
|
||||
designate the shape. Some shapes will also allow the specification of
|
||||
normals or other shape-specific data. Arbitrary user data may also be
|
||||
attached to a shape as primitive variables. Primitive variables may be
|
||||
interpolated in a variety of ways: one constant value per primitive, one
|
||||
constant value per face, or per-vertex values that are interpolated
|
||||
across faces in various ways.
|
||||
|
||||
If a shader input parameter's name and type match the name and type
|
||||
of a primitive variable on the object (and that input parameters is
|
||||
not already explicitly connected to another layer's output), the
|
||||
interpolated primitive variable will override the instance value or
|
||||
default.
|
||||
|
||||
|
||||
#### Attribute state and shader assignments
|
||||
|
||||
Every geometric primitive has a collection of *attributes* (sometimes
|
||||
called the *graphics state*) that includes its transformation
|
||||
matrix, the list of which lights illuminate it, whether it is one-sided
|
||||
or two-sided, shader assignments, etc. There may also be a long list of
|
||||
renderer-specific or user-designated attributes associated with each
|
||||
object. A particular attribute state may be shared among many geometric
|
||||
primitives.
|
||||
|
||||
The attribute state also includes shader assignments --- the shaders or
|
||||
shader groups for each of several *shader uses*, such as surface
|
||||
shaders that designate how light reflects or emits from each point on a shape,
|
||||
displacement shaders that can add fine detail to the shape on a
|
||||
point-by-point basis, and volume shaders that describe how light is
|
||||
scattered within a region of space. A particular renderer may have
|
||||
additional shader types that it supports.
|
||||
|
||||
|
||||
#### Shader execution state: parameter binding and global variables
|
||||
|
||||
When the body of code of an individual shader is about to execute, all
|
||||
its parameters are *bound* --- that is, take on specific values
|
||||
(from connections from other layers, interpolated primitive variables,
|
||||
instance values, or defaults, in that order).
|
||||
|
||||
Certain state about the position on the surface where the shading is
|
||||
being run is stored in so-called *global variables*. This includes
|
||||
such useful data as the 3D coordinates of the point being shaded, the
|
||||
surface normal and tangents at that point, etc.
|
||||
|
||||
Additionally, the shader may query other information about other
|
||||
elements of the attribute state attached to the primitive, and
|
||||
information about the renderer as a whole (rendering options, etc.).
|
||||
|
||||
#### Surface and volume shaders compute closures
|
||||
|
||||
Surface shaders (and volume shaders) do not by themselves compute the
|
||||
final color of light emanating from the surface (or along a volume).
|
||||
Rather, they compute a *closure*, which is a symbolic representation
|
||||
describing the appearance of the surface, that may be more fully
|
||||
evaluated later. This is in effect a parameterized formula, in which
|
||||
some inputs have definite numeric values, but others may depend on
|
||||
quantities not yet known (such as the direction from which the surface
|
||||
is being viewed, and the amount of light from each source that is
|
||||
arriving at the surface).
|
||||
|
||||
For example, a surface shader may compute its result like this:
|
||||
|
||||
color paint = texture ("file.tx", u, v);
|
||||
Ci = paint * diffuse (N);
|
||||
|
||||
In this example, the variable `paint` will take on a specific numeric
|
||||
value (by looking up from a texture map). But the `diffuse()` function
|
||||
returns a `color closure`, not a definite numeric `color`. The output
|
||||
variable `Ci` that represents the appearance of the surface is also a `color
|
||||
closure`, whose numeric value is not known yet, except that it will be the
|
||||
product of `paint`` and a Lambertian reflectance.
|
||||
|
||||
|
||||
|
||||
```{image} Figures/shaderexecschematic.png
|
||||
```
|
||||
|
||||
The closures output by surface and volume shaders can do a number of
|
||||
interesting things that a mere number cannot:
|
||||
|
||||
* Evaluate: given input and output light directions, compute the
|
||||
proportion of light propagating from input to output.
|
||||
* Sample: given just an input (or output) direction, choose a
|
||||
scattering direction with a probability distribution that is
|
||||
proportional to the amount of light that will end up going in various
|
||||
directions.
|
||||
* Integrate: given all lights and a view direction, compute
|
||||
the total amount of light leaving the surface in the view direction.
|
||||
* Recompute: given changes only to lights (or only to one light),
|
||||
recompute the integrated result without recomputing other lights or
|
||||
any of the calculations that went into assembling constants in the
|
||||
closure (such as texture lookups, noise functions, etc.).
|
||||
|
||||
<!--
|
||||
At present, we are assuming that the primitive closure functions (such
|
||||
as `diffuse`, `ward`, `cooktorrance`, etc.) are all built
|
||||
into the renderer, or implemented as renderer plugins. At a later time,
|
||||
possibly in a later draft or maybe not until a truly later version of
|
||||
the spec, we will fully spec it out so that closure primitive functions
|
||||
may be written in OSL. But I fear that if we do it too soon,
|
||||
we'll screw it up. But, yes, the eventual goal is for you to be able to
|
||||
write these primitive functions in the language itself.
|
||||
-->
|
||||
|
||||
|
||||
#### Integrators
|
||||
|
||||
The renderer contains a number of *integrators* (selectable via the
|
||||
renderer's API) which will combine the color closures computed by
|
||||
surfaces and volumes with the light sources and view-dependent
|
||||
information, to yield the amount of light visible to the camera.
|
||||
|
||||
```{image} Figures/integratorschematic.png
|
||||
:width: 6.0in
|
||||
```
|
||||
|
||||
<!--
|
||||
At present, this document is written as if the integrators are built
|
||||
into the renderer itself (or implemented as renderer plug-ins). At a
|
||||
later time, we intend to make it possible for integrators themselves
|
||||
to be written in OSL.
|
||||
-->
|
||||
|
||||
|
||||
#### Units
|
||||
|
||||
You can tell the renderer (through a global option) what units the scene
|
||||
is using for distance and time. Then the shader has a built-in function
|
||||
called `transformu()` that works a lot like `transform()`, but
|
||||
instead of converting between coordinate systems, it converts among
|
||||
units. For example,
|
||||
|
||||
```
|
||||
displacement bumpy (float bumpdist = 1,
|
||||
string bumpunits = "cm")
|
||||
{
|
||||
// convert bumpdist to common units
|
||||
float spacing = transformu (bumpunits, "common", bumpdist);
|
||||
float n = noise (P / spacing);
|
||||
displace (n);
|
||||
}
|
||||
```
|
||||
|
||||
So you can write a shader to achieve some effect in real world units,
|
||||
and that shader is totally reusable on another show that used different
|
||||
modeling units.
|
||||
|
||||
It knows all the standard names like `cm`, `in`, `km`,
|
||||
etc., and can convert among any of those, as well as between named
|
||||
coordinate systems. For example,
|
||||
|
||||
```
|
||||
float x = transformu ("object", "mm", 1);
|
||||
```
|
||||
|
||||
now `x` is the number of millimeters per unit of "object" space on
|
||||
that primitive.
|
||||
|
||||
[^rendererapi]: This document does not dictate a specific renderer API for
|
||||
declaring shader instances, groups, and connections; the code above is just
|
||||
an example of how it might be done.
|
||||
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
from __future__ import absolute_import
|
||||
import sys
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
default_role = 'code'
|
||||
|
||||
project = 'Open Shading Language'
|
||||
copyright = 'Contributors to the Open Shading Language project'
|
||||
author = 'Larry Gritz, editor'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
|
||||
# LG addition: we search for it in the CMakeLists.txt so we don't need to
|
||||
# keep modifying this file:
|
||||
version = '0.0'
|
||||
release = '0.0.0'
|
||||
import re
|
||||
version_regex = re.compile(r'set \(OSL_VERSION \"?((\d+\.\d+)\.\d+)\.\d+\"?\)')
|
||||
f = open('../../CMakeLists.txt')
|
||||
for l in f:
|
||||
aa=re.search(version_regex, l)
|
||||
if aa is not None:
|
||||
release = aa.group(1)
|
||||
version = aa.group(2)
|
||||
break
|
||||
f.close()
|
||||
print ("OSL docs version = {}, release = {}".format(version, release))
|
||||
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
|
||||
# add custom extensions directory to python path
|
||||
sys.path.insert(0, os.path.join(os.path.abspath(os.path.dirname(__file__)), 'extensions/sphinxtr'))
|
||||
sys.path.insert(0, os.path.join(os.path.abspath(os.path.dirname(__file__)), '../../ext/breathe'))
|
||||
#import html_mods
|
||||
#import latex_mods
|
||||
|
||||
extensions = [
|
||||
'breathe',
|
||||
'myst_parser',
|
||||
'sphinx_tabs.tabs',
|
||||
]
|
||||
|
||||
myst_enable_extensions = [
|
||||
# "amsmath",
|
||||
"attrs_inline",
|
||||
"colon_fence",
|
||||
"deflist",
|
||||
"dollarmath",
|
||||
"fieldlist",
|
||||
# "html_admonition",
|
||||
# "html_image",
|
||||
# "linkify",
|
||||
# "replacements",
|
||||
# "smartquotes",
|
||||
# "strikethrough",
|
||||
# "substitution",
|
||||
# "tasklist",
|
||||
]
|
||||
myst_heading_anchors = 3
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = []
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
#html_theme = 'alabaster'
|
||||
#html_theme = 'astropy-sphinx-theme'
|
||||
# html_theme = 'sphinx_rtd_theme'
|
||||
html_theme = 'furo'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
|
||||
# Breathe options
|
||||
breathe_projects = { "osl": "../../build/doxygen/xml" }
|
||||
breathe_default_project = "osl"
|
||||
breathe_domain_by_extension = {'h': 'cpp'}
|
||||
breathe_default_members = ()
|
||||
primary_domain = 'cpp'
|
||||
highlight_language = 'cpp'
|
||||
|
||||
|
||||
read_the_docs_build = os.getenv('READTHEDOCS') == 'True'
|
||||
|
||||
if read_the_docs_build:
|
||||
print ("cwd =", os.getcwd())
|
||||
print ("checkpoint -- rtd build")
|
||||
if not os.path.exists('../../build/doxygen') :
|
||||
os.makedirs ('../../build/doxygen')
|
||||
print ("checkpoint 2 -- rtd build")
|
||||
subprocess.call('echo "Calling Doxygen"', shell=True)
|
||||
subprocess.call(['doxygen'], shell=True)
|
||||
subprocess.call('echo "Ran Doxygen"', shell=True)
|
||||
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
# Copyright Notice
|
||||
|
||||
|
||||
The code that implements Open Shading Language is licensed under the BSD
|
||||
3-clause (also sometimes known as "new BSD" or "modified BSD") license.
|
||||
|
||||
```{include} ../../LICENSE.md
|
||||
```
|
||||
|
||||
|
||||
This manual and other text documentation about OSL are licensed under the
|
||||
Creative Commons Attribution 4.0 International License.
|
||||
|
||||
```{image} figures/CC-BY.png
|
||||
:alt: Beautiful Sunset
|
||||
:width: 200px
|
||||
:align: center
|
||||
```
|
||||
|
||||
http://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
|
||||
OSL incorporates code from several other software packages with
|
||||
compatible licenses. Copies of their licenses are reproduced here:
|
||||
https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/master/THIRD-PARTY.md
|
||||
@@ -0,0 +1,709 @@
|
||||
---
|
||||
numbering:
|
||||
heading_1: true
|
||||
heading_2: true
|
||||
heading_3: true
|
||||
---
|
||||
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
(chap-types)=
|
||||
# Data types
|
||||
|
||||
OSL provides several built-in simple data types for performing
|
||||
computations inside your shader:
|
||||
|
||||
Type | Explanation
|
||||
:---------- | :-----------
|
||||
`int` | Integer data
|
||||
`float` | Scalar floating-point data (numbers)
|
||||
`point`, `vector`, `normal` | Three-dimensional positions, directions, and face orientations
|
||||
`color` | Spectral reflectivities and light energy values
|
||||
`matrix` | $4 \times 4$ transformation matrices
|
||||
`string` | Character strings (such as filenames)
|
||||
`void` | Indicates functions that do not return a value
|
||||
|
||||
In addition, you may create arrays and structures (much like C), and
|
||||
OSL has a new type of data structure called a *closure*.
|
||||
|
||||
The remainder of this chapter will describe the simple and aggregate
|
||||
data types available in OSL.
|
||||
|
||||
(sec-datatypes-int)=
|
||||
## `int`
|
||||
|
||||
The basic type for discrete numeric values is `int`. The size of
|
||||
the `int` type is renderer-dependent, but is guaranteed to be at
|
||||
least 32 bits.
|
||||
|
||||
Integer constants are constructed the same way as in C. The following
|
||||
are examples of `int` constants: `1`, `-2`, etc. Integer
|
||||
constants may be specified as hexadecimal, for example: `0x01cf`.
|
||||
|
||||
Unlike C, no unsigned, bool, char, short, or long types are supplied.
|
||||
This is to simplify the process of writing shaders (as well as
|
||||
implementing shading systems).
|
||||
|
||||
The following operators may be used with `int` values (in order of
|
||||
decreasing precedence, with each box holding operators of the same
|
||||
precedence):
|
||||
|
||||
|
||||
Operation | Result | Explanation
|
||||
:--------- | :------ | :---
|
||||
*int* `++` | `int` | post-increment by 1
|
||||
*int* `--` | `int` | post-decrement by 1
|
||||
| |
|
||||
| |
|
||||
`++` *int* | `int` | pre-increment by 1
|
||||
`--` *int* | `int` | pre-decrement by 1
|
||||
`-` *int* | `int` | unary negation
|
||||
`~` *int* | `int` | bitwise complement (1 and 0 bits flipped)
|
||||
`!` *int* | `int` | boolean `not' (1 if operand is zero, otherwise 0)
|
||||
| |
|
||||
| |
|
||||
*int* `*` *int* | `int` | multiplication
|
||||
*int* `/` *int* | `int` | division
|
||||
*int* `%` *int* | `int` | modulus
|
||||
| |
|
||||
| |
|
||||
*int* `+` *int* | `int` | addition
|
||||
*int* `-` *int* | `int` | subtraction
|
||||
| |
|
||||
| |
|
||||
*int* `<<` *int* | `int` | shift left
|
||||
*int* `>>` *int* | `int` | shift right
|
||||
| |
|
||||
| |
|
||||
*int* `<` *int* | `int` | 1 if the first value is less than the second, else 0
|
||||
*int* `<=` *int* | `int` | 1 if the first value is less or equal to the second, else 0
|
||||
*int* `>` *int* | `int` | 1 if the first value is greater than the second, else 0
|
||||
*int* `>=` *int* | `int` | 1 if the first value is greater than or equal to the second, else 0
|
||||
| |
|
||||
| |
|
||||
*int* `==` *int* | `int` | 1 if the two values are equal, else 0
|
||||
*int* `!=` *int* | `int` | 1 if the two values are different, else 0
|
||||
| |
|
||||
| |
|
||||
*int* `&` *int* | `int` | bitwise and
|
||||
| |
|
||||
| |
|
||||
*int* `^` *int* | `int` | bitwise exclusive or
|
||||
| |
|
||||
| |
|
||||
*int* `\|` *int* | `int` | bitwise or
|
||||
| |
|
||||
| |
|
||||
*int* `&&` *int* | `int` | boolean and (1 if both operands are nonzero, otherwise 0)
|
||||
| |
|
||||
| |
|
||||
*int* `\|\|` *int* | `int` | boolean or (1 if either operand is nonzero, otherwise 0)
|
||||
|
||||
|
||||
Note that the `not`, `and`, and `or` keywords are synonyms for `!`, `&&`, and
|
||||
`||`, respectively.
|
||||
|
||||
|
||||
|
||||
## `float`
|
||||
|
||||
The basic type for scalar floating-point numeric values is `float`. The
|
||||
size of the `float` type is renderer-dependent, but is guaranteed to
|
||||
be at least IEEE 32-bit float (the standard C `float` data type).
|
||||
Individual renderer implementations may choose to implement `float` with
|
||||
even more precision (such as using the C `double` as the underlying
|
||||
representation).
|
||||
|
||||
Floating-point constants are constructed the same way as in C. The following
|
||||
are examples of `float` constants: `1.0`, `2.48`, `-4.3e2`.
|
||||
|
||||
An `int` may be used in place of a `float` when used with any valid
|
||||
`float` operator. In such cases, the `int` will be promoted to a
|
||||
`float` and the resulting expression will be `float`. An `int` may
|
||||
also be passed to a function that expects a `float` parameters, with the
|
||||
`int` automatically promoted to `float`.
|
||||
|
||||
The following operators may be used with `float` values (in order of
|
||||
decreasing precedence, with each box holding operators of the same
|
||||
precedence):
|
||||
|
||||
|
||||
Operation | Result | Explanation
|
||||
:--------- | :------ | :---
|
||||
*float* `++` | `float` | post-increment by 1
|
||||
*float* `--` | `float` | post-decrement by 1
|
||||
| |
|
||||
| |
|
||||
`++` *float* | `float` | pre-increment by 1
|
||||
`--` *float* | `float` | pre-decrement by 1
|
||||
`-` *float* | `float` | unary negation
|
||||
| |
|
||||
| |
|
||||
*float* `*` *float* | `float` | multiplication
|
||||
*float* `/` *float* | `float` | division
|
||||
| |
|
||||
| |
|
||||
*float* `+` *float* | `float` | addition
|
||||
*float* `-` *float* | `float` | subtraction
|
||||
| |
|
||||
| |
|
||||
*float* `<` *float* | `int` | 1 if the first value is less than the second, else 0
|
||||
*float* `<=` *float* | `int` | 1 if the first value is less or equal to the second, else 0
|
||||
*float* `>` *float* | `int` | 1 if the first value is greater than the second, else 0
|
||||
*float* `>=` *float* | `int` | 1 if the first value is greater than or equal to the second, else 0
|
||||
| |
|
||||
| |
|
||||
*float* `==` *float* | `int` | 1 if the two values are equal, else 0
|
||||
*float* `!=` *float* | `int` | 1 if the two values are different, else 0
|
||||
|
||||
|
||||
|
||||
## `color`
|
||||
|
||||
The `color` type is used to represent 3-component (RGB) spectral
|
||||
reflectivities and light energies. You can assemble a
|
||||
color out of three floats, either representing an RGB triple or some
|
||||
other color space known to the renderer, as well as from a single
|
||||
float (replicated for all three channels). Following are some examples:
|
||||
|
||||
```
|
||||
color (0, 0, 0) // black
|
||||
color ("rgb", .75, .5, .5) // pinkish
|
||||
color ("hsv", .2, .5, .63) // specify in "hsv" space
|
||||
color (0.5) // same as color (0.5, 0.5, 0.5)
|
||||
```
|
||||
|
||||
All these expressions above return colors in "rgb" space. Even the third
|
||||
example returns a color in "rgb" space --- specifically, the RGB value of the
|
||||
color that is equivalent to hue 0.2, saturation 0.5, and value 0.63. In other
|
||||
words, when assembling a color from components given relative to a specific
|
||||
color space in this manner, there is an implied transformation to "rgb" space.
|
||||
The following table lists the built-in color spaces.
|
||||
|
||||
% \caption{Names of color spaces.}\label{tab:colorspacenames}
|
||||
|
||||
| | |
|
||||
:--------- | :------
|
||||
`"rgb"` | The coordinate system that all colors start out in, and in which the renderer expects to find colors that are set by your shader.
|
||||
`"hsv"` | hue, saturation, and value.
|
||||
`"hsl"` | hue, saturation, and lightness.
|
||||
`"YIQ"` | the color space used for the NTSC television standard.
|
||||
`"XYZ"` | CIE *XYZ* coordinates.
|
||||
`"xyY"` | CIE *xyY* coordinates.
|
||||
|
||||
Colors may be assigned another color or a `float` value (which sets
|
||||
all three components to the value). For example:
|
||||
|
||||
```
|
||||
color C;
|
||||
C = color (0, 0.3, 0.3);
|
||||
C = 0.5; // same as C = color (0.5, 0.5, 0.5)
|
||||
```
|
||||
|
||||
Colors can have their individual components examined and set using the
|
||||
`[]` array access notation. For example:
|
||||
|
||||
```
|
||||
color C;
|
||||
float g = C[1]; // get the green component
|
||||
C[0] = 0.5; // set the red component
|
||||
```
|
||||
|
||||
Components 0, 1, and 2 are red, green, and blue, respectively.
|
||||
It is an error to access a color component with an index outside the
|
||||
$[0...2]$ range.
|
||||
|
||||
Color variables may also have their components referenced using "named
|
||||
components" that look like accessing structure fields named `r`, `g`, and `b`,
|
||||
as synonyms for `[0]`, `[1]`, and `[2]`, respectively:
|
||||
|
||||
```
|
||||
float green = C.g; // get the green component
|
||||
C.r = 0.5; // set the red component
|
||||
```
|
||||
|
||||
The following operators may be used with `color` values (in order of
|
||||
decreasing precedence, with each box holding operators of the same
|
||||
precedence):
|
||||
|
||||
|
||||
Operation | Result | Explanation
|
||||
:--------- | :------ | :---
|
||||
*color* `[` *int* `]` | `float` | component access
|
||||
| |
|
||||
| |
|
||||
`-` *color* | `color` | unary negation
|
||||
| |
|
||||
| |
|
||||
*color* `*` *color* | `color` | component-wise multiplication
|
||||
*color* `*` *float* | `color` | scaling
|
||||
*float* `*` *color* | `color` | scaling
|
||||
*color* `/` *color* | `color` | component-wise division
|
||||
*color* `/` *float* | `color` | scaling
|
||||
*float* `/` *color* | `color` | scaling
|
||||
| |
|
||||
| |
|
||||
*color* `+` *color* | `color` | component-wise addition
|
||||
*color* `-` *color* | `color` | component-wise subtraction
|
||||
| |
|
||||
| |
|
||||
*color* `==` *color* | `int` | 1 if the two values are equal, else 0
|
||||
*color* `!=` *color* | `int` | 1 if the two values are different, else 0
|
||||
|
||||
All of the binary operators may combine a scalar value (`float` or
|
||||
`int`) with a `color`, treating the scalar if it were a `color` with
|
||||
three identical components.
|
||||
|
||||
|
||||
## Point-like types: `point`, `vector`, `normal`
|
||||
|
||||
Points, vectors, and normals are similar data types with identical
|
||||
structures but subtly different semantics. We will frequently refer to
|
||||
them collectively as the "point-like" data types when making
|
||||
statements that apply to all three types.
|
||||
|
||||
A `point` is a position in 3D space. A `vector` has a length and
|
||||
direction, but does not exist in a particular location. A `normal` is a
|
||||
special type of vector that is *perpendicular* to a surface, and
|
||||
thus describes the surface's orientation. Such a perpendicular vector
|
||||
uses different transformation rules than ordinary vectors, as we will
|
||||
describe below.
|
||||
|
||||
All of these point-like types are internally represented by three
|
||||
floating-point numbers that uniquely describe a position or
|
||||
direction relative to the three axes of some coordinate system.
|
||||
|
||||
All points, vectors, and normals are described relative to some
|
||||
coordinate system. All data provided to a shader (surface information,
|
||||
graphics state, parameters, and vertex data) are relative to one
|
||||
particular coordinate system that we call the `"common"` coordinate
|
||||
system. The `"common"` coordinate system is one that is convenient
|
||||
for the renderer's shading calculations.
|
||||
|
||||
You can "assemble" a point-like type out of three floats using a
|
||||
constructor:
|
||||
|
||||
```
|
||||
point (0, 2.3, 1)
|
||||
vector (a, b, c)
|
||||
normal (0, 0, 1)
|
||||
```
|
||||
|
||||
These expressions are interpreted as a point, vector, and normal
|
||||
whose three components are the floats given, relative to "common" space .
|
||||
|
||||
As with colors, you may also specify the coordinates relative to some other
|
||||
coordinate system:
|
||||
|
||||
```
|
||||
Q = point ("object", 0, 0, 0);
|
||||
```
|
||||
|
||||
This example assigns to `Q` the point at the origin of "object" space.
|
||||
However, this statement does *not* set the components of `Q` to (0,0,0)!
|
||||
Rather, `Q` will contain the "common" space coordinates of the point that is
|
||||
at the same location as the origin of "object" space. In other words, the
|
||||
point constructor that specifies a space name implicitly specifies a
|
||||
transformation to "common" space. This type of constructor also can be used
|
||||
for vectors and normals.
|
||||
|
||||
The choice of "common" space is renderer-dependent, though will usually
|
||||
be equivalent to either "camera" space or "world" space.
|
||||
|
||||
Some computations may be easier in a coordinate system other than
|
||||
"common" space. For example, it is much more convenient to apply a
|
||||
"solid texture" to a moving object in its "object" space than in
|
||||
"common" space. For these reasons, OSL provides a built-in
|
||||
`transform()` function that
|
||||
allows you to transform points, vectors, and normals
|
||||
among different coordinate systems (see Section [](#sec-stdlib-geom)). Note,
|
||||
however, that OSL does not keep track of which point variables are
|
||||
in which coordinate systems. It is the responsibility of the shader
|
||||
programmer to keep track of this and ensure that, for example, lighting
|
||||
computations are performed using quantities in "common" space.
|
||||
|
||||
Several coordinate systems are predefined by name, listed in the following
|
||||
table. Additionally, a renderer will probably allow for additional coordinate
|
||||
systems to be named in the scene description, and these names may also be
|
||||
referenced inside your shader to designate transformations.
|
||||
|
||||
% \caption{Names of predeclared geometric spaces.\label{tab:spacenames}}
|
||||
|
||||
`"common"`
|
||||
: The coordinate system that all spatial values start out in and the one in
|
||||
which all lighting calculations are carried out. Note that the choice of
|
||||
`"common"` space may be different on each renderer.
|
||||
|
||||
`"object"`
|
||||
: The local coordinate system of the graphics primitive (sphere, patch, etc.)
|
||||
that we are shading.
|
||||
|
||||
`"shader"`
|
||||
: The local coordinate system active at the time that the shader was
|
||||
instanced.
|
||||
|
||||
`"world"`
|
||||
: The world coordinate system designated in the scene.
|
||||
|
||||
`"camera"`
|
||||
: The coordinate system with its origin at the center of the camera lens,
|
||||
$x$-axis pointing right, $y$-axis pointing up, and $z$-axis pointing into
|
||||
the screen.
|
||||
|
||||
`"screen"`
|
||||
: The coordinate system of the camera's image plane (after perspective
|
||||
transformation, if any). Coordinate (0,0) of `"screen"` space is looking
|
||||
along the $z$-axis of "camera" space.
|
||||
|
||||
`"raster"`
|
||||
: 2D pixel coordinates, with (0,0) as the upper-left
|
||||
corner of the image and (xres, yres) as the lower-right corner.
|
||||
|
||||
`"NDC"`
|
||||
: 2D Normalized Device Coordinates --- like raster space, but normalized so
|
||||
that $x$ and $y$ both run from 0 to 1 across the whole image, with (0,0)
|
||||
being at the upper left of the image, and (1,1) being at the lower right.
|
||||
|
||||
|
||||
Point types can have their individual components examined and set using
|
||||
the `[]` array access notation. For example:
|
||||
|
||||
```
|
||||
point P;
|
||||
float y = P[1]; // get the y component
|
||||
P[0] = 0.5; // set the x component
|
||||
```
|
||||
|
||||
Components 0, 1, and 2 are $x$, $y$, and $z$, respectively.
|
||||
It is an error to access a point component with an index outside the
|
||||
$[0...2]$ range.
|
||||
|
||||
Point-like variables may also have their components referenced using "named
|
||||
components" that look like accessing structure fields named `x`, `y`, and `z`,
|
||||
as synonyms for `[0]`, `[1]`, and `[2]`, respectively:
|
||||
|
||||
```
|
||||
float yval = P.y; // get the [1] or y component
|
||||
P.x = 0.5; // set the [0] or x component
|
||||
```
|
||||
|
||||
The following operators may be used with point-like values (in order of
|
||||
decreasing precedence, with each box holding operators of the same
|
||||
precedence):
|
||||
|
||||
|
||||
Operation | Result | Explanation
|
||||
:--------- | :------ | :---
|
||||
*ptype* `[` `int` `]` | `float` | component access
|
||||
| |
|
||||
| |
|
||||
`-` *ptype* | `vector` | component-wise unary negation
|
||||
| |
|
||||
| |
|
||||
*ptype* `*` *ptype* | *ptype* | component-wise multiplication
|
||||
`float` `*` *ptype* | *ptype* | scaling of all components
|
||||
*ptype* `*` `float` | *ptype* | scaling of all components
|
||||
*ptype* `/` *ptype* | *ptype* | component-wise division
|
||||
*ptype* `/` `float` | *ptype* | division of all components
|
||||
`float` `/` *ptype* | *ptype* | division by all components
|
||||
| |
|
||||
| |
|
||||
*ptype* `+` *ptype* | *ptype* | component-wise addition
|
||||
*ptype* `-` *ptype* | `vector` | component-wise subtraction
|
||||
| |
|
||||
| |
|
||||
*ptype* `==` *ptype* | `int` | 1 if the two values are equal, else 0
|
||||
*ptype* `!=` *ptype* | `int` | 1 if the two values are different, else 0
|
||||
|
||||
|
||||
The generic *ptype* is listed in places where any of `point`, `vector`, or
|
||||
`normal` may be used.
|
||||
|
||||
All of the binary operators may combine a scalar value (`float` or `int`) with
|
||||
a point-like type, treating the scalar if it were point-like with three
|
||||
identical components.
|
||||
|
||||
|
||||
## `matrix`
|
||||
|
||||
OSL has a `matrix` type that represents the transformation matrix required to
|
||||
transform points and vectors between one coordinate system and another.
|
||||
Matrices are represented internally by 16 floats (a $4 \times 4$ homogeneous
|
||||
transformation matrix).
|
||||
|
||||
A `matrix` can be constructed from a single float or 16 floats. For example:
|
||||
|
||||
```
|
||||
matrix zero = 0; // makes a matrix with all 0 components
|
||||
matrix ident = 1; // makes the identity matrix
|
||||
|
||||
// Construct a matrix from 16 floats
|
||||
matrix m = matrix (m00, m01, m02, m03, m10, m11, m12, m13,
|
||||
m20, m21, m22, m23, m30, m31, m32, m33);
|
||||
```
|
||||
|
||||
Assigning a single floating-point number $x$ to a matrix will result
|
||||
in a matrix with diagonal components all being $x$ and other
|
||||
components being zero (i.e., $x$ times the identity matrix).
|
||||
Constructing a matrix with 16 floats will create the matrix whose
|
||||
components are those floats, in row-major order.
|
||||
|
||||
Similar to point-like types, a `matrix` may be constructed in
|
||||
reference to a named space:
|
||||
|
||||
```
|
||||
// Construct matrices relative to something other than "common"
|
||||
matrix q = matrix ("shader", 1);
|
||||
matrix m = matrix ("world", m00, m01, m02, m03, m10, m11, m12, m13,
|
||||
m20, m21, m22, m23, m30, m31, m32, m33);
|
||||
```
|
||||
|
||||
The first form creates the matrix that transforms points from "shader" space
|
||||
to "common" space. Transforming points by this matrix is identical to calling
|
||||
`transform("shader", "common", ...)`. The second form prepends the
|
||||
current-to-world transformation matrix onto the $4 \times 4$ matrix with
|
||||
components $m_{0,0} ... m_{3,3}$. Note that although we have used `"shader"`
|
||||
and `"world"` space in our examples, any named space is acceptable.
|
||||
|
||||
A matrix may also be constructed from the names of two coordinate
|
||||
systems, yielding the matrix that transforms coordinates from the
|
||||
first named space to the second named space:
|
||||
|
||||
```
|
||||
matrix m = matrix ("object", "world");
|
||||
```
|
||||
|
||||
The example returns the *object-to-world* transformation matrix.
|
||||
|
||||
Matrix variables can be tested for equality and inequality with the `==` and
|
||||
`!=` boolean operators. Also, the `*` operator between matrices denotes
|
||||
matrix multiplication, while `m1 / m2` denotes multiplying `m1` by the inverse
|
||||
of matrix `m2`. Thus, a matrix can be inverted by writing `1/m`. In
|
||||
addition, some functions will accept matrix variables as arguments, as
|
||||
described in Section [](#chap-stdlibrary).
|
||||
|
||||
Individual components of a matrix variable may be set or accessed using array
|
||||
notation, for example,
|
||||
|
||||
```
|
||||
matrix M;
|
||||
float x = M[row][col];
|
||||
M[row][col] = 1;
|
||||
```
|
||||
|
||||
Valid component indices are integers on $[0...3]$. It is an error to access a
|
||||
matrix component with either a row or column outside this range.
|
||||
|
||||
The following operators may be used with matrices (in order of decreasing
|
||||
precedence, with each box holding operators of the same precedence):
|
||||
|
||||
Operation | Result | Explanation
|
||||
:--------- | :------ | :---
|
||||
*matrix* `[` *int* `][` *int* `]` | `float` | component access (row, column)
|
||||
| |
|
||||
| |
|
||||
`-` *matrix* | `matrix` | unary negation
|
||||
| |
|
||||
| |
|
||||
*matrix* `*` *matrix* | `matrix` | matrix multiplication
|
||||
*matrix* `*` *float* | `matrix` | component-wise scaling
|
||||
*float* `*` *matrix* | `matrix` | component-wise scaling
|
||||
*matrix* `/` *matrix* | `matrix` | multiply the first matrix by the *inverse of the second
|
||||
*matrix* `/` *float* | `matrix` | component-wise division
|
||||
*float* `/` *matrix* | `matrix` | multiply the *float* by the *inverse of the matrix
|
||||
| |
|
||||
| |
|
||||
*matrix* `==` *matrix* | *int* | 1 if the two values are equal, else 0
|
||||
*matrix* `!=` *matrix* | *int* | 1 if the two values are different, else 0
|
||||
|
||||
|
||||
## `string`
|
||||
|
||||
The `string` type may hold character strings. The main application
|
||||
of strings is to provide the names of files where textures may be
|
||||
found. Strings can be compared using `==` and `!=`.
|
||||
|
||||
String constants are denoted by surrounding the characters with double
|
||||
quotes, as in `"I am a string literal"`. As in C programs, string
|
||||
literals may contain escape sequences such as `\n` (newline),
|
||||
`\r` (carriage return), `\t` (tab), `\"` (double quote),
|
||||
`\\` (backslash).
|
||||
|
||||
Two quote-quoted string literals that are separated only by whitespace
|
||||
(spaces, tabs, or newlines) will be automatically concatenated into a
|
||||
single string literal. In other words,
|
||||
|
||||
```text
|
||||
"foo" "bar"
|
||||
```
|
||||
|
||||
is exactly equivalent to `"foobar"`.
|
||||
|
||||
## `void`
|
||||
|
||||
The `void` type is used to designate a function that does not return a value.
|
||||
No variable may have type `void`.
|
||||
|
||||
## Arrays
|
||||
|
||||
Arrays of any of the basic types are supported, provided that they
|
||||
are 1D and statically sized, using the usual syntax for C-like languages:
|
||||
|
||||
```
|
||||
float d[10]; // Declare an uninitialized array
|
||||
float c[3] = { 0.1, 0.2, 3.14 }; // Initialize the array
|
||||
|
||||
float f = c[1]; // Access one element
|
||||
```
|
||||
|
||||
The built-in function `arraylength()` returns the number of elements in an
|
||||
array. For example:
|
||||
|
||||
```
|
||||
float c[3];
|
||||
int clen = arraylength(c); // should return 3
|
||||
```
|
||||
|
||||
There are two circumstances when arrays do not need to have a declared
|
||||
length --- an array parameter to a function, and a shader parameter that
|
||||
is an array. This is indicated by empty array brackets, as shown in the
|
||||
following example:
|
||||
|
||||
```
|
||||
float sum (float x[])
|
||||
{
|
||||
float s = 0;
|
||||
for (int i = 0; i < arraylength(x); ++i)
|
||||
s += x[i];
|
||||
return s;
|
||||
}
|
||||
```
|
||||
|
||||
It is allowed in OSL to copy an entire array at once using the `=` operator,
|
||||
provided that the arrays contain elements of the same type and that the
|
||||
destination array is at least as long as the source array. For example:
|
||||
|
||||
```
|
||||
float array[4], anotherarray[4];
|
||||
...
|
||||
anotherarray = array;
|
||||
```
|
||||
|
||||
|
||||
## Structures
|
||||
|
||||
Structures are used to group several fields of potentially different types
|
||||
into a single object that can be referred to by name. You may then use the
|
||||
structure type name to declare structure variables as you would for any of the
|
||||
built-in types. Structure elements are accessed using the `.` ("dot")
|
||||
operator. The syntax for declaring and using structures is similar to C or
|
||||
C++:
|
||||
|
||||
```
|
||||
struct RGBA { // Define a structure type
|
||||
color rgb;
|
||||
float alpha;
|
||||
};
|
||||
|
||||
RGBA col; // Declare a structure
|
||||
r.rgb = color (1, 0, 0); // Assign to one field
|
||||
color c = r.rgb; // Read from a structure field
|
||||
|
||||
RGBA b = { color(.1,.2,.3), 1 }; // Member-by-member initialization
|
||||
```
|
||||
|
||||
You can use "constructor expressions" for a your struct types much like
|
||||
you can construct built-in types like `color` or `point`:
|
||||
|
||||
> *struct_name* `(` *first_member_value*, ... `}`
|
||||
|
||||
For example,
|
||||
|
||||
```
|
||||
RGBA c = RGBA(col,alpha); // Constructor syntax
|
||||
|
||||
RGBA add (RGBA a, RGBA b)
|
||||
{
|
||||
return RGBA (a.rgb+b.rgb, a.a+b.a); // return expression
|
||||
}
|
||||
|
||||
// pass constructor expression as a parameter:
|
||||
RGBA d = add (c, RGBA(color(.3,.4,.5), 0));
|
||||
```
|
||||
|
||||
You may also use the *compound initializer list* syntax to construct a type
|
||||
when it can be deduced from context which compound type is required. For
|
||||
example, this is equivalent to the preceding example:
|
||||
|
||||
```
|
||||
RGBA c = {col,alpha}; // deduce by what is being assigned to
|
||||
|
||||
RGBA add (RGBA a, RGBA b)
|
||||
{
|
||||
return { a.rgb+b.rgb, a.a+b.a }; // deduce by func return type
|
||||
}
|
||||
|
||||
RGBA d = add (c, {{.3,.4,.5}, 0}); // deduce by expected arg type
|
||||
```
|
||||
|
||||
It is permitted to have a structure field that is an array, as well as to have
|
||||
an array of structures. But it is not currently permitted to "nest" arrays
|
||||
(that is, to have an array of structs which contain members that are arrays).
|
||||
|
||||
```
|
||||
struct A {
|
||||
color a;
|
||||
float b[4]; // Ok: struct may contain an array
|
||||
};
|
||||
|
||||
RGBA vals[4]; // Ok: Array of structures
|
||||
vals[0].a = 0;
|
||||
|
||||
A d[5]; // NO: Array of structures that contain arrays
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Closures
|
||||
|
||||
A `closure`is an expression or function call that will be stored, along
|
||||
with necessary contextual information, to be evaluated at a later time.
|
||||
|
||||
In general, the type "`closure` *gentype*" behaves exactly like a
|
||||
*gentype*, except that its numeric values may not be examined or
|
||||
used for the duration of the shader's execution. For example, a
|
||||
`color closure` behaves mostly like a color --- you can multiply it by a
|
||||
scalar, assign it to a `color closure` variable, etc. --- but you may not
|
||||
assign it to an ordinary `color` or examine its individual component's
|
||||
numeric values.
|
||||
|
||||
It is legal to assign `0` to a closure, which is understood to mean setting it
|
||||
to a *null closure* (even though in all other circumstances, assigning a
|
||||
`float` to a `closure`would not be allowed).
|
||||
|
||||
At present, the only type of `closure`supported by OSL is the `color closure`,
|
||||
and the only allowed operations are those that let you form a linear
|
||||
combination of `color closure`'s. Additional closure types and operations are
|
||||
reserved for future use.
|
||||
|
||||
Allowable operations on `color closure` include:
|
||||
|
||||
Operation | Result | Explanation
|
||||
:--------- | :------ | :---
|
||||
`-` *colorclosure* | `color closure` | unary negation
|
||||
| |
|
||||
| |
|
||||
*color* `*` *colorclosure* | `color closure` | component-wise scaling
|
||||
*colorclosure* `*` *color* | `color closure` | component-wise scaling
|
||||
*float* `*` *colorclosure* | `color closure` | scaling
|
||||
*colorclosure* `*` *float* | `color closure` | scaling
|
||||
| |
|
||||
| |
|
||||
*colorclosure* `+` *colorclosure* | `color closure` | component-wise addition
|
||||
% *colorclosure* `-` *colorclosure* | `color closure` | component-wise subtraction
|
||||
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
(chap-glossary)=
|
||||
# Glossary
|
||||
|
||||
Attribute state
|
||||
|
||||
: The set of variables that determines all the properties (other than shape)
|
||||
of a *geometric primitive* --- such as its local transformation matrix,
|
||||
the surface, displacement, and volume shaders to be used, which light
|
||||
sources illuminate objects that share the attribute state, whether
|
||||
surfaces are one-sided or two-sided, etc. Basically all of the options
|
||||
that determine the behavior and appearance of the primitives, that are not
|
||||
determined by the shape itself or the code of the shaders. A single
|
||||
attribute state may be shared among multiple geometric primitives. Also
|
||||
sometimes called *graphics state*.
|
||||
|
||||
BSDF
|
||||
|
||||
: Bidirectional scattering distribution function, a function that describes
|
||||
light scattering properties of a surface.
|
||||
|
||||
Built-in function
|
||||
|
||||
: A function callable from within a shader, where the implementation of the
|
||||
function is provided by the renderer (as opposed to a function that the
|
||||
shader author writes in OSL itself).
|
||||
|
||||
Closure
|
||||
|
||||
: A symbolic representation of a function to be called, and values for its
|
||||
parameters, that are packaged up to be evaluated at a later time to yield
|
||||
a final numeric value.
|
||||
|
||||
Connection
|
||||
|
||||
: A routing of the value of an *output parameter* of one *shader layer* to
|
||||
an *input parameter* of another shader layer within the same *shader
|
||||
group*.
|
||||
|
||||
Default parameter value
|
||||
|
||||
: The initial value of a *shader parameter*, if the renderer does not
|
||||
override it with an *instance value*, an interpolated *primitive
|
||||
variable*, or a *connection* to an output parameter of another *layer*
|
||||
within the *group*. The default value of a shader parameter is explicitly
|
||||
given in the code for that shader, and may either be a constant or a
|
||||
computed expression.
|
||||
|
||||
EDF
|
||||
|
||||
: Emission distribution function, a function that describes the distribution
|
||||
of light emitted by a light source.
|
||||
|
||||
Geometric primitive
|
||||
|
||||
: A single shape, such as a NURBS patch, a polygon or subdivision mesh, a
|
||||
hair primitive, etc.
|
||||
|
||||
Global variables
|
||||
|
||||
: The set of "built-in" variables describing the common renderer inputs to
|
||||
all shaders (as opposed to shader-specific parameters). These include
|
||||
position (`P`), surface normal (`N`), surface tangents (`dPdu`, `dPdv`),
|
||||
as well as standard radiance output (`Ci`). Different *shader types*
|
||||
support different subsets of the global variables.
|
||||
|
||||
Graphics state
|
||||
|
||||
: See *attribute state*.
|
||||
|
||||
Group
|
||||
|
||||
: See *shader group*.
|
||||
|
||||
Input parameter
|
||||
|
||||
: A read-only *shader parameter* that provides a value to control a
|
||||
shader's behavior. Can also refer to a read-only parameter to a
|
||||
*shader function*.
|
||||
|
||||
Instance value
|
||||
|
||||
: A constant value that overrides a default parameter value for a
|
||||
particular *shader instance*. Each instance of a shader may have a
|
||||
completely different set of instance values for its parameters.
|
||||
|
||||
Layer
|
||||
|
||||
: See *shader layer*.
|
||||
|
||||
Output parameter
|
||||
|
||||
: A read/write *shader parameter* allows a shader to provide outputs beyond
|
||||
the *global variables* such as `Ci`. Can also refer to a read/write
|
||||
parameter to a *shader function*, allowing a function to provide more
|
||||
outputs than a simple return value.
|
||||
|
||||
Primitive
|
||||
|
||||
: Usually refers to a *geometric primitive*.
|
||||
|
||||
Primitive variable
|
||||
|
||||
: A named variable, and values, attached to an individual geometric
|
||||
primitive. Primitive variables may have one of several *interpolation
|
||||
methods* --- such as a single value for the whole primitive, a value for
|
||||
each piece or face of the primitive, or per-vertex values that are
|
||||
smoothly interpolated across the surface.
|
||||
|
||||
% Public method
|
||||
%
|
||||
% : A function within a shader that has an entry point that is visible and
|
||||
% directly callable by the renderer, as opposed to merely being called from
|
||||
% other code within the shader. Public methods must be *top-level* (not
|
||||
% defined within other functions) and must be preceded by the `public`
|
||||
% keyword.
|
||||
|
||||
Shader
|
||||
|
||||
: A small self-contained program written in OSL, used to extend the
|
||||
functionality of a renderer with custom behavior of materials and lights.
|
||||
A particular shader may have multiple *shader instances* within a scene,
|
||||
each of which has its unique *instance parameters*, transformation, etc.
|
||||
|
||||
Shader function
|
||||
|
||||
: A function written in OSL that may be called from within a shader.
|
||||
|
||||
Shader group
|
||||
|
||||
: An ordered collection of *shader instances* (individually called the
|
||||
*layers* of a group) that are executed to collectively determine material
|
||||
properties or displacement of a geometric primitive, emission of a light
|
||||
source, or scattering properties of a volume. In addition to executing
|
||||
sequentially, layers within a group may optionally have any of their input
|
||||
parameters explicitly connected to output parameters of other layers
|
||||
within the group in an acyclic manner (thus, sometimes being referred to
|
||||
as a *shader network*).
|
||||
|
||||
Shader instance
|
||||
|
||||
: A particular reference to a *shader*, with a unique set of *instance
|
||||
values*, transformation, and potentially other attributes. Each shader
|
||||
instance is a separate entity, despite their sharing executable code.
|
||||
|
||||
Shader network
|
||||
|
||||
: See *shader group*.
|
||||
|
||||
Shader layer
|
||||
|
||||
: An individual *shader instance* within a *shader group*.
|
||||
|
||||
Shader parameter
|
||||
|
||||
: A named input or output variable of a shader. *Input parameters* provide
|
||||
"knobs" that control the behavior of a shader; *output parameters*
|
||||
additional provide a way for shaders to produce additional output beyond
|
||||
the usual *global variables*.
|
||||
|
||||
Shading
|
||||
|
||||
: The computations within a renderer that implement the behavior and visual
|
||||
appearance of materials and lights.
|
||||
|
||||
VDF
|
||||
|
||||
: Volumetric distribution function, a function that describes the scattering
|
||||
properties of a volume.
|
||||
@@ -0,0 +1,239 @@
|
||||
---
|
||||
numbering:
|
||||
heading_1: true
|
||||
heading_2: true
|
||||
heading_3: true
|
||||
---
|
||||
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
(chap-grammar)=
|
||||
# Formal Language Grammar
|
||||
|
||||
This section gives the complete syntax of OSL. Syntactic structures that have
|
||||
a name ending in `-opt` are optional. Structures surrounded by curly braces
|
||||
`{ }` may be repeated 0 or more times. Text in `typewriter` face indicates
|
||||
literal text. The $\epsilon$ character is used to indicate that it is
|
||||
acceptable for there to be nothing (empty, no token).
|
||||
|
||||
#### Lexical elements
|
||||
|
||||
|
||||
\<digit\> ::= "`0`" | "`1`" | "`2`" | "`3`" | "`4`" | "`5`" | "`6`" | "`7`" | "`8`" | "`9`"
|
||||
|
||||
\<digit-sequence\> ::= \<digit\> { \<digit\> }
|
||||
|
||||
\<hexdigit\> ::= \<digit\> | "`a`" | "`A`" | "`b`" | "`B`" | "`c`" | "`C`" | "`d`" | "`D`" | "`e`" | "`E`" | "`f`" | "`F`"
|
||||
|
||||
\<hexdigit-sequence\> ::= \<hexdigit\> { \<hexdigit\> }
|
||||
|
||||
\<integer\> ::= \<sign\> \<digit-sequence\>
|
||||
<br>$~~~~~~~~~~$ | \<sign\> "`0x`" \<hexdigit-sequence\>
|
||||
|
||||
\<floating-point\> ::= \<digit-sequence\> \<decimal-part-opt\> \<exponent-opt\>
|
||||
<br>$~~~~~~~~~~$ | \<decimal-part\> \<exponent-opt\>
|
||||
|
||||
\<decimal-part\> ::= '`.`' { \<digit\> }
|
||||
|
||||
\<exponent\> ::= '`e`' \<sign\> \<digit-sequence\>
|
||||
|
||||
\<sign\> ::= '`-`' | '`+`' | $\epsilon$
|
||||
|
||||
\<number\> ::= \<integer\>
|
||||
<br>$~~~~~~~~~~$ | \<floating-point\>
|
||||
|
||||
\<char-sequence\> ::= { \<any-char\> }
|
||||
|
||||
\<stringliteral> ::= `"` \<char-sequence\> `"`
|
||||
|
||||
\<identifier\> ::= \<letter-or-underscore\> { \<letter-or-underscore-or-digit\> }
|
||||
|
||||
|
||||
#### Overall structure
|
||||
|
||||
\<shader-file\> ::= { \<global-declaration\> }
|
||||
|
||||
\<global-declaration\> ::= \<function-declaration\>
|
||||
<br>$~~~~~~~~~~$ | \<struct-declaration\>
|
||||
<br>$~~~~~~~~~~$ | \<shader-declaration\>
|
||||
|
||||
\<shader-declaration\> ::= <br>$~~~~~~~~~~~~$ $~~~~~~~~~~$
|
||||
\<shadertype\> \<identifier\> \<metadata-block-opt\>
|
||||
"(" \<shader-formal-params-opt\> ")" "{" \<statement-list\> "}"
|
||||
|
||||
\<shadertype\> ::= "displacement" | "shader" | "surface" | "volume"
|
||||
|
||||
\<shader-formal-params\> ::= \<shader-formal-param\> { "," \<shader-formal-param\> }
|
||||
|
||||
\<shader-formal-param\> ::= \<outputspec\> \<typespec\> \<identifier\>
|
||||
\<initializer\> \<metadata-block-opt\>
|
||||
<br>$~~~~~~~~~~$ | \<outputspec\> \<typespec\> \<identifier\> \<arrayspec\>
|
||||
\<initializer-list\> \<metadata-block-opt\>
|
||||
|
||||
\<metadata-block> ::= "[[" \<metadata\> { "," \<metadata\> } "]]"
|
||||
|
||||
\<metadata\> ::= \<simple-typespec\> \<identifier\> \<initializer\>
|
||||
|
||||
|
||||
|
||||
#### Declarations
|
||||
|
||||
\<function-declaration\> ::= <br>$~~~~~~~~~~~~$ \<typespec\> \<identifier\>
|
||||
"(" \<function-formal-params-opt\> ")" "{" \<statement-list\> "}"
|
||||
|
||||
\<function-formal-params\> ::= \<function-formal-param\> { "," \<function-formal-param\> }
|
||||
|
||||
\<function-formal-param\> ::= \<outputspec\> \<typespec\> \<identifier\> \<arrayspec-opt\>
|
||||
|
||||
\<outputspec> ::= "output" | $\epsilon$
|
||||
|
||||
\<struct-declaration\> ::= "struct" \<identifier\> "{" \<field-declarations> "}" ";"
|
||||
|
||||
\<field-declarations\> ::= \<field-declaration\> { \<field-declaration\> }
|
||||
|
||||
\<field-declaration\> ::= \<typespec\> \<typed-field-list\> ";"
|
||||
|
||||
\<typed-field-list\> ::= \<typed-field\> { "," \<typed-field\> }
|
||||
|
||||
\<typed-field\> ::= \<identifier\> \<arrayspec-opt\>
|
||||
|
||||
\<local-declaration\> ::= \<function-declaration\>
|
||||
<br>$~~~~~~~~~~$ | \<variable-declaration\>
|
||||
|
||||
\<arrayspec> ::= "[" \<integer\> "]"
|
||||
<br>$~~~~~~~~~~$ | "[" "]"
|
||||
|
||||
\<variable-declaration\> ::= \<typespec\> \<def-expressions> ";"
|
||||
|
||||
\<def-expressions\> ::= \<def-expression\> { "," <def-expression\> }
|
||||
|
||||
\<def-expression\> ::= \<identifier\> \<initializer-opt\>
|
||||
<br>$~~~~~~~~~~$ | \<identifier\> \<arrayspec\> \<initializer-list-opt\>
|
||||
|
||||
\<initializer\> ::= "=" \<expression\>
|
||||
|
||||
\<initializer-list\> ::= "=" \<compound-initializer\>
|
||||
|
||||
\<compound-initializer\> ::= "{" \<init-expression-list\> "}"
|
||||
|
||||
\<init-expression-list\> ::= \<init-expression\> { "," \<init-expression\> }
|
||||
|
||||
\<init-expression\> ::= \<expression\> | \<compound-initializer\>
|
||||
|
||||
\<typespec\> ::= \<simple-typename>
|
||||
<br>$~~~~~~~~~~$ | "closure" \<simple-typename\>
|
||||
<br>$~~~~~~~~~~$ | \<identifier-structname\>
|
||||
|
||||
\<simple-typename\> ::=
|
||||
"color"
|
||||
| "float"
|
||||
| "matrix"
|
||||
| "normal"
|
||||
| "point"
|
||||
| "string"
|
||||
| "vector"
|
||||
| "void"
|
||||
|
||||
|
||||
|
||||
#### Statements
|
||||
|
||||
\<statement-list\> ::= \<statement\> { \<statement\> }
|
||||
|
||||
\<statement\> ::=
|
||||
\<compound-expression-opt\> ";"
|
||||
<br>$~~~~~~~~~~$ | \<scoped-statements\>
|
||||
<br>$~~~~~~~~~~$ | \<local-declaration\>
|
||||
<br>$~~~~~~~~~~$ | \<conditional-statement\>
|
||||
<br>$~~~~~~~~~~$ | \<loop-statement\>
|
||||
<br>$~~~~~~~~~~$ | \<loopmod-statement\>
|
||||
<br>$~~~~~~~~~~$ | \<return-statement\>
|
||||
|
||||
\<scoped-statements> ::= "{" \<statement-list-opt\> "}"
|
||||
|
||||
\<conditional-statement\> ::= <br>$~~~~~~~~~~~~$ "if" "(" \<compound-expression\> ")" \<statement\>
|
||||
<br>$~~~~~~~~~~$ | "if" "(" \<compound-expression\> ")" \<statement\> "else" \<statement\>
|
||||
|
||||
\<loop-statement\> ::= <br>$~~~~~~~~~~~~$ "while" "(" \<compound-expression\> ")" \<statement\>
|
||||
<br>$~~~~~~~~~~$ | "do" \<statement\> "while" "(" \<compound-expression\> ")" ";"
|
||||
<br>$~~~~~~~~~~$ | "for" "(" \<for-init-statement-opt\> \<compound-expression-opt\> ";"
|
||||
\<compound-expression-opt\> ")" \<statement\>
|
||||
|
||||
\<for-init-statement\> ::= <br>$~~~~~~~~~~~~$ \<expression-opt\> ";"
|
||||
<br>$~~~~~~~~~~$ | \<variable-declaration\>
|
||||
|
||||
\<loopmod-statement\> ::= "break" ";"
|
||||
<br>$~~~~~~~~~~$ | "continue" ";"
|
||||
|
||||
|
||||
\<return-statement\> ::= "return" \<expression-opt\> ";"
|
||||
|
||||
|
||||
|
||||
#### Expressions
|
||||
|
||||
\<expression-list\> ::= \<expression\> { "," \<expression\> }
|
||||
|
||||
\<expression\> ::= \<number\>
|
||||
<br>$~~~~~~~~~~$ | \<stringliteral\>
|
||||
<br>$~~~~~~~~~~$ | \<type-constructor\>
|
||||
<br>$~~~~~~~~~~$ | \<incdec-op\> \<variable-ref\>
|
||||
<br>$~~~~~~~~~~$ | \<expression\> \<binary-op\> \<expression\>
|
||||
<br>$~~~~~~~~~~$ | \<unary-op\> \<expression\>
|
||||
<br>$~~~~~~~~~~$ | "(" \<compound-expression\> ")"
|
||||
<br>$~~~~~~~~~~$ | \<function-call\>
|
||||
<br>$~~~~~~~~~~$ | \<assign-expression\>
|
||||
<br>$~~~~~~~~~~$ | \<ternary-expression\>
|
||||
<br>$~~~~~~~~~~$ | \<typecast-expression\>
|
||||
<br>$~~~~~~~~~~$ | \<variable-ref\>
|
||||
<br>$~~~~~~~~~~$ | \<compound-initializer\>
|
||||
|
||||
\<compound-expression\> ::= \<expression\> { "," \<expression\> }
|
||||
|
||||
\<variable-lvalue\> ::= \<identifier\> \<array-deref-opt\> \<component-deref-opt\>
|
||||
<br>$~~~~~~~~~~$ | \<variable_lvalue> "[" \<expression\> "]"
|
||||
<br>$~~~~~~~~~~$ | \<variable_lvalue> "." \<identifier\>
|
||||
|
||||
\<variable-ref\> ::= \<identifier\> \<array-deref-opt\>
|
||||
|
||||
\<array-deref> ::= "[" \<expression\> "]"
|
||||
|
||||
\<component-deref> ::= "[" \<expression\> "]"
|
||||
<br>$~~~~~~~~~~$ | "." \<component-field\>
|
||||
|
||||
\<component-field\> ::= "x" | "y" | "z" | "r" | "g" | "b"
|
||||
|
||||
\<binary-op> ::= "*" | "/" | "\%"
|
||||
<br>$~~~~~~~~~~$ | "+" | "-"
|
||||
<br>$~~~~~~~~~~$ | "<<" | ">>"
|
||||
<br>$~~~~~~~~~~$ | "<" | "<=" | ">" | ">="
|
||||
<br>$~~~~~~~~~~$ | "==" | "!="
|
||||
<br>$~~~~~~~~~~$ | "&"
|
||||
<br>$~~~~~~~~~~$ | "^"
|
||||
<br>$~~~~~~~~~~$ | "|"
|
||||
<br>$~~~~~~~~~~$ | "&&" | "and"
|
||||
<br>$~~~~~~~~~~$ | "||" | "or"
|
||||
|
||||
\<unary-op> ::= "-" | "~" | "!" | "not"
|
||||
|
||||
\<incdec-op> ::= "++" | "--"
|
||||
|
||||
\<type-constructor\> ::= \<typespec> "(" \<expression-list\> ")"
|
||||
|
||||
\<function-call\> ::= \<identifier\> "(" \<function-args-opt\> ")"
|
||||
|
||||
\<function-args\> ::= \<expression\> { "," \<expression\> }
|
||||
|
||||
\<assign-expression\> ::= \<variable-lvalue\> \<assign-op\> \<expression\>
|
||||
|
||||
\<assign-op> ::= "=" | "*=" | "/=" | "+=" | "-=" | "&=" | "|=" | "^=" |
|
||||
"<<=" | ">>="
|
||||
|
||||
\<ternary-expression\> ::= \<expression\> "?" \<expression\> ":" \<expression\>
|
||||
|
||||
\<typecast-expression\> ::= "(" \<simple-typename> ")" \<expression\>
|
||||
|
||||
@@ -0,0 +1,403 @@
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
# Gross syntax, shader types, parameters
|
||||
|
||||
The overall structure of a shader is as follows:
|
||||
|
||||
> *optional-function-or-struct-declarations* \
|
||||
\
|
||||
shader-type shader-name `(` optional-parameters `)` \
|
||||
`{` \
|
||||
*statements* \
|
||||
`}`
|
||||
|
||||
Note that *statements* may include function or structure definitions, local
|
||||
variable declarations, or public methods, as well as ordinary execution
|
||||
instructions (such as assignments, etc.).
|
||||
|
||||
## Shader types
|
||||
|
||||
Shader types include the following: `surface`, `displacement`, `light`,
|
||||
`volume`, and generic `shader`. Some operations may only be performed from
|
||||
within certain types of shaders (e.g., one may only call `displace()` or alter
|
||||
`P` in a displacement shader), and some global variables may only be accessed
|
||||
from within certain types of shaders (e.g., `dPdu` is not defined inside a
|
||||
volume shader).
|
||||
|
||||
Following are brief descriptions of the basic types of shaders:
|
||||
|
||||
|
||||
`surface` shaders
|
||||
|
||||
: Surface shaders determine the basic material properties of a surface and
|
||||
how it reacts to light. They are responsible for computing a
|
||||
`color closure` that describes the material, and optionally setting
|
||||
other user-defined output variables. They may not alter
|
||||
the position of the surface.
|
||||
|
||||
Surface shaders are written as if they describe the behavior of a single
|
||||
point on the primitive, and the renderer will choose the positions
|
||||
surface at which the shader must be evaluated.
|
||||
|
||||
Surface shaders also are used to describe emissive objects, i.e., light
|
||||
sources. OSL does not need a separate shader type to describe lights.
|
||||
|
||||
`displacement` shaders
|
||||
|
||||
: Displacement shaders alter the position and shading normal (or,
|
||||
optionally, just the shading normal) to make a piece of geometry appear
|
||||
deformed, wrinkled, or bumpy. They are the only kind of shader that
|
||||
is allowed to alter a primitive's position.
|
||||
|
||||
`volume` shaders
|
||||
|
||||
: Volume shaders describe how a participating medium (air, smoke, glass,
|
||||
etc.) reacts to light and affects the appearance of objects on the other
|
||||
side of the medium. They are similar to `surface` shaders, except
|
||||
that they may be called from positions that do not lie upon (and are not
|
||||
necessarily associated with) any particular primitive.
|
||||
|
||||
`shader` generic shaders
|
||||
|
||||
: Generic shaders are used for utility code, generic routines that may be
|
||||
called as individual layers in a shader group. Generic shaders need not
|
||||
specify a shader type, and therefore may be reused from inside surface,
|
||||
displacement, or volume shader groups. But as a result, they may
|
||||
not contain any functionality that cannot be performed from inside all
|
||||
shader types (for example, they may not alter `P`, which can only be done
|
||||
from within a displacement shader).
|
||||
|
||||
|
||||
## Shader parameters
|
||||
|
||||
An individual shader has (optionally) many *parameters* whose
|
||||
values may be set in a number of ways so that a single shader may have
|
||||
different behaviors or appearances when used on different objects.
|
||||
|
||||
### Shader parameter syntax
|
||||
|
||||
Shader parameters are specified in the shader declaration, in
|
||||
parentheses after the shader's name. This is much like the parameters
|
||||
to an OSL function (or a function in C or similar languages),
|
||||
except that shader parameters must have an *initializer*, giving a
|
||||
default value for the parameter. Shader parameter default initializers
|
||||
may be expressions (i.e., may be computed rather than restricted to
|
||||
numeric constants), and are evaluated in the order that the parameters
|
||||
are declared, and may include references to previously-declared
|
||||
parameters. Formally, the grammar for a simple parameter
|
||||
declaration looks like this:
|
||||
|
||||
> *type parametername* `=` *default-expression*
|
||||
|
||||
where *type* is one of the data types described in Chapter [](#chap-types),
|
||||
*parametername* is the name of the parameter, and *default-expression* is a
|
||||
valid expression (see Section [](#sec-expressions)). Multiple parameters are
|
||||
simply separated by commas:
|
||||
|
||||
> *type1 parameter1* `=` *expr1* `,` *type2 parameter2* `=` *expr2* `,` ...
|
||||
|
||||
Fixed-length, one-dimensional array parameters are declared as follows:
|
||||
|
||||
> *type parametername* `[` *array-length* `] = {` *expr0* `,` *expr1* ... `}`
|
||||
|
||||
where *array-length* is a positive integer constant giving the length of the
|
||||
array, and the initializer is a series of initializing expressions listed
|
||||
between curly braces. The first initializing expression provides the
|
||||
initializer for the first element of the array, the second expression provides
|
||||
the initializer for the second element of the array, and so on. If the number
|
||||
of initializing expressions is less than the length of the array, any
|
||||
additional array elements will have undefined values.
|
||||
|
||||
Arrays may also be declared without a set length:
|
||||
|
||||
> *type parametername* `[ ] = {` *expr0* `,` *expr1* ... `}`
|
||||
|
||||
where no array length is found between the square brackets.
|
||||
This indicates that the array's length will be determined based on
|
||||
whatever is passed in --- a connection from the output of another shader
|
||||
in the group (take on the length of that output), an instance value
|
||||
(take on the length specified by the declaration of the instance value),
|
||||
or a primitive variable (length determined by its declaration on the
|
||||
primitive). If no instance value, primitive value, or connection is
|
||||
supplied, then the number of initializing expressions will determine the
|
||||
length, as well as the default values, of the array.
|
||||
|
||||
Structure parameters are also straightforward to declare:
|
||||
|
||||
> *structure-type parametername* `= {` *expr0* `,` *expr1* ... `}`
|
||||
|
||||
where *structure-type* is the name of a previously-declared `struct` type, and
|
||||
the *expr* initializers correspond to each respective field within the
|
||||
structure. An initializer of appropriate type is required for every field of
|
||||
the structure.
|
||||
|
||||
### Shader output parameters
|
||||
|
||||
Shader parameters are, by default, read-only in the body of the
|
||||
shader. However, special \emph{output parameters} may be altered
|
||||
by execution of the shader. Parameters may be designated outputs
|
||||
by use of the {\cf output} keyword immediately prior to the
|
||||
type declaration of the parameter:
|
||||
|
||||
> `output` *type parametername* `=` *expr*
|
||||
|
||||
(Output parameters may be arrays and structures, but we will omit spelling out
|
||||
the obvious syntax here.)
|
||||
|
||||
Output parameters may be connected to inputs of later-run shader layers in the
|
||||
shader group, may be queried by later-run shaders in the group via message
|
||||
passing (i.e., `getmessage()` calls), or used by the renderer as an output
|
||||
image channel (in a manner described through the renderer's API).
|
||||
|
||||
### Shader parameter example
|
||||
|
||||
Here is an example of a shader declaration, with several parameters:
|
||||
|
||||
```
|
||||
surface wood (
|
||||
/* Simple params with constant initializers */
|
||||
float Kd = 0.5,
|
||||
color woodcolor = color (.7, .5, .3),
|
||||
string texturename = "wood.tx",
|
||||
/* Computed from an earlier parameter */
|
||||
color ringcolor = 0.25 * woodcolor,
|
||||
/* Fixed-length array */
|
||||
color paintcolors[3] = { color(0,.25,0.7), color(1,1,1),
|
||||
color(0.75,0.5,0.2) },
|
||||
/* variable-length array */
|
||||
int pattern[] = { 2, 4, 2, 1 },
|
||||
/* output parameter */
|
||||
output color Cunlit = 0
|
||||
)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### How shader parameters get their values
|
||||
|
||||
Shader parameters get their values in the following manner,
|
||||
in order of decreasing priority:
|
||||
|
||||
1. If the parameter has been designated by the renderer to be connected to an
|
||||
output parameter of a previously-executed shader layer within the shader
|
||||
group, that is the value it will get.
|
||||
2. If the parameter matches the name and type of a per-primitive, per-face, or
|
||||
per-vertex *primitive variable* on the particular piece of geometry
|
||||
being shaded, the parameter's value will be computed by interpolating the
|
||||
primitive variable for each position that must be shaded.
|
||||
3. If there is no connection or primitive variable, the parameter may will
|
||||
take on an *instance value*, if that parameter was given an explicit
|
||||
per-instance value at the time that the renderer referenced the shader
|
||||
(associating it with an object or set of objects).
|
||||
4. If none of these overrides is present, the parameter's value will be
|
||||
determined by executing the parameter initialization code in the shader.
|
||||
|
||||
This triage is performed per parameter, in order of declaration. So, for
|
||||
example, in the code sample above where the default value for `ringcolor1 is a
|
||||
scaled version of `woodcolor`, this relationship would hold whether
|
||||
`woodcolor` was the default, an instance value, an interpolated primitive
|
||||
value, or was connected to another layer's output. Unless `ringcolor` itself
|
||||
was given an instance, primitive, or connection value, in which case that's
|
||||
what would be used.
|
||||
|
||||
|
||||
|
||||
## Shader metadata
|
||||
|
||||
A shader may optionally include *metadata* (data *about* the
|
||||
shader, as opposed to data *used by* the shader). Metadata may be
|
||||
used to annotate the shader or any of its individual parameters with
|
||||
additional hints or information that will be compiled into the shader
|
||||
and may be queried by applications. A common use of metadata is to
|
||||
specify user interface hints about shader parameters --- for example,
|
||||
that a particular parameter should only take on integer values, should
|
||||
have an on/off checkbox, is intended to be a filename, etc.
|
||||
|
||||
Metadata is specified inside double brackets `[[` and `]]` enclosing a
|
||||
comma-separated list of metadata items. Each metadatum looks like a parameter
|
||||
declaration --- having a data type, name, and initializer. However, metadata
|
||||
may only be simple types or arrays of simple types (not structs or closures)
|
||||
and their value initializers must be numeric or string constants (not computed
|
||||
expressions).
|
||||
|
||||
Metadata about the shader as a whole is placed between the shader name
|
||||
and the parameter list. Metadata about shader parameters are placed
|
||||
immediately after the parameter's initializing expression, but before
|
||||
the comma or closing parentheses that terminates the parameter
|
||||
description.
|
||||
|
||||
Below is an example shader declaration showing the use of shader and
|
||||
parameter metadata:
|
||||
|
||||
```
|
||||
surface wood
|
||||
[[ string help = "Realistic wood shader" ]]
|
||||
(
|
||||
float Kd = 0.5
|
||||
[[ string help = "Diffuse reflectivity",
|
||||
float min = 0, float max = 1 ]] ,
|
||||
color woodcolor = color (.7, .5, .3)
|
||||
[[ string help = "Base color of the wood" ]],
|
||||
color ringcolor = 0.25 * woodcolor
|
||||
[[ string help = "Color of the dark rings" ]],
|
||||
string texturename = "wood.tx"
|
||||
[[ string help = "Texture map for the grain",
|
||||
string widget = "filename" ]],
|
||||
int pattern = 0
|
||||
[[ string widget = "mapper",
|
||||
string options = "oak:0|elm:1|walnut:2" ]]
|
||||
)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
The metadata are not semantically meaningful; that is, the metadata does
|
||||
not affect the actual execution of the shader. Most metadata exist only
|
||||
to be embedded in the compiled shader and able to be queried by other
|
||||
applications, such as to construct user interfaces for shader assignment
|
||||
that allow usage tips, appropriate kinds of widgets for setting each
|
||||
parameter, etc.
|
||||
|
||||
The choice of metadata and their meaning is completely up to the shader
|
||||
writer and/or modeling system. However, we propose some conventions
|
||||
below. These conventions are not intended to be comprehensive, nor to
|
||||
meet all your needs --- merely to establish a common nomenclature for
|
||||
the most common metadata uses.
|
||||
|
||||
The use of metadata is entirely optional on the part of the shader
|
||||
writer, and any application that queries shader metadata is free to
|
||||
honor or ignore any metadata it finds.
|
||||
|
||||
string label
|
||||
: A short label to be displayed in the UI for this parameter. If not
|
||||
present, the parameter name itself should be used as the widget label.
|
||||
|
||||
string help
|
||||
: Help text that describes the purpose and use of the shader or parameter.
|
||||
|
||||
string page
|
||||
: Helps to group related widgets by ``page.''
|
||||
|
||||
string widget
|
||||
: The type of widget that should be used to adjust this parameter.
|
||||
Suggested widget types:
|
||||
|
||||
"number"
|
||||
: Provide a slider and/or numeric input. This is the default widget type for
|
||||
`float` or `int` parameters. Numeric inputs also may be influenced by the
|
||||
following metadata: `min`, `max`, `sensitivity`, `digits`, `slider`,
|
||||
`slidermin`, `slidermax`, `slidercenter`, `sliderexponent`.
|
||||
|
||||
"string"
|
||||
: Provide a text entry widget. This is the default widget type for
|
||||
{\cf string} parameters.
|
||||
|
||||
"boolean"
|
||||
: Provide a pop-up menu with "Yes" and "No" options. Works on strings
|
||||
or numbers. With strings, "Yes" and "No" values are used, with
|
||||
numbers, 0 and 1 are used.
|
||||
|
||||
"checkBox"
|
||||
: A boolean widget displayed as a checkbox. Works on strings or
|
||||
numbers. With strings, "Yes" and "No" values are used, with numbers,
|
||||
0 and 1 are used.
|
||||
|
||||
"popup"
|
||||
: A pop-up menu of literal choices. This widget further requires
|
||||
parameter metadata `options` (a string listing the supported
|
||||
menu items, delimited by the `|` character), and optionally `editable`
|
||||
(an integer, which if nonzero means the widget should allow the
|
||||
text field should be directly editable). For example:
|
||||
```
|
||||
string wrap = "default"
|
||||
[[ string widget = "popup",
|
||||
string options = "default|black|clamp|periodic|mirror" ]]
|
||||
```
|
||||
|
||||
"mapper"
|
||||
: A pop-up with associative choices (an enumerated type, if the values are
|
||||
integers). This widget further requires parameter metadata `options`, a
|
||||
`|`-delimited string with "key:value" pairs. For example:
|
||||
```
|
||||
int pattern = 0
|
||||
[[ string widget = "mapper",
|
||||
string options = "oak:0|elm:1|walnut:2" ]]
|
||||
```
|
||||
|
||||
"filename"
|
||||
: A file selection dialog.
|
||||
|
||||
"null"
|
||||
: A hidden widget.
|
||||
|
||||
|
||||
float min, float max, int min, int max
|
||||
: The minimum and/or maximum value that the parameter may take on.
|
||||
|
||||
float sensitivity, int sensitivity
|
||||
: The precision or step size for incrementing or decrementing the value
|
||||
(within the appropriate min/max range).
|
||||
|
||||
int digits
|
||||
: The number of digits to show (-1 for full precision).
|
||||
|
||||
int slider
|
||||
: If nonzero, enables display of a slider sub-widget. This also respects the
|
||||
following additional metadata that control the slider specifically:
|
||||
`slidermin` (minimum value for the slider, `slidermax` (maximum value for
|
||||
the slider), `slidercenter` (origin value for the slider), `sliderexponent`
|
||||
(nonlinear slider options).
|
||||
|
||||
string URL
|
||||
: Provides a URL for full documentation of the shader or parameter.
|
||||
|
||||
string units
|
||||
: Gives the assumed units, if any, for the parameter (e.g., `cm`, `sec`,
|
||||
`degrees`). The compiler or renderer may issue a warning if it detects that
|
||||
this assumption is being violated (for example, the compiler can warn if a
|
||||
`degrees` variable is passed as the argument to `cos`).
|
||||
|
||||
|
||||
% We never implemented this:
|
||||
% ## Public methods
|
||||
%
|
||||
% Ordinary (non-public) functions inside a shader may be called only from
|
||||
% within the shader; they do not generate entry points that the renderer
|
||||
% is aware of.
|
||||
%
|
||||
% A *public method* is a function that may be directly called by the
|
||||
% renderer. Only top-level local functions of a shader --- that is,
|
||||
% declared within the braces that define the local scope of the shader,
|
||||
% but not within any other such function --- may be public methods. A
|
||||
% function may be designated a public method by using the `public`
|
||||
% keyword immediately before the function declaration:
|
||||
%
|
||||
% > *shader-type shader-name* `(` *params* `)` \
|
||||
% > `{` \
|
||||
% >
|
||||
% > `public` *return-type* *function-name* `(` *optional-parameters* `)` \
|
||||
% > `{` \
|
||||
% > *statements* \
|
||||
% > `}` \
|
||||
% >
|
||||
% > ...\\
|
||||
% > `}`
|
||||
|
||||
|
||||
% A given renderer will publish a list of public methods (names, arguments
|
||||
% expected, and return value) that has particular meaning for that
|
||||
% renderer. For example, a renderer may honor a public method
|
||||
% ```
|
||||
% public float maxdisplacement ()
|
||||
% ```
|
||||
% that computes and returns the maximum distance
|
||||
% that a displacement shader will move any surface points.
|
||||
|
||||
% At some later point, this spec will recommend several ``standard''
|
||||
% public methods that should be honored by most renderers.
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
..
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
|
||||
|
||||
.. image::
|
||||
../../ASWF/logos/openshadinglanguage-stacked-Shaded.png
|
||||
|
||||
|
||||
=============================================
|
||||
Open Shading Language |version| Documentation
|
||||
=============================================
|
||||
|
||||
.. only:: not latex
|
||||
|
||||
|
||||
|
||||
Editor: Larry Gritz, OSL Chief Architect
|
||||
|
||||
Open Shading Language (OSL) is a small but rich language for programmable
|
||||
shading in advanced renderers and other applications, ideal for describing
|
||||
materials, lights, displacement, and pattern generation.
|
||||
|
||||
Quick Links:
|
||||
`GitHub repository <https://github.com/AcademySoftwareFoundation/OpenShadingLanguage>`_ /
|
||||
`Developer mail list <https://lists.aswf.io/g/osl-dev>`_ /
|
||||
`BSD License <https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/master/LICENSE.md>`_
|
||||
|
||||
|
||||
------------
|
||||
|
||||
.. default-role:: code
|
||||
|
||||
|
||||
.. only:: not latex
|
||||
|
||||
Contents
|
||||
--------
|
||||
|
||||
.. toctree::
|
||||
:caption: Introduction
|
||||
|
||||
copyr
|
||||
|
||||
.. toctree::
|
||||
:caption: The OSL Language Specification
|
||||
:maxdepth: 2
|
||||
:numbered: 2
|
||||
|
||||
intro
|
||||
bigpicture
|
||||
lexical
|
||||
grosssyntax
|
||||
datatypes
|
||||
syntax
|
||||
stdlib
|
||||
grammar
|
||||
shadergroups
|
||||
glossary
|
||||
|
||||
|
||||
.. comment
|
||||
This is where we would put additional documentation sections
|
||||
in the future.
|
||||
|
||||
|
||||
.. comment
|
||||
Helpful links when writing documentation:
|
||||
|
||||
Doxygen docs:
|
||||
http://www.doxygen.nl/manual/index.html
|
||||
Sphinx docs:
|
||||
http://www.sphinx-doc.org/en/master/contents.html
|
||||
http://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#cpp-domain
|
||||
Breathe docs:
|
||||
https://github.com/michaeljones/breathe
|
||||
https://breathe.readthedocs.io/en/latest/directives.html
|
||||
RST:
|
||||
|
||||
sphinx-tabs plugin for Sphinx:
|
||||
https://pypi.org/project/sphinx-tabs/
|
||||
https://sphinx-tabs.readthedocs.io/en/latest/#
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
-->
|
||||
|
||||
|
||||
(chap-introduction=)
|
||||
# Introduction
|
||||
|
||||
Welcome to Open Shading Language!
|
||||
|
||||
|
||||
Open Shading Language (OSL) is a small but rich language for
|
||||
programmable shading in advanced renderers and other applications, ideal
|
||||
for describing materials, lights, displacement, and pattern generation.
|
||||
|
||||
OSL was developed by Sony Pictures Imageworks for use in its in-house
|
||||
renderer used for feature film animation and visual effects. The
|
||||
language specification was developed with input by other visual effects
|
||||
and animation studios who also wish to use it.
|
||||
|
||||
OSL is distributed under the "New BSD" license. In short, you are free
|
||||
to use it in your own applications, whether they are free or commercial,
|
||||
open or proprietary, as well as to modify the OSL code as you desire,
|
||||
provided that you retain the original copyright notices as described in
|
||||
the license.
|
||||
|
||||
|
||||
#### How OSL is different from other shading languages
|
||||
|
||||
OSL has syntax similar to C, as well as other shading languages.
|
||||
However, it is specifically designed for advanced rendering algorithms
|
||||
and has features such as radiance closures, BSDFs, and deferred ray
|
||||
tracing as first-class concepts.
|
||||
|
||||
OSL has several unique characteristics not found in other shading
|
||||
languages (certainly not all together). Here are some things you will
|
||||
find are different in OSL compared to other languages:
|
||||
|
||||
* **Surface and volume shaders compute radiance closures, not final colors.**
|
||||
|
||||
OSL's surface and volume shaders compute an explicit symbolic
|
||||
description, called a "closure," of the way a surface or volume
|
||||
scatters light, in units of radiance. These radiance closures may be
|
||||
evaluated in particular directions, sampled to find important
|
||||
directions, or saved for later evaluation and re-evaluation.
|
||||
This new approach is ideal for a physically-based renderer that
|
||||
supports ray tracing and global illumination.
|
||||
|
||||
In contrast, other shading languages usually compute just a surface
|
||||
color as visible from a particular direction. These old shaders are
|
||||
"black boxes" that a renderer can do little with but execute to for
|
||||
this once piece of information (for example, there is no effective way
|
||||
to discover from them which directions are important to sample).
|
||||
Furthermore, the physical units of lights and surfaces are often
|
||||
underspecified, making it very difficult to ensure that shaders are
|
||||
behaving in a physically correct manner.
|
||||
|
||||
* **Surface and volume shaders do not loop over lights or shoot rays.**
|
||||
|
||||
There are no "light loops" or explicitly traced rays in OSL surface
|
||||
shaders. Instead, surface shaders compute a radiance closure
|
||||
describing how the surface scatters light, and a part of the renderer
|
||||
called an "integrator" evaluates the closures for a particular set of
|
||||
light sources and determines in which directions rays should be
|
||||
traced. Effects that would ordinarily require explicit ray tracing,
|
||||
such as reflection and refraction, are simply part of the radiance
|
||||
closure and look like any other BSDF.
|
||||
|
||||
Advantages of this approach include that integration and sampling may
|
||||
be batched or re-ordered to increase ray coherence; a "ray budget" can
|
||||
be allocated to optimally sample the BSDF; the closures may be used by
|
||||
for bidirectional ray tracing or Metropolis light transport; and the
|
||||
closures may be rapidly re-evaluated with new lighting without having
|
||||
to re-run the shaders.
|
||||
|
||||
* **Surface and light shaders are the same thing.**
|
||||
|
||||
OSL does not have a separate kind of shader for light sources. Lights
|
||||
are simply surfaces that are emissive, and all lights are area lights.
|
||||
|
||||
* **Transparency is just another kind of illumination.**
|
||||
|
||||
You don't need to explicitly set transparency/opacity variables in the
|
||||
shader. Transparency is just another way for light to interact with a
|
||||
surface, and is included in the main radiance closure computed by a
|
||||
surface shader.
|
||||
|
||||
* **Renderer outputs (AOV's) are specified using "light path expressions."**
|
||||
|
||||
Sometimes it is desirable to output images containing individual
|
||||
lighting components such as specular, diffuse, reflection, individual
|
||||
lights, etc. In other languages, this is usually accomplished by
|
||||
adding a plethora of "output variables" to the shaders that collect
|
||||
these individual quantities.
|
||||
|
||||
OSL shaders need not be cluttered with any code or output variables to
|
||||
accomplish this. Instead, there is a regular-expression-based
|
||||
notation for describing which light paths should contribute to which
|
||||
outputs. This is all done on the renderer side (though supported by
|
||||
the OSL implementation). If you desire a new output, there is no need
|
||||
to modify the shaders at all; you only need to tell the renderer the
|
||||
new light path expression.
|
||||
|
||||
* **Shaders are organized into networks.**
|
||||
|
||||
OSL shaders are not monolithic, but rather can be organized into
|
||||
networks of shaders (sometimes called a shader group, graph, or DAG),
|
||||
with named outputs of some nodes being connected to named inputs of
|
||||
other nodes within the network. These connections may be done
|
||||
dynamically at render time, and do not affect compilation of
|
||||
individual shader nodes. Furthermore, the individual nodes are
|
||||
evaluated lazily, only their outputs are "pulled" from the later nodes
|
||||
that depend on them (shader writers may remain blissfully unaware of
|
||||
these details, and write shaders as if everything is evaluated
|
||||
normally).
|
||||
|
||||
* **No "uniform" and "varying" keywords in the language.**
|
||||
|
||||
OSL shaders are evaluated in SIMD fashion, executing shaders on many
|
||||
points at once, but there is no need to burden shader writers with
|
||||
declaring which variables need to be uniform or varying.
|
||||
|
||||
In the open source OSL implementation, this is done both automatically
|
||||
and dynamically, meaning that a variable can switch back and forth
|
||||
between uniform and varying, on an instruction-by-instruction basis,
|
||||
depending on what is assigned to it.
|
||||
|
||||
* **Arbitrary derivatives without grids or extra shading points.**
|
||||
|
||||
In OSL, you can take derivatives of any computed quantity in a shader,
|
||||
and use arbitrary quantities as texture coordinates and expect correct
|
||||
filtering. This does not require that shaded points be arranged in a
|
||||
rectangular grid, or have any particular connectivity, or that any
|
||||
"extra points" be shaded.
|
||||
|
||||
In the open source OSL implementation, this is possible because
|
||||
derivatives are not computed by finite differences with neighboring
|
||||
points, but rather by "automatic differentiation," computing partial
|
||||
differentials for the variables that lead to derivatives, without any
|
||||
intervention required by the shader writer.
|
||||
|
||||
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
The original designer and project leader of OSL is Larry Gritz. Other early
|
||||
developers of OSL are (in order of joining the project): Cliff Stein, Chris
|
||||
Kulla, Alejandro Conty, Jay Reynolds, Solomon Boulos, Adam Martinez, Brecht
|
||||
Van Lommel.
|
||||
|
||||
Additionally, many others have contributed features, bug fixes, and other
|
||||
changes: Steve Agland, Shane Ambler, Martijn Berger, Farchad Bidgolirad,
|
||||
Nicholas Bishop, Stefan Büttner, Matthaus G. Chajdas, Thomas Dinges, Henri
|
||||
Fousse, Syoyo Fujita, Derek Haase, Sven-Hendrik Haase, John Haddon, Daniel
|
||||
Heckenberg, Ronan Keryell, Elvic Liang, Max Liani, Bastien Montagne, Erich
|
||||
Ocean, Mikko Ohtamaa, Alex Schworer, Sergey Sharybin, Stephan Steinbach,
|
||||
Esteban Tovagliari, Alexander von Knorring, Roman Zulak. (Listed
|
||||
alphabetically; if we've left anybody out, please let us know.)
|
||||
|
||||
We cannot possibly express sufficient gratitude to the managers at Sony
|
||||
Pictures Imageworks who allowed this project to proceed, supported it
|
||||
wholeheartedly, and permitted us to release the source, especially Rob
|
||||
Bredow, Brian Keeney, Barbara Ford, Rene Limberger, and Erik Strauss.
|
||||
|
||||
Huge thanks also go to the crack shading team at SPI, and the brave
|
||||
lookdev TDs and CG supes willing to use OSL on their shows. They served
|
||||
as our guinea pigs, inspiration, testers, and a fantastic source of
|
||||
feedback. Thank you, and we hope we've been responsive to your needs.
|
||||
|
||||
OSL was not developed in isolation. We owe a debt to the individuals
|
||||
and studios who patiently read early drafts of the language
|
||||
specification and gave us very helpful feedback and additional ideas,
|
||||
and especially to those at other companies who have taken the risk of
|
||||
incorporating OSL into their products and pipelines.
|
||||
|
||||
The open source OSL implementation incorporates or depends upon several
|
||||
other open source packages:
|
||||
|
||||
- **OpenImageIO** Copyright Contributors to OpenImageIO.
|
||||
http://openimageio.org
|
||||
- **Imath** Copyright Contributors to Imath.
|
||||
http://www.openexr.com
|
||||
- **Boost** Copyright various authors. http://www.boost.org
|
||||
- **LLVM** Copyright 2003-2010 University of Illinois at
|
||||
Urbana-Champaign. http://llvm.org
|
||||
|
||||
These other packages are all distributed under licenses that allow them
|
||||
to be used by and distributed with OSL.
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
# Lexical structure
|
||||
|
||||
## Characters
|
||||
|
||||
Source code for OSL consists of ASCII or UTF-8 characters.
|
||||
|
||||
The characters for space, tab, carriage return, and linefeed are
|
||||
collectively referred to as *whitespace*. Whitespace characters
|
||||
delimit identifiers, keywords, or other symbols, but other than that
|
||||
have no syntactic meaning. Multiple whitespace characters in a row
|
||||
are equivalent to a single whitespace character.
|
||||
|
||||
Source code may be split into multiple lines, separated by end-of-line
|
||||
markers (carriage return and/or linefeed). Lines may be of any length
|
||||
and end-of-line markers carry no significant difference from other
|
||||
whitespace, except that they terminate `//` comments and delimit
|
||||
preprocessor directives.
|
||||
|
||||
## Identifiers
|
||||
|
||||
*Identifiers* are the names of variables, parameters, functions, and shaders.
|
||||
In OSL, identifiers consist of one or more characters. The first character
|
||||
may be a letter (`A`-`Z` or `a`-`z`) or underscore (`_`), and subsequent
|
||||
characters may be letters, underscore, or numerals (`0`-`9`). Examples of
|
||||
valid and invalid identifiers are:
|
||||
|
||||
```
|
||||
opacity // valid
|
||||
Long_name42 // valid - letters, underscores, numbers are ok
|
||||
_foo // valid - ok to start with an underscore
|
||||
|
||||
2smart // invalid - starts with a numeral
|
||||
bigbuck$ // invalid - $ is an illegal character
|
||||
```
|
||||
|
||||
|
||||
## Comments
|
||||
|
||||
*Comments* are text that are for the human reader of programs, and
|
||||
are ignored entirely by the OSL compiler. Just like in C++, there
|
||||
are two ways to designate comments in OSL:
|
||||
|
||||
1. Any text enclosed by `/*` and `*/` will be considered a comment, even if
|
||||
the comment spans several lines.
|
||||
|
||||
```
|
||||
/* this is a comment */
|
||||
|
||||
/* this is also
|
||||
a comment, spanning
|
||||
several lines */
|
||||
```
|
||||
|
||||
2. Any text following `//`, up to the end of the current line, will be
|
||||
considered a comment.
|
||||
|
||||
```
|
||||
// This is a comment
|
||||
a = 3; // another comment
|
||||
```
|
||||
|
||||
|
||||
## Keywords and reserved words
|
||||
|
||||
There are two sets of names that you may not use as identifiers:
|
||||
keywords and reserved words.
|
||||
|
||||
The following are *keywords* that have special meaning in OSL:
|
||||
|
||||
and break closure color continue do else emit float for if illuminance
|
||||
illuminate int matrix normal not or output point public return string
|
||||
struct vector void while
|
||||
|
||||
The following are *reserved words* that currently have no special meaning in
|
||||
OSL, but we reserve them for possible future use, or because they are
|
||||
confusingly similar to keywords in related programming languages:
|
||||
|
||||
bool case catch char class const delete default double
|
||||
enum extern false friend
|
||||
goto inline long new operator private protected
|
||||
short signed sizeof static
|
||||
switch template this throw true try typedef
|
||||
uniform union unsigned varying virtual volatile
|
||||
|
||||
|
||||
## Preprocessor
|
||||
|
||||
Shader source code is passed through a standard C preprocessor as a
|
||||
first step in parsing.
|
||||
|
||||
Preprocessor directives are designated by a hash mark `#` as the first
|
||||
character on a line, followed by a preprocessor directive name. Whitespace may
|
||||
optionally appear between the hash and the directive name.
|
||||
|
||||
OSL compilers support the full complement of C/C++ preprocessing directives,
|
||||
including:
|
||||
|
||||
```
|
||||
#define
|
||||
#undef
|
||||
#if
|
||||
#ifdef
|
||||
#ifndef
|
||||
#elif
|
||||
#else
|
||||
#endif
|
||||
#include
|
||||
#pragma error "message"
|
||||
#pragma once
|
||||
#pragma osl ...
|
||||
#pragma warning "message"
|
||||
```
|
||||
|
||||
Additionally, the following preprocessor symbols will already be
|
||||
defined by the compiler:
|
||||
|
||||
| | |
|
||||
| ------ | :------- |
|
||||
| `OSL_VERSION_MAJOR` | Major version (e.g., 1) |
|
||||
| `OSL_VERSION_MINOR` | Minor version (e.g., 9) |
|
||||
| `OSL_VERSION_PATCH` | Patch version (e.g., 3) |
|
||||
| `OSL_VERSION` | Combined version number = `10000*major + 100*minor + patch` (e.g., 10903 for version 1.9.3) |
|
||||
@@ -0,0 +1,6 @@
|
||||
sphinx >= 5.0
|
||||
breathe == 4.34.0
|
||||
sphinx-tabs
|
||||
furo==2022.6.21
|
||||
myst-parser
|
||||
linkify
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
numbering:
|
||||
heading_1: true
|
||||
heading_2: true
|
||||
heading_3: true
|
||||
---
|
||||
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
(chap-shader-groups)=
|
||||
# Describing shader groups
|
||||
|
||||
Below, we propose a simple grammar giving a standard way to serialize (i.e.,
|
||||
express as text) a full shader group, including instance values and
|
||||
connectivity of the shader layers. There are only three statements/operations:
|
||||
set an instance value, make a shader instance, and connect two instances.
|
||||
|
||||
**`param`** *`type paramname value`*... **`;`** <br> **`param`** *`type paramname value`*... **`[[`** *`metadata`*... **`]] ;`**
|
||||
|
||||
: Declare an instance value of a shader parameter to be applied to the next
|
||||
`shader` statement. We refer to the parameter values set, which have not
|
||||
yet had their shader declared, as *pending parameters*.
|
||||
|
||||
The *`paramname`* is the name of the parameter whose instance values are
|
||||
being specified.
|
||||
|
||||
The *`type`* is one of the basic numeric or string data types described in
|
||||
Chapter [](#chap-types) (`int`, `float`,`color`, `point`, `vector`, `normal`,
|
||||
`matrix`, or `string`), or an array thereof (indicated by the usual notation
|
||||
of `[size]`). The *`type`* must match the declared type of the parameter in
|
||||
the shader.
|
||||
|
||||
The actual values are listed individually, with multiple values (in the
|
||||
case of an array or an aggregate such as a `color`) simply separated by
|
||||
whitespace. If fewer values are supplied than the total number of array
|
||||
elements or aggregate components, the remainder will be understood to be
|
||||
filled with 0 values. String values must be enclosed in double quotes
|
||||
(`"like this"`).
|
||||
|
||||
The `param` statement is terminated by a semicolon (`;`).
|
||||
|
||||
Optionally, metadata hints may be supplied enclosed by double brackets,
|
||||
immediately before the semicolon.
|
||||
|
||||
|
||||
**`shader`** *`shadername layername`* **`;`**
|
||||
|
||||
: Declares a shader instance, which will receive any pending parameters that
|
||||
were declared since the previous `shader` statement (and in the process,
|
||||
clear the list of pending parameters).
|
||||
|
||||
The `shadername` is an identifier that specifies the name of the shader
|
||||
to use as the master for this instance. The `layername` is an identifier
|
||||
that names the layer (e.g., to subsequently specify it as a source or
|
||||
destination for connections).
|
||||
|
||||
The `shader` statement is terminated by a semicolon (`;`).
|
||||
|
||||
|
||||
**`connect`** *`source_layername`* **`.`** *`paramname`* $~~$ *` destination_layername`* **`.`** *`paramname`* **`;`**
|
||||
|
||||
: Establish a connection between an output parameter of a source layer and an
|
||||
input parameter of a destination layer, both of which have been previously
|
||||
declared within this group. The source layer must have preceded the
|
||||
destination layer when they were declared, and the parameters must exist and
|
||||
be of a compatible type so that it is meaningful to establish a connection
|
||||
(for example, you may connect a `color` to a `color`, but you may not connect
|
||||
a `color` to a `matrix`).
|
||||
|
||||
If the named parameters are structures, the two structures must have
|
||||
identical data layout, and establishing the connection will connect each
|
||||
corresponding data member. It is also possible to make a connection of just
|
||||
a single member of a structure by using the usual ``dot'' syntax, for
|
||||
example, for layers `A` and `B`, `connect A.c.x B.y` might
|
||||
connect A's parameter `c`, member `x`, to B's parameter `y` (the
|
||||
types of `c.x` in A and `y` in B must match).
|
||||
|
||||
The `connect` statement is terminated by a semicolon (`;`).
|
||||
|
||||
**Example**
|
||||
|
||||
param string name "rings.tx" ; # set pending `name'
|
||||
param float scale 3.5 ; # set pending `scale'
|
||||
shader "texturemap" "tex1" ; # tex1 layer, picks up `name', `scale'
|
||||
param string name "grain.tx" ;
|
||||
shader "texturemap" "tex2" ;
|
||||
param float gam 2.2 ;
|
||||
shader "gamma" "gam1" ;
|
||||
param float gam 1.0 ;
|
||||
shader "gamma" "gam2" ;
|
||||
param color woodcolor 0.42 0.38 0.22 ; # example of a color param
|
||||
shader "wood" "wood1" ;
|
||||
connect tex1.Cout gam1.Cin ; # connect tex1's Cout to gam1's Cin
|
||||
connect tex2.Cout gam2.Cin ;
|
||||
connect gam1.Cout wood1.rings ;
|
||||
connect gam2.Cout wood1.grain ;
|
||||
+2232
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,566 @@
|
||||
---
|
||||
numbering:
|
||||
heading_1: true
|
||||
heading_2: true
|
||||
heading_3: true
|
||||
---
|
||||
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
(chap-syntax)=
|
||||
# Language Syntax
|
||||
|
||||
The body of a shader is a sequence of individual *statements*.
|
||||
This chapter describes the types of statements and control-flow patterns
|
||||
in OSL.
|
||||
|
||||
Statements in OSL include the following types of constructs:
|
||||
|
||||
* Scoped statements.
|
||||
* Variable declarations.
|
||||
* Expressions.
|
||||
* Assignments.
|
||||
* Control flow: `if`, `else`, `while`, `do`, `for`, `break`, `continue`
|
||||
* Function declarations.
|
||||
|
||||
#### Scoping
|
||||
|
||||
Any place where it is legal to have a statement, it is legal to have multiple
|
||||
statements enclosed by curly braces `{ }`. This is called a *scope*. Any
|
||||
variables or functions declared within a scope are only visible within that
|
||||
scope, and only may be used after their declaration. Variables or functions
|
||||
that are referenced will always resolve to the matching name in the innermost
|
||||
scope relative to its use. For example
|
||||
|
||||
```
|
||||
float a = 1; // Call this the "outer" 'a'
|
||||
float b = 2;
|
||||
{
|
||||
float a = 3; // Call this the "inner" 'a'
|
||||
float c = 1;
|
||||
b = a; // b gets 3, because a is resolved to the inner scope
|
||||
}
|
||||
b += c; // ERROR -- c was only in the inner scope
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Variable declarations and assignments
|
||||
|
||||
### Variable declarations
|
||||
|
||||
The syntax for declaring a variable in OSL is:
|
||||
|
||||
> *type* *name*
|
||||
>
|
||||
> *type* *name* `=` *value*
|
||||
|
||||
where
|
||||
|
||||
* *type* is one of the basic data types, described earlier.
|
||||
* *name* is the name of the variable you are declaring.
|
||||
* If you wish to initialize your variable an initial value, you may
|
||||
immediately assign it a *value*, which may be any valid expression.
|
||||
|
||||
You may declare several variables of the same type in a single
|
||||
declaration by separating multiple variable names by commas:
|
||||
|
||||
> *type* *name1* `,` *name2* ...
|
||||
>
|
||||
> *type* *name1* [ = *value1*] `,` *name2* [ `=` *value2* ] ...
|
||||
|
||||
|
||||
Some examples of variable declarations are
|
||||
|
||||
```
|
||||
float a; // Declare; current value is undefined
|
||||
float b = 1; // Declare and assign a constant initializer
|
||||
float c = a*b; // Computed initializer
|
||||
float d, e = 2, f; // Declare several variables of the same type
|
||||
```
|
||||
|
||||
### Arrays
|
||||
|
||||
Arrays are also supported, declared as follows:
|
||||
|
||||
> *type variablename* `[` *arraylen* `}`
|
||||
>
|
||||
> *type variablename* `[` *arraylen* `}` `=` `{` *init0 `,` *init1* ... `}`
|
||||
|
||||
Array variables in OSL must have a constant length (though function parameters
|
||||
and shader parameters may have undetermined length). Some examples of array
|
||||
variable declarations are:
|
||||
|
||||
```
|
||||
float d[10]; // Declare an uninitialized array
|
||||
float c[3] = { 0.1, 0.2, 3.14 }; // Initialize the array
|
||||
```
|
||||
|
||||
### Structures
|
||||
|
||||
Structures are used to group several fields of potentially different
|
||||
types into a single object that can be referred to by name. The syntax
|
||||
for declaring a structure type is:
|
||||
|
||||
\spc `struct` *structname* {\cf \{}
|
||||
|
||||
\spc\spc *type1* *fieldname1* `;`
|
||||
|
||||
\spc\spc ...
|
||||
|
||||
\spc\spc *typeN* *fieldnameN* `;`
|
||||
|
||||
\spc `) ;`
|
||||
|
||||
You may then use the structure type name to declare structure variables
|
||||
as you would for any of the built-in types:
|
||||
|
||||
\spc *structname* *variablename* `;`
|
||||
|
||||
\spc *structname* *variablename* {\cf = \{ }
|
||||
*initializer1* `,` ... *initializerN* `) ;`
|
||||
|
||||
If initializers are supplied, each field of the structure will be
|
||||
initialized with the initializer in the corresponding position, which
|
||||
is expected to be of the appropriate type.
|
||||
|
||||
Structure elements are accessed in the same way as other C-like
|
||||
languages, using the `dot' operator:
|
||||
|
||||
\spc *variablename*{\cf .} *fieldname*
|
||||
|
||||
Examples of declaration and use of structures:
|
||||
|
||||
```
|
||||
struct ray {
|
||||
point pos;
|
||||
vector dir;
|
||||
};
|
||||
|
||||
ray r; // Declare a structure
|
||||
ray s = { point(0,0,0), vector(0,0,1) }; // declare and initialize
|
||||
r.pos = point (1, 0, 0); // Assign to one field
|
||||
```
|
||||
|
||||
It is permitted to have a structure field that is an array, as well as
|
||||
to have an array of structures. But it is not permitted for one
|
||||
structure to have a field that is another structure.
|
||||
|
||||
Please refer to Section~\ref{sec:types:struct} for more information
|
||||
on using `struct`.
|
||||
|
||||
|
||||
(sec-expressions)=
|
||||
## Expressions
|
||||
|
||||
The expressions available in OSL include the following:
|
||||
|
||||
* Constants: integer (e.g., `1`, `42`), floating-point (e.g. `1.0`, `3`,
|
||||
`-2.35e4`), or string literals (e.g., `"hello"`)
|
||||
|
||||
* point, vector, normal, or matrix constructors, for example:
|
||||
|
||||
```
|
||||
color (1, 0.75, 0.5)
|
||||
point ("object", 1, 2, 3)
|
||||
```
|
||||
|
||||
If all the arguments to a constructor are themselves constants, the
|
||||
constructed point is treated like a constant and has no runtime cost.
|
||||
That is, `color(1,2,3)` is treated as a single constant entity, not
|
||||
assembled bit by bit at runtime.
|
||||
|
||||
* Variable or parameter references
|
||||
|
||||
* An individual element of an array (using `[ ]`)
|
||||
|
||||
* An individual component of a `color`, `point`, `vector`, `normal` (using
|
||||
`[ ]`), or of a `matrix` (using `[][]`)
|
||||
|
||||
* prefix and postfix increment and decrement operators:
|
||||
|
||||
Operator | Meaning
|
||||
:-- | :--
|
||||
*varref* `++` | post-increment
|
||||
*varref* `--` | post-decrement
|
||||
`++` *varref* | pre-increment
|
||||
`--` *varref* | pre-decrement
|
||||
|
||||
The post-increment and post-decrement (e.g., {\cf a++}) returns the old
|
||||
value, then increments or decrements the variable; the pre-increment and
|
||||
pre-decrement ({\cf ++a}) will first increment or decrement the
|
||||
variable, then return the new value.
|
||||
|
||||
* Unary and binary arithmetic operators on other expressions:
|
||||
|
||||
Operator | Meaning
|
||||
:-- | :--
|
||||
`-` *expr* | negation
|
||||
`~` *expr* | bitwise complement
|
||||
*expr* `*` *expr* | multiplication
|
||||
*expr* `/` *expr* | division
|
||||
*expr* `+` *expr* | addition
|
||||
*expr* `-` *expr* | subtraction
|
||||
*expr* `%` *expr* | integer modulus
|
||||
*expr* `<<` *expr* | integer shift left
|
||||
*expr* `>>` *expr* | integer shift right
|
||||
*expr* `&` *expr* | bitwise and
|
||||
*expr* `\|` *expr* | bitwise or
|
||||
*expr* `^` *expr* | bitwise exclusive or
|
||||
|
||||
The operators `+`, `-`, `*`, `/`, and the unary `-` (negation) may be used
|
||||
on most of the numeric types. For multicomponent types (`color`, `point`,
|
||||
`vector`, `normal`, `matrix`), these operators combine their arguments on a
|
||||
component-by-component basis. The only operators that may be applied to the
|
||||
`matrix` type are `*` and `/`, which respectively denote matrix-matrix
|
||||
multiplication and matrix multiplication by the inverse of another matrix.
|
||||
|
||||
The integer and bit-wise operators `%`, `<<`, `>>`, `&`, `|`, `^`, and `~`
|
||||
may only be used with expressions of type `int`.
|
||||
|
||||
For details on which operators are allowed, please consult the operator
|
||||
tables for each individual type in Chapter [](#chap-types).
|
||||
|
||||
* Relational operators (all lower precedence than the arithmetic operators):
|
||||
|
||||
Operator | Meaning
|
||||
:-- | :--
|
||||
*expr* `==` *expr* | equal to
|
||||
*expr* `!=` *expr* | not equal to
|
||||
*expr* `<` *expr* | less then
|
||||
*expr* `<=` *expr* | less than or equal to
|
||||
*expr* `>` *expr* | greater than
|
||||
*expr* `>=` *expr* | greater than or equal
|
||||
|
||||
The `==` and `!=` operators may be performed between any two values of equal
|
||||
type, and are performed component-by-component for multi-component types.
|
||||
The `<`, `<=`, `>`, `>=` may not be used to compare multi-component types.
|
||||
|
||||
An `int` expression may be compared to a `float` (and is treated as if
|
||||
they are both `float`). A `float` expression may be compared to a
|
||||
multi-component type (and is treated as a multi-component type as if
|
||||
constructed from a single float).
|
||||
|
||||
Relation comparisons produce Boolean (true/false) values. These
|
||||
are implemented as `int` values, 0 if false and 1 if true.
|
||||
|
||||
* Logical unary and binary operators:
|
||||
|
||||
> `!` *expr*
|
||||
> *expr1* `&&` *expr2*
|
||||
> *expr1* `\|\|` *expr2*
|
||||
|
||||
Note that the `not`, `and`, and `or` keywords are synonyms for `!`, `&&`,
|
||||
and `||`, respectively.
|
||||
|
||||
For the logical operators, numeric expressions (`int` or `float`) are
|
||||
considered *true* if nonzero, *false* if zero. Multi-component types (such
|
||||
as `color`) are considered *true* any component is nonzero, *false* all
|
||||
components are zero. Strings are considered *true* if they are nonempty,
|
||||
*false* if they are the empty string (`""`).
|
||||
|
||||
* another expression enclosed in parentheses: `( )`. Parentheses may be used
|
||||
to guarantee associativity of operations.
|
||||
|
||||
* Type casts, specified either by having the type name in parentheses in front
|
||||
of the value to cast (C-style typecasts) or the type name called as a
|
||||
constructor (C++-style type constructors):
|
||||
|
||||
```
|
||||
(vector) P /* cast a point to a vector */
|
||||
(point) f /* cast a float to a point */
|
||||
(color) P /* cast a point to a color! */
|
||||
|
||||
vector (P) /* Means the same thing */
|
||||
point (f)
|
||||
color (P)
|
||||
```
|
||||
|
||||
The three-component types (`color`, `point`, `vector`, `normal`) may be cast
|
||||
to other three-component types. A `float` may be cast to any of the
|
||||
three-component types (by placing the float in all three components) or to a
|
||||
`matrix` (which makes a matrix with all diagonal components being the
|
||||
`float`). Obviously, there are some type casts that are not allowed because
|
||||
they make no sense, like casting a `point` to a `float`, or casting a
|
||||
`string` to a numerical type.
|
||||
|
||||
* function calls
|
||||
|
||||
* assignment expressions:
|
||||
|
||||
same thing as `var = var OP expr` :
|
||||
|
||||
Operator | Meaning
|
||||
:-- | :--
|
||||
*var* `=` *expr* | assign
|
||||
*var* `+=` *expr* | add
|
||||
*var* `-=` *expr* | subtract
|
||||
*var* `*=` *expr* | multiply
|
||||
*var* `/=` *expr* | divide
|
||||
*int-var* `&=` *int-expr* | bitwise and
|
||||
*int-var* `\|=` *int-expr* | bitwise or
|
||||
*int-var* `^=` *int-expr* | bitwise exclusive or
|
||||
*int-var* `<<=` *int-expr* | integer shift left
|
||||
*int-var* `>>=` *int-expr* | integer shift right
|
||||
|
||||
Note that the integer and bit-wise operators are only allowed with `int`
|
||||
variables and expressions. In general, `var OP= expr` is allowed only if
|
||||
`var = var OP expr` is allowed, and means exactly the same thing. Please
|
||||
consult the operator tables for each individual type in Chapter
|
||||
[](#chap-types).
|
||||
|
||||
* ternary operator, just like C:
|
||||
|
||||
> *condition* `?` *expr1* `:` *expr2*
|
||||
|
||||
This expression takes on the value of *expr1* if *condition* is true
|
||||
(nonzero), or *expr2* if *condition* is false (zero).
|
||||
|
||||
|
||||
Please refer to Chapter [](#chap-types), where the section describing each
|
||||
data type describes the full complement of operators that may be used with the
|
||||
type. Operator precedence in OSL is identical to that of C.
|
||||
|
||||
|
||||
## Control flow: `if`, `while`, `do`, `for`
|
||||
|
||||
Conditionals in OSL just like in C or C++:
|
||||
|
||||
\begin{tabbing}
|
||||
\hspace{0.5in} \= \hspace{0.3in} \= \kill
|
||||
\> {\cf if (} *condition* {\cf )} \\
|
||||
\> \> *truestatement*
|
||||
\end{tabbing}
|
||||
|
||||
and
|
||||
|
||||
\begin{tabbing}
|
||||
\hspace{0.5in} \= \hspace{0.3in} \= \kill
|
||||
\> {\cf if (} *condition* {\cf )} \\
|
||||
\> \> *truestatement* \\
|
||||
\> {\cf else} \\
|
||||
\> \> *falsestatement*
|
||||
\end{tabbing}
|
||||
|
||||
The statements can also be entire blocks, surrounded by curly
|
||||
braces. For example,
|
||||
|
||||
```
|
||||
if (s > 0.5) {
|
||||
x = s;
|
||||
y = 1;
|
||||
} else {
|
||||
x = s+t;
|
||||
}
|
||||
```
|
||||
|
||||
The *condition* may be any valid expression, including:
|
||||
|
||||
* The result of any comparison operator (such as `<`, `==`, etc.).
|
||||
* Any numeric expression (`int`, `color`, `point`, `vector`, `normal`,
|
||||
`matrix`), which is considered "true" if nonzero and "false" if zero.
|
||||
* Any string expression, which is considered "true" if it is a nonempty
|
||||
string, "false" if it is the empty string (`""`).
|
||||
* A closure, which is considered "true" if it's empty (not assigned, or
|
||||
initialized with {\cf =0}), and "false" if anything else has been assigned
|
||||
to it.
|
||||
* A logical combination of expressions using the operators `!` (not), `&&`
|
||||
(logical "and"), or `||` (logical "or"). Note that `&&` and `\|\|`
|
||||
*short circuit* as in C, i.e. `A && B` will only evaluate B if A
|
||||
is true, and `A || B` will only evaluate B if A is false.
|
||||
|
||||
Repeated execution of statements for as long as a condition is true is
|
||||
possible with a `while` statement:
|
||||
|
||||
> `while (` *condition* `)` *statements*
|
||||
|
||||
Or the test may happen after the body of the loop, with a `do/while` loop:
|
||||
|
||||
> `do` *statement* `while (` *condition* `)`
|
||||
|
||||
Also, `for` loops are also allowed:
|
||||
|
||||
> `for (` *initialization-statement* `;` *condition* `;` *iteration-statement* `)` \
|
||||
> *body-statements*
|
||||
|
||||
As in C++, a `for` loop's initialization may contain variable declarations and
|
||||
initializations, which are scoped locally to the `for` loop itself. For
|
||||
example,
|
||||
|
||||
```
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
As with `if` statements, loop conditions may be relations or numerical
|
||||
quantities (which are considered "true" if nonzero, "false" if zero), or
|
||||
strings (considered "true" if nonempty, "false" if the empty string `""`.
|
||||
|
||||
Inside the body of a loop, the `break` statement terminates the loop
|
||||
altogether, and the `continue` statement skip to the end of the body and
|
||||
proceeds to the next iteration of the loop.
|
||||
|
||||
## Functions
|
||||
|
||||
### Function definitions
|
||||
|
||||
You may define functions much like in C or C++.
|
||||
|
||||
> *return-type* *function-name* `(` *optional-parameters* `)` \
|
||||
> `{` \
|
||||
> *statements* \
|
||||
> `}`
|
||||
|
||||
Parameters to functions are similar to shader parameters, except that they do
|
||||
not permit initializers. A function call must pass values for all formal
|
||||
parameters. Function parameters in OSL are all *passed by reference*, and are
|
||||
read-only within the body of the function unless they are also designated as
|
||||
`output` (in the same manner as output shader parameters).
|
||||
|
||||
Like for shaders, statements inside functions may be actual executions
|
||||
(assignments, function call, etc.), local variable declarations (visible
|
||||
only from within the body of the function), or local function
|
||||
declarations (callable only from within the body of the function).
|
||||
|
||||
The return type may be any simple data type, a `struct`, or a
|
||||
`closure`. Functions may not return arrays. The return type may be
|
||||
`void`, indicating that the function does not return a value (and
|
||||
should not contain a `return` statement). A `return` statement
|
||||
inside the body of the function will halt execution of the function at
|
||||
that point, and designates the value that will be returned (if not a
|
||||
`void` function).
|
||||
|
||||
Functions may be *overloaded*. That is, multiple functions may be
|
||||
defined to have the same name, as long as they have differently-typed
|
||||
parameters, so that when the function is called the list of arguments can
|
||||
select which version of the function is desired. When there are multiple
|
||||
potential matches, function versions whose argument types match exactly are
|
||||
favored, followed by those that match with type coercion (for example,
|
||||
passing an `int` when the function expects a `float`, or passing a
|
||||
`float` when the function expects a `color`), and finally by trying to
|
||||
match the return value to the type of variable the result is assigned to.
|
||||
|
||||
(sec-syntax-functioncalls)=
|
||||
### Function calls
|
||||
|
||||
Function calls are very similar to C and related programming languages:
|
||||
|
||||
> *functionname* `(` *arg1* `,` ... `,` *argn* `)`
|
||||
|
||||
If the function returns a value (not `void`), you may use its value as an
|
||||
expression. It is fine to completely ignore the value of even a non-`void`
|
||||
function.
|
||||
|
||||
In OSL, all arguments are passed by reference. This generally will not be
|
||||
noticeably different from C-style "pass by value" semantics, except if you
|
||||
pass the same variable as two separate arguments to a function that modifies
|
||||
an argument's value.
|
||||
|
||||
Certain functions allow optional arguments to be passed.
|
||||
Optional arguments are key-value pairs with the key passed as an argument and
|
||||
the associated value passed as the subsequent argument:
|
||||
|
||||
> *functionname* `(` *arg1* `,` ... `,` *argn* `,` *"optionalkey"* `,` *optionalvalue* `,` ... `)`
|
||||
|
||||
|
||||
### Operator overloading
|
||||
|
||||
OSL permits \emph{operator overloading}, which is the practice of providing a
|
||||
function that will be called when you use an operator like `+` or `*`. This is
|
||||
especially handy when you use `struct` to define mathematical types and wish
|
||||
for the usual math operators to work with them. Here is a typical example,
|
||||
which also shows the special naming convention that allows operator
|
||||
overloading:
|
||||
|
||||
```
|
||||
struct vector4 {
|
||||
float x, y, z, w;
|
||||
};
|
||||
|
||||
vector4 __operator__add__ (vector4 a, vector4 b) {
|
||||
return vector4 (a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
|
||||
}
|
||||
|
||||
shader test ()
|
||||
{
|
||||
vector4 a = vector4 (.2, .3, .4, .5);
|
||||
vector4 b = vector4 (1, 2, 3, 4);
|
||||
|
||||
vector4 c = a + b; // Will call __operator__add__(vector4,vector4)
|
||||
printf ("a+b = %g %g %g %g\n", c.x, c.y, c.z, c.w);
|
||||
}
|
||||
```
|
||||
|
||||
The full list of these special function names is as follows (in order of
|
||||
decreasing operator precedence):
|
||||
|
||||
|
||||
Operator | Overload function name | notes
|
||||
:---------- | :----------- | :------
|
||||
`-` | `__operator__neg__` | unary negation
|
||||
`~` | `__operator__compl__` | unary bitwise
|
||||
`!` | `__operator__not__` | unary boolean 'not'
|
||||
`*` | `__operator__mul__` |
|
||||
`/` | `__operator__div__` |
|
||||
`\%` | `__operator__mod__` |
|
||||
`+` | `__operator__add__` |
|
||||
`-` | `__operator__sub__` |
|
||||
`<<` | `__operator__shl__` |
|
||||
`>>` | `__operator__shr__` |
|
||||
`<` | `__operator__lt__` |
|
||||
`<=` | `__operator__le__` |
|
||||
`>` | `__operator__gt__` |
|
||||
`>=` | `__operator__ge__` |
|
||||
`==` | `__operator__eq__` |
|
||||
`!=` | `__operator__ne__` |
|
||||
`\&` | `__operator__bitand__` |
|
||||
`^` | `__operator__xor__` |
|
||||
`\|` | `__operator__bitor__` |
|
||||
|
||||
|
||||
## Global variables
|
||||
|
||||
*Global variables* (sometimes called *graphics state variables*) contain the
|
||||
basic information that the renderer knows about the point being shaded, such
|
||||
as position, surface orientation, and default surface color. You need not
|
||||
declare these variables; they are simply available by default in your shader.
|
||||
Global variables available in shaders are listed in the following table:
|
||||
|
||||
Variable | Description
|
||||
:---------- | :-----------
|
||||
`point P` | Position of the point you are shading. In a displacement shader, changing this variable displaces the surface.
|
||||
`vector I` | The *incident* ray direction, pointing from the viewing position to the shading position `P`.
|
||||
`normal N` | The surface "Shading" "normal of the surface at `P`. Changing `N` yields bump mapping.
|
||||
`normal Ng` | The true surface normal at `P`. This can differ from `N`; `N` can be overridden in various ways including bump mapping and user-provided vertex normals, but `Ng` is always the true surface geometric normal of the surface at `P`.
|
||||
`float u, v` | The 2D parametric coordinates of \P (on the particular geometric primitive you are shading).
|
||||
`vector dPdu, dPdv` | Partial derivatives $\partial P/\partial u$ and $\partial P/\partial v$ tangent to the surface at `P`.
|
||||
`point Ps` | Position at which the light is being queried (currently only used for light attenuation shaders)
|
||||
`float time` | Current shutter time for the point being shaded.
|
||||
`float dtime` | The amount of time covered by this shading sample.
|
||||
`vector dPdtime` | How the surface position \P is moving per unit time
|
||||
`closure color Ci` | Incident radiance --- a closure representing the color of the light leaving the surface from `P` in the direction `-I`.
|
||||
|
||||
|
||||
Accessibility of variables by shader type:
|
||||
|
||||
Variable | surface | displacement | volume
|
||||
:---------- | ----- | -- | --
|
||||
`P` | R | RW | R
|
||||
`I` | R | | R
|
||||
`N` | RW | RW |
|
||||
`Ng` | R | R |
|
||||
`dPdu` | R | R |
|
||||
`dPdv` | R | R |
|
||||
`Ps` | | | R
|
||||
`u, v` | R | R | R
|
||||
`time` | R | R | R
|
||||
`dtime` | R | R | R
|
||||
`dPdtime` | R | R | R
|
||||
`Ci` | RW | | RW
|
||||
|
||||
Reference in New Issue
Block a user