编程知识 cdmana.com

Application of react optimization technique in Web ray tracing

In the last , We introduced JS Operator overloading scheme in , It's like React Use in JSX Instead of React.createElement like that . We can optimize our code , Make it more concise and intuitive .

Industrial Agglomeration :React Optimization skills in Web Applications in ray tracing ( On )

However , It's just grammar sugar , It doesn't solve the performance problem . The huge amount of computation of ray tracing algorithm , Other optimization techniques are needed . Today, let's talk about these techniques .

Solution :Time Slicing

Time is divided , Or asynchronous rendering , Or concurrent mode , Whatever the name is , It's about a long-term task , Divide it into small pieces , Every execution period of time , Stop to let the main thread backlog of other tasks ( For example, rendering ) Get released .

React and Vue It's been shown before . In our scene , You can also use this idea , And there's no need to implement a Concurrency frame . use async/await and generator function You can simply meet the needs .

So let's see , How to divide the calculation task of ray tracing into blocks .

The idea of ray tracing algorithm is , Calculate the color of this pixel position pixel by pixel . So there are two for loop ,i = 0width Add j = 0height, Each group i, j For the location of the pixels .

For each pixel , We start with the eyes ( Observation points ) Launch in 100 A light , Simulate the reverse path of the light path from the object to the eye , To sample the light source . The calculation of each pixel is shown in the figure below :

img

Light for sampling , Every time you hit an object , According to the material characteristics of the object itself , On reflection 、 refraction 、 Scattering, etc . It's equivalent to using the impact point as the light source , Send light back to other places . The light is in collision , Gradual loss of energy ( Total loss of energy , It's black ; Like shadows , The shadow is usually at the angle of the object , High frequency collisions of light in narrow places , It's partially absorbed with each impact , Partial reflection , Partial refraction , Multiple impacts , It's fully absorbed ).

Considering that the theme of this series is , Take ray tracing, for example , Let's talk about the strategy of rendering optimization . therefore , A more detailed description of the ray tracing algorithm , Beyond the scope of ; Interested students , You can search 《Ray Tracing in a Weekend》 Wait for reading materials .

After we implement the ray tracing algorithm , Want to put it in the browser to run , You need to use the optimization measures described in this series of articles .

The present , Suppose we've implemented the ray tracing algorithm . Its JS The code expresses , As shown in the figure below :

img

The first two layers for loop , To determine the position of pixels ; The third level for The loop is the number of times the sample light is emitted , Add a little Math.random() Random disturbance , Let the sampling points be emitted at different points in a small square , Can detect a wider environment .

color(ray, world) Function to calculate recursively ray Light and world The collision relationship between the objects in , Value a color .

Finally, we get the color value of the sampled light , Add up , Take the average again . It's the actual color of the pixel . Because it is normalized to 01 The value range of , So finally zoom in to 0255 Of RGB In interval . Before that, I did a radical , It's a simple simulation of gamma correction , It doesn't matter here , Press the table .

thus , We know how our ray tracing algorithm works . How can I cut it ?

First step , The color value is the average value after accumulation . We can't emit light so many times in one traversal , It's just one shot . You can get a rough image . Store the pixel values of this image . Then initiate another traversal , Each pixel emits light again , Get another rough image , Two images are superimposed and averaged , More detailed images .

img

We've eliminated the third layer for loop . Instead, it's a way of executing functions over and over again , Get more than one content, combined , We can get the same detailed image as ray tracing .

We did . But it's amazing , Take a detailed image , Divided into a number of rough images , It doesn't solve the problem completely . Just a dozen minutes , It's a dozen seconds . For web pages , More than ten seconds , Still unacceptable .

How else can we divide the task ? Every calculation n Stop once per pixel ? It can . But how to write our code , Two layers of for The loop can go well xy Axis width height positioning . We don't want to use messy code , To forcibly meet the needs of fragmentation .

There's a great way to , Change our function to generator function, It can pass. yiled The keyword stops many times .

img

Now? , We don't collect it inside the function content 了 , We put them 4 In groups yield get out , Collect from the outside .

img

Outside through data Array to accumulate color values , use innerCount To accumulate rendering times , It's convenient to average ; use duration To track the execution time , every other 100 millisecond , Just await delay() once ( For internal use setTimeout(f, 0)), Make room for UI The main thread .

such , Just by generator function and async/await, We've made it easy Time Slicing. Although the drawing time is still 10 Seconds ( In a computer or mobile phone with poor performance ), But at least the interface has to move , At least it can be constantly rendered dom To read the seconds and time .

img

Advanced program :Streaming Rendering

thus , We split high-definition images into multiple blurred images . And the generation of a blurred image , according to 100ms It's broken down into sections , Give Way UI Other rendering tasks in the main thread ( such as DOM), Have the opportunity to execute . The interface is no longer stuck .

Our ray tracing is available in browsers , But that's not the limit we can do . We can go further , Make images show faster .

Take a look back. , In use React do SSR when , If it's rendered HTML Too complicated , Waiting for the whole thing to be done , And send it to the browser . Users will always see a white screen . How did we optimize it at that time ?

We will adopt renderToNodeStreaming, Render into Node.js Stream, Let the browser receive one by one HTML character string , Achieve progressive rendering . In our ray tracing scene , This optimization strategy is also feasible .

because , Even if not all the pixels of an image are collected , It's still renderable( Renderable ), Keep the rest transparent ( We don't even have to deal with ,cxt.createImageData Generated data structure , The default is transparency ).

img

As shown above , Compared to 100ms There's no brain delay once , Give Way UI The possible backlog of tasks in the thread is released ; This time we , Launch it directly once requestAnimationFrame Rendering of , To render canvas Pictures are also added to UI In the main route . When all the pixels are collected , We'll do an extra overall rendering .

such , And that's what happened Streaming Rendering, We don't have to wait any longer 10 Second , The first time I saw the whole picture . We can see part of the image in the first second . As shown below ,1.6 You can see part of the image in seconds .

img

We successfully solved the problem of first rendering , But we can do better . Except for the first rendering , In the update phase, we can also add some optimization measures .

such as , Many images are mostly simple backgrounds , Only a few objects , We do the calculation equally , It's a waste . We should put our valuable computing resources , Put something more critical , Especially on objects in the center of vision . Make them clear first .

Next time , I'll show you how to use React Upcoming Schedule The idea of priority strategy , Perfect our ray tracing .

版权声明
本文为[Industrial Agglomeration]所创,转载请带上原文链接,感谢
https://cdmana.com/2020/12/20201224152607721x.html

Scroll to Top