• Stars
    star
    2,466
  • Rank 18,648 (Top 0.4 %)
  • Language
    JavaScript
  • License
    Other
  • Created over 11 years ago
  • Updated almost 9 years ago

Reviews

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

Repository Details

Flat Surface Shader for rendering illuminated triangles

Flat Surface Shader [FSS]

Simple, lightweight Flat Surface Shader written in JavaScript for rendering lit Triangles to a number of contexts. Currently there is support for WebGL, Canvas 2D and SVG. Check out this demo to see it in action.

Understanding Lighting

Simply put, FSS uses the Lambertian Reflectance model to calculate the color of a Triangle based on an array of Light sources within a Scene.

Light

A Light is composed of a 3D position Vector and 2 Color objects defining its ambient & diffuse emissions. These color channels interact with the Material of a Mesh to calculate the color of a Triangle.

Triangle

A Triangle is constructed from 3 Vertices which each define the x, y and z coordinates of a corner. Based on these 3 Vertices, a forth 3D Vector is automatically derived at the center of the Triangle – this is known as its Centroid. Alongside the Centroid, a fifth unit Vector is automatically calculated which defines the surface Normal. The Normal describes the direction that the Triangle is facing.

Geometry

Geometry is simply a collection of triangles – nothing more.

Material

A Material is composed of 2 Color objects which define the ambient & diffuse properties of a surface.

Mesh

A Mesh is constructed from a Geometry object and a Material object. All the Triangles within the Geometry are rendered using the properties of the Material.

Scene

A Scene sits at the very top of the stack. It simply manages arrays of Mesh & Light objects.

Renderer

The Renderer takes all the information in a Scene and renders it to a context. Currently FSS supports WebGL, Canvas 2D and SVG.

Calculation

For every Triangle in a Scene the following calculation is performed:

  1. A Vector between the Triangle's Centroid and the Light's Position is calculated and normalised. This can be considered as a single Ray travelling from the Light to the center of the Triangle.
  2. The angle beween this Ray and the Normal of the Triangle is then calculated using the dot product. This angle is simply a number ranging from -1 to 1. When the Ray and the Normal are coincident, this value is 0, and when they are perpendicular to one another, this value is 1. This value goes into the negative range when the Light is behind the Triangle.
  3. Firstly, the diffuse color of the Light is multiplied by the diffuse color of the Material associated with the Triangle. This color is then multiplied by the coincidence angle described above. For example, if the diffuse color of the Light is #FFFFFF { R:1, G:1, B:1 } and the diffuse color of the Material is #FF0000 { R:1, G:0, B:0 }, the combined color would be #FF0000 { R:1*1=1, G:1*0=0, B:1*0=0 }. If the coincidence angle was 0.5, the final color of the Triangle would be #800000 { R:1*0.5=0.5, G:0*0.5=0, B:0*0.5=0 }.
  4. In much the same way as above, the ambient color of the Light is multipled by the ambient color of the Material. Since ambient light is a uniform dissipation of scattered light, it is not modified any further.
  5. The final color of the Triangle is simply calculated by adding the diffuse & ambient colors together. Simples.

Example

NOTE: All objects exist within the FSS namespace.

// 1) Create a Renderer for the context you would like to render to.
//    You can use either the WebGLRenderer, CanvasRenderer or SVGRenderer.
var renderer = new FSS.CanvasRenderer();

// 2) Add the Renderer's element to the DOM:
var container = document.getElementById('container');
container.appendChild(renderer.element);

// 3) Create a Scene:
var scene = new FSS.Scene();

// 4) Create some Geometry & a Material, pass them to a Mesh constructor, and add the Mesh to the Scene:
var geometry = new FSS.Plane(200, 100, 4, 2);
var material = new FSS.Material('#444444', '#FFFFFF');
var mesh = new FSS.Mesh(geometry, material);
scene.add(mesh);

// 5) Create and add a Light to the Scene:
var light = new FSS.Light('#FF0000', '#0000FF');
scene.add(light);

// 6) Finally, render the Scene:
renderer.render(scene);

Building

Install Dependancies:

npm install [email protected]

Build:

node build.js

Inspiration

Please also checkout the case study on Behance created by my dear friend Tobias van Schneider – @schneidertobias.

Acknowledgments

The architecture of this project was heavily influenced by three.js and the implementation of the Vector calculations was taken from glMatrix.

Author

Matthew Wagerfield: @mwagerfield

License

Licensed under MIT. Enjoy.

More Repositories

1

parallax

Parallax Engine that reacts to the orientation of a smart device
JavaScript
16,466
star
2

cssmixins

CSS3 mixins for STYL, SCSS, SASS & LESS.
513
star
3

onno

Tiny (596B) utility for composing class variants using clsx
TypeScript
107
star
4

nuxt-typescript

TypeScript module for Nuxt
JavaScript
90
star
5

nuxt-stack

Suite of modules and commands for building performant applications with zero configuration
JavaScript
66
star
6

axonometric-projection

2.5D Axonometric Projection Engine
JavaScript
60
star
7

cinnamon

Lean boilerplate for front-end projects
JavaScript
36
star
8

ig-api

Axios wrapper around IG's API
JavaScript
25
star
9

eslint-index

CLI for finding and managing rules in ESLint config files
JavaScript
20
star
10

storybook-tailwind

Storybook with Tailwind 2 JIT and PostCSS 8
JavaScript
19
star
11

vue-fela

Fela plugin for Vue
JavaScript
17
star
12

vue-pwa-installer

Vue interface for installing Progressive Web Apps
JavaScript
14
star
13

cinema4D

Useful resources for Cinema 4D
8
star
14

girder

Powerful utility classes, an evolved mouse, useful display classes, advanced drawing methods, comprehensive video components with plug and play gui, project navigation classes, file loading, third party framework layers, and much, much more!
ActionScript
8
star
15

vue-static-data

Add static data to Vue instances
JavaScript
7
star
16

xrc

React component library written in TypeScript and styled with emotion and onno
TypeScript
7
star
17

nd-physics

Dimension Agnostic Physics Engine
JavaScript
7
star
18

colorgasm

WebAudio Visualiser inspired by Nina Geometrieva's Colorgasm
JavaScript
6
star
19

pinscreen

WebGL Pinscreen
JavaScript
6
star
20

nuxtflix

Nuxt + Netlify + Contentful = Awesome
JavaScript
6
star
21

cursor

Complete list of CSS cursor values (auto, pointer, help, etc.)
5
star
22

inferno-fuse-box

Inferno starter project using FuseBox and TypeScript
JavaScript
2
star
23

playgroup

Collaborative Play using WebRTC
2
star
24

aperture

Depth of Field Calculator
2
star
25

jasmine-custom-matchers

Custom matchers for Jasmine Behaviour Driven Development Framework
JavaScript
2
star
26

danbo

Danbo brought to the web in CSS3D
2
star
27

xrc-framer

XRC FramerX Project & Components
TypeScript
2
star
28

i18next-hmr-hook

i18next HMR React Hook Demo
JavaScript
2
star
29

gulp-spritezero

Gulp plugin for spritezero
JavaScript
1
star
30

vue-tabbing

Tabbing navigation utility for Vue
JavaScript
1
star
31

interface

Reactive User Interface
1
star
32

nuxt-base

Base module for Nuxt.js
JavaScript
1
star
33

next-fetch-from-static

Attempt to statically export pages with dynamic JSON
JavaScript
1
star
34

fela-base

Fela Preset & Rules
TypeScript
1
star
35

framer-boilerplate

Rapid, automated boilerplate project for creating prototypes with Framer
JavaScript
1
star
36

unscene

2D Graphics Library
TypeScript
1
star