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
1
Question by hendrikgruss · Jan 16, 2017 at 03:03 PM · shadertexturerendertextureconversionblit

How to use Graphics.Blit with custom input textures

I am facing some problems in converting an image from YUV to RGB format.

I am using the Google Tango API with Unity. It gives me the bytes of an image in YUV format in the following callback function:

 OnTangoImageAvailableEventHandler(TangoEnums.TangoCameraId cameraId, TangoUnityImageData imageBuffer)

Fortunately, they already have a YUV2RGB shader together with a material to convert images in their YUV format to RGB. So my plan was to create the two textures that the shader expects as input from the imageBuffer.data byte array. I then set those to the material from Tango and use Graphics.Blit to render the result to a RenderTexture. This is the function that I use for this task:

 public void OnTangoImageAvailableEventHandler(TangoEnums.TangoCameraId cameraId, TangoUnityImageData imageBuffer)
     {
         // Split buffer into y and uv part
         byte[] yDataPart = new byte[imageBuffer.width * imageBuffer.height];
         Array.Copy (imageBuffer.data, 0, yDataPart, 0, imageBuffer.width * imageBuffer.height); 
 
         byte[] uDataPart = new byte[2 * (imageBuffer.width / 2) * (imageBuffer.height / 2)];
         Array.Copy (imageBuffer.data, imageBuffer.width * imageBuffer.height, uDataPart, 0, 2 * (imageBuffer.width / 2) * (imageBuffer.height / 2));
 
         // Create the textures from the data
         Texture2D yTex = new Texture2D(width / 4, height, TextureFormat.RGBA32, false);
         yTex.LoadRawTextureData (yDataPart);
         yTex.Apply ();
 
         Texture2D uTex = new Texture2D((width / 2) / 4 * 2, height / 2, TextureFormat.RGBA32, false);;
         uTex.LoadRawTextureData (uDataPart);
         uTex.Apply ();
 
         // Set them to shader
         yuv2rgbMat.SetTexture ("_YTex", yTex);
         yuv2rgbMat.SetTexture ("_UTex", uTex);
 
         // Draw
         Graphics.Blit (dummyRenderTex, rgbRenderTex, yuv2rgbMat);
     }

In that code snippet, the yuv2rgbMat is set to the ARScreen material from tango, which has the YUV2RGB shader connected.

This leads directly to my first question:

Is it necessary to provide an input render texture to Graphics.Blit if I already set the input textures directly to the material?

Now besides from that question, here is the real problem. When I later what to create a Texture2D from the RenderTexture to work further with it, the texture is completely set to 0. This is the code I use to access the resulting texture:

 public IEnumerator drawRGBTexture()
         {
             while (true) {
                 yield return new WaitForEndOfFrame ();
     
                 if (rgbRenderTex != null) {
                     RenderTexture.active = rgbRenderTex;
                     rgbTex.ReadPixels (new Rect (0, 0, width, height), 0, 0);
                     rgbTex.Apply ();
     
                     // At this point rgbTex is completely filled with zeros!!
                     // Even if there were a lot of non zero entries in the original YUV byte stream
     
                     RenderTexture.active = null;
                 }
             }
         }

This leads to my second question:

Why is the resulting texture filled with zeros and not with the correct output of the shader?

Comment
Add comment · Show 2
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 hendrikgruss · Jan 18, 2017 at 10:08 PM 0
Share

I made some progress in the problem, the conversion using Graphics.Blit works now. There are still problems with accessing the raw image data. Here is the link to a new question I posted on Stackoverflow: http://stackoverflow.com/questions/41730124/how-to-access-raw-data-from-rendertexture-in-unity

avatar image chezulkhairi · Apr 20, 2017 at 05:09 PM 0
Share

Hi,

Where does the OnTangoImageAvailableEventHandler function go. Did you edit and put it into one of the existing Tango .cs file? And, how do you make the Shader output to your UI Raw Image that has the (http://stackoverflow.com/questions/41730124/how-to-access-raw-data-from-rendertexture-in-unity) code to it?

Thanks, Che

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by hendrikgruss · Apr 20, 2017 at 08:07 PM

Oh sorry I forgot to post that i solved the Problem. I had some uninutialized variables, that caused the error in consequence.

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 karyuu_s · May 07, 2017 at 10:08 AM 0
Share

Hi,I'm developing an app with Tango SD$$anonymous$$(Farandole Unity 5),but I met a problem similar to your's.The core code is listed down:

 private int tWidth = 0;
 private int tHeight = 0;
 private Texture2D dummyInput;
 private Texture2D yTex;
 private Texture2D uvTex;
 private byte[] yDataPart;
 private byte[] uvDataPart;
 private RenderTexture mRenderTexture;
 private Texture2D mTexture;
 private bool mTextureReady = false;
 public $$anonymous$$aterial YUV2RGB;
 public GameObject mQuad;
 
 public void OnTangoImageAvailableEventHandler(TangoEnums.TangoCameraId cameraID, TangoUnityImageData imageData){
     if (TangoEnums.TangoCameraId.TANGO_CA$$anonymous$$ERA_COLOR == cameraID) {
         if (!mTextureReady) {
             tWidth = (int)imageData.width;
             tHeight = (int)imageData.height;
 
             dummyInput = new Texture2D (tWidth, tHeight, TextureFormat.RGBA32, false);
 
             yDataPart = new byte[tWidth * tHeight];
             uvDataPart = new byte[2 * (tWidth / 2) * (tHeight / 2)];
             yTex = new Texture2D (tWidth / 4, tHeight, TextureFormat.RGBA32, false);
             yTex.Apply ();
             uvTex = new Texture2D ((tWidth / 2) / 4 * 2, tHeight / 2, TextureFormat.RGBA32, false);
             uvTex.Apply ();
 
             mRenderTexture = new RenderTexture (tWidth, tHeight, 0, RenderTextureFormat.ARGB32);
 
             mTexture = new Texture2D (tWidth, tHeight, TextureFormat.ARGB32, false);
             mTexture.Apply ();
             mQuad.GetComponent<Renderer> ().material.mainTexture = mTexture;
 
             mTextureReady = true;
 
             StartCoroutine (UpdateTexture2D ());
         }
 
         Array.Copy (imageData.data, 0, yDataPart, 0, tWidth * tHeight);
 
         Array.Copy (imageData.data, tWidth * tHeight, uvDataPart, 0, 2 * (tWidth / 2) * (tHeight / 2));
 
         yTex.LoadRawTextureData (yDataPart);
         yTex.Apply ();
 
         uvTex.LoadRawTextureData (uvDataPart);
         uvTex.Apply ();
 
         YUV2RGB.SetFloat ("_TexWidth", tWidth);
         YUV2RGB.SetFloat ("_TexHeight", tHeight);
         YUV2RGB.SetTexture ("_YTex", yTex);
         YUV2RGB.SetTexture ("_UTex", uvTex);
 
         Graphics.Blit (dummyInput, mRenderTexture, YUV2RGB);
     }
 }
 
 IEnumerator UpdateTexture2D(){
     while (mTextureReady) {
         yield return new WaitForEndOfFrame ();
 
         RenderTexture.active = mRenderTexture;
         mTexture.ReadPixels (new Rect (0, 0, tWidth, tHeight), 0, 0);
         mTexture.Apply ();
         RenderTexture.active = null;
     }
 }

But the output texture is just confusing,it's quite different from what I expected.Could you please tell me what's wrong with my code or is there any tutorial about it?

PS: The CPU method works fine.I mean,the imageData is just right,and if I process it directly to the texture2D(without using shader and renderTexture),the output is fine(what I expected).

Thank you.

avatar image karyuu_s karyuu_s · May 08, 2017 at 09:15 AM 0
Share

Well,I fixed it partly.The fixed code is list below,it works fine in my app.

 private int tWidth = 0;
 private int tHeight = 0;
 private Texture2D dummyInput;
 private Texture2D yTex;
 private Texture2D uvTex;
 private byte[] yDataPart;
 private byte[] uvDataPart;
 private RenderTexture mRenderTexture;
 private Texture2D mTexture;
 private bool mTextureReady = false;
 public $$anonymous$$aterial YUV2RGB;//$$anonymous$$aterial: TangoPrefabs/$$anonymous$$aterials/ar_screen
 public GameObject mQuad;
 
 public void OnTangoImageAvailableEventHandler(TangoEnums.TangoCameraId cameraID, TangoUnityImageData imageData){
     if (TangoEnums.TangoCameraId.TANGO_CA$$anonymous$$ERA_COLOR == cameraID) {
         CheckSize ((int)imageData.width, (int)imageData.height);
 
         Array.Copy (imageData.data, 0, yDataPart, 0, tWidth * tHeight);
 
         Array.Copy (imageData.data, tWidth * tHeight, uvDataPart, 0, 2 * (tWidth / 2) * (tHeight / 2));
 
         yTex.LoadRawTextureData (yDataPart);
         yTex.Apply ();
 
         uvTex.LoadRawTextureData (uvDataPart);
         uvTex.Apply ();
 
         YUV2RGB.SetFloat ("_TexWidth", tWidth);
         YUV2RGB.SetFloat ("_TexHeight", tHeight);
         YUV2RGB.SetTexture ("_YTex", yTex);
         YUV2RGB.SetTexture ("_UTex", uvTex);
 
         mRenderTexture.DiscardContents ();
         Graphics.Blit (dummyInput, mRenderTexture, YUV2RGB);
         //It seems that only right-top region of mRenderTexture is rendered.Could someone tell me why?
         GL.InvalidateState ();
 
         RenderTexture.active = mRenderTexture;
         mTexture.ReadPixels (new Rect (tWidth / 2, tHeight / 2, tWidth, tHeight), 0, 0);
         mTexture.Apply ();
         RenderTexture.active = null;
     }
 }
avatar image karyuu_s karyuu_s · May 08, 2017 at 09:16 AM 0
Share
 public void CheckSize(int _width, int _height){
     if (!mTextureReady) {
         tWidth = _width;
         tHeight = _height;
 
         dummyInput = new Texture2D (64, 64);
 
         yDataPart = new byte[tWidth * tHeight];
         uvDataPart = new byte[2 * (tWidth / 2) * (tHeight / 2)];
         yTex = new Texture2D (tWidth / 4, tHeight, TextureFormat.RGBA32, false);
         yTex.Apply ();
         uvTex = new Texture2D ((tWidth / 2) / 4 * 2, tHeight / 2, TextureFormat.RGBA32, false);
         uvTex.Apply ();
 
         mRenderTexture = new RenderTexture (tWidth, tHeight, 0);
 
         mTexture = new Texture2D (tWidth / 2, tHeight / 2);
         mTexture.Apply ();
         mQuad.SetActive (true);
         mQuad.GetComponent<Renderer> ().material.mainTexture = mTexture;
 
         mTextureReady = true;
     }
 
     if (tWidth == _width && tHeight == _height) {
         return;
     }
 
     tWidth = _width;
     tHeight = _height;
 
     yDataPart = new byte[tWidth * tHeight];
     uvDataPart = new byte[2 * (tWidth / 2) * (tHeight / 2)];
     GC.Collect ();
 
     DestroyImmediate (yTex);
     DestroyImmediate (uvTex);
 
     yTex = new Texture2D (tWidth / 4, tHeight, TextureFormat.RGBA32, false);
     yTex.Apply ();
     uvTex = new Texture2D ((tWidth / 2) / 4 * 2, tHeight / 2, TextureFormat.RGBA32, false);
     uvTex.Apply ();
 
     mRenderTexture.Release ();
     mRenderTexture = new RenderTexture (tWidth, tHeight, 0);
 
     DestroyImmediate (mTexture);
     mTexture = new Texture2D (tWidth / 2, tHeight / 2);
     mTexture.Apply ();
     mQuad.GetComponent<Renderer> ().material.mainTexture = mTexture;
 }
avatar image
0

Answer by larch181 · Mar 10, 2018 at 06:23 AM

Thank you for your effort. But when I use your two guys's code in my project. What I can get is just a rectangular with light red color? Is there any special setting? @karyuu_s @hendrikgruss

Comment
Add comment · 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

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

7 People are following this question.

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

Related Questions

How to clean on RenderTexture to transparent with brush 0 Answers

Copy result of pass to another pass of the same shader 1 Answer

Manipulating pixels in a texture 0 Answers

Render material to full screen quad 2 Answers

use RenderTexture on a sphere correctly? 1 Answer


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