2

我用以下节点创建了一个脉动闪亮的效果:

Abs(Time * speed) => sine

我有一个介于 0 和 1 之间的振荡值,但问题是该值可能从 0 和 1 之间的任何值开始,具体取决于时间值。

我试图找出一种可以在着色器之外获取该值的方法,以便脚本可以将属性设置为偏移:

float offset = GetTimeFromShader();
material.SetFloat("_Offset", offset);

着色器最终得到:

Abs((Time - offset) * speed) => sine

这将确保脉动从 0 开始。

另一种可能性是在着色器模拟中创建一个增加的vector1:

temp += Time.deltaTime * speed;

但是着色器图可以防止节点循环。

我可以在脚本中执行此操作并将其传递给着色器属性,但如果有办法将其全部保存在着色器中。

4

2 回答 2

1

我有一个介于 0 和 1 之间的振荡值,但问题是该值可能从 0 和 1 之间的任何值开始,具体取决于时间值。

那就是你的问题。您可以很容易地将着色器更改为从 0 开始振荡并且独立于内置着色器时间,不是吗?这将意味着从脚本驱动着色器,这是您不想要的,但我认为在这种情况下这不是坏习惯,因为听起来您希望振荡直接与游戏中的特定事件相关联- 所以非常努力地将着色器代码与应用程序代码分离在这里有点多余 - 它们需要以某种方式链接到某个地方。

要将着色器与内置着色器时间分离,而不是Abs(Time * speed)将 Time 替换为您控制的属性,即Abs(phase * speed).

我使用以下代码来播放冲击波效果,并始终确保它从我想要的位置开始:

// ensures shockwave plays once and does a full wave over duration
IEnumerator PlayShockwave(float duration, Renderer shockwave)
{
    float timeElapsed = 0f;
    float speed = Mathf.Abs(shockwave.material.GetFloat("_Speed"));
    float phase = shockwave.material.GetFloat("_Phase");
    float targetPhase = 1 / speed;

    while (timeElapsed <= duration)
    {
        timeElapsed += Time.deltaTime;
        shockwave.material.SetFloat("_Phase", Mathf.Lerp(phase, targetPhase, timeElapsed / duration));
        yield return new WaitForEndOfFrame();
    }
}

并调用它StartCoroutine(PlayShockwave(2.0f, YourRenderer));

于 2021-01-03T03:06:07.660 回答
0

我认为问题在于您无法保证着色器开始渲染时 Time 的值是多少。这也意味着提供偏移量是没有意义的,因为您不知道偏移量需要的值(并且它可能每次都会改变)。要执行您要求的操作,您需要使用脚本设置的着色器属性MaterialPropertyBlock

于 2020-10-19T03:33:13.273 回答