Scene Format - v1

Table of Contents

Intro

Top
This scene format is intended to be used to define scenes for rendering as a part of a computer graphics course.
We use protobuf to define files schema (see it on GitHub). Protobuf schema is a single source of truth and it is used to generate io libraries and this document.
Data is stored as json in files with .cowscene extension (binary mode is also supported).

Structure

The top-level structure of this file is Scene. All scene objects are listed there.
Note that fields marked with "Required to implement? No" mean fields and features which are not required to be implemented as a part of the course. These fields are added for fun and experimentation purposes only.

Usage & example

Please see the example of the demo scene defined in this format (example for binary is available in our github repo). To read or write such files we provide libraries for a number of languages. These libraries support both json and binary as inputs.
It is strongly advised to use libraries we provide instead of implementing your own parser. That is because our libraries implement additional pre/postprocessing steps when reading/writing the file.

Supported languages

C#

Install SceneFormat as NuGet library

TypeScript/JavaScript

Install SceneFormat as NPM library

Java

Install SceneFormat using Gradle/Maven

C++

Read build instructions

Rust programming language logoimage/svg+xml

Rust

Install as Cargo crate.

Other languages

Please let us know if we missed some language you use. You can also build library yourself using protoc, as described in protobuf docs.

Problems? Contributions?

If you have any suggestions or would like to submit a patch, feel free to create a pull request against the scene format repo or create an issue.
Also, feel free to contact anyone from the scene format team if you have any questions or issues: @nikitavbv, @Brookokoko, @metamodern, @TheBestTvarynka, @grizik.

scene.proto

Top

BlendMaterial

Top

Representation of blend material

Field Type Default value Required to implement? Description
diffuse Color yes

specular Color yes

roughness double 0.5 yes

Camera

Top

Representation of camera
Camera can be transformed as any other point is space using transformation matrix
and camera viewport is located along negative z-axis
For more detailed explanation follow link

Field Type Default value Required to implement? Description
id int32 yes

Object id in scene.
Should be equal or greater than 1.
Should be unique across all Camera, Light and SceneObject

transform Transform yes

camera (one of) perspective PerspectiveCamera yes

orthographic OrthographicCamera no

realistic RealisticCamera no

Color

Top

Representation of RGB colors.
Components should be greater or equal 0. No upper bound
(0, 0, 0) - white
(1, 1, 1) - black
All values greater than 1 should be mapped to range [0, 1] by using gamma correction or just clamping values

Field Type Default value Required to implement? Description
r double yes

g double yes

b double yes

Cube

Top

Representation of cube (rectangular parallelepiped, to be precise.)
To determine the position of a cube look at Transform.position
Transform.scale should be ignored
If your renderer supports only axis aligned box Transform.rotation should be ignored
For more detailed explanation about aabb follow link
For those who dare to support oriented bounding box here link how obb is implemented in opengl

Field Type Default value Required to implement? Description
size Vector3 (1, 1, 1) yes

Size of cube in each dimension (in other words, you can view vector components as the length of parallelepiped sides)

CustomProperty

Top

Custom properties can be used to extend format in ways specific to implementation.
Please consider opening a PR/issue in format repo if you think your property would better be a regular field.

Field Type Default value Required to implement? Description
key string yes

value (one of) text_value string yes

int32_value int32 yes

Disk

Top

Representation of disk - surface defined by point and normal with limited radius
To determine the position of a disk look at Transform.position
To determine the normal of a disk look at Transform.up
For more detailed explanation follow link

Field Type Default value Required to implement? Description
radius double 1 yes

Radius of disk

Face

Top

Faces are defined using lists of vertex and normal indices.

Field Type Default value Required to implement? Description
elements FaceElement, repeated yes

FaceElement

Top

Field Type Default value Required to implement? Description
vertex_index int32 yes

normal_index int32 yes

texture_index int32 yes

FresnelMaterial

Top

Representation of fresnel material

Field Type Default value Required to implement? Description
color Color yes

eta double 1.5 no

r double 1 yes

Amount of reflection

t double 1 yes

Amount of transmission

LambertReflectionMaterial

Top

Representation of Lambert material
This material reflects light in all directions with equal probability
For more detailed explanation follow link

Field Type Default value Required to implement? Description
color Color yes

r double 1 yes

Amount of reflection

Light

Top

Representation of light

Field Type Default value Required to implement? Description
id int32 yes

Object id in scene.
Should be equal or greater than 1.
Should be unique across all Camera, Light and SceneObject

transform Transform yes

color Color (1, 1, 1) yes

Color of source light

light (one of) point LightPoint yes

directional LightDirectional yes

sphere LightSphere no

environment LightEnvironment yes

LightDirectional

Top

Representation of directional light
To determine the direction of a light look at Transform.forward
For more detailed explanation follow link

LightEnvironment

Top

Representation of environment light
No transformation should be applied
Direction is determined randomly
For more detailed explanation follow link

LightPoint

Top

Representation of point light
To determine the position of a light look at Transform.position
For more detailed explanation follow link
In article above this light source is named spherical light but it is actually a point light

LightSphere - not required to implement

Top


Representation of sphere light

Field Type Default value Required to implement? Description
radius double 1 yes

Radius of source light

Material

Top

Representation of material
For more detailed explanation follow link
or this link

Field Type Default value Required to implement? Description
id string yes

material (one of) lambert_reflection LambertReflectionMaterial yes

specular_reflection SpecularReflectionMaterial yes

specular_transmission SpecularTransmitionMaterial yes

fresnel FresnelMaterial yes

oren_nayar OrenNayarMaterial yes

microfacet_reflection MicrofacetReflectionMaterial yes

metal MetalMaterial yes

plastic PlasticMaterial yes

blend BlendMaterial yes

mirror MirrorMaterial yes

MeshGeometry - not required to implement

Top


Embedded obj file. Can be used to create scene files without external dependencies.
See OBJ format description on Wikipedia.

Field Type Default value Required to implement? Description
vertices Vertex, repeated yes

List of geometric vertices

vertex_normals VertexNormal, repeated yes

List of vertex normals; normals might not be unit vectors.

texture_coordinates TextureCoordinates, repeated yes

List of texture coordinates.

faces Face, repeated yes

Polygonal face element

MeshedObject

Top

Mesh specified in obj file

Field Type Default value Required to implement? Description
reference string yes

Reference to obj file.
Absolute or relative path

obj MeshGeometry no

Embedded obj file. Can be used to create scene files without external dependencies.

MetalMaterial

Top

Representation of metal material

Field Type Default value Required to implement? Description
color Color yes

r double 1 yes

Amount of reflection

eta double 1.5 yes

k double 1 yes

Extinction coefficient

roughness double 0.5 yes

MicrofacetReflectionMaterial

Top

Representation of reflection material using microfacet model

Field Type Default value Required to implement? Description
color Color yes

r double 1 yes

Amount of reflection

eta double 1.5 yes

roughness double 0 yes

MirrorMaterial

Top

Field Type Default value Required to implement? Description
color Color yes

r double 1 yes

Amount of reflection

OrenNayarMaterial

Top

Representation of diffuse material with Oren-Nayar model

Field Type Default value Required to implement? Description
color Color yes

r double 1 yes

Amount of reflection

roughness double 0 yes

OrthographicCamera - not required to implement

Top


Representation of orthographic camera

PerspectiveCamera

Top

Representation of perspective camera

Field Type Default value Required to implement? Description
fov double 60 yes

Horizontal field of view
Should be in range (0, 180)

Plane

Top

Representation of plane - unbound surface defined by point and normal
To determine the position of a plane look at Transform.position
To determine the normal of a plane look at Transform.up
For more detailed explanation follow link

PlasticMaterial

Top

Representation of plastic material

Field Type Default value Required to implement? Description
color Color yes

r double 1 yes

Amount of reflection

roughness double 0.5 yes

RealisticCamera - not required to implement

Top


Representation of realistic camera

Field Type Default value Required to implement? Description
fov double 60 yes

Horizontal field of view
Should be in range (0, 180)

focus double 1 yes

Focal length

radius double 0.01 yes

Radius of lens

RenderOptions

Top

Default options for rendering scene.
Can be overridden in renderer

Field Type Default value Required to implement? Description
camera_id int32 1 yes

Camera from which scene should be rendered

width int32 640 yes

Width of final image

height int32 320 yes

Height of final image

rayDepth int32 3 yes

Depth of path tracing

raysPerPixelDimension int32 1 yes

Number of rays per pixel dimension

custom_properties CustomProperty, repeated no

Can be used as a map containing custom properties specific to renderer implementation.
If you are using this field, consider adding it to the format spec as a regular field if you think that
other implementations may benefit from your custom fields.

Scene

Top

Field Type Default value Required to implement? Description
version int32 yes

"1" is the only allowed value at the moment.

render_options RenderOptions yes

scene_objects SceneObject, repeated yes

lights Light, repeated yes

cameras Camera, repeated yes

materials Material, repeated yes

SceneObject

Top

Representation of object to render.
A sceneObject is one of the main things of this format. It describes all the required fields to use if you want to render something.
Using this fields you can render a transformed object of any type with applied material.

SceneObject contains:
- id: defines the id which is unique across the scene.
- transform: this part has all data for transformation of the object.
- material: this part contains information about the material, which should be applied to object.
- mesh: this is the object itself.

Field Type Default value Required to implement? Description
id int32 yes

Object id in scene.
Should be equal or greater than 1.
Should be unique across all Camera, Light and SceneObject

transform Transform yes

material (one of) material_id string yes

Reference to a material in the array of materials

material Material yes

mesh (one of) sphere Sphere yes

cube Cube yes

plane Plane yes

disk Disk yes

meshed_object MeshedObject yes

SpecularReflectionMaterial

Top

Representation of specular reflection material
This material reflects light strictly in one direction which can be found by reflecting ray direction around normal
For more detailed explanation follow link

Field Type Default value Required to implement? Description
color Color yes

eta double 1.5 no

Index of refraction
The index of refraction describes how much more slowly light travels in a particular medium than in a vacuum
Index of refraction for different medium

r double 1 yes

Amount of reflection

SpecularTransmitionMaterial

Top

Representation of specular transmition material

Field Type Default value Required to implement? Description
color Color yes

eta double 1.5 no

Index of refraction
The index of refraction describes how much more slowly light travels in a particular medium than in a vacuum
Index of refraction for different medium

t double 1 yes

Amount of transmission

Sphere

Top

Representation of sphere
Transform.scale should be ignored
To determine the position of a sphere look at Transform.position
For more detailed explanation follow link

Field Type Default value Required to implement? Description
radius double 1 yes

Radius of sphere

TextureCoordinates

Top

Field Type Default value Required to implement? Description
u double yes

vary between 0 and 1.

v double 0 vary between 0 and 1. yes

w double 0 vary between 0 and 1. yes

Transform

Top

Position, rotation and scale of an object
To calculate transformation matrix:


Process using parent is specified below

Right vector can be extracted
from 1st column of the matrix if your renderer uses column-major conversion
from 1st row of the matrix if your renderer uses row-major conversion

Up vector can be extracted
from 2nd column of the matrix if your renderer uses column-major conversion
from 2nd row of the matrix if your renderer uses row-major conversion

Forward vector can be extracted
from 3rd column of the matrix if your renderer uses column-major conversion
from 3rd row of the matrix if your renderer uses row-major conversion

Detailed explanation about matrices
Explanation about different conversions

Field Type Default value Required to implement? Description
position Vector3 (0, 0, 0) yes

rotation Vector3 (0, 0, 0) yes

Rotation in euler angles.
Can be negative or positive.
Angles are measured counterclockwise.

scale Vector3 (1, 1, 1) yes

parent_id int32 0 no

Id of parent relative to which transformation should be applied.
If parent_id is 0 transformation is specified in world space.
To correctly apply transformation you should build a tree structure representing relationships between objects.
Then from top to bottom create transformation matrix.
If object has parent: multiply parent's matrix by object's matrix to get final matrix

Vector3

Top

Representation of 3D vectors and points

Field Type Default value Required to implement? Description
x double yes

y double yes

z double yes

Vertex

Top

Right-hand coordinate system is used to specify coordinate locations.

Field Type Default value Required to implement? Description
x double yes

y double yes

z double yes

w double 1.0 yes

VertexNormal

Top

Field Type Default value Required to implement? Description
x double yes

y double yes

z double yes

Intro

Top
Scalar TypeC#JavaScriptJavaC++
double double any double double
float float any float float
int32 int any int int32
int64 long any long int64
uint32 uint any int uint32
uint64 ulong any long uint64
sint32 int any int int32
sint64 long any long int64
fixed32 uint any int uint32
fixed64 ulong any long uint64
sfixed32 int any int int32
sfixed64 long any long int64
bool bool any boolean bool
string string any String string
bytes ByteString any ByteString string

JSON example

Top
Scene examples to check if your program works with format correctly.
Only focus on the general look of a scene, outputs may not be identical. Colors may wary from renderer to renderer and light sources might be too bright.
Scenes without light sources are rendered only with normals to show how objects should look. Scenes with light sources and materials are rendered using Whitted raytracing.
Parameters for Whitted raycaster:
        {
  "version": 1,
  "renderOptions": {
    "cameraId": 1,
    "width": 640,
    "height": 360
  },
  "cameras": [
    {
      "id": 1,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 6
        }
      },
      "perspective": {
        "fov": 60
      }
    }
  ],
  "sceneObjects": [
    {
      "id": 2,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "sphere": {
        "radius": 1.5
      }
    }
  ]
}
        
        sphere
        {
  "version": 1,
  "renderOptions": {
    "cameraId": 1,
    "width": 640,
    "height": 360
  },
  "cameras": [
    {
      "id": 1,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 6
        }
      },
      "perspective": {
        "fov": 60
      }
    }
  ],
  "sceneObjects": [
    {
      "id": 2,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "cube": {
        "size": {
          "x": 2,
          "y": 1,
          "z": 1
        }
      }
    }
  ]
}
        
        cube
        {
  "version": 1,
  "renderOptions": {
    "cameraId": 1,
    "width": 640,
    "height": 360
  },
  "cameras": [
    {
      "id": 1,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 6
        }
      },
      "perspective": {
        "fov": 60
      }
    }
  ],
  "sceneObjects": [
    {
      "id": 2,
      "transform": {
        "position": {
          "x": 0,
          "y": -1,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "plane": {}
    }
  ]
}
        
        plane
        {
  "version": 1,
  "renderOptions": {
    "cameraId": 1,
    "width": 640,
    "height": 360
  },
  "cameras": [
    {
      "id": 1,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 6
        }
      },
      "perspective": {
        "fov": 60
      }
    }
  ],
  "sceneObjects": [
    {
      "id": 2,
      "transform": {
        "position": {
          "x": 0,
          "y": -1,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "disk": {
        "radius": 5
      }
    }
  ]
}
        
        disk
        {
  "version": 1,
  "renderOptions": {
    "cameraId": 1,
    "width": 640,
    "height": 360
  },
  "cameras": [
    {
      "id": 1,
      "transform": {
        "position": {
          "x": 0,
          "y": 0.3,
          "z": 1.2
        }
      },
      "perspective": {
        "fov": 60
      }
    }
  ],
  "sceneObjects": [
    {
      "id": 2,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "meshed_object": {
        "reference": "cow2.obj"
      }
    }
  ]
}
        
        mesh
        {
  "version": 1,
  "renderOptions": {
    "cameraId": 1,
    "width": 640,
    "height": 360
  },
  "cameras": [
    {
      "id": 1,
      "transform": {
        "position": {
          "x": 3,
          "y": 3,
          "z": 6
        },
        "rotation": {
          "x": -25,
          "y": 25,
          "z": 0
        }
      },
      "perspective": {
        "fov": 60
      }
    }
  ],
  "sceneObjects": [
    {
      "id": 2,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "cube": {
        "size": {
          "x": 2,
          "y": 1,
          "z": 1
        }
      }
    }
  ]
}
        
        camera_rotation
        {
  "version": 1,
  "renderOptions": {
    "cameraId": 1,
    "width": 640,
    "height": 360
  },
  "cameras": [
    {
      "id": 1,
      "transform": {
        "position": {
          "x": 1.25,
          "y": 0.1,
          "z": 0
        },
        "rotation": {
          "x": 10,
          "y": 90,
          "z": 0
        }
      },
      "perspective": {
        "fov": 60
      }
    }
  ],
  "sceneObjects": [
    {
      "id": 2,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 0
        },
        "scale": {
          "x": 0.4,
          "y": 1,
          "z": 4
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "meshed_object": {
        "reference": "cow2.obj"
      }
    }
  ]
}
        
        transformations
        {
  "version": 1,
  "renderOptions": {
    "cameraId": 2,
    "width": 640,
    "height": 360
  },
  "cameras": [
    {
      "id": 1,
      "transform": {
        "position": {
          "x": 1.25,
          "y": 0.1,
          "z": 0
        },
        "rotation": {
          "x": 10,
          "y": 90,
          "z": 0
        }
      },
      "perspective": {
        "fov": 60
      }
    },
    {
      "id": 2,
      "transform": {
        "position": {
          "x": 0,
          "y": 0.3,
          "z": 1.2
        }
      },
      "perspective": {
        "fov": 100
      }
    }
  ],
  "sceneObjects": [
    {
      "id": 3,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 0
        },
        "scale": {
          "x": 0.4,
          "y": 1,
          "z": 4
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "meshed_object": {
        "reference": "cow2.obj"
      }
    }
  ]
}
        
        multiple_cameras
        {
  "version": 1,
  "renderOptions": {
    "cameraId": 1,
    "width": 640,
    "height": 360
  },
  "cameras": [
    {
      "id": 1,
      "transform": {
        "position": {
          "x": 0,
          "y": 1,
          "z": 3
        },
        "rotation": {
          "x": -10,
          "y": 0,
          "z": 0
        }
      },
      "perspective": {
        "fov": 60
      }
    }
  ],
  "sceneObjects": [
    {
      "id": 2,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 1
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "meshed_object": {
        "reference": "cow2.obj"
      }
    },
    {
      "id": 3,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": -1
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "meshed_object": {
        "reference": "dragon.obj"
      }
    },
    {
      "id": 4,
      "transform": {
        "position": {
          "x": 1.1,
          "y": 0,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "sphere": {
        "radius": 0.3
      }
    },
    {
      "id": 5,
      "transform": {
        "position": {
          "x": -1.1,
          "y": 0,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "cube": {
        "size": {
          "x": 0.3,
          "y": 0.3,
          "z": 0.3
        }
      }
    }
  ]
}
        
        multiple_objects
        {
  "version": 1,
  "renderOptions": {
    "cameraId": 1,
    "width": 640,
    "height": 360
  },
  "cameras": [
    {
      "id": 1,
      "transform": {
        "position": {
          "x": 0,
          "y": 1,
          "z": 5
        },
        "rotation": {
          "x": 0,
          "y": 0,
          "z": 0
        }
      },
      "perspective": {
        "fov": 60
      }
    }
  ],
  "sceneObjects": [
    {
      "id": 2,
      "transform": {
        "position": {
          "x": 0,
          "y": 1,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "sphere": {
        "radius": 1
      }
    },
    {
      "id": 3,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 0,
            "b": 0
          }
        }
      },
      "disk": {
        "radius": 10
      }
    }
  ],
  "lights": [
    {
      "id": 4,
      "color": {
        "r": 3,
        "g": 3,
        "b": 3
      },
      "environment": {}
    }
  ]
}
        
        lambert
        {
  "version": 1,
  "renderOptions": {
    "cameraId": 1,
    "width": 640,
    "height": 360
  },
  "cameras": [
    {
      "id": 1,
      "transform": {
        "position": {
          "x": 0,
          "y": 1,
          "z": 5
        },
        "rotation": {
          "x": 0,
          "y": 0,
          "z": 0
        }
      },
      "perspective": {
        "fov": 60
      }
    }
  ],
  "sceneObjects": [
    {
      "id": 2,
      "transform": {
        "position": {
          "x": 0,
          "y": 1,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 0,
            "g": 0,
            "b": 1
          }
        }
      },
      "sphere": {
        "radius": 1
      }
    },
    {
      "id": 3,
      "transform": {
        "position": {
          "x": 2,
          "y": 1,
          "z": 1
        }
      },
      "material": {
        "specular_reflection": {
          "eta": 2
        }
      },
      "sphere": {
        "radius": 1
      }
    },
    {
      "id": 4,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 0,
            "b": 0
          }
        }
      },
      "disk": {
        "radius": 10
      }
    }
  ],
  "lights": [
    {
      "id": 5,
      "color": {
        "r": 3,
        "g": 3,
        "b": 3
      },
      "environment": {}
    }
  ]
}
        
        reflection
        {
  "version": 1,
  "renderOptions": {
    "cameraId": 1,
    "width": 640,
    "height": 360
  },
  "cameras": [
    {
      "id": 1,
      "transform": {
        "position": {
          "x": 0,
          "y": 1,
          "z": 5
        },
        "rotation": {
          "x": 0,
          "y": 0,
          "z": 0
        }
      },
      "perspective": {
        "fov": 60
      }
    }
  ],
  "sceneObjects": [
    {
      "id": 2,
      "transform": {
        "position": {
          "x": 0,
          "y": 1,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "sphere": {
        "radius": 1
      }
    },
    {
      "id": 3,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 0,
            "b": 0
          }
        }
      },
      "disk": {
        "radius": 10
      }
    }
  ],
  "lights": [
    {
      "id": 4,
      "transform": {
        "position": {
          "x": 0,
          "y": 2,
          "z": 2
        }
      },
      "color": {
        "r": 100,
        "g": 100,
        "b": 100
      },
      "point": {}
    }
  ]
}
        
        point
        {
  "version": 1,
  "renderOptions": {
    "cameraId": 1,
    "width": 640,
    "height": 360
  },
  "cameras": [
    {
      "id": 1,
      "transform": {
        "position": {
          "x": 0,
          "y": 1,
          "z": 5
        },
        "rotation": {
          "x": 0,
          "y": 0,
          "z": 0
        }
      },
      "perspective": {
        "fov": 60
      }
    }
  ],
  "sceneObjects": [
    {
      "id": 2,
      "transform": {
        "position": {
          "x": 0,
          "y": 1,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 1,
            "b": 1
          }
        }
      },
      "sphere": {
        "radius": 1
      }
    },
    {
      "id": 3,
      "transform": {
        "position": {
          "x": 0,
          "y": 0,
          "z": 0
        }
      },
      "material": {
        "lambert_reflection": {
          "color": {
            "r": 1,
            "g": 0,
            "b": 0
          }
        }
      },
      "disk": {
        "radius": 10
      }
    }
  ],
  "lights": [
    {
      "id": 4,
      "transform": {
        "rotation": {
          "x": -30,
          "y": -100,
          "z": 0
        }
      },
      "color": {
        "r": 3,
        "g": 3,
        "b": 3
      },
      "directional": {}
    }
  ]
}
        
        directional