- Home /
Texture2D is blurred when procedurally generated
I'm creating an automatically generated texture for my game. It's used for a tilemap. Thing is, every time I regenerate it, the texture itself get's blurred. I have point filtering enabled, so I'm not sure what's happening.
As you can see in the first picture, the castle up top is what the stone tiles are supposed to look like. Instead the texture gets blurred. It's supposed to be pixel perfect like the castle.
The import settings for the texture atlas which contains the original tiles is point filtering, mipmaps disables, RGBA 32 bit compression, 1024 max size, it's read/writeable, and 16 pixels per unit. The camera already has a script attached to adjust the orthographic size. I've been searching all over the place for a solution, and haven't found one.
Here's the code.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class TiledMapGeneration : MonoBehaviour {
public int size_x = 100;
public int size_y = 50;
public float tileSize = 1.0f;
public int sparcityOfStones;
public Texture2D terrainTiles;
public int tileResolution = 16;
private int numTilesPerRow;
private int numRows;
public bool isNotMainLayer;
private TiledMap tm;
public bool isStone;
Color[][] ChopUpTiles () {
Color[][] tiles = new Color[numTilesPerRow * numRows][];
for (int y = 0; y < numRows; y++) {
for (int x = 0; x < numTilesPerRow; x++) {
tiles[y * numTilesPerRow + x] = terrainTiles.GetPixels (x * tileResolution, y * tileResolution, tileResolution, tileResolution);
}
}
return tiles;
}
void Awake () {
BuildMesh ();
}
void BuildTexture () {
numTilesPerRow = terrainTiles.width / tileResolution;
numRows = terrainTiles.height / tileResolution;
int texWidth = size_x * tileResolution;
int textHeight = size_y * tileResolution;
Texture2D texture = new Texture2D (texWidth, textHeight);
Color[][] tiles = ChopUpTiles ();
if (isNotMainLayer) {
for (int y = 0; y < size_y; y++) {
for (int x = 0; x < size_x; x++) {
Color[] p = tiles[tm.getTileTexCoordinatesAt (x, y).y * numTilesPerRow + tm.getTileTexCoordinatesAt (x, y).x];
texture.SetPixels (x * tileResolution, y * tileResolution, tileResolution, tileResolution, p);
}
}
} else {
for (int y = 0; y < size_y; y++) {
for (int x = 0; x < size_x; x++) {
Color[] p = tiles[GameManager.tiledmap.getTileTexCoordinatesAt (x, y).y * numTilesPerRow + GameManager.tiledmap.getTileTexCoordinatesAt (x, y).x];
texture.SetPixels (x * tileResolution, y * tileResolution, tileResolution, tileResolution, p);
}
}
}
texture.filterMode = FilterMode.Point;
texture.wrapMode = TextureWrapMode.Clamp;
texture.Apply (false);
MeshRenderer mesh_renderer = GetComponent <MeshRenderer> ();
mesh_renderer.sharedMaterials[0].mainTexture = texture;
}
void BuildCollider () {
try {
GameObject childColl = transform.GetChild (0).gameObject;
DestroyImmediate (childColl);
} catch {}
GameObject collision = new GameObject ("Stone");
if(isStone) {
for (int x = 0; x < GameManager.tiledmap.width; x++) {
for (int y = 0; y < GameManager.tiledmap.width; y++) {
if(GameManager.tiledmap.tiles[x,y].type == Tile.castle) {
BoxCollider2D collider = (BoxCollider2D)collision.AddComponent <BoxCollider2D> ();
collider.offset = new Vector2 (x * tileSize + tileSize / 2f, y * tileSize + tileSize / 2f);
collider.size = new Vector2 (tileSize, tileSize);
}
}
}
}
collision.transform.parent = gameObject.transform;
collision.tag = "Stone";
collision.layer = 8;
}
public void BuildMesh () {
if (isNotMainLayer) {
tm = new TiledMap (size_x, size_y, isStone, tileSize, sparcityOfStones);
} else {
GameManager.tiledmap = new TiledMap (size_x, size_y, isStone, tileSize, sparcityOfStones);
}
if (isStone && !isNotMainLayer) {
BuildCollider ();
}
int numTiles = size_x * size_y;
int numTris = numTiles * 2;
//int vsize_x = size_x * 2;
//int vsize_y = size_y * 2;
int numVerts = numTiles * 4;
Vector3[] vertices = new Vector3[numVerts];
Vector3[] normals = new Vector3[numVerts];
Vector2[] uv = new Vector2[numVerts];
int[] triangles = new int[numTris * 3];
int x, y;
TileVerts[] verts= new TileVerts[numTiles];
for (y = 0; y < size_y; y++) {
for(x = 0; x < size_x; x++) {
verts[y * size_x + x] = new TileVerts (new Vector3 (x * tileSize, y * tileSize), tileSize, size_x, size_y);
}
}
int a = 0;
for (int i = 0; i < verts.Length; i++) {
for (int j = 0; j < 4; j++) {
vertices[a] = verts[i].verts[j];
normals[a] = Vector3.back;
uv[a] = verts[i].uv[j];
a++;
}
}
for (y = 0; y < size_y; y++) {
for (x = 0; x < size_x; x++) {
int squareIndex = y * size_x + x;
int triOffset = squareIndex * 6;
triangles[triOffset] = (squareIndex) * 4 + 0;
triangles[triOffset + 1] = (squareIndex) * 4 + 3;
triangles[triOffset + 2] = (squareIndex) * 4 + 2;
triangles[triOffset + 3] = (squareIndex) * 4 + 0;
triangles[triOffset + 4] = (squareIndex) * 4 + 1;
triangles[triOffset + 5] = (squareIndex) * 4 + 3;
}
}
Mesh mesh = new Mesh ();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uv;
mesh.name = isStone.ToString ();
MeshFilter mesh_filter = GetComponent <MeshFilter> ();
mesh_filter.mesh = mesh;
BuildTexture ();
}
}
Here's the method getTileTexCoordinatesAt ()
public Vector2 getTileTexCoordinatesAt (int x, int y) {
return tiles[x,y].graphicsCoordinate;
}
Here's Tile.
using UnityEngine;
using System.Collections;
public class Tile {
public const string grass = "Grass";
public const string castle = "Castle";
public const string castlebackground = "Castlebackground";
public const string fence1 = "Fence1";
public const string fence2 = "Fence2";
public const string blank = "Blank";
public string type;
public Vector2 graphicsCoordinate;
public bool isWalkable;
public Tile (string type) {
this.type = type;
if(type == "Grass") {
graphicsCoordinate = new Vector2 (0, 0);
isWalkable = true;
}
if(type == "Castle") {
graphicsCoordinate = new Vector2 (1, 0);
isWalkable = false;
}
if(type == "Castlebackground") {
graphicsCoordinate = new Vector2 (2, 0);
isWalkable = true;
}
if(type == "Fence1") {
graphicsCoordinate = new Vector2 (0, 1);
isWalkable = false;
}
if(type == "Fence2") {
graphicsCoordinate = new Vector2 (1, 1);
isWalkable = false;
}
if(type == "Blank") {
graphicsCoordinate = new Vector2 (4, 1);
isWalkable = false;
}
}
}
I really hope the solution to this is stupidly simple, because I've been searching all over the place for what's causing it (it wasn't happening before).
EDIT: I also wanted to mention this happened after I connected an android device for testing, but it doesn't make sense that doing that would mess up the textures on the computer.
Is Texture Quality set to Full Res? (Edit > ProjectSettings > Quality)
Answer by Ultrachessmaster · Jul 30, 2015 at 09:18 PM
Not sure what caused this to happen, but I found a solution when changing the code to be more efficient. Here it is for anybody in the future that encounters this weird glitch.
public void BuildMesh () {
if (isNotMainLayer) {
tm = new TiledMap (size_x, size_y, isStone, tileSize, sparcityOfStones);
} else {
tm = new TiledMap (size_x, size_y, isStone, tileSize, sparcityOfStones);
GameManager.tiledmap = tm;
}
if (isStone && !isNotMainLayer) {
BuildCollider ();
}
int tileCount = tm.width * tm.height;
TileVerts[] verts = new TileVerts[tileCount];
Vector3[] vertices = new Vector3[tileCount * 4];
Vector3[] normals = new Vector3[tileCount * 4];
Vector2[] uv = new Vector2[tileCount * 4];
int[] triangles = new int[tileCount * 4 * 6];
int x, y;
for (x = 0; x < tm.width; x++) {
for(y = 0; y < tm.height; y++) {
verts[x * tm.height + y] = new TileVerts (new Vector3 (x * tileSize, y * tileSize), tileSize,
tileResolution, terrainTiles.width, (int)tm[x, y].texCoor.x * tileResolution, (int)tm[x, y].texCoor.y * tileResolution);
}
}
int a = 0;
for (int i = 0; i < verts.Length; i++) {
for (int j = 0; j < 4; j++) {
vertices[a] = verts[i].verts[j];
normals[a] = Vector3.back;
uv[a] = verts[i].uv[j];
a++;
}
}
for (x = 0; x < tm.width; x++) {
for (y = 0; y < tm.height; y++) {
int squareIndex = x * tm.height + y;
int triOffset = squareIndex * 6;
triangles[triOffset] = (squareIndex) * 4 + 2;
triangles[triOffset + 1] = (squareIndex) * 4 + 3;
triangles[triOffset + 2] = (squareIndex) * 4 + 0;
triangles[triOffset + 3] = (squareIndex) * 4 + 3;
triangles[triOffset + 4] = (squareIndex) * 4 + 1;
triangles[triOffset + 5] = (squareIndex) * 4 + 0;
}
}
Mesh mesh = new Mesh ();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uv;
MeshFilter mesh_filter = GetComponent <MeshFilter> ();
MeshRenderer mesh_renderer = GetComponent <MeshRenderer> ();
mesh_filter.mesh = mesh;
mesh_renderer.sharedMaterial.mainTexture = terrainTiles;
}
Not sure why this fixes the problem, but it does.
Your answer
Follow this Question
Related Questions
Blurred sprite borders - Quick question 0 Answers
All of my textures now appear blurry (2D) 0 Answers
MipMapBias alternative for Android? 1 Answer
Odd image effects around edges of the camera 1 Answer
Update a texture at runtime using UV 0 Answers