Unity3d creates water effect (2), unity3deffect
Previous Article: unity3d self-made water effect (1)
Surface Subdivision: Unity3d uses the DX11 Surface Subdivision
PBR:
Basic Algorithms
Unity3d specular BRDF Based on physical Rendering Physically-Based Rendering
Plus
Unity3d implements Physically-Based Rendering Based on physical RenderingUnity3d top-level physical Rendering of Physically-Based Rendering
I have been writing shader with unity4.6 before, and finally made up my mind to change to unity5. Then I found that the rendering of unity5 is much better than that of 4,
Before the completion of this operation, we had to drag the unsolved normal problem in July, and it was really easy to calculate the normal problem.
The water body uses two kinds of fluctuation algorithms, one is the Szecsi and Arman algorithms in ShaderX6, and the other is the Gerstner wave Algorithm in Gpu gems1. Then use PBR for rendering. Then it is a curved surface subdivision.
Results:
The Szecsi & Arman fluctuation algorithm first looks at the fluctuation Algorithm in ShaderX6:
For the fluctuation speed, λ is the wavelength, and the wavelength is the distance from the peak to the peak. The velocity v is the distance from the peak to the movement per second.
Then there is the phase function. k is the fluctuation direction, the movement direction, which is perpendicular to the horizontal direction of the Time plane. p is the position, and t is the Time (_ Time. y)
Returns the displacement S of a wave. a is the amplitude, and the amplitude is the height from the horizontal plane to the peak.
In the end, our water is combined by multiple waves, so the final result is:
A total of four waves are merged.
The key code is as follows:
<span style="font-size:14px;"> vv = sqrt(_G * _Lambda / (2 * _PIE));psi = 2 * _PIE / _Lambda *(dot(v.vertex.xyz, _K.xyz) + vv*_Time.y);s = lerp(-cos(psi), sin(psi), _A)*0.05;p.y += s;vv = sqrt(_G * _Lambda2 / (2 * _PIE));psi = 2 * _PIE / _Lambda2 *(dot(v.vertex.xyz, _K2.xyz) + vv*_Time.y);s = lerp(-cos(psi), sin(psi), _A2)*0.05;p.y += s;vv = sqrt(_G * _Lambda3 / (2 * _PIE));psi = 2 * _PIE / _Lambda3 *(dot(v.vertex.xyz, _K3.xyz) + vv*_Time.y);s = lerp(-cos(psi), sin(psi), _A3)*0.1;p.y += s;vv = sqrt(_G * _Lambda4 / (2 * _PIE));psi = 2 * _PIE / _Lambda4 *(dot(v.vertex.xyz, _K4.xyz) + vv*_Time.y);s = lerp(-cos(psi), sin(psi), _A4)*0.1;p.y += s;v.vertex.xyz = p.xyz;</span>
Volatility:
The previous pbr can be used to simulate various liquids.
Milk
Blood, etc.
However, due to the subdivision of the surface, there are still small details on the water surface, which need to be solved.
Gerstner wave and Gerstner Wave
The key code is as follows:
<span style="font-size:14px;"> float wave(float x, float z, float timer) { float y = 0; float oct = _OCT; float fac = _FAC; float d = sqrt(x * x + z * z);// length(float2(x, z)); for (oct; oct>0; oct--) { y -= fac * cos(timer * _SP + (1 / fac) * x * z * _WS); fac /= 2; } return 2 * _VS * d * y; } </span>
The small surface produced by surface subdivision is not very obvious, and the smooth effect can be seen without the need to be subdivided.
At last, let's talk about the normal generation,
Normal generation is complex and simple, but in essence it is biased.
Let's take a look at the complex, Chapter 42 from GPU Gems1.
First, find
For example (^ _ ^ ):
Is it very troublesome ..
The normal is essentially like this, but we have two functions: ddx and ddy.
We only need to find the coordinates of the world, worldpos
You can simply find the normal:
N = cross (ddx (worldpos), ddy (worldpos ))
The method is very simple, but don't forget that it is essentially a string above...
Remember: ddx and ddy can only be used in fragment shader.
Only the water body with diffuse reflection is as follows:
-------- By wolf96 http://blog.csdn.net/wolf96
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.