查看: 1414|回复: 0
打印 上一主题 下一主题

unity虚拟视觉效果创建(三)

[复制链接]

5552

主题

2

听众

8万

积分

首席设计师

Rank: 8Rank: 8

纳金币
-1
精华
11

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2012-6-11 15:00:08 |只看该作者 |倒序浏览
Adding an extra dimension
Up to this points we're only using the X axis for input, and in one case time as well. Now we will make a new graph object that uses the Z axis too, thus producing a grid instead of a line.

Create a new Unity object just like Graph 1 along with a new grapher script, calling them Graph 2 and Grapher2 instead. You can speed this up by duplicating them and then making the necessary changes. Disable Graph 1 by toggling the checkbox in front of its name field, because we're not using it anymore. Copy the code from Grapher1 to Grapher2, only changing the class name to Grapher3. We'll modify the rest of the code in a moment.


To change the line into a square grid, we change the CreatePoints method of Grapher2. We need to create a lot more points and use a nested for loop to initialize them. We now set the Z position and the blue color component too.

private void CreatePoints () {

if(resolution < 2){

resolution = 2;

}

currentResolution = resolution;

emitter.ClearParticles();

emitter.Emit(resolution * resolution);

points = emitter.particles;

float increment = 1f / (resolution - 1);

int i = 0;

for(int x = 0; x < resolution; x++){

for(int z = 0; z < resolution; z++){

Vector3 p = new Vector3(x * increment, 0f, z * increment);

points.position = p;

points[i++].color = new Color(p.x, 0f, p.z);

}

}

}


Now we have a nice flat grid! But shouldn't it show the Linear function? It does, but currently only for the first row of points along the Z axis. If you select a different function, only these points will change while the rest remain as they are. This is because in the Update method only loops over resolution points, while it should loop over all of them. We'll use the Length property that every array has to fix this.

void Update () {

if(currentResolution != resolution){

CreatePoints();

}

FunctionDelegate f = functionDelegates[(int)function];

for(int i = 0; i < points.Length; i++){

Vector3 p = points.position;

p.y = f(p.x);

points.position = p;

Color c = points.color;

c.g = p.y;

points.color = c;

}

emitter.particles = points;

}


Now we can see our functions again, extended along to Z axis. Increasing the resolution results in a nice smooth surface. However, you'll notice that if you set the resolution higher than 127, part of the graph will disappear. This is because there is a limit to how many particles a Particle Renderer will display. So it's a good idea to limit the resolution to 127, which translates to 16129 points.

private void CreatePoints () {

if(resolution < 2){

resolution = 2;

}

else if(resolution > 127){

resolution = 127;

}

currentResolution = resolution;

emitter.ClearParticles();

emitter.Emit(resolution * resolution);

points = emitter.particles;

float increment = 1f / (resolution - 1);

int i = 0;

for(int x = 0; x < resolution; x++){

for(int z = 0; z < resolution; z++){

Vector3 p = new Vector3(x * increment, 0f, z * increment);

points.position = p;

points[i++].color = new Color(p.x, 0f, p.z);

}

}

}

There's something else going on that's pretty weird. Try rotating the perspective view while displaying the parabola. From some angles, the graph is drawn wrong. This is because the particles are drawn in the order that we've created them, they don't take view direction into account. You can fix this by setting the Stretch Particles field of the Particle Renderer component to Sorted Billboard. While this makes sure that the graph is show correctly from all view angles, it results in a massive performance hit as well. It's best to stick to the Billboard option and simply look at the graph from only a few angles.


Let's update our function code so we can take advantage of the new dimension. First change the input paramaters of FunctionDelegate to a vector and a float instead of just a single float. While we could specify the X and Z position separately, we'll simply give it the entire position vector. We'll also include the current time, instead of having to look it up inside the functions themselves.

private delegate float FunctionDelegate (Vector3 p, float t);

Now we need to update the function methods accordingly and change how the delegate is called.

void Update () {

if(currentResolution != resolution){

CreatePoints();

}

FunctionDelegate f = functionDelegates[(int)function];

for(int i = 0; i < points.Length; i++){

Vector3 p = points.position;

p.y = f(p, Time.timeSinceLevelLoad);

points.position = p;

Color c = points.color;

c.g = p.y;

points.color = c;

}

emitter.particles = points;

}

private static float Linear (Vector3 p, float t) {

return p.x;

}

private static float Exponential (Vector3 p, float t) {

return p.x * p.x;

}

private static float Parabola (Vector3 p, float t){

p.x = 2f * p.x - 1f;

return p.x * p.x;

}

private static float Sine (Vector3 p, float t){

return 0.5f + 0.5f * Mathf.Sin(2 * Mathf.PI * p.x + t);

}

We're ready to include Z in our mathematical functions! For example, change the Parabola function to f(x,z) = 1 - (2x - 1)2 * (2z - 1)2. We can also go wild with the Sine function, layering multiple sines to get a complex oscillating effect.

private static float Parabola (Vector3 p, float t){

p.x = 2f * p.x - 1f;

p.z = 2f * p.z - 1f;

return 1f - p.x * p.x * p.z * p.z;

}

private static float Sine (Vector3 p, float t){

return 0.50f +

0.25f * Mathf.Sin(4 * Mathf.PI * p.x + 4 * t) * Mathf.Sin(2 * Mathf.PI * p.z + t) +

0.10f * Mathf.Cos(3 * Mathf.PI * p.x + 5 * t) * Mathf.Cos(5 * Mathf.PI * p.z + 3 * t) +

0.15f * Mathf.Sin(Mathf.PI * p.x + 0.6f * t);

}

分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2025-6-16 14:52 , Processed in 0.057731 second(s), 28 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部