Losing quality of textures

So I am trying to get this mechanic to work but keep running into problems. I am trying to read the pixels on the screen and apply them to the background. I have this working but the more times I apply it to the background I begin noticing blurring and it seems to be moving. I have pictures showing this because its hard to describe.

I have been adjusting filtering options, mipmapbias, wrapmode, aniso stuff and everything I could find but nothing seems to make a difference. Is there something I am missing?

function ScreenshotApply()
{
	// wait for graphics to render
	yield WaitForEndOfFrame();

	var tmp = Camera.mainCamera.pixelWidth;
	var tmp3 = Camera.mainCamera.pixelHeight;

	texture = new Texture2D(tmp, tmp3, TextureFormat.ARGB32, false);
	texture.ReadPixels(new Rect(0, 0, tmp, tmp3), 0, 0);
	texture.anisoLevel = 9;
	texture.filterMode = FilterMode.Trilinear;
	texture.wrapMode = TextureWrapMode.Clamp;
	texture.mipMapBias = -5.0;
	gameObject.renderer.material.mainTexture = texture;
	texture.Apply();
}

So after some toying around, I think it has something to do with my UV coordinates or my mesh that I created. Can anyone spot something that is wrong?

I’ve had the same problem when I use rendertextures. I think it’s because of the difference between pixels and texels. Take a look a this, it might help: Directly Mapping Texels to Pixels (Direct3D 9) - Win32 apps | Microsoft Learn If I remember correctly (haven’t touched that code in a bit) you could work around it by offsetting the mesh location by whatever equates to .5 pixels (or something similar). Play around with it a bit and you should be able to get it working.

Ah thank you, I’ll need to try that out tomorrow when I get a chance.

Ugh this is beginning to suck… so I looked into this whole texel thing more and more. I first thought OK this shouldn’t be too hard to adjust something by half a pixel, it’ll just take a bit of math. So I wrote this up and in my head it should be working but it doesn’t so I had to “rig” some things in order to get it to be somewhat how I envisioned this to be. The pixels still blur out eventually but its not as bad as it used to be.

I started looking into this thing GL.LoadPixelMatrix, but this baffles me on how to put this into my code.

Here is the script I am working with, my ultimate goal is whenever the player dies take a screenshot of the scene and apply it to the background. Would it be better to scrap all this and use GUITextures? It seems GUITextures are aligned by pixels not texels. Hopefully its just a mistake between a minus or addition…

import System.IO;

private var count : int = 0;
private var texture : Texture2D;
private var test : GameObject;
private var mesh : Mesh;
private var aa : Vector3;
private var ab : Vector3;
private var ac : Vector3;
private var ad : Vector3;

function Awake()
{
    gameObject.AddComponent("MeshFilter");
    gameObject.AddComponent("MeshRenderer");
    gameObject.transform.position = Camera.mainCamera.transform.position;
    gameObject.transform.position.z = 1.25;

    mesh = GetComponent(MeshFilter).mesh;
    mesh.Clear();

    //Figure out some math with screen coordinates
    //////////////////////////////////////////////
    var pixW = Camera.mainCamera.pixelWidth;
    var pixH = Camera.mainCamera.pixelHeight;

    var worldWidth = Camera.mainCamera.ScreenToWorldPoint(Vector3(Camera.mainCamera.pixelWidth-1,               Camera.mainCamera.pixelHeight-1, 0) - Camera.mainCamera.ScreenToWorldPoint(Vector3(0,0,0)));

    var tempW = worldWidth.x/pixW;
    var tempH = worldWidth.y/pixH;

    //This should be 0.5 but that was breaking it
    tempW *= 1.0; 
    tempH *= 1.0;

        

    //Need to adjust these values so that the point are aligned with the texel
    //This is still a little funny, not sure if Unity will allow for pixel perfect
    //texture application

    aa = Camera.mainCamera.ScreenToWorldPoint(Vector3(0,0,0));
    aa.x -= tempW;
    aa.y -= tempH;

    ab = Camera.mainCamera.ScreenToWorldPoint(Vector3(Camera.mainCamera.pixelWidth,0,0));
    ab.x += tempW;
    ab.y -= tempH;

    ac = Camera.mainCamera.ScreenToWorldPoint(Vector3(0,Camera.mainCamera.pixelHeight,0));
    ac.x -= tempW;
    ac.y += tempH;

    ad = Camera.mainCamera.ScreenToWorldPoint(Vector3(Camera.mainCamera.pixelWidth,Camera.mainCamera.pixelHeight,0));
    ad.x += tempW;
    ad.y += tempH;

    mesh.vertices = [ab, aa, ac, ad];
    mesh.uv = [Vector2 (1, 0), Vector2 (0, 0), Vector2 (0, 1), Vector2 (1, 1)];
    mesh.triangles = [0, 1, 2,
    		  0, 2, 3];

    mesh.RecalculateNormals();
    mesh.RecalculateBounds();	
    mesh.Optimize();

    //Not sure why but moving it like this also helped
    gameObject.transform.position.x -= tempW;
    gameObject.transform.position.y += tempH;	
		 
    gameObject.renderer.material.mainTexture = Resources.Load("CanvasTexture");
}

function Update()
{
	if (Input.GetKeyDown("k"))
	{
		StartCoroutine(ScreenshotEncode());
	}
}

function ScreenshotEncode()
{
	// wait for graphics to render
	yield WaitForEndOfFrame();

	var tmp = Camera.mainCamera.pixelWidth;
	var tmp3 = Camera.mainCamera.pixelHeight;

	texture = Texture2D(tmp, tmp3, TextureFormat.ARGB32, false);

	// put buffer into texture
	texture.ReadPixels(Rect(0, 0, tmp-1, tmp3-1), 0, 0);

	texture.anisoLevel = 9;
	texture.filterMode = FilterMode.Point;
	texture.wrapMode = TextureWrapMode.Clamp;

	gameObject.renderer.material.mainTexture = texture;

	texture.Apply();
}