Unity_1lab/1 laba/Assets/furniture/BK_AlchemistHouse/Scripts/VolumetricLightRenderer.cs
lapich_valya ba035efa87 models
добавила модели, текстуры стен, пола
2025-09-18 12:50:59 +03:00

683 lines
26 KiB
C#

// Copyright(c) 2016, Michal Skalsky
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT
// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using UnityEngine;
using System.Collections;
using UnityEngine.Rendering;
using System;
[RequireComponent(typeof(Camera))]
public class VolumetricLightRenderer : MonoBehaviour
{
public enum VolumtericResolution
{
Full,
Half,
Quarter
};
public static event Action<VolumetricLightRenderer, Matrix4x4> PreRenderEvent;
private static Mesh _pointLightMesh;
private static Mesh _spotLightMesh;
private static Material _lightMaterial;
private Camera _camera;
private CommandBuffer _preLightPass;
private Matrix4x4 _viewProj;
private Material _blitAddMaterial;
private Material _bilateralBlurMaterial;
private RenderTexture _volumeLightTexture;
private RenderTexture _halfVolumeLightTexture;
private RenderTexture _quarterVolumeLightTexture;
private static Texture _defaultSpotCookie;
private RenderTexture _halfDepthBuffer;
private RenderTexture _quarterDepthBuffer;
private VolumtericResolution _currentResolution = VolumtericResolution.Half;
private Texture2D _ditheringTexture;
private Texture3D _noiseTexture;
public VolumtericResolution Resolution = VolumtericResolution.Half;
public Texture DefaultSpotCookie;
public CommandBuffer GlobalCommandBuffer { get { return _preLightPass; } }
/// <summary>
///
/// </summary>
/// <returns></returns>
public static Material GetLightMaterial()
{
return _lightMaterial;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public static Mesh GetPointLightMesh()
{
return _pointLightMesh;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public static Mesh GetSpotLightMesh()
{
return _spotLightMesh;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public RenderTexture GetVolumeLightBuffer()
{
if (Resolution == VolumtericResolution.Quarter)
return _quarterVolumeLightTexture;
else if (Resolution == VolumtericResolution.Half)
return _halfVolumeLightTexture;
else
return _volumeLightTexture;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public RenderTexture GetVolumeLightDepthBuffer()
{
if (Resolution == VolumtericResolution.Quarter)
return _quarterDepthBuffer;
else if (Resolution == VolumtericResolution.Half)
return _halfDepthBuffer;
else
return null;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public static Texture GetDefaultSpotCookie()
{
return _defaultSpotCookie;
}
/// <summary>
///
/// </summary>
void Awake()
{
_camera = GetComponent<Camera>();
if (_camera.actualRenderingPath == RenderingPath.Forward)
_camera.depthTextureMode = DepthTextureMode.Depth;
_currentResolution = Resolution;
Shader shader = Shader.Find("Hidden/BlitAdd");
if (shader == null)
throw new Exception("Critical Error: \"Hidden/BlitAdd\" shader is missing. Make sure it is included in \"Always Included Shaders\" in ProjectSettings/Graphics.");
_blitAddMaterial = new Material(shader);
shader = Shader.Find("Hidden/BilateralBlur");
if (shader == null)
throw new Exception("Critical Error: \"Hidden/BilateralBlur\" shader is missing. Make sure it is included in \"Always Included Shaders\" in ProjectSettings/Graphics.");
_bilateralBlurMaterial = new Material(shader);
_preLightPass = new CommandBuffer();
_preLightPass.name = "PreLight";
ChangeResolution();
if (_pointLightMesh == null)
{
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
_pointLightMesh = go.GetComponent<MeshFilter>().sharedMesh;
Destroy(go);
}
if (_spotLightMesh == null)
{
_spotLightMesh = CreateSpotLightMesh();
}
if (_lightMaterial == null)
{
shader = Shader.Find("Sandbox/VolumetricLight");
if (shader == null)
throw new Exception("Critical Error: \"Sandbox/VolumetricLight\" shader is missing. Make sure it is included in \"Always Included Shaders\" in ProjectSettings/Graphics.");
_lightMaterial = new Material(shader);
}
if (_defaultSpotCookie == null)
{
_defaultSpotCookie = DefaultSpotCookie;
}
LoadNoise3dTexture();
GenerateDitherTexture();
}
/// <summary>
///
/// </summary>
void OnEnable()
{
//_camera.RemoveAllCommandBuffers();
if(_camera.actualRenderingPath == RenderingPath.Forward)
_camera.AddCommandBuffer(CameraEvent.AfterDepthTexture, _preLightPass);
else
_camera.AddCommandBuffer(CameraEvent.BeforeLighting, _preLightPass);
}
/// <summary>
///
/// </summary>
void OnDisable()
{
//_camera.RemoveAllCommandBuffers();
if(_camera.actualRenderingPath == RenderingPath.Forward)
_camera.RemoveCommandBuffer(CameraEvent.AfterDepthTexture, _preLightPass);
else
_camera.RemoveCommandBuffer(CameraEvent.BeforeLighting, _preLightPass);
}
/// <summary>
///
/// </summary>
void ChangeResolution()
{
int width = _camera.pixelWidth;
int height = _camera.pixelHeight;
if (_volumeLightTexture != null)
Destroy(_volumeLightTexture);
_volumeLightTexture = new RenderTexture(width, height, 0, RenderTextureFormat.ARGBHalf);
_volumeLightTexture.name = "VolumeLightBuffer";
_volumeLightTexture.filterMode = FilterMode.Bilinear;
if (_halfDepthBuffer != null)
Destroy(_halfDepthBuffer);
if (_halfVolumeLightTexture != null)
Destroy(_halfVolumeLightTexture);
if (Resolution == VolumtericResolution.Half || Resolution == VolumtericResolution.Quarter)
{
_halfVolumeLightTexture = new RenderTexture(width / 2, height / 2, 0, RenderTextureFormat.ARGBHalf);
_halfVolumeLightTexture.name = "VolumeLightBufferHalf";
_halfVolumeLightTexture.filterMode = FilterMode.Bilinear;
_halfDepthBuffer = new RenderTexture(width / 2, height / 2, 0, RenderTextureFormat.RFloat);
_halfDepthBuffer.name = "VolumeLightHalfDepth";
_halfDepthBuffer.Create();
_halfDepthBuffer.filterMode = FilterMode.Point;
}
if (_quarterVolumeLightTexture != null)
Destroy(_quarterVolumeLightTexture);
if (_quarterDepthBuffer != null)
Destroy(_quarterDepthBuffer);
if (Resolution == VolumtericResolution.Quarter)
{
_quarterVolumeLightTexture = new RenderTexture(width / 4, height / 4, 0, RenderTextureFormat.ARGBHalf);
_quarterVolumeLightTexture.name = "VolumeLightBufferQuarter";
_quarterVolumeLightTexture.filterMode = FilterMode.Bilinear;
_quarterDepthBuffer = new RenderTexture(width / 4, height / 4, 0, RenderTextureFormat.RFloat);
_quarterDepthBuffer.name = "VolumeLightQuarterDepth";
_quarterDepthBuffer.Create();
_quarterDepthBuffer.filterMode = FilterMode.Point;
}
}
/// <summary>
///
/// </summary>
public void OnPreRender()
{
// use very low value for near clip plane to simplify cone/frustum intersection
Matrix4x4 proj = Matrix4x4.Perspective(_camera.fieldOfView, _camera.aspect, 0.01f, _camera.farClipPlane);
proj = GL.GetGPUProjectionMatrix(proj, true);
_viewProj = proj * _camera.worldToCameraMatrix;
_preLightPass.Clear();
bool dx11 = SystemInfo.graphicsShaderLevel > 40;
if (Resolution == VolumtericResolution.Quarter)
{
Texture nullTexture = null;
// down sample depth to half res
_preLightPass.Blit(nullTexture, _halfDepthBuffer, _bilateralBlurMaterial, dx11 ? 4 : 10);
// down sample depth to quarter res
_preLightPass.Blit(nullTexture, _quarterDepthBuffer, _bilateralBlurMaterial, dx11 ? 6 : 11);
_preLightPass.SetRenderTarget(_quarterVolumeLightTexture);
}
else if (Resolution == VolumtericResolution.Half)
{
Texture nullTexture = null;
// down sample depth to half res
_preLightPass.Blit(nullTexture, _halfDepthBuffer, _bilateralBlurMaterial, dx11 ? 4 : 10);
_preLightPass.SetRenderTarget(_halfVolumeLightTexture);
}
else
{
_preLightPass.SetRenderTarget(_volumeLightTexture);
}
_preLightPass.ClearRenderTarget(false, true, new Color(0, 0, 0, 1));
UpdateMaterialParameters();
if (PreRenderEvent != null)
PreRenderEvent(this, _viewProj);
}
[ImageEffectOpaque]
public void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (Resolution == VolumtericResolution.Quarter)
{
RenderTexture temp = RenderTexture.GetTemporary(_quarterDepthBuffer.width, _quarterDepthBuffer.height, 0, RenderTextureFormat.ARGBHalf);
temp.filterMode = FilterMode.Bilinear;
// horizontal bilateral blur at quarter res
Graphics.Blit(_quarterVolumeLightTexture, temp, _bilateralBlurMaterial, 8);
// vertical bilateral blur at quarter res
Graphics.Blit(temp, _quarterVolumeLightTexture, _bilateralBlurMaterial, 9);
// upscale to full res
Graphics.Blit(_quarterVolumeLightTexture, _volumeLightTexture, _bilateralBlurMaterial, 7);
RenderTexture.ReleaseTemporary(temp);
}
else if (Resolution == VolumtericResolution.Half)
{
RenderTexture temp = RenderTexture.GetTemporary(_halfVolumeLightTexture.width, _halfVolumeLightTexture.height, 0, RenderTextureFormat.ARGBHalf);
temp.filterMode = FilterMode.Bilinear;
// horizontal bilateral blur at half res
Graphics.Blit(_halfVolumeLightTexture, temp, _bilateralBlurMaterial, 2);
// vertical bilateral blur at half res
Graphics.Blit(temp, _halfVolumeLightTexture, _bilateralBlurMaterial, 3);
// upscale to full res
Graphics.Blit(_halfVolumeLightTexture, _volumeLightTexture, _bilateralBlurMaterial, 5);
RenderTexture.ReleaseTemporary(temp);
}
else
{
RenderTexture temp = RenderTexture.GetTemporary(_volumeLightTexture.width, _volumeLightTexture.height, 0, RenderTextureFormat.ARGBHalf);
temp.filterMode = FilterMode.Bilinear;
// horizontal bilateral blur at full res
Graphics.Blit(_volumeLightTexture, temp, _bilateralBlurMaterial, 0);
// vertical bilateral blur at full res
Graphics.Blit(temp, _volumeLightTexture, _bilateralBlurMaterial, 1);
RenderTexture.ReleaseTemporary(temp);
}
// add volume light buffer to rendered scene
_blitAddMaterial.SetTexture("_Source", source);
Graphics.Blit(_volumeLightTexture, destination, _blitAddMaterial, 0);
}
private void UpdateMaterialParameters()
{
_bilateralBlurMaterial.SetTexture("_HalfResDepthBuffer", _halfDepthBuffer);
_bilateralBlurMaterial.SetTexture("_HalfResColor", _halfVolumeLightTexture);
_bilateralBlurMaterial.SetTexture("_QuarterResDepthBuffer", _quarterDepthBuffer);
_bilateralBlurMaterial.SetTexture("_QuarterResColor", _quarterVolumeLightTexture);
Shader.SetGlobalTexture("_DitherTexture", _ditheringTexture);
Shader.SetGlobalTexture("_NoiseTexture", _noiseTexture);
}
/// <summary>
///
/// </summary>
void Update()
{
//#if UNITY_EDITOR
if (_currentResolution != Resolution)
{
_currentResolution = Resolution;
ChangeResolution();
}
if ((_volumeLightTexture.width != _camera.pixelWidth || _volumeLightTexture.height != _camera.pixelHeight))
ChangeResolution();
//#endif
}
/// <summary>
///
/// </summary>
void LoadNoise3dTexture()
{
// basic dds loader for 3d texture - !not very robust!
TextAsset data = Resources.Load("NoiseVolume") as TextAsset;
byte[] bytes = data.bytes;
uint height = BitConverter.ToUInt32(data.bytes, 12);
uint width = BitConverter.ToUInt32(data.bytes, 16);
uint pitch = BitConverter.ToUInt32(data.bytes, 20);
uint depth = BitConverter.ToUInt32(data.bytes, 24);
uint formatFlags = BitConverter.ToUInt32(data.bytes, 20 * 4);
// uint fourCC = BitConverter.ToUInt32(data.bytes, 21 * 4);
uint bitdepth = BitConverter.ToUInt32(data.bytes, 22 * 4);
if (bitdepth == 0)
bitdepth = pitch / width * 8;
// doesn't work with TextureFormat.Alpha8 for some reason
_noiseTexture = new Texture3D((int)width, (int)height, (int)depth, TextureFormat.RGBA32, false);
_noiseTexture.name = "3D Noise";
Color[] c = new Color[width * height * depth];
uint index = 128;
if (data.bytes[21 * 4] == 'D' && data.bytes[21 * 4 + 1] == 'X' && data.bytes[21 * 4 + 2] == '1' && data.bytes[21 * 4 + 3] == '0' &&
(formatFlags & 0x4) != 0)
{
uint format = BitConverter.ToUInt32(data.bytes, (int)index);
if (format >= 60 && format <= 65)
bitdepth = 8;
else if (format >= 48 && format <= 52)
bitdepth = 16;
else if (format >= 27 && format <= 32)
bitdepth = 32;
//Debug.Log("DXGI format: " + format);
// dx10 format, skip dx10 header
//Debug.Log("DX10 format");
index += 20;
}
uint byteDepth = bitdepth / 8;
pitch = (width * bitdepth + 7) / 8;
for (int d = 0; d < depth; ++d)
{
//index = 128;
for (int h = 0; h < height; ++h)
{
for (int w = 0; w < width; ++w)
{
float v = (bytes[index + w * byteDepth] / 255.0f);
c[w + h * width + d * width * height] = new Color(v, v, v, v);
}
index += pitch;
}
}
_noiseTexture.SetPixels(c);
_noiseTexture.Apply();
}
/// <summary>
///
/// </summary>
private void GenerateDitherTexture()
{
if (_ditheringTexture != null)
{
return;
}
int size = 8;
#if DITHER_4_4
size = 4;
#endif
// again, I couldn't make it work with Alpha8
_ditheringTexture = new Texture2D(size, size, TextureFormat.Alpha8, false, true);
_ditheringTexture.filterMode = FilterMode.Point;
Color32[] c = new Color32[size * size];
byte b;
#if DITHER_4_4
b = (byte)(0.0f / 16.0f * 255); c[0] = new Color32(b, b, b, b);
b = (byte)(8.0f / 16.0f * 255); c[1] = new Color32(b, b, b, b);
b = (byte)(2.0f / 16.0f * 255); c[2] = new Color32(b, b, b, b);
b = (byte)(10.0f / 16.0f * 255); c[3] = new Color32(b, b, b, b);
b = (byte)(12.0f / 16.0f * 255); c[4] = new Color32(b, b, b, b);
b = (byte)(4.0f / 16.0f * 255); c[5] = new Color32(b, b, b, b);
b = (byte)(14.0f / 16.0f * 255); c[6] = new Color32(b, b, b, b);
b = (byte)(6.0f / 16.0f * 255); c[7] = new Color32(b, b, b, b);
b = (byte)(3.0f / 16.0f * 255); c[8] = new Color32(b, b, b, b);
b = (byte)(11.0f / 16.0f * 255); c[9] = new Color32(b, b, b, b);
b = (byte)(1.0f / 16.0f * 255); c[10] = new Color32(b, b, b, b);
b = (byte)(9.0f / 16.0f * 255); c[11] = new Color32(b, b, b, b);
b = (byte)(15.0f / 16.0f * 255); c[12] = new Color32(b, b, b, b);
b = (byte)(7.0f / 16.0f * 255); c[13] = new Color32(b, b, b, b);
b = (byte)(13.0f / 16.0f * 255); c[14] = new Color32(b, b, b, b);
b = (byte)(5.0f / 16.0f * 255); c[15] = new Color32(b, b, b, b);
#else
int i = 0;
b = (byte)(1.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(49.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(13.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(61.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(4.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(52.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(16.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(64.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(33.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(17.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(45.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(29.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(36.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(20.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(48.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(32.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(9.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(57.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(5.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(53.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(12.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(60.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(8.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(56.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(41.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(25.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(37.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(21.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(44.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(28.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(40.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(24.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(3.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(51.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(15.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(63.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(2.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(50.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(14.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(62.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(35.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(19.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(47.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(31.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(34.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(18.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(46.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(30.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(11.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(59.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(7.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(55.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(10.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(58.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(6.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(54.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(43.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(27.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(39.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(23.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(42.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(26.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(38.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
b = (byte)(22.0f / 65.0f * 255); c[i++] = new Color32(b, b, b, b);
#endif
_ditheringTexture.SetPixels32(c);
_ditheringTexture.Apply();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private Mesh CreateSpotLightMesh()
{
// copy & pasted from other project, the geometry is too complex, should be simplified
Mesh mesh = new Mesh();
const int segmentCount = 16;
Vector3[] vertices = new Vector3[2 + segmentCount * 3];
Color32[] colors = new Color32[2 + segmentCount * 3];
vertices[0] = new Vector3(0, 0, 0);
vertices[1] = new Vector3(0, 0, 1);
float angle = 0;
float step = Mathf.PI * 2.0f / segmentCount;
float ratio = 0.9f;
for (int i = 0; i < segmentCount; ++i)
{
vertices[i + 2] = new Vector3(-Mathf.Cos(angle) * ratio, Mathf.Sin(angle) * ratio, ratio);
colors[i + 2] = new Color32(255, 255, 255, 255);
vertices[i + 2 + segmentCount] = new Vector3(-Mathf.Cos(angle), Mathf.Sin(angle), 1);
colors[i + 2 + segmentCount] = new Color32(255, 255, 255, 0);
vertices[i + 2 + segmentCount * 2] = new Vector3(-Mathf.Cos(angle) * ratio, Mathf.Sin(angle) * ratio, 1);
colors[i + 2 + segmentCount * 2] = new Color32(255, 255, 255, 255);
angle += step;
}
mesh.vertices = vertices;
mesh.colors32 = colors;
int[] indices = new int[segmentCount * 3 * 2 + segmentCount * 6 * 2];
int index = 0;
for (int i = 2; i < segmentCount + 1; ++i)
{
indices[index++] = 0;
indices[index++] = i;
indices[index++] = i + 1;
}
indices[index++] = 0;
indices[index++] = segmentCount + 1;
indices[index++] = 2;
for (int i = 2; i < segmentCount + 1; ++i)
{
indices[index++] = i;
indices[index++] = i + segmentCount;
indices[index++] = i + 1;
indices[index++] = i + 1;
indices[index++] = i + segmentCount;
indices[index++] = i + segmentCount + 1;
}
indices[index++] = 2;
indices[index++] = 1 + segmentCount;
indices[index++] = 2 + segmentCount;
indices[index++] = 2 + segmentCount;
indices[index++] = 1 + segmentCount;
indices[index++] = 1 + segmentCount + segmentCount;
//------------
for (int i = 2 + segmentCount; i < segmentCount + 1 + segmentCount; ++i)
{
indices[index++] = i;
indices[index++] = i + segmentCount;
indices[index++] = i + 1;
indices[index++] = i + 1;
indices[index++] = i + segmentCount;
indices[index++] = i + segmentCount + 1;
}
indices[index++] = 2 + segmentCount;
indices[index++] = 1 + segmentCount * 2;
indices[index++] = 2 + segmentCount * 2;
indices[index++] = 2 + segmentCount * 2;
indices[index++] = 1 + segmentCount * 2;
indices[index++] = 1 + segmentCount * 3;
////-------------------------------------
for (int i = 2 + segmentCount * 2; i < segmentCount * 3 + 1; ++i)
{
indices[index++] = 1;
indices[index++] = i + 1;
indices[index++] = i;
}
indices[index++] = 1;
indices[index++] = 2 + segmentCount * 2;
indices[index++] = segmentCount * 3 + 1;
mesh.triangles = indices;
mesh.RecalculateBounds();
return mesh;
}
}