Skip to content

Instantly share code, notes, and snippets.

@PossiblyAShrub
Created July 18, 2020 20:50
Show Gist options
  • Save PossiblyAShrub/24bce799f585200ff6436ea316d2e881 to your computer and use it in GitHub Desktop.
Save PossiblyAShrub/24bce799f585200ff6436ea316d2e881 to your computer and use it in GitHub Desktop.
A procedural tree shader, instructions are in the comments (WARNING: this shader may crash your magicavoxel, backup/save you file before using, and limit the size of you 'chunk' when using. - If your app crashes and you forgot to save, magicavoxel has a backup.vox file, file that and use it to recover your project. And if you want to risk it, yo…
// Instructions
// 1. Download into the folder 'shader' in your MagicaVoxel install folder
// 2. Open the shaders panel on the right
// 3. Place down a 'seed' color (make this unique) this is where your trees will grow
// 4. Congifure your tree properties in the 'ARG' panel
// 5. Click the shader and press play!
//
// !!!!! WARNING: this shader doesn't support: SDF brush, or areas larger then 64^3 at a time
// !!!!! NOTICE: as this shader can crash magicavoxel, it's recommended to make a backup of your
// project BEFORE running the shader
//
//
// Copyright 2020 Aidan (@PossiblyAShrub)
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
// associated documentation files (the "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
// following conditions: The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// xs_begin
// author : @PossiblyAShrub
// arg : {id="0" name="bark color" value="1" range="1 255" decimal="0"}
// arg : {id="1" name="leaf color" value="1" range="1 255" decimal="0"}
// arg : {id="2" name="leaf color range" value="2" range="1 255" decimal="0"}
// arg : {id="3" name="log height" value="8" range="1 64" decimal="0"}
// arg : {id="4" name="leaf radius" value="5.2" range="1 64" decimal="1"}
// arg : {id="6" name="leaf randomness" value="0.75" range="0 1" decimal="2"}
// arg : {id="7" name="danger mode (could crash)" value="0" range="0 1" decimal="0"}
// xs_end
//===== user args =====
// uniform float i_args[8];
//===== built-in args =====
// uniform vec3 i_volume_size; // volume size [1-256]
// uniform float i_color_index; // color index [0-255]
// uniform vec3 i_mirror; // mirror mode [0,1]
// uniform vec3 i_axis; // axis mode [0,1]
// uniform float i_iter; // iteration index
// a simple hash function - generates a random number between 0 and 1, based on a seed
float hash(float p) {
return fract(tan(dot(vec2(-p, p), vec2(15.1242, 2346.39))) * 274.32629);
}
float map(vec3 v) {
// if size is too big, catch so we don't crash
// this can we disabled by setting the danger mode arg to 1
if (i_args[7] == 0)
if (i_volume_size.x * i_volume_size.y * i_volume_size.z > pow(64, 3)) return voxel(v);
// color/mat_idx variables
float seedClr = i_color_index;
float bark = i_args[0];
float leaves = i_args[1];
float leavesRange = i_args[2];
// tree props
float barkHeight = i_args[3];
float leafRad = i_args[4];
float leafRand = 1 - i_args[6];
// gen tree
// 1. make bark
for (int i = v.z; i > v.z - barkHeight; i--)
if (voxel(vec3(v.x, v.y, i)) == seedClr) return bark;
// 2. make leaves
// a. find seed
for (int z = 0; z < i_volume_size.z; z++) {
for (int x = 0; x < i_volume_size.x; x++) {
for (int y = 0; y < i_volume_size.y; y++) {
if (voxel(vec3(x, y, z)) == seedClr) { // b. found seed - now we know top of tree pos
// c. make sphere on top of tree + add randomness!
if (length(v - vec3(x, y, z + barkHeight)) < leafRad && hash(v.z * v.y + v.x / v.z) > leafRand)
return leaves + floor(hash(v.z / v.x * v.y) * leavesRange);
}
}
}
}
// otherwise "leaf" things as we found them
return voxel(v);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment