- Home /
X-raying plane to see underneath
I basically have two planes, which are just a maps of top sight 2d game I make. So the one above is visible all the time, but sometimes I like to xray through it to show whats on the one under it. Top one has material with Alpha blend particles shader so I can actually make alpha holes in it and restore it when I want it to. But is there something that works same way but more smooth and can be easier adjustable if I'd like to assign it to, lets say, rotating game object?
public Camera camera;
public GameObject frontPlane;
public GameObject backPlane;
private Color[] _colorlBackup;
private Color _color;
private Texture2D tex;
// Use this for initialization
void Start () {
_timer = 0;
_color = new Color(0.0f, 0.0f, 0.0f, 0.0f);
}
private void GetPixels(){
RaycastHit hit;
Ray ray = camera.ScreenPointToRay (Input.mousePosition);
if(Physics.Raycast(ray, out hit)){
//Get texture of hitted collider
tex = (Texture2D)hit.transform.gameObject.renderer.sharedMaterial.mainTexture;
//Backup texture color array if its empty
if(_colorlBackup == null){
Debug.Log ("Tak");
_colorlBackup = tex.GetPixels();
}
else if(_colorlBackup != null) {
Debug.Log ("Drawing...");
//Get UV's at the hit.point
Vector2 uv;
uv.x = (int)(((hit.point.x - hit.collider.bounds.min.x) / hit.collider.bounds.size.x) * tex.width);
uv.y = (int)(((hit.point.z - hit.collider.bounds.min.z) / hit.collider.bounds.size.z) * tex.height);
StartCoroutine("SetPixelsToChange", uv);
}
}
}
private IEnumerator SetPixelsToChange(Vector2 uv){
Vector2[] pixelsToChange = new Vector2[15000];
int cnt = 0;
for( int y = 0; y < 100; y++ ){
for( int x = 0; x < y; x++){
pixelsToChange[cnt] = new Vector2(uv.x + x, uv.y + y);
pixelsToChange[cnt+1] = new Vector2(uv.x - x, uv.y + y);
cnt += 2;
}
}
if(cnt >= 1000){
for( int i = 0; i < pixelsToChange.Length; i++)
tex.SetPixel ((int)(-pixelsToChange[i].x), (int)(-pixelsToChange[i].y), _color);
cnt--;
}
tex.Apply();
yield return new WaitForSeconds(.05f);
tex.SetPixels(_colorlBackup);
tex.Apply();
StopCoroutine("SetPixelsToChange");
}
// Update is called once per frame
void Update () {
GetPixels();
}
Answer by CHPedersen · Aug 02, 2013 at 09:47 AM
The issue here is that you're doing all the work CPU side. Looping over pixels on the CPU is expensive, especially for larger textures, and the calls to tex.Apply are really expensive, because they have to transfer the texture back to the GPU (so you incur the cost of passing data through the PCI bus).
The only way to do this efficiently is to move all the calculations to the GPU instead to avoid the heavy pixel-looping and the transfer of modified textures. Either use a custom shader for it, or set up a system of existing shaders that yield the same result.
The custom shader option would require you to write Cg code. Do you have ShaderLab/Cg experience? If so, it will be relatively easy. You can calculate on the CPU side how big the X-ray circle is going to be on the plane, then use Material.SetFloat and Material.SetVector to pass the circle's mathematical parameters (radious and center) to the shader. In the shader's fragment program, you would then test each pixel's world position against the circle to see if it's inside or outside the circle. If inside, set its alpha to 0. If outside, render normally.
This would yield precisely the same result without having to do any work on the CPU except for evaluating the circle parameters. It's also possible there is a simpler cut-out based solution involving a white texture with an alpha-0 hole in its center, and a projector setup that projects the hole onto the plane where you want it to be transparent. That might be easier to set up.
As far as I don't have shader experience (just started to learn) the last solution with the projector seem the best option for me. I'll look into it. Thanks alot :]
You're welcome. :) In your investigatons, search for topics that have to do with "X-ray", "projector" and "alpha-cutout". I got these links, which seem like they might be of interest to you:
http://unitycoder.com/blog/2012/02/22/x-ray-cutout-shader-with-mouse/
http://forum.unity3d.com/threads/187659-X-ray-shader-problems-need-help