Special effects of the earth - water wave

zhaozj2021-02-08  252

(If this picture is not appeared on the left, please wait patiently for a moment)

Seeing this animation on the left, you may not believe it is actually made with a computer, this is the charm of "water wave" special effects. This little animation is grabbed from the execution screen of the program. If you want to perform the source program personally, look at the actual effect, you can download Ripsample.zip (92K). (Including source programs and executables. This example is just a simplified version of the water wave screen, saves many code that has nothing to do with the horizontal principle, which is to make the principle of water wave easier to understand)

Before introducing the programming, let's take a look at the knowledge of water waves we have learned in high school physics class. Water waves have the following characteristics:

Diffusion: When you cast a stone to the water, you will see a circle of water waves formed by stone into the water, here, you may be misleaded by this phenomenon, thinking that every point on the water wave is The stone into the water is spread outward, which is wrong. In fact, any point on the water wave is spread around at any time, and the reason why it will form a cyclic water wave, because the inner part of the water wave is unveiled because of the symmetry of diffusion. Attenuation: Because water is damped, otherwise, when you put the stone in the pool, the water wave will never stop. Water refraction: Because the inclination angle of different places on the water wave is different, because the water is refracted, we are not in the bottom of the observation point, and there is a certain offset. This is why we can feel the shape of the water wave. Reflection: The water wave encounters an obstacle reflection. Damage: Suddenly think of this, but in the program, you can't see it. If you can put a reef on the pool, or put a middle-slit partition, you can see the diffraction of water waves.

Ok, have these features, use mathematics and geometries, we can simulate real water waves. However, if you have used 3Dmax to do water waves animation, you will know how to render a real shape, you have to have a few minutes, and we need real-time rendering, at least It is also possible to render 20 frames to make the water waves smoothed. Considering the speed of computer operations, we cannot construct water waves in a sinusoidal function or a precise formula, can not use the multi-division method, more unavailable in SiN, COS, can only use a rapid algorithm for approximately value, although this algorithm has certain Error, but in order to meet the requirements of real-time animation, we have to do this.

First we have to build two arrays of the pool image as a size buf1 [PoolWidth * PoolHeight] and BUF2 [PoolWidth * poolHeight] (PoolWidth = Pixel Width of Pool Image, PoolHeight = Pixel Height) To save the previous moments of each point on the water and the last moment of spinning data, because the volatility represents the energy of the wave, so we call these two arrays as a wave energy buffer. The water surface is a plane in the initial state, and the variation of each point is 0, so the initial value of these two arrays is equal to 0.

Below to derive the formula of calculating the wavelength

We assume that there is such a formula, and you can calculate the amplitude of this point in front of the next time before, after, left, right, and the amplitude of this point, then, then we may Using the summary method for any moment, the amplitude on the water is at any time. Such as left, you can see, at a certain moment, the amplitude of X0 points is from the influence of X0 point's own amplitude, and it is from the surrounding point around it, then left, left and right (x1, x2, x3, x4) The effect (for simplification, we ignore all other points), and these four points can be said to be equal to the influence of A0 points. Then we can assume that this first formula is: X0 '= a (x1 x2 x3 x4) bx0 (Equation 1) A, B is the amplitude X0, X0, X0, X0, X0, X1, X1, X0, X0, X0, X1, X2 , X3, X4 is the amplitude of the current time

Let's solve A and B below. Assume the damping of water is 0. Under this ideal condition, the intensity of water will remain unchanged. That is to say at any time, the amplitude of all points is unchanged. Then you can get the following formula: X0 ' X1' ... XN '= X0 X1 ... XN

Calculate each point like Equation 1, and then substitute to form: (4a b) X0 (4a b) x1 ... (4a b) xn = X0 x1 ... xn => 4A B = 1

Find a most simplified: a = 1/2, b = -1 Because 1/2 can be done with shift operators ">>", this form of solution is the most suitable and is fastest. Then the final formula is: x0 '= (x1 x2 x3 x4) / 2- x0

Ok, I have the approximation formula above, you can be promoted to this general conclusion: known a little in the water in the water, then, at the next moment, any volatility is equal to the front adjacent to this point. The summary of the vane of the left and right four points is 2, and then the velocity of this point is subtracted.

It should be noted that the water is actually damped, otherwise, with the above formula, once you add a wave source in the water, the water will never stop the oscillation. Therefore, it is also necessary to decay the vane data, so that each point is reduced by a certain proportion of the ideal than the ideal value. This attenuation rate is tested, and it is more suitable with 1/32, that is, 1/2 ^ 5. Can be obtained quickly by shift operation.

Here, the most difficult part of the water wave special effect production has been spent, the following is the code calculated in the source program.

// ******************************************************** ******* // calculate wave energy data buffer // ******************************************* ******************************* VOID RIPPLESPREAD () {for (INT I = backwidth; i > 1) - BUF2 [i]; // wave energy attenuation BUF2 [I] - = BUF2 [I] >> 5;} // Exchange Wave Data Buffer Short * PTMP = BUF1; BUF1 = BUF2; BUF2 = PTMP;} Writing here, I have been panting, calling -, take a break first ...

Ok, let's render the page according to the calculated vanity data.

Because of the refraction of water, when the water is not perpendicular to our line of line, the underwater scene we see is not under the front of the observation point, and there is a certain offset. The degree of offset is related to the slope of the water wave, the refractive index of water, and the depth of water, it is obviously unrealistic if it is necessary to perform accurate calculations. Similarly, we only need to do linear approximation processing. Because the tilt of the water surface, the larger the offset of the scene seen, so we can approximate the difference between the volatility of the width, the difference between the two points, and the difference between the two points. the amount.

In the program, load the original image with a page, rendering with another page. First lock two pages with the LOCK function, get the pointer to the point memory area, and then copy each pixel on the original image to the rendering page according to the offset. The code for page rendering is as follows: (The following code is not easy to understand, in fact, the optimized code is much more troublesome than it)

// ******************************************************** ******* // Rendering the off-screen page according to the wavelength data buffer // ************************************* ********************************************* VOID RENDERRIPPLE () {// Lock two off-screen DDSurfaceDesc DDSD1, DDSD2; DDSD1.DWSIZE = sizeof (DDSURFACEDESC); ddsd2.dwSize = sizeof (DDSURFACEDESC); lpDDSPic1-> Lock (NULL, & ddsd1, DDLOCK_WAIT, NULL); lpDDSPic2-> Lock (NULL, & ddsd2, DDLOCK_WAIT, NULL); // page acquired pixel bit depth , And page memory pointer int Depth = ddsd1.ddpfpixelformat.dwrgbbitcount / 8; Byte * bitmap1 = (byte *) DDSD1.LPSURFACE; BYTE * BITMAP2 = (Byte *) DDSD2.LPSURFACE; // Take the page Rendering Int Xoff, Yoff ; Int K = backwidth; for (int i = 1; i backheight) {K ; Continue;} IF ((J Xoff) <0 ) {k ; continue;} {k ; continue;} // calculates the memory address offset INT POS1, POS2; POS1 = DDSD1, the offset pixel and the original pixel. LPITCH * (i yoff) defth * (j Xoff); POS2 = DDSD2.LPITCH * I DEPTH * J; // Copy pixel for (int D = 0; D UNLOCK (& DDSD1); lpddspic2-> unlock (& ​​DDSD2);} Add Wave source

As the saying goes: No wind is not wave, in order to form water waves, we must join the Wave source in the pool, you can imagine into the water into the stone, the size and energy of the formed wave source and the radius of the stone are related to the power of the stone. I know these, so good, we only need to modify the wavelength data buffer BUF, let it get a negative "tip pulse" in the location of the stone into the water, that is, let BUF [X, Y] = - n. After experimentation, the range of N is relatively suitable between (32 to 128). The control wave source radius is also good, you only need to focus on the center of the stone into the center of the water, draw a circle with a radius of stone radius, so that all points in this circle come to such a negative "tip pulse" (here also Due to approximate processing).

The code to increase the wave source is as follows:

// ******************************************************** ***** // increase the wave source // ************************************************* ************** VOID DROPSTONE (INT X, / / ​​X coordinate int y, // y coordinate int st stonesize, / / ​​wave source radius INT stoneWeight) / / Wave source energy {// judgment coordinate Whether IF in the screen range ((x stonesize)> Backwidth || (Y Stonesize)> Backheight || (x-stonesize) <0 || (Y-Stonesize) <0) Return; for (int Posx = x -stonesize; POSX

Ok, here, the principle of production of water wave effects will be revealed. In the derivation of the above, there is a lot of seemingly very excessive approximation, but you don't have to worry about it, it has proved that this method can be used to get a very good effect on speed and image. There is a very detailed comment in the source program, and you should notify them, you should not be a problem.

This program is DirectX programming under Win32 without any packaging library. On my computer (AMDK6-200, 2MVRAM, 64MSRAM), 320x240 screen size, can reach 25 frames per second. Different from the previous few programs, this program uses window mode, so it is very convenient to debug. If you are not familiar with the window mode, this program is also a good example.

转载请注明原文地址:https://www.9cbs.com/read-1297.html

New Post(0)