Skip to content

Commit 7f9372f

Browse files
authored
osltoy (#824)
osltoy is a GUI app that lets you interactively edit a pattern shader and adjust its parameters, seeing the updated rendered results in real time. It's the OSL equivalent https://www.shadertoy.com/ The GUI uses Qt5. If that's not on your system (or if you purposely disable it with the build-time option USE_QT=0), osltoy will not be built (but the rest of OSL will). A few other changes that come along with the ride: * The `shade_image` utility function has changed its API slightly: the last (optional) parameter that used to be a simple thread count is now a `parallel_image_options` struct. But this struct can be implicitly constructed from an int (which is, in fact, the thread count), so any source code that calls shade_image should not need to be altered. * New mandelbrot.osl shader has been added. It computes Julia sets, too. Enjoy!
1 parent 897c20d commit 7f9372f

22 files changed

Lines changed: 2900 additions & 29 deletions

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ set (PUGIXML_HOME "" CACHE STRING "Hint about where to find external PugiXML lib
9393
option (USE_FAST_MATH "Use fast math approximations (if no, then use system math library)" ON)
9494
option (OSL_BUILD_PLUGINS "Bool OSL plugins, for example OIIO plugin" ON)
9595
option (USE_BOOST_WAVE "Use Boost Wave for C preprocessor (alternative is to use clang)" OFF)
96+
option (USE_QT "Include Qt support" ON)
9697

9798

9899
# set (USE_OIIO_STATIC ON CACHE BOOL "If OIIO is built static")
@@ -159,6 +160,10 @@ if (OSL_BUILD_PLUGINS)
159160
add_subdirectory (src/osl.imageio)
160161
endif ()
161162

163+
if (USE_QT AND Qt5_FOUND)
164+
add_subdirectory (src/osltoy)
165+
endif ()
166+
162167
add_subdirectory (src/shaders)
163168
add_subdirectory (src/shaders/MaterialX)
164169

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ ifneq (${BOOST_HOME},)
129129
MY_CMAKE_FLAGS += -DBOOST_ROOT:STRING=${BOOST_HOME}
130130
endif
131131

132+
ifneq (${USE_QT},)
133+
MY_CMAKE_FLAGS += -DUSE_QT:BOOL=${USE_QT}
134+
endif
135+
132136
ifneq (${STOP_ON_WARNING},)
133137
MY_CMAKE_FLAGS += -DSTOP_ON_WARNING:BOOL=${STOP_ON_WARNING}
134138
endif
@@ -365,7 +369,8 @@ help:
365369
@echo " BOOST_HOME=path Custom Boost installation"
366370
@echo " OPENEXR_HOME=path Custom OpenEXR installation"
367371
@echo " ILMBASE_HOME=path Custom Ilmbase installation"
368-
@echo " PARTIO_HOME= Use Partio from the given location"
372+
@echo " PARTIO_HOME=path Use Partio from the given location"
373+
@echo " USE_QT=0 Skip anything that needs Qt"
369374
@echo " LLVM-related options:"
370375
@echo " LLVM_VERSION=4.0 Specify which LLVM version to use"
371376
@echo " LLVM_DIRECTORY=xx Specify where LLVM lives"

src/cmake/externalpackages.cmake

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ if (NOT VERBOSE)
1515
set (PugiXML_FIND_QUIETLY TRUE)
1616
set (PythonInterp_FIND_QUIETLY true)
1717
set (PythonLibs_FIND_QUIETLY true)
18+
set (Qt5_FIND_QUIETLY true)
1819
set (Threads_FIND_QUIETLY true)
1920
set (ZLIB_FIND_QUIETLY true)
2021
endif ()
@@ -181,3 +182,29 @@ find_package (PugiXML REQUIRED)
181182
include_directories (BEFORE "${PUGIXML_INCLUDE_DIR}")
182183
# end Pugixml setup
183184
###########################################################################
185+
186+
187+
###########################################################################
188+
# Qt setup
189+
190+
if (USE_QT)
191+
set (qt5_modules Core Gui Widgets)
192+
# if (USE_OPENGL)
193+
# list (APPEND qt5_modules OpenGL)
194+
# endif ()
195+
find_package (Qt5 COMPONENTS ${qt5_modules})
196+
endif ()
197+
if (USE_QT AND Qt5_FOUND)
198+
if (NOT Qt5_FIND_QUIETLY)
199+
message (STATUS "Qt5_FOUND=${Qt5_FOUND}")
200+
endif ()
201+
else ()
202+
message (STATUS "No Qt5 -- skipping components that need Qt5.")
203+
if (USE_QT AND NOT Qt5_FOUND AND APPLE)
204+
message (STATUS "If you think you installed qt5 with Homebrew and it still doesn't work,")
205+
message (STATUS "try: export PATH=/usr/local/opt/qt5/bin:$PATH")
206+
endif ()
207+
endif ()
208+
209+
# end Qt setup
210+
###########################################################################

src/doc/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
set (public_docs osl-languagespec.pdf
22
testshade.md.html
3+
osltoy.md.html
34
markdeep.min.js
45
docs.css
56
)
@@ -16,3 +17,7 @@ install ( FILES "${PROJECT_SOURCE_DIR}/LICENSE"
1617
file (GLOB testshade_figures "Figures/testshade/*.jpg")
1718
install (FILES ${testshade_figures}
1819
DESTINATION ${CMAKE_INSTALL_DOCDIR}/Figures/testshade )
20+
21+
file (GLOB osltoy_figures "Figures/osltoy/*.jpg")
22+
install (FILES ${osltoy_figures}
23+
DESTINATION ${CMAKE_INSTALL_DOCDIR}/Figures/osltoy )
38.5 KB
Loading
90 KB
Loading
108 KB
Loading

src/doc/osltoy.md.html

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
**osltoy**
2+
revision date: 30 Nov 2017
3+
4+
5+
6+
7+
_osltoy_ basics
8+
==================================================
9+
10+
`osltoy` is an interactive editor and realtime visualizer for OSL shaders.
11+
It is inspired by [Shadertoy](https://www.shadertoy.com/) by Inigo Quilez.
12+
But it uses a real VFX shading language!
13+
14+
![osltoy](Figures/osltoy/osltoy-fbm.jpg width="400px")
15+
16+
The basic functionaity of `osltoy` is:
17+
18+
* Allow you to edit OSL shader source code.
19+
* Live and continuous rendering of an "image" that is the result of running
20+
your shader on each pixel of the image (pixel color is taken from the
21+
shader's parameter `output color Cout`.)
22+
23+
24+
## Command line
25+
26+
Launch `osltoy` from the command line:
27+
28+
`osltoy` [*options*]
29+
30+
Additional command line arguments:
31+
32+
`--help`
33+
: Print command line options and other help.
34+
35+
`-v`
36+
: Verbose mode. (Doesn't really do anything currently.)
37+
38+
`--res` *xres* *yres*         
39+
: Specifies the resolution of the render window (default: 512 x 512).
40+
41+
`--threads` *n*
42+
: Specifies the number of simultaneous threads to use for shading. If not
43+
specified, it will use all your hardware cores.
44+
45+
*filename.osl*
46+
: If one or more filenames of shader source code are specified, they will
47+
be loaded into editor tabs upon startup.
48+
49+
50+
## osltoy Basics
51+
52+
First, let's launch `osltoy`:
53+
54+
```
55+
$ osltoy
56+
```
57+
58+
![ ](Figures/osltoy/osltoy-start.jpg width="400px")
59+
This will start up a new `osltoy` session.
60+
On the right half of the GUI is a code editor window. Below the code editor
61+
is an area that will show you any compilation errors. The left half of the
62+
GUI will display the results of the shader (a checkerboard if no shader
63+
has been compiled yet). Below that is an area that will hold widgets to
64+
allow adjustment of shader parameter values.
65+
66+
At the very bottom of the app window is a status bar showing time, frames
67+
per second, and other status messages. At the very top of the app window
68+
(or, on MacOS, at the top of the screen) is a menu bar with the usual set of
69+
common operations.
70+
71+
### Loading and saving shaders
72+
73+
You can load a shader one of three ways:
74+
75+
1. Specify the filename of an existing shader when you launch the app:
76+
```
77+
osltoy test.osl
78+
```
79+
80+
2. From a blank window, load an existing shader by selecting the menu
81+
bar choice `File` --> `Open`, or hitting the hotkey `Ctrl-O` (on MacOS,
82+
⌘`-O`). This will present a file selection dialog.
83+
84+
3. Just start typing in the editor window.
85+
86+
You can save the edited shader with the menu bar `File` --> `Save`
87+
or the hotkey `Ctrl-S` (⌘`-S` on MacOS). If the file does not yet
88+
have a name, you will be presented with a file save dialog (as you will
89+
if you use `File` --> `Save As`).
90+
91+
!!! Note
92+
Every time we talk about a `Ctrl-`*key* combination, if you are on MacOS
93+
(OSX), that hotkey will be ⌘`-`*key*. This document won't awkwardly
94+
repeat this clarification for every command.
95+
96+
### Compiling shaders
97+
98+
When you have loaded or edited your OSL source code, you can compile the
99+
shader with menu `Tools` --> `Recompile shaders`, or by clicking the
100+
`Recompile` button below the source code editor widget, or by using the
101+
hotkey `Ctrl-R`.
102+
103+
!!! Warning
104+
`osltoy` won't compile a buffer that doesn't have a filename ending in
105+
`.osl`, and if you started with a blank window, it won't have a name at
106+
all until you save the first time.
107+
108+
In the compilation status window below the editor, you will either see
109+
an `Ok` message if the compiler succeeded, or the error output from the
110+
compiler, as illustrated here:
111+
112+
![Compilation error display.](Figures/osltoy/osltoy-error.jpg width="512px")
113+
114+
115+
!!! Warning
116+
`osltoy` appears to let you load or create multiple shaders, appearing
117+
in a tabbed editor. We'll get this working eventually (so you can edit
118+
whole shader groups and all the shaders that are in them), but currently
119+
only the shader in the first tab will be compiled and executed, so don't
120+
get confused by the non-functional parts of the interface.
121+
122+
123+
### Executing shaders and interactive changes
124+
125+
Once you compile the shader successfully, it will execute and display the
126+
results of shading a rectangle.
127+
128+
![osltoy has executed the shader](Figures/osltoy/osltoy-fbm.jpg)
129+
130+
As soon as you recompile, the shader will be executed as quickly as possible
131+
and displayed as an image on the left, with shader parameter adjustment
132+
widgets below it.
133+
134+
Evey time you change a parameter value through its widget, the shader will
135+
automatically recompile and re-execute. If you edit the text of the shader,
136+
clicking the `Recompile` button or using the hotkey `Ctrl-R` will recompile
137+
and re-execute the shader.
138+
139+
140+
Rules of the game
141+
==================
142+
143+
## Shader inputs and state
144+
145+
The shader is executed on every pixel of an image (defaulting to a 512x512
146+
square, but you can change the resolution via a command line flag).
147+
148+
The `float u` and `v` global variables vary from 0 to 1 along the rectangle.
149+
150+
The `point P` global variable will be set to `(x,y,0)`, where `x` is the pixel
151+
horizontal coordinate (0 to xres-1 as it goes from left to right) and `y`
152+
is the pixel vertical coordinate (0 to yres-1 as it goes from top to bottom
153+
of the image).
154+
155+
The `float time` global variable contains the time (in seconds) since the
156+
last time the shader was recompiled. Making your shader change its behavior
157+
based on the `time` variable will make an animated shader.
158+
159+
## Shader outputs
160+
161+
The color displayed is taken from the shader output parameter that is
162+
declared like this:
163+
164+
```
165+
output color Cout = 0
166+
```
167+
168+
Whatever you place in that output will be the color displayed at each pixel
169+
of the output image.
170+
171+
!!! Note
172+
Your shader does not need to set `Ci` or deal with closures. The
173+
`osltoy` app is just for exploring pattern generation, not illumination.
174+
It doesn't actually have any notion of 3D geometry or lights.
175+
176+
177+
## Shader execution
178+
179+
If your shader does not reference the `time` variable in any way, it will
180+
only be executed once each time it recompiles. But if `time` appears in your
181+
shader, it will execute repeatedly, as quickly as possible, until you exit
182+
or recompile.
183+
184+
Shader execution will by default use enough threads to keep all your cores
185+
busy. The command line option `--threads` can be used to limit the number
186+
of cores (or to "over-thread").
187+
188+
189+
Caveats, limitations, and broken stuff
190+
========================
191+
192+
These are current limitations or breakages that we will fix over time.
193+
194+
* The GUI seems to let you open multiple editor tabs, but currently, the
195+
only one that will compile and execute is the *first* (farthest to the left
196+
tab that was loaded or saved under a name that ends in `".osl"`.
197+
198+
* We intend to add "Pause" and "Reset" buttons to control time.
199+
200+
* I tried to make the parameter adjustment widgets be clever about how
201+
quickly to modify the values, depending on their range. But I don't have
202+
it quite right. It's still being refined.
203+
204+
* There isn't yet have a way to get the shader itself to get information about
205+
external events such as mouse clicks or key presses, but that would be
206+
fun.
207+
208+
* There isn't yet a way for the shader to have *state* that can be computed,
209+
stored, then re-read when the shader executes on the next frame.
210+
211+
212+
Things to try
213+
=============
214+
215+
* Try this:
216+
217+
` osltoy ` *osl_install_directory*`/shaders/mandelbrot.osl`
218+
219+
* Use the global `time` variable to make animated patterns.
220+
221+
* Explore noise functions and other pattern generation interactively.
222+
223+
* Explore (by keeping an eye on the "FPS" reading at the bottom) what shader
224+
operations are fast and what is slow.
225+
226+
* Don't forget that `texture()` calls work as expected in shadertoy!
227+
228+
* `osltoy` is a great tool for leaning or *teaching* OSL.
229+
230+
* The actual "geometry" is just a rectangle, but like with Shadertoy,
231+
you can make patterns that *look like* by implementing a simple ray tracer
232+
in the shader itself, or using other clever tricks.
233+
234+
* Look at the many examples on [Shadertoy](https://www.shadertoy.com/)
235+
for inspiration!
236+
237+
* Make crazy stuff and post the shaders to the `osl-dev` mail list!
238+
239+
240+
241+
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js?"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>
242+
<link rel="stylesheet" href="docs.css?">
243+

src/include/OSL/oslexec.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737
#include <OpenImageIO/refcnt.h>
3838
#include <OpenImageIO/ustring.h>
3939
#include <OpenImageIO/array_view.h>
40+
#if OPENIMAGEIO_VERSION <= 10902
41+
#include <OpenImageIO/imagebufalgo_util.h>
42+
#endif
4043

4144
OSL_NAMESPACE_ENTER
4245

@@ -623,9 +626,9 @@ class OSLEXECPUBLIC ShadingSystem
623626

624627

625628

626-
#ifdef OPENIMAGEIO_IMAGEBUF_H
629+
#ifdef OPENIMAGEIO_IMAGEBUFALGO_H
627630
// To keep from polluting all OSL clients with ImageBuf & ROI, only expose
628-
// the following declarations if they have included OpenImageIO/imagebuf.h.
631+
// the following declarations if they have included OpenImageIO/imagebufalgo.h.
629632

630633
// enum describing where shades are located for shade_image().
631634
enum ShadeImageLocations {
@@ -658,7 +661,8 @@ bool shade_image (ShadingSystem &shadingsys, ShaderGroup &group,
658661
const ShaderGlobals *defaultsg,
659662
OIIO::ImageBuf &buf, OIIO::array_view<ustring> outputs,
660663
ShadeImageLocations shadelocations = ShadePixelCenters,
661-
OIIO::ROI roi = OIIO::ROI(), int nthreads = 0);
664+
OIIO::ROI roi = OIIO::ROI(),
665+
OIIO::ImageBufAlgo::parallel_image_options popt = 0);
662666

663667
#endif
664668

0 commit comments

Comments
 (0)