Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Question How can I apply a custom projection in HLSL?

Discussion in 'General Graphics' started by Kyle45, Jul 10, 2023.

  1. Kyle45

    Kyle45

    Joined:
    Apr 18, 2015
    Posts:
    10
    Hi,

    I'm trying to take the built in URP Particle shader and render everything using a camera's projection matrix so that all first person effects stay at 60 fov, regardless of what the primary camera fov is set to. I'm trying to avoid camera stacking since its quite costly. I believe Ive found the part of the code to modify, but with my current solution the models get flipped upside down and move in the opposite vertical direction with the scene camera. I'm not sure why my solution wouldn't work so I'd appreciate some help from someone.

    This function gets called from the Vertex shader which is where I try to apply a different projection, "my_projection", which is being passed in from a monobehavior.

    Code (csharp):
    1.  
    2. HLSLPROGRAM
    3. ...
    4. uniform float4x4 my_projection;
    5. ...
    6.          
    7. VertexPositionInputs KylesGetVertexPositionInputs(float3 positionOS)
    8. {
    9.     VertexPositionInputs input;
    10.  
    11.     input.positionWS = TransformObjectToWorld(positionOS);
    12.     input.positionVS = TransformWorldToView(input.positionWS);
    13.  
    14.     // This works
    15.     // float4x4 viewProjection = mul(UNITY_MATRIX_P, UNITY_MATRIX_V);
    16.     // input.positionCS = mul(viewProjection, float4(input.positionWS, 1.0));
    17.  
    18.     // This does not work
    19.     float4x4 viewProjection = mul(my_projection, UNITY_MATRIX_V);
    20.     input.positionCS = mul(viewProjection, float4(input.positionWS, 1.0));
    21.  
    22.     float4 ndc = input.positionCS * 0.5f;
    23.     input.positionNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
    24.     input.positionNDC.zw = input.positionCS.zw;
    25.  
    26.     return input;
    27. }
    28.  
    Code (CSharp):
    1.    
    2. [SerializeField] private Camera fpCam;
    3.    
    4. private void Update() {
    5.     // Obviously slow
    6.     GetComponent<Renderer>().material.SetMatrix("my_projection", fpCam.projectionMatrix);
    7. }
    8.  
     
  2. lilacsky824

    lilacsky824

    Joined:
    May 19, 2018
    Posts:
    167
    Hi.
    Is your graphics API DirectX?
    If you render object into RenderTexture then you can try this to get correct projection matrix.
    Code (CSharp):
    1. GL.GetGPUProjectionMatrix(fpCam.projectionMatrix, true)
     
  3. fontesdeletrass

    fontesdeletrass

    Joined:
    Aug 25, 2023
    Posts:
    1
    1. Create a custom projection matrix. This matrix can be defined in any way that you want, but it must be a 4x4 matrix.
    2. In your vertex shader, declare a variable to store the custom projection matrix.
    3. In the vertex shader's main function, multiply the model matrix by the custom projection matrix.
    4. Pass the result of the multiplication to the fragment shader.
    5. In the fragment shader, you can use the projection matrix to transform the vertex's position from world space to clip space.
    Here is an example of how to apply a custom projection in HLSL:

    // Create the custom projection matrix.
    float4x4 customProjectionMatrix = ...;

    // Declare a variable to store the custom projection matrix.
    float4x4 g_CustomProjectionMatrix;

    // In the vertex shader's main function, multiply the model matrix by the custom projection matrix.
    float4 vPositionClipSpace = mul(modelMatrix, g_CustomProjectionMatrix);

    // Pass the result of the multiplication to the fragment shader.
    out float4 vPositionClipSpace : SV_POSITION;

    I hope this helps! Let me know if you have any other questions.
    Letras Diferentes
     
    Last edited: Aug 26, 2023