I have to display bitmaps on a tv screen object…but need to be sure that the aspect ratio is preserved
Image to place:
How it display on a square mesh:
So I wrote some code to adjust UV tiling and offset for each image that will be projected on screen:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class MainCameraScript : MonoBehaviour
{
public GameObject screen;
public Material bmp;
// Use this for initialization
void Start()
{
SetTexture("C:\\testimage.png");
}
void SetTexture(string path)
{
// Create new texture2d
Texture2D tex = LoadPNG(path);
if (tex == null)
{
return;
}
// Set width/height scale/offset for UV's
float twidth = 1.0f;
float theight = 1.0f;
float owidth = 0.0f;
float oheight = 0.0f;
if (tex.width >= tex.height)
{
theight = (float)tex.width / tex.height; // Tiling
oheight = oheight = (theight -1) / -2; // Offset
}
else
{
twidth = (float)tex.height / tex.width;
owidth = (twidth -1) / -2;
}
// Set texture to material albedo
bmp.mainTexture = tex;
// Scale object UVs to fit texture
bmp.mainTextureScale = new Vector2(twidth, theight);
bmp.mainTextureOffset = new Vector2(owidth, oheight);
}
public static Texture2D LoadPNG(string filePath)
{
Texture2D tex = null;
byte[] fileData;
if (File.Exists(filePath))
{
fileData = File.ReadAllBytes(filePath);
tex = new Texture2D(2, 2, TextureFormat.ARGB32, false);
tex.filterMode = FilterMode.Point;
tex.wrapMode = TextureWrapMode.Clamp;
tex.LoadImage(fileData);
}
return tex;
}
}
It’s now OK for aspect ratio and centering…but as you can see I would now need to set the pixels to black when outside of UV coordinates!
Could you please tell me how to proceed (I’m really noob at shading)?
I saw on this page (http://metalbyexample.com/textures-and-samplers/) that this would be known as “Clamp-to-zero addressing”?
Thanks for your help!
PS: would all this be possible entirely through shader (tiling/offsetting/clamping)?
Something like that should work. Honestly I haven’t tried it (and wrote the whole thing out of memory inside this text editor), so there may be some issues/things I could add if you want. This shader will add a one pixel wide black border to your images, however.
Thank you so much for the reply and for taking time to write the code down!
Unfortunately, it doesn’t work as expected: the bitmap is stretched all the way out, manually settings tiling and offset seems ‘broken’
(btw, I don’t know if this code is to replace the tile/offset in code, so doing everything in the shader…or if I still need the code)
You are using old variables which generally don’t work anymore. In your script, instead of;
bmp.mainTexture = tex;
// Scale object UVs to fit texture
bmp.mainTextureScale = new Vector2(twidth, theight);
bmp.mainTextureOffset = new Vector2(owidth, oheight);
Try;
bmp.SetTexture ("_MainTex", tex);
// Scale object UVs to fit texture
bmp.SetTextureScale ("_MainTex", new Vector2 (twidth, theight));
bmp.SetTextureOffset ("_MainTex", new Vector2 (owidth, oheight));
Again, error on my part. I wasn’t using the transformed UVs for the border check, so it was essentially doing nothing. I’ve checked this in unity and it works for me;
To answer your question you change “half4 (0,0,0,1)” the last number is the opacity (or calling discard), but at this point you would be better off resizing the quad in the vertex shader and never running the fragment shader for those pixels
Ik the post is pretty old, but is there any way to get the same functionality of the code in Shader Graph for the URP? I couldnt find anything on google. Would realy appreciate any help!