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
 | |
|     }
 | |
| }
 | 
