Raymarching-Engine-Unity

December 27, 2023 ยท View on GitHub

A fast GPU-accelerated raymarching engine for Unity with support for over 28 primitives (including fractals, n-dimensional objects, volumetric clouds) and set operations (Union, Subtract, Intersect). Includes a custom interface for manipulating shader parameters through the editor.

https://user-images.githubusercontent.com/58925008/155891674-fdb4e1e8-3e80-447b-9439-aec03d8f34eb.mp4

Updates

v002

  • The engine now stores the dimensions of the shapes as scriptable objects, to keep multiple instances of same shape persistant across sessions.
  • Added support for Ambient Occlussion, Hard/Soft Shadows and various render setting exposed for the users to play around with.
  • Download the .unitypackage here.

Rendering the shapes provided

  • Attach Raymarcher.cs to the Main Camera and RaymarchRenderer.cs to an empty gameobject.
  • Drag the ImageEffectRaymarcher.shader in Shader field of Raymarcher.cs in inspector and direction light to the Sun's transform field.
  • Click on Create New Dimensions in the RaymarchRenderer.cs to create a scriptable object to hold the dimesnion data of the shapes.
  • You can control the following settings for the raymarching using the Raymarcher component-
    CategoryVariableDescription
    General SettingsShaderShader used for raymarching.
    SunDirectional light in the scene.
    LoopRepetition of structures in the raymarching shader.
    Light SettingsIs LitToggle lighting calculations on/off.
    Is Shadow HardToggle between hard and soft shadows.
    Is AOEnable or disable Ambient Occlusion.
    Light ColColor of the light.
    Light IntensityIntensity of the light.
    Shadow IntensityIntensity of shadows.
    Shadow MinMinimum shadow distance.
    Shadow MaxMaximum shadow distance.
    Shadow SmoothSmoothness of shadow edges.
    AO StepStep size for AO calculation.
    AO IntensityIntensity of AO.
    AO IterationNumber of iterations for AO calculation.
    Render SettingsMax StepsMaximum number of steps for raymarching.
    Max DistMaximum distance to raymarch before considering a hit.
    Surf DistThreshold for considering a hit in raymarching.
  • You can control the following properties of the individual shapes using the RaymarchRenderer componnent-
    CategoryVariableDescription
    Default InspectorShapeShape to be rendered.
    OperationOperation to be performed (union, subtraction, intersection).
    ColorColor of the shape.
    Create New DimensionsButton to create new dimenion scriptable object for the shape
    DimensionsScriptable Object holding the shape's dimension data.
    Shape DimensionsDimension PropsThe dimension properties based on the chosen 4D shape.

Rendering a custom shape

  • Append the distance function of the shape in DFs.cginc like
    float sdShape(float3 p, // dimension parameters)	
    {
        // distance function here
    }
    
  • Append the distance function created above in GetDist() in the ImageEffectRaymarcher.shader.
    float GetDist(Shape shape, float3 p) {
        switch (shape.shapeIndex) {
        case n:
            return sdShape(float3 p, // dimension parameters);
        }
    }
    
  • Add the shape data in the scriptable object ShapeDimensions.cs
    public float shapeDimension = default dimenison
    
  • Add the shape in Shape enum in RaymarchRenderer.cs
    public enum Shape {
        // shape name
    };  
    
  • Make the dimension array in Helpers.cs to be sent as a compute buffer to the Raymarching shader.
    public static vector12 GetDimensionVectors(int i)
    {
        //dimension vector12 object
    }
    
  • Finally make a custom editor for your shape in the PropertiesEditor.cs
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        RaymarchRenderer renderer = (RaymarchRenderer)target;        
         
        if (GUILayout.Button("Create New Dimensions"))
           renderer.dimensions = CreateShapeDimensionsAsset();
         
        if (renderer.dimensions == null)
           return;
    
        switch (renderer.shape)
        {
            //property editor here
        }
    }