- Home /
When using Graphics.Blit() in Android, getting a black screen
I'm performing some GPU computation (using surface shaders) on Android (Pro) in Unity (Pro) - a series of straightforward pixel comparisons, followed by a merging of all changes observed between the textures over the previous sixty frames. To extract the results from the GPU, I was using a secondary camera and active RenderTexture, but was advised to use Graphics.Blit() instead for performance benefits (and to deal with offset issues that arose when it came to the merging shader). I used ReadPixels in both approaches to extract the data to a Texture2D.
Employing Graphics.Blit() did provide a performance benefit in the Windows Editor, and also solved the issue I'd been having with the merging step, with the program running exactly as intended. When I deployed the project on a test platform (Samsung Galaxy S4), however, all I got was a black screen with a frames-per-second overlay.
In attempting to resolve this issue, I've searched the forum pretty thoroughly for similar issues, and found a few. The most common suggestion to folks with similar problems was to add
ZTest Always Cull Off ZWrite Off Fog { Mode Off }
to the shaders, which I've done to no avail. I've used both the default renderer.material and a separate purpose-specific material to hold the textures and shaders, with it making no difference. I've attempted to process the Blit with shader to an intermediate RenderTexture before doing a straight copy of that onto the target RenderTexture (which was a proposed solution for iOS developers with a similar problem), but it didn't help.
To give an example of the context, here's one of the comparison calls:
Texture2D cam_feed_grayscale;
Texture2D cam_feed;
Texture2D last_cam_feed_grayscale;
Texture2D difference;
RenderTexture dataPasser;
float threshold;
void Update(){
renderer.material.SetTexture("_grayScale",cam_feed_grayscale);
renderer.material.SetTexture("_lastFrame",last_cam_feed_grayscale);
renderer.material.SetFloat("_threshold", threshold);
Graphics.Blit (cam_feed, dataPasser, renderer.material);
difference.ReadPixels(shaderRegion, 0, 0);
difference.Apply();}
where the appropriate variables are declared and new'd elsewhere, and its associated shader:
Shader "Custom/FrameCompare" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_grayScale ("Base (RGB)", 2D) = "white" {}
_lastFrame ("Base (RGB)", 2D) = "white" {}
_threshold ("_threshold", Float) = 0.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
ZTest Always Cull Off ZWrite Off Fog { Mode Off }
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
sampler2D _lastFrame;
sampler2D _grayScale;
float _threshold;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
half2 temp = IN.uv_MainTex;
temp.x = 1.0-temp.x;
half4 c = tex2D (_grayScale, temp);
half4 d = tex2D (_lastFrame, temp);
if(c.r < d.r - _threshold)
{
o.Albedo = half3(0,0,0);
}
else if(c.r > d.r + _threshold)
{
o.Albedo = half3(0,0,0);
}
else
{
o.Albedo = half3(1,1,1);
}
o.Alpha = 1;
}
ENDCG
}
FallBack "Diffuse"
}
As I say, everything works fine in the Editor. It's only when I deploy the code to an Android device that things seem to get a little squiffy. I suspect I'm doing something wrong with my application of Graphics.Blit(), or perhaps within the shader itself (though not to a degree that causes complaint in the Editor), but if I am I can't see what it is - any advice would be gratefully appreciated.
Answer by marsian · Jan 19, 2014 at 06:25 PM
Enabling 32 bit display depth worked for me. (Default is 16-bit whitout alpha and it's unlikeley that RT would work)
Answer by iaanus · Nov 04, 2013 at 10:43 AM
Same problem here. Did you succeed in solving the problem?
Answer by Mythal82 · Nov 04, 2013 at 11:12 AM
No, unfortunately - had to ditch the GPU computing aspect of the project. I did find, though, that it did work perfectly well on nVidia Tegra platforms - including the old Nexus 7. Might be an issue with the Adreno GPU specifically, rather than Unity, as it wouldn't work on the new Nexus 7 either.
:( Sorry to hear that. Actually I use Graphics.Blit for a post-render effect which works perfectly on PC and iOS, and I am getting a black screen on Android. I can't just hope that an Android user has a working GPU... Damn Android, I just wish I could avoid supporting it, it's just too much hassle for so little revenue. (Not mentioning that Android users don't deserve any sympathy, given that that the piracy rate is close to 100%).
Answer by radiantSil · Jun 14, 2014 at 09:24 PM
In my enviroment, Everything works fine with setting OpenGL ES version target to 3.0. Target 2.0 causes black screen on ES3.0 devices such as Nexus7(2013), Xperia Z1, etc.
I think it is problem about ES2.0 emulation on ES3.0 devices.
Answer by KBAallstar · Jul 13, 2015 at 11:57 PM
I had issues with basic materials turning black on Android. Fixed it by reducing the "smoothness" of the material to 0.5 or less. I also chose compress in ETC1 format, but I think the main issue was smoothness above 0.5. I'm using Unity 5.1.
Your answer
Follow this Question
Related Questions
fragment evaluation shader compile error 1 Answer
Unity5 Android GPU Crash 2 Answers
Radial Blur for Android/iOS 0 Answers
UI leads to game crash 1 Answer
UI CustomShader disappears when Android losing focus 0 Answers