Files
PrinceOfGlory/Assets/Third Party/SimpleLOD/Extensions/Texture2DExtensions.cs
kridoo 6e91a0c7f0 111
2025-09-15 17:32:08 +08:00

225 lines
8.8 KiB
C#

/* SimpleLOD 1.5a */
/* By Orbcreation BV */
/* Richard Knol */
/* March 18, 2015 */
/* Note: if you also use other packages by Orbcreation, */
/* you may end up with multiple copies of this file. */
/* In that case, better delete/merge those files into 1. */
using UnityEngine;
using System;
using System.Collections;
namespace OrbCreationExtensions
{
public static class Texture2DExtensions
{
public static Texture2D GetCopy(this Texture2D tex) {
return GetCopy(tex, 0, 0, tex.width, tex.height, (tex.mipmapCount > 1));
}
public static Texture2D GetCopy(this Texture2D tex, int x, int y, int w, int h) {
return GetCopy(tex, x, y, w, h, (tex.mipmapCount > 1));
}
public static Texture2D GetSection(this Texture2D tex, int x, int y, int w, int h) {
return GetCopy(tex, x, y, w, h, (tex.mipmapCount > 1));
}
public static Texture2D GetCopy(this Texture2D tex, int x, int y, int w, int h, bool mipMaps) {
Texture2D newTex = new Texture2D(w, h, GetWritableFormat(tex.format), mipMaps);
newTex.SetPixels(tex.GetPixels(x, y, w, h, 0), 0);
newTex.Apply(mipMaps, false);
return newTex;
}
public static Texture2D ScaledCopy(this Texture2D tex, int width, int height, bool mipMaps) {
if(width<=0 || height<=0) return null;
if(width==tex.width && height==tex.height) return GetCopy(tex, 0, 0, tex.width, tex.height, mipMaps);
Color[] newPixels = ScaledPixels(tex.GetPixels(0), tex.width, tex.height, width, height);
Texture2D newTex = new Texture2D(width, height, GetWritableFormat(tex.format), mipMaps);
newTex.SetPixels(newPixels,0);
newTex.Apply(mipMaps, false);
return newTex;
}
public static void CopyFrom(this Texture2D tex, Texture2D fromTex, int toX, int toY, int fromX, int fromY, int width, int height) {
MakeFormatWritable(tex);
int fullWidth = tex.width;
Color[] pixels = tex.GetPixels(0);
Color[] fromPixels = fromTex.GetPixels(fromX, fromY, width, height, 0);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
pixels[((y + toY) * fullWidth) + x + toX] = fromPixels[(y * width) + x];
}
}
tex.SetPixels(pixels,0);
tex.Apply((tex.mipmapCount > 1), false);
}
public static void Scale(this Texture2D tex, int width, int height) {
if(width<=0 || height<=0 || (width==tex.width && height==tex.height)) return;
MakeFormatWritable(tex);
Color[] newPixels = ScaledPixels(tex.GetPixels(0), tex.width, tex.height, width, height);
if(tex.Reinitialize(width, height, tex.format, tex.mipmapCount>1)) {
tex.SetPixels(newPixels,0);
tex.Apply((tex.mipmapCount > 1), false);
}
}
public static void MakeFormatWritable(this Texture2D tex) {
TextureFormat oldFormat = tex.format;
TextureFormat newFormat = GetWritableFormat(tex.format);
if(newFormat != oldFormat) {
Color[] pixels = tex.GetPixels(0);
tex.Reinitialize(tex.width, tex.height, newFormat, tex.mipmapCount>1);
tex.SetPixels(pixels,0);
tex.Apply((tex.mipmapCount > 1), false);
}
}
public static TextureFormat GetWritableFormat(TextureFormat format) {
if(format != TextureFormat.Alpha8 && format != TextureFormat.RGB24 && format != TextureFormat.ARGB32 && format != TextureFormat.RGBA32) {
if(format == TextureFormat.RGB24 || format == TextureFormat.DXT1 || format == TextureFormat.PVRTC_RGB2 || format == TextureFormat.PVRTC_RGB4 || format == TextureFormat.ETC_RGB4 || format == TextureFormat.ETC_RGB4 || format == TextureFormat.ETC2_RGBA8 || format == TextureFormat.ETC2_RGB || format == TextureFormat.ASTC_4x4 || format == TextureFormat.ASTC_5x5 || format == TextureFormat.ASTC_5x5 || format == TextureFormat.ASTC_5x5 || format == TextureFormat.ASTC_6x6 || format == TextureFormat.ASTC_10x10 || format == TextureFormat.ASTC_12x12) format = TextureFormat.RGB24;
else format = TextureFormat.RGBA32;
}
return format;
}
public static Color GetAverageColor(this Texture2D tex) {
Vector4 c = Vector4.zero;
float tot = 0f;
Color[] pxls = tex.GetPixels(0);
for(int i=0;i<pxls.Length;i++) {
c += ((Vector4)pxls[i]) * pxls[i].a;
tot += pxls[i].a;
}
if(tot < 1f) tot = 1f;
c.w = tot;
return (Color)(c / tot);
}
public static Color GetAverageColor(this Texture2D tex, Color useThisColorForAlpha) {
Vector4 c = Vector4.zero;
float tot = 0f;
Color[] pxls = tex.GetPixels(0);
for(int i=0;i<pxls.Length;i++) {
c += ((Vector4)pxls[i]) * pxls[i].a;
c += ((Vector4)useThisColorForAlpha) * (1f - pxls[i].a);
tot += 1f;
}
if(tot < 1f) tot = 1f;
c.w = tot;
return (Color)(c / tot);
}
public static bool IsReadable(this Texture2D tex) {
try {
tex.GetPixels(0, 0, 1, 1, 0);
} catch(Exception e) {
return e == null;
}
return true;
}
public static bool HasTransparency(this Texture2D tex) {
Color[] pixels;
try {
pixels = tex.GetPixels(0);
} catch(Exception e) {
Debug.LogError(e);
return false;
}
for (int i=0; i<pixels.Length; i++) {
if(pixels[i].a < 1f) return true;
}
return false;
}
private static Color[] ScaledPixels(Color[] originalPixels, int oldWidth, int oldHeight, int width, int height) {
if(width<=0 || height<=0 || (width==oldWidth && height==oldHeight)) return originalPixels;
float scaleX = (float)width / (float)oldWidth;
float scaleY = (float)height / (float)oldHeight;
Color[] newPixels = new Color[width * height];
for (int y = 0; y < height; y++) {
float originalY = y / scaleY;
int originalYLow = Mathf.FloorToInt(originalY);
int originalYHigh = Mathf.CeilToInt(originalY);
for (int x = 0; x < width; x++) {
float originalX = x / scaleX;
int originalXLow = Mathf.FloorToInt(originalX);
int originalXHigh = Mathf.CeilToInt(originalX);
Color pixel = originalPixels[(originalYLow * oldWidth) + originalXLow] *
(1.0f - (originalY - originalYLow)) *
(1.0f - (originalX - originalXLow));
if(originalXLow < originalXHigh && originalXHigh<oldWidth) {
pixel = pixel + originalPixels[(originalYLow * oldWidth) + originalXHigh] *
(1.0f - (originalY - originalYLow)) *
(1.0f - (originalXHigh - originalX));
}
if(originalYLow < originalYHigh && originalYHigh<oldHeight) {
pixel = pixel + originalPixels[(originalYHigh * oldWidth) + originalXLow] *
(1.0f - (originalYHigh - originalY)) *
(1.0f - (originalX - originalXLow));
if(originalXLow < originalXHigh && originalXHigh<oldWidth) {
pixel = pixel + originalPixels[(originalYHigh * oldWidth) + originalXHigh] *
(1.0f - (originalYHigh - originalY)) *
(1.0f - (originalXHigh - originalX));
}
}
newPixels[(y * width) + x] = pixel;
}
}
return newPixels;
}
public static Texture2D GetUnityNormalMap(this Texture2D tex) {
Texture2D normalTexture = new Texture2D(tex.width, tex.height, TextureFormat.ARGB32, tex.mipmapCount > 1);
Color[] pixels = tex.GetPixels(0);
Color[] nPixels = new Color[pixels.Length];
for (int y=0; y<tex.height; y++) {
for (int x=0; x<tex.width; x++) {
Color p = pixels[(y * tex.width) + x];
Color np = new Color(0,0,0,0);
np.r = p.g;
np.g = p.g; // waste of memory space if you ask me
np.b = p.g;
np.a = p.r;
nPixels[(y * tex.width) + x] = np;
}
}
normalTexture.SetPixels(nPixels, 0);
normalTexture.Apply(tex.mipmapCount > 1, false);
return normalTexture;
}
public static Texture2D FromUnityNormalMap(this Texture2D tex) {
Texture2D normalTexture = new Texture2D(tex.width, tex.height, TextureFormat.RGB24, tex.mipmapCount > 1);
Color[] pixels = tex.GetPixels(0);
Color[] nPixels = new Color[pixels.Length];
for (int y=0; y<tex.height; y++) {
for (int x=0; x<tex.width; x++) {
Color p = pixels[(y * tex.width) + x];
Color np = new Color(0,0,0,0);
np.g = p.r;
np.r = p.a;
np.b = 1f;
nPixels[(y * tex.width) + x] = np;
}
}
normalTexture.SetPixels(nPixels, 0);
normalTexture.Apply(tex.mipmapCount > 1, false);
return normalTexture;
}
public static void Fill(this Texture2D tex, Color aColor) {
MakeFormatWritable(tex);
Color[] pixels = tex.GetPixels(0);
for (int i=0; i<pixels.Length; i++) {
pixels[i] = aColor;
}
tex.SetPixels(pixels, 0);
tex.Apply(tex.mipmapCount > 1, false);
}
}
}