0
\$\begingroup\$

I want to animate foliage with vertex animation but I have wrong output because I can't correctrly transform from object space to clip space, and my foliage goes off the model. How Can I convert in corrent way the space?

fragmentInput vertexProgram(vertexInput data)
{
    UNITY_SETUP_INSTANCE_ID(data);

    fragmentInput output;
    float3 positionWS = TransformObjectToWorld(data.positionOS);
    output.positionCS = TransformWorldToHClip(positionWS);
    output.positionWSAndFog = float4(positionWS, ComputeFogFactor(output.positionCS.z));

    VertexNormalInputs normalInput = GetVertexNormalInputs(data.normalOS, data.tangentOS);
    output.normalWS = normalInput.normalWS;
    output.tangentWS = normalInput.tangentWS;
    output.bitangentWS = normalInput.bitangentWS;

    output.uv = TRANSFORM_TEX(data.uv, _BaseColor);

    output.viewDirectionWS = GetWorldSpaceViewDir(positionWS);

#ifdef _MAIN_LIGHT_SHADOWS
    output.shadowCoord = TransformWorldToShadowCoord(positionWS);
#endif

    OUTPUT_LIGHTMAP_UV(input.staticLightmapUV, unity_LightmapST, output.staticLightmapUV);
    OUTPUT_SH(output.normalWS, output.vertexSH);
    
    // I'm starting my animation from here
    float4 worldPos = mul(data.positionOS, unity_ObjectToWorld);
    float2 samplePos = worldPos.xz / _WorldSize.xz;
    samplePos += _Time.x * _WindSpeed.xy;
    float windSample = tex2Dlod(_WindTex, float4(samplePos, 0, 0));

    output.positionCS.x += sin(_WaveSpeed * windSample) * _WaveAmp;
    output.positionCS.z += cos(_WaveSpeed * windSample) * _WaveAmp;

    // then I sholud somehow convert to clip space if im not wrong
    return output;
}

Here what I've got: enter image description here

\$\endgroup\$
5
  • \$\begingroup\$ It looks to me like you have the correct function to use already demonstrated at the top of this code: TransformWorldToHClip(positionWS); You can find its source code here. How have you tried using this so far and where did things go wrong? \$\endgroup\$ Commented Mar 12, 2023 at 20:45
  • \$\begingroup\$ @DMGregory I used it with cg transform function before and it was ok, but now with hlsl it doesn't work \$\endgroup\$ Commented Mar 12, 2023 at 20:53
  • \$\begingroup\$ What exact code did you write using this function, and in what way did the results differ from what you wanted? \$\endgroup\$ Commented Mar 12, 2023 at 21:01
  • \$\begingroup\$ @DMGregory I Finally resolved it. The value for wave amplitude was too high, it affect on the position. \$\endgroup\$ Commented Mar 12, 2023 at 21:10
  • \$\begingroup\$ @DMGregory I remember I did it already, but im too tired, to remember this right now. So my mistake \$\endgroup\$ Commented Mar 12, 2023 at 21:14

2 Answers 2

0
\$\begingroup\$

_WaveAmp value was too high and affect possition of vertecies. Around 0.08 is ok

    output.positionCS.x += sin(_WaveSpeed * windSample) * _WaveAmp;
    output.positionCS.z += cos(_WaveSpeed * windSample) * _WaveAmp;
\$\endgroup\$
2
  • \$\begingroup\$ You're modifying the position directly in homogeneous clip space. That will make your animation view dependent, which may not be what you want. \$\endgroup\$ Commented Mar 12, 2023 at 21:21
  • \$\begingroup\$ @DMGregory Yes, I get it. I'm only studying all that stuff and don't know any other war right now. Thanks for the information \$\endgroup\$ Commented Mar 12, 2023 at 21:32
0
\$\begingroup\$

It looks to me like what you want is something like this. Start with the beginning of the shader until it computes the position in world space:

fragmentInput vertexProgram(vertexInput data)
{
    UNITY_SETUP_INSTANCE_ID(data);

    fragmentInput output;
    float3 positionWS = TransformObjectToWorld(data.positionOS);

Now add your code that modifies the world space position. You don't need your line float4 worldPos = ... since positionWS already contains the world space position:

    float2 samplePos = positionWS.xz / _WorldSize.xz;
    samplePos += _Time.x * _WindSpeed.xy;
    float windSample = tex2Dlod(_WindTex, float4(samplePos, 0, 0));

    positionWS.x += sin(_WaveSpeed * windSample) * _WaveAmp;
    positionWS.z += cos(_WaveSpeed * windSample) * _WaveAmp;

Now you can continue with the rest of the shader, that computes the clip space position from the world space position:

    output.positionCS = TransformWorldToHClip(positionWS);
    output.positionWSAndFog = float4(positionWS, ComputeFogFactor(output.positionCS.z));

    VertexNormalInputs normalInput = GetVertexNormalInputs(data.normalOS, data.tangentOS);
    output.normalWS = normalInput.normalWS;
    output.tangentWS = normalInput.tangentWS;
    output.bitangentWS = normalInput.bitangentWS;

    output.uv = TRANSFORM_TEX(data.uv, _BaseColor);

    output.viewDirectionWS = GetWorldSpaceViewDir(positionWS);

#ifdef _MAIN_LIGHT_SHADOWS
    output.shadowCoord = TransformWorldToShadowCoord(positionWS);
#endif

    OUTPUT_LIGHTMAP_UV(input.staticLightmapUV, unity_LightmapST, output.staticLightmapUV);
    OUTPUT_SH(output.normalWS, output.vertexSH);
    
    return output;
}

Doing it this way, your wind displacement also affects the shadow.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for help \$\endgroup\$ Commented Mar 12, 2023 at 21:59

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.