|
7 | 7 | <link rel="icon" type="image/png" href="../playcanvas-favicon.png" />
|
8 | 8 | <script src="../../build/playcanvas.js"></script>
|
9 | 9 | <script src="../../build/playcanvas-extras.js"></script>
|
| 10 | + <script src="../assets/scripts/asset-loader.js"></script> |
10 | 11 | <style>
|
11 | 12 | body {
|
12 | 13 | margin: 0;
|
|
20 | 21 | <canvas id="application-canvas"></canvas>
|
21 | 22 |
|
22 | 23 | <script>
|
23 |
| - function createMaterial(colors) { |
24 |
| - var material = new pc.StandardMaterial(); |
25 |
| - for (var param in colors) { |
26 |
| - material[param] = colors[param]; |
27 |
| - } |
28 |
| - material.update(); |
29 |
| - return material; |
30 |
| - } |
31 | 24 | </script>
|
32 | 25 |
|
33 | 26 | <!-- The script -->
|
|
38 | 31 | var app = new pc.Application(canvas, {
|
39 | 32 | keyboard: new pc.Keyboard(window)
|
40 | 33 | });
|
41 |
| - app.start(); |
42 | 34 |
|
43 |
| - // Set the canvas to fill the window and automatically change resolution to be the same as the canvas size |
44 |
| - app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW); |
45 |
| - app.setCanvasResolution(pc.RESOLUTION_AUTO); |
46 |
| - |
47 |
| - window.addEventListener("resize", function () { |
48 |
| - app.resizeCanvas(canvas.width, canvas.height); |
| 35 | + // A list of assets that need to be loaded |
| 36 | + var assetManifest = { |
| 37 | + statue: { |
| 38 | + type: "container", |
| 39 | + url: "../assets/models/statue.glb" |
| 40 | + }, |
| 41 | + font: { |
| 42 | + type: "font", |
| 43 | + url: "../assets/fonts/arial.json" |
| 44 | + }, |
| 45 | + heart: { |
| 46 | + type: "texture", |
| 47 | + url: "../assets/textures/heart.png" |
| 48 | + }, |
| 49 | + }; |
| 50 | + |
| 51 | + // Load all assets and then run the example |
| 52 | + loadManifestAssets(app, assetManifest, function () { |
| 53 | + run(); |
49 | 54 | });
|
50 | 55 |
|
51 |
| - var miniStats = new pcx.MiniStats(app); |
| 56 | + var spotlight, omnilight, directionallight, statue, text; |
52 | 57 |
|
53 |
| - app.scene.ambientLight = new pc.Color(0.4, 0.4, 0.4); |
| 58 | + function run() { |
54 | 59 |
|
55 |
| - var entity, light, camera; |
| 60 | + app.start(); |
56 | 61 |
|
57 |
| - // Load a model file and create a Entity with a model component |
58 |
| - var url = "../assets/models/statue.glb"; |
59 |
| - app.assets.loadFromUrl(url, "container", function (err, asset) { |
60 |
| - entity = new pc.Entity(); |
61 |
| - entity.addComponent("model", { |
62 |
| - type: "asset", |
63 |
| - asset: asset.resource.model, |
64 |
| - castShadows: true |
| 62 | + // Set the canvas to fill the window and automatically change resolution to be the same as the canvas size |
| 63 | + app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW); |
| 64 | + app.setCanvasResolution(pc.RESOLUTION_AUTO); |
| 65 | + |
| 66 | + window.addEventListener("resize", function () { |
| 67 | + app.resizeCanvas(canvas.width, canvas.height); |
65 | 68 | });
|
66 |
| - app.root.addChild(entity); |
67 |
| - }); |
68 | 69 |
|
69 |
| - // Create an Entity with a camera component |
70 |
| - var camera = new pc.Entity(); |
71 |
| - camera.addComponent("camera", { |
72 |
| - clearColor: new pc.Color(0.4, 0.45, 0.5) |
73 |
| - }); |
74 |
| - camera.translate(0, 7, 24); |
75 |
| - camera.rotate(0, 0, 0); |
76 |
| - app.root.addChild(camera); |
77 |
| - |
78 |
| - // Create an Entity for the ground |
79 |
| - var ground = new pc.Entity(); |
80 |
| - ground.addComponent("model", { |
81 |
| - type: "box" |
82 |
| - }); |
83 |
| - ground.setLocalScale(50, 1, 50); |
84 |
| - ground.setLocalPosition(0, -0.5, 0); |
| 70 | + var miniStats = new pcx.MiniStats(app); |
85 | 71 |
|
86 |
| - var material = createMaterial({ |
87 |
| - ambient: pc.Color.GRAY, |
88 |
| - diffuse: pc.Color.GRAY |
89 |
| - }); |
90 |
| - ground.model.material = material; |
91 |
| - app.root.addChild(ground); |
92 |
| - |
93 |
| - // Create an spot light |
94 |
| - var spotlight = new pc.Entity(); |
95 |
| - spotlight.addComponent("light", { |
96 |
| - type: "spot", |
97 |
| - color: pc.Color.WHITE, |
98 |
| - outerConeAngle: 60, |
99 |
| - innerConeAngle: 40, |
100 |
| - range: 100, |
101 |
| - intensity: 0.6, |
102 |
| - castShadows: true, |
103 |
| - shadowBias: 0.005, |
104 |
| - normalOffsetBias: 0.01, |
105 |
| - shadowResolution: 2048 |
106 |
| - }); |
| 72 | + app.scene.ambientLight = new pc.Color(0.4, 0.4, 0.4); |
107 | 73 |
|
108 |
| - var cone = new pc.Entity(); |
109 |
| - cone.addComponent("model", { |
110 |
| - type: "cone" |
111 |
| - }); |
112 |
| - cone.model.material = createMaterial({ emissive: pc.Color.WHITE }); |
113 |
| - spotlight.addChild(cone); |
114 |
| - app.root.addChild(spotlight); |
115 |
| - |
116 |
| - // Create a omni light |
117 |
| - var omnilight = new pc.Entity(); |
118 |
| - omnilight.addComponent("light", { |
119 |
| - type: "omni", |
120 |
| - color: pc.Color.YELLOW, |
121 |
| - range: 100, |
122 |
| - castShadows: true, |
123 |
| - intensity: 0.6 |
124 |
| - }); |
125 |
| - omnilight.addComponent("model", { |
126 |
| - type: "sphere" |
127 |
| - }); |
128 |
| - omnilight.model.material = createMaterial({ diffuse: new pc.Color(0, 0, 0), emissive: pc.Color.YELLOW }); |
129 |
| - app.root.addChild(omnilight); |
130 |
| - |
131 |
| - // Create a directional light |
132 |
| - var directionallight = new pc.Entity(); |
133 |
| - directionallight.addComponent("light", { |
134 |
| - type: "directional", |
135 |
| - color: pc.Color.CYAN, |
136 |
| - range: 100, |
137 |
| - castShadows: true, |
138 |
| - shadowBias: 0.05, |
139 |
| - normalOffsetBias: 0.1, |
140 |
| - intensity: 0.6 |
141 |
| - }); |
142 |
| - app.root.addChild(directionallight); |
| 74 | + // add an instance of the statue to the hierarchy |
| 75 | + statue = assetManifest["statue"].asset.resource.instantiateRenderEntity({ |
| 76 | + castShadows: true |
| 77 | + }); |
| 78 | + app.root.addChild(statue); |
| 79 | + |
| 80 | + function createMaterial(colors) { |
| 81 | + var material = new pc.StandardMaterial(); |
| 82 | + for (var param in colors) { |
| 83 | + material[param] = colors[param]; |
| 84 | + } |
| 85 | + material.update(); |
| 86 | + return material; |
| 87 | + } |
143 | 88 |
|
| 89 | + // Create an Entity with a camera component |
| 90 | + var camera = new pc.Entity(); |
| 91 | + camera.addComponent("camera", { |
| 92 | + clearColor: new pc.Color(0.4, 0.45, 0.5) |
| 93 | + }); |
| 94 | + camera.translate(0, 12, 45); |
| 95 | + camera.rotate(-10, 0, 0); |
| 96 | + app.root.addChild(camera); |
| 97 | + |
| 98 | + // Create an Entity for the ground |
| 99 | + var ground = new pc.Entity(); |
| 100 | + ground.addComponent("model", { |
| 101 | + type: "box" |
| 102 | + }); |
| 103 | + ground.setLocalScale(50, 1, 50); |
| 104 | + ground.setLocalPosition(0, -0.5, 0); |
144 | 105 |
|
145 |
| - // Create a 2D screen for text rendering |
146 |
| - var screen = new pc.Entity(); |
147 |
| - screen.addComponent("screen", { |
148 |
| - referenceResolution: new pc.Vec2(1280, 720), |
149 |
| - scaleBlend: 0.5, |
150 |
| - scaleMode: pc.SCALEMODE_BLEND, |
151 |
| - screenSpace: true |
152 |
| - }); |
153 |
| - app.root.addChild(screen); |
| 106 | + var material = createMaterial({ |
| 107 | + ambient: pc.Color.GRAY, |
| 108 | + diffuse: pc.Color.GRAY |
| 109 | + }); |
| 110 | + ground.model.material = material; |
| 111 | + app.root.addChild(ground); |
| 112 | + |
| 113 | + // Create an spot light |
| 114 | + spotlight = new pc.Entity(); |
| 115 | + spotlight.addComponent("light", { |
| 116 | + type: "spot", |
| 117 | + color: pc.Color.WHITE, |
| 118 | + outerConeAngle: 25, |
| 119 | + innerConeAngle: 20, |
| 120 | + range: 100, |
| 121 | + intensity: 0.6, |
| 122 | + castShadows: true, |
| 123 | + shadowBias: 0.005, |
| 124 | + normalOffsetBias: 0.01, |
| 125 | + shadowResolution: 2048, |
| 126 | + |
| 127 | + // heart texture's alpha channel as a cookie texture |
| 128 | + cookie: assetManifest["heart"].asset.resource, |
| 129 | + cookieChannel: "a" |
| 130 | + }); |
| 131 | + |
| 132 | + var cone = new pc.Entity(); |
| 133 | + cone.addComponent("model", { |
| 134 | + type: "cone" |
| 135 | + }); |
| 136 | + cone.model.material = createMaterial({ emissive: pc.Color.WHITE }); |
| 137 | + spotlight.addChild(cone); |
| 138 | + app.root.addChild(spotlight); |
| 139 | + |
| 140 | + // Create a omni light |
| 141 | + omnilight = new pc.Entity(); |
| 142 | + omnilight.addComponent("light", { |
| 143 | + type: "omni", |
| 144 | + color: pc.Color.YELLOW, |
| 145 | + range: 100, |
| 146 | + castShadows: true, |
| 147 | + intensity: 0.6 |
| 148 | + }); |
| 149 | + omnilight.addComponent("model", { |
| 150 | + type: "sphere" |
| 151 | + }); |
| 152 | + omnilight.model.material = createMaterial({ diffuse: new pc.Color(0, 0, 0), emissive: pc.Color.YELLOW }); |
| 153 | + app.root.addChild(omnilight); |
| 154 | + |
| 155 | + // Create a directional light |
| 156 | + directionallight = new pc.Entity(); |
| 157 | + directionallight.addComponent("light", { |
| 158 | + type: "directional", |
| 159 | + color: pc.Color.CYAN, |
| 160 | + range: 100, |
| 161 | + castShadows: true, |
| 162 | + shadowDistance: 100, |
| 163 | + shadowBias: 0.2, |
| 164 | + normalOffsetBias: 0.1, |
| 165 | + intensity: 0.6 |
| 166 | + }); |
| 167 | + app.root.addChild(directionallight); |
154 | 168 |
|
155 |
| - // Load a font |
156 |
| - var fontAsset = new pc.Asset('arial.json', "font", { |
157 |
| - url: "../assets/fonts/arial.json" |
158 |
| - }); |
159 |
| - fontAsset.on('load', onFontLoaded); |
160 |
| - app.assets.add(fontAsset); |
161 |
| - app.assets.load(fontAsset); |
162 | 169 |
|
163 |
| - // When the font is loaded, create text to show which lights are enabled |
164 |
| - var text; |
165 |
| - function onFontLoaded() { |
| 170 | + // Create a 2D screen for text rendering |
| 171 | + var screen = new pc.Entity(); |
| 172 | + screen.addComponent("screen", { |
| 173 | + referenceResolution: new pc.Vec2(1280, 720), |
| 174 | + scaleBlend: 0.5, |
| 175 | + scaleMode: pc.SCALEMODE_BLEND, |
| 176 | + screenSpace: true |
| 177 | + }); |
| 178 | + app.root.addChild(screen); |
| 179 | + |
166 | 180 | // Create a basic text element
|
167 | 181 | text = new pc.Entity();
|
168 | 182 | text.addComponent("element", {
|
169 | 183 | anchor: new pc.Vec4(0.1, 0.1, 0.5, 0.5),
|
170 |
| - fontAsset: fontAsset, |
| 184 | + fontAsset: assetManifest["font"].asset, |
171 | 185 | fontSize: 28,
|
172 | 186 | pivot: new pc.Vec2(0.5, 0.1),
|
173 | 187 | type: pc.ELEMENTTYPE_TEXT,
|
|
195 | 209 | var angleRad = 0;
|
196 | 210 | app.on("update", function (dt) {
|
197 | 211 | angleRad += 0.3 * dt;
|
198 |
| - if (entity) { |
199 | 212 |
|
200 |
| - spotlight.lookAt(entity.getPosition()); |
| 213 | + if (statue) { |
| 214 | + |
| 215 | + spotlight.lookAt(statue.getPosition()); |
201 | 216 | spotlight.rotateLocal(90, 0, 0);
|
202 |
| - spotlight.setLocalPosition(20 * Math.sin(angleRad), 5, 20 * Math.cos(angleRad)); |
| 217 | + spotlight.setLocalPosition(20 * Math.sin(angleRad * 0.5), 25, 20 * Math.cos(angleRad * 0.5)); |
203 | 218 |
|
204 |
| - omnilight.setLocalPosition(5 * Math.sin(-2 * angleRad), 10, 5 * Math.cos(-2 * angleRad)); |
| 219 | + omnilight.setLocalPosition(5 * Math.sin(-2 * angleRad), 15, 5 * Math.cos(-2 * angleRad)); |
205 | 220 |
|
206 | 221 | directionallight.setLocalEulerAngles(45, 60 * angleRad, 0);
|
207 |
| - } |
208 | 222 |
|
209 |
| - // update text showing which lights are enabled |
210 |
| - if (text) { |
| 223 | + // update text showing which lights are enabled |
211 | 224 | text.element.text =
|
212 | 225 | "[Key 1] Omni light: " + omnilight.enabled +
|
213 | 226 | "\n[Key 2] Spot light: " + spotlight.enabled +
|
|
0 commit comments