Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question How to render meshes to a render texture immediately using URP?

Discussion in 'Universal Render Pipeline' started by CDF, Oct 11, 2021.

  1. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    1,307
    Hi, So I'm struggling to figure out how to render some meshes to a render texture immediately in URP.
    In the built-in pipeline you can build a command buffer and call Graphics.ExecuteCommandBuffer
    However, in URP, doing this results in pink materials.

    I want to just draw some objects to a texture at any time and have that function return a Texture2D.

    I see that using RenderPipelineManager.beginContextRendering does work, but that means I can't return a texture immediately.

    What do I need to do, in order to render some meshes at anytime to a texture in URP?
     
  2. RyanKeable

    RyanKeable

    Joined:
    Oct 16, 2013
    Posts:
    62
    tun1018 likes this.
  3. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    1,307
    Hmm, doesn't that mean you need a ScriptableRenderFeature added to the pipeline?

    I don't want a persistent render feature added. I just want to render some meshes to a texture on some event.
    Like pressing a button.

    How can you inject a ScriptableRenderPass, execute it and get the results in a single call?
     
    febucci likes this.
  4. j_chai

    j_chai

    Joined:
    Jun 30, 2021
    Posts:
    38
    Most likely a terrible idea, but this worked for me:
    Add an Action to RenderPipelineManager.beginCameraRendering, as an example I'm calling mine "RenderNow", containing something like:
    Code (CSharp):
    1. private void RenderNow(ScriptableRenderContext context, Camera camera)
    2. {
    3.     // initialize [_renderingCamera] with the perspective you want to render from
    4.     if (camera == _renderingCamera)
    5.     {
    6.         var cmd = CommandBufferPool.Get();
    7.         // Set RT
    8.         // cmd.SetRenderTarget(rt);
    9.         // Clear RT
    10.         // cmd.ClearRenderTarget(true, true, Color.black);
    11.         // Your renderer and Material here, any Draw function from the command buffer should be usable
    12.         // cmd.DrawRenderer(renderer, material);
    13.         context.ExecuteCommandBuffer(cmd);
    14.         CommandBufferPool.Release(cmd);
    15.     }
    16. }
    Disable the [_renderingCamera] GameObject, and call _renderingCamera.Render whenever you want to render.
     
  5. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    1,307
    Thanks.

    Turns out Graphics.DrawMesh works within that callback, and is more useful to me, as I can specify the layer and camera to draw the meshes into.

    Basically, I'm trying to render a static preview of some meshes isolated from other scene elements (lighting, shadows) etc. So while the command buffer method does work, it unfortunately includes lighting and shadow information from the current scene.

    Would be nice if there was a way to render some meshes excluded from all scene lighting and provide my own lighting setup... maybe it's possible for a command buffer to override some internal values, like light color, light direction, shadow map etc. But not sure
     
  6. j_chai

    j_chai

    Joined:
    Jun 30, 2021
    Posts:
    38
    I'm not sure if you can override Unity's shader values using command buffers either, but one option is to guard the lighting, GI, etc, calculation just like how you can define [SHADERGRAPH_PREVIEW] in shadergraph shaders.
    You'll either need to modify the URP package or modify your custom shader,
    but you can have something like this in your shader code:
    Code (CSharp):
    1. #ifdef STATIC_PREVIEW
    2. Light GetMainLight()
    3. {
    4.     Light output = (Light)0;
    5.     output.direction = half3(0, 0, 1);
    6.     output.color = half3(1, 1, 1);
    7.     // ...
    8.     return output;
    9. }
    10. #else
    11. Light GetMainLight()
    12. {
    13.     // Unity's GetMainLight function
    14. }
    15. #endif
    You could then use Material.EnableKeyword before calling Graphics.DrawMesh.
    Don't forget to add #pragma multi_compile or shader_feature if you use this method.
     
    CDF likes this.
  7. BOXOPHOBIC

    BOXOPHOBIC

    Joined:
    Jul 17, 2015
    Posts:
    506
    Hey, this might help: https://www.dropbox.com/s/oxa85e0vfauscpc/renderwithoutcamera2.unitypackage?dl=0

    It is rendering unlit objects or particles to a render texture in a defined volume, from top down, basicaly like an ortographic camera. It can be turned into a perspective cam by modifing some matrix I used, and it can save the overhead from adding a new camera and save some layers.

    This is some early experimentation I used while developing my asset, the veg engine, I m not sure what s the state on it, it might me messy...

    If you want to suppot all pipelines with an unlit shader, a nice trick is to remove the LightMode tag. I hope it helps :)
     
  8. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    1,307
    Thanks, I'll check this out
     
  9. qpuilie

    qpuilie

    Joined:
    Jan 14, 2020
    Posts:
    69
    Hi,I am also plagued by the same problem.I want to render terrain depth in single rendertexture use "DepthOnlyPass".
    Currently I only found one way to successfully write Mesh to RenderTexture:
    It won't work if i don't use callbacks.
    Did you find a solution?

    Thanks.
     

    Attached Files:

  10. dsfgddsfgdsgd

    dsfgddsfgdsgd

    Joined:
    Jan 24, 2014
    Posts:
    16
    This is great thanks so much for sharing
     
  11. tun1018

    tun1018

    Joined:
    Sep 18, 2019
    Posts:
    12
    WOW,could you upload this package again...Thank YOU!!
     
  12. BOXOPHOBIC

    BOXOPHOBIC

    Joined:
    Jul 17, 2015
    Posts:
    506
    It is not working?
     
  13. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    13,291
    Use a separate camera with shader replacement renderer feature
     
  14. tun1018

    tun1018

    Joined:
    Sep 18, 2019
    Posts:
    12
    Working,I got it....THX
     
  15. NOT_Lonely

    NOT_Lonely

    Joined:
    Feb 2, 2013
    Posts:
    522
    Could you please explain how to render to a render texture from an additional camera? In BiRP I used camera.Render method on a disabled camera to render only once when I need. But it looks like it doesn't work in URP.
     
  16. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    13,291
    You can just have an always enabled camera in the scene directly, but there is also a URP render now function if need to recreate the BIRP behavior.
     
  17. NOT_Lonely

    NOT_Lonely

    Joined:
    Feb 2, 2013
    Posts:
    522
    What should I use to make a render from this camera?
     
  18. NOT_Lonely

    NOT_Lonely

    Joined:
    Feb 2, 2013
    Posts:
    522
    I think I just got it working. I created a new Universal Renderer asset, added it into the URP asset Renderer List, and then selected it for my camera, that I need to render into RT. After all that it works as it was in the BiRP - just call myCamera.Render().
     
  19. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    13,291
    yes correct, in that renderer can assign any method, like render objects with replacement shader etc

    Not sure on camera.render() though, as URP has a specific method for that

    UniversalRenderPipeline.RenderSingleCamera

    https://forum.unity.com/threads/is-there-any-way-to-do-a-single-camera-render-with-urp.816696/
     
  20. NOT_Lonely

    NOT_Lonely

    Joined:
    Feb 2, 2013
    Posts:
    522
    I tried to do it using this method, but didn't understand how it works. In the example from the thread it looks like I have to subscribe to the RenderPipeline.beginCameraRendering, and then call the UniversalRenderPipeline.RenderSingleCamera from there, but it executes in a loop, not only once as I needed.
     
  21. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    13,291
    I see, if works with the old camera.render() should also be fine i guess

    I suppose the register in the event make sense if need to cast that render in the specific time in the pipeline, but if is a once thing should not matter
     
  22. NOT_Lonely

    NOT_Lonely

    Joined:
    Feb 2, 2013
    Posts:
    522
    Yeah, this is exactly how I understood this. So if I don't need to inject something specific into the render loop, this method is useless for me. Thanks man for your help!
     
    nasos_333 likes this.
  23. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    13,291
    np :)
     
  24. tun1018

    tun1018

    Joined:
    Sep 18, 2019
    Posts:
    12
    like offline rendering.

    first set my render target.

    and then render objects to the render target.