• Stars
    star
    100
  • Rank 329,736 (Top 7 %)
  • Language
    C
  • License
    GNU General Publi...
  • Created over 3 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Signed is a 3D modeling and construction language based on Lua and SDFs. Signed will be available for macOS and iOS and is heavily optimized for Metal.

Signed - A 3D modeling language

screenshot

Abstract

Signed is a Lua based 3D modeling language, it provides a unique way to create high quality 3D content for your game or visualization.

Artist driven workflows of the major 3D editing packages are great, for artists. Developers still have a hard time creating high quality content for their games and Signed hopes to fill this gap.

Signed itself is a development language, but it will over time provide tools to dynamically visualize for example paths and areas while typing.

Signed will be available for macOS and iPad OS and is heavily optimized for Metal.

How it works

Signed executes SDF modeling and material commands into a 3D texture utilizing Disney BSDF materials. A full featured BSDF path tracer is included. The content of the 3D texture will can be exported to OBJ.

Signed is based on Lua, a fast and easy to learn scripting language which provides the foundation for the Signed workflow.

You can create objects, materials and modules (language extensions) in your project and even share them in the public database (thus expanding the available language).

Lua

Signed is based on Lua. I will not teach you Lua here but there are many resources available on the net. Lua is popular because it is fast and can be easily extended via modules. For more information please visit Lua.org.

Modeling Commands

The following code creates a slightly rounded, reflective red box at the center of your available 3D space.

local bbox = bbox:new()

local box = command:newShape("Box")
box:set("position", bbox.center)
box:set("size", 1, 1, 1)
box:set("rounding", 0.1)
box:set("color", 1, 0, 0)
box:set("roughness", 0.2)
box:execute(0)

The execute call models the box, the parameter for execute is the material index for the modeling call. You can later re-use this material id to stack any amount of material layers.

Different shapes support different geometry parameters, selecting the shape icon in Signed will show a list of the supported parameters of the shape.

To change the boolean mode of the command:

box:set("mode", "subtract")
box:set("smoothing", 0.1)

This would subtract the shape from the content in the 3D texture, other modes are "add" (the default) and "intersect". The smoothing parameter allows for smooth boolean operations.

Coordinates and Bounding Boxes

The coordinate 0, 0, 0 is the center of the 3D texture, with positive X and Y coordinates pointing right and up and positive Z pointing away from the observer.

The extent of the available modeling space is the 3D texture size divided by the pixel per meter parameter. Both can be changed in the settings of the current scene. A 3D texture size of 500x500x500 and 100 pixels per meter would give a total available modeling space of 5 meters.

The bounding box (bbox) module helps to provide more context as it provides a lot of helper functions and members like left, right, top, bottom, front and back (all numbers) and center, size and the rotation (all vec3).

The default bounding box can be created with

local bbox = bbox:new()

and encapsulates the available 3D modeling space. Bounding boxes are heavily used by objects.

All functionality in Signed is available via public modules, selecting a module will show the implementation and detailed help in the source code.

Objects

Objects help to bundle a set of modeling commands into re-usable components called objects. Adding objects to your project and sharing them with the community is one the core functions of Signed.

Let's consider this simple example object, called Sphere:

function buildObject(index, bbox, options)
    -- options
    local radius = options.radius or 1.0

    local cmd = command:newShape("Sphere")
    cmd:set("position", bbox.center)
    cmd:set("radius", radius)

    bbox:execute(cmd, index)
end

-- Default size for preview rendering
function defaultSize()
    return vec3(1, 1, 1)
end

You will note that an object definition gets it's own bounding box, together with the base material index and the options table.

Important here is to note that we do not call the cmd:execute() function but the execute function of the bbox and pass it the command and material index. We do this so that rotated bounding boxes can modify the rotation parameters of the cmd to correctly rotate around the center of the bounding box.

To instantiate an object (from either your project or an arbitrary object from the public database) use something like this:

local pos = vec3(bbox.center.x + (bbox.right - bbox.center.x) / 2, bbox.center.y, bbox.center.z)
local size = vec3(bbox.right - bbox.center.x, bbox.size.y, bbox.size.z)

local obj = command:newObject("Sphere", bbox:new(pos, size))
obj:execute(0, { radius: 1.5 })

This models the Sphere object in the right half of the global bounding box. We create the bounding box and pass it to the newObject() function of the command class.

We then execute the object with the material index and the options we want to pass.

The bounding box is created by passing three vec3, the first one is the position (or center) of the bbox, the second parameter is the size. The third parameter is the rotation of the bbox which is here just a 0 vector (and could be omitted).

As with the modules, selecting an object will show it's source code and clicking the "Build" button will build the preview of the object. Examining the source code of object's is a good way to learn more about Signed (and Lua if you are not yet familiar with the language).

Standalone Materials

So far we have created shapes together with their materials. As mentioned earlier, we can stack materials by applying standalone material commands.

local material = command:newMaterial("Gold")
material:setBlendMode("valuenoise", {
    offset = vec3(0,0,0);
    frequency = 3;
    smoothing = 6; -- octaves
})
material:execute(10)

The above would load the gold material from the database and apply it to all shapes which have an material index of 10. This particular command uses a value noise to blend the gold material over the existing material, you could also use linear blending:

material:setBlendMode("linear", {
    value = 0.6;
})

To create a a default material do not provide a material name when calling newMaterial.

You can also copy a material from the library to your shape command:

local material = command:newMaterial("Gold")
local box = command:newShape("Box")
box:copyMaterial(material)
...

Materials support the full Disney BSDF parameter set.

Modules

Modules are an important part of Signed in that they provide a shareable way to extend the language. As with objects and materials, users can add a module to their project, develop it, test it and optionally upload it to the public database.

You can use the require function to load modules dynamically.

For example to create a wall with Signed, you can use the user supplied path2d and wallbuilder modles:

require("path2d")
require("wallbuilder")

local backPath = path2d:new() -- Create a line
backPath:moveTo(vec2(-2.3, -2))
backPath:lineTo(vec2(2.5, -2))

local builder = wallbuilder:new(backPath) -- Create a wall builder based on the given path
builder.brickSize = vec3(0.40, 0.30, 0.30) -- Adjust the brickSize and height of the wall.
builder.height = 4.6
builder:build((function(cmd, column, row)
    --[[ When building the wall this function is called with the modeling command and the brick
    column and row number of the current brick. We can use the modeling command to modify any aspect of the shape or material on a per brick basis.
    Here we slightly rotate the brick randomly around the Y axis to make it look a bit less uniform, modify it's color randomly a bit and set its roughness and specular options.
    --]]
    local rotation = cmd:getVec3("rotation")
    rotation.y = rotation.y + 40 * (math.random() - 0.5)
    cmd:setVec3("rotation", rotation)
    local rand = math.random() / 2
    local color = vec3(0.9 * rand,0.9 * rand,0.9 * rand)
    cmd:setVec3("color", color)
    cmd:setNumber("roughness", 0.2)
    cmd:setNumber("specular", 1)
    cmd:execute(5)
end
))

Over time convenience modules will be added to Signed to make building complex objects and structures easier.

License

Signed is licensed under the GPL, this is mostly to prevent others uploading copies to the AppStore. Everything you create inside Signed is of course under your copyright.

I only ask to make objects, materials and modules you may upload to the public database free of any proprietory licenses and free to use and consume for everybody.

Acknowledgements

  • Inigo Quilez was my original inspiration for starting with signed distance functions, you can see his amazing work on Shadertoy and his research on his website.

  • Fabrice Neyret and his shaders were a great learning resource as well, he was also extremely helpful in answering questions. His research is here.

  • The Disney BSDF path tracer in Signed is based on GLSL-PathTracer from Asif.

More Repositories

1

Eldiron

Create cross platform retro RPGs in 2D and 3D. Written in Rust.
Rust
336
star
2

ShaderMania

A Metal fragment shader editor for macOS and iOS
Swift
289
star
3

ForgedThoughts

A 3D modeling and rendering programming language utilizing SDFs.
Rust
45
star
4

richtextjs

A standalone rich text editor based on the 2d canvas
JavaScript
41
star
5

Render-Z

A visual Metal shader editor for macOS and iPadOS
Swift
36
star
6

viralgraphics.io

Creating Competitive Desktop Applications for the Web
JavaScript
33
star
7

Fabricated

A procedural game asset generator for macOS and iOS
Swift
27
star
8

Denrim

Unique text based 2D game creator for macOS, iOS and tvOS
Swift
20
star
9

rust-pathtracer

A principled BSDF pathtracer with an abstracted backend. Perfect for rendering procedural content.
Rust
16
star
10

jsenginewrapper

Easy to use JavaScript Engine Wrapper for v8 and SpiderMonkey
C++
13
star
11

code_editor

A standalone code editor with syntax highlighting and themes.
Rust
13
star
12

raycaster

A Raycaster engine written in Rust
Rust
13
star
13

Carthage

A light weight game engine for the Apple Ecosystem acting as an abstraction layer for SceneKit and RealityKit. Carthage will be available for macOS and iOS.
Swift
11
star
14

metalRay

Code games in Swift and C in this "down to the metal" game framework for Xcode
Swift
9
star
15

RPU_OLD

A procedural 2D and 3D scene definition language with integrated scripting and shaders.
Rust
7
star
16

SwiftNoise

A library of tillable, procedural noise and pattern functions. Implemented in Swift and utilizes the Surge Library.
Swift
7
star
17

DenrimScript

Scripting language for Swift with upcoming GPU support
Swift
4
star
18

TheFramework

A cross platform application framework for Rust with UI and visual coding support.
Rust
4
star
19

noises-and-patterns

A creator library for procedural 2D noises and patterns in Rust.
Rust
3
star
20

Xcode2Rust

Make Rust based 2D games and apps accessible in Xcode
Swift
3
star
21

DenrimPlayer

A player for Denrim Games for macOS, iOS and tvOS
Objective-C
2
star
22

Raytraced

Swift
1
star
23

MetalMania

Swift
1
star
24

Eldiron-Demo

An online demo for Eldiron. Work in progress.
JavaScript
1
star
25

Eldiron-Website

Website of Eldiron.com
1
star
26

markusmoenig

1
star
27

Eldiron-Web

CSS
1
star
28

ForgedThoughts-Web

JavaScript
1
star
29

TheRenderer

A fast 2D renderer for your applications or games written in Rust.
Rust
1
star
30

Cellua

Swift
1
star
31

Eldiron-Book

The documentation source files for Eldiron
CSS
1
star
32

DungeonHost

Swift
1
star
33

Signed

Rust
1
star