├── img
├── 2d.jpg
├── vft.jpg
├── fmx_18.jpg
├── fmx_19.jpg
├── sig_19.jpg
├── volumes.jpg
├── particles.jpg
├── vft_cover.jpg
└── comparison
│ ├── grid_hd.jpg
│ ├── a_fog_9min.jpg
│ ├── a_poly_2min.jpg
│ ├── a_pts_4min.jpg
│ ├── a_sdf_3min.jpg
│ ├── frustum_hd.jpg
│ ├── m_fog_8min.jpg
│ ├── m_pts_11min.jpg
│ ├── m_sdf_16min.jpg
│ ├── rs_fog_1min.jpg
│ ├── rs_pts_4min.jpg
│ ├── a_pts_cam_1min.jpg
│ ├── frustum_hd_25.jpg
│ ├── frustum_hd_5.jpg
│ ├── frustum_hd_75.jpg
│ ├── m_poly_10min.jpg
│ ├── m_pts_cam_8min.jpg
│ ├── rs_poly_1min.jpg
│ ├── a_pts_spec_1min.jpg
│ ├── m_fog_spec_13min.jpg
│ ├── m_pts_spec_3min.jpg
│ ├── rs_pts_cam_2min.jpg
│ ├── a_pts_cam_2spp_1min.jpg
│ ├── a_pts_cam_3spp_1min.jpg
│ ├── a_pts_spec_too_long.jpg
│ ├── a_pts_cam_1_5spp_1min.jpg
│ └── rs_pts_spec_spheres_incorrect.jpg
├── web
├── README.md
├── style.css
├── mandelbrot.html
└── mandelbrot.js
├── blender
├── primitives.blend
├── volume_test.blend
├── stripes_test.blend
├── README.md
└── osl
│ ├── primitive_test.osl
│ └── stripes_test.osl
├── houdini
├── scenes
│ ├── pts.hipnc
│ ├── subd.hipnc
│ ├── osl_scene.hipnc
│ ├── camera_fly.hipnc
│ ├── testing_scene.hipnc
│ ├── rs_resolution_test.hipnc
│ ├── htoa_resolution_test.hipnc
│ ├── testing_scene_mantra_only.hipnc
│ └── run.sh
├── otls
│ ├── vft_points.hdanc
│ ├── vft_benesiIter.hdanc
│ ├── vft_curlNoise.hdanc
│ ├── vft_fog_volume.hdanc
│ ├── vft_ides2Iter.hdanc
│ ├── vft_idesIter.hdanc
│ ├── vft_iqBulbIter.hdanc
│ ├── vft_scaleIter.hdanc
│ ├── vft_sdf_volume.hdanc
│ ├── vft_boxFoldIter.hdanc
│ ├── vft_fabsFoldIter.hdanc
│ ├── vft_preScaleIter.hdanc
│ ├── vft_rotationIter.hdanc
│ ├── vft_addCOffsetIter.hdanc
│ ├── vft_amazingSurfIter.hdanc
│ ├── vft_bristorbrotIter.hdanc
│ ├── vft_compress_colors.hdanc
│ ├── vft_josKleinianIter.hdanc
│ ├── vft_mandelboxIter.hdanc
│ ├── vft_mandelbulb2Iter.hdanc
│ ├── vft_mandelbulb3Iter.hdanc
│ ├── vft_mandelbulb4Iter.hdanc
│ ├── vft_mandelbulbIter.hdanc
│ ├── vft_raymarch_points.hdanc
│ ├── vft_tgladFoldIter.hdanc
│ ├── vft_translateIter.hdanc
│ ├── vft_mengerSmoothIter.hdanc
│ ├── vft_mengerSpongeIter.hdanc
│ ├── vft_quaternion3dIter.hdanc
│ ├── vft_sierpinski3dIter.hdanc
│ ├── vft_xenodreambuieIter.hdanc
│ ├── vft_fog_volume_combined.hdanc
│ ├── vft_mandelbulbPower2Iter.hdanc
│ ├── vft_raymarch_perspective.hdanc
│ ├── vft_generate_points_camera.hdanc
│ ├── vft_generate_points_sphere.hdanc
│ └── vft_fog_volume_combined_frustum.hdanc
├── toolbar
│ └── dev.shelf
├── ocl
│ ├── vft_attractor_kernels.cl
│ ├── include
│ │ ├── vft_defines.h
│ │ ├── vft_utils.h
│ │ ├── vft_shading.h
│ │ ├── vft_math.h
│ │ └── vft_fractals.h
│ └── vft_kernels.cl
├── vex
│ └── include
│ │ ├── vft_particles.h
│ │ ├── vft_fractals.h
│ │ └── vft_subd.h
└── python2.7libs
│ └── vft_hou.py
├── .gitignore
├── nuke
├── scenes
│ └── run.sh
└── blink
│ ├── test_param_var.blink
│ ├── root.blink
│ ├── modulo.blink
│ ├── test_kernel.blink
│ ├── complex_plane.blink
│ ├── include
│ └── vft_blink.h
│ └── mandelbrot.blink
├── osl
├── vft_get_matrix_element.osl
├── vft_primitive.osl
├── vft_mandelbulb.osl
├── vft_ides.osl
├── vft_benesi.osl
└── include
│ ├── vft_osl.h
│ └── vft_fractals_osl.h
├── LICENSE
├── python
└── m3fanalyze.py
├── comparison.md
└── README.md
/img/2d.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/2d.jpg
--------------------------------------------------------------------------------
/img/vft.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/vft.jpg
--------------------------------------------------------------------------------
/img/fmx_18.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/fmx_18.jpg
--------------------------------------------------------------------------------
/img/fmx_19.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/fmx_19.jpg
--------------------------------------------------------------------------------
/img/sig_19.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/sig_19.jpg
--------------------------------------------------------------------------------
/img/volumes.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/volumes.jpg
--------------------------------------------------------------------------------
/img/particles.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/particles.jpg
--------------------------------------------------------------------------------
/img/vft_cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/vft_cover.jpg
--------------------------------------------------------------------------------
/web/README.md:
--------------------------------------------------------------------------------
1 | Work was moved [here](https://github.com/jtomori/web_experiments).
--------------------------------------------------------------------------------
/blender/primitives.blend:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/blender/primitives.blend
--------------------------------------------------------------------------------
/blender/volume_test.blend:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/blender/volume_test.blend
--------------------------------------------------------------------------------
/houdini/scenes/pts.hipnc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/scenes/pts.hipnc
--------------------------------------------------------------------------------
/houdini/scenes/subd.hipnc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/scenes/subd.hipnc
--------------------------------------------------------------------------------
/blender/stripes_test.blend:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/blender/stripes_test.blend
--------------------------------------------------------------------------------
/img/comparison/grid_hd.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/grid_hd.jpg
--------------------------------------------------------------------------------
/houdini/otls/vft_points.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_points.hdanc
--------------------------------------------------------------------------------
/houdini/scenes/osl_scene.hipnc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/scenes/osl_scene.hipnc
--------------------------------------------------------------------------------
/img/comparison/a_fog_9min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/a_fog_9min.jpg
--------------------------------------------------------------------------------
/img/comparison/a_poly_2min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/a_poly_2min.jpg
--------------------------------------------------------------------------------
/img/comparison/a_pts_4min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/a_pts_4min.jpg
--------------------------------------------------------------------------------
/img/comparison/a_sdf_3min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/a_sdf_3min.jpg
--------------------------------------------------------------------------------
/img/comparison/frustum_hd.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/frustum_hd.jpg
--------------------------------------------------------------------------------
/img/comparison/m_fog_8min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/m_fog_8min.jpg
--------------------------------------------------------------------------------
/img/comparison/m_pts_11min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/m_pts_11min.jpg
--------------------------------------------------------------------------------
/img/comparison/m_sdf_16min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/m_sdf_16min.jpg
--------------------------------------------------------------------------------
/img/comparison/rs_fog_1min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/rs_fog_1min.jpg
--------------------------------------------------------------------------------
/img/comparison/rs_pts_4min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/rs_pts_4min.jpg
--------------------------------------------------------------------------------
/houdini/otls/vft_benesiIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_benesiIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_curlNoise.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_curlNoise.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_fog_volume.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_fog_volume.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_ides2Iter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_ides2Iter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_idesIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_idesIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_iqBulbIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_iqBulbIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_scaleIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_scaleIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_sdf_volume.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_sdf_volume.hdanc
--------------------------------------------------------------------------------
/houdini/scenes/camera_fly.hipnc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/scenes/camera_fly.hipnc
--------------------------------------------------------------------------------
/img/comparison/a_pts_cam_1min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/a_pts_cam_1min.jpg
--------------------------------------------------------------------------------
/img/comparison/frustum_hd_25.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/frustum_hd_25.jpg
--------------------------------------------------------------------------------
/img/comparison/frustum_hd_5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/frustum_hd_5.jpg
--------------------------------------------------------------------------------
/img/comparison/frustum_hd_75.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/frustum_hd_75.jpg
--------------------------------------------------------------------------------
/img/comparison/m_poly_10min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/m_poly_10min.jpg
--------------------------------------------------------------------------------
/img/comparison/m_pts_cam_8min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/m_pts_cam_8min.jpg
--------------------------------------------------------------------------------
/img/comparison/rs_poly_1min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/rs_poly_1min.jpg
--------------------------------------------------------------------------------
/houdini/otls/vft_boxFoldIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_boxFoldIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_fabsFoldIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_fabsFoldIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_preScaleIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_preScaleIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_rotationIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_rotationIter.hdanc
--------------------------------------------------------------------------------
/houdini/scenes/testing_scene.hipnc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/scenes/testing_scene.hipnc
--------------------------------------------------------------------------------
/img/comparison/a_pts_spec_1min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/a_pts_spec_1min.jpg
--------------------------------------------------------------------------------
/img/comparison/m_fog_spec_13min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/m_fog_spec_13min.jpg
--------------------------------------------------------------------------------
/img/comparison/m_pts_spec_3min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/m_pts_spec_3min.jpg
--------------------------------------------------------------------------------
/img/comparison/rs_pts_cam_2min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/rs_pts_cam_2min.jpg
--------------------------------------------------------------------------------
/houdini/otls/vft_addCOffsetIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_addCOffsetIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_amazingSurfIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_amazingSurfIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_bristorbrotIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_bristorbrotIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_compress_colors.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_compress_colors.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_josKleinianIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_josKleinianIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_mandelboxIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_mandelboxIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_mandelbulb2Iter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_mandelbulb2Iter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_mandelbulb3Iter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_mandelbulb3Iter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_mandelbulb4Iter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_mandelbulb4Iter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_mandelbulbIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_mandelbulbIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_raymarch_points.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_raymarch_points.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_tgladFoldIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_tgladFoldIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_translateIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_translateIter.hdanc
--------------------------------------------------------------------------------
/img/comparison/a_pts_cam_2spp_1min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/a_pts_cam_2spp_1min.jpg
--------------------------------------------------------------------------------
/img/comparison/a_pts_cam_3spp_1min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/a_pts_cam_3spp_1min.jpg
--------------------------------------------------------------------------------
/img/comparison/a_pts_spec_too_long.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/a_pts_spec_too_long.jpg
--------------------------------------------------------------------------------
/houdini/otls/vft_mengerSmoothIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_mengerSmoothIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_mengerSpongeIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_mengerSpongeIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_quaternion3dIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_quaternion3dIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_sierpinski3dIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_sierpinski3dIter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_xenodreambuieIter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_xenodreambuieIter.hdanc
--------------------------------------------------------------------------------
/houdini/scenes/rs_resolution_test.hipnc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/scenes/rs_resolution_test.hipnc
--------------------------------------------------------------------------------
/img/comparison/a_pts_cam_1_5spp_1min.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/a_pts_cam_1_5spp_1min.jpg
--------------------------------------------------------------------------------
/houdini/otls/vft_fog_volume_combined.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_fog_volume_combined.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_mandelbulbPower2Iter.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_mandelbulbPower2Iter.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_raymarch_perspective.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_raymarch_perspective.hdanc
--------------------------------------------------------------------------------
/houdini/scenes/htoa_resolution_test.hipnc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/scenes/htoa_resolution_test.hipnc
--------------------------------------------------------------------------------
/houdini/otls/vft_generate_points_camera.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_generate_points_camera.hdanc
--------------------------------------------------------------------------------
/houdini/otls/vft_generate_points_sphere.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_generate_points_sphere.hdanc
--------------------------------------------------------------------------------
/houdini/scenes/testing_scene_mantra_only.hipnc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/scenes/testing_scene_mantra_only.hipnc
--------------------------------------------------------------------------------
/img/comparison/rs_pts_spec_spheres_incorrect.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/img/comparison/rs_pts_spec_spheres_incorrect.jpg
--------------------------------------------------------------------------------
/houdini/otls/vft_fog_volume_combined_frustum.hdanc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtomori/vft/HEAD/houdini/otls/vft_fog_volume_combined_frustum.hdanc
--------------------------------------------------------------------------------
/web/style.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | margin: 0;
3 | }
4 |
5 | canvas {
6 | width: 100vw;
7 | height: 100vh;
8 | display: block;
9 | }
--------------------------------------------------------------------------------
/blender/README.md:
--------------------------------------------------------------------------------
1 | Blender integration is being developed in [blender](/../../tree/blender) branch, because it requires some changes in OSL shaders, which were initially created for Arnold.
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | *.pyc
3 | backup
4 | bak
5 | presets
6 | geo
7 | *.autosave
8 | *.nk~
9 | node_modules
10 | npm-debug.log
11 | *.oso
12 | /houdini/scenes/caches
13 | *.blend?
--------------------------------------------------------------------------------
/web/mandelbrot.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | VFT | Mandelbrot
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/nuke/scenes/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # usage
4 |
5 | # find location of this script and move to blink dir
6 | ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd ../blink && pwd )"
7 |
8 | # set needed paths
9 | export BLINK_PATH="${ROOT_DIR}"
10 | export FN_BLINK_INCLUDE_PATHS="${ROOT_DIR}"
11 |
12 | # run the scene, expects an "nuke_launcher" environment variable pointing to binary of Nuke (e.g. /usr/local/Nuke11.1v4/Nuke11.1)
13 | ${nuke_launcher} test_scene.nk
14 |
--------------------------------------------------------------------------------
/houdini/toolbar/dev.shelf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/osl/vft_get_matrix_element.osl:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | shader vft_get_matrix_element(
13 | matrix mat = 1,
14 | int row = 0,
15 | int column = 0,
16 |
17 | output float element_out = 0.0
18 | )
19 | {
20 | element_out = mat[row][column];
21 | }
--------------------------------------------------------------------------------
/houdini/scenes/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # usage
4 | printf "Usage:./run.sh scene_file.hip (-cpu)\n -cpu: optional argument to run OpenCL code on a CPU device (default: GPU)\n\n\n"
5 |
6 | # find location of this script
7 | ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd ../.. && pwd )"
8 |
9 | # include this project in HOUDINI_PATH
10 | export HOUDINI_PATH="${ROOT_DIR}/houdini:${HOUDINI_PATH}"
11 |
12 | # setup OSL
13 | export ARNOLD_PLUGIN_PATH="${ARNOLD_PLUGIN_PATH}:${ROOT_DIR}/osl:${ROOT_DIR}/houdini/ocl/include"
14 | export OSL_OPTIONS="range_checking=1,max_warnings_per_thread=100,compile_report=1" # debug_nan=1,debug_uninit=1
15 |
16 | # use a cpu mode
17 | if [[ $2 == "-cpu" ]]
18 | then
19 | export HOUDINI_OCL_DEVICETYPE="CPU"
20 | printf "CPU mode set\n"
21 | fi
22 |
23 | # run the scene
24 | houdini $1 -foreground
--------------------------------------------------------------------------------
/nuke/blink/test_param_var.blink:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #include "include/vft_blink.h"
13 |
14 | /*
15 | First testing kernel, just to try out things
16 | */
17 |
18 | kernel testParamVar : ImageComputationKernel
19 | {
20 | Image dst;
21 |
22 | param:
23 | float4 color;
24 |
25 | void define() {
26 | defineParam(color, "Color", float4(1.0f));
27 | }
28 |
29 | void init() {
30 | }
31 |
32 | void process()
33 | {
34 | color *= 0.99f;
35 |
36 | dst() = color;
37 | }
38 | };
--------------------------------------------------------------------------------
/nuke/blink/root.blink:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #include "include/vft_blink.h"
13 |
14 | /*
15 | Root input image
16 | */
17 |
18 | kernel rootKernel : ImageComputationKernel
19 | {
20 | Image src;
21 | Image dst;
22 |
23 | param:
24 | float root;
25 |
26 | void define() {
27 | defineParam(root, "root", 2.0f);
28 | }
29 |
30 | void init() {
31 |
32 | }
33 |
34 | void process()
35 | {
36 | float4 img_src = float4(src(0), src(1), src(2), src(3));
37 | dst() = pow(img_src, float4(1.0f/root));
38 | }
39 | };
--------------------------------------------------------------------------------
/houdini/ocl/vft_attractor_kernels.cl:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | kernel void lorenzAttractor(
13 | int P_length,
14 | global float* P,
15 | int k_length,
16 | global int* k_index,
17 | global float* k
18 | )
19 | {
20 | int idx = get_global_id(0);
21 | if (idx >= P_length)
22 | return;
23 |
24 | float3 p = vload3(idx, P);
25 | float a = k[0];
26 | float b = k[1];
27 | float c = k[2];
28 | float dt = 0.0005;
29 |
30 | float3 d;
31 | d.x = a * (p.y - p.x);
32 | d.y = p.x * (b - p.z) - p.y;
33 | d.z = p.x * p.y - c * p.z;
34 |
35 | p += d * dt;
36 | vstore3(p, idx, P);
37 | }
38 |
--------------------------------------------------------------------------------
/nuke/blink/modulo.blink:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #include "include/vft_blink.h"
13 |
14 | /*
15 | Modulo input image
16 | */
17 |
18 | kernel moduloKernel : ImageComputationKernel
19 | {
20 | Image src;
21 | Image dst;
22 |
23 | param:
24 | float4 modulo;
25 |
26 | void define() {
27 | defineParam(modulo, "modulo", float4(1.0f, 1.0f, 1.0f, 1.0f));
28 | }
29 |
30 | void init() {
31 |
32 | }
33 |
34 | void process()
35 | {
36 | dst() = float4(fmod(src(0), modulo.x), fmod(src(1), modulo.y), fmod(src(2), modulo.z), fmod(src(3), modulo.w));
37 | }
38 | };
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/houdini/ocl/include/vft_defines.h:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #ifndef VFT_DEFINES
13 | #define VFT_DEFINES
14 |
15 | // constants
16 |
17 | #define NULL 0
18 |
19 | #define LARGE_NUMBER 10e10
20 | #define ORBITS_OFFSET 0.006f // is used to hide colored seams in sdf subtracting
21 |
22 | #define ORBITS_ARRAY_LENGTH 9
23 | #define ENABLE_DELTA_DE 0
24 |
25 | // functions
26 |
27 | #define SIN(x) native_sin(x)
28 | #define COS(x) native_cos(x)
29 | #define TAN(x) native_tan(x)
30 | #define POWR(x, y) native_powr((x), (y))
31 | #define SQRT(x) native_sqrt(x)
32 | #define LOG(x) native_log(x)
33 | #define EXP(x) native_exp(x)
34 | #define DIV(x, y) native_divide((x), (y))
35 | #define NORMALIZE(x) fast_normalize(x)
36 | #define LENGTH(x) fast_length(x)
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/blender/osl/primitive_test.osl:
--------------------------------------------------------------------------------
1 | // sphere: position, radius
2 | float sphere( vector P, float rad )
3 | {
4 | float dist = length(P) - rad;
5 | return dist;
6 | }
7 |
8 | shader vft_mandelbulb(
9 | int primitive = 0 [[ string widget = "popup", string options = "Sphere|Box|Rounded Box|Torus|Cone" ]],
10 | float sphere_size = 1.0,
11 | vector box_size_vec = vector(1, 2, 3),
12 | float box_roundness = 1.0,
13 | float torus_radius = 1.0,
14 | float torus_thickness = 1.0,
15 | float cone_radius_x = 1.0,
16 | float cone_radius_y = 1.0,
17 |
18 | output float dist = 0.0
19 | )
20 | {
21 | vector Z = P;
22 |
23 | if (primitive == 0)
24 | dist = sphere(Z, sphere_size);
25 | // else if (primitive == 1)
26 | // dist = box(Z, float3(box_size_vec[0], box_size_vec[1], box_size_vec[2]));
27 | // else if (primitive == 2)
28 | // dist = roundBox(Z, float3(box_size_vec[0], box_size_vec[1], box_size_vec[2]), box_roundness);
29 | // else if (primitive == 3)
30 | // dist = torus(Z, float2(torus_radius, torus_thickness));
31 | // else if (primitive == 4)
32 | // dist = cone(Z, float2(cone_radius_x, cone_radius_y));
33 |
34 | dist = dist < 1.0 ? 1.0 : 0.0;
35 | }
--------------------------------------------------------------------------------
/nuke/blink/test_kernel.blink:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #include "include/vft_blink.h"
13 |
14 | /*
15 | First testing kernel, just to try out things
16 | */
17 |
18 | kernel testKernel : ImageComputationKernel
19 | {
20 | Image dst;
21 |
22 | param:
23 | float2 center;
24 | float radius;
25 | float falloff;
26 |
27 | void define() {
28 | defineParam(center, "Center", float2(960.0f, 540.0f));
29 | defineParam(radius, "Radius (px)", 200.0f);
30 | defineParam(falloff, "Falloff", 1.0f);
31 | }
32 |
33 | void init() {
34 |
35 | }
36 |
37 | void process(int2 pos)
38 | {
39 | float dist = length( float2(pos.x, pos.y) - center );
40 | //dist = sqrt( dot(float2(pos.x, pos.y) - center, float2(pos.x, pos.y) - center) );
41 | dist = fit(dist, 0.0f, radius, 1.0f, 0.0f);
42 | dist = pow(dist, falloff);
43 |
44 | dst() = float4(dist, dist, dist, 1);
45 | }
46 | };
--------------------------------------------------------------------------------
/nuke/blink/complex_plane.blink:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #include "include/vft_blink.h"
13 |
14 | /*
15 | Generates a complex plane which has positions of X and Y axes in R and G channels,
16 | it is meant to be used with fractal kernels, which use complex plane image as an input
17 | */
18 |
19 | kernel complexPlane : ImageComputationKernel
20 | {
21 | Image dst;
22 |
23 | param:
24 | int2 img_res;
25 | float zoom;
26 | float exp_zoom;
27 | float2 offset;
28 |
29 | void define() {
30 | defineParam(img_res, "resolution", int2(1920, 1080));
31 | defineParam(zoom, "initial_zoom", 1.0f);
32 | defineParam(exp_zoom, "exponential_zoom", 0.0f);
33 | defineParam(offset, "offset", float2(0.0f, 0.0f));
34 | }
35 |
36 | void init() {
37 | }
38 |
39 | void process(int2 pos)
40 | {
41 | float2 c = float2(pos.x, pos.y) - float2(img_res.x, img_res.y)/2;
42 | c = zoomComplexPlane(c, zoom, exp_zoom, offset);
43 |
44 | dst() = float4(c.x, c.y, 0, 0);
45 | }
46 | };
--------------------------------------------------------------------------------
/osl/vft_primitive.osl:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #include "include/vft_osl.h"
13 | #include "include/vft_fractals_osl.h"
14 |
15 | shader vft_mandelbulb(
16 | int primitive = 0 [[ string widget = "popup", string options = "Sphere|Box|Rounded Box|Torus|Cone" ]],
17 | float sphere_size = 1.0,
18 | vector box_size_vec = vector(1, 2, 3),
19 | float box_roundness = 1.0,
20 | float torus_radius = 1.0,
21 | float torus_thickness = 1.0,
22 | float cone_radius_x = 1.0,
23 | float cone_radius_y = 1.0,
24 |
25 | output float dist = 0.0
26 | )
27 | {
28 | float3 Z = float3(P[0], P[1], P[2]);
29 |
30 | if (primitive == 0)
31 | dist = sphere(Z, sphere_size);
32 | else if (primitive == 1)
33 | dist = box(Z, float3(box_size_vec[0], box_size_vec[1], box_size_vec[2]));
34 | else if (primitive == 2)
35 | dist = roundBox(Z, float3(box_size_vec[0], box_size_vec[1], box_size_vec[2]), box_roundness);
36 | else if (primitive == 3)
37 | dist = torus(Z, float2(torus_radius, torus_thickness));
38 | else if (primitive == 4)
39 | dist = cone(Z, float2(cone_radius_x, cone_radius_y));
40 | }
--------------------------------------------------------------------------------
/houdini/vex/include/vft_particles.h:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #ifndef VFT_PARTICLES
13 | #define VFT_PARTICLES
14 |
15 | function vector transform_right(vector vx; int i) {
16 | int i_mod = i % 3;
17 |
18 | if (i_mod == 0) return vx;
19 | if (i_mod == 1) return set(vx.z,vx.x,vx.y);
20 | if (i_mod == 2) return set(vx.y,vx.z,vx.x);
21 | else return vx;
22 | }
23 |
24 | function vector transform_left(vector vx; int i) {
25 | int i_mod = i % 3;
26 |
27 | if (i_mod == 0) return vx;
28 | if (i_mod == 1) return set(vx.y,vx.z,vx.x);
29 | if (i_mod == 2) return set(vx.z,vx.x,vx.y);
30 | else return vx;
31 | }
32 |
33 | function vector transform_full(vector vx; int i) {
34 | int i_mod = i % 6;
35 |
36 | if (i_mod == 0) return vx;
37 | if (i_mod == 1) return set(vx.y,vx.z,vx.x);
38 | if (i_mod == 2) return set(vx.z,vx.x,vx.y);
39 | if (i_mod == 3) return set(vx.x,vx.z,vx.y);
40 | if (i_mod == 4) return set(vx.z,vx.y,vx.x);
41 | if (i_mod == 5) return set(vx.y,vx.x,vx.z);
42 |
43 | else return vx;
44 | }
45 |
46 | function vector transform_straight(vector vx; int i) {
47 | return vx;
48 | }
49 |
50 | #endif
51 |
--------------------------------------------------------------------------------
/houdini/vex/include/vft_fractals.h:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #ifndef VFT_FRACTALS
13 | #define VFT_FRACTALS
14 |
15 | struct computeFogParms
16 | {
17 | vector pos = {0.0, 0.0, 0.0};
18 | int max_iter = 20;
19 | float max_dist = 2;
20 | float power = 8;
21 | float orbit_volume_scale = 1.0;
22 | vector orbit_volume_offset = {0.0, 0.0, 0.0};
23 | }
24 |
25 | function float computeFog(computeFogParms parms; vector colors)
26 | {
27 | vector z = parms.pos;
28 | int i = 0;
29 |
30 | float dr = 1.0;
31 | float r = 0.0;
32 | float orbit_volume = 10000000000000000000;
33 |
34 | for (; i < parms.max_iter; i++) {
35 | // convert to polar coordinates
36 | float theta = acos(z.z/r);
37 | float phi = atan(z.y, z.x);
38 | dr = pow(r, parms.power-1.0) * parms.power * dr + 1.0;
39 |
40 | // scale and rotate the point
41 | float zr = pow(r, parms.power);
42 | theta = theta * parms.power;
43 | phi = phi * parms.power;
44 |
45 | // convert back to cartesian coordinates
46 | z = zr * set(sin(theta)*cos(phi), sin(phi)*sin(theta), cos(theta));
47 | z += parms.pos;
48 |
49 | // check for exit
50 | r = length(z);
51 | orbit_volume = min(orbit_volume, volumesample(1, 0, (z + parms.orbit_volume_offset) * parms.orbit_volume_scale));
52 |
53 | if (r > parms.max_dist)
54 | break;
55 | }
56 |
57 | colors.x = orbit_volume;
58 | return i == parms.max_iter ? 1.0 : 0.0;
59 | }
60 |
61 | #endif
62 |
--------------------------------------------------------------------------------
/python/m3fanalyze.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | -----------------------------------------------------------------------------
5 | This source file has been developed within the scope of the
6 | Technical Director course at Filmakademie Baden-Wuerttemberg.
7 | http://technicaldirector.de
8 |
9 | Written by Juraj Tomori.
10 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
11 | -----------------------------------------------------------------------------
12 | """
13 |
14 | import os
15 | import fnmatch
16 |
17 | def countInstructions(filePath):
18 | with open(filePath) as file:
19 | lines = file.readlines()
20 | lines = [n.replace(" ","") for n in lines] # kill spaces for finding exact line
21 |
22 | # find start and ending lines of code section
23 | start = lines.index("[CODE]\n")
24 | end = lines.index("[END]\n")
25 | length = end-start-1
26 |
27 | # create a list with lines containing instructions
28 | code = []
29 |
30 | for i in range(length):
31 | code.append( lines[start + i + 1].replace("\n", "") )
32 |
33 | # concat the list and divide by 2 (hexadecimal instrcutions)
34 | return len( "".join(code) )/2
35 |
36 | # path to the formulas folder
37 | path = "/home/jtomori/Downloads/mb3d-master/M3Formulas"
38 |
39 | # find files only
40 | files = [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]
41 |
42 | # keep only .m3f files, but not JIT
43 | files = fnmatch.filter(files, "*.m3f")
44 | files = [n for n in files if not fnmatch.fnmatch(n.lower(), "*jit*")]
45 |
46 | # a list containing amount of instructions per file
47 | instructions = []
48 |
49 | for file in files:
50 | instructions.append( countInstructions( os.path.join(path, file) ) )
51 |
52 | # generate an index list
53 | sortedIndices = sorted(range(len(instructions)), key=lambda k: instructions[k])
54 |
55 | # print from longest to shortest code formulas
56 | for index in sortedIndices[::-1]:
57 | print files[index] + " (" + str(instructions[index]) + " instructions)"
--------------------------------------------------------------------------------
/nuke/blink/include/vft_blink.h:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #ifndef VFT_BLINK_FUNCS
13 | #define VFT_BLINK_FUNCS
14 |
15 | // constants
16 | #define LARGE_NUMBER 10e10
17 |
18 |
19 | // functions
20 | static float fit(float value, float src_min, float src_max, float dst_min, float dst_max) {
21 | return dst_min + (dst_max - dst_min) * (value - src_min) / (src_max - src_min);
22 | }
23 |
24 | static float distPtLine(float2 pt, float2 line_pt_1, float2 line_pt_2)
25 | {
26 | float numerator = fabs( pt.x*( line_pt_2.y - line_pt_1.y ) - pt.y*( line_pt_2.x - line_pt_1.x ) + line_pt_2.x*line_pt_1.y - line_pt_2.y * line_pt_1.x );
27 | float denominator = sqrt( pow( line_pt_2.y - line_pt_1.y , 2.0f) + pow( line_pt_2.x - line_pt_1.x , 2.0f) );
28 | return numerator / denominator;
29 | }
30 |
31 | static float distPtCircle(float2 pt, float2 center, float radius)
32 | {
33 | return length(pt - center) - radius;
34 | }
35 |
36 | static float2 zoomComplexPlane(float2 pos, float zoom, float exp_zoom, float2 offset)
37 | {
38 | pos /= zoom;
39 | pos /= exp(exp_zoom);
40 | pos += offset;
41 |
42 | return pos;
43 | }
44 |
45 | // complex number functions
46 | typedef float2 complex;
47 |
48 | static complex complex_add(complex a, complex b)
49 | {
50 | return complex(a.x + b.x, a.y + b.y);
51 | }
52 |
53 | static complex complex_mult(complex a, complex b)
54 | {
55 | return complex(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
56 | }
57 |
58 | static float complex_abs(complex a)
59 | {
60 | return dot(float2(a), float2(a));
61 | }
62 |
63 | static complex complex_pow(complex a, int n)
64 | {
65 | complex result = a;
66 |
67 | for (int i = 0; i < (n-1); i++)
68 | {
69 | result = complex_mult(result, a);
70 | }
71 |
72 | return result;
73 | }
74 |
75 | #endif
76 |
--------------------------------------------------------------------------------
/osl/vft_mandelbulb.osl:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #include "include/vft_osl.h"
13 | #include "include/vft_fractals_osl.h"
14 |
15 | shader vft_mandelbulb(
16 | float power = 8.0,
17 | int julia_enable = 0 [[ string widget = "boolean" ]],
18 | vector julia_coord = vector(0, 0, 0),
19 | int max_iterations = 100,
20 | float max_distance = 250.0,
21 |
22 | output matrix out = 0
23 | )
24 | {
25 | point P_w = P;
26 | point P_o = transform("object", P_w);
27 |
28 | point P_in = P_o;
29 | point Z = P_in;
30 | float4 julia = float4( julia_enable, julia_coord[0], julia_coord[1], julia_coord[2] );
31 | int i = 0;
32 | float z_dist = LENGTH(Z);
33 |
34 | float orbit_coord_dist = LARGE_NUMBER;
35 | float orbit_sphere_dist = LARGE_NUMBER;
36 | point orbit_plane_origin = point(0.0);
37 | vector orbit_plane_dist = vector(LARGE_NUMBER);
38 |
39 | for (; i < max_iterations; i++)
40 | {
41 | z_dist = LENGTH(Z);
42 | if (z_dist > max_distance) break;
43 |
44 | //mandelbulbIter(Z, P_in, 1.0, julia, power);
45 | //mandelboxIter(Z, P_in, 0.1, julia, -1.5);
46 | //mandelbulbPower2Iter(Z, P_in, 1.0, julia);
47 | //bristorbrotIter(Z, P_in, 1.0, julia);
48 | //xenodreambuieIter(Z, P_in, 1.0, julia, power, 0.0, 0.0);
49 | //benesiIter(Z, P_in, 1.0, julia);
50 | //idesIter(Z, P_in, 1.0, julia, point(1.0, 2.0, 1.0), float2(0.5, 0.5));
51 | iqBulbIter(Z, P_in, 1.0, julia, power, power+2.0);
52 |
53 | // orbit traps
54 | orbit_coord_dist = min(orbit_coord_dist, fabs( length2(Z - P_in) ));
55 | orbit_sphere_dist = min( orbit_sphere_dist, fabs( length2(Z - point(0)) - 2.0) );
56 | orbit_plane_dist[0] = min( orbit_plane_dist[0], distPointPlane(Z, vector(1.0, 0.0, 0.0), orbit_plane_origin) );
57 | orbit_plane_dist[1] = min( orbit_plane_dist[1], distPointPlane(Z, vector(0.0, 1.0, 0.0), orbit_plane_origin) );
58 | orbit_plane_dist[2] = min( orbit_plane_dist[2], distPointPlane(Z, vector(0.0, 0.0, 1.0), orbit_plane_origin) );
59 | }
60 |
61 | orbit_coord_dist = sqrt(orbit_coord_dist);
62 | orbit_sphere_dist = sqrt(orbit_sphere_dist);
63 |
64 | float mask = i == max_iterations ? 1 : 0;
65 |
66 | out[0][0] = mask;
67 | out[0][1] = orbit_coord_dist;
68 | out[0][2] = orbit_sphere_dist;
69 | out[0][3] = orbit_plane_dist[0];
70 | out[1][0] = orbit_plane_dist[1];
71 | out[1][1] = orbit_plane_dist[2];
72 | }
--------------------------------------------------------------------------------
/osl/vft_ides.osl:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #include "include/vft_osl.h"
13 | #include "include/vft_fractals_osl.h"
14 |
15 | shader vft_mandelbulb(
16 | float power = 8.0,
17 | int julia_enable = 0 [[ string widget = "boolean" ]],
18 | vector julia_coord = vector(0, 0, 0),
19 | vector multiplier = vector(1, 2, 1),
20 | vector sub_multiplier = vector(0.5, 0.5, -99999),
21 | int max_iterations = 100,
22 | float max_distance = 250.0,
23 |
24 | output matrix out = 0
25 | )
26 | {
27 | point P_w = P;
28 | point P_o = transform("object", P_w);
29 |
30 | point P_in = P_o;
31 | point Z = P_in;
32 | float4 julia = float4( julia_enable, julia_coord[0], julia_coord[1], julia_coord[2] );
33 | int i = 0;
34 | float z_dist = LENGTH(Z);
35 |
36 | float orbit_coord_dist = LARGE_NUMBER;
37 | float orbit_sphere_dist = LARGE_NUMBER;
38 | point orbit_plane_origin = point(0.0);
39 | vector orbit_plane_dist = vector(LARGE_NUMBER);
40 |
41 | for (; i < max_iterations; i++)
42 | {
43 | z_dist = LENGTH(Z);
44 | if (z_dist > max_distance) break;
45 |
46 | //mandelbulbIter(Z, P_in, 1.0, julia, power);
47 | //mandelboxIter(Z, P_in, 0.1, julia, -1.5);
48 | //mandelbulbPower2Iter(Z, P_in, 1.0, julia);
49 | //bristorbrotIter(Z, P_in, 1.0, julia);
50 | //xenodreambuieIter(Z, P_in, 1.0, julia, power, 0.0, 0.0);
51 | //benesiIter(Z, P_in, 1.0, julia);
52 | idesIter(Z, P_in, 1.0, julia, multiplier, float2(sub_multiplier[0], sub_multiplier[1]));
53 | //iqBulbIter(Z, P_in, 1.0, julia, power, power);
54 |
55 | // orbit traps
56 | orbit_coord_dist = min(orbit_coord_dist, fabs( length2(Z - P_in) ));
57 | orbit_sphere_dist = min( orbit_sphere_dist, fabs( length2(Z - point(0)) - 2.0) );
58 | orbit_plane_dist[0] = min( orbit_plane_dist[0], distPointPlane(Z, vector(1.0, 0.0, 0.0), orbit_plane_origin) );
59 | orbit_plane_dist[1] = min( orbit_plane_dist[1], distPointPlane(Z, vector(0.0, 1.0, 0.0), orbit_plane_origin) );
60 | orbit_plane_dist[2] = min( orbit_plane_dist[2], distPointPlane(Z, vector(0.0, 0.0, 1.0), orbit_plane_origin) );
61 | }
62 |
63 | orbit_coord_dist = sqrt(orbit_coord_dist);
64 | orbit_sphere_dist = sqrt(orbit_sphere_dist);
65 |
66 | float mask = i == max_iterations ? 1 : 0;
67 |
68 | out[0][0] = mask;
69 | out[0][1] = orbit_coord_dist;
70 | out[0][2] = orbit_sphere_dist;
71 | out[0][3] = orbit_plane_dist[0];
72 | out[1][0] = orbit_plane_dist[1];
73 | out[1][1] = orbit_plane_dist[2];
74 | }
--------------------------------------------------------------------------------
/osl/vft_benesi.osl:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #include "include/vft_osl.h"
13 | #include "include/vft_fractals_osl.h"
14 |
15 | shader vft_mandelbulb(
16 | vector translate = vector(0, 0, 0),
17 | vector euluer_rotate = vector(0, 0, 0),
18 | int julia_enable = 0 [[ string widget = "boolean" ]],
19 | vector julia_coord = vector(0, 0, 0),
20 | int max_iterations = 100,
21 | float max_distance = 250.0,
22 |
23 | output matrix out = 0
24 | )
25 | {
26 | point P_w = P;
27 | point P_o = transform("object", P_w);
28 |
29 | point P_in = P_o;
30 | point Z = P_in;
31 | float4 julia = float4( julia_enable, julia_coord[0], julia_coord[1], julia_coord[2] );
32 | int i = 0;
33 | float z_dist = LENGTH(Z);
34 |
35 | float orbit_coord_dist = LARGE_NUMBER;
36 | float orbit_sphere_dist = LARGE_NUMBER;
37 | point orbit_plane_origin = point(0.0);
38 | vector orbit_plane_dist = vector(LARGE_NUMBER);
39 |
40 | for (; i < max_iterations; i++)
41 | {
42 | z_dist = LENGTH(Z);
43 | if (z_dist > max_distance) break;
44 |
45 | //mandelbulbIter(Z, P_in, 1.0, julia, power);
46 | //mandelboxIter(Z, P_in, 0.1, julia, -1.5);
47 | //mandelbulbPower2Iter(Z, P_in, 1.0, julia);
48 | //bristorbrotIter(Z, P_in, 1.0, julia);
49 | //xenodreambuieIter(Z, P_in, 1.0, julia, power, 0.0, 0.0);
50 | benesiIter(Z, P_in, 1.0, julia);
51 | Z += translate;
52 | Z = transform(euler_rotation(euluer_rotate), Z);
53 | //idesIter(Z, P_in, 1.0, julia, point(1.0, 2.0, 1.0), float2(0.5, 0.5));
54 | //iqBulbIter(Z, P_in, 1.0, julia, power, power+2.0);
55 |
56 | // orbit traps
57 | orbit_coord_dist = min(orbit_coord_dist, fabs( length2(Z - P_in) ));
58 | orbit_sphere_dist = min( orbit_sphere_dist, fabs( length2(Z - point(0)) - 2.0) );
59 | orbit_plane_dist[0] = min( orbit_plane_dist[0], distPointPlane(Z, vector(1.0, 0.0, 0.0), orbit_plane_origin) );
60 | orbit_plane_dist[1] = min( orbit_plane_dist[1], distPointPlane(Z, vector(0.0, 1.0, 0.0), orbit_plane_origin) );
61 | orbit_plane_dist[2] = min( orbit_plane_dist[2], distPointPlane(Z, vector(0.0, 0.0, 1.0), orbit_plane_origin) );
62 | }
63 |
64 | orbit_coord_dist = sqrt(orbit_coord_dist);
65 | orbit_sphere_dist = sqrt(orbit_sphere_dist);
66 |
67 | float mask = i == max_iterations ? 1 : 0;
68 |
69 | out[0][0] = mask;
70 | out[0][1] = orbit_coord_dist;
71 | out[0][2] = orbit_sphere_dist;
72 | out[0][3] = orbit_plane_dist[0];
73 | out[1][0] = orbit_plane_dist[1];
74 | out[1][1] = orbit_plane_dist[2];
75 | }
--------------------------------------------------------------------------------
/blender/osl/stripes_test.osl:
--------------------------------------------------------------------------------
1 | // a cell noise function that takes two parameters
2 | float cnoise(float a, float b){
3 | return noise("cell",vector(a,b,0));
4 | }
5 |
6 | // return the relative position of a value in a slot given the upper
7 | // boundary an the slot number.
8 | // m : the upper boundary
9 | // i : the slot number
10 | // n : the number of slots
11 | // value: the value
12 | // offset: the offset of the lower boundary of the slot with index 0
13 | // width: the width of each slot
14 | // varw: the variance of the width
15 | // seed: a random seed
16 |
17 | float relvalue(float m, float i, float n, float value,
18 | float offset, float width, float varw, float seed){
19 |
20 | float mp=0;
21 | float ri = i; // parameters are passed by reference so if we alter them it has effect outside
22 | float val = value;
23 | float last = m;
24 | ri -= 1;
25 | if( ri < 0 ){
26 | ri = n - 1;
27 | last += 1;
28 | val += 1;
29 | }
30 | mp = offset + ri * width + (cnoise(ri,seed)-0.5)*varw;
31 | return (val - mp)/(last - mp);
32 | }
33 |
34 | // return the slot that a value belongs to and its
35 | // relative position within the slot
36 | // value : a value between [0,1]
37 | // n : the number of slots
38 | // var : the variance of the position of the slot boundaries
39 | // seed : a random seed, allows you to pick a pattern
40 | // rel : will recive the relative position of the value within
41 | // a slot
42 |
43 | float slot(float value, float n, float var, float seed,
44 | output float rel){
45 |
46 | float dw = 1.0/n;
47 | float dw2 = dw/2;
48 | float varw = dw * var;
49 | float i;
50 |
51 | float m,mn;
52 |
53 | for(i=0; i
8 |
9 | Mantra ~ 10 min, Arnold ~ 2 min, Redshift ~ 1 min
10 |
11 |
12 |
13 | ### B) Points (sphere trace), ~ 50.6 M
14 |
15 |
16 | Mantra ~ 11 min, Arnold ~ 4 min, Redshift ~ 4 min
17 |
18 |
19 |
20 | ### C) Points (perspective camera trace), ~ 10.3 M (4 samples/pixel)
21 |
22 |
23 | Mantra ~ 8 min, Arnold ~ 1 min, Redshift ~ 2 min
24 |
25 |
26 |
27 | ### D) Volume, ~ 90 M voxels
28 |
29 |
30 | Mantra (with GGX) ~ 13 min, Mantra ~ 8 min, Arnold ~ 9 min, Redshift ~ 1 min
31 |
32 |
33 |
34 | ### E) SDF, ~ 70 M voxels
35 |
36 |
37 | Mantra ~ 16 min, Arnold ~ 3 min
38 |
39 |
40 |
41 | ## Mantra sdf vs polygons vs points (sphere traced) vs points (camera traced) vs fog vs fog (with GGX)
42 |
43 |
44 |
45 |
46 | ## Arnold points (camera traced), ~ 1 min
47 |
48 |
49 | 4 spp (~ 10.3 M points), 3 spp (~ 5.8 M points), 2 spp (~ 2.5 M points), 1.5 spp (~ 1.5 M points)
50 |
51 |
52 |
53 | ## Points (sphere traced) with GGX speculars, ~ 87 M points
54 |
55 |
56 | Mantra ~ 3 min, Arnold ~ 1 min (particles as discs with correct normals), Arnold (using instancing, too slow), Redshift ~ 3 min (as spheres - incorrect speculars, instancing not possible because of VRAM)
57 |
58 |
59 |
60 | ## Grid vs Frustum volumes comparison of volume size and render time
61 |
62 |
63 | Grid volume (~ 800MB, 272M voxels) - 3:30s, frustum volume 1.0 z (~ 800MB, 272M voxels) - 5:20s, frustum volume 0.75 z (~ 600MB, 204M voxels) - 5:21s, frustum volume 0.5 z (~ 400MB, 136M voxels) - 5:27s, frustum volume 0.25 z (~ 200MB, 68M voxels) - 5:42s
64 |
65 | **1.0 z** means scaling of resolution along Z axis (inside of the image)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | VFX Fractal Toolkit
2 | ==========================
3 | 
4 | *Set of tools for generating fractal and generative art.*
5 |
6 |
7 |
8 | ## About
9 | This is my graduation project: **VFX Fractal Toolkit** (VFT), which I developed at *Filmakademie Baden-Württemberg* while studying [Technical Directing](https://animationsinstitut.de/de/studium/animation/technical-director/informationen/).
10 |
11 | It contains tools written in *OpenCL, OSL, Blink, Python, VEX and JavaScript* intended to be used in *Houdini, Arnold, Nuke or a web browser*.
12 |
13 | The code is in prototyping stage and many features are experimental. It is **not production ready** and most parts of it need refactoring.
14 |
15 | Here are some animations produced with it:
16 |
17 | * [](https://www.youtube.com/watch?v=E8n6chN2Txw)
18 | * [](https://www.youtube.com/watch?v=_gdApm_QPjs)
19 | * [](https://www.youtube.com/watch?v=__8gaEv5GAs)
20 |
21 | I had a chance to present progress of VFT at two **FMX** conferences (2018, 2019), you can find the recordings here:
22 |
23 | * [](https://youtu.be/n-m00N7TYYM?t=2452)
24 | * [](https://youtu.be/SNa18n5d8UY?t=1m26s)
25 |
26 | It was also featured in **Posters Preview: SIGGRAPH 2019** video:
27 | * [](https://youtu.be/aRmfaEBLNmw)
28 |
29 | This project was presented at **The 15th ACM SIGGRAPH European Conference on Visual Media Production** [(CVMP 2018)](https://www.cvmp-conference.org/2018/programme/) conference: [fast-forward](https://www.youtube.com/watch?v=_CI8GFDmKZQ), [paper](https://animationsinstitut.de/fileadmin/user_upload/files_forschung/pdf/Publications/18_cvmp_vft_juraj_tomori_paper.pdf), [poster](https://animationsinstitut.de/fileadmin/user_upload/files_forschung/pdf/Publications/18_cvmp_vft_juraj_tomori_poster.png).
30 |
31 | It was also presented in [posters session](https://s2019.siggraph.org/presentation/?sess=sess175&id=pos_114#038;id=pos_114) at **SIGGRAPH 2019** in Los Angeles. You can find the abstract [here](https://dl.acm.org/citation.cfm?id=3306214.3338543).
32 |
33 | You can also cite my work:
34 | ```
35 | @inproceedings{Tomori:2019:VFT:3306214.3338543,
36 | author = {Tomori, Juraj},
37 | title = {VFX Fractal Toolkit: Integrating Fractals into VFX Pipeline},
38 | booktitle = {ACM SIGGRAPH 2019 Posters},
39 | series = {SIGGRAPH '19},
40 | year = {2019},
41 | isbn = {978-1-4503-6314-3},
42 | location = {Los Angeles, California},
43 | pages = {97:1--97:2},
44 | articleno = {97},
45 | numpages = {2},
46 | url = {http://doi.acm.org/10.1145/3306214.3338543},
47 | doi = {10.1145/3306214.3338543},
48 | acmid = {3338543},
49 | publisher = {ACM},
50 | address = {New York, NY, USA},
51 | keywords = {distance fields, fractals, pipeline, ray marching, vfx},
52 | }
53 | ```
54 |
55 | You can find **comparison of various techniques** (visual quality vs performance) [here](comparison.md).
56 |
57 |
58 |
59 | ## Resources
60 | * [Mandelbulber2 source code repository](https://github.com/buddhi1980/mandelbulber2/)
61 | * [Mandelbulb3D source code repository](https://github.com/thargor6/mb3d)
62 | * [Capturing the infinite universe in "Lucy": fractal rendering in film production](https://dl.acm.org/citation.cfm?id=2614166)
63 | * [The fractal nature of Guardians of the Galaxy Vol. 2](https://www.fxguide.com/featured/the-fractal-nature-of-guardians-of-the-galaxy-vol-2/)
64 |
65 |
66 |
67 | ## Thanks
68 | * [Íñigo Quílez](http://www.iquilezles.org/www/index.htm) - great articles on raymarching, fractals, orbit traps, SDFs...
69 | * Krzysztof Marczak - lead Mandelbulber2 developer, supporting via emails
70 | * [Mikael Hvidtfeldt Christensen](http://blog.hvidtfeldts.net/) - great articles on raymarching, fractals, generative art
71 | * [Dom Penfold](http://woo4.me/) - blog with useful articles
--------------------------------------------------------------------------------
/web/mandelbrot.js:
--------------------------------------------------------------------------------
1 | const glsl = x => x;
2 |
3 |
4 | // init
5 | var canvas = document.getElementById("main");
6 | var gl = canvas.getContext('webgl');
7 |
8 | // canvas size
9 | // Lookup the size the browser is displaying the canvas.
10 | var displayWidth = canvas.clientWidth;
11 | var displayHeight = canvas.clientHeight;
12 |
13 | // Check if the canvas is not the same size.
14 | if (canvas.width != displayWidth || canvas.height != displayHeight) {
15 | // Make the canvas the same size
16 | canvas.width = displayWidth;
17 | canvas.height = displayHeight;
18 | }
19 |
20 | /**
21 | * Shaders
22 | */
23 |
24 | // Utility to fail loudly on shader compilation failure
25 | function compileShader(shaderSource, shaderType) {
26 | var shader = gl.createShader(shaderType);
27 | gl.shaderSource(shader, shaderSource);
28 | gl.compileShader(shader);
29 |
30 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
31 | throw "Shader compile failed with: " + gl.getShaderInfoLog(shader);
32 | }
33 |
34 | return shader;
35 | }
36 |
37 | var vertexShader = compileShader(glsl`
38 | attribute vec2 position;
39 |
40 | void main() {
41 | // position specifies only x and y.
42 | // We set z to be 0.0, and w to be 1.0
43 | gl_Position = vec4(position, 0.0, 1.0);
44 | }
45 | `, gl.VERTEX_SHADER);
46 |
47 | var fragmentShader = compileShader(glsl`
48 | precision highp float;
49 | uniform vec2 res;
50 |
51 | void main(){
52 | // Draw every pixel red
53 | gl_FragColor = vec4(gl_FragCoord.x/res.x, gl_FragCoord.y/res.y, 0.0, 1.0);
54 | }
55 | `, gl.FRAGMENT_SHADER);
56 |
57 | var program = gl.createProgram();
58 | gl.attachShader(program, vertexShader);
59 | gl.attachShader(program, fragmentShader);
60 | gl.linkProgram(program);
61 | gl.useProgram(program);
62 |
63 | // setup uniforms
64 | var resLocation = gl.getUniformLocation(program, "res");
65 | gl.uniform2f(resLocation, displayWidth, displayHeight);
66 |
67 | /**
68 | * Geometry setup
69 | */
70 |
71 | // Set up 4 vertices, which we'll draw as a rectangle
72 | // via 2 triangles
73 | //
74 | // A---C
75 | // | /|
76 | // | / |
77 | // |/ |
78 | // B---D
79 | //
80 | // We order them like so, so that when we draw with
81 | // gl.TRIANGLE_STRIP, we draw triangle ABC and BCD.
82 | var vertexData = new Float32Array([
83 | -1.0, 1.0, // top left
84 | -1.0, -1.0, // bottom left
85 | 1.0, 1.0, // top right
86 | 1.0, -1.0, // bottom right
87 | ]);
88 | var vertexDataBuffer = gl.createBuffer();
89 | gl.bindBuffer(gl.ARRAY_BUFFER, vertexDataBuffer);
90 | gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
91 |
92 | /**
93 | * Attribute setup
94 | */
95 |
96 | // Utility to complain loudly if we fail to find the attribute
97 |
98 | function getAttribLocation(program, name) {
99 | var attributeLocation = gl.getAttribLocation(program, name);
100 | if (attributeLocation === -1) {
101 | throw 'Can not find attribute ' + name + '.';
102 | }
103 | return attributeLocation;
104 | }
105 |
106 | // To make the geometry information available in the shader as attributes, we
107 | // need to tell WebGL what the layout of our data in the vertex buffer is.
108 | var positionHandle = getAttribLocation(program, 'position');
109 | gl.enableVertexAttribArray(positionHandle);
110 | gl.vertexAttribPointer(positionHandle,
111 | 2, // position is a vec2
112 | gl.FLOAT, // each component is a float
113 | gl.FALSE, // don't normalize values
114 | 2 * 4, // two 4 byte float components per vertex
115 | 0 // offset into each span of vertex data
116 | );
117 |
118 | /**
119 | * Draw
120 | */
121 |
122 | // Render the 4 vertices specified above (starting at index 0)
123 | // in TRIANGLE_STRIP mode.
124 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
125 |
--------------------------------------------------------------------------------
/houdini/ocl/include/vft_utils.h:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #ifndef VFT_UTILS
13 | #define VFT_UTILS
14 |
15 | // some of the functions here are ported/derived from those sources:
16 | // http://iquilezles.org/www/
17 | // http://woo4.me/woofractal/
18 |
19 | ////////////// helper funcs
20 |
21 |
22 | // export float attrib
23 | static void vstore1(float dataIn, long i, global float* dataOut)
24 | {
25 | dataOut[i] = dataIn;
26 | }
27 |
28 |
29 | ////////////// sdf operations
30 |
31 |
32 | // polynomial smooth min
33 | static float sminPoly( float a, float b, float k )
34 | {
35 | float h = clamp( 0.5f + 0.5f * DIV((b - a), k), 0.0f, 1.0f );
36 | return mix( b, a, h ) - k * h * (1.0f - h);
37 | }
38 |
39 | // exponential smooth min
40 | static float sminExp( float a, float b, float k )
41 | {
42 | float res = EXP( -k * a ) + EXP( -k * b );
43 | return -DIV(LOG(res), k);
44 | }
45 |
46 | // union
47 | static float sdfUnion( float a, float b )
48 | {
49 | return min(a, b);
50 | }
51 |
52 | // smooth union
53 | static float sdfUnionSmooth( float a, float b, float k )
54 | {
55 | return sminPoly(a, b, k);
56 | }
57 |
58 | // subtraction
59 | static float sdfSubtract( float b, float a )
60 | {
61 | return max(-a, b);
62 | }
63 |
64 | // intersection
65 | static float sdfIntersect( float a, float b )
66 | {
67 | return max(a, b);
68 | }
69 |
70 | // blend
71 | static float sdfBlend(float d1, float d2, float a)
72 | {
73 | return (1 - a) * d1 + a * d2;
74 | }
75 |
76 | // infinitely repeat by a distance (c)
77 | static float3 spaceRep( float3 p, float3 c )
78 | {
79 | p = fmod(p,c) - 0.5f*c ;
80 | return p;
81 |
82 | }
83 |
84 | // repeat by a distance (c) and by a fixed number of copies (limit)
85 | static float3 spaceRepFixed(float3 p, float3 c, float3 limit)
86 | {
87 | limit *= c-1;
88 | p = min(-limit, p) + limit
89 | + fmod(max(min(p, limit), -limit), c) - 0.5f*c
90 | + max(p, limit) - limit;
91 | return p;
92 | }
93 |
94 | // [M2] wrap
95 | static float3 wrap(float3 x, float3 a, float3 s)
96 | {
97 | x -= s;
98 | return (float3)(x.x - a.x * floor(DIV(x.x, a.x)) + s.x, x.y - a.y * floor(DIV(x.y, a.y)) + s.y, x.z - a.z * floor(DIV(x.z, a.z)) + s.z);
99 | }
100 |
101 | ////////////// debug
102 |
103 |
104 | // print a mtx
105 | static void printMtx(float16 m)
106 | {
107 | int idx = get_global_id(0);
108 | if (idx == 0) {
109 | printf( "\n" );
110 | printf( "%2.2v4hlf\n", m.s0123 );
111 | printf( "%2.2v4hlf\n", m.s4567 );
112 | printf( "%2.2v4hlf\n", m.s89ab );
113 | printf( "%2.2v4hlf\n", m.scdef );
114 | printf( "\n" );
115 | }
116 | }
117 |
118 | // print a mtx
119 | static void printMtxVol(float16 m)
120 | {
121 | int gidx = get_global_id(0);
122 | int gidy = get_global_id(1);
123 | int gidz = get_global_id(2);
124 |
125 | if (gidx == 0 && gidy == 0 && gidz == 0) {
126 | printf( "\n" );
127 | printf( "%2.2v4hlf\n", m.s0123 );
128 | printf( "%2.2v4hlf\n", m.s4567 );
129 | printf( "%2.2v4hlf\n", m.s89ab );
130 | printf( "%2.2v4hlf\n", m.scdef );
131 | printf( "\n" );
132 | }
133 | }
134 |
135 | // print a vector
136 | static void printVec(float3 a)
137 | {
138 | int idx = get_global_id(0);
139 | if (idx == 0) {
140 | printf( "%2.2v3hlf\n", a );
141 | }
142 | }
143 |
144 | // print a float
145 | static void printFloat(float a)
146 | {
147 | int idx = get_global_id(0);
148 | if (idx == 0) {
149 | printf( "%2.15f\n", a );
150 | }
151 | }
152 |
153 | // print n new lines
154 | static void printNewLines(int n)
155 | {
156 | int idx = get_global_id(0);
157 | if (idx == 0) {
158 | for (int i = 0; i < n; i++)
159 | printf( "\n" );
160 | }
161 | }
162 |
163 | #endif
164 |
--------------------------------------------------------------------------------
/osl/include/vft_osl.h:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #ifndef VFT_OSL
13 | #define VFT_OSL
14 |
15 | // Trying to make OSL more compatible with OpenCL syntax
16 | // Some features like vector swizzling are not supported in OSL, so they won't be fully compatible with the current code,
17 | // but I am at least creating some helper macros and structs to speed up porting my OpenCL code
18 | // Note that list of types and functions here is not complete, I implemented only those which were required by OpenCL functions
19 |
20 | // functions
21 |
22 | #define SIN(x) sin(x)
23 | #define COS(x) cos(x)
24 | #define POWR(x, y) pow((x), (y))
25 | #define SQRT(x) sqrt(x)
26 | #define LOG(x) log(x)
27 | #define EXP(x) exp(x)
28 | #define DIV(x, y) ((x) / (y))
29 | #define NORMALIZE(x) normalize(x)
30 | #define LENGTH(x) length(x)
31 |
32 | #define M_PI_F 3.14159265358979323846
33 | #define LARGE_NUMBER 10e10
34 |
35 | // float3
36 |
37 | struct float3
38 | {
39 | float x, y, z;
40 | };
41 |
42 | float length(float3 vec)
43 | {
44 | return length( vector(vec.x, vec.y, vec.z) );
45 | }
46 |
47 | float3 fabs(float3 a)
48 | {
49 | vector vec = fabs( vector(a.x, a.y, a.z) );
50 | return float3(vec[0], vec[1], vec[2]);
51 | }
52 |
53 | float3 max(float3 a, float3 b)
54 | {
55 | vector vec = max( vector(a.x, a.y, a.z), vector(b.x, b.y, b.z) );
56 | return float3(vec[0], vec[1], vec[2]);
57 | }
58 |
59 | float3 max(float3 a, float b)
60 | {
61 | vector vec = max( vector(a.x, a.y, a.z), vector(b) );
62 | return float3(vec[0], vec[1], vec[2]);
63 | }
64 |
65 | float3 mix(float3 a, float3 b, float t)
66 | {
67 | vector vec = mix( vector(a.x, a.y, a.z), vector(b.x, b.y, b.z), t );
68 | return float3(vec[0], vec[1], vec[2]);
69 | }
70 |
71 | float3 __operator__neg__ (float3 a)
72 | {
73 | return float3(-a.x, -a.y, -a.z);
74 | }
75 |
76 | float3 __operator__add__ (float3 a, float3 b)
77 | {
78 | return float3(a.x+b.x, a.y+b.y, a.z+b.z);
79 | }
80 |
81 | float3 __operator__sub__ (float3 a, float3 b)
82 | {
83 | return float3(a.x-b.x, a.y-b.y, a.z-b.z);
84 | }
85 |
86 | float3 __operator__mul__ (float3 a, float3 b)
87 | {
88 | return float3(a.x*b.x, a.y*b.y, a.z*b.z);
89 | }
90 |
91 | float3 __operator__mul__ (float a, float3 b)
92 | {
93 | return float3(a*b.x, a*b.y, a*b.z);
94 | }
95 |
96 | float3 __operator__div__ (float3 a, float3 b)
97 | {
98 | return float3(a.x/b.x, a.y/b.y, a.z/b.z);
99 | }
100 |
101 | float3 __operator__mod__ (float3 a, float3 b)
102 | {
103 | return float3(fmod(a.x, b.x), fmod(a.y, b.y), fmod(a.z, b.z));
104 | }
105 |
106 | int __operator__eq__ (float3 a, float3 b)
107 | {
108 | if (a.x == b.x && a.y == b.y && a.z == b.z)
109 | return 1;
110 | else
111 | return 0;
112 | }
113 |
114 | int __operator__ne__ (float3 a, float3 b)
115 | {
116 | return 1 - (a == b);
117 | }
118 |
119 | // float2
120 |
121 | struct float2
122 | {
123 | float x, y;
124 | };
125 |
126 | float length(float2 vec)
127 | {
128 | return length( vector(vec.x, vec.y, 0) );
129 | }
130 |
131 | float2 normalize(float2 a)
132 | {
133 | vector vec = normalize( vector(a.x, a.y, 0) );
134 | return float2(vec[0], vec[1]);
135 | }
136 |
137 | float dot(float2 a, float2 b)
138 | {
139 | return dot( vector(a.x, a.y, 0), vector(b.x, b.y, 0) );
140 | }
141 |
142 | // float4
143 |
144 | struct float4
145 | {
146 | float x, y, z, w;
147 | };
148 |
149 |
150 | // functions
151 |
152 | float length2(vector vec)
153 | {
154 | return dot(vec, vec);
155 | }
156 |
157 | // point to plane distance
158 | float distPointPlane(vector pt, vector plane_n, vector plane_point)
159 | {
160 | float sb, sn, sd;
161 | vector point_proj;
162 |
163 | sn = -dot( plane_n, (pt - plane_point));
164 | sd = dot(plane_n, plane_n);
165 | sb = DIV(sn, sd);
166 |
167 | point_proj = pt + sb * plane_n;
168 |
169 | return LENGTH(pt - point_proj);
170 | }
171 |
172 | // returns rotation matrix specified by euler rotations in rot vector in degrees
173 | matrix euler_rotation(vector rot)
174 | {
175 | vector rot_rad = radians(-rot);
176 |
177 | float cosx = COS(rot_rad[0]);
178 | float sinx = SIN(rot_rad[0]);
179 | matrix x = matrix(1, 0, 0, 0,
180 | 0, cosx, -sinx, 0,
181 | 0, sinx, cosx, 0,
182 | 0, 0, 0, 1 );
183 |
184 | float cosy = COS(rot_rad[1]);
185 | float siny = SIN(rot_rad[1]);
186 | matrix y = matrix(cosy, 0, siny, 0,
187 | 0, 1, 0, 0,
188 | -siny, 0, cosy, 0,
189 | 0, 0, 0, 1 );
190 |
191 | float cosz = COS(rot_rad[2]);
192 | float sinz = SIN(rot_rad[2]);
193 | matrix z = matrix(cosz, -sinz, 0, 0,
194 | sinz, cosz, 0, 0,
195 | 0, 0, 1, 0,
196 | 0, 0, 0, 1 );
197 |
198 | matrix xform = 1;
199 | xform *= x;
200 | xform *= y;
201 | xform *= z;
202 |
203 | return xform;
204 | }
205 |
206 | #endif
207 |
--------------------------------------------------------------------------------
/nuke/blink/mandelbrot.blink:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #include "include/vft_blink.h"
13 |
14 | /*
15 | Mandelbort set visualizer, it takes complex image plane as an input (e.g. generated by complex_plane.blink)
16 |
17 | complex numbers are stored in vec2(X, Y) type, where X is real and Y is imaginary part
18 | */
19 |
20 | kernel mandelbrotKernel : ImageComputationKernel
21 | {
22 | Image c_src;
23 | Image c_trap;
24 |
25 | Image dst;
26 |
27 | param:
28 | int max_iter;
29 | int mandelbrot_power;
30 |
31 | int julia_mode;
32 | float2 julia_coord_parm;
33 |
34 | int color_mode;
35 |
36 | float2 orbit_pt_parm;
37 | float2 orbit_line_pt_1_parm;
38 | float2 orbit_line_pt_2_parm;
39 | float2 orbit_circle_center_parm;
40 | float orbit_circle_radius;
41 | float2 orbit_bitmap_offset;
42 | float orbit_bitmap_zoom;
43 |
44 | float zoom;
45 | float exp_zoom;
46 | float exp_zoom_anim;
47 | float2 offset;
48 | int2 img_res;
49 |
50 | local:
51 |
52 | void define() {
53 | defineParam(max_iter, "maximum_iterations", 1000);
54 | defineParam(mandelbrot_power, "mandelbrot_power", 2);
55 |
56 | defineParam(julia_mode, "julia_mode", 0);
57 | defineParam(julia_coord_parm, "julia_coordinate", float2(0.0f, 0.0f));
58 |
59 | defineParam(color_mode, "color_mode", 1);
60 |
61 | defineParam(orbit_pt_parm, "orbit_point_coordinate", float2(0.0f, 0.0f));
62 | defineParam(orbit_line_pt_1_parm, "orbit_line_point_1_coordinate", float2(0.0f, 0.0f));
63 | defineParam(orbit_line_pt_2_parm, "orbit_line_point_2_coordinate", float2(1.0f, 1.0f));
64 | defineParam(orbit_circle_center_parm, "orbit_circle_coordinate", float2(1.0f, 1.0f));
65 | defineParam(orbit_circle_radius, "orbit_circle_radius", 2.0f);
66 | defineParam(orbit_bitmap_offset, "orbit_bitmap_offset", float2(0.0f, 0.0f));
67 | defineParam(orbit_bitmap_zoom, "orbit_bitmap_zoom", 100.0f);
68 |
69 | defineParam(zoom, "initial_zoom", 1.0f);
70 | defineParam(exp_zoom, "exponential_zoom", 0.0f);
71 | defineParam(exp_zoom_anim, "exponential_zoom_anim", 0.0f);
72 | defineParam(offset, "offset", float2(0.0f, 0.0f));
73 | defineParam(img_res, "resolution", int2(1920, 1080));
74 | }
75 |
76 | void init() {
77 | }
78 |
79 | void process(int2 pos)
80 | {
81 | //float2 c_my = float2(pos.x, pos.y) - float2(img_res.x, img_res.y)/2;
82 | //c_my = zoomComplexPlane(c_my, zoom, exp_zoom_anim, offset);
83 |
84 | complex c = complex(c_src(0), c_src(1));
85 | //c = c_my;
86 | complex z = c;
87 | complex z0 = z;
88 | complex z_next;
89 | int i = 0;
90 |
91 | float col_smooth = exp( -dot(z,z) );
92 |
93 | float orbit_pt_dist = LARGE_NUMBER;
94 | float orbit_coord_dist = LARGE_NUMBER;
95 | float orbit_line_dist = LARGE_NUMBER;
96 | float orbit_circle_dist = LARGE_NUMBER;
97 |
98 | float2 orbit_pt = zoomComplexPlane(orbit_pt_parm - float2(img_res.x, img_res.y)/2, zoom, exp_zoom, offset) - offset;
99 | float2 orbit_line_pt_1 = zoomComplexPlane(orbit_line_pt_1_parm - float2(img_res.x, img_res.y)/2, zoom, exp_zoom, offset) - offset;
100 | float2 orbit_line_pt_2 = zoomComplexPlane(orbit_line_pt_2_parm - float2(img_res.x, img_res.y)/2, zoom, exp_zoom, offset) - offset;
101 | float2 orbit_circle_center = zoomComplexPlane(orbit_circle_center_parm - float2(img_res.x, img_res.y)/2, zoom, exp_zoom, offset) - offset;
102 | float4 orbit_bitmap_color = float4(0.0f);
103 | float2 orbit_sample_pos = float2(0.0f);
104 |
105 | float2 julia_coord = zoomComplexPlane(julia_coord_parm - float2(img_res.x, img_res.y)/2, zoom, exp_zoom, offset) - offset;
106 |
107 | if (julia_mode)
108 | c = julia_coord;
109 |
110 | for (; i < max_iter; i++)
111 | {
112 | // complex iterative function
113 | z_next = complex_add(complex_pow(z, mandelbrot_power), c);
114 | z = z_next;
115 |
116 | // colors
117 | col_smooth += exp( -dot(z,z) );
118 |
119 | // orbit traps
120 | if (color_mode == 2)
121 | {
122 | orbit_pt_dist = min(orbit_pt_dist, fabs( dot(z - orbit_pt, z - orbit_pt) ));
123 | orbit_coord_dist = min(orbit_coord_dist, fabs( dot(z - z0, z - z0) ));
124 | orbit_line_dist = min(orbit_line_dist, fabs( distPtLine(z, orbit_line_pt_1, orbit_line_pt_2) ));
125 | orbit_circle_dist = min(orbit_circle_dist, fabs( distPtCircle(z, orbit_circle_center, orbit_circle_radius) ));
126 | }
127 | else if (color_mode == 3)
128 | {
129 | orbit_sample_pos = z * float2(orbit_bitmap_zoom) - orbit_bitmap_offset;
130 | orbit_bitmap_color = c_trap(orbit_sample_pos.x, orbit_sample_pos.y);
131 |
132 | if (orbit_bitmap_color.w > 0.05)
133 | break;
134 | }
135 |
136 | if (complex_abs(z) > 4)
137 | break;
138 | }
139 |
140 | orbit_pt_dist = sqrt(orbit_pt_dist);
141 | orbit_coord_dist = sqrt(orbit_coord_dist);
142 |
143 | float4 out_col;
144 | float col_steps;
145 | float vis_min;
146 |
147 | if (color_mode == 0) // steps shading
148 | {
149 | col_steps = float(i) / float(max_iter);
150 | if (i == max_iter)
151 | col_steps = 0.0f;
152 |
153 | out_col = float4(col_steps, col_steps, col_steps, 1.0);
154 | }
155 |
156 | else if (color_mode == 1) // smooth shading
157 | {
158 | col_smooth /= float(max_iter);
159 |
160 | out_col = float4(col_smooth, col_smooth, col_smooth, 1.0);
161 | }
162 |
163 | else if (color_mode == 2) // orbit traps
164 | {
165 | out_col = float4(orbit_pt_dist, orbit_coord_dist, orbit_line_dist, orbit_circle_dist);
166 | }
167 |
168 | else if (color_mode == 3) // bitmap orbit trap
169 | {
170 | out_col = orbit_bitmap_color;
171 | }
172 |
173 | else if (color_mode == 4) // orbit traps visualization
174 | {
175 | vis_min = min(
176 | sqrt( fabs( dot(float2(pos.x, pos.y) - orbit_pt_parm, float2(pos.x, pos.y) - orbit_pt_parm) )) * 0.0003f,
177 | fabs( distPtLine(float2(pos.x, pos.y), orbit_line_pt_1_parm, orbit_line_pt_2_parm) ) * 0.0003f
178 | );
179 |
180 | vis_min = min(
181 | vis_min,
182 | fabs( distPtCircle(float2(pos.x, pos.y), orbit_circle_center_parm, orbit_circle_radius) ) * 0.0003f
183 | );
184 |
185 | out_col = float4(vis_min, vis_min, vis_min, 1.0f);
186 | }
187 |
188 | dst() = float4(out_col.x, out_col.y, out_col.z, out_col.w);
189 | }
190 | };
--------------------------------------------------------------------------------
/houdini/ocl/include/vft_shading.h:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #ifndef VFT_SHADING
13 | #define VFT_SHADING
14 |
15 | float scene(float3, const int, float*, float3*, global const void*);
16 | static float length2(float3);
17 | static float distPointPlane(float3, float3, float3);
18 | float primitive_stack(float3, const int);
19 | void fractal_stack(float3*, float*, const float3*, int*, const int, global const void*);
20 |
21 | ////////////// shading functions
22 |
23 | // compute Normals
24 | // based on "Modeling with distance functions" article from Inigo Quilez
25 | static float3 compute_N(const float* iso_limit, const float3* ray_P_world, global const void* theXNoise)
26 | {
27 | float3 N_grad;
28 | float2 e = (float2)(1.0f, -1.0f) * (*iso_limit) * 0.01f;
29 |
30 | N_grad = NORMALIZE( e.xyy * scene( (*ray_P_world) + e.xyy, 0, NULL, NULL, theXNoise) +
31 | e.yyx * scene( (*ray_P_world) + e.yyx, 0, NULL, NULL, theXNoise) +
32 | e.yxy * scene( (*ray_P_world) + e.yxy, 0, NULL, NULL, theXNoise) +
33 | e.xxx * scene( (*ray_P_world) + e.xxx, 0, NULL, NULL, theXNoise) );
34 | return N_grad;
35 | }
36 |
37 | // compute Ambient Occlusion
38 | // based on "Modeling with distance functions" article from Inigo Quilez
39 | static float compute_AO(const float3* N, const float3* ray_P_world, global const void* theXNoise)
40 | {
41 | float AO = 1.0f;
42 | float AO_occ = 0.0f;
43 | float AO_sca = 1.0f;
44 |
45 | #pragma unroll
46 | for(int j=0; j<5; j++)
47 | {
48 | float AO_hr = 0.01f + 0.12f * DIV((float)(j), 4.0f);
49 | float3 AO_pos = (*N) * AO_hr + (*ray_P_world);
50 | float AO_dd = scene(AO_pos, 0, NULL, NULL, theXNoise);
51 | AO_occ += -(AO_dd-AO_hr)*AO_sca;
52 | AO_sca *= 0.95f;
53 | }
54 |
55 | AO = clamp( 1.0f - 3.4f * AO_occ, 0.0f, 1.0f );
56 | AO = POWR(AO, 1.6f);
57 |
58 | return AO;
59 | }
60 |
61 | // primitive shape function - calls respective parto of primitive_stack(), in case of DELTA DE mode also outputs N
62 | static float primitive(float3 P, const float size, const int final, float* orbit_closest, float* orbit_colors, const float3 color, float3* N, const int stack)
63 | {
64 | P = DIV(P, size);
65 | float out_distance = primitive_stack(P, stack);
66 |
67 | if (final == 1 && out_distance <= *orbit_closest - ORBITS_OFFSET)
68 | {
69 | #pragma unroll
70 | for (int i=0; i max_distance) break;
115 |
116 | fractal_stack(&Z, &de, &P_in, &log_lin, stack, theXNoise);
117 |
118 | // orbit traps calculations
119 | if (final == 1)
120 | {
121 | orbit_pt_dist = min(orbit_pt_dist, length2(Z - orbit_pt));
122 | orbit_plane_dist.x = min( orbit_plane_dist.x, distPointPlane(Z, orbit_plane.xyy, orbit_plane_origin) );
123 | orbit_plane_dist.y = min( orbit_plane_dist.y, distPointPlane(Z, orbit_plane.yxy, orbit_plane_origin) );
124 | orbit_plane_dist.z = min( orbit_plane_dist.z, distPointPlane(Z, orbit_plane.yyx, orbit_plane_origin) );
125 | orbit_coord_dist = min( orbit_coord_dist, fabs(dot(Z, P_in)) );
126 | orbit_sphere_dist = min( orbit_sphere_dist, length2(Z - NORMALIZE(Z)*orbit_sphere_rad) );
127 | orbit_axis_dist.x = min(orbit_axis_dist.x, Z.y*Z.y + Z.z*Z.z);
128 | orbit_axis_dist.y = min(orbit_axis_dist.y, Z.x*Z.x + Z.z*Z.z);
129 | orbit_axis_dist.z = min(orbit_axis_dist.z, Z.x*Z.x + Z.y*Z.y);
130 | }
131 | }
132 | distance = LENGTH(Z);
133 | *iterations = i;
134 |
135 | // delta DE method
136 | // based on Makin/Buddhi 4-point Delta-DE formula
137 | #if ENABLE_DELTA_DE
138 | float delta = 0.000005f;
139 |
140 | Z = P_in + (float3)(delta, 0.0f, 0.0f);
141 | #pragma unroll
142 | for (int j=0; j= 0) out_distance = 0.5f * LOG(distance) * DIV(distance, de);
177 | else out_distance = DIV(distance, fabs(de));
178 |
179 | // outputting orbit traps (and N in case of DELTA DE mode) to the closest shape
180 | if (final == 1 && out_distance <= *orbit_closest)
181 | {
182 | orbit_colors[0] = SQRT(orbit_pt_dist); // distance to point at specified coordinates
183 | orbit_colors[1] = orbit_plane_dist.x; // distance to YZ plane
184 | orbit_colors[2] = orbit_plane_dist.y; // distance to XZ plane
185 | orbit_colors[3] = orbit_plane_dist.z; // distance to XY plane
186 | orbit_colors[4] = orbit_coord_dist; // dot(Z, world coords)
187 | orbit_colors[5] = SQRT(orbit_sphere_dist); // distance to sphere
188 | orbit_colors[6] = SQRT(orbit_axis_dist.x); // distance to X axis
189 | orbit_colors[7] = SQRT(orbit_axis_dist.y); // distance to Y axis
190 | orbit_colors[8] = SQRT(orbit_axis_dist.z); // distance to Z axis
191 |
192 | #if ENABLE_DELTA_DE
193 | *N = dist_grad;
194 | #endif
195 | }
196 |
197 | // change orbit_closest, if the evaluated point is closer to this shape
198 | *orbit_closest = min(*orbit_closest, out_distance * size);
199 |
200 | // output distance estimate, take shape's size into consideration
201 | return out_distance * size;
202 | }
203 |
204 | #endif
205 |
--------------------------------------------------------------------------------
/osl/include/vft_fractals_osl.h:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #ifndef VFT_FRACTALS_OSL
13 | #define VFT_FRACTALS_OSL
14 |
15 | // Porting OpenCL fractal functions from vft_fractals.h
16 | // it means removing
17 | // "static" keyword,
18 | // "f" literal,
19 | // "const" keyword,
20 | // fixing expressions with vector swizzling,
21 | // removing pointers,
22 | // removing casts
23 | // removing de, log_lin variables
24 |
25 | // sphere: position, radius
26 | float sphere( float3 P, float rad )
27 | {
28 | float dist = LENGTH(P) - rad;
29 | return dist;
30 | }
31 |
32 | // box: position, size
33 | float box( float3 P, float3 b )
34 | {
35 | float3 d = fabs(P) - b;
36 | return min( max( d.x, max(d.y, d.z) ), 0.0) + LENGTH( max(d, 0.0) );
37 | }
38 |
39 | // round box: position, size, roundness
40 | float roundBox( float3 P, float3 b, float r )
41 | {
42 | return LENGTH( max( fabs(P) - b, 0.0 ) )-r;
43 | }
44 |
45 | // torus: position, size (radius, thickness)
46 | float torus( float3 P, float2 t )
47 | {
48 | float2 q = float2(LENGTH( float2(P.x, P.z) )-t.x,P.y);
49 | return LENGTH(q)-t.y;
50 | }
51 |
52 | // infinite cone
53 | float cone( float3 P, float2 c )
54 | {
55 | c = NORMALIZE(c);
56 | float q = LENGTH(float2(P.x, P.y));
57 | return dot( c, float2(q, P.z) );
58 | }
59 |
60 | // [WEB] - http://blog.hvidtfeldts.net/index.php/2011/09/
61 | void mandelbulbIter(point Z, point P_in, float weight, float4 julia, float power)
62 | {
63 | point Z_orig = Z;
64 |
65 | float distance = LENGTH(Z);
66 |
67 | // convert to polar coordinates
68 | float theta = acos( DIV(Z[2], distance));
69 | float phi = atan2(Z[1], Z[0]);
70 |
71 | // scale and rotate the point
72 | float zr = POWR(distance, power);
73 | theta *= power;
74 | phi *= power;
75 |
76 | // convert back to cartesian coordinates
77 | point new_pZ = zr * point( SIN(theta)*COS(phi), SIN(phi)*SIN(theta), COS(theta) );
78 |
79 | if (julia.x == 0.0)
80 | {
81 | Z = new_pZ + P_in;
82 | }
83 | else
84 | {
85 | Z = new_pZ + point(julia.y, julia.z, julia.w);
86 | }
87 |
88 | Z = mix(Z_orig, Z, weight);
89 | }
90 |
91 | // [WEB] - http://www.fractalforums.com/index.php?topic=2785.msg14893#msg14893
92 | void mandelboxIter(point Z, point P_in, float weight, float4 julia, float scale)
93 | {
94 | point Z_orig = Z;
95 |
96 | float fixedRadius = 1.0;
97 | float fR2 = fixedRadius * fixedRadius;
98 | float minRadius = 0.5;
99 | float mR2 = minRadius * minRadius;
100 |
101 | if (Z[0] > 1.0) Z[0] = 2.0 - Z[0];
102 | else if (Z[0] < -1.0) Z[0] = -2.0 - Z[0];
103 |
104 | if (Z[1] > 1.0) Z[1] = 2.0 - Z[1];
105 | else if (Z[1] < -1.0) Z[1] = -2.0 - Z[1];
106 |
107 | if (Z[2] > 1.0) Z[2] = 2.0 - Z[2];
108 | else if (Z[2] < -1.0) Z[2] = -2.0 - Z[2];
109 |
110 | float r2 = Z[0]*Z[0] + Z[1]*Z[1] + Z[2]*Z[2];
111 |
112 | if (r2 < mR2)
113 | {
114 | Z = Z * DIV(fR2, mR2);
115 | }
116 | else if (r2 < fR2)
117 | {
118 | Z = Z * DIV(fR2, r2);
119 | }
120 |
121 | if (julia.x == 0.0)
122 | {
123 | Z = Z * scale + P_in;
124 | }
125 | else
126 | {
127 | Z = Z * scale + point(julia.y, julia.z, julia.w);
128 | }
129 |
130 | Z = mix(Z_orig, Z, weight);
131 | }
132 |
133 | // [M2] - Classic Mandelbulb Power 2 fractal - MandelbulbPower2Iteration
134 | void mandelbulbPower2Iter(point Z, point P_in, float weight, float4 julia)
135 | {
136 | point Z_orig = Z;
137 |
138 | float x2 = Z[0] * Z[0];
139 | float y2 = Z[1] * Z[1];
140 | float z2 = Z[2] * Z[2];
141 | float temp = DIV(1.0 - z2, (x2 + y2));
142 | point new_p;
143 | new_p[0] = (x2 - y2) * temp;
144 | new_p[0] = 2.0 * Z[0] * Z[1] * temp;
145 | new_p[0] = -2.0 * Z[2] * SQRT(x2 + y2);
146 |
147 | if (julia.x == 0.0)
148 | {
149 | Z = new_p + P_in;
150 | }
151 | else
152 | {
153 | Z = new_p + point(julia.y, julia.z, julia.w);
154 | }
155 |
156 | Z = mix(Z_orig, Z, weight);
157 | }
158 |
159 | // [M2] - Bristorbrot formula - BristorbrotIteration
160 | void bristorbrotIter(point Z, point P_in, float weight, float4 julia)
161 | {
162 | point Z_orig = Z;
163 |
164 | point new_p;
165 | new_p[0] = Z[0] * Z[0] - Z[1] * Z[1] - Z[2] * Z[2];
166 | new_p[1] = Z[1] * (2.0 * Z[0] - Z[2]);
167 | new_p[2] = Z[2] * (2.0 * Z[0] + Z[1]);
168 |
169 | Z = new_p;
170 |
171 | if (julia.x == 0.0)
172 | {
173 | Z += P_in;
174 | }
175 | else
176 | {
177 | Z += point(julia.y, julia.z, julia.w);
178 | }
179 |
180 | Z = mix(Z_orig, Z, weight);
181 | }
182 |
183 | // [M2] - Xenodreambuie - XenodreambuieIteration
184 | void xenodreambuieIter(point Z, point P_in, float weight, float4 julia, float power, float alpha_parm, float beta_parm)
185 | {
186 | point Z_orig = Z;
187 |
188 | float distance = LENGTH(Z);
189 |
190 | float alpha = radians(alpha_parm);
191 | float beta = radians(beta_parm);
192 |
193 | float rp = POWR(distance, power - 1.0);
194 | rp *= distance;
195 |
196 | float th = atan2(Z[1], Z[0]) + beta;
197 | float ph = acos( DIV(Z[2], distance)) + alpha;
198 |
199 | if (fabs(ph) > 0.5 * M_PI_F) ph = sign(ph) * M_PI_F - ph;
200 |
201 | Z[0] = rp * COS(th * power) * SIN(ph * power);
202 | Z[1] = rp * SIN(th * power) * SIN(ph * power);
203 | Z[2] = rp * COS(ph * power);
204 |
205 | if (julia.x == 0.0)
206 | {
207 | Z += P_in;
208 | }
209 | else
210 | {
211 | Z += point(julia.y, julia.z, julia.w);
212 | }
213 |
214 | Z = mix(Z_orig, Z, weight);
215 | }
216 |
217 | // [M2] - Benesi formula invented by Benesi - BenesiIteration
218 | void benesiIter(point Z, point P_in, float weight, float4 julia)
219 | {
220 | point Z_orig = Z;
221 |
222 | float distance = LENGTH(Z);
223 |
224 | float r1 = Z[1] * Z[1] + Z[2] * Z[2];
225 | float newx;
226 | if (P_in[0] < 0.0 || Z[0] < SQRT(r1))
227 | {
228 | newx = Z[0] * Z[0] - r1;
229 | }
230 | else
231 | {
232 | newx = -Z[0] * Z[0] + r1;
233 | }
234 | r1 = DIV(-1.0, SQRT(r1)) * 2.0 * fabs(Z[0]);
235 | float newy = r1 * (Z[1] * Z[1] - Z[2] * Z[2]);
236 | float newz = r1 * 2.0 * Z[1] * Z[2];
237 |
238 | Z = point(newx, newy, newz);
239 |
240 | if (julia.x == 0.0)
241 | {
242 | Z += P_in;
243 | }
244 | else
245 | {
246 | Z += point(julia.y, julia.z, julia.w);
247 | }
248 |
249 | Z = mix(Z_orig, Z, weight);
250 | }
251 |
252 | // [M2] - Ides formula made by Trafassel, the original Ide's Formula thread - IdesIteration
253 | void idesIter(point Z, point P_in, float weight, float4 julia, point multiplier, float2 sub_multiplier)
254 | {
255 | point Z_orig = Z;
256 |
257 | if (fabs(Z[0]) < 2.5) Z[0] = Z[0] * 0.9;
258 | if (fabs(Z[2]) < 2.5) Z[2] = Z[2] * 0.9;
259 |
260 | point z2 = Z * Z;
261 | point newZ;
262 | newZ[0] = multiplier[0] * z2[0] - sub_multiplier.x * (z2[1] + z2[2]);
263 | newZ[1] = multiplier[1] * Z[0] * Z[1] * Z[2];
264 | newZ[2] = multiplier[2] * z2[2] - sub_multiplier.y * (z2[0] + z2[1]);
265 | Z = newZ;
266 |
267 | if (julia.x == 0.0)
268 | {
269 | Z += P_in;
270 | }
271 | else
272 | {
273 | Z += point(julia.y, julia.z, julia.w);
274 | }
275 |
276 | Z = mix(Z_orig, Z, weight);
277 | }
278 |
279 | // [M2] - IQ Bulb from Mandelbulb 3D and Inigo Quilez - IqBulbIteration
280 | void iqBulbIter(point Z, point P_in, float weight, float4 julia, float power, float zpower)
281 | {
282 | point Z_orig = Z;
283 |
284 | float distance = LENGTH(Z);
285 |
286 | // extract polar coordinates
287 | float wr = distance;
288 | float wo = acos( DIV(Z[1], wr));
289 | float wi = atan2(Z[0], Z[2]);
290 |
291 | // scale and rotate the point
292 | wr = POWR(wr, power - 1.0);
293 | wr *= distance;
294 | wo *= power;
295 | wi *= zpower;
296 |
297 | // convert back to cartesian coordinates
298 | Z[0] = SIN(wo) * SIN(wi);
299 | Z[1] = COS(wo);
300 | Z[2] = SIN(wo) * COS(wi);
301 |
302 | Z *= wr; // then add Cpixel constant
303 |
304 | if (julia.x == 0.0)
305 | {
306 | Z += P_in;
307 | }
308 | else
309 | {
310 | Z += point(julia.y, julia.z, julia.w);
311 | }
312 |
313 | Z = mix(Z_orig, Z, weight);
314 | }
315 |
316 | #endif
317 |
--------------------------------------------------------------------------------
/houdini/ocl/include/vft_math.h:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #ifndef VFT_MATH
13 | #define VFT_MATH
14 |
15 | // some of the functions here are ported/derived from Three.js library for WebGL:
16 | // https://github.com/mrdoob/three.js/tree/master/src/math
17 |
18 | // length2
19 | static float length2(float3 vec)
20 | {
21 | return (float)(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z);
22 | }
23 |
24 | // point to plane distance
25 | static float distPointPlane(float3 point, float3 plane_n, float3 plane_point)
26 | {
27 | float sb, sn, sd;
28 | float3 point_proj;
29 |
30 | sn = -dot( plane_n, (point - plane_point));
31 | sd = dot(plane_n, plane_n);
32 | sb = DIV(sn, sd);
33 |
34 | point_proj = point + sb * plane_n;
35 |
36 | return LENGTH(point - point_proj);
37 | }
38 |
39 | // identity 4x4 matrix
40 | static float16 mtxIdent()
41 | {
42 | return (float16)(1,0,0,0,
43 | 0,1,0,0,
44 | 0,0,1,0,
45 | 0,0,0,1);
46 | }
47 |
48 | // transpose a 4x4 matrix
49 | static float16 mtxTranspose(float16 m)
50 | {
51 | float16 x;
52 | x = (float16)( m.s0,m.s4,m.s8,m.sc,
53 | m.s1,m.s5,m.s9,m.sd,
54 | m.s2,m.s6,m.sa,m.se,
55 | m.s3,m.s7,m.sb,m.sf);
56 | return x;
57 | }
58 |
59 | // multiplication of two 4x4 matrices
60 | static float16 mtxMult(float16 a, float16 b)
61 | {
62 | // float16 to float4 array
63 | const float4 ma[4] = { (float4)(a.s0123),
64 | (float4)(a.s4567),
65 | (float4)(a.s89ab),
66 | (float4)(a.scdef) };
67 |
68 | const float4 mb[4] = { (float4)(b.s048c),
69 | (float4)(b.s159d),
70 | (float4)(b.s26ae),
71 | (float4)(b.s37bf) };
72 |
73 | // compute matrix multiplication as a table of dot products
74 | float4 x[4] = {
75 | (float4)( dot(ma[0], mb[0]), dot(ma[0], mb[1]), dot(ma[0], mb[2]), dot(ma[0], mb[3]) ),
76 | (float4)( dot(ma[1], mb[0]), dot(ma[1], mb[1]), dot(ma[1], mb[2]), dot(ma[1], mb[3]) ),
77 | (float4)( dot(ma[2], mb[0]), dot(ma[2], mb[1]), dot(ma[2], mb[2]), dot(ma[2], mb[3]) ),
78 | (float4)( dot(ma[3], mb[0]), dot(ma[3], mb[1]), dot(ma[3], mb[2]), dot(ma[3], mb[3]) )
79 | };
80 |
81 | // float4 array to float16
82 | return (float16)(x[0].x,x[0].y,x[0].z,x[0].w,
83 | x[1].x,x[1].y,x[1].z,x[1].w,
84 | x[2].x,x[2].y,x[2].z,x[2].w,
85 | x[3].x,x[3].y,x[3].z,x[3].w );
86 | }
87 |
88 | // generates a 4x4 scaling matrix
89 | static float16 mtxScale(float3 s)
90 | {
91 | float16 x;
92 | x = (float16)(s.x, 0, 0, 0,
93 | 0 , s.y, 0, 0,
94 | 0 , 0, s.z, 0,
95 | 0 , 0, 0, 1);
96 | return x;
97 | }
98 |
99 | // generates a 4x4 translation matrix
100 | static float16 mtxTranslate(float3 t)
101 | {
102 | float16 x;
103 | x = (float16)(1, 0, 0, 0,
104 | 0, 1, 0, 0,
105 | 0, 0, 1, 0,
106 | t.x, t.y, t.z, 1);
107 | return x;
108 | }
109 |
110 | // generates a 4x4 rotation matrix in XYZ order, in degrees
111 | static float16 mtxRotate(float3 rot)
112 | {
113 | rot = radians(-rot);
114 |
115 | const float cosx = COS(rot.x);
116 | const float sinx = SIN(rot.x);
117 | const float16 x = (float16)(1, 0, 0, 0,
118 | 0, cosx, -sinx, 0,
119 | 0, sinx, cosx, 0,
120 | 0, 0, 0, 1 );
121 |
122 | const float cosy = COS(rot.y);
123 | const float siny = SIN(rot.y);
124 | const float16 y = (float16)(cosy, 0, siny, 0,
125 | 0, 1, 0, 0,
126 | -siny, 0, cosy, 0,
127 | 0, 0, 0, 1 );
128 |
129 | const float cosz = COS(rot.z);
130 | const float sinz = SIN(rot.z);
131 | const float16 z = (float16)(cosz, -sinz, 0, 0,
132 | sinz, cosz, 0, 0,
133 | 0, 0, 1, 0,
134 | 0, 0, 0, 1 );
135 |
136 | float16 xform = mtxIdent();
137 | xform = mtxMult(xform, x);
138 | xform = mtxMult(xform, y);
139 | xform = mtxMult(xform, z);
140 |
141 | return xform;
142 | }
143 |
144 |
145 | // multiplciation of a 4x4 matrix and a position vector (homogeneous)
146 | static float3 mtxPtMult(float16 mtx, float3 vec)
147 | {
148 | const float4 m[4] = { (float4)(mtx.s048c),
149 | (float4)(mtx.s159d),
150 | (float4)(mtx.s26ae),
151 | (float4)(mtx.s37bf) };
152 |
153 | const float4 v = (float4)(vec.x, vec.y, vec.z, 1);
154 | float4 x = (float4)( dot(v, m[0]), dot(v, m[1]), dot(v, m[2]), dot(v, m[3]) );
155 | x = DIV(x, x.w);
156 |
157 | return (float3)(x.xyz);
158 | }
159 |
160 | // multiplciation of a 4x4 matrix and a directional vector, assumes affine matrix
161 | static float3 mtxDirMult(float16 mtx, float3 vec)
162 | {
163 | const float4 m[3] = { (float4)(mtx.s048c),
164 | (float4)(mtx.s159d),
165 | (float4)(mtx.s26ae) };
166 |
167 | const float4 v = (float4)(vec.x, vec.y, vec.z, 1.0f);
168 | float3 x = (float3)( dot(v, m[0]), dot(v, m[1]), dot(v, m[2]) );
169 |
170 | return x;
171 | }
172 |
173 | // inverts a 4x4 matrix
174 | static float16 mtxInvert(float16 me)
175 | {
176 | float16 te;
177 |
178 | float
179 | n11 = me.s0, n21 = me.s1, n31 = me.s2, n41 = me.s3,
180 | n12 = me.s4, n22 = me.s5, n32 = me.s6, n42 = me.s7,
181 | n13 = me.s8, n23 = me.s9, n33 = me.sa, n43 = me.sb,
182 | n14 = me.sc, n24 = me.sd, n34 = me.se, n44 = me.sf,
183 |
184 | t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
185 | t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
186 | t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
187 | t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
188 |
189 | float det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
190 |
191 | //if ( det == 0 ) return mtxIdent(); // assuming invertible matrices only
192 |
193 | float detInv = DIV(1.0f, det);
194 |
195 | te.s0 = t11 * detInv;
196 | te.s1 = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
197 | te.s2 = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
198 | te.s3 = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
199 |
200 | te.s4 = t12 * detInv;
201 | te.s5 = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
202 | te.s6 = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
203 | te.s7 = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
204 |
205 | te.s8 = t13 * detInv;
206 | te.s9 = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
207 | te.sa = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
208 | te.sb = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
209 |
210 | te.sc = t14 * detInv;
211 | te.sd = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
212 | te.se = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
213 | te.sf = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
214 |
215 | return te;
216 |
217 | }
218 |
219 | #endif
220 |
--------------------------------------------------------------------------------
/houdini/vex/include/vft_subd.h:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #ifndef VFT_SUBD
13 | #define VFT_SUBD
14 |
15 | // a function for constructing new primitives, to be used in subdivision functions
16 | function void construct_primitives(int prim_pts_idx[], new_edge_pts[]; int new_face_pt, ordering_mode, primnum)
17 | {
18 | removeprim(0, primnum, 0);
19 |
20 | if (ordering_mode == 0)
21 | {
22 | // uniform
23 | addprim(0, "poly", prim_pts_idx[0], new_edge_pts[0], new_face_pt, new_edge_pts[3]);
24 | addprim(0, "poly", new_edge_pts[0], prim_pts_idx[1], new_edge_pts[1], new_face_pt);
25 | addprim(0, "poly", new_face_pt, new_edge_pts[1], prim_pts_idx[2], new_edge_pts[2]);
26 | addprim(0, "poly", new_edge_pts[3], new_face_pt, new_edge_pts[2], prim_pts_idx[3]);
27 | }
28 | else if (ordering_mode == 1)
29 | {
30 | // mirror x y
31 | addprim(0, "poly", prim_pts_idx[0], new_edge_pts[0], new_face_pt, new_edge_pts[3]);
32 | addprim(0, "poly", prim_pts_idx[1], new_edge_pts[0], new_face_pt, new_edge_pts[1]);
33 | addprim(0, "poly", prim_pts_idx[2], new_edge_pts[2], new_face_pt, new_edge_pts[1]);
34 | addprim(0, "poly", prim_pts_idx[3], new_edge_pts[2], new_face_pt, new_edge_pts[3]);
35 | }
36 | else if (ordering_mode == 2)
37 | {
38 | // mirror y
39 | addprim(0, "poly", prim_pts_idx[0], new_edge_pts[0], new_face_pt, new_edge_pts[3]);
40 | addprim(0, "poly", prim_pts_idx[1], new_edge_pts[0], new_face_pt, new_edge_pts[1]);
41 | addprim(0, "poly", new_edge_pts[1], new_face_pt, new_edge_pts[2], prim_pts_idx[2]);
42 | addprim(0, "poly", new_edge_pts[3], new_face_pt, new_edge_pts[2], prim_pts_idx[3]);
43 | }
44 | else if (ordering_mode == 3)
45 | {
46 | // mirror x
47 | addprim(0, "poly", prim_pts_idx[0], new_edge_pts[0], new_face_pt, new_edge_pts[3]);
48 | addprim(0, "poly", new_edge_pts[0], prim_pts_idx[1], new_edge_pts[1], new_face_pt);
49 | addprim(0, "poly", new_edge_pts[2], prim_pts_idx[2], new_edge_pts[1], new_face_pt);
50 | addprim(0, "poly", prim_pts_idx[3], new_edge_pts[2], new_face_pt, new_edge_pts[3]);
51 | }
52 | else if (ordering_mode == 4)
53 | {
54 | // cyclic
55 | addprim(0, "poly", prim_pts_idx[0], new_edge_pts[0], new_face_pt, new_edge_pts[3]);
56 | addprim(0, "poly", prim_pts_idx[1], new_edge_pts[1], new_face_pt, new_edge_pts[0]);
57 | addprim(0, "poly", prim_pts_idx[2], new_edge_pts[2], new_face_pt, new_edge_pts[1]);
58 | addprim(0, "poly", prim_pts_idx[3], new_edge_pts[3], new_face_pt, new_edge_pts[2]);
59 | }
60 | else if (ordering_mode == 5)
61 | {
62 | // opposite
63 | addprim(0, "poly", new_edge_pts[3], new_face_pt, new_edge_pts[0], prim_pts_idx[0]);
64 | addprim(0, "poly", new_edge_pts[1], new_face_pt, new_edge_pts[0], prim_pts_idx[1]);
65 | addprim(0, "poly", new_edge_pts[1], new_face_pt, new_edge_pts[2], prim_pts_idx[2]);
66 | addprim(0, "poly", new_edge_pts[3], new_face_pt, new_edge_pts[2], prim_pts_idx[3]);
67 | }
68 | }
69 |
70 | // returns point number of a vertex in a primitive
71 | // primnum - primitive containing a vertex
72 | // vertexnum - vertex number (relative to the primitive, starting at 0)
73 | function int vertexprimpoint(int geo, primnum, vertexnum)
74 | {
75 | return vertexpoint(geo, vertexindex(geo, primnum, vertexnum) );
76 | }
77 |
78 | // a struct containing weights and parameters - to be used for transferring all the weights into functions
79 | struct quad_face_split_parms
80 | {
81 | float face_weights[] = {1.0, 1.0, 1.0, 1.0};
82 | float face_weight_offset = 0.0;
83 | float edge_weights[] = {1.0, 1.0};
84 | float edge_weight_offset = 0.0;
85 | int ordering_mode = 0;
86 | }
87 |
88 | // basic quad subdivision
89 | function void quad_face_split(int primnum; quad_face_split_parms weights)
90 | {
91 | ////// face point
92 |
93 | // find pints in a primitive
94 | int prim_pts_idx[] = primpoints(0, primnum);
95 | vector new_face_P = {0, 0, 0};
96 |
97 | // interpolate attribute
98 | for (int i = 0; i < len(prim_pts_idx); i++)
99 | {
100 | new_face_P += vector(point(0, "P", prim_pts_idx[i])) * weights.face_weights[i];
101 | }
102 |
103 | new_face_P /= sum(weights.face_weights) + weights.face_weight_offset;
104 |
105 | // add new point
106 | int new_face_pt = addpoint(0, new_face_P);
107 |
108 | ////// edge points
109 |
110 | vector2 edge_vertices[] = array( {0, 1}, {1, 2}, {2, 3}, {3, 0} );
111 | int new_edge_pts[];
112 |
113 | foreach (vector2 edge; edge_vertices)
114 | {
115 | // get point numbers of vertices in the edge
116 | int pt_1 = vertexprimpoint(0, primnum, (int)edge[0]);
117 | int pt_2 = vertexprimpoint(0, primnum, (int)edge[1]);
118 |
119 | // interpolate attribute
120 | vector pt_1_P = point(0, "P", pt_1);
121 | vector pt_2_P = point(0, "P", pt_2);
122 |
123 | vector new_edge_P = pt_1_P * weights.edge_weights[0] + pt_2_P * weights.edge_weights[1];
124 | new_edge_P /= sum(weights.edge_weights) + weights.edge_weight_offset;
125 |
126 | // add new point
127 | append(new_edge_pts, addpoint(0, new_edge_P));
128 | }
129 |
130 | ////// construct primitives
131 | construct_primitives(prim_pts_idx, new_edge_pts, new_face_pt, weights.ordering_mode, primnum);
132 | }
133 |
134 | struct catmull_clark_quad_parms
135 | {
136 | float new_face_pt_weights[] = {1.0, 1.0, 1.0, 1.0};
137 | float new_face_pt_weights_offset = 0.0;
138 | float new_edge_pt_weights[] = {6.0, 6.0, 1.0, 1.0, 1.0, 1.0};
139 | float new_edge_pt_weights_offset = 0.0;
140 | float pt_3_pt_weights[] = {15.0, 6.0, 6.0, 6.0, 1.0, 1.0, 1.0};
141 | float pt_3_pt_weights_offset = 0.0;
142 | float pt_4_pt_weights[] = {36.0, 6.0, 6.0, 6.0, 6.0, 1.0, 1.0, 1.0, 1.0};
143 | float pt_4_pt_weights_offset = 0.0;
144 | float pt_5_pt_weights[] = {65.0, 6.0, 6.0, 6.0, 6.0, 6.0, 1.0, 1.0, 1.0, 1.0, 1.0};
145 | float pt_5_pt_weights_offset = 0.0;
146 |
147 | int ordering_mode = 0;
148 | }
149 |
150 | // catmull clark subdivision on quad meshes
151 | function void catmull_clark_quad(int primnum; catmull_clark_quad_parms weights)
152 | {
153 | ////// face point
154 |
155 | // find pints in a primitive
156 | int prim_pts_idx[] = primpoints(0, primnum);
157 | vector new_face_P = {0, 0, 0};
158 |
159 | // interpolate attribute
160 | for (int i = 0; i < len(prim_pts_idx); i++)
161 | {
162 | new_face_P += vector(point(0, "P", prim_pts_idx[i])) * weights.new_face_pt_weights[i];
163 | }
164 |
165 | new_face_P /= sum(weights.new_face_pt_weights) + weights.new_face_pt_weights_offset;
166 |
167 | // add new point
168 | int new_face_pt = addpoint(0, new_face_P);
169 |
170 | ////// edge points
171 |
172 | vector2 edge_vertices[] = array( {0, 1}, {1, 2}, {2, 3}, {3, 0} );
173 | int new_edge_pts[];
174 |
175 | foreach (vector2 edge; edge_vertices)
176 | {
177 | // get point numbers of vertices in the edge
178 | int pt_1 = vertexprimpoint(0, primnum, (int)edge[0]);
179 | int pt_2 = vertexprimpoint(0, primnum, (int)edge[1]);
180 |
181 | // find all primitives that contain the two points
182 | int prims_1[] = pointprims(0, pt_1);
183 | int prims_2[] = pointprims(0, pt_2);
184 | int prims_shared[];
185 |
186 | // find shared primitives
187 | foreach (int pt_prim; prims_1)
188 | {
189 | int found_idx = find(prims_2, pt_prim);
190 | if (found_idx >= 0)
191 | append(prims_shared, pt_prim);
192 | }
193 |
194 | if (len(prims_shared) > 2)
195 | warning("Edge | Found more than two shared primitives");
196 |
197 | // if edge is shared between two primitives
198 | if (len(prims_shared) == 2)
199 | {
200 | int edge_prims_pts[];
201 | append(edge_prims_pts, primpoints(0, prims_shared[0]));
202 | append(edge_prims_pts, primpoints(0, prims_shared[1]));
203 |
204 | removevalue(edge_prims_pts, pt_1);
205 | removevalue(edge_prims_pts, pt_1);
206 | removevalue(edge_prims_pts, pt_2);
207 | removevalue(edge_prims_pts, pt_2);
208 | edge_prims_pts = sort(edge_prims_pts);
209 |
210 | if (len(edge_prims_pts) != 4)
211 | warning("Edge | There are not 4 unshared points between two primitives");
212 |
213 | int influence_pt_nums[];
214 | append(influence_pt_nums, sort(array(pt_1, pt_2)));
215 | append(influence_pt_nums, edge_prims_pts);
216 |
217 | if (len(influence_pt_nums) != 6)
218 | warning("Edge | Length of array with influencing points is not 6");
219 |
220 | vector new_edge_P = {0, 0, 0};
221 |
222 | // interpolate attribute
223 | for (int i = 0; i < 6; i++)
224 | {
225 | new_edge_P += vector(point(0, "P", influence_pt_nums[i])) * weights.new_edge_pt_weights[i];
226 | }
227 |
228 | new_edge_P /= sum(weights.new_edge_pt_weights) + weights.new_edge_pt_weights_offset;
229 |
230 | // add new point
231 | append(new_edge_pts, addpoint(0, new_edge_P));
232 | }
233 |
234 | // if edge is not shared between primitives
235 | else if (len(prims_shared) == 1)
236 | {
237 | // interpolate attribute
238 | vector pt_1_P = point(0, "P", pt_1);
239 | vector pt_2_P = point(0, "P", pt_2);
240 |
241 | vector new_edge_P = pt_1_P * weights.new_edge_pt_weights[0] + pt_2_P * weights.new_edge_pt_weights[1];
242 | new_edge_P /= weights.new_edge_pt_weights[0] + weights.new_edge_pt_weights[1] + weights.new_edge_pt_weights_offset;
243 |
244 | // add new point
245 | append(new_edge_pts, addpoint(0, new_edge_P));
246 | }
247 | }
248 |
249 | ////// construct primitives
250 |
251 | construct_primitives(prim_pts_idx, new_edge_pts, new_face_pt, weights.ordering_mode, primnum);
252 |
253 | ////// original vertices
254 |
255 | foreach (int prim_pt; prim_pts_idx)
256 | {
257 | int prim_pt_prims[] = sort(pointprims(0, prim_pt));
258 |
259 | // only distort vertex if the current primitive has the highest number of primitives that belong to the vertex - to avoid duplicate translations
260 | if (primnum == prim_pt_prims[-1])
261 | {
262 | int influence_pt_nums[];
263 | append(influence_pt_nums, prim_pt); // myself
264 |
265 | int prim_pt_neigbors[] = sort(neighbours(0, prim_pt));
266 | append(influence_pt_nums, prim_pt_neigbors); // neighbors
267 | int prim_pt_valence = len(prim_pt_neigbors);
268 |
269 | int prim_pt_distant_neighbors[];
270 |
271 | foreach(int prim_pt_prim; prim_pt_prims) // for each primitive that belongs to iterated point
272 | {
273 | int prim_pt_prim_pts[] = primpoints(0, prim_pt_prim);
274 |
275 | removevalue(prim_pt_prim_pts, prim_pt); // remove itself
276 |
277 | foreach (int prim_pt_neigbor; prim_pt_neigbors)
278 | {
279 | removevalue(prim_pt_prim_pts, prim_pt_neigbor); // remove neighbors
280 | }
281 |
282 | if (len(prim_pt_prim_pts) != 1)
283 | warning("Original vertex | After removing center and neighbor vertices, there is not exactly one point left");
284 |
285 | append(influence_pt_nums, prim_pt_prim_pts[0]); // distant neighbors
286 | }
287 |
288 | vector new_orig_vertex_P = {0, 0, 0};
289 |
290 | //if (prim_pt_valence > 5)
291 | // error("Original vertex | Subdivision is supported only for geometry with points of maximum valence 5");
292 |
293 | // interpolate attribute
294 | int neighbor_counter = 0;
295 | foreach (int influence_pt_num; influence_pt_nums)
296 | {
297 | if (prim_pt_valence == 3)
298 | {
299 | new_orig_vertex_P += vector(point(0, "P", influence_pt_num)) * weights.pt_3_pt_weights[neighbor_counter];
300 | }
301 | else if (prim_pt_valence == 4)
302 | {
303 | new_orig_vertex_P += vector(point(0, "P", influence_pt_num)) * weights.pt_4_pt_weights[neighbor_counter];
304 | }
305 | else if (prim_pt_valence == 5)
306 | {
307 | new_orig_vertex_P += vector(point(0, "P", influence_pt_num)) * weights.pt_5_pt_weights[neighbor_counter];
308 | }
309 |
310 | neighbor_counter++;
311 | }
312 |
313 | if (prim_pt_valence == 3)
314 | new_orig_vertex_P /= sum(weights.pt_3_pt_weights) + weights.pt_3_pt_weights_offset;
315 | else if (prim_pt_valence == 4)
316 | new_orig_vertex_P /= sum(weights.pt_4_pt_weights) + weights.pt_4_pt_weights_offset;
317 | else if (prim_pt_valence == 5)
318 | new_orig_vertex_P /= sum(weights.pt_5_pt_weights) + weights.pt_5_pt_weights_offset;
319 |
320 | // translate
321 | if (prim_pt_valence >= 3)
322 | setpointattrib(0, "P", prim_pt, new_orig_vertex_P, "set");
323 | }
324 | }
325 | }
326 |
327 | #endif
328 |
--------------------------------------------------------------------------------
/houdini/python2.7libs/vft_hou.py:
--------------------------------------------------------------------------------
1 | """
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | """
11 |
12 | import hou
13 | import toolutils
14 | import os
15 | import logging
16 | import time
17 |
18 | """
19 | todo
20 | * pass parameters as attributes, to reduce overhead of kernel re-compilation
21 | * pass in arbitrary combination of hybrids, primitives and boolean-combine them
22 | """
23 |
24 | # logging config
25 | logging.basicConfig(level=logging.DEBUG) # set to logging.INFO to disable DEBUG logs
26 | log = logging.getLogger(__name__)
27 |
28 | class NodeUtils(object):
29 | """
30 | set of methods operating on Houdini nodes
31 | """
32 | @staticmethod
33 | def getInputFractalNodes(root):
34 | """
35 | returns list of fractal nodes that are connected (upstream) to root node
36 | """
37 | # node type names of all fractal nodes
38 | fractals_nodes = set( ["vft_bristorbrotIter", "vft_mandelbulbPower2Iter", "vft_mengerSpongeIter"] )
39 |
40 | all_input_nodes = root.inputAncestors()
41 | input_fractal_nodes = []
42 |
43 | # find fractal nodes in all input nodes
44 | for node in all_input_nodes:
45 | if node.type().name() in fractals_nodes:
46 | input_fractal_nodes.append(node)
47 |
48 | return input_fractal_nodes
49 |
50 | @staticmethod
51 | def getOutputNodeByTypeName(start_node, type_name=""):
52 | """
53 | returns a connected node (downstream) which belongs to "vft generator" list
54 | """
55 | all_children_nodes = NodeUtils.outputChildren(start_node)
56 | out = None
57 |
58 | for node in all_children_nodes:
59 | if node.type().name() == type_name:
60 | out = node
61 | break
62 |
63 | return out
64 |
65 | @staticmethod
66 | def outputChildren(node):
67 | """
68 | find all descending connected (downstream) nodes
69 | """
70 | children = list( node.outputs() )
71 | for node in children:
72 | new_children = node.outputs()
73 | if len(new_children) == 0:
74 | break
75 | else:
76 | for child in new_children:
77 | children.append( child )
78 | NodeUtils.outputChildren(child)
79 |
80 | return children
81 |
82 | @staticmethod
83 | def fillKernelCodePythonSop():
84 | """
85 | this func will do all the parsing and will set up the kernel parm in descendant opencl node
86 | """
87 | start_time = time.time()
88 | me = hou.pwd()
89 | geo = me.geometry()
90 | kernels_parm = me.parm("vft_kernels")
91 |
92 | # find a opencl downstream node
93 | cl_node = NodeUtils.getOutputNodeByTypeName(me, "opencl")
94 |
95 | # init a GenerateKernel object and init member var vft_kernels
96 | kernel = GenerateKernel()
97 | kernel.loadKernelsFileFromParm(kernels_parm)
98 |
99 | # get set of incoming fractals
100 | detail_attribs = geo.globalAttribs()
101 |
102 | # do the parsing
103 | kernel.parseKernelsFile(detail_attribs)
104 |
105 | # set vft_kernels_parsed to kernelcode parm in an opencl node if has changed
106 | cl_node_parm = cl_node.parm("kernelcode")
107 | old_cl_code = cl_node_parm.eval()
108 |
109 | if old_cl_code != kernel.vft_kernels_parsed:
110 | cl_node_parm.set(kernel.vft_kernels_parsed)
111 | log.debug("Kernel in OpenCL node updated")
112 | else:
113 | log.debug("Kernel in OpenCL is up to date")
114 |
115 | log.debug("Python SOP evaluated in {0:.8f} seconds \n\n".format( time.time() - start_time ))
116 |
117 | class GenerateKernel(object):
118 | """
119 | class that will generate fractal generation CL code that Houdini will read from a string parameter and will execute
120 | """
121 | def __init__(self):
122 | self.vft_root_path = self.getVftRootFromPath( hou.getenv("HOUDINI_PATH") )
123 | self.vft_kernels_path = os.path.join(self.vft_root_path, "ocl/vft_kernels.cl")
124 |
125 | self.vft_kernels = None
126 | self.vft_kernels_parsed = None
127 |
128 | def clStatementsToString(self, statements):
129 | """
130 | helper func
131 | """
132 | return ";\n".join(statements) + ";\n"
133 |
134 | def getVftRootFromPath(self, path):
135 | """
136 | this might not work on Windows
137 | extracts path to VFT from os-style paths string
138 | """
139 | paths = path.replace(";",":").split(":")
140 |
141 | # this will need to be changed if git repository name changes
142 | pattern = os.sep + "raymarching" + os.sep + "houdini"
143 |
144 | # find pattern in list of paths
145 | vft_root = ""
146 | for path in paths:
147 | if pattern in path:
148 | vft_root = path
149 | break
150 |
151 | return vft_root
152 |
153 | def loadKernelsFileToMemberVar(self):
154 | """
155 | loads vft_kernels.cl file into member variable
156 | """
157 | start_time = time.time()
158 | with open(self.vft_kernels_path, 'r') as file:
159 | self.vft_kernels = file.read()
160 |
161 |
162 | log.debug("Kernels file loaded from disk in {0:.8f} seconds".format( time.time() - start_time ))
163 |
164 | def loadKernelsFileToParm(self, parm):
165 | """
166 | loads vft_kernels.cl into specified parm object (which should be string) - this function should be called by a button for (re)loading a parm
167 | """
168 | if self.vft_kernels == None:
169 | self.loadKernelsFileToMemberVar()
170 |
171 | parm.set(self.vft_kernels)
172 |
173 | def loadKernelsFileFromParm(self, parm):
174 | """
175 | loads vft_kernels.cl into member var - either from disk, or parm (if it is loaded there already)
176 | """
177 | if parm.eval() == "":
178 | log.debug("Loading member var from file")
179 | self.loadKernelsFileToMemberVar()
180 | else:
181 | log.debug("Loading member var from node parameter")
182 | self.vft_kernels = parm.eval()
183 |
184 | def parseKernelsFile(self, attribs):
185 | """
186 | parses vft_kernels.cl file and replaces PY_* macros and saves it into member varible
187 | """
188 | start_time = time.time()
189 | self.vft_kernels_parsed = self.vft_kernels
190 |
191 | attribs_dict = {}
192 | for attr in attribs:
193 | attribs_dict[ attr.name() ] = attr.strings()
194 |
195 | # generate fractal stack
196 | fractal_stack_token = "#define PY_FRACTAL_STACK"
197 |
198 | fractal_stack_cl_code = ""
199 | try:
200 | fractal_stack_cl_code = self.clStatementsToString( self.generateClFractalStack(attribs_dict["fractal_stack"]) )
201 | except KeyError:
202 | pass
203 | log.error('No "fractal_stack" attribute found, probably missing input')
204 |
205 | fractal_stack_cl_code = fractal_stack_token + "\n\n" + fractal_stack_cl_code
206 |
207 | # generate pre-transform stack
208 | allowed_pre_transforms = ["curlNoise", "translateIter", "tgladFoldIter", "fabsFoldIter", "boxFoldIter", "rotationIter", "preScaleIter"]
209 | pre_transform_stack_token = "#define PY_PRE_TRANSFORM_STACK"
210 |
211 | pre_transform_stack_cl_code = ""
212 | try:
213 | pre_transform_stack_cl_code = self.clStatementsToString( self.generateClFractalStack(attribs_dict["pre-transform_stack"], valid_list=allowed_pre_transforms) )
214 | except KeyError:
215 | pass
216 | log.debug('No "pre-transform_stack" attribute found, probably missing input')
217 |
218 | pre_transform_stack_cl_code = pre_transform_stack_token + "\n\n" + pre_transform_stack_cl_code
219 |
220 |
221 | self.vft_kernels_parsed = self.vft_kernels_parsed.replace(fractal_stack_token, fractal_stack_cl_code)
222 | self.vft_kernels_parsed = self.vft_kernels_parsed.replace(pre_transform_stack_token, pre_transform_stack_cl_code)
223 |
224 | log.debug("Kernels file parsed in {0:.8f} seconds".format( time.time() - start_time ))
225 |
226 | def generateClFractalStack(self, fractal_attribs, valid_list=None):
227 | """
228 | returns a list of CL statements with fractal function calls from a list of fractal nodes
229 | """
230 |
231 | # a dictionary mapping strings of arguments to OpenCL fractal function names
232 | args_dict = {
233 | "default" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f))",
234 | "mandelboxIter" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f), {obj.parms[scale]:.6f}f)",
235 | "mengerSpongeIter" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f), {obj.parms[modulus]:.0f})",
236 | "mandelbulbIter" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f), {obj.parms[power]:.6f}f)",
237 | "xenodreambuieIter" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f), {obj.parms[power]:.6f}f, {obj.parms[alpha]:.6f}f, {obj.parms[beta]:.6f}f)",
238 | "sierpinski3dIter" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f), {obj.parms[scale]:.6f}f, (float3)({obj.parms[offsetx]:.6f}f, {obj.parms[offsety]:.6f}f, {obj.parms[offsetz]:.6f}f), (float3)({obj.parms[rotx]:.6f}f, {obj.parms[roty]:.6f}f, {obj.parms[rotz]:.6f}f))",
239 | "mengerSmoothIter" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f), {obj.parms[scale]:.6f}f, {obj.parms[offset_s]:.6f}f, (float3)({obj.parms[offset_cx]:.6f}f, {obj.parms[offset_cy]:.6f}f, {obj.parms[offset_cz]:.6f}f), (float3)({obj.parms[rotx]:.6f}f, {obj.parms[roty]:.6f}f, {obj.parms[rotz]:.6f}f))",
240 | "amazingSurfIter" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f), {obj.parms[foldx]:.6f}f, {obj.parms[foldy]:.6f}f, {obj.parms[force_cylindrical_fold]:.0f}, {obj.parms[min_radius]:.6f}f, {obj.parms[scale]:.6f}f, {obj.parms[scale_fold_influence]:.6f}f, (float3)({obj.parms[rotx]:.6f}f, {obj.parms[roty]:.6f}f, {obj.parms[rotz]:.6f}f), {obj.parms[multiply_c]:.0f}, (float3)({obj.parms[c_multiplierx]:.6f}f, {obj.parms[c_multipliery]:.6f}f, {obj.parms[c_multiplierz]:.6f}f))",
241 | "mandelbulb4Iter" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f), {obj.parms[power]:.6f}f, (float3)({obj.parms[anglesx]:.6f}f, {obj.parms[anglesy]:.6f}f, {obj.parms[anglesz]:.6f}f))",
242 | "idesIter" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f), (float3)({obj.parms[multiplierx]:.6f}f, {obj.parms[multipliery]:.6f}f, {obj.parms[multiplierz]:.6f}f), (float2)({obj.parms[sub_multiplierx]:.6f}f, {obj.parms[sub_multipliery]:.6f}f))",
243 | "ides2Iter" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f), (float3)({obj.parms[multiplierx]:.6f}f, {obj.parms[multipliery]:.6f}f, {obj.parms[multiplierz]:.6f}f), (float2)({obj.parms[sub_multiplierx]:.6f}f, {obj.parms[sub_multipliery]:.6f}f))",
244 | "iqBulbIter" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f), {obj.parms[power]:.6f}f, {obj.parms[zpower]:.6f}f)",
245 | "quaternion3dIter" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f), (float3)({obj.parms[scalex]:.6f}f, {obj.parms[scaley]:.6f}f, {obj.parms[scalez]:.6f}f), (float3)({obj.parms[offsetx]:.6f}f, {obj.parms[offsety]:.6f}f, {obj.parms[offsetz]:.6f}f), (float3)({obj.parms[rotx]:.6f}f, {obj.parms[roty]:.6f}f, {obj.parms[rotz]:.6f}f), {obj.parms[de_influence]:.6f}f)",
246 | "josKleinianIter" : "{obj.cl_function_name}(Z, de, P_in, log_lin, {obj.parms[weight]:.6f}f, (float4)({obj.parms[julia_mode]:.1f}f, {obj.parms[juliax]:.6f}f, {obj.parms[juliay]:.6f}f, {obj.parms[juliaz]:.6f}f), {obj.parms[r]:.6f}f, {obj.parms[l]:.6f}f, (float3)({obj.parms[box_sizex]:.6f}f, {obj.parms[box_sizey]:.6f}f, {obj.parms[box_sizez]:.6f}f))",
247 | "rotationIter" : "{obj.cl_function_name}(Z, (float3)({obj.parms[rotx]:.6f}f, {obj.parms[roty]:.6f}f, {obj.parms[rotz]:.6f}f))",
248 | "boxFoldIter" : "{obj.cl_function_name}(Z, (int3)({obj.parms[axis_enablex]:.0f}, {obj.parms[axis_enabley]:.0f}, {obj.parms[axis_enablez]:.0f}), {obj.parms[folding_limit]:.6f}f, {obj.parms[folding_value]:.6f}f, {obj.parms[z_scale]:.6f}f)",
249 | "fabsFoldIter" : "{obj.cl_function_name}(Z, (int3)({obj.parms[axis_enablex]:.0f}, {obj.parms[axis_enabley]:.0f}, {obj.parms[axis_enablez]:.0f}), (float3)({obj.parms[offsetx]:.6f}f, {obj.parms[offsety]:.6f}f, {obj.parms[offsetz]:.6f}f))",
250 | "tgladFoldIter" : "{obj.cl_function_name}(Z, (int3)({obj.parms[axis_enablex]:.0f}, {obj.parms[axis_enabley]:.0f}, {obj.parms[axis_enablez]:.0f}), (float3)({obj.parms[offsetx]:.6f}f, {obj.parms[offsety]:.6f}f, {obj.parms[offsetz]:.6f}f))",
251 | "scaleIter" : "{obj.cl_function_name}(Z, de, (float3)({obj.parms[scalex]:.6f}f, {obj.parms[scaley]:.6f}f, {obj.parms[scalez]:.6f}f))",
252 | "translateIter" : "{obj.cl_function_name}(Z, (float3)({obj.parms[translatex]:.6f}f, {obj.parms[translatey]:.6f}f, {obj.parms[translatez]:.6f}f))",
253 | "addCOffsetIter" : "{obj.cl_function_name}(Z, P_in, (float3)({obj.parms[offsetx]:.6f}f, {obj.parms[offsety]:.6f}f, {obj.parms[offsetz]:.6f}f))",
254 | "curlNoise" : "{obj.cl_function_name}(theXNoise, Z, (float4)({obj.parms[frequencyx]:.6f}f, {obj.parms[frequencyy]:.6f}f, {obj.parms[frequencyz]:.6f}f, {obj.parms[frequencyw]:.6f}f), (float4)({obj.parms[offsetx]:.6f}f, {obj.parms[offsety]:.6f}f, {obj.parms[offsetz]:.6f}f, {obj.parms[offsetw]:.6f}f), (float3)({obj.parms[amplitudex]:.6f}f, {obj.parms[amplitudey]:.6f}f, {obj.parms[amplitudez]:.6f}f))",
255 | "preScaleIter" : "{obj.cl_function_name}(Z, (float3)({obj.parms[scalex]:.6f}f, {obj.parms[scaley]:.6f}f, {obj.parms[scalez]:.6f}f))"
256 | }
257 |
258 | def args_format(args_dict, obj):
259 | """
260 | if a function has some custom arguments, then their formatting is specified here
261 | """
262 | if obj.cl_function_name in args_dict:
263 |
264 | # this line is picking a string to be formatted from args_dict dictionary
265 | string = args_dict[obj.cl_function_name]
266 | string = string.format( obj=obj )
267 |
268 | # if function has not arguments mapping in args_dict, then it is considered to use default one
269 | else:
270 | string = args_dict["default"]
271 | string = string.format( obj=obj )
272 |
273 | return string
274 |
275 | fractal_objects = []
276 | for attrib in fractal_attribs:
277 | obj = FractalObject()
278 | obj.attribToVars(attrib)
279 |
280 | if valid_list:
281 | if obj.cl_function_name in valid_list:
282 | fractal_objects.append(obj)
283 | else:
284 | fractal_objects.append(obj)
285 |
286 | # list which will hold CL fractal funcs calls
287 | stack = []
288 |
289 | for obj in fractal_objects:
290 | statement = args_format(args_dict, obj)
291 | log.debug(statement)
292 | stack.append(statement)
293 |
294 | return stack
295 |
296 | class FractalObject(object):
297 | """
298 | a class that will hold data and functionality for getting fractal data from detail attribute
299 | """
300 | def __init__(self):
301 | # init member vars
302 | self.asset_name = None
303 | self.parent_name = None
304 | self.parent_path = None
305 | self.cl_function_name = None
306 | self.parms = {
307 | "weight" : 1.0,
308 | "julia_mode" : 0,
309 | "juliax" : 0.0,
310 | "juliay" : 0.0,
311 | "juliaz" : 0.0
312 | }
313 |
314 | def attribToVars(self, attrib):
315 | """
316 | this will parse attribute string and will set member vars from it
317 | """
318 | attrib_list = attrib.split("|")
319 |
320 | self.asset_name = attrib_list[0]
321 | self.parent_name = attrib_list[1]
322 | self.parent_path = attrib_list[2]
323 |
324 | self.cl_function_name = self.asset_name.split("_")[-1]
325 |
326 | parms_string = attrib_list[3]
327 | parms_list = parms_string.split(",")
328 |
329 | for item in parms_list:
330 | item_split = item.split(":")
331 | self.parms[ item_split[0] ] = float(item_split[1])
332 |
333 | def nodeToVars(self):
334 | """
335 | this will fill in member vars based on a node, it should be used inside of a fractal node
336 | """
337 | node = hou.pwd()
338 |
339 | self.asset_name = node.parent().type().name()
340 | self.parent_name = node.parent().name()
341 | self.parent_path = node.parent().path()
342 |
343 | parms = node.parent().parms()
344 | for parm in parms:
345 | if parm.parmTemplate().type() != hou.parmTemplateType.Label:
346 | self.parms[ parm.name() ] = parm.eval()
347 |
348 | def varsToAttrib(self):
349 | """
350 | this will serialize member vars into a string, which should be stored in detail attribute
351 | """
352 | parms_string = ""
353 |
354 | for key, value in self.parms.iteritems():
355 | parms_string += key + ":" + "{0:.6f}".format(value) + ","
356 | parms_string = parms_string[:-1] # remove the last comma
357 |
358 | attrib = "|".join( [self.asset_name, self.parent_name, self.parent_path, parms_string] )
359 | return attrib
360 |
361 | class FpsCam(object):
362 | """
363 | Set of functions helping with FPS/Flying camera orientation in scenes.
364 | """
365 | pass
--------------------------------------------------------------------------------
/houdini/ocl/vft_kernels.cl:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #include "xnoise.h"
13 | #include "vft_defines.h"
14 | #include "vft_utils.h"
15 | #include "vft_math.h"
16 | #include "vft_fractals.h"
17 | #include "vft_shading.h"
18 |
19 | // contains primitives
20 | float primitive_stack(float3 P, const int stack)
21 | {
22 | float out_distance;
23 | switch (stack)
24 | {
25 | case 0:
26 | {
27 | out_distance = sphere(P, 1.0f);
28 |
29 | break;
30 | }
31 | case 1:
32 | {
33 | out_distance = torus(P, (float2)(1.0f, 0.5f));
34 |
35 | break;
36 | }
37 | }
38 |
39 | return out_distance;
40 | }
41 |
42 | void pre_transform_stack(float3* Z, global const void* theXNoise)
43 | {
44 | #define PY_PRE_TRANSFORM_STACK
45 | }
46 |
47 | // contains fractal combinations for all shapes
48 | void fractal_stack(float3* Z, float* de, const float3* P_in, int* log_lin, const int stack, global const void* theXNoise)
49 | {
50 | switch (stack)
51 | {
52 | case 0:
53 | {
54 | iqBulbIter(Z, de, P_in, log_lin, 1.0f, (float4)(0.0f, 0.0f, 0.0f, 0.0f), 8.0f, 8.0f);
55 | //idesIter(Z, de, P_in, log_lin, 1.0f, (float4)(0.0f, 0.0f, 0.0f, 0.0f), (float3)(1.0f, 2.0f, 1.0f), (float2)(0.5f, 0.5f));
56 | //benesiIter(Z, de, P_in, log_lin, 1.0f, (float4)(0.0f, 0.0f, 0.0f, 0.0f));
57 | //hypercomplexIter(Z, de, P_in, log_lin, 1.0f, (float4)(0.0f, 0.0f, 0.0f, 0.0f));
58 | //josKleinianIter(Z, de, P_in, log_lin, 1.0f, (float4)(0.0f, 1.0f, 1.0f, 3.0f), 2.0f, 0.0f, (float3)(1.0f, 1.0f, 1.0f));
59 | //amazingSurfIter(Z, de, P_in, log_lin, 1.0f, (float4)(1.0f, 0.0f, 0.0f, 0.0f), 1.0f, 1.0f, 0, 0.5f, 2.0f, 1.0f, (float3)(0.0f, 0.0f, 0.0f), 1, (float3)(1.0f, 1.0f, 1.0f));
60 | //mandelbulbPower2Iter(Z, de, P_in, log_lin, 1.0f, (float4)(1.0f, 0.3f, 0.5f, 0.2f)); // log
61 | //bristorbrotIter(Z, de, P_in, log_lin, 1.0f, (float4)(0.0f, 1.3f, 3.3f, 0.0f)); // log
62 | //xenodreambuieIter(Z, de, P_in, log_lin, 1.0f, (float4)(1.0f, 1.0f, 0.0f, 0.0f), 9.0f, 0.0f, 0.0f); // log
63 | //mandelboxIter(Z, de, P_in, log_lin, 1.0f, (float4)(0.0f, 1.0f, 3.0f, 4.0f), 3.1f); // lin
64 | //mandelbulbIter(Z, de, P_in, log_lin, 1.0f, (float4)(0.0f, 1.0f, 0.0f, 0.0f), 8.0f); // log
65 | //mengerSpongeIter(Z, de, P_in, log_lin, 1.0f, (float4)(0.0f, 0.0f, 1.0f, 0.0f)); // lin
66 | //sierpinski3dIter(Z, de, P_in, log_lin, 1.0f, (float4)(0.0f, 0.0f, 0.0f, 0.5f), 2.0f, (float3)(1.0f, 1.0f, 1.0f), (float3)(0.0f, 0.0f, 0.0f) ); // lin
67 |
68 | break;
69 | }
70 |
71 | case 1:
72 | {
73 | sierpinski3dIter(Z, de, P_in, log_lin, 1.0f, (float4)(0.0f, 0.0f, 0.0f, 0.5f), 2.0f, (float3)(1.0f, 1.0f, 1.0f), (float3)(0.0f, 0.0f, 0.0f) ); // lin
74 |
75 | break;
76 | }
77 |
78 | case 2:
79 | {
80 | mandelbulbPower2Iter(Z, de, P_in, log_lin, 1.0f, (float4)(1.0f, 0.3f, 0.5f, 0.2f)); // log
81 |
82 | break;
83 | }
84 | case 3:
85 | {
86 | #define PY_FRACTAL_STACK
87 |
88 | break;
89 | }
90 | }
91 | }
92 |
93 | // scene setup - setting of coordinates and shapes in them
94 |
95 | // scene with multiple unions of prims and fractals
96 | /*float scene( float3 P, const int final, float* orbit_colors, float3* N ) {
97 | float dist_out;
98 | float orbit_closest = LARGE_NUMBER;
99 |
100 | float shape1 = hybrid(P, 10, 10.0f, 1.0f, final, &orbit_closest, orbit_colors, N, 0);
101 | float shape2 = hybrid(P - (float3)(2.0f), 10, 10.0f, 1.0f, final, &orbit_closest, orbit_colors, N, 1);
102 | float shape3 = hybrid(P + (float3)(2.0f), 10, 10.0f, 1.0f, final, &orbit_closest, orbit_colors, N, 2);
103 |
104 | float shape4 = primitive(P - (float3)(2.0f, 0.0f, 0.0f), 0.3f, final, &orbit_closest, orbit_colors, (float3)(1.0f,0.0f,1.0f), N, 0);
105 | float shape5 = primitive(P - (float3)(-2.0f, 0.0f, 0.0f), 0.6f, final, &orbit_closest, orbit_colors, (float3)(1.0f,1.0f,0.0f), N, 1);
106 |
107 | dist_out = sdfUnion( sdfUnion( sdfUnion( sdfUnion(shape1, shape2) , shape3 ) , shape4 ) , shape5 );
108 |
109 | return dist_out;
110 | }*/
111 |
112 | // scene showing unions and subtractions
113 | /*float scene( float3 P, const int final, float* orbit_colors, float3* N ) {
114 | float dist_out;
115 | float orbit_closest = LARGE_NUMBER;
116 |
117 | float shape1 = hybrid(P, 10, 10.0f, 1.0f, final, &orbit_closest, orbit_colors, N, 0);
118 | float shape2 = hybrid(P - (float3)(0.4f), 10, 10.0f, 1.0f, final, &orbit_closest, orbit_colors, N, 1);
119 | //float shape3 = hybrid(P - (float3)(-0.5f, 0.0f, 0.5f), 10, 10.0f, 1.0f, final, &orbit_closest, orbit_colors, N, 2);
120 |
121 | float shape4 = primitive(P - (float3)(0.7f, 0.0f, 0.0f), 1.0f, final, &orbit_closest, orbit_colors, (float3)(1.0f,0.0f,1.0f), N, 0);
122 |
123 | dist_out = sdfSubtract( sdfUnion(shape1, shape2) , shape4 );
124 |
125 | return dist_out;
126 | }*/
127 |
128 | float scene( float3 P, const int final, float* orbit_colors, float3* N, global const void* theXNoise ) {
129 | float dist_out;
130 | float orbit_closest = LARGE_NUMBER;
131 | int iterations = 0;
132 |
133 | pre_transform_stack(&P, theXNoise);
134 |
135 | float shape1 = hybrid(P, 25, 10.0f, 1.0f, final, &orbit_closest, orbit_colors, N, 3, theXNoise, &iterations);
136 |
137 | dist_out = shape1;
138 |
139 | return dist_out;
140 | }
141 |
142 | float scene_fog( float3 P, const int final, float* orbit_colors, float3* N, global const void* theXNoise, const int max_iter, const float max_dist ) {
143 | float dist_out;
144 | float orbit_closest = LARGE_NUMBER;
145 | int iterations = 0;
146 |
147 | pre_transform_stack(&P, theXNoise);
148 |
149 | float shape1 = hybrid(P, max_iter, max_dist, 1.0f, final, &orbit_closest, orbit_colors, N, 3, theXNoise, &iterations);
150 |
151 | dist_out = iterations == max_iter ? 1.0f : 0.0f;
152 |
153 | return dist_out;
154 | }
155 |
156 | kernel void marchPerspCam(
157 | global const void* theXNoise,
158 | int P_length, global float* P,
159 | int planeZ_length, global float* planeZ,
160 | int width_length, global float* width,
161 | int height_length, global float* height,
162 | int px_length, global float* px,
163 | int camXform_length, global float* camXform,
164 | int camPos_length, global float* camPos,
165 | int N_length, global float* N,
166 | int iRel_length, global float* iRel,
167 | int Cd_length, global float* Cd,
168 | int orbits_length, global int* orbits_index, global float* orbits
169 | )
170 | {
171 | // get current point id
172 | const long idx = get_global_id(0);
173 |
174 | // if current point is not valid, then end
175 | if ( idx >= P_length ) return;
176 |
177 | // read in P attrib
178 | const float3 pixel_P_origin = vload3(idx, P);
179 | float3 pixel_P_world = pixel_P_origin;
180 |
181 | //// transforming to near img plane
182 |
183 | // move to near img plane
184 | pixel_P_world.z = planeZ[0];
185 |
186 | // compute scale of near img plane
187 | const float16 near_plane_scale = mtxScale( (float3)(width[0]-px[0], height[0]-px[0], 1.0f) );
188 |
189 | // read in cam world matrix
190 | const float16 cam_xform_world = (float16)(camXform[0],camXform[1],camXform[2],camXform[3],
191 | camXform[4],camXform[5],camXform[6],camXform[7],
192 | camXform[8],camXform[9],camXform[10],camXform[11],
193 | camXform[12],camXform[13],camXform[14],camXform[15] );
194 |
195 | // create a mtx to hold transformations
196 | float16 near_plane_xform = mtxIdent();
197 |
198 | // apply transformations, also produce alternative matrix with scaled near plane
199 | near_plane_xform = mtxMult(near_plane_xform, near_plane_scale);
200 | float16 near_plane_xform_scaled = mtxMult(near_plane_xform, mtxScale( (float3)(10000000.0f) ) );
201 | near_plane_xform = mtxMult(near_plane_xform, cam_xform_world);
202 | near_plane_xform_scaled = mtxMult(near_plane_xform_scaled, cam_xform_world);
203 |
204 | // create a scaled near plane position for more accurate ray_dir calculation
205 | float3 pixel_P_world_scaled = mtxPtMult(near_plane_xform_scaled, pixel_P_world);
206 |
207 | // transform pixels into near img plane
208 | pixel_P_world = mtxPtMult(near_plane_xform, pixel_P_world);
209 |
210 | // get camera world space position and compute ray direction vector
211 | const float3 cam_P_world = (float3)(camPos[0], camPos[1], camPos[2]);
212 | const float3 ray_dir = NORMALIZE(pixel_P_world_scaled - cam_P_world);
213 |
214 | //// raymarching
215 |
216 | // raymarch settings, initialize variables
217 | float3 color = (float3)(0.0f);
218 | float AO = 1.0f;
219 | float orbit_colors[ORBITS_ARRAY_LENGTH];
220 | float3 Cd_out = (float3)(1.0f);
221 | float3 N_grad;
222 |
223 | float3 ray_P_world = pixel_P_world;
224 | float cam_dist = scene(cam_P_world, 0, NULL, NULL, theXNoise);
225 | float de = 0.0f;
226 | int i = 0;
227 |
228 | // quality settings
229 | float step_size = 0.35f;
230 | float iso_limit_mult = 0.5f;
231 | float ray_dist = planeZ[0];
232 | const int max_steps = 2500;
233 | const float max_dist = 1000.0f;
234 |
235 | float iso_limit = cam_dist * 0.0001f * iso_limit_mult;
236 |
237 | // raymarching loop
238 | #pragma unroll
239 | for (i=0; i= max_dist )
244 | {
245 | de = scene(ray_P_world, 1, orbit_colors, &N_grad, theXNoise) * step_size;
246 | break;
247 | }
248 |
249 | ray_dist += de;
250 | ray_P_world += ray_dir * de;
251 | }
252 |
253 | // relative amount of steps
254 | float i_rel = DIV((float)(i), (float)(max_steps));
255 | i_rel = 1.0f-POWR(i_rel, DIV(1.0f, 3.0f));
256 |
257 | // remove missed
258 | if ( de > iso_limit )
259 | {
260 | i_rel = -1.0f;
261 | }
262 | else
263 | {
264 | // compute N and AO only when not using DELTA DE mode
265 | #if !ENABLE_DELTA_DE
266 | N_grad = compute_N(&iso_limit, &ray_P_world, theXNoise);
267 | AO = compute_AO(&N_grad, &ray_P_world, theXNoise);
268 | #endif
269 |
270 | // output shading for viewport preview
271 | color.x = AO;
272 | color.y = orbit_colors[0];
273 | color.z = 1.0f;
274 |
275 | Cd_out = color;
276 | }
277 |
278 | // export attribs
279 | vstore3(ray_P_world, idx, P);
280 | vstore3(N_grad, idx, N);
281 | vstore3(Cd_out, idx, Cd);
282 | vstore1(i_rel, idx, iRel);
283 |
284 | long orbits_idx_start = orbits_index[idx];
285 | long orbits_idx_end = orbits_idx_start + ORBITS_ARRAY_LENGTH;
286 | #pragma unroll
287 | for (long j=orbits_idx_start; j= P_length ) return;
307 |
308 | // read in P, N attribs
309 | const float3 point_P_origin = vload3(idx, P);
310 | const float3 point_N = vload3(idx, N);
311 |
312 | //// raymarching
313 |
314 | // raymarch settings, initialize variables
315 | float3 color = (float3)(0.0f);
316 | float AO = 1.0f;
317 | float orbit_colors[ORBITS_ARRAY_LENGTH];
318 | float3 Cd_out = (float3)(1.0f);
319 | float3 N_grad;
320 |
321 | float3 ray_P_world = point_P_origin;
322 | float cam_dist = scene(point_P_origin, 0, NULL, NULL, theXNoise);
323 | float de = 0.0f;
324 | int i = 0;
325 |
326 | // quality settings
327 | float step_size = 0.9f;
328 | float iso_limit_mult = 0.4f;
329 | float ray_dist = 0.0f;
330 | const int max_steps = 150;
331 | const float max_dist = 100.0f;
332 |
333 | float iso_limit = cam_dist * 0.0001f * iso_limit_mult;
334 |
335 | // raymarching loop
336 | #pragma unroll
337 | for (i=0; i= max_dist )
342 | {
343 | de = scene(ray_P_world, 1, orbit_colors, &N_grad, theXNoise) * step_size;
344 | break;
345 | }
346 |
347 | ray_dist += de;
348 | ray_P_world += point_N * de;
349 | }
350 |
351 | // relative amount of steps
352 | float i_rel = DIV((float)(i), (float)(max_steps));
353 | i_rel = 1.0f-POWR(i_rel, DIV(1.0f, 3.0f));
354 |
355 | // remove missed
356 | if ( de > iso_limit )
357 | {
358 | i_rel = -1.0f;
359 | }
360 | else
361 | {
362 | // compute N and AO only when not using DELTA DE mode
363 | #if !ENABLE_DELTA_DE
364 | N_grad = compute_N(&iso_limit, &ray_P_world, theXNoise);
365 | AO = compute_AO(&N_grad, &ray_P_world, theXNoise);
366 | #endif
367 |
368 | // output shading for viewport preview
369 | color.x = AO;
370 | color.y = orbit_colors[0];
371 | color.z = 1.0f;
372 |
373 | Cd_out = color;
374 | }
375 |
376 | // export attribs
377 | vstore3(ray_P_world, idx, P);
378 | vstore3(N_grad, idx, N);
379 | vstore3(Cd_out, idx, Cd);
380 | vstore1(i_rel, idx, iRel);
381 |
382 | long orbits_idx_start = orbits_index[idx];
383 | long orbits_idx_end = orbits_idx_start + ORBITS_ARRAY_LENGTH;
384 | #pragma unroll
385 | for (long j=orbits_idx_start; j 50) taper_mtx[9] *= -1;
651 |
652 | //density_xformtoworld_inverted = mtxInvert(density_xformtoworld_inverted);
653 |
654 | //float3 P_taper = mtxPtMult(density_xformtoworld_inverted, P_vol);
655 | //P_taper = mtxPtMult(density_xformtoworld, P_taper);
656 | //P_taper = mtxPtMult(density_xformtoworld, P_taper);
657 |
658 | float3 P_world = mtxPtMult(taper_mtx, P_vol);
659 | //P_world = P_vol;
660 |
661 | float fog = 0.0f;
662 | //fog = scene_fog(P_world, 0, NULL, NULL, theXNoise, max_iter, max_dist);
663 | if ( LENGTH(P_world) < 30.6f ) fog = 1.0f;
664 |
665 | printMtxVol(taper_mtx);
666 |
667 | vstore1(fog, idx, density);
668 | }
669 |
670 | kernel void computePoints(
671 | global const void* theXNoise,
672 | int P_length,
673 | global float* P,
674 | int density_length,
675 | global float* density,
676 | float max_dist,
677 | int max_iter
678 | )
679 | {
680 | int idx = get_global_id(0);
681 | if (idx >= density_length)
682 | return;
683 |
684 | float3 P_world = vload3(idx, P);
685 |
686 | float fog = 0.0f;
687 | fog = scene_fog(P_world, 0, NULL, NULL, theXNoise, max_iter, max_dist);
688 |
689 | vstore1(fog, idx, density);
690 | }
691 |
692 | kernel void lorenzAttractor(
693 | int P_length,
694 | global float* P,
695 | int k_length,
696 | global int* k_index,
697 | global float* k
698 | )
699 | {
700 | int idx = get_global_id(0);
701 | if (idx >= P_length)
702 | return;
703 |
704 | }
705 |
--------------------------------------------------------------------------------
/houdini/ocl/include/vft_fractals.h:
--------------------------------------------------------------------------------
1 | /*
2 | -----------------------------------------------------------------------------
3 | This source file has been developed within the scope of the
4 | Technical Director course at Filmakademie Baden-Wuerttemberg.
5 | http://technicaldirector.de
6 |
7 | Written by Juraj Tomori.
8 | Copyright (c) 2019 Animationsinstitut of Filmakademie Baden-Wuerttemberg
9 | -----------------------------------------------------------------------------
10 | */
11 |
12 | #ifndef VFT_FRACTALS
13 | #define VFT_FRACTALS
14 |
15 | // mapping of variables
16 | // aux.r_dz -> de
17 | // aux.r -> distance
18 | // aux.de -> de
19 | // dr -> de
20 | // r -> distance
21 | // Bailout -> max_distance
22 | // Iterations -> max_iterations
23 | // positive log_lin -> log, negative -> lin
24 |
25 | // fractal formula sources:
26 | // [M2] - Mandelbulber v2
27 | // [M3D] - Mandelbulb 3D
28 | // [WEB] - From the web
29 |
30 | ////////////// primitives
31 | // [WEB] - http://iquilezles.org/www/articles/distfunctions/distfunctions.htm
32 |
33 | // sphere: position, radius
34 | static float sphere( float3 P, float rad )
35 | {
36 | float dist = LENGTH(P) - rad;
37 | return dist;
38 | }
39 |
40 | // box: position, size
41 | static float box( float3 P, float3 b )
42 | {
43 | float3 d = fabs(P) - b;
44 | return min( max( d.x, max(d.y, d.z) ), 0.0f) + LENGTH( max(d, 0.0f) );
45 | }
46 |
47 | // round box: position, size, roundness
48 | static float roundBox( float3 P, float3 b, float r )
49 | {
50 | return LENGTH( max( fabs(P) - b, 0.0f ) )-r;
51 | }
52 |
53 | // torus: position, size (radius, thickness)
54 | static float torus( float3 P, float2 t )
55 | {
56 | float2 q = (float2)(LENGTH(P.xz)-t.x,P.y);
57 | return LENGTH(q)-t.y;
58 | }
59 |
60 | // infinite cone
61 | static float cone( float3 P, float2 c )
62 | {
63 | c = NORMALIZE(c);
64 | float q = LENGTH(P.xy);
65 | return dot( c, (float2)(q, P.z) );
66 | }
67 |
68 |
69 | ////////////// fractals
70 |
71 | // [WEB] - http://blog.hvidtfeldts.net/index.php/2011/09/
72 | static void mandelbulbIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia, const float power)
73 | {
74 | float3 Z_orig = *Z;
75 | float de_orig = *de;
76 |
77 | float distance = LENGTH(*Z);
78 |
79 | // convert to polar coordinates
80 | float theta = acos( DIV((*Z).z, distance));
81 | float phi = atan2((*Z).y, (*Z).x);
82 |
83 | *de = POWR(distance, power-1) * power * (*de) + 1.0f;
84 |
85 | // scale and rotate the point
86 | float zr = POWR(distance, power);
87 | theta *= power;
88 | phi *= power;
89 |
90 | // convert back to cartesian coordinates
91 | float3 newZ = zr * (float3)( SIN(theta)*COS(phi), SIN(phi)*SIN(theta), COS(theta) );
92 |
93 | if (julia.x == 0.0f)
94 | {
95 | *Z = newZ + *P_in;
96 | }
97 | else {
98 | *Z = newZ + julia.yzw;
99 | }
100 |
101 | *Z = mix(Z_orig, *Z, weight);
102 | *de = mix(de_orig, *de, weight);
103 | (*log_lin)++;
104 | }
105 |
106 | // [WEB] - http://www.fractalforums.com/index.php?topic=2785.msg14893#msg14893
107 | static void mandelboxIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia, const float scale)
108 | {
109 | float3 Z_orig = *Z;
110 | float de_orig = *de;
111 |
112 | float fixedRadius = 1.0f;
113 | float fR2 = fixedRadius * fixedRadius;
114 | float minRadius = 0.5f;
115 | float mR2 = minRadius * minRadius;
116 |
117 | if ((*Z).x > 1.0f) (*Z).x = 2.0f - (*Z).x;
118 | else if ((*Z).x < -1.0f) (*Z).x = -2.0f - (*Z).x;
119 |
120 | if ((*Z).y > 1.0f) (*Z).y = 2.0f - (*Z).y;
121 | else if ((*Z).y < -1.0f) (*Z).y = -2.0f - (*Z).y;
122 |
123 | if ((*Z).z > 1.0f) (*Z).z = 2.0f - (*Z).z;
124 | else if ((*Z).z < -1.0f) (*Z).z = -2.0f - (*Z).z;
125 |
126 | float r2 = (*Z).x*(*Z).x + (*Z).y*(*Z).y + (*Z).z*(*Z).z;
127 |
128 | if (r2 < mR2)
129 | {
130 | *Z = *Z * DIV(fR2, mR2);
131 | *de = *de * DIV(fR2, mR2);
132 | }
133 | else if (r2 < fR2)
134 | {
135 | *Z = *Z * DIV(fR2, r2);
136 | *de *= DIV(fR2, r2);
137 | }
138 |
139 | *de *= scale;
140 |
141 | if (julia.x == 0.0f)
142 | {
143 | *Z = *Z * scale + *P_in;
144 | }
145 | else
146 | {
147 | *Z = *Z * scale + julia.yzw;
148 | }
149 |
150 | *Z = mix(Z_orig, *Z, weight);
151 | *de = mix(de_orig, *de, weight);
152 | (*log_lin)--;
153 | }
154 |
155 | // [M2] - Classic Mandelbulb Power 2 fractal - MandelbulbPower2Iteration
156 | static void mandelbulbPower2Iter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia)
157 | {
158 | float3 Z_orig = *Z;
159 | float de_orig = *de;
160 |
161 | float distance = LENGTH(*Z);
162 |
163 | *de = *de * 2.0f * distance;
164 | float x2 = (*Z).x * (*Z).x;
165 | float y2 = (*Z).y * (*Z).y;
166 | float z2 = (*Z).z * (*Z).z;
167 | float temp = DIV(1.0f - z2, (x2 + y2));
168 | float3 new;
169 | new.x = (x2 - y2) * temp;
170 | new.y = 2.0f * (*Z).x * (*Z).y * temp;
171 | new.z = -2.0f * (*Z).z * SQRT(x2 + y2);
172 |
173 | if (julia.x == 0.0f)
174 | {
175 | *Z = new + *P_in;
176 | }
177 | else
178 | {
179 | *Z = new + julia.yzw;
180 | }
181 |
182 | *Z = mix(Z_orig, *Z, weight);
183 | *de = mix(de_orig, *de, weight);
184 | (*log_lin)++;
185 | }
186 |
187 | // [M2] - Menger Sponge formula created by Knighty, modulus modification by mancoast - MengerSpongeIteration
188 | static void mengerSpongeIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia, const int modulus)
189 | {
190 | float3 Z_orig = *Z;
191 | float de_orig = *de;
192 |
193 | (*Z).x = fabs((*Z).x);
194 | (*Z).y = fabs((*Z).y);
195 | (*Z).z = fabs((*Z).z);
196 |
197 | if ((*Z).x - (*Z).y < 0.0f) (*Z).xy = (*Z).yx;
198 | if ((*Z).x - (*Z).z < 0.0f) (*Z).xz = (*Z).zx;
199 | if ((*Z).y - (*Z).z < 0.0f) (*Z).yz = (*Z).zy;
200 |
201 | *Z *= 3.0f;
202 |
203 | (*Z).x -= 2.0f;
204 | (*Z).y -= 2.0f;
205 |
206 | if (modulus == 0)
207 | {
208 | if ((*Z).z > 1.0f) (*Z).z -= 2.0f;
209 | }
210 | else
211 | {
212 | if (fmod((*Z).z, M_PI_F) > 2.0f) (*Z).z -= 2.0f;
213 | }
214 |
215 | *de *= 3.0f;
216 |
217 | if (julia.x == 1.0f)
218 | {
219 | *Z += julia.yzw;
220 | }
221 |
222 | *Z = mix(Z_orig, *Z, weight);
223 | *de = mix(de_orig, *de, weight);
224 | (*log_lin)--;
225 | }
226 |
227 | // [M2] - Bristorbrot formula - BristorbrotIteration
228 | static void bristorbrotIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia)
229 | {
230 | float3 Z_orig = *Z;
231 | float de_orig = *de;
232 |
233 | float distance = LENGTH(*Z);
234 |
235 | float3 new;
236 | new.x = (*Z).x * (*Z).x - (*Z).y * (*Z).y - (*Z).z * (*Z).z;
237 | new.y = (*Z).y * (2.0f * (*Z).x - (*Z).z);
238 | new.z = (*Z).z * (2.0f * (*Z).x + (*Z).y);
239 |
240 | *de = *de * 2.0f * distance;
241 | *Z = new;
242 |
243 | if (julia.x == 0.0f)
244 | {
245 | *Z += *P_in;
246 | }
247 | else
248 | {
249 | *Z += julia.yzw;
250 | }
251 |
252 | *Z = mix(Z_orig, *Z, weight);
253 | *de = mix(de_orig, *de, weight);
254 | (*log_lin)++;
255 | }
256 |
257 | // [M2] - Xenodreambuie - XenodreambuieIteration
258 | static void xenodreambuieIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia, const float power, float alpha, float beta)
259 | {
260 | float3 Z_orig = *Z;
261 | float de_orig = *de;
262 |
263 | float distance = LENGTH(*Z);
264 |
265 | alpha = radians(alpha);
266 | beta = radians(beta);
267 |
268 | float rp = POWR(distance, power - 1.0f);
269 | *de = rp * (*de) * power + 1.0f;
270 | rp *= distance;
271 |
272 | float th = atan2((*Z).y, (*Z).x) + beta;
273 | float ph = acos( DIV((*Z).z, distance)) + alpha;
274 |
275 | if (fabs(ph) > 0.5f * M_PI_F) ph = sign(ph) * M_PI_F - ph;
276 |
277 | (*Z).x = rp * COS(th * power) * SIN(ph * power);
278 | (*Z).y = rp * SIN(th * power) * SIN(ph * power);
279 | (*Z).z = rp * COS(ph * power);
280 |
281 | if (julia.x == 0.0f)
282 | {
283 | *Z += *P_in;
284 | }
285 | else
286 | {
287 | *Z += julia.yzw;
288 | }
289 |
290 | *Z = mix(Z_orig, *Z, weight);
291 | *de = mix(de_orig, *de, weight);
292 | (*log_lin)++;
293 | }
294 |
295 | // [M2] - Sierpinski3D. made from Darkbeam's Sierpinski code from M3D - Sierpinski3dIteration
296 | static void sierpinski3dIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia, const float scale, const float3 offset, const float3 rot)
297 | {
298 | float3 Z_orig = *Z;
299 | float de_orig = *de;
300 |
301 | float3 temp = *Z;
302 |
303 | if ((*Z).x - (*Z).y < 0.0f) (*Z).xy = (*Z).yx;
304 | if ((*Z).x - (*Z).z < 0.0f) (*Z).xz = (*Z).zx;
305 | if ((*Z).y - (*Z).z < 0.0f) (*Z).yz = (*Z).zy;
306 | if ((*Z).x + (*Z).y < 0.0f)
307 | {
308 | temp.x = -(*Z).y;
309 | (*Z).y = -(*Z).x;
310 | (*Z).x = temp.x;
311 | }
312 | if ((*Z).x + (*Z).z < 0.0f)
313 | {
314 | temp.x = -(*Z).z;
315 | (*Z).z = -(*Z).x;
316 | (*Z).x = temp.x;
317 | }
318 | if ((*Z).y + (*Z).z < 0.0f)
319 | {
320 | temp.y = -(*Z).z;
321 | (*Z).z = -(*Z).y;
322 | (*Z).y = temp.y;
323 | }
324 |
325 | *Z *= scale;
326 | *de *= scale;
327 |
328 | *Z -= offset;
329 |
330 | *Z = mtxPtMult( mtxRotate(rot) , *Z );
331 |
332 | if (julia.x == 1.0f)
333 | {
334 | *Z += julia.yzw;
335 | }
336 |
337 | *Z = mix(Z_orig, *Z, weight);
338 | *de = mix(de_orig, *de, weight);
339 | (*log_lin)--;
340 | }
341 |
342 | // [M2] - Menger Smooth - mengerSmoothIteration
343 | static void mengerSmoothIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia, const float scale, const float offset_s, const float3 offset_c, const float3 rot)
344 | {
345 | float3 Z_orig = *Z;
346 | float de_orig = *de;
347 |
348 | float sc1 = scale - 1.0f;
349 | float sc2 = DIV(sc1, scale);
350 |
351 | *Z = (float3)(SQRT((*Z).x * (*Z).x + offset_s), SQRT((*Z).y * (*Z).y + offset_s), SQRT((*Z).z * (*Z).z + offset_s));
352 |
353 | float t;
354 |
355 | t = (*Z).x - (*Z).y;
356 | t = 0.5f * (t - SQRT(t * t + offset_s));
357 | (*Z).x = (*Z).x - t;
358 | (*Z).y = (*Z).y + t;
359 |
360 | t = (*Z).x - (*Z).z;
361 | t = 0.5f * (t - SQRT(t * t + offset_s));
362 | (*Z).x = (*Z).x - t;
363 | (*Z).z = (*Z).z + t;
364 |
365 | t = (*Z).y - (*Z).z;
366 | t = 0.5f * (t - SQRT(t * t + offset_s));
367 | (*Z).y = (*Z).y - t;
368 | (*Z).z = (*Z).z + t;
369 |
370 | (*Z).z = (*Z).z - offset_c.z * sc2;
371 | (*Z).z = -SQRT((*Z).z * (*Z).z + offset_s);
372 | (*Z).z = (*Z).z + offset_c.z * sc2;
373 |
374 | (*Z).x = scale * (*Z).x - offset_c.x * sc1;
375 | (*Z).y = scale * (*Z).y - offset_c.y * sc1;
376 | (*Z).z = scale * (*Z).z;
377 |
378 | *de *= scale;
379 |
380 | *Z = mtxPtMult( mtxRotate(rot) , *Z );
381 |
382 | if (julia.x == 1.0f)
383 | {
384 | *Z += *P_in;
385 | *Z += julia.yzw;
386 | }
387 |
388 | *Z = mix(Z_orig, *Z, weight);
389 | *de = mix(de_orig, *de, weight);
390 | (*log_lin)--;
391 | }
392 |
393 | // [M2] - Amazing Surf from Mandelbulber3D, formula proposed by Kali, with features added by Darkbeam - AmazingSurfIteration
394 | static void amazingSurfIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia, const float fold_x, const float fold_y, const int force_cylindrical_fold, const float min_radius, float scale, const float scale_fold_influence, const float3 rot, const int multiply_c, const float3 c_multiplier)
395 | {
396 | float3 Z_orig = *Z;
397 | float de_orig = *de;
398 |
399 | float actual_scale = scale;
400 |
401 | (*Z).x = fabs((*Z).x + fold_x) - fabs((*Z).x - fold_x) - (*Z).x;
402 | (*Z).y = fabs((*Z).y + fold_y) - fabs((*Z).y - fold_y) - (*Z).y;
403 |
404 | float rr = dot(*Z, *Z);
405 |
406 | // get rid of if afterwards
407 | if (force_cylindrical_fold == 1)
408 | {
409 | rr -= (*Z).z * (*Z).z;
410 | }
411 |
412 | float SQRTMinR = SQRT(min_radius);
413 | float dividend = rr < SQRTMinR ? SQRTMinR : min(rr, 1.0f);
414 |
415 | float m = DIV(actual_scale, dividend);
416 |
417 | *Z *= (m - 1.0f) * scale_fold_influence + 1.0f;
418 | *de = *de * fabs(m) + 1.0f;
419 |
420 | if (multiply_c == 1)
421 | {
422 | *Z += (float3)((*P_in).y, (*P_in).x, (*P_in).z) * c_multiplier;
423 | }
424 |
425 | *Z = mtxPtMult( mtxRotate(rot) , *Z );
426 |
427 | if (julia.x == 0.0f)
428 | {
429 | *Z += (float3)((*P_in).y, (*P_in).x, (*P_in).z);
430 | }
431 | else
432 | {
433 | *Z += julia.yzw;
434 | }
435 |
436 | *Z = mix(Z_orig, *Z, weight);
437 | *de = mix(de_orig, *de, weight);
438 | (*log_lin)--;
439 | }
440 |
441 | // [M2] - Benesi formula invented by Benesi - BenesiIteration
442 | static void benesiIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia)
443 | {
444 | float3 Z_orig = *Z;
445 | float de_orig = *de;
446 |
447 | float distance = LENGTH(*Z);
448 |
449 | *de = *de * 2.0f * distance;
450 | float r1 = (*Z).y * (*Z).y + (*Z).z * (*Z).z;
451 | float newx;
452 | if ((*P_in).x < 0.0f || (*Z).x < SQRT(r1))
453 | {
454 | newx = (*Z).x * (*Z).x - r1;
455 | }
456 | else
457 | {
458 | newx = -(*Z).x * (*Z).x + r1;
459 | }
460 | r1 = DIV(-1.0f, SQRT(r1)) * 2.0f * fabs((*Z).x);
461 | float newy = r1 * ((*Z).y * (*Z).y - (*Z).z * (*Z).z);
462 | float newz = r1 * 2.0f * (*Z).y * (*Z).z;
463 |
464 | *Z = (float3)(newx, newy, newz);
465 |
466 | if (julia.x == 0.0f)
467 | {
468 | *Z += *P_in;
469 | }
470 | else
471 | {
472 | *Z += julia.yzw;
473 | }
474 |
475 | *Z = mix(Z_orig, *Z, weight);
476 | *de = mix(de_orig, *de, weight);
477 | (*log_lin)++;
478 | }
479 |
480 | // [M2] - Mandelbulb 2 fractal formula created by Buddhi - Mandelbulb2Iteration
481 | static void mandelbulb2Iter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia)
482 | {
483 | float3 Z_orig = *Z;
484 | float de_orig = *de;
485 |
486 | float distance = LENGTH(*Z);
487 |
488 | *de = *de * 2.0f * distance;
489 |
490 | float tempR = SQRT((*Z).x * (*Z).x + (*Z).y * (*Z).y); //+ 1e-061
491 | *Z *= DIV(1.0f, tempR);
492 | float temp = (*Z).x * (*Z).x - (*Z).y * (*Z).y;
493 | (*Z).y = 2.0f * (*Z).x * (*Z).y;
494 | (*Z).x = temp;
495 | *Z *= tempR;
496 |
497 | tempR = SQRT((*Z).y * (*Z).y + (*Z).z * (*Z).z); //+ 1e-061
498 | *Z *= DIV(1.0f, tempR);
499 | temp = (*Z).y * (*Z).y - (*Z).z * (*Z).z;
500 | (*Z).z = 2.0f * (*Z).y * (*Z).z;
501 | (*Z).y = temp;
502 | *Z *= tempR;
503 |
504 | tempR = SQRT((*Z).x * (*Z).x + (*Z).z * (*Z).z); //+ 1e-061
505 | *Z *= DIV(1.0f, tempR);
506 | temp = (*Z).x * (*Z).x - (*Z).z * (*Z).z;
507 | (*Z).z = 2.0f * (*Z).x * (*Z).z;
508 | (*Z).x = temp;
509 | *Z *= tempR;
510 |
511 | (*Z) *= distance;
512 |
513 | if (julia.x == 0.0f)
514 | {
515 | *Z += *P_in;
516 | }
517 | else
518 | {
519 | *Z += julia.yzw;
520 | }
521 |
522 | *Z = mix(Z_orig, *Z, weight);
523 | *de = mix(de_orig, *de, weight);
524 | (*log_lin)--;
525 | }
526 |
527 | // [M2] - Mandelbulb 3 fractal formula created by Buddhi - Mandelbulb3Iteration
528 | static void mandelbulb3Iter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia)
529 | {
530 | float3 Z_orig = *Z;
531 | float de_orig = *de;
532 |
533 | float distance = LENGTH(*Z);
534 |
535 |
536 | *de = *de * 2.0f * distance;
537 |
538 | float temp, tempR;
539 |
540 | float sign = 1.0f;
541 | float sign2 = 1.0f;
542 |
543 | if ((*Z).x < 0.0f) sign2 = -1.0f;
544 | tempR = SQRT((*Z).x * (*Z).x + (*Z).y * (*Z).y); //+ 1e-061
545 | *Z *= DIV(1.0f, tempR);
546 | temp = (*Z).x * (*Z).x - (*Z).y * (*Z).y;
547 | (*Z).y = 2.0f * (*Z).x * (*Z).y;
548 | (*Z).x = temp;
549 | *Z *= tempR;
550 |
551 | if ((*Z).x < 0.0f) sign = -1.0f;
552 | tempR = SQRT((*Z).x * (*Z).x + (*Z).z * (*Z).z); //+ 1e-061
553 | *Z *= DIV(1.0f, tempR);
554 | temp = (*Z).x * (*Z).x - (*Z).z * (*Z).z;
555 | (*Z).z = 2.0f * (*Z).x * (*Z).z * sign2;
556 | (*Z).x = temp * sign;
557 | *Z *= tempR;
558 |
559 | *Z *= distance;
560 |
561 | if (julia.x == 0.0f)
562 | {
563 | *Z += *P_in;
564 | }
565 | else
566 | {
567 | *Z += julia.yzw;
568 | }
569 |
570 | *Z = mix(Z_orig, *Z, weight);
571 | *de = mix(de_orig, *de, weight);
572 | (*log_lin)++;
573 | }
574 |
575 | // [M2] - Mandelbulb 4 fractal formula created by Buddhi - Mandelbulb4Iteration
576 | static void mandelbulb4Iter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia, const float power, const float3 angles)
577 | {
578 | float3 Z_orig = *Z;
579 | float de_orig = *de;
580 |
581 | float distance = LENGTH(*Z);
582 |
583 | float rp = POWR(distance, power - 1.0f);
584 | *de = rp * (*de) * power + 1.0f;
585 |
586 | float angZ = degrees(atan2((*Z).y, (*Z).x)) + angles.x;
587 | float angY = degrees(atan2((*Z).z, (*Z).x)) + angles.y;
588 | float angX = degrees(atan2((*Z).z, (*Z).y)) + angles.z;
589 |
590 | float16 rotM = mtxRotate( (float3)((angX * (power - 1.0f)), (angY * (power - 1.0f)), (angZ * (power - 1.0f))) );
591 |
592 | *Z = mtxPtMult( rotM , *Z ) * rp;
593 |
594 | if (julia.x == 0.0f)
595 | {
596 | *Z += *P_in;
597 | }
598 | else
599 | {
600 | *Z += julia.yzw;
601 | }
602 |
603 | *Z = mix(Z_orig, *Z, weight);
604 | *de = mix(de_orig, *de, weight);
605 | (*log_lin)++;
606 | }
607 |
608 | // [M2] - Ides formula made by Trafassel, the original Ide's Formula thread - IdesIteration
609 | static void idesIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia, const float3 multiplier, const float2 sub_multiplier)
610 | {
611 | float3 Z_orig = *Z;
612 | float de_orig = *de;
613 |
614 | if (fabs((*Z).x) < 2.5f) (*Z).x = (*Z).x * 0.9f;
615 | if (fabs((*Z).z) < 2.5f) (*Z).z = (*Z).z * 0.9f;
616 |
617 | float3 z2 = (*Z) * (*Z);
618 | float3 newZ;
619 | newZ.x = multiplier.x * z2.x - sub_multiplier.x * (z2.y + z2.z);
620 | newZ.y = multiplier.y * (*Z).x * (*Z).y * (*Z).z;
621 | newZ.z = multiplier.z * z2.z - sub_multiplier.y * (z2.x + z2.y);
622 | *Z = newZ;
623 |
624 | if (julia.x == 0.0f)
625 | {
626 | *Z += *P_in;
627 | }
628 | else
629 | {
630 | *Z += julia.yzw;
631 | }
632 |
633 | *Z = mix(Z_orig, *Z, weight);
634 | }
635 |
636 |
637 | // [M2] - Ides 2 formula made by Trafassel, the original Ide's Formula thread - Ides2Iteration
638 | static void ides2Iter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia, const float3 multiplier, const float2 sub_multiplier)
639 | {
640 | float3 Z_orig = *Z;
641 | float de_orig = *de;
642 |
643 | float3 z2 = (*Z) * (*Z);
644 | float3 newZ;
645 | newZ.x = multiplier.x * z2.x - sub_multiplier.x * (z2.y + z2.z);
646 | newZ.y = multiplier.y * (*Z).x * (*Z).y * (*Z).z;
647 | newZ.z = multiplier.z * z2.z - sub_multiplier.y * (z2.x + z2.y);
648 |
649 | *Z = newZ + (*Z);
650 |
651 | if (julia.x == 0.0f)
652 | {
653 | *Z += *P_in;
654 | }
655 | else
656 | {
657 | *Z += julia.yzw;
658 | }
659 |
660 | *Z = mix(Z_orig, *Z, weight);
661 | }
662 |
663 | // [M2] - IQ Bulb from Mandelbulb 3D and Inigo Quilez - IqBulbIteration
664 | static void iqBulbIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia, const float power, const float zpower)
665 | {
666 | float3 Z_orig = *Z;
667 | float de_orig = *de;
668 |
669 | float distance = LENGTH(*Z);
670 |
671 | // extract polar coordinates
672 | float wr = distance;
673 | float wo = acos( DIV((*Z).y, wr));
674 | float wi = atan2((*Z).x, (*Z).z);
675 |
676 | // scale and rotate the point
677 | wr = POWR(wr, power - 1.0f);
678 | *de = wr * *de * power + 1.0f;
679 | wr *= distance;
680 | wo *= power;
681 | wi *= zpower;
682 |
683 | // convert back to cartesian coordinates
684 | (*Z).x = SIN(wo) * SIN(wi);
685 | (*Z).y = COS(wo);
686 | (*Z).z = SIN(wo) * COS(wi);
687 |
688 | *Z *= wr; // then add Cpixel constant
689 |
690 | if (julia.x == 0.0f)
691 | {
692 | *Z += *P_in;
693 | }
694 | else
695 | {
696 | *Z += julia.yzw;
697 | }
698 |
699 | *Z = mix(Z_orig, *Z, weight);
700 | *de = mix(de_orig, *de, weight);
701 | (*log_lin)++;
702 | }
703 |
704 | // [M2] - Quaternion3DE fractal with extended controls - Quaternion3dIteration
705 | static void quaternion3dIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia, const float3 scale, const float3 offset, const float3 rot, const float de_influence)
706 | {
707 | float3 Z_orig = *Z;
708 | float de_orig = *de;
709 |
710 | float distance = LENGTH(*Z);
711 |
712 | *de = (*de) * 2.0f * distance;
713 | *Z = (float3)((*Z).x * (*Z).x - (*Z).y * (*Z).y - (*Z).z * (*Z).z, (*Z).x * (*Z).y, (*Z).x * (*Z).z);
714 |
715 | float tempL = LENGTH(*Z);
716 | *Z *= scale;
717 | float3 tempAvgScale = (float3)((*Z).x, DIV((*Z).y, 2.0f), DIV((*Z).z, 2.0f));
718 | float avgScale = DIV(LENGTH(tempAvgScale), tempL);
719 | float tempAux = *de * avgScale;
720 | *de = *de + (tempAux - *de) * de_influence;
721 |
722 | *Z = mtxPtMult( mtxRotate(rot) , *Z );
723 |
724 | *Z += offset;
725 |
726 | if (julia.x == 0.0f)
727 | {
728 | *Z += *P_in;
729 | }
730 | else
731 | {
732 | *Z += julia.yzw;
733 | }
734 |
735 | *Z = mix(Z_orig, *Z, weight);
736 | *de = mix(de_orig, *de, weight);
737 | (*log_lin)++;
738 | }
739 |
740 | // [M2] - JosLeys-Kleinian - JosKleinianIteration
741 | // will not work in this case, requires different DE computation
742 | static void josKleinianIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia, const float r, const float l, const float3 box_size)
743 | {
744 | float3 Z_orig = *Z;
745 | float de_orig = *de;
746 |
747 | float a = r;
748 | float b = l;
749 | float f = sign(b);
750 |
751 | float3 box1 = (float3)(2.0f * box_size.x, a * box_size.y, 2.0 * box_size.z);
752 | float3 box2 = (float3)(-box_size.x, -box_size.y + 1.0f, -box_size.z);
753 | float3 wrapped = wrap(*Z, box1, box2);
754 |
755 | *Z = (float3)(wrapped.x, wrapped.y, wrapped.z);
756 |
757 | if ((*Z).y >= a * (0.5f + 0.2f * SIN(f * M_PI_F * DIV(((*Z).x + b * 0.5f), box_size.x))))
758 | *Z = (float3)(-b, a, 0.0f) - *Z;
759 |
760 | float z2 = dot(*Z, *Z);
761 |
762 | float iR = DIV(1.0f, z2);
763 | *Z *= -iR;
764 | (*Z).x = -b - (*Z).x;
765 | (*Z).y = a + (*Z).y;
766 | *de *= iR;
767 |
768 | if (julia.x == 0.0f)
769 | {
770 | *Z += *P_in;
771 | }
772 | else
773 | {
774 | *Z += julia.yzw;
775 | }
776 |
777 | *Z = mix(Z_orig, *Z, weight);
778 | *de = mix(de_orig, *de, weight);
779 | (*log_lin)++;
780 | }
781 |
782 | // [M2] - T>rotation - TransfRotationIteration
783 | static void rotationIter(float3* Z, const float3 rot)
784 | {
785 | *Z = mtxPtMult( mtxRotate(rot) , *Z );
786 | }
787 |
788 | // [M2] - T>Box Fold - TransfBoxFoldIteration
789 | static void boxFoldIter(float3* Z, const int3 axis_enable, const float folding_limit, const float folding_value, const float z_scale)
790 | {
791 | if (axis_enable.x == 1)
792 | {
793 | if (fabs((*Z).x) > folding_limit)
794 | {
795 | (*Z).x = sign((*Z).x) * folding_value - (*Z).x;
796 | }
797 | }
798 | if (axis_enable.y == 1)
799 | {
800 | if (fabs((*Z).y) > folding_limit)
801 | {
802 | (*Z).y = sign((*Z).y) * folding_value - (*Z).y;
803 | }
804 | }
805 | if (axis_enable.z == 1)
806 | {
807 | float zLimit = folding_limit * z_scale;
808 | float zValue = folding_value * z_scale;
809 | if (fabs((*Z).z) > zLimit)
810 | {
811 | (*Z).z = sign((*Z).z) * zValue - (*Z).z;
812 | }
813 | }
814 | }
815 |
816 | // [M2] - Rotation Folding: rotatedAbs & Rotated Folding transform from M3D - TransfRotationFoldingIteration
817 | static void fabsFoldIter(float3* Z, const int3 axis_enable, const float3 offset)
818 | {
819 | if (axis_enable.x == 1)
820 | {
821 | (*Z).x = fabs((*Z).x + offset.x) - offset.x;
822 | }
823 | if (axis_enable.y == 1)
824 | {
825 | (*Z).y = fabs((*Z).y + offset.y) - offset.y;
826 | }
827 | if (axis_enable.z == 1)
828 | {
829 | (*Z).z = fabs((*Z).z + offset.z) - offset.z;
830 | }
831 | }
832 |
833 |
834 | // [M2] - Rotation Folding: rotatedAbs & Rotated Folding transform from M3D - TransfRotationFoldingIteration
835 | static void tgladFoldIter(float3* Z, const int3 axis_enable, const float3 offset)
836 | {
837 | if (axis_enable.x == 1)
838 | {
839 | (*Z).x = fabs((*Z).x + offset.x) - fabs((*Z).x - offset.x) - (*Z).x;
840 | }
841 | if (axis_enable.y == 1)
842 | {
843 | (*Z).y = fabs((*Z).y + offset.y) - fabs((*Z).y - offset.y) - (*Z).y;
844 | }
845 | if (axis_enable.z == 1)
846 | {
847 | (*Z).z = fabs((*Z).z + offset.z) - fabs((*Z).z - offset.z) - (*Z).z;
848 | }
849 | }
850 |
851 | // [M2] - T>Scale - TransfScaleIteration
852 | static void scaleIter(float3* Z, float* de, const float3 scale)
853 | {
854 | float distance_init = LENGTH(*Z);
855 |
856 | *Z = mtxPtMult( mtxScale(scale) , *Z );
857 |
858 | float distance_scaled = LENGTH(*Z);
859 | *de *= DIV(distance_scaled, distance_init);
860 | }
861 |
862 | static void preScaleIter(float3* Z, const float3 scale)
863 | {
864 | *Z = mtxPtMult( mtxScale(scale) , *Z );
865 | }
866 |
867 | static void translateIter(float3* Z, const float3 translate)
868 | {
869 | *Z += translate;
870 | }
871 |
872 | static void addCOffsetIter(float3* Z, const float3* P_in, const float3 offset)
873 | {
874 | *Z += *P_in + offset;
875 | }
876 |
877 | static void curlNoise(global const void* theXNoise, float3* Z, const float4 frequency, const float4 offset, const float3 amplitude)
878 | {
879 | *Z += curlxnoise4(theXNoise, (float4)(*Z, 1.0f) * frequency + offset) * amplitude;
880 | }
881 |
882 |
883 | // testing new formulas
884 | /*
885 |
886 |
887 | // [M2] - Hypercomplex 3D Mandelbrot formula invented by David Makin - HypercomplexIteration
888 | static void hypercomplexIter(float3* Z, float* de, const float3* P_in, int* log_lin, const float weight, const float4 julia)
889 | {
890 | float3 Z_orig = *Z;
891 | float de_orig = *de;
892 |
893 | float distance = length(*Z);
894 | float4 Z_complex = (float4)((*Z).x, (*Z).y, (*Z).z, 1.0f);
895 | float4* Z_ = &Z_complex;
896 |
897 | *de = *de * 2.0f * distance;
898 | float newx = (*Z_).x * (*Z_).x - (*Z_).y * (*Z_).y - (*Z_).z * (*Z_).z - (*Z_).w * (*Z_).w;
899 | float newy = 2.0f * (*Z_).x * (*Z_).y - 2.0f * (*Z_).w * (*Z_).z;
900 | float newz = 2.0f * (*Z_).x * (*Z_).z - 2.0f * (*Z_).y * (*Z_).w;
901 | float neww = 2.0f * (*Z_).x * (*Z_).w - 2.0f * (*Z_).y * (*Z_).z;
902 | //(*Z).x = newx;
903 | //(*Z).y = newy;
904 | //(*Z).z = newz;
905 | //(*Z).w = neww;
906 |
907 | (*Z).x = newx * newx - newy * newy - newz * newz - neww * neww;
908 | (*Z).y = newx * newy;
909 | (*Z).z = newx * newz;
910 |
911 | if (julia.x == 0.0f)
912 | {
913 | *Z += *P_in;
914 | }
915 | else
916 | {
917 | *Z += julia.yzw;
918 | }
919 |
920 | *Z = mix(Z_orig, *Z, weight);
921 | *de = mix(de_orig, *de, weight);
922 | (*log_lin)++;
923 | }
924 |
925 |
926 |
927 | // quaternion fractals, kind of works, but not sure what to do with z.w component :)
928 | static float quaternion(float3 P, float size)
929 | {
930 | //void QuaternionIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
931 | //{
932 | // Q_UNUSED(fractal);
933 |
934 | // aux.r_dz = aux.r_dz * 2.0 * aux.r;
935 | // double newx = z.x * z.x - z.y * z.y - z.z * z.z - z.w * z.w;
936 | // double newy = 2.0 * z.x * z.y;
937 | // double newz = 2.0 * z.x * z.z;
938 | // double neww = 2.0 * z.x * z.w;
939 | // z.x = newx;
940 | // z.y = newy;
941 | // z.z = newz;
942 | // z.w = neww;
943 | //}
944 | P /= size;
945 |
946 | float4 z = (float4)(P, 1);
947 | float dr = 1.0;
948 | float r = 0.0;
949 | int Iterations = 50;
950 | int Bailout = 40;
951 |
952 | for (int i = 0; i < Iterations ; i++)
953 | {
954 | r = length(z);
955 | if (r > Bailout) break;
956 |
957 | dr = dr * 2.0f * r;
958 | float newx = z.x * z.x - z.y * z.y - z.z * z.z - z.w * z.w;
959 | float newy = 2.0f * z.x * z.y;
960 | float newz = 2.0f * z.x * z.z;
961 | float neww = 2.0f * z.x * z.w;
962 | z.x = newx;
963 | z.y = newy;
964 | z.z = newz;
965 | //z.w = neww;
966 | }
967 |
968 | float out = 0.5f * log(r) * r/dr;
969 | return out * size;
970 | }
971 |
972 | // quaternion3d
973 | // kind of works, but does not exactly match M2 visual, but parameters deform it in a similar manner, I hardcoded some of the parameters into values, there are some buggy areas, missing parts, noisy normals etc.
974 | static float quaternion3d(float3 P, float size)
975 | {
976 | //void Quaternion3dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
977 | //{
978 | //
979 | // aux.r_dz = aux.r_dz * 2.0 * aux.r;
980 | // z = CVector4(z.x * z.x - z.y * z.y - z.z * z.z, z.x * z.y, z.x * z.z, z.w);
981 | //
982 | // double tempL = z.Length();
983 | // z *= fractal).transformCommon.constantMultiplier122;
984 | // // if (tempL < 1e-21) tempL = 1e-21;
985 | // CVector4 tempAvgScale = CVector4(z.x, z.y / 2.0, z.z / 2.0, z.w);
986 | // double avgScale = tempAvgScale.Length() / tempL;
987 | // double tempAux = aux.r_dz * avgScale;
988 | // aux.r_dz = aux.r_dz + (tempAux - aux.r_dz) * fractal).transformCommon.scaleA1;
989 | //
990 | // if (fractal).transformCommon.rotationEnabled)
991 | // z = fractal).transformCommon.rotationMatrix.RotateVector(z);
992 | //
993 | // z += fractal).transformCommon.additionConstant000;
994 | //}
995 | P /= size;
996 |
997 | float4 z = (float4)(P, 1);
998 | float dr = 1.0;
999 | float r = 0.0;
1000 | int Iterations = 250;
1001 | int Bailout = 20;
1002 |
1003 | for (int i = 0; i < Iterations ; i++)
1004 | {
1005 | r = length(z);
1006 | if (r > Bailout) break;
1007 |
1008 | dr = dr * 2.0 * r;
1009 | z = (float4)(z.x * z.x - z.y * z.y - z.z * z.z, z.x * z.y, z.x * z.z, z.w);
1010 |
1011 | float tempL = r;
1012 | z *= (float4)(1,1,1,1);
1013 |
1014 | float4 tempAvgScale = (float4)(z.x, z.y / 2.0, z.z / 2.0, z.w);
1015 | float avgScale = length(tempAvgScale) / tempL;
1016 | float tempAux = dr * avgScale;
1017 | dr = dr + (tempAux - dr) * 1.0f;
1018 |
1019 | //if (fractal).transformCommon.rotationEnabled)
1020 | // z = fractal).transformCommon.rotationMatrix.RotateVector(z);
1021 |
1022 | z += (float4)(0,0,0,0);
1023 | }
1024 |
1025 | //float out = 0.5f * log(r) * r/dr;
1026 | float out = r / dr;
1027 | return out * size;
1028 | }
1029 |
1030 | */
1031 | #endif
1032 |
--------------------------------------------------------------------------------