├── public
├── fable.ico
└── index.html
├── package.json
├── Nuget.Config
├── src
├── App.fsproj
├── App.fs
└── ThreeJsTypes.fs
├── README.md
├── webpack.config.js
├── LICENSE
└── .gitignore
/public/fable.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/w0lya/fable-three/HEAD/public/fable.ico
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "dependencies": {
4 | "@babel/core": "^7.1.2",
5 | "fable-compiler": "^2.1.6",
6 | "fable-loader": "^2.1.0",
7 | "react": "^16.6.0",
8 | "react-dom": "^16.6.0",
9 | "three": "^0.99.0",
10 | "webpack": "^4.25.1",
11 | "webpack-cli": "^3.1.2",
12 | "webpack-dev-server": "^3.1.10"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Nuget.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/App.fsproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Three.js sample project based on Fable 2 Minimal App
2 |
3 | ## Requirements
4 |
5 | * [dotnet SDK](https://www.microsoft.com/net/download/core) 2.1 or higher
6 | * [node.js](https://nodejs.org) with [npm](https://www.npmjs.com/)
7 |
8 | ## Building and running the app
9 |
10 | * Install JS dependencies: `npm install`
11 | * Start Webpack dev server: `npx webpack-dev-server`
12 | * After the first compilation is finished, in your browser open: http://localhost:8080/
13 |
14 | Any modification you do to the F# code will be reflected in the web page after saving.
15 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | // Note this only includes basic configuration for development mode.
2 | // For a more comprehensive configuration check:
3 | // https://github.com/fable-compiler/webpack-config-template
4 |
5 | var path = require("path");
6 |
7 | module.exports = {
8 | mode: "development",
9 | entry: "./src/App.fsproj",
10 | output: {
11 | path: path.join(__dirname, "./public"),
12 | filename: "bundle.js",
13 | },
14 | devServer: {
15 | contentBase: "./public",
16 | port: 8080,
17 | },
18 | module: {
19 | rules: [{
20 | test: /\.fs(x|proj)?$/,
21 | use: "fable-loader"
22 | }]
23 | }
24 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Volha Samusik
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 | obj/
3 |
4 | # Logs
5 | logs
6 | *.log
7 | npm-debug.log*
8 | yarn-debug.log*
9 | yarn-error.log*
10 |
11 | # Runtime data
12 | pids
13 | *.pid
14 | *.seed
15 | *.pid.lock
16 |
17 | # Directory for instrumented libs generated by jscoverage/JSCover
18 | lib-cov
19 |
20 | # Coverage directory used by tools like istanbul
21 | coverage
22 |
23 | # nyc test coverage
24 | .nyc_output
25 |
26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
27 | .grunt
28 |
29 | # Bower dependency directory (https://bower.io/)
30 | bower_components
31 |
32 | # node-waf configuration
33 | .lock-wscript
34 |
35 | # Compiled binary addons (https://nodejs.org/api/addons.html)
36 | build/Release
37 |
38 | # Dependency directories
39 | node_modules/
40 | jspm_packages/
41 |
42 | # TypeScript v1 declaration files
43 | typings/
44 |
45 | # Optional npm cache directory
46 | .npm
47 |
48 | # Optional eslint cache
49 | .eslintcache
50 |
51 | # Optional REPL history
52 | .node_repl_history
53 |
54 | # Output of 'npm pack'
55 | *.tgz
56 |
57 | # Yarn Integrity file
58 | .yarn-integrity
59 |
60 | # dotenv environment variables file
61 | .env
62 |
63 | # next.js build output
64 | .next
65 |
--------------------------------------------------------------------------------
/src/App.fs:
--------------------------------------------------------------------------------
1 | module App
2 |
3 | open System.Collections.Generic
4 | open Fable.Core
5 | open Fable.Import
6 | open Fable.Import.Browser
7 | open ThreeJs.ThreeJsTypes
8 |
9 | // There's a bug in Fable that doesn't allow global values that are both mutable
10 | // and public, we can solve it by making them private (latest version throws error):
11 | // let [] mutable private globalCamera: ArrayCamera = jsNative
12 |
13 | // However, in this case we do want to declare the variables ourselves
14 | // so we can just do it in F# and initialize them to null
15 | let mutable globalCamera: ArrayCamera = null
16 | let mutable globalScene: Scene = null
17 | let mutable globalRenderer: WebGLRenderer = null
18 | let mutable globalMesh: Mesh = null
19 |
20 | let onWindowResize(e:Browser.UIEvent) =
21 | globalCamera.aspect <- window.innerWidth / window.innerHeight
22 | globalCamera.updateProjectionMatrix()
23 | globalRenderer.setSize( window.innerWidth, window.innerHeight)
24 |
25 | let init() =
26 |
27 | let amount = 5.
28 | let size = 1. / amount
29 | let aspectRatio = window.innerWidth / window.innerHeight
30 | let cameras = new List()
31 |
32 | for y = 0 to (int)amount do
33 | for x = 0 to (int)amount do
34 |
35 | let subcamera = Globals.PerspectiveCamera.Create( 40, aspectRatio, 0.1, 10 )
36 |
37 | subcamera.bounds <- Globals.Vector4.Create( (float)x / amount, (float)y / amount, size, size )
38 |
39 | subcamera.position.x <- ( (float)x / amount ) - 0.5
40 | subcamera.position.y <- 0.5 - ( (float)y / amount )
41 | subcamera.position.z <- 1.5
42 | subcamera.position.multiplyScalar( 2.) |> ignore
43 | subcamera.lookAt( 0., 0., 0. )
44 | subcamera.updateMatrixWorld()
45 |
46 | cameras.Add(subcamera)
47 |
48 | // Camera at a higher level (ArrayCamera)
49 | let camera = Globals.ArrayCamera.Create(cameras)
50 |
51 | camera.position.z <- 3.
52 |
53 | globalCamera <- camera
54 |
55 | let scene = Globals.Scene.Create()
56 | let ambientLight = Globals.AmbientLight.Create(Globals.Color.Create(0xFF8080))
57 |
58 | scene.add(ambientLight) |> ignore
59 |
60 | let dirLight = Globals.DirectionalLight.Create()
61 | dirLight.position.set( 0.5, 0.5, 1. ) |> ignore
62 | dirLight.castShadow <- true
63 | dirLight.shadow.camera.zoom <- 4.
64 | scene.add( dirLight ) |> ignore
65 |
66 | let geometry = Globals.PlaneBufferGeometry.Create(100,100)
67 | let material = Globals.MeshPhongMaterial.Create(color=Globals.Color.Create(0x006600))
68 | let background = Globals.Mesh.Create(geometry, material)
69 | background.receiveShadow <- true
70 | background.position.set( 0., 0., -1. ) |> ignore
71 | scene.add( background ) |> ignore
72 |
73 | let cbGeometry = Globals.CylinderBufferGeometry.Create(0.5, 0., 1, 45)
74 | cbGeometry.parameters.radiusTop <- 0.5
75 | let cbMaterial = Globals.MeshPhongMaterial.Create(color=Globals.Color.Create(0xFFAA00))
76 | let mesh = Globals.Mesh.Create(cbGeometry, cbMaterial)
77 |
78 | mesh.castShadow <- true
79 | mesh.receiveShadow <- true
80 | scene.add(mesh) |> ignore
81 |
82 | globalScene <- scene
83 | globalMesh <- mesh
84 |
85 | let renderer = Globals.WebGLRenderer.Create()
86 | renderer.setPixelRatio( window.devicePixelRatio )
87 | renderer.setSize( window.innerWidth, window.innerHeight )
88 | renderer.shadowMap.enabled <- true
89 | document.body.appendChild( renderer.domElement ) |> ignore
90 |
91 | globalRenderer <- renderer
92 |
93 | Browser.window.addEventListener_resize(onWindowResize, false )
94 |
95 |
96 | let rec animate _: unit =
97 | globalMesh.rotation.x <- globalMesh.rotation.x + 0.005
98 | globalMesh.rotation.z <- globalMesh.rotation.z + 0.01
99 | globalRenderer.render( globalScene, globalCamera )
100 |
101 | Browser.window.requestAnimationFrame(animate) |> ignore
102 |
103 | init()
104 |
105 | animate 0.
106 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | three.js webgl - arraycamera
5 |
6 |
7 |
8 |
15 |
16 |
17 |
21 |
22 |
23 |
24 |
155 |
156 |
157 |
226 |
227 |
--------------------------------------------------------------------------------
/src/ThreeJsTypes.fs:
--------------------------------------------------------------------------------
1 | namespace ThreeJs
2 |
3 | module ThreeJsTypes =
4 |
5 |
6 | open Fable.Core
7 | open Fable.Import.Browser
8 |
9 | type [] Matrix4 =
10 | interface end
11 |
12 | type [] Euler =
13 | abstract x : float with get,set
14 | abstract y : float with get, set
15 | abstract z : float with get, set
16 |
17 | type [] Vector3 =
18 | abstract x : float with get,set
19 | abstract y : float with get, set
20 | abstract z : float with get, set
21 | // Sets value of this vector.
22 | abstract set: x: float * y: float * z: float -> Vector3
23 | /// Multiplies this vector by scalar s.
24 | abstract multiplyScalar: s: float -> Vector3
25 | and [] Vector3Type =
26 | [] abstract Create: unit -> Vector3
27 |
28 |
29 | type [] Vector4 =
30 | abstract x : float with get,set
31 | abstract y : float with get, set
32 | abstract z : float with get, set
33 | abstract w : float with get, set
34 | and [] Vector4Type =
35 | [] abstract Create: ?p1:obj * ?p2:obj * ?p3:obj * ?p4:obj -> Vector4
36 |
37 |
38 | type [] Color =
39 | /// Red channel value between 0 and 1. Default is 1.
40 | abstract r: float with get, set
41 | /// Green channel value between 0 and 1. Default is 1.
42 | abstract g: float with get, set
43 | /// Blue channel value between 0 and 1. Default is 1.
44 | abstract b: float with get, set
45 | abstract setHex: hex: float -> Color
46 | abstract set: color: string -> Color
47 | abstract setRGB: r: float * g: float * b: float -> Color
48 | and [] ColorType =
49 | [] abstract Create: ?p1:obj -> Color
50 |
51 |
52 |
53 | type [] Object3D =
54 | abstract position: Vector3 with get, set
55 | abstract add: param : obj -> obj //ResizeArray -> Object3D
56 | abstract castShadow: bool with get, set
57 | abstract receiveShadow: bool with get, set
58 | abstract rotation: Euler with get, set
59 |
60 | type [] Camera =
61 | inherit Object3D
62 |
63 | type [] OrthographicCamera =
64 | inherit Camera
65 | abstract zoom: float with get, set
66 |
67 |
68 | type [] PerspectiveCamera =
69 | inherit Camera
70 |
71 | /// Camera frustum vertical field of view, from bottom to top of view, in degrees.
72 | abstract fov: float with get, set
73 |
74 | /// Camera frustum aspect ratio, window width divided by window height.
75 | abstract aspect: float with get, set
76 |
77 | /// Camera frustum near plane.
78 | abstract near: float with get, set
79 |
80 | /// Camera frustum far plane.
81 | abstract far: float with get, set
82 | abstract bounds : Vector4 with get, set // not found in TS
83 | abstract lookAt: p1:float * p2:float * p3:float -> unit
84 | abstract updateMatrixWorld: ?force: bool -> unit
85 | abstract updateProjectionMatrix: unit -> unit
86 |
87 | and [] PerspectiveCameraType =
88 | [] abstract Create: ?p1:obj * ?p2:obj * ?p3:obj * ?p4:obj -> PerspectiveCamera
89 |
90 |
91 | type [] ArrayCamera =
92 | inherit PerspectiveCamera
93 | abstract cameras: ResizeArray with get, set
94 | abstract isArrayCamera: obj with get, set
95 |
96 | and [] ArrayCameraType =
97 | [] abstract Create: ?p1:obj -> ArrayCamera
98 |
99 |
100 | type [] Scene =
101 | inherit Object3D
102 | and [] SceneType =
103 | [] abstract Create: unit -> Scene
104 |
105 | type [] LightShadow =
106 | abstract camera: Camera with get, set
107 |
108 | type [] DirectionalLightShadow =
109 | interface
110 | inherit LightShadow
111 | abstract camera: OrthographicCamera with get, set
112 | end
113 |
114 | type [] Light =
115 | inherit Object3D
116 | abstract color: Color with get, set
117 |
118 | type [] AmbientLight =
119 | inherit Light
120 | abstract castShadow: bool with get, set
121 | and [] AmbientLightType =
122 | [] abstract Create: ?p1:obj -> AmbientLight
123 |
124 |
125 | type [] DirectionalLight =
126 | inherit Light
127 | /// Target used for shadow camera orientation.
128 | abstract target: Object3D with get, set
129 | abstract shadow: DirectionalLightShadow with get, set
130 | and [] DirectionalLightType =
131 | [] abstract Create: unit -> DirectionalLight
132 |
133 |
134 |
135 | type [] EventDispatcher =
136 | interface end
137 |
138 | // Type to resolve parameters for Geometries.
139 | type [] GeometryParameters =
140 | abstract width : int with get, set
141 | abstract height : int with get, set
142 | abstract radiusTop : float with get, set
143 | abstract radiusBottom : float with get, set
144 | abstract radialSegments : int with get, set
145 |
146 | type [] Geometry =
147 | inherit EventDispatcher
148 |
149 | type [] BufferGeometry =
150 | inherit Geometry
151 |
152 |
153 | type [] CylinderBufferGeometry =
154 | inherit BufferGeometry
155 | abstract parameters: GeometryParameters with get, set
156 | and [] CylinderBufferGeometryType =
157 | [] abstract Create: ?p1:obj * ?p2:obj * ?p3:obj * ?p4:obj -> CylinderBufferGeometry
158 |
159 |
160 |
161 | type [] PlaneBufferGeometry =
162 | inherit BufferGeometry
163 | abstract parameters: GeometryParameters with get, set
164 | and [] PlaneBufferGeometryType =
165 | [] abstract Create: ?p1:obj * ?p:obj -> PlaneBufferGeometry
166 |
167 |
168 | type [] Material =
169 | inherit EventDispatcher
170 |
171 | type [] MeshPhongMaterial =
172 | inherit Material
173 | abstract color: Color with get, set
174 | and [] MeshPhongMaterialType =
175 | [] abstract Create: ?p1:obj -> MeshPhongMaterial
176 |
177 |
178 | type [] Mesh =
179 | inherit Object3D
180 | abstract geometry: obj with get, set
181 | abstract material: obj with get, set
182 | and [] MeshType =
183 | [] abstract Create: ?p1 :obj * ?p2:obj -> Mesh
184 |
185 |
186 | type [] Renderer =
187 | abstract domElement: HTMLCanvasElement with get, set
188 | abstract render: scene: Scene * camera: Camera -> unit
189 | abstract setSize: width: float * height: float * ?updateStyle: bool -> unit
190 |
191 | type [] WebGLShadowMap =
192 | abstract enabled: bool with get, set
193 |
194 | type [] WebGLRenderer =
195 | inherit Renderer
196 | abstract shadowMap: WebGLShadowMap with get, set
197 | abstract getPixelRatio: unit -> float
198 | abstract setPixelRatio: value: float -> unit
199 | and [] WebGLRendererType =
200 | [] abstract Create: unit -> WebGLRenderer
201 |
202 | type [] Globals =
203 | [] static member PerspectiveCamera with get(): PerspectiveCameraType = jsNative and set(v: PerspectiveCameraType): unit = jsNative
204 | [] static member ArrayCamera with get(): ArrayCameraType = jsNative and set(v: ArrayCameraType): unit = jsNative
205 | [] static member Scene with get(): SceneType = jsNative and set(v: SceneType): unit = jsNative
206 | [] static member WebGLRenderer with get(): WebGLRendererType = jsNative and set(v: WebGLRendererType): unit = jsNative
207 | [] static member Mesh with get(): MeshType = jsNative and set(v: MeshType): unit = jsNative
208 | [] static member Vector4 with get(): Vector4Type = jsNative and set(v: Vector4Type): unit = jsNative
209 | [] static member Vector3 with get(): Vector3Type = jsNative and set(v: Vector3Type): unit = jsNative
210 | [] static member AmbientLight with get(): AmbientLightType = jsNative and set(v: AmbientLightType): unit = jsNative
211 | [] static member Color with get(): ColorType = jsNative and set(v: ColorType): unit = jsNative
212 | [] static member DirectionalLight with get(): DirectionalLightType = jsNative and set(v: DirectionalLightType): unit = jsNative
213 | [] static member PlaneBufferGeometry with get(): PlaneBufferGeometryType = jsNative and set(v: PlaneBufferGeometryType): unit = jsNative
214 | [] static member MeshPhongMaterial with get(): MeshPhongMaterialType = jsNative and set(v: MeshPhongMaterialType): unit = jsNative
215 | [] static member CylinderBufferGeometry with get(): CylinderBufferGeometryType = jsNative and set(v: CylinderBufferGeometryType): unit = jsNative
216 |
217 |
218 |
219 |
--------------------------------------------------------------------------------