diff --git a/README.md b/README.md index 8e3c1f6..21e524f 100644 --- a/README.md +++ b/README.md @@ -7,19 +7,6 @@ https://avik-das.github.io/build-your-own-raytracer/ ## Getting Started -This uses webpack for the build process. -As of lesson 1, there is no `webpack.config.js`, just run webpack since -`index.js` is in `src/` and the default build of `dist/main.js` works. +Clone this repository and from it run `npm i`. -## Progress - -- [x] Lesson 1 -- [x] Lesson 2 -- [x] Lesson 3 -- [x] Lesson 4 -- [x] Lesson 5 -- [x] Lesson 6 -- [x] Create Visible Light Sources -- [x] Try with bigger image -- [x] Try skewed camera -- [ ] \ No newline at end of file +Create 8 solar system images with `node src/index.js SolarSystem`. \ No newline at end of file diff --git a/data/components/Colors.yml b/data/components/Colors.yml index 71dc4f3..e45c4e7 100644 --- a/data/components/Colors.yml +++ b/data/components/Colors.yml @@ -1,14 +1,35 @@ +Blue: + size: .5 + ambient: [0, 0, .3] + diffuse: [0, 0, 1] + spec: [.2, .2, .5] + shine: 5 + +Gray: + size: .5 + ambient: [.3, .3, .3] + diffuse: [.5, .5, .5] + spec: [.5, .5, .5] + shine: 5 + LimeGreen: size: .5 ambient: [.2, .3, .2] diffuse: [.2, .8, .2] spec: [.2, .5, .2] shine: 5 - -Gray: + +Red: size: .5 + ambient: [.3, 0, 0] + diffuse: [1, 0, 0] + spec: [.5, .2, .2] + shine: 5 + +S-White: + size: .2 ambient: [.3, .3, .3] - diffuse: [.5, .5, .5] + diffuse: [1, 1, 1] spec: [.5, .5, .5] shine: 5 \ No newline at end of file diff --git a/data/components/Lights.yml b/data/components/Lights.yml index 59cecd3..45fa35f 100644 --- a/data/components/Lights.yml +++ b/data/components/Lights.yml @@ -18,6 +18,6 @@ RedLight: Flame: isLight: true light: - diffuse: [1, 0, 0] - spec: [1, 0, 0] - size: 1 \ No newline at end of file + diffuse: [1, .8, 0] + spec: [1, 1, 1] + size: .2 \ No newline at end of file diff --git a/data/components/Shoes.yml b/data/components/Shoes.yml new file mode 100644 index 0000000..c2a82c8 --- /dev/null +++ b/data/components/Shoes.yml @@ -0,0 +1,7 @@ + +WoodenShoe: + size: .2 + ambient: [.5, .4, .2] + diffuse: [0.59, 0.44, .2] + spec: [.5, .44, .2] + shine: 5 \ No newline at end of file diff --git a/data/objects/Characters.yml b/data/objects/Characters.yml new file mode 100644 index 0000000..160e215 --- /dev/null +++ b/data/objects/Characters.yml @@ -0,0 +1,32 @@ + +importComponents: + - Colors + - Shoes + +define: + MainCharacter: + place: + - name: LeftShoe + obj: Shoes.WoodenShoe + loc: [0, .7, .3] + - name: RightShoe + obj: Shoes.WoodenShoe + loc: [0, .7, -0.3] + - name: LowerBody + obj: Colors.Blue + loc: [0, 1.2, 0] + - name: UpperBody + obj: Colors.Red + loc: + from: LowerBody + dir: [0, .7, 0] + - name: LeftHand + obj: Colors.S-White + loc: + from: UpperBody + dir: [0, 0, .7] + - name: RightHand + obj: Colors.S-White + loc: + from: UpperBody + dir: [0, 0, -0.7] \ No newline at end of file diff --git a/data/objects/Lights.yml b/data/objects/Lights.yml index 463c46a..740aadf 100644 --- a/data/objects/Lights.yml +++ b/data/objects/Lights.yml @@ -1,6 +1,7 @@ importComponents: - - Lights + - Lights + - Nature define: Flame: @@ -8,6 +9,27 @@ define: - name: Light obj: Lights.Flame loc: [0, 1, 0] + Torch: + place: + - name: Stick + obj: Nature.Stick + loc: [0, .6, 0] + - name: Stick + obj: Nature.Stick + loc: + from: Stick + dir: [0, .2, 0] + - name: Stick + obj: Nature.Stick + loc: + from: Stick + dir: [0, .2, 0] + - name: Fire + obj: Lights.Flame + loc: + from: Stick + dir: [0, .3, 0] + WhiteLight: place: - name: Light diff --git a/data/objects/SolarSystem.yml b/data/objects/SolarSystem.yml index 0d5e53d..8723334 100644 --- a/data/objects/SolarSystem.yml +++ b/data/objects/SolarSystem.yml @@ -80,11 +80,4 @@ define: from: Sun random: [ [ -1, 1 ], [ 0, 0 ], [ -1, 1 ] ] scale: [21, 0, 21] - - - name: Mirror (Test) - obj: Utils.MirrorBall - loc: - from: Sun - random: [ [ -1, 1 ], [ 0, 0 ], [ -1, 1 ] ] - scale: [9, 0, 9] \ No newline at end of file diff --git a/data/objects/Structures.yml b/data/objects/Structures.yml index db1019b..e907bf5 100644 --- a/data/objects/Structures.yml +++ b/data/objects/Structures.yml @@ -1,8 +1,147 @@ importComponents: - Colors + - Nature define: + XFence: + place: + + - name: CenterPost + obj: Nature.Stick + loc: [0, .6, 0] + - name: CenterPostLower + obj: Nature.Stick + loc: + from: CenterPost + dir: [0, .2, 0] + - name: CenterPost + obj: Nature.Stick + loc: + from: CenterPostLower + dir: [0, .2, 0] + - name: CenterPostHigher + obj: Nature.Stick + loc: + from: CenterPost + dir: [0, .2, 0] + - name: CenterPost + obj: Nature.Stick + loc: + from: CenterPostHigher + dir: [0, .2, 0] + + - name: LowerLeft + obj: Nature.Stick + loc: + from: CenterPostLower + dir: [-0.2, 0, 0] + - name: LowerLeft + obj: Nature.Stick + loc: + from: LowerLeft + dir: [-0.2, 0, 0] + - name: LowerRight + obj: Nature.Stick + loc: + from: CenterPostLower + dir: [0.2, 0, 0] + - name: LowerRight + obj: Nature.Stick + loc: + from: LowerRight + dir: [0.2, 0, 0] + + - name: UpperLeft + obj: Nature.Stick + loc: + from: CenterPostHigher + dir: [-0.2, 0, 0] + - name: UpperLeft + obj: Nature.Stick + loc: + from: UpperLeft + dir: [-0.2, 0, 0] + - name: UpperRight + obj: Nature.Stick + loc: + from: CenterPostHigher + dir: [0.2, 0, 0] + - name: UpperRight + obj: Nature.Stick + loc: + from: UpperRight + dir: [0.2, 0, 0] + + ZFence: + place: + + - name: CenterPost + obj: Nature.Stick + loc: [0, .6, 0] + - name: CenterPostLower + obj: Nature.Stick + loc: + from: CenterPost + dir: [0, .2, 0] + - name: CenterPost + obj: Nature.Stick + loc: + from: CenterPostLower + dir: [0, .2, 0] + - name: CenterPostHigher + obj: Nature.Stick + loc: + from: CenterPost + dir: [0, .2, 0] + - name: CenterPost + obj: Nature.Stick + loc: + from: CenterPostHigher + dir: [0, .2, 0] + + - name: LowerClose + obj: Nature.Stick + loc: + from: CenterPostLower + dir: [0, 0, -0.2] + - name: LowerClose + obj: Nature.Stick + loc: + from: LowerClose + dir: [0, 0, -0.2] + - name: LowerFar + obj: Nature.Stick + loc: + from: CenterPostLower + dir: [0, 0, 0.2] + - name: LowerFar + obj: Nature.Stick + loc: + from: LowerFar + dir: [0, 0, 0.2] + + - name: UpperClose + obj: Nature.Stick + loc: + from: CenterPostHigher + dir: [0, 0, -0.2] + - name: UpperClose + obj: Nature.Stick + loc: + from: UpperClose + dir: [0, 0, -0.2] + - name: UpperFar + obj: Nature.Stick + loc: + from: CenterPostHigher + dir: [0, 0, 0.2] + - name: UpperFar + obj: Nature.Stick + loc: + from: UpperFar + dir: [0, 0, 0.2] + XWall: place: - name: Bottom diff --git a/data/scenes/Demo1.yml b/data/scenes/Demo1.yml new file mode 100644 index 0000000..31ca17c --- /dev/null +++ b/data/scenes/Demo1.yml @@ -0,0 +1,64 @@ + +importObjects: + - Characters + - Lights + - Plants + - SingleSpheres + - Structures + +layTurf: + type: grass + x: 10 + z: 10 + +place: + + - name: Light + obj: Lights.WhiteLight + loc: [ 0, 10, 3 ] + + - name: MainCharacter + obj: Characters.MainCharacter + loc: [0, 0, 0] + + - name: Torch + obj: Lights.Torch + loc: [-3, 0, -3] + + - name: Tree + obj: Plants.Tree + loc: [-3, 0, 0] + + - name: SilverBall + obj: SingleSpheres.SilverStone + loc: [-3, 0, 3] + + - name: Fencing + obj: Structures.XFence + loc: [0, 0, -3] + + - name: Fencing + obj: Structures.XFence + loc: [1, 0, -3] + + - name: Fencing + obj: Structures.XFence + loc: [2, 0, -3] + + - name: Fencing + obj: Structures.ZFence + loc: [0, 0, -3] + + - name: Fencing + obj: Structures.ZFence + loc: [0, 0, -2] + + - name: Fencing + obj: Structures.ZFence + loc: [0, 0, -1] + + - name: SilverBall + obj: SingleSpheres.SilverStone + loc: [3, 0, 3] + +pictures: 6 \ No newline at end of file diff --git a/data/scenes/Story1.yml b/data/scenes/Story1.yml new file mode 100644 index 0000000..3a7b843 --- /dev/null +++ b/data/scenes/Story1.yml @@ -0,0 +1,21 @@ + +importObjects: + - Characters + - Lights + +layTurf: + type: grass + x: 5 + z: 5 + +place: + + - name: Light + obj: Lights.WhiteLight + loc: [ 0, 10, 3 ] + + - name: MainCharacter + obj: Characters.MainCharacter + loc: [0, 0, 0] + +pictures: 6 \ No newline at end of file diff --git a/data/scenes/Test.yml b/data/scenes/Test.yml index 28e191e..365613e 100644 --- a/data/scenes/Test.yml +++ b/data/scenes/Test.yml @@ -8,7 +8,7 @@ importObjects: - Tests layTurf: - type: brick + type: grass x: 10 z: 10 @@ -16,7 +16,7 @@ place: - name: Light obj: Lights.WhiteLight - loc: [ -4, 10, 0 ] + loc: [ 4, 10, 0 ] - name: Tree obj: Plants.Tree @@ -89,4 +89,32 @@ place: obj: Structures.XWall loc: [2, 0, -5] + - name: Fencing + obj: Structures.XFence + loc: [2, 0, 0] + + - name: Fencing + obj: Structures.XFence + loc: [3, 0, 0] + + - name: Fencing + obj: Structures.XFence + loc: [4, 0, 0] + + - name: Fencing + obj: Structures.ZFence + loc: [2, 0, 0] + + - name: Fencing + obj: Structures.ZFence + loc: [2, 0, 1] + + - name: Fencing + obj: Structures.ZFence + loc: [2, 0, 2] + + - name: torch + obj: Lights.Torch + loc: [4, 0, 2] + pictures: 6 \ No newline at end of file diff --git a/examples/complex-demo.png b/examples/complex-demo.png new file mode 100644 index 0000000..9b66ff1 Binary files /dev/null and b/examples/complex-demo.png differ diff --git a/examples/neptune.png b/examples/neptune.png new file mode 100644 index 0000000..baee664 Binary files /dev/null and b/examples/neptune.png differ diff --git a/examples/simple-demo.png b/examples/simple-demo.png new file mode 100644 index 0000000..09661ad Binary files /dev/null and b/examples/simple-demo.png differ diff --git a/examples/solar-system1.png b/examples/solar-system1.png new file mode 100644 index 0000000..5aee867 Binary files /dev/null and b/examples/solar-system1.png differ diff --git a/examples/solar-system2.png b/examples/solar-system2.png new file mode 100644 index 0000000..6c54496 Binary files /dev/null and b/examples/solar-system2.png differ diff --git a/out/v0.png b/out/v0.png index a9ef078..b957e6f 100644 Binary files a/out/v0.png and b/out/v0.png differ diff --git a/out/v1.png b/out/v1.png index 76e61ea..a45bd5f 100644 Binary files a/out/v1.png and b/out/v1.png differ diff --git a/out/v2.png b/out/v2.png index d2447ba..3097478 100644 Binary files a/out/v2.png and b/out/v2.png differ diff --git a/out/v3.png b/out/v3.png index f8ea3bc..f6a430f 100644 Binary files a/out/v3.png and b/out/v3.png differ diff --git a/out/v4.png b/out/v4.png index af1ba18..0ef91f3 100644 Binary files a/out/v4.png and b/out/v4.png differ diff --git a/out/v5.png b/out/v5.png deleted file mode 100644 index 9274158..0000000 Binary files a/out/v5.png and /dev/null differ diff --git a/out/v6.png b/out/v6.png new file mode 100644 index 0000000..6ee58e2 Binary files /dev/null and b/out/v6.png differ diff --git a/out/v7.png b/out/v7.png new file mode 100644 index 0000000..6b68fed Binary files /dev/null and b/out/v7.png differ diff --git a/package.json b/package.json index e82a1d9..eb19662 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ }, "homepage": "https://github.com/jfmario/js-raytracer-tutorial#readme", "dependencies": { + "argparse": "^1.0.10", "jimp": "^0.2.28", "underscore": "^1.9.0", "yamljs": "^0.3.0" diff --git a/src/index.js b/src/index.js index a4a090c..30e528b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,3 @@ -const main = require('./lessons/lesson04') -// main(); - -require('./scripts/custom-scene')({ scene: "Test" }); \ No newline at end of file +require('./scripts/custom-scene')({ scene: process.argv[2] }); \ No newline at end of file diff --git a/src/lessons/main.js b/src/lessons/main.js new file mode 100644 index 0000000..be5c39e --- /dev/null +++ b/src/lessons/main.js @@ -0,0 +1,134 @@ + +const Vector3 = require('../data-structures/vector3'); + +const SolarSystem = require('../scenes/solar-system'); + +const ImagePlane = require('../view/image-plane'); +const View = require('../view'); + +async function main() { + + let scene = new SolarSystem(); + // scene.randomizeAmbientLight(); + + let views = scene.getViews(); + + /** + const view = View.createDefaultView(); + + const farView = new View( + new Vector3(0, 0, -5), + view.imagePlane, + 256, 192 + ); + + const closeView = new View( + new Vector3(0, 0, -0.5), + view.imagePlane, + 512, 384 + ); + + const leftSideView = new View( + new Vector3(-4, 0, 2.5), + new ImagePlane( + new Vector3(-3, 0.75, 3.5), + new Vector3(-3, 0.75, 1.5), + new Vector3(-3, -0.75, 3.5), + new Vector3(-3, -0.75, 1.5), + ), + 512, 384 + ); + + const rightSideView = new View( + new Vector3(4, 0, 2.5), + new ImagePlane( + new Vector3(3, 0.75, 1.5), + new Vector3(3, 0.75, 3.5), + new Vector3(3, -0.75, 1.5), + new Vector3(3, -0.75, 3.5), + ), + 512, 384 + ); + + const reverseView = new View( + new Vector3(0, 0, 6), + new ImagePlane( + new Vector3(1, 0.75, 5), + new Vector3(-1, 0.75, 5), + new Vector3(1, -0.75, 5), + new Vector3(-1, -0.75, 5), + ), + 512, 384 + ); + + const topView = new View( + new Vector3(0, 2, 2.5), + new ImagePlane( + new Vector3(-1, 1, 3.25), + new Vector3(1, 1, 3.25), + new Vector3(-1, 1, 1.75), + new Vector3(1, 1, 1.75), + ), + 512, 384 + ); + + const bottomView = new View( + new Vector3(0, -2, 2.5), + new ImagePlane( + new Vector3(-1, -1, 1.75), + new Vector3(1, -1, 1.75), + new Vector3(-1, -1, 3.25), + new Vector3(1, -1, 3.25), + ), + 512, 384 + ); + + let center = new Vector3(0, 0, 2.5); + center = scene.lights[0].location; + let dir = new Vector3(Math.random(), Math.random(), Math.random()).normalized(); + + let dist = dir._scale(4); + let cam = center.plus(dist); + let ipCenter = cam._minus(dir); + + let abX = Math.abs(dir.x); + let abY = Math.abs(dir.y); + let abZ = Math.abs(dir.z); + + var ip = null; + + if (abX > abY && abX > abY) { + // x is most significant change + if (dir.x > 0) ip = ImagePlane.lookDownX(ipCenter); + else ip = ImagePlane.lookUpX(ipCenter); + } + else if (abY > abX && abY > abZ) { + if (dir.y > 0) ip = ImagePlane.lookDownY(ipCenter); + else ip = ImagePlane.lookUpY(ipCenter); + } + else if (abZ > abX && abZ > abY) { + if (dir.z > 0) ip = ImagePlane.lookDownZ(ipCenter); + else ip = ImagePlane.lookUpZ(ipCenter); + } + else { + ip = ImagePlane.lookUpZ(ipCenter); + } + + let randomView = new View( + cam, + ip, + 512, 384 + ); + */ + + for (var i = 0; i < views.length; ++i) { + + var view = views[i]; + + console.log(`Writing view ${i}.`); + let image = await view.viewScene(scene); + image.writeImage(`out/v${i}.png`); + } + +} +module.exports = main;