Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by LukaKotar · Sep 06, 2015 at 09:48 PM · shadershader programmingadvanced

Send float value from shader to script?

Can a shader give information to the CPU code? For example, a shader function returns some information which the shader itself can't do anything with, but would be valuable information in CPU code. Where do I store that value to have access to it from script?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Eudaimonium · Sep 06, 2015 at 09:59 PM

You cannot. Shaders are part of the graphics "pipeline", which means that you input the info to the GPU and it'll render stuff on screen.

It's a one-way ticket.

Problem is, you cannot simply return one float (even if you could return some data). Remember, shader program is executed once per every vertex of a game object + once for every pixel of game object displayed on screen.

So if your object covers half the screen on a fullHD resolution, a pixel shader would theoretically "return" ~1 million different float values.

You can actually return some values from GPU back to main memory, but it's special GPGPU computing area and not GPU accelerated graphics, which is what we're dealing with in a game engine.

Note: I do not know how ComputeShader works though.

Now, if you need that info for some debugging to find out what's going on in your shader code, best way is to actually render out the float values in some meaningful way. Suppose you want to find out if a particular pixel is too close to the camera, and you need to find out what's the depth value.

Simply have the pixel shader program write a red pixel if the value is too close, or return normal colored pixel if value is too far.

Pixels that are too close will be red. Shader debugging is often composed of such various hacks and workarounds.

If you absolutely must analize your shader input in total detail, you can write the needed values into seperate RenderTarget texture, and then read that texture using the CPU. Note: Reading the RenderTexture values via CPU is EXTREMELY slow and will kill performance. I recommend avoiding that.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image TheSmokingGnu · May 11, 2020 at 06:21 PM 0
Share

Could you please give an example of RenderTarget texture approach? How to 1) write to it in the hlsl and 2) read it whole in the C#?

I'd really love to have the ability to send the data from shader to RA$$anonymous$$, however slow and hacky, to use at least once in editor, and your last paragraph is the most promising thing that I found!

avatar image Eudaimonium TheSmokingGnu · May 11, 2020 at 08:17 PM 0
Share

Yeah, you can use the Texture2D.GetPixels method: https://docs.unity3d.com/ScriptReference/Texture2D.GetPixels.html

RenderTexture inherits from Texture2D so it also has the same method. There is also a way to do this asyncronously to avoid stalling the main thread but it's significantly more complex: https://unity.xiaomo.info/ScriptReference/Rendering.AsyncGPUReadbackRequest.html

avatar image TheSmokingGnu Eudaimonium · May 12, 2020 at 04:16 PM 0
Share

So reading (receiving) on cpu is actually simple. What I didn't realise was that "sending" on GPU is actually rendering ( returning data as a color in fragment shader).

This is not ideal, because surface shaders, or the new shader graph do not let you control exactly what is returned from fragment shader. Now I am using Albedo to pass my value, and it sort of works: 0.5 on gpu -> .498 on cpu. But it is still scary that lighting can interfere with it.


EDIT: Also, looks like I get only 3 digits per color value this way :) - since with shader graph (and I imagine surface shaders too), the resulting fragment color value is truncated to [0, 1], and frag shaders there use half3, which allows only for 3 digits of precision


Anyway, here's the example for that, from this thread.

 if (!TryGetComponent(out $$anonymous$$eshRenderer renderer))
         {
             return;
         }
         //  all colors should be the same since you should return a constant debug value, so we need only one pixel/color
         int width = 1;
         int height = 1;
 
         RenderTexture buffer = new RenderTexture(
                                width,
                                height,
                                0,                            // No depth/stencil buffer
                                RenderTextureFormat.ARGB32,   // Standard colour format
                                RenderTextureReadWrite.Linear // No sRGB conversions
                            );
 
         Graphics.Blit(null, buffer, renderer.shared$$anonymous$$aterial);
 
 
         Texture2D outputTex = new Texture2D(width, height, TextureFormat.ARGB32, false);
 
         RenderTexture.active = buffer;           // If not using a scene camera
         outputTex.ReadPixels(
                   new Rect(0, 0, width, height), // Capture the whole texture
                   0, 0,                          // Write starting at the top-left texel
                   false                          // No mipmaps
         );
     // this is what you return in your fragment shader
     Debug.Log($"Shader Debug Color: {string.Join(",", outputTex.GetPixels()[0])}");


Then, each color of the array will hold the value returned by your fragment shader.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

28 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Shader Graph - How to draw Circle? 1 Answer

Shader - Render to Texture 0 Answers

How to locate the correct texture within a texture atlas using a shader? 1 Answer

Unity crashes when trying to run depth shader with color lerp. 1 Answer

I am Getting Error in shader how can i solve it,I am Getting error in Shader 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges