程序代写代做代考 Java javascript GPU html js chain CSCI-396 Jeff Bush

CSCI-396 Jeff Bush
1

 So far, models have been simple hard-coded (triangles, squares, trapezoid) or procedurally generated (circle, Sierpinski’s triangle) shapes
 We want to be able to use complex 3D models and having thousands of vertices of data in our JS file would be un-maintainable and has many other issues
 Solution: define the 3D model in a separate file, download it on-demand from the server, and then load it onto the GPU
2

 There are literally hundreds of 3D Model file formats
▪ Every 3D design program has its own format (DWG for
AutoCAD, BLEND for Blender, …)
▪ STL: not good: only positions; only triangles; no IBOs; text-based
▪ JSON:
▪ Pros: can support anything we want; very easy to load into JavaScript
▪ Cons:non-standard(mustmanuallywriteormakeconverter);text-based
▪ OBJ: extremely common, always IBOs ▪ Cons:onlytriangles;text-based
▪ glTF: common, full-featured, has binary version (rarer)
▪ X3D/X3DOM: common, full-featured, has binary version (rarer)
▪ VRML/WML: precursor to X3D
▪ Webgl-Loader/UTF8: rarer but most efficient for browsers
3

 JSON:
▪ Quite simple
▪ Can write our own loader
▪ To convert OBJ to JSON: kurilo.su/workingprocess/webgl/c/ ▪ OBJ files are commonly found and essentially every 3D software
can export as OBJ, however they don’t support triangle strips
 glTF:
▪ Uses JSON or a binary format, fairly common
▪ Much more complex
▪ Includes an entire scene, can even define shader code for objects
▪ I have to play around with it a bit more before we use it
▪ VS Code Extension: glTF Tools
4

 Restricted syntax used to define objects in JavaScript
▪ Similar to dict in Python
 Curly braces {} define object, use key:value
for each item, separate with commas ▪ Keys must be strings in double quotes
▪ Last item cannot have a comma after it
▪ Values can be lists with [], numbers, strings in double quotes, true, false, null, and other objects
5

 JSON.parse(s) – takes a string and returns the JavaScript object
▪ Since a JavaScript object is just a dictionary, we can include any data we want: VBOs, IBOs, drawing mode, multiple objects, …
 How do we get the JSON string though?
▪ If we include the string in our code we aren’t any
better off then before
▪ We can load it with the Fetch API
▪ Modern replacement of AJAX
▪ Still asynchronous which means we call a function now and it will complete at a later time, if we want the “return” value we need to have another function called when it is available
6

 JavaScript is single-threaded and event-driven
▪ Everything you do should be in response to an event
▪ While an event is being handled no other code can run
▪ If anything will take time [or block] (e.g. downloading a file or rendering) we should (must) do it asynchronously
▪ Otherwise the tab will become unresponsive (since no other events can be handled) and the browser may kill it
▪ The browser maintains a queue of events using a FIFO strategy  JavaScript uses promises and callbacks to overcome
single threaded limitations
▪ Promises are similar to async functions with await in Python
▪ In fact JavaScript uses the same keywords sometimes
▪ Callbacks are a function that is called when the result is ready
7

Filling the Queue
The JavaScript event loop
8

 A bit complicated
▪ There are entire books on promises…
▪ We only need to understand a small amount about them
 A Promise is the idea that an asynchronous action is promised to
complete at some point in the future ▪ Completion could be in error
 For now two methods of a Promise that are important:
▪ then(onFulfilled) – when the Promise completes without exception, the given onFulfilled function is called with the return value as an argument
▪ then() returns another Promise so you can chain them
▪ catch(onRejected) – when the Promise completes with exception, the given onRejected function is called with the error as an argument
▪ Also returns another Promise
9

 Open 2-Rendering/promises.html ▪ Look at the console output
 There is a console.log() at the top level
▪ Does this execute before, after, or in-between the outputs in promises?
 What order do the functions execute it? ▪ Is it in DFS or BFS order?
 How is result argument to then functions determined?
▪ What happens to the result of the last step?
▪ What happens if a step doesn’t produce a result?
 Without promises, how could you rewrite the code?
 When writing anonymous functions, how can you simplify
their definitions?
▪ Common for callbacks
#1 #2
#3a #4a
#3b #4b
#5
10

 Since the then() method returns another Promise, and that Promise has a then() method, you can chain them together to clean the code even more:
p.then(…).then(…).then()…
 If an anonymous function would only contain a return
statement, the definition can be reduced even further:
x => x + 5
is the same as
function name(x) { return x; }
 See promises2.html for an example of all of this
11

 Single argument: string with URL to fetch
▪ Also accepts additional request information (e.g. a method of POST or a request body)
 Returns a Promise that resolves to a Response object
▪ i.e. the function given to then() will be given a Response object as an argument
 Response object can be checked for errors with ok attribute, downloaded data can be accessed as well:
▪ arrayBuffer() returns a Promise that results in an object that can be made into a typed array
▪ json() return a Promise that results in the parsed JSON object
 Write the code to fetch the JSON file tree.json and get the object into the global variable data
12

 Single argument: string with URL to fetch
▪ Also accepts additional request information (e.g. a method of POST or a request body)
 ReturnsaPromisethatresolvestoaResponseobject
▪ i.e. the function given to then() will be given a Response object as an argument
 Response object can be checked for errors with ok attribute, downloaded data can be accessed as well:
▪ arrayBuffer() returns a Promise that results in an object that can be made into a typed array
▪ json() return a Promise that results in the parsed JSON object
 Write the code to fetch the JSON file tree.json and get the object
into the global variable data fetch(‘tree.json’)
.then(r => r.json()) .then(obj => { data = obj; });
13

 We can use the catch() method to call a function whenever a step fails:
fetch(tree.json’)
.then(r => r.json()) .then(obj => { data = obj; }) .catch(console.error);
 In this case it will log the error out to the console ▪ Try running this code with something like
sphere.json (which doesn’t exist)
▪ Could do something more sophisticated than logging
14

 In model-loading complete the loadModel() function  It takes the name of the JSON file to load and returns a Promise that resolves to an array containing the VAO
reference and the number of indices to draw
▪ The VAO will need to be setup with the object’s VBO and IBO
▪ Most of the added code (compared to what was on the previous slide) will come from our initBuffers() function we have been writing
▪ MakesuretofindonethatusesanIBO
▪ Instead of using gl.vao make a local vao variable and return it
▪ Instead of using coords or indices use the argument to the function
 Code that uses loadModel() is already written for you in init() and the models are used in render()
15

 Example supports loading multiple models
▪ In init() it uses Promise.all([…]) to wait
for all models to load before going to then() ▪ Once all are loaded it saves the list of models to
gl.models and then finally calls render() ▪ We cannot call render() earlier than this
▪ In render() there is a loop that goes through gl.models and draws each model
 Adjust the code to load both the tree and bird
16

17

 Nissan GTR is made up of 178 parts!
▪ Code to call loadModel() is done for you
 However, missing the body of loadModel()
▪ The car model is 3D though so be careful
 Also add the necessary code to make the
canvas always the size of the document
 Once you get it rendering, can you see the
3d-ness? What is the problem?
18

 For our brains to see 3D we need something to indicate depth:
▪ Lighting
▪ Chapter 3
▪ Perspective – further things are smaller
▪ Chapter 4
▪ Note: the car already had perspective applied
▪ Parallax – further things appear to move slower ▪ Chapter 4 + 5
▪ Colors ▪ Motion
19

20

 Tetrahedron is the simplest 3D shape
▪ 4 triangles
▪ 4 vertices
 Can color it so that depth can be seen  Run tetrahedron example
▪ What’s wrong?
21

 By default depth testing is off
▪ Without depth testing WebGL just takes last fragment
processed for each pixel
▪ With depth testing WebGL uses the 𝑧 for each vertex to determine the fragment depth and thus which to use
 To turn on depth testing: gl.enable(gl.DEPTH_TEST);
(in the init() function where clear color is set)
 To allow the depth to change each render() need to add the following to gl.clear() call:
| gl.DEPTH_BUFFER_BIT
22

23

 Sierpinski’s Triangle but in 3D
▪ Technically a fractional dimensional object
 We can subdivide the volume using the
midpoints on each side
 We remove the solid from the center leaving four smaller tetrahedra in the corners
24

 Create the sierpinski3 function: sierpinski3(a, b, c, d, count, points)
▪ Base this off of the sierpinski() function from before but now we are in 3D:
▪ You have 4 vertices and 6 edges to deal with each time  You also need to adjust the load event:
▪ Call sierpinski3 ▪ Deal with colors
25