Graphics.Blit() weird behaviour - unity3d

I have some problems understanding the proper usage of Graphics.Blit() in Unity
I have a Shader (volumeShaderSecondPass), for debug reasons it simply returns float4(1.0,1.0,1.0,1.0) right now.
If I use it in a material created in the Editor, I correctly see just a white square if it is applied to a cube:
If I create a material in code and try to use Graphics.Blit() to display it, my whole screen turns white.
void OnRenderImage(RenderTexture src, RenderTexture dst)
{
volumeCam.targetTexture = volumeFirstPassTexture;
volumeCam.backgroundColor = new Color(1.0f, 0f, 0.5f, 0.5f);
volumeCam.clearFlags = CameraClearFlags.Color;
volumeCam.cullingMask = 1 << LayerMask.NameToLayer("Volume");
volumeCam.RenderWithShader(volumeShaderFirstPass, null);
volumeMat = new Material(volumeShaderSecondPass);
volumeMat.hideFlags = HideFlags.DontSave;
volumeMat.SetTexture("_Texture3D", data);
Graphics.Blit(volumeFirstPassTexture, dst, volumeMat);
}

Related

Unity: Add a Text Using a TextMesh Via Script?

I just want to be able to see some text rendered in the world.
The only example code that I've found is this:
GameObject Text = new GameObject();
TextMesh textMesh = Text.AddComponent<TextMesh>();
textMesh.font = new Font();
mat.SetColor("_Color", Color.black);
mat.SetPass(0);
meshRenderer.material = mat;
textMesh.text = "Hello World!";
Where mat is defined by the code:
Shader shader = Shader.Find("Hidden/Internal-Colored");
mat = new Material(shader);
mat.hideFlags = HideFlags.HideAndDontSave;
mat.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
mat.SetInt("_ZWrite", 0);
mat.SetColor("_Color", Color.blue);
mat.SetPass(0);
This code is added to the Start of MonoBevaviour. And the script is tied to Game Main camera.
No text appears anywhere that I can see.
Ah I think I might have something.
I am not sure though if this works for VR devices - I know that Unity e.g. doesn't render Screenspace overlay canvas on XR.
But back to the point: There is a legacy UI system which is usually not used anymore except for in editor Inspector scripting IMGUI
I think it might actually fit your very special need using GUILayout.Label you should be able to draw a flat label onto the screen even in VR.
With GUI.Label you have full control over the pixel coordinates and size.
public class YourTextDrawer : MonoBehaviour
{
void OnGUI()
{
var color = GUI.color;
GUI.color = Color.green;
var textPosition = new Rect(Screen.width / 2 - 150, Screen.height / 2 - 100, 300, 200);
GUI.Label(textPosition, "Hello World!");
GUI.color = color;
}
}
Not tested, just scrabbling this down from memory right now
And actually thinking about it, this might even work for your image as well

How to set Texture2D to skybox Panoramic material?

I'm developing a VR App by using skybox Panoramic material. And I want to bind the material with a Texture2D created in C# script, then rendering the Texture2D in native plugin, the codes is below, but the skybox doesn't show anything, why?
private int texWidth = 2304;
private int texHeight = 2304;
private Texture2D tex;
// Start is called before the first frame update
void Start()
{
// Create a texture
Texture2D tex = new Texture2D(2304, 2304, TextureFormat.ARGB32, true);
// Set point filtering just so we can see the pixels clearly
tex.filterMode = FilterMode.Trilinear;
// Call Apply() so it‘s actually uploaded to the GPU
tex.Apply();
init(tex.GetNativeTexturePtr());
// Set texture onto our material
//RenderSettings.skybox.SetTexture("_MainTex", tex);
RenderSettings.skybox.mainTexture = tex;
}

How to remove the gizmo perspective icon on the top right corner in Unity 3d?

I want to turn off the display of the "persp icon" on the top right, you know, the one with the green, red, and blue conical arms.
Simply make a screenshot of the SceneView camera e.g. like (source)
/// <summary>
/// This adds an entry to the top main menu and a shortcut CTRL+ALT+S and stores files without transparency to Assets/{TimeStamp}.png
/// </summary>
[MenuItem("My Stuff/CaptureEditorScreenshot %&S")]
private static void CaptureEditorScreenshot()
{
var path = Path.Combine(Application.dataPath, DateTime.Now.ToString("yyyy_MM_dd-hh_mm_ss") + ".png");
CaptureEditorScreenshot(path);
}
public static void CaptureEditorScreenshot(string filePath)
{
var sw = SceneView.lastActiveSceneView;
if (!sw)
{
Debug.LogError("Unable to capture editor screenshot, no scene view found");
return;
}
var cam = sw.camera;
if (!cam)
{
Debug.LogError("Unable to capture editor screenshot, no camera attached to current scene view");
return;
}
var renderTexture = cam.targetTexture;
if (!renderTexture)
{
Debug.LogError("Unable to capture editor screenshot, camera has no render texture attached");
return;
}
var width = renderTexture.width;
var height = renderTexture.height;
var outputTexture = new Texture2D(width, height, TextureFormat.RGB24, false);
RenderTexture.active = renderTexture;
cam.Render();
outputTexture.ReadPixels(new Rect(0, 0, width, height), 0, 0);
var pngData = outputTexture.EncodeToPNG();
UnityEngine.Object.DestroyImmediate(outputTexture);
RenderTexture.active = null;
File.WriteAllBytes(filePath, pngData);
AssetDatabase.Refresh();
Debug.Log("Screenshot written to file " + filePath);
}
Afaik by default this ignores all handles, grids, gizmos and in specific also that top-right scene view handle. It just renders the content as if it would look in the GameView.
Note: Make sure to either put this in a folder called Editor or add according #if UNITY_EDITOR pre-processors around it since SceneView is in the UnityEditor namespace. You said you never build that project anyway but you know just in case and also for other readers ;)
Clicking on the 3 dots on the top right corner opens a drop down menu,inside the first option "overlays" you can check on or off the "orientation" option.
https://i.stack.imgur.com/rWwlZ.gif

How to change texture format from Alpha8 to RGBA in Unity3d?

I have been trying to change the format from a camera that give a texture in Alpha8 to RGBA and have been unsuccessful so far.
This is the code I've tried:
public static class TextureHelperClass
{
public static Texture2D ChangeFormat(this Texture2D oldTexture, TextureFormat newFormat)
{
//Create new empty Texture
Texture2D newTex = new Texture2D(2, 2, newFormat, false);
//Copy old texture pixels into new one
newTex.SetPixels(oldTexture.GetPixels());
//Apply
newTex.Apply();
return newTex;
}
}
And I'm calling the code like this:
Texture imgTexture = Aplpha8Texture.ChangeFormat(TextureFormat.RGBA32);
But the image gets corrupted and isn't visible.
Does anyone know how to change this Alpha8 to RGBA so I can process it like any other image in OpenCV?
A friend provided me with the answer:
Color[] cs =oldTexture.GetPixels();
for(int i = 0; i < cs.Length; i++){//we want to set the r g b values to a
cs[i].r = cs[i].a;
cs[i].g = cs[i].a;
cs[i].b = cs[i].a;
cs[i].a = 1.0f;
}
//set the pixels in the new texture
newTex.SetPixels(cs);
//Apply
newTex.Apply();
This will take alot of resources but it will work for sure.
If you know a better way to make this change please add an answer to this thread.

Scale a PNG in Unity5? - Bountie

Surprisingly in Unity, for years the only way to simply scale an actual PNG is to use the very awesome library http://wiki.unity3d.com/index.php/TextureScale
Example below
How do you scale a PNG using Unity5 functions? There must be a way now with new UI and so on.
So, scaling actual pixels (such as in Color[]) or literally a PNG file, perhaps downloaded from the net.
(BTW if you're new to Unity, the Resize call is unrelated. It merely changes the size of an array.)
public WebCamTexture wct;
public void UseFamousLibraryToScale()
{
// take the photo. scale down to 256
// also crop to a central-square
WebCamTexture wct;
int oldW = wct.width; // NOTE example code assumes wider than high
int oldH = wct.height;
Texture2D photo = new Texture2D(oldW, oldH,
TextureFormat.ARGB32, false);
//consider WaitForEndOfFrame() before GetPixels
photo.SetPixels( 0,0,oldW,oldH, wct.GetPixels() );
photo.Apply();
int newH = 256;
int newW = Mathf.FloorToInt(
((float)newH/(float)oldH) * oldW );
// use a famous Unity library to scale
TextureScale.Bilinear(photo, newW,newH);
// crop to central square 256.256
int startAcross = (newW - 256)/2;
Color[] pix = photo.GetPixels(startAcross,0, 256,256);
photo = new Texture2D(256,256, TextureFormat.ARGB32, false);
photo.SetPixels(pix);
photo.Apply();
demoImage.texture = photo;
// consider WriteAllBytes(
// Application.persistentDataPath+"p.png",
// photo.EncodeToPNG()); etc
}
Just BTW it occurs to me I'm probably only talking about scaling down here (as you often have to do to post an image, create something on the fly or whatever.) I guess, there would not often be a need to scale up in size an image; it's pointless quality-wise.
If you're okay with stretch-scaling, actually there's simpler way by using a temporary RenderTexture and Graphics.Blit. If you need it to be Texture2D, swapping RenderTexture.active temporarily and read its pixels to Texture2D should do the trick. For example:
public Texture2D ScaleTexture(Texture src, int width, int height){
RenderTexture rt = RenderTexture.GetTemporary(width, height);
Graphics.Blit(src, rt);
RenderTexture currentActiveRT = RenderTexture.active;
RenderTexture.active = rt;
Texture2D tex = new Texture2D(rt.width,rt.height);
tex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
tex.Apply();
RenderTexture.ReleaseTemporary(rt);
RenderTexture.active = currentActiveRT;
return tex;
}