184 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			184 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|   | // | ||
|  | // Kino/Bloom v2 - Bloom filter for Unity | ||
|  | // | ||
|  | // Copyright (C) 2015, 2016 Keijiro Takahashi | ||
|  | // | ||
|  | // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
|  | // of this software and associated documentation files (the "Software"), to deal | ||
|  | // in the Software without restriction, including without limitation the rights | ||
|  | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
|  | // copies of the Software, and to permit persons to whom the Software is | ||
|  | // furnished to do so, subject to the following conditions: | ||
|  | // | ||
|  | // The above copyright notice and this permission notice shall be included in | ||
|  | // all copies or substantial portions of the Software. | ||
|  | // | ||
|  | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
|  | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
|  | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
|  | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
|  | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
|  | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
|  | // THE SOFTWARE. | ||
|  | // | ||
|  | using UnityEngine; | ||
|  | using UnityEditor; | ||
|  | 
 | ||
|  | namespace Kino | ||
|  | { | ||
|  |     // Class used for drawing the brightness response curve | ||
|  |     public class BloomGraphDrawer | ||
|  |     { | ||
|  |         #region Public Methods | ||
|  | 
 | ||
|  |         // Update internal state with a given bloom instance. | ||
|  |         public void Prepare(Bloom bloom) | ||
|  |         { | ||
|  |             #if UNITY_5_6_OR_NEWER | ||
|  |             if (bloom.GetComponent<Camera>().allowHDR) | ||
|  |             #else | ||
|  |             if (bloom.GetComponent<Camera>().hdr) | ||
|  |             #endif | ||
|  |             { | ||
|  |                 _rangeX = 6; | ||
|  |                 _rangeY = 1.5f; | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  |                 _rangeX = 1; | ||
|  |                 _rangeY = 1; | ||
|  |             } | ||
|  | 
 | ||
|  |             _threshold = bloom.thresholdLinear; | ||
|  |             _knee = bloom.softKnee * _threshold + 1e-5f; | ||
|  | 
 | ||
|  |             // Intensity is capped to prevent sampling errors. | ||
|  |             _intensity = Mathf.Min(bloom.intensity, 10); | ||
|  |         } | ||
|  | 
 | ||
|  |         // Draw the graph at the current position. | ||
|  |         public void DrawGraph() | ||
|  |         { | ||
|  |             _rectGraph = GUILayoutUtility.GetRect(128, 80); | ||
|  | 
 | ||
|  |             // Background | ||
|  |             DrawRect(0, 0, _rangeX, _rangeY, 0.1f, 0.4f); | ||
|  | 
 | ||
|  |             // Soft-knee range | ||
|  |             DrawRect(_threshold - _knee, 0, _threshold + _knee, _rangeY, 0.25f, -1); | ||
|  | 
 | ||
|  |             // Horizontal lines | ||
|  |             for (var i = 1; i < _rangeY; i++) | ||
|  |                 DrawLine(0, i, _rangeX, i, 0.4f); | ||
|  | 
 | ||
|  |             // Vertical lines | ||
|  |             for (var i = 1; i < _rangeX; i++) | ||
|  |                 DrawLine(i, 0, i, _rangeY, 0.4f); | ||
|  | 
 | ||
|  |             // Label | ||
|  |             Handles.Label( | ||
|  |                 PointInRect(0, _rangeY) + Vector3.right, | ||
|  |                 "Brightness Response (linear)", EditorStyles.miniLabel | ||
|  |             ); | ||
|  | 
 | ||
|  |             // Threshold line | ||
|  |             DrawLine(_threshold, 0, _threshold, _rangeY, 0.6f); | ||
|  | 
 | ||
|  |             // Response curve | ||
|  |             var vcount = 0; | ||
|  |             while (vcount < _curveResolution) | ||
|  |             { | ||
|  |                 var x = _rangeX * vcount / (_curveResolution - 1); | ||
|  |                 var y = ResponseFunction(x); | ||
|  |                 if (y < _rangeY) | ||
|  |                 { | ||
|  |                     _curveVertices[vcount++] = PointInRect(x, y); | ||
|  |                 } | ||
|  |                 else | ||
|  |                 { | ||
|  |                     if (vcount > 1) | ||
|  |                     { | ||
|  |                         // Extend the last segment to the top edge of the rect. | ||
|  |                         var v1 = _curveVertices[vcount - 2]; | ||
|  |                         var v2 = _curveVertices[vcount - 1]; | ||
|  |                         var clip = (_rectGraph.y - v1.y) / (v2.y - v1.y); | ||
|  |                         _curveVertices[vcount - 1] = v1 + (v2 - v1) * clip; | ||
|  |                     } | ||
|  |                     break; | ||
|  |                 } | ||
|  |             } | ||
|  | 
 | ||
|  |             if (vcount > 1) | ||
|  |             { | ||
|  |                 Handles.color = Color.white * 0.9f; | ||
|  |                 Handles.DrawAAPolyLine(2.0f, vcount, _curveVertices); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         #endregion | ||
|  | 
 | ||
|  |         #region Response Function | ||
|  | 
 | ||
|  |         float _threshold; | ||
|  |         float _knee; | ||
|  |         float _intensity; | ||
|  | 
 | ||
|  |         float ResponseFunction(float x) | ||
|  |         { | ||
|  |             var rq = Mathf.Clamp(x - _threshold + _knee, 0, _knee * 2); | ||
|  |             rq = rq * rq * 0.25f / _knee; | ||
|  |             return Mathf.Max(rq, x - _threshold) * _intensity; | ||
|  |         } | ||
|  | 
 | ||
|  |         #endregion | ||
|  | 
 | ||
|  |         #region Graph Functions | ||
|  | 
 | ||
|  |         // Number of vertices in curve | ||
|  |         const int _curveResolution = 96; | ||
|  | 
 | ||
|  |         // Vertex buffers | ||
|  |         Vector3[] _rectVertices = new Vector3[4]; | ||
|  |         Vector3[] _lineVertices = new Vector3[2]; | ||
|  |         Vector3[] _curveVertices = new Vector3[_curveResolution]; | ||
|  | 
 | ||
|  |         Rect _rectGraph; | ||
|  |         float _rangeX; | ||
|  |         float _rangeY; | ||
|  | 
 | ||
|  |         // Transform a point into the graph rect. | ||
|  |         Vector3 PointInRect(float x, float y) | ||
|  |         { | ||
|  |             x = Mathf.Lerp(_rectGraph.x, _rectGraph.xMax, x / _rangeX); | ||
|  |             y = Mathf.Lerp(_rectGraph.yMax, _rectGraph.y, y / _rangeY); | ||
|  |             return new Vector3(x, y, 0); | ||
|  |         } | ||
|  | 
 | ||
|  |         // Draw a line in the graph rect. | ||
|  |         void DrawLine(float x1, float y1, float x2, float y2, float grayscale) | ||
|  |         { | ||
|  |             _lineVertices[0] = PointInRect(x1, y1); | ||
|  |             _lineVertices[1] = PointInRect(x2, y2); | ||
|  |             Handles.color = Color.white * grayscale; | ||
|  |             Handles.DrawAAPolyLine(2.0f, _lineVertices); | ||
|  |         } | ||
|  | 
 | ||
|  |         // Draw a rect in the graph rect. | ||
|  |         void DrawRect(float x1, float y1, float x2, float y2, float fill, float line) | ||
|  |         { | ||
|  |             _rectVertices[0] = PointInRect(x1, y1); | ||
|  |             _rectVertices[1] = PointInRect(x2, y1); | ||
|  |             _rectVertices[2] = PointInRect(x2, y2); | ||
|  |             _rectVertices[3] = PointInRect(x1, y2); | ||
|  | 
 | ||
|  |             Handles.DrawSolidRectangleWithOutline( | ||
|  |                 _rectVertices, | ||
|  |                 fill < 0 ? Color.clear : Color.white * fill, | ||
|  |                 line < 0 ? Color.clear : Color.white * line | ||
|  |             ); | ||
|  |         } | ||
|  | 
 | ||
|  |         #endregion | ||
|  |     } | ||
|  | } |