浏览代码

Moved common classes into UnityEngine.Experimental.Rendering namespace.

/fptl_cleanup
Torbjorn Laedre 8 年前
当前提交
90252d1d
共有 5 个文件被更改,包括 784 次插入770 次删除
  1. 157
      Assets/ScriptableRenderPipeline/common/Camera/CameraSwitcher.cs
  2. 102
      Assets/ScriptableRenderPipeline/common/Camera/FreeCamera.cs
  3. 191
      Assets/ScriptableRenderPipeline/common/Debugging.cs
  4. 415
      Assets/ScriptableRenderPipeline/common/SkyboxHelper.cs
  5. 689
      Assets/ScriptableRenderPipeline/common/TextureCache.cs

157
Assets/ScriptableRenderPipeline/common/Camera/CameraSwitcher.cs


using System.Collections.Generic;
using UnityEngine;
public class CameraSwitcher : MonoBehaviour
namespace UnityEngine.Experimental.Rendering
public Camera[] m_Cameras;
public class CameraSwitcher : MonoBehaviour
{
public Camera[] m_Cameras;
private int m_CurrentCameraIndex = -1;
private Camera m_OriginalCamera = null;
private Vector3 m_OriginalCameraPosition;
private Quaternion m_OriginalCameraRotation;
private Camera m_CurrentCamera = null;
private int m_CurrentCameraIndex = -1;
private Camera m_OriginalCamera = null;
private Vector3 m_OriginalCameraPosition;
private Quaternion m_OriginalCameraRotation;
private Camera m_CurrentCamera = null;
private float m_MessageDuration = 1.0f;
private float m_MessageTimer = 1000.0f;
private float m_MessageDuration = 1.0f;
private float m_MessageTimer = 1000.0f;
private static string kDebugNext = "Debug Next";
private static string kDebugPrevious = "Debug Previous";
private string[] m_RequiredInputButtons = { kDebugNext, kDebugPrevious };
private bool m_Valid = true;
private static string kDebugNext = "Debug Next";
private static string kDebugPrevious = "Debug Previous";
private string[] m_RequiredInputButtons = { kDebugNext, kDebugPrevious };
private bool m_Valid = true;
void OnEnable()
{
m_OriginalCamera = GetComponent<Camera>();
m_CurrentCamera = m_OriginalCamera;
void OnEnable()
{
m_OriginalCamera = GetComponent<Camera>();
m_CurrentCamera = m_OriginalCamera;
m_Valid = Debugging.CheckRequiredInputButtonMapping(m_RequiredInputButtons);
}
m_Valid = Debugging.CheckRequiredInputButtonMapping(m_RequiredInputButtons);
}
int GetCameraCount()
{
return m_Cameras.Length + 1; // We need +1 for handling the original camera.
}
int GetCameraCount()
{
return m_Cameras.Length + 1; // We need +1 for handling the original camera.
}
void NextCamera()
{
m_CurrentCameraIndex = (m_CurrentCameraIndex + 1) % GetCameraCount();
}
void NextCamera()
{
m_CurrentCameraIndex = (m_CurrentCameraIndex + 1) % GetCameraCount();
}
void PreviousCamera()
{
m_CurrentCameraIndex = m_CurrentCameraIndex - 1;
if (m_CurrentCameraIndex == -1)
m_CurrentCameraIndex = m_Cameras.Length;
}
void PreviousCamera()
{
m_CurrentCameraIndex = m_CurrentCameraIndex - 1;
if (m_CurrentCameraIndex == -1)
m_CurrentCameraIndex = m_Cameras.Length;
}
Camera GetNextCamera()
{
if (m_CurrentCameraIndex == m_Cameras.Length)
return m_OriginalCamera;
else
return m_Cameras[m_CurrentCameraIndex];
}
Camera GetNextCamera()
{
if (m_CurrentCameraIndex == m_Cameras.Length)
return m_OriginalCamera;
else
return m_Cameras[m_CurrentCameraIndex];
}
void Update()
{
if (m_Valid && Debugging.debugControlEnabled && m_OriginalCamera != null)
void Update()
m_MessageTimer += Time.deltaTime;
bool needUpdateCamera = false;
if (Input.GetButtonDown(kDebugNext))
if (m_Valid && Debugging.debugControlEnabled && m_OriginalCamera != null)
NextCamera();
needUpdateCamera = true;
}
m_MessageTimer += Time.deltaTime;
bool needUpdateCamera = false;
if (Input.GetButtonDown(kDebugNext))
{
NextCamera();
needUpdateCamera = true;
}
if (Input.GetButtonDown(kDebugPrevious))
{
PreviousCamera();
needUpdateCamera = true;
}
if (needUpdateCamera)
{
m_MessageTimer = 0.0f;
if(m_CurrentCamera == m_OriginalCamera)
if (Input.GetButtonDown(kDebugPrevious))
m_OriginalCameraPosition = m_OriginalCamera.transform.position;
m_OriginalCameraRotation = m_OriginalCamera.transform.rotation;
PreviousCamera();
needUpdateCamera = true;
m_CurrentCamera = GetNextCamera();
if(m_CurrentCamera != null)
if (needUpdateCamera)
// If we witch back to the original camera, put back the transform in it.
if (m_CurrentCamera == m_OriginalCamera)
m_MessageTimer = 0.0f;
if(m_CurrentCamera == m_OriginalCamera)
m_OriginalCamera.transform.position = m_OriginalCameraPosition;
m_OriginalCamera.transform.rotation = m_OriginalCameraRotation;
m_OriginalCameraPosition = m_OriginalCamera.transform.position;
m_OriginalCameraRotation = m_OriginalCamera.transform.rotation;
transform.position = m_CurrentCamera.transform.position;
transform.rotation = m_CurrentCamera.transform.rotation;
m_CurrentCamera = GetNextCamera();
if(m_CurrentCamera != null)
{
// If we witch back to the original camera, put back the transform in it.
if (m_CurrentCamera == m_OriginalCamera)
{
m_OriginalCamera.transform.position = m_OriginalCameraPosition;
m_OriginalCamera.transform.rotation = m_OriginalCameraRotation;
}
transform.position = m_CurrentCamera.transform.position;
transform.rotation = m_CurrentCamera.transform.rotation;
}
}
if (m_MessageTimer < m_MessageDuration)
{
string cameraName = m_CurrentCamera != null ? m_CurrentCamera.name : "NULL";
string message = string.Format("Switching to camera : {0}", cameraName);
Debugging.PushDebugMessage(message);
if (m_MessageTimer < m_MessageDuration)
{
string cameraName = m_CurrentCamera != null ? m_CurrentCamera.name : "NULL";
string message = string.Format("Switching to camera : {0}", cameraName);
Debugging.PushDebugMessage(message);
}
}
}
}

102
Assets/ScriptableRenderPipeline/common/Camera/FreeCamera.cs


using UnityEngine;
public class FreeCamera : MonoBehaviour
namespace UnityEngine.Experimental.Rendering
public float m_LookSpeedController = 120f;
public float m_LookSpeedMouse = 10.0f;
public float m_MoveSpeed = 50.0f;
public float m_Turbo = 10.0f;
public class FreeCamera : MonoBehaviour
{
public float m_LookSpeedController = 120f;
public float m_LookSpeedMouse = 10.0f;
public float m_MoveSpeed = 50.0f;
public float m_Turbo = 10.0f;
private static string kMouseX = "Mouse X";
private static string kMouseY = "Mouse Y";
private static string kRightStickX = "Controller Right Stick X";
private static string kRightStickY = "Controller Right Stick Y";
private static string kVertical = "Vertical";
private static string kHorizontal = "Horizontal";
private string[] m_RequiredInputAxes = { kMouseX, kMouseY, kRightStickX, kRightStickY, kVertical, kHorizontal };
private static string kMouseX = "Mouse X";
private static string kMouseY = "Mouse Y";
private static string kRightStickX = "Controller Right Stick X";
private static string kRightStickY = "Controller Right Stick Y";
private static string kVertical = "Vertical";
private static string kHorizontal = "Horizontal";
private string[] m_RequiredInputAxes = { kMouseX, kMouseY, kRightStickX, kRightStickY, kVertical, kHorizontal };
private bool m_Valid = true;
void OnEnable()
{
m_Valid = Debugging.CheckRequiredInputAxisMapping(m_RequiredInputAxes);
}
private bool m_Valid = true;
void OnEnable()
{
m_Valid = Debugging.CheckRequiredInputAxisMapping(m_RequiredInputAxes);
}
void Update()
{
if(m_Valid)
void Update()
float inputRotateAxisX = 0.0f;
float inputRotateAxisY = 0.0f;
if (Input.GetMouseButton(1))
if(m_Valid)
inputRotateAxisX = Input.GetAxis(kMouseX) * m_LookSpeedMouse;
inputRotateAxisY = Input.GetAxis(kMouseY) * m_LookSpeedMouse;
}
inputRotateAxisX += (Input.GetAxis(kRightStickX) * m_LookSpeedController * Time.deltaTime);
inputRotateAxisY += (Input.GetAxis(kRightStickY) * m_LookSpeedController * Time.deltaTime);
float inputRotateAxisX = 0.0f;
float inputRotateAxisY = 0.0f;
if (Input.GetMouseButton(1))
{
inputRotateAxisX = Input.GetAxis(kMouseX) * m_LookSpeedMouse;
inputRotateAxisY = Input.GetAxis(kMouseY) * m_LookSpeedMouse;
}
inputRotateAxisX += (Input.GetAxis(kRightStickX) * m_LookSpeedController * Time.deltaTime);
inputRotateAxisY += (Input.GetAxis(kRightStickY) * m_LookSpeedController * Time.deltaTime);
float inputVertical = Input.GetAxis(kVertical);
float inputHorizontal = Input.GetAxis(kHorizontal);
float inputVertical = Input.GetAxis(kVertical);
float inputHorizontal = Input.GetAxis(kHorizontal);
bool moved = inputRotateAxisX != 0.0f || inputRotateAxisY != 0.0f || inputVertical != 0.0f || inputHorizontal != 0.0f;
if (moved)
{
float rotationX = transform.localEulerAngles.x;
float newRotationY = transform.localEulerAngles.y + inputRotateAxisX;
bool moved = inputRotateAxisX != 0.0f || inputRotateAxisY != 0.0f || inputVertical != 0.0f || inputHorizontal != 0.0f;
if (moved)
{
float rotationX = transform.localEulerAngles.x;
float newRotationY = transform.localEulerAngles.y + inputRotateAxisX;
// Weird clamping code due to weird Euler angle mapping...
float newRotationX = (rotationX - inputRotateAxisY);
if (rotationX <= 90.0f && newRotationX >= 0.0f)
newRotationX = Mathf.Clamp(newRotationX, 0.0f, 90.0f);
if (rotationX >= 270.0f)
newRotationX = Mathf.Clamp(newRotationX, 270.0f, 360.0f);
// Weird clamping code due to weird Euler angle mapping...
float newRotationX = (rotationX - inputRotateAxisY);
if (rotationX <= 90.0f && newRotationX >= 0.0f)
newRotationX = Mathf.Clamp(newRotationX, 0.0f, 90.0f);
if (rotationX >= 270.0f)
newRotationX = Mathf.Clamp(newRotationX, 270.0f, 360.0f);
transform.localRotation = Quaternion.Euler(newRotationX, newRotationY, transform.localEulerAngles.z);
transform.localRotation = Quaternion.Euler(newRotationX, newRotationY, transform.localEulerAngles.z);
float moveSpeed = Time.deltaTime * m_MoveSpeed;
if (Input.GetMouseButton(1))
moveSpeed *= Input.GetKey(KeyCode.LeftShift) ? m_Turbo : 1.0f;
else
moveSpeed *= Input.GetAxis("Fire1") > 0.0f ? m_Turbo : 1.0f;
transform.position += transform.forward * moveSpeed * inputVertical;
transform.position += transform.right * moveSpeed * inputHorizontal;
float moveSpeed = Time.deltaTime * m_MoveSpeed;
if (Input.GetMouseButton(1))
moveSpeed *= Input.GetKey(KeyCode.LeftShift) ? m_Turbo : 1.0f;
else
moveSpeed *= Input.GetAxis("Fire1") > 0.0f ? m_Turbo : 1.0f;
transform.position += transform.forward * moveSpeed * inputVertical;
transform.position += transform.right * moveSpeed * inputHorizontal;
}
}
}
}

191
Assets/ScriptableRenderPipeline/common/Debugging.cs


using System.Collections.Generic;
using UnityEngine;
public class Debugging : MonoBehaviour
namespace UnityEngine.Experimental.Rendering
public class Debugging : MonoBehaviour
{
private static bool m_DebugControlEnabled = false;
public static bool debugControlEnabled { get { return m_DebugControlEnabled; } }
private static bool m_DebugControlEnabled = false;
public static bool debugControlEnabled { get { return m_DebugControlEnabled; } }
private float m_DebugControlEnabledMsgTime = 3.0f;
private float m_DebugControlEnabledMsgTimer = 0.0f;
private float m_DebugControlEnabledMsgTime = 3.0f;
private float m_DebugControlEnabledMsgTimer = 0.0f;
private bool m_DebugKeyUp1 = false;
private bool m_DebugKeyUp2 = false;
private bool m_CanReceiveInput = true;
private bool m_DebugKeyUp1 = false;
private bool m_DebugKeyUp2 = false;
private bool m_CanReceiveInput = true;
private static List<string> m_DebugMessages = new List<string>();
private static List<string> m_DebugMessages = new List<string>();
private static string kEnableDebugBtn1 = "Enable Debug Button 1";
private static string kEnableDebugBtn2 = "Enable Debug Button 2";
private string[] m_RequiredInputButtons = { kEnableDebugBtn1, kEnableDebugBtn2 };
private bool m_Valid = true;
private static string kEnableDebugBtn1 = "Enable Debug Button 1";
private static string kEnableDebugBtn2 = "Enable Debug Button 2";
private string[] m_RequiredInputButtons = { kEnableDebugBtn1, kEnableDebugBtn2 };
private bool m_Valid = true;
public static void PushDebugMessage(string message)
{
m_DebugMessages.Add(message);
}
public static void PushDebugMessage(string message)
{
m_DebugMessages.Add(message);
}
static public bool CheckRequiredInputButtonMapping(string[] values)
{
bool inputsOk = true;
foreach(string value in values)
static public bool CheckRequiredInputButtonMapping(string[] values)
try
{
Input.GetButton(value);
}
catch
bool inputsOk = true;
foreach(string value in values)
Debug.LogWarning(string.Format("Required input button mapping missing: {0}.", value));
inputsOk = false;
try
{
Input.GetButton(value);
}
catch
{
Debug.LogWarning(string.Format("Required input button mapping missing: {0}.", value));
inputsOk = false;
}
}
return inputsOk;
}
return inputsOk;
}
static public bool CheckRequiredInputAxisMapping(string[] values)
{
bool inputsOk = true;
foreach (string value in values)
static public bool CheckRequiredInputAxisMapping(string[] values)
try
{
Input.GetAxis(value);
}
catch
bool inputsOk = true;
foreach (string value in values)
Debug.LogWarning(string.Format("Required input axis mapping missing: {0}.", value));
inputsOk = false;
try
{
Input.GetAxis(value);
}
catch
{
Debug.LogWarning(string.Format("Required input axis mapping missing: {0}.", value));
inputsOk = false;
}
return inputsOk;
return inputsOk;
}
void OnEnable()
{
m_Valid = CheckRequiredInputButtonMapping(m_RequiredInputButtons);
}
void OnEnable()
{
m_Valid = CheckRequiredInputButtonMapping(m_RequiredInputButtons);
}
void Update()
{
if(m_Valid)
void Update()
m_DebugControlEnabledMsgTimer += Time.deltaTime;
if(m_Valid)
{
m_DebugControlEnabledMsgTimer += Time.deltaTime;
bool enableDebug = Input.GetButton(kEnableDebugBtn1) && Input.GetButton(kEnableDebugBtn2) || Input.GetKey(KeyCode.LeftControl) && Input.GetKey(KeyCode.Backspace);
bool enableDebug = Input.GetButton(kEnableDebugBtn1) && Input.GetButton(kEnableDebugBtn2) || Input.GetKey(KeyCode.LeftControl) && Input.GetKey(KeyCode.Backspace);
if (m_CanReceiveInput && enableDebug)
{
m_DebugControlEnabled = !m_DebugControlEnabled;
m_DebugControlEnabledMsgTimer = 0.0f;
m_CanReceiveInput = false;
m_DebugKeyUp1 = false;
m_DebugKeyUp2 = false;
}
if (m_CanReceiveInput && enableDebug)
{
m_DebugControlEnabled = !m_DebugControlEnabled;
m_DebugControlEnabledMsgTimer = 0.0f;
m_CanReceiveInput = false;
m_DebugKeyUp1 = false;
m_DebugKeyUp2 = false;
}
if (Input.GetButtonUp(kEnableDebugBtn1))
{
m_DebugKeyUp1 = true;
}
if (Input.GetButtonUp(kEnableDebugBtn2))
{
m_DebugKeyUp2 = true;
}
if (Input.GetButtonUp(kEnableDebugBtn1))
{
m_DebugKeyUp1 = true;
}
if (Input.GetButtonUp(kEnableDebugBtn2))
{
m_DebugKeyUp2 = true;
}
// For keyboard you want to be able to keep ctrl pressed.
if (Input.GetKeyUp(KeyCode.Backspace))
{
m_DebugKeyUp1 = m_DebugKeyUp2 = true;
}
// For keyboard you want to be able to keep ctrl pressed.
if (Input.GetKeyUp(KeyCode.Backspace))
{
m_DebugKeyUp1 = m_DebugKeyUp2 = true;
}
m_CanReceiveInput = m_DebugKeyUp1 && m_DebugKeyUp2;
m_CanReceiveInput = m_DebugKeyUp1 && m_DebugKeyUp2;
if (m_DebugControlEnabledMsgTimer < m_DebugControlEnabledMsgTime)
{
if (m_DebugControlEnabled)
PushDebugMessage("Debug Controls Enabled");
else
PushDebugMessage("Debug Controls Disabled");
if (m_DebugControlEnabledMsgTimer < m_DebugControlEnabledMsgTime)
{
if (m_DebugControlEnabled)
PushDebugMessage("Debug Controls Enabled");
else
PushDebugMessage("Debug Controls Disabled");
}
}
void OnGUI()
{
using(new GUILayout.HorizontalScope())
void OnGUI()
GUILayout.Space(10.0f);
using(new GUILayout.VerticalScope())
using(new GUILayout.HorizontalScope())
for (int i = 0; i < m_DebugMessages.Count; ++i)
using(new GUILayout.VerticalScope())
GUILayout.Label(m_DebugMessages[i]);
GUILayout.Space(10.0f);
for (int i = 0; i < m_DebugMessages.Count; ++i)
{
GUILayout.Label(m_DebugMessages[i]);
}
// Make sure to clear only after all relevant events have occured.
if (Event.current.type == EventType.Repaint)
m_DebugMessages.Clear();
// Make sure to clear only after all relevant events have occured.
if (Event.current.type == EventType.Repaint)
m_DebugMessages.Clear();
}
}

415
Assets/ScriptableRenderPipeline/common/SkyboxHelper.cs


using UnityEngine;
using UnityEngine.Experimental.Rendering;
public class SkyboxHelper
namespace UnityEngine.Experimental.Rendering
public SkyboxHelper()
public class SkyboxHelper
}
const int k_NumFullSubdivisions = 3; // 3 subdivs == 2048 triangles
const int k_NumHorizonSubdivisions = 2;
public void CreateMesh()
{
var vertData = new Vector3[8 * 3];
for (int i = 0; i < 8 * 3; i++)
public SkyboxHelper()
vertData[i] = m_OctaVerts[i];
// Regular subdivisions
for (int i = 0; i < k_NumFullSubdivisions; i++)
const int k_NumFullSubdivisions = 3; // 3 subdivs == 2048 triangles
const int k_NumHorizonSubdivisions = 2;
public void CreateMesh()
var srcData = vertData.Clone() as Vector3[];
var verts = new List<Vector3>();
for (int k = 0; k < srcData.Length; k += 3)
var vertData = new Vector3[8 * 3];
for (int i = 0; i < 8 * 3; i++)
Subdivide(verts, srcData[k], srcData[k + 1], srcData[k + 2]);
vertData[i] = m_OctaVerts[i];
vertData = verts.ToArray();
}
// Horizon subdivisions
var horizonLimit = 1.0f;
for (int i = 0; i < k_NumHorizonSubdivisions; i++)
{
var srcData = vertData.Clone() as Vector3[];
var verts = new List<Vector3>();
horizonLimit *= 0.5f; // First iteration limit to y < +-0.5, next one 0.25 etc.
for (int k = 0; k < srcData.Length; k += 3)
// Regular subdivisions
for (int i = 0; i < k_NumFullSubdivisions; i++)
var maxAbsY = Mathf.Max(Mathf.Abs(srcData[k].y), Mathf.Abs(srcData[k + 1].y), Mathf.Abs(srcData[k + 2].y));
if (maxAbsY > horizonLimit)
{
// Pass through existing triangle
verts.Add(srcData[k]);
verts.Add(srcData[k + 1]);
verts.Add(srcData[k + 2]);
}
else
var srcData = vertData.Clone() as Vector3[];
var verts = new List<Vector3>();
for (int k = 0; k < srcData.Length; k += 3)
SubdivideYOnly(verts, srcData[k], srcData[k + 1], srcData[k + 2]);
Subdivide(verts, srcData[k], srcData[k + 1], srcData[k + 2]);
vertData = verts.ToArray();
vertData = verts.ToArray();
}
// Write out the mesh
var vertexCount = vertData.Length;
var triangles = new int[vertexCount];
for (int i = 0; i < vertexCount; i++)
{
triangles[i] = i;
}
// Horizon subdivisions
var horizonLimit = 1.0f;
for (int i = 0; i < k_NumHorizonSubdivisions; i++)
{
var srcData = vertData.Clone() as Vector3[];
var verts = new List<Vector3>();
m_Mesh = new Mesh
{
vertices = vertData,
triangles = triangles
};
}
horizonLimit *= 0.5f; // First iteration limit to y < +-0.5, next one 0.25 etc.
for (int k = 0; k < srcData.Length; k += 3)
{
var maxAbsY = Mathf.Max(Mathf.Abs(srcData[k].y), Mathf.Abs(srcData[k + 1].y), Mathf.Abs(srcData[k + 2].y));
if (maxAbsY > horizonLimit)
{
// Pass through existing triangle
verts.Add(srcData[k]);
verts.Add(srcData[k + 1]);
verts.Add(srcData[k + 2]);
}
else
{
SubdivideYOnly(verts, srcData[k], srcData[k + 1], srcData[k + 2]);
}
}
vertData = verts.ToArray();
}
public UnityEngine.Mesh mesh
{
get { return m_Mesh; }
}
// Write out the mesh
var vertexCount = vertData.Length;
var triangles = new int[vertexCount];
for (int i = 0; i < vertexCount; i++)
{
triangles[i] = i;
}
public void Draw(ScriptableRenderContext loop, Camera camera)
{
if (camera.clearFlags != CameraClearFlags.Skybox)
{
return;
m_Mesh = new Mesh
{
vertices = vertData,
triangles = triangles
};
var mat = RenderSettings.skybox;
if (mat == null)
public UnityEngine.Mesh mesh
return;
get { return m_Mesh; }
var cmd = new CommandBuffer { name = "Skybox" };
var looksLikeSixSidedShader = true;
looksLikeSixSidedShader &= (mat.passCount == 6); // should have six passes
//looksLikeSixSidedShader &= !mat.GetShader()->GetShaderLabShader()->HasLightingPasses();
if (looksLikeSixSidedShader)
public void Draw(ScriptableRenderContext loop, Camera camera)
Debug.LogWarning("Six sided skybox not yet supported.");
}
else
{
if (mesh == null)
if (camera.clearFlags != CameraClearFlags.Skybox)
CreateMesh();
return;
var dist = camera.farClipPlane * 10.0f;
var mat = RenderSettings.skybox;
var world = Matrix4x4.TRS(camera.transform.position, Quaternion.identity, new Vector3(dist, dist, dist));
if (mat == null)
{
return;
}
var skyboxProj = SkyboxHelper.GetProjectionMatrix(camera);
cmd.SetViewProjectionMatrices (camera.worldToCameraMatrix, skyboxProj);
cmd.DrawMesh(mesh, world, mat);
var cmd = new CommandBuffer { name = "Skybox" };
cmd.SetViewProjectionMatrices (camera.worldToCameraMatrix, camera.projectionMatrix);
}
var looksLikeSixSidedShader = true;
looksLikeSixSidedShader &= (mat.passCount == 6); // should have six passes
//looksLikeSixSidedShader &= !mat.GetShader()->GetShaderLabShader()->HasLightingPasses();
loop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
if (looksLikeSixSidedShader)
{
Debug.LogWarning("Six sided skybox not yet supported.");
}
else
{
if (mesh == null)
{
CreateMesh();
}
public static Matrix4x4 GetProjectionMatrix(Camera camera)
{
var skyboxProj = Matrix4x4.Perspective(camera.fieldOfView, camera.aspect, camera.nearClipPlane, camera.farClipPlane);
var dist = camera.farClipPlane * 10.0f;
var nearPlane = camera.nearClipPlane * 0.01f;
skyboxProj = AdjustDepthRange(skyboxProj, camera.nearClipPlane, nearPlane, camera.farClipPlane);
return MakeProjectionInfinite(skyboxProj, nearPlane);
}
var world = Matrix4x4.TRS(camera.transform.position, Quaternion.identity, new Vector3(dist, dist, dist));
static Matrix4x4 MakeProjectionInfinite(Matrix4x4 m, float nearPlane)
{
const float epsilon = 1e-6f;
var skyboxProj = SkyboxHelper.GetProjectionMatrix(camera);
cmd.SetViewProjectionMatrices (camera.worldToCameraMatrix, skyboxProj);
cmd.DrawMesh(mesh, world, mat);
var r = m;
r[2, 2] = -1.0f + epsilon;
r[2, 3] = (-2.0f + epsilon) * nearPlane;
r[3, 2] = -1.0f;
return r;
}
cmd.SetViewProjectionMatrices (camera.worldToCameraMatrix, camera.projectionMatrix);
}
static Matrix4x4 AdjustDepthRange(Matrix4x4 mat, float origNear, float newNear, float newFar)
{
var x = mat[0, 0];
var y = mat[1, 1];
var w = mat[0, 2];
var z = mat[1, 2];
loop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
var r = ((2.0f * origNear) / x) * ((w + 1) * 0.5f);
var t = ((2.0f * origNear) / y) * ((z + 1) * 0.5f);
var l = ((2.0f * origNear) / x) * (((w + 1) * 0.5f) - 1);
var b = ((2.0f * origNear) / y) * (((z + 1) * 0.5f) - 1);
public static Matrix4x4 GetProjectionMatrix(Camera camera)
{
var skyboxProj = Matrix4x4.Perspective(camera.fieldOfView, camera.aspect, camera.nearClipPlane, camera.farClipPlane);
var ratio = (newNear / origNear);
var nearPlane = camera.nearClipPlane * 0.01f;
skyboxProj = AdjustDepthRange(skyboxProj, camera.nearClipPlane, nearPlane, camera.farClipPlane);
return MakeProjectionInfinite(skyboxProj, nearPlane);
}
r *= ratio;
t *= ratio;
l *= ratio;
b *= ratio;
var ret = new Matrix4x4();
static Matrix4x4 MakeProjectionInfinite(Matrix4x4 m, float nearPlane)
{
const float epsilon = 1e-6f;
ret[0, 0] = (2.0f * newNear) / (r - l); ret[0, 1] = 0; ret[0, 2] = (r + l) / (r - l); ret[0, 3] = 0;
ret[1, 0] = 0; ret[1, 1] = (2.0f * newNear) / (t - b); ret[1, 2] = (t + b) / (t - b); ret[1, 3] = 0;
ret[2, 0] = 0; ret[2, 1] = 0; ret[2, 2] = -(newFar + newNear) / (newFar - newNear); ret[2, 3] = -(2.0f * newFar * newNear) / (newFar - newNear);
ret[3, 0] = 0; ret[3, 1] = 0; ret[3, 2] = -1.0f; ret[3, 3] = 0;
var r = m;
r[2, 2] = -1.0f + epsilon;
r[2, 3] = (-2.0f + epsilon) * nearPlane;
r[3, 2] = -1.0f;
return r;
}
return ret;
}
static Matrix4x4 AdjustDepthRange(Matrix4x4 mat, float origNear, float newNear, float newFar)
{
var x = mat[0, 0];
var y = mat[1, 1];
var w = mat[0, 2];
var z = mat[1, 2];
// Octahedron vertices
readonly Vector3[] m_OctaVerts =
{
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f), new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f),
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f), new Vector3(-1.0f, 0.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(-1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f), new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(-1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f), new Vector3(-1.0f, 0.0f, 0.0f),
};
var r = ((2.0f * origNear) / x) * ((w + 1) * 0.5f);
var t = ((2.0f * origNear) / y) * ((z + 1) * 0.5f);
var l = ((2.0f * origNear) / x) * (((w + 1) * 0.5f) - 1);
var b = ((2.0f * origNear) / y) * (((z + 1) * 0.5f) - 1);
Vector3 SubDivVert(Vector3 v1, Vector3 v2)
{
return Vector3.Normalize(v1 + v2);
}
var ratio = (newNear / origNear);
void Subdivide(ICollection<Vector3> dest, Vector3 v1, Vector3 v2, Vector3 v3)
{
var v12 = SubDivVert(v1, v2);
var v23 = SubDivVert(v2, v3);
var v13 = SubDivVert(v1, v3);
r *= ratio;
t *= ratio;
l *= ratio;
b *= ratio;
dest.Add(v1);
dest.Add(v12);
dest.Add(v13);
dest.Add(v12);
dest.Add(v2);
dest.Add(v23);
dest.Add(v23);
dest.Add(v13);
dest.Add(v12);
dest.Add(v3);
dest.Add(v13);
dest.Add(v23);
}
var ret = new Matrix4x4();
void SubdivideYOnly(ICollection<Vector3> dest, Vector3 v1, Vector3 v2, Vector3 v3)
{
// Find out which vertex is furthest out from the others on the y axis
ret[0, 0] = (2.0f * newNear) / (r - l); ret[0, 1] = 0; ret[0, 2] = (r + l) / (r - l); ret[0, 3] = 0;
ret[1, 0] = 0; ret[1, 1] = (2.0f * newNear) / (t - b); ret[1, 2] = (t + b) / (t - b); ret[1, 3] = 0;
ret[2, 0] = 0; ret[2, 1] = 0; ret[2, 2] = -(newFar + newNear) / (newFar - newNear); ret[2, 3] = -(2.0f * newFar * newNear) / (newFar - newNear);
ret[3, 0] = 0; ret[3, 1] = 0; ret[3, 2] = -1.0f; ret[3, 3] = 0;
var d12 = Mathf.Abs(v2.y - v1.y);
var d23 = Mathf.Abs(v2.y - v3.y);
var d31 = Mathf.Abs(v3.y - v1.y);
return ret;
}
Vector3 top, va, vb;
// Octahedron vertices
readonly Vector3[] m_OctaVerts =
{
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f), new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f),
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f), new Vector3(-1.0f, 0.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(-1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f), new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(-1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f), new Vector3(-1.0f, 0.0f, 0.0f),
};
if (d12 < d23 && d12 < d31)
Vector3 SubDivVert(Vector3 v1, Vector3 v2)
top = v3;
va = v1;
vb = v2;
}
else if (d23 < d12 && d23 < d31)
{
top = v1;
va = v2;
vb = v3;
}
else
{
top = v2;
va = v3;
vb = v1;
return Vector3.Normalize(v1 + v2);
var v12 = SubDivVert(top, va);
var v13 = SubDivVert(top, vb);
dest.Add(top);
dest.Add(v12);
dest.Add(v13);
// A bit of extra logic to prevent triangle slivers: choose the shorter of (13->va), (12->vb) as triangle base
if ((v13 - va).sqrMagnitude > (v12 - vb).sqrMagnitude)
void Subdivide(ICollection<Vector3> dest, Vector3 v1, Vector3 v2, Vector3 v3)
var v12 = SubDivVert(v1, v2);
var v23 = SubDivVert(v2, v3);
var v13 = SubDivVert(v1, v3);
dest.Add(v1);
dest.Add(va);
dest.Add(vb);
dest.Add(v13);
dest.Add(v12);
dest.Add(v2);
dest.Add(v23);
dest.Add(v23);
dest.Add(vb);
dest.Add(v3);
dest.Add(v13);
dest.Add(v23);
else
void SubdivideYOnly(ICollection<Vector3> dest, Vector3 v1, Vector3 v2, Vector3 v3)
dest.Add(v13);
// Find out which vertex is furthest out from the others on the y axis
var d12 = Mathf.Abs(v2.y - v1.y);
var d23 = Mathf.Abs(v2.y - v3.y);
var d31 = Mathf.Abs(v3.y - v1.y);
Vector3 top, va, vb;
if (d12 < d23 && d12 < d31)
{
top = v3;
va = v1;
vb = v2;
}
else if (d23 < d12 && d23 < d31)
{
top = v1;
va = v2;
vb = v3;
}
else
{
top = v2;
va = v3;
vb = v1;
}
var v12 = SubDivVert(top, va);
var v13 = SubDivVert(top, vb);
dest.Add(top);
dest.Add(va);
dest.Add(va);
dest.Add(vb);
// A bit of extra logic to prevent triangle slivers: choose the shorter of (13->va), (12->vb) as triangle base
if ((v13 - va).sqrMagnitude > (v12 - vb).sqrMagnitude)
{
dest.Add(v12);
dest.Add(va);
dest.Add(vb);
dest.Add(v13);
dest.Add(v12);
dest.Add(vb);
}
else
{
dest.Add(v13);
dest.Add(v12);
dest.Add(va);
dest.Add(v13);
dest.Add(va);
dest.Add(vb);
}
}
Mesh m_Mesh;
Mesh m_Mesh;
}
}

689
Assets/ScriptableRenderPipeline/common/TextureCache.cs


using UnityEditor;
#endif
public class TextureCache2D : TextureCache
namespace UnityEngine.Experimental.Rendering
private Texture2DArray m_Cache;
public override void TransferToSlice(int sliceIndex, Texture texture)
public class TextureCache2D : TextureCache
var mismatch = (m_Cache.width != texture.width) || (m_Cache.height != texture.height);
private Texture2DArray m_Cache;
if (texture is Texture2D)
public override void TransferToSlice(int sliceIndex, Texture texture)
mismatch |= (m_Cache.format != (texture as Texture2D).format);
}
var mismatch = (m_Cache.width != texture.width) || (m_Cache.height != texture.height);
if (mismatch)
{
if (!Graphics.ConvertTexture(texture, 0, m_Cache, sliceIndex))
if (texture is Texture2D)
Debug.LogErrorFormat(texture, "Unable to convert texture \"{0}\" to match renderloop settings ({1}x{2} {3})",
texture.name, m_Cache.width, m_Cache.height, m_Cache.format);
mismatch |= (m_Cache.format != (texture as Texture2D).format);
}
if (mismatch)
{
if (!Graphics.ConvertTexture(texture, 0, m_Cache, sliceIndex))
{
Debug.LogErrorFormat(texture, "Unable to convert texture \"{0}\" to match renderloop settings ({1}x{2} {3})",
texture.name, m_Cache.width, m_Cache.height, m_Cache.format);
}
}
else
{
Graphics.CopyTexture(texture, 0, m_Cache, sliceIndex);
else
public override Texture GetTexCache()
Graphics.CopyTexture(texture, 0, m_Cache, sliceIndex);
return m_Cache;
}
public bool AllocTextureArray(int numTextures, int width, int height, TextureFormat format, bool isMipMapped)
{
var res = AllocTextureArray(numTextures);
m_NumMipLevels = GetNumMips(width, height);
public override Texture GetTexCache()
{
return m_Cache;
}
m_Cache = new Texture2DArray(width, height, numTextures, format, isMipMapped)
{
hideFlags = HideFlags.HideAndDontSave,
wrapMode = TextureWrapMode.Clamp
};
public bool AllocTextureArray(int numTextures, int width, int height, TextureFormat format, bool isMipMapped)
{
var res = AllocTextureArray(numTextures);
m_NumMipLevels = GetNumMips(width, height);
return res;
}
m_Cache = new Texture2DArray(width, height, numTextures, format, isMipMapped)
public void Release()
hideFlags = HideFlags.HideAndDontSave,
wrapMode = TextureWrapMode.Clamp
};
return res;
Texture.DestroyImmediate(m_Cache); // do I need this?
}
public void Release()
public class TextureCacheCubemap : TextureCache
Texture.DestroyImmediate(m_Cache); // do I need this?
}
}
private CubemapArray m_Cache;
public class TextureCacheCubemap : TextureCache
{
private CubemapArray m_Cache;
// the member variables below are only in use when TextureCache.supportsCubemapArrayTextures is false
private Texture2DArray m_CacheNoCubeArray;
private RenderTexture[] m_StagingRTs;
private int m_NumPanoMipLevels;
private Material m_CubeBlitMaterial;
private int m_CubeMipLevelPropName;
private int m_cubeSrcTexPropName;
// the member variables below are only in use when TextureCache.supportsCubemapArrayTextures is false
private Texture2DArray m_CacheNoCubeArray;
private RenderTexture[] m_StagingRTs;
private int m_NumPanoMipLevels;
private Material m_CubeBlitMaterial;
private int m_CubeMipLevelPropName;
private int m_cubeSrcTexPropName;
public override void TransferToSlice(int sliceIndex, Texture texture)
{
if(!TextureCache.supportsCubemapArrayTextures)
TransferToPanoCache(sliceIndex, texture);
else
public override void TransferToSlice(int sliceIndex, Texture texture)
var mismatch = (m_Cache.width != texture.width) || (m_Cache.height != texture.height);
if (texture is Cubemap)
if(!TextureCache.supportsCubemapArrayTextures)
TransferToPanoCache(sliceIndex, texture);
else
mismatch |= (m_Cache.format != (texture as Cubemap).format);
}
var mismatch = (m_Cache.width != texture.width) || (m_Cache.height != texture.height);
if (mismatch)
{
bool failed = false;
if (texture is Cubemap)
{
mismatch |= (m_Cache.format != (texture as Cubemap).format);
}
for (int f = 0; f < 6; f++)
if (mismatch)
if (!Graphics.ConvertTexture(texture, f, m_Cache, 6 * sliceIndex + f))
bool failed = false;
for (int f = 0; f < 6; f++)
failed = true;
break;
if (!Graphics.ConvertTexture(texture, f, m_Cache, 6 * sliceIndex + f))
{
failed = true;
break;
}
}
if (failed)
if (failed)
{
Debug.LogErrorFormat(texture, "Unable to convert texture \"{0}\" to match renderloop settings ({1}x{2} {3})",
texture.name, m_Cache.width, m_Cache.height, m_Cache.format);
}
}
else
Debug.LogErrorFormat(texture, "Unable to convert texture \"{0}\" to match renderloop settings ({1}x{2} {3})",
texture.name, m_Cache.width, m_Cache.height, m_Cache.format);
for (int f = 0; f < 6; f++)
Graphics.CopyTexture(texture, f, m_Cache, 6 * sliceIndex + f);
else
{
for (int f = 0; f < 6; f++)
Graphics.CopyTexture(texture, f, m_Cache, 6 * sliceIndex + f);
}
}
public override Texture GetTexCache()
{
return !TextureCache.supportsCubemapArrayTextures ? (Texture) m_CacheNoCubeArray : m_Cache;
}
public override Texture GetTexCache()
{
return !TextureCache.supportsCubemapArrayTextures ? (Texture) m_CacheNoCubeArray : m_Cache;
}
public bool AllocTextureArray(int numCubeMaps, int width, TextureFormat format, bool isMipMapped)
{
var res = AllocTextureArray(numCubeMaps);
m_NumMipLevels = GetNumMips(width, width); // will calculate same way whether we have cube array or not
public bool AllocTextureArray(int numCubeMaps, int width, TextureFormat format, bool isMipMapped)
{
var res = AllocTextureArray(numCubeMaps);
m_NumMipLevels = GetNumMips(width, width); // will calculate same way whether we have cube array or not
if(!TextureCache.supportsCubemapArrayTextures)
{
if(!m_CubeBlitMaterial) m_CubeBlitMaterial = new Material(Shader.Find("Hidden/CubeToPano"));
if(!TextureCache.supportsCubemapArrayTextures)
{
if(!m_CubeBlitMaterial) m_CubeBlitMaterial = new Material(Shader.Find("Hidden/CubeToPano"));
int panoWidthTop = 4*width;
int panoHeightTop = 2*width;
int panoWidthTop = 4*width;
int panoHeightTop = 2*width;
// create panorama 2D array. Hardcoding the render target for now. No convenient way atm to
// map from TextureFormat to RenderTextureFormat and don't want to deal with sRGB issues for now.
m_CacheNoCubeArray = new Texture2DArray(panoWidthTop, panoHeightTop, numCubeMaps, TextureFormat.RGBAHalf, isMipMapped)
{
hideFlags = HideFlags.HideAndDontSave,
wrapMode = TextureWrapMode.Repeat,
wrapModeV = TextureWrapMode.Clamp,
filterMode = FilterMode.Trilinear,
anisoLevel = 0
};
// create panorama 2D array. Hardcoding the render target for now. No convenient way atm to
// map from TextureFormat to RenderTextureFormat and don't want to deal with sRGB issues for now.
m_CacheNoCubeArray = new Texture2DArray(panoWidthTop, panoHeightTop, numCubeMaps, TextureFormat.RGBAHalf, isMipMapped)
{
hideFlags = HideFlags.HideAndDontSave,
wrapMode = TextureWrapMode.Repeat,
wrapModeV = TextureWrapMode.Clamp,
filterMode = FilterMode.Trilinear,
anisoLevel = 0
};
m_NumPanoMipLevels = isMipMapped ? GetNumMips(panoWidthTop, panoHeightTop) : 1;
m_StagingRTs = new RenderTexture[m_NumPanoMipLevels];
for(int m=0; m<m_NumPanoMipLevels; m++)
{
m_StagingRTs[m] = new RenderTexture(Mathf.Max(1,panoWidthTop>>m), Mathf.Max(1,panoHeightTop>>m), 0, RenderTextureFormat.ARGBHalf);
}
m_NumPanoMipLevels = isMipMapped ? GetNumMips(panoWidthTop, panoHeightTop) : 1;
m_StagingRTs = new RenderTexture[m_NumPanoMipLevels];
for(int m=0; m<m_NumPanoMipLevels; m++)
{
m_StagingRTs[m] = new RenderTexture(Mathf.Max(1,panoWidthTop>>m), Mathf.Max(1,panoHeightTop>>m), 0, RenderTextureFormat.ARGBHalf);
if(m_CubeBlitMaterial)
{
m_CubeMipLevelPropName = Shader.PropertyToID("_cubeMipLvl");
m_cubeSrcTexPropName = Shader.PropertyToID("_srcCubeTexture");
}
if(m_CubeBlitMaterial)
else
m_CubeMipLevelPropName = Shader.PropertyToID("_cubeMipLvl");
m_cubeSrcTexPropName = Shader.PropertyToID("_srcCubeTexture");
m_Cache = new CubemapArray(width, numCubeMaps, format, isMipMapped)
{
hideFlags = HideFlags.HideAndDontSave,
wrapMode = TextureWrapMode.Clamp,
filterMode = FilterMode.Trilinear,
anisoLevel = 0 // It is important to set 0 here, else unity force anisotropy filtering
};
return res;
else
public void Release()
m_Cache = new CubemapArray(width, numCubeMaps, format, isMipMapped)
if (m_CacheNoCubeArray)
hideFlags = HideFlags.HideAndDontSave,
wrapMode = TextureWrapMode.Clamp,
filterMode = FilterMode.Trilinear,
anisoLevel = 0 // It is important to set 0 here, else unity force anisotropy filtering
};
Texture.DestroyImmediate(m_CacheNoCubeArray);
for(int m=0; m<m_NumPanoMipLevels; m++)
{
m_StagingRTs[m].Release();
}
m_StagingRTs=null;
if(m_CubeBlitMaterial) Material.DestroyImmediate(m_CubeBlitMaterial);
}
if (m_Cache)
Texture.DestroyImmediate(m_Cache);
return res;
}
public void Release()
{
if (m_CacheNoCubeArray)
private void TransferToPanoCache(int sliceIndex, Texture texture)
Texture.DestroyImmediate(m_CacheNoCubeArray);
m_CubeBlitMaterial.SetTexture(m_cubeSrcTexPropName, texture);
m_StagingRTs[m].Release();
m_CubeBlitMaterial.SetInt(m_CubeMipLevelPropName, Mathf.Min(m_NumMipLevels-1,m) );
Graphics.SetRenderTarget(m_StagingRTs[m]);
Graphics.Blit(null, m_CubeBlitMaterial, 0);
m_StagingRTs=null;
if(m_CubeBlitMaterial) Material.DestroyImmediate(m_CubeBlitMaterial);
}
if (m_Cache)
Texture.DestroyImmediate(m_Cache);
}
private void TransferToPanoCache(int sliceIndex, Texture texture)
{
m_CubeBlitMaterial.SetTexture(m_cubeSrcTexPropName, texture);
for(int m=0; m<m_NumPanoMipLevels; m++)
{
m_CubeBlitMaterial.SetInt(m_CubeMipLevelPropName, Mathf.Min(m_NumMipLevels-1,m) );
Graphics.SetRenderTarget(m_StagingRTs[m]);
Graphics.Blit(null, m_CubeBlitMaterial, 0);
for(int m=0; m<m_NumPanoMipLevels; m++)
Graphics.CopyTexture(m_StagingRTs[m], 0, 0, m_CacheNoCubeArray, sliceIndex, m);
for(int m=0; m<m_NumPanoMipLevels; m++)
Graphics.CopyTexture(m_StagingRTs[m], 0, 0, m_CacheNoCubeArray, sliceIndex, m);
}
public abstract class TextureCache
{
protected int m_NumMipLevels;
public abstract class TextureCache
{
protected int m_NumMipLevels;
static int s_GlobalTextureCacheVersion = 0;
int m_TextureCacheVersion = 0;
static int s_GlobalTextureCacheVersion = 0;
int m_TextureCacheVersion = 0;
#if UNITY_EDITOR
internal class AssetReloader : UnityEditor.AssetPostprocessor
{
void OnPostprocessTexture(Texture texture)
#if UNITY_EDITOR
internal class AssetReloader : UnityEditor.AssetPostprocessor
s_GlobalTextureCacheVersion++;
void OnPostprocessTexture(Texture texture)
{
s_GlobalTextureCacheVersion++;
}
}
#endif
#endif
public static bool isMobileBuildTarget
{
get
public static bool isMobileBuildTarget
#if UNITY_EDITOR
switch (EditorUserBuildSettings.activeBuildTarget)
get
case BuildTarget.iOS:
case BuildTarget.Android:
case BuildTarget.Tizen:
case BuildTarget.WSAPlayer:
// Note: We return true on purpose even if Windows Store Apps are running on Desktop.
return true;
default:
return false;
#if UNITY_EDITOR
switch (EditorUserBuildSettings.activeBuildTarget)
{
case BuildTarget.iOS:
case BuildTarget.Android:
case BuildTarget.Tizen:
case BuildTarget.WSAPlayer:
// Note: We return true on purpose even if Windows Store Apps are running on Desktop.
return true;
default:
return false;
}
#else
return Application.isMobilePlatform;
#endif
#else
return Application.isMobilePlatform;
#endif
}
public static TextureFormat GetPreferredCompressedTextureFormat
{
get
public static TextureFormat GetPreferredCompressedTextureFormat
var format = TextureFormat.RGBAHalf;
get
{
var format = TextureFormat.RGBAHalf;
var probeFormat = TextureFormat.BC6H;
var probeFormat = TextureFormat.BC6H;
// On editor the texture is uncompressed when operating against mobile build targets
if (SystemInfo.SupportsTextureFormat(probeFormat) && !TextureCache.isMobileBuildTarget)
format = probeFormat;
// On editor the texture is uncompressed when operating against mobile build targets
if (SystemInfo.SupportsTextureFormat(probeFormat) && !TextureCache.isMobileBuildTarget)
format = probeFormat;
return format;
return format;
}
}
public static bool supportsCubemapArrayTextures
{
get
public static bool supportsCubemapArrayTextures
return (SystemInfo.supportsCubemapArrayTextures && !TextureCache.isMobileBuildTarget);
get
{
return (SystemInfo.supportsCubemapArrayTextures && !TextureCache.isMobileBuildTarget);
}
}
private struct SSliceEntry
{
public uint texId;
public uint countLRU;
};
private struct SSliceEntry
{
public uint texId;
public uint countLRU;
};
private int m_NumTextures;
private int[] m_SortedIdxArray;
private SSliceEntry[] m_SliceArray;
private int m_NumTextures;
private int[] m_SortedIdxArray;
private SSliceEntry[] m_SliceArray;
Dictionary<uint, int> m_LocatorInSliceArray;
Dictionary<uint, int> m_LocatorInSliceArray;
private static uint g_MaxFrameCount = unchecked((uint)(-1));
private static uint g_InvalidTexID = (uint)0;
private static uint g_MaxFrameCount = unchecked((uint)(-1));
private static uint g_InvalidTexID = (uint)0;
public int FetchSlice(Texture texture)
{
var texId = (uint)texture.GetInstanceID();
public int FetchSlice(Texture texture)
{
var texId = (uint)texture.GetInstanceID();
//assert(TexID!=g_InvalidTexID);
if (texId == g_InvalidTexID) return 0;
//assert(TexID!=g_InvalidTexID);
if (texId == g_InvalidTexID) return 0;
var bSwapSlice = false;
var bFoundAvailOrExistingSlice = false;
var sliceIndex = -1;
var bSwapSlice = false;
var bFoundAvailOrExistingSlice = false;
var sliceIndex = -1;
// search for existing copy
if (m_LocatorInSliceArray.ContainsKey(texId))
{
if (m_TextureCacheVersion != s_GlobalTextureCacheVersion)
// search for existing copy
if (m_LocatorInSliceArray.ContainsKey(texId))
m_LocatorInSliceArray.Remove(texId);
m_TextureCacheVersion++;
Debug.Assert(m_TextureCacheVersion <= s_GlobalTextureCacheVersion);
if (m_TextureCacheVersion != s_GlobalTextureCacheVersion)
{
m_LocatorInSliceArray.Remove(texId);
m_TextureCacheVersion++;
Debug.Assert(m_TextureCacheVersion <= s_GlobalTextureCacheVersion);
}
else
{
sliceIndex = m_LocatorInSliceArray[texId];
bFoundAvailOrExistingSlice = true;
}
//assert(m_SliceArray[sliceIndex].TexID==TexID);
else
// If no existing copy found in the array
if (!bFoundAvailOrExistingSlice)
sliceIndex = m_LocatorInSliceArray[texId];
bFoundAvailOrExistingSlice = true;
// look for first non zero entry. Will by the least recently used entry
// since the array was pre-sorted (in linear time) in NewFrame()
var bFound = false;
int j = 0, idx = 0;
while ((!bFound) && j < m_NumTextures)
{
idx = m_SortedIdxArray[j];
if (m_SliceArray[idx].countLRU == 0) ++j; // if entry already snagged by a new texture in this frame then ++j
else bFound = true;
}
if (bFound)
{
// if we are replacing an existing entry delete it from m_locatorInSliceArray.
if (m_SliceArray[idx].texId != g_InvalidTexID)
{
m_LocatorInSliceArray.Remove(m_SliceArray[idx].texId);
}
m_LocatorInSliceArray.Add(texId, idx);
m_SliceArray[idx].texId = texId;
sliceIndex = idx;
bFoundAvailOrExistingSlice = true;
bSwapSlice = true;
}
//assert(m_SliceArray[sliceIndex].TexID==TexID);
// wrap up
//assert(bFoundAvailOrExistingSlice);
if (bFoundAvailOrExistingSlice)
{
m_SliceArray[sliceIndex].countLRU = 0; // mark slice as in use this frame
if (bSwapSlice) // if this was a miss
{
// transfer new slice to sliceIndex from source texture
TransferToSlice(sliceIndex, texture);
}
}
return sliceIndex;
// If no existing copy found in the array
if (!bFoundAvailOrExistingSlice)
public void NewFrame()
// look for first non zero entry. Will by the least recently used entry
// since the array was pre-sorted (in linear time) in NewFrame()
var bFound = false;
int j = 0, idx = 0;
while ((!bFound) && j < m_NumTextures)
var numNonZeros = 0;
var tmpBuffer = new int[m_NumTextures];
for (int i = 0; i < m_NumTextures; i++)
idx = m_SortedIdxArray[j];
if (m_SliceArray[idx].countLRU == 0) ++j; // if entry already snagged by a new texture in this frame then ++j
else bFound = true;
tmpBuffer[i] = m_SortedIdxArray[i]; // copy buffer
if (m_SliceArray[m_SortedIdxArray[i]].countLRU != 0) ++numNonZeros;
if (bFound)
int nonZerosBase = 0, zerosBase = 0;
for (int i = 0; i < m_NumTextures; i++)
// if we are replacing an existing entry delete it from m_locatorInSliceArray.
if (m_SliceArray[idx].texId != g_InvalidTexID)
if (m_SliceArray[tmpBuffer[i]].countLRU == 0)
{
m_SortedIdxArray[zerosBase + numNonZeros] = tmpBuffer[i];
++zerosBase;
}
else
m_LocatorInSliceArray.Remove(m_SliceArray[idx].texId);
m_SortedIdxArray[nonZerosBase] = tmpBuffer[i];
++nonZerosBase;
}
m_LocatorInSliceArray.Add(texId, idx);
m_SliceArray[idx].texId = texId;
sliceIndex = idx;
bFoundAvailOrExistingSlice = true;
bSwapSlice = true;
for (int i = 0; i < m_NumTextures; i++)
{
if (m_SliceArray[i].countLRU < g_MaxFrameCount) ++m_SliceArray[i].countLRU; // next frame
//for(int q=1; q<m_numTextures; q++)
// assert(m_SliceArray[m_SortedIdxArray[q-1]].CountLRU>=m_SliceArray[m_SortedIdxArray[q]].CountLRU);
// wrap up
//assert(bFoundAvailOrExistingSlice);
if (bFoundAvailOrExistingSlice)
protected TextureCache()
m_SliceArray[sliceIndex].countLRU = 0; // mark slice as in use this frame
if (bSwapSlice) // if this was a miss
{
// transfer new slice to sliceIndex from source texture
TransferToSlice(sliceIndex, texture);
}
m_NumTextures = 0;
m_NumMipLevels = 0;
return sliceIndex;
}
public virtual void TransferToSlice(int sliceIndex, Texture texture)
{
}
public void NewFrame()
{
var numNonZeros = 0;
var tmpBuffer = new int[m_NumTextures];
for (int i = 0; i < m_NumTextures; i++)
public virtual Texture GetTexCache()
tmpBuffer[i] = m_SortedIdxArray[i]; // copy buffer
if (m_SliceArray[m_SortedIdxArray[i]].countLRU != 0) ++numNonZeros;
return null;
int nonZerosBase = 0, zerosBase = 0;
for (int i = 0; i < m_NumTextures; i++)
protected bool AllocTextureArray(int numTextures)
if (m_SliceArray[tmpBuffer[i]].countLRU == 0)
if (numTextures > 0)
m_SortedIdxArray[zerosBase + numNonZeros] = tmpBuffer[i];
++zerosBase;
}
else
{
m_SortedIdxArray[nonZerosBase] = tmpBuffer[i];
++nonZerosBase;
m_SliceArray = new SSliceEntry[numTextures];
m_SortedIdxArray = new int[numTextures];
m_LocatorInSliceArray = new Dictionary<uint, int>();
m_NumTextures = numTextures;
for (int i = 0; i < m_NumTextures; i++)
{
m_SliceArray[i].countLRU = g_MaxFrameCount; // never used before
m_SliceArray[i].texId = g_InvalidTexID;
m_SortedIdxArray[i] = i;
}
//return m_SliceArray != NULL && m_SortedIdxArray != NULL && numTextures > 0;
return numTextures > 0;
for (int i = 0; i < m_NumTextures; i++)
// should not really be used in general. Assuming lights are culled properly entries will automatically be replaced efficiently.
public void RemoveEntryFromSlice(Texture texture)
if (m_SliceArray[i].countLRU < g_MaxFrameCount) ++m_SliceArray[i].countLRU; // next frame
}
var texId = (uint)texture.GetInstanceID();
//for(int q=1; q<m_numTextures; q++)
// assert(m_SliceArray[m_SortedIdxArray[q-1]].CountLRU>=m_SliceArray[m_SortedIdxArray[q]].CountLRU);
}
//assert(TexID!=g_InvalidTexID);
if (texId == g_InvalidTexID) return;
protected TextureCache()
{
m_NumTextures = 0;
m_NumMipLevels = 0;
}
// search for existing copy
if (!m_LocatorInSliceArray.ContainsKey(texId))
return;
public virtual void TransferToSlice(int sliceIndex, Texture texture)
{
}
var sliceIndex = m_LocatorInSliceArray[texId];
public virtual Texture GetTexCache()
{
return null;
}
protected bool AllocTextureArray(int numTextures)
{
if (numTextures > 0)
{
m_SliceArray = new SSliceEntry[numTextures];
m_SortedIdxArray = new int[numTextures];
m_LocatorInSliceArray = new Dictionary<uint, int>();
//assert(m_SliceArray[sliceIndex].TexID==TexID);
m_NumTextures = numTextures;
for (int i = 0; i < m_NumTextures; i++)
// locate entry sorted by uCountLRU in m_pSortedIdxArray
var foundIdxSortLRU = false;
var i = 0;
while ((!foundIdxSortLRU) && i < m_NumTextures)
m_SliceArray[i].countLRU = g_MaxFrameCount; // never used before
m_SliceArray[i].texId = g_InvalidTexID;
m_SortedIdxArray[i] = i;
if (m_SortedIdxArray[i] == sliceIndex) foundIdxSortLRU = true;
else ++i;
}
//return m_SliceArray != NULL && m_SortedIdxArray != NULL && numTextures > 0;
return numTextures > 0;
}
if (!foundIdxSortLRU)
return;
// should not really be used in general. Assuming lights are culled properly entries will automatically be replaced efficiently.
public void RemoveEntryFromSlice(Texture texture)
{
var texId = (uint)texture.GetInstanceID();
// relocate sliceIndex to front of m_pSortedIdxArray since uCountLRU will be set to maximum.
for (int j = 0; j < i; j++)
{
m_SortedIdxArray[j + 1] = m_SortedIdxArray[j];
}
m_SortedIdxArray[0] = sliceIndex;
//assert(TexID!=g_InvalidTexID);
if (texId == g_InvalidTexID) return;
// search for existing copy
if (!m_LocatorInSliceArray.ContainsKey(texId))
return;
var sliceIndex = m_LocatorInSliceArray[texId];
//assert(m_SliceArray[sliceIndex].TexID==TexID);
// delete from m_locatorInSliceArray and m_pSliceArray.
m_LocatorInSliceArray.Remove(texId);
m_SliceArray[sliceIndex].countLRU = g_MaxFrameCount; // never used before
m_SliceArray[sliceIndex].texId = g_InvalidTexID;
}
// locate entry sorted by uCountLRU in m_pSortedIdxArray
var foundIdxSortLRU = false;
var i = 0;
while ((!foundIdxSortLRU) && i < m_NumTextures)
protected int GetNumMips(int width, int height)
if (m_SortedIdxArray[i] == sliceIndex) foundIdxSortLRU = true;
else ++i;
return GetNumMips(width > height ? width : height);
if (!foundIdxSortLRU)
return;
// relocate sliceIndex to front of m_pSortedIdxArray since uCountLRU will be set to maximum.
for (int j = 0; j < i; j++)
protected int GetNumMips(int dim)
m_SortedIdxArray[j + 1] = m_SortedIdxArray[j];
var uDim = (uint)dim;
var iNumMips = 0;
while (uDim > 0)
{ ++iNumMips; uDim >>= 1; }
return iNumMips;
m_SortedIdxArray[0] = sliceIndex;
// delete from m_locatorInSliceArray and m_pSliceArray.
m_LocatorInSliceArray.Remove(texId);
m_SliceArray[sliceIndex].countLRU = g_MaxFrameCount; // never used before
m_SliceArray[sliceIndex].texId = g_InvalidTexID;
}
protected int GetNumMips(int width, int height)
{
return GetNumMips(width > height ? width : height);
}
protected int GetNumMips(int dim)
{
var uDim = (uint)dim;
var iNumMips = 0;
while (uDim > 0)
{ ++iNumMips; uDim >>= 1; }
return iNumMips;
}
}
正在加载...
取消
保存