You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
5.9 KiB
183 lines
5.9 KiB
// |
|
// 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 |
|
} |
|
}
|
|
|