private void OnEnable() { _diffusionTexture = PaintUtils.GenerateDiffusionTexture(); }
private void DrawStroke(RenderTexture targetTexture, PaintParameters current, float textureScale = 1f) { var previous = _lastParameters.Count > 0 ? _lastParameters[0] : current; var last = _lastParameters.Count > 1 ? _lastParameters[1] : previous; bool hasMoved = _lastParameters.Count > 0; var actualSpeed = Vector2.Distance(current.Position, previous.Position) / (Time.deltaTime * 1000f); // Smooth speed: current.Speed = Mathf.Lerp(previous.Speed, actualSpeed, 0.2f); var brushSize = current.BrushSize; float angle = Angle; float roundness = Roundness; if (BrushTexture != null) { BrushMaterial.EnableKeyword("USE_TEXTURE"); } else { BrushMaterial.DisableKeyword("USE_TEXTURE"); } BrushMaterial.SetFloat("_Hardness", BrushHardness); var brushTexture = BrushTexture != null ? BrushTexture : Texture2D.whiteTexture; var positionOffset = Vector2.zero; if (current.IsPen) { var tilt = current.Tilt; //var azimuth = Mathf.Atan2(tilt.y, tilt.x); var length = Mathf.Clamp01(tilt.magnitude); var altitude = Mathf.Atan2(1f - length, length); //angle = azimuth * Mathf.Rad2Deg; var brushAngle = 1f - altitude / (Mathf.PI * 0.5f); // scale brush none linearly: roundness = 1f + Mathf.Pow(brushAngle, 4f) * MaxBrushScaleFromTilt; positionOffset = new Vector2(tilt.x, -tilt.y) * brushSize * 0.4f; } var startPosition = previous.Position; var endPosition = current.Position; var startPressure = previous.Pressure; var endPressure = current.Pressure; var distance = Vector2.Distance(endPosition, startPosition); var absoluteBrushDistance = Mathf.Max(1f, brushSize * BrushSpacing); if (hasMoved && distance < absoluteBrushDistance) { return; } var tangent = (startPosition - last.Position).normalized; var normal = new Vector2(tangent.y, -tangent.x); var control = startPosition + tangent * (distance * 0.3f); RenderTexture.active = targetTexture; GL.PushMatrix(); GL.LoadPixelMatrix(0, targetTexture.width, 0, targetTexture.height); Vector2 pos = endPosition; foreach (float t in PaintUtils.DrawLine(startPosition, endPosition, absoluteBrushDistance)) { if (hasMoved && t == 0f) { continue; } pos = QuadraticInterpolation ? PaintUtils.PointOnQuadraticCurve(startPosition, control, endPosition, t) : Vector2.LerpUnclamped(startPosition, endPosition, t); var pressure = Mathf.Lerp(startPressure, endPressure, t); var speed = Mathf.Lerp(previous.Speed, current.Speed, t); var modifiedBrushSize = brushSize * Mathf.Lerp(1f, pressure, PenPressureInfluence) * (1f + Random.Range(-1f, 1f) * SizeJitter) * Mathf.Lerp(1f, 1f / (1f + speed), StrokeSpeedInfluence); angle = Angle + Mathf.Lerp(0f, Random.Range(-180f, 180f), AngleJitter); var localBrushRotation = Quaternion.Euler(0, 0, -angle); roundness = Mathf.Clamp01(Roundness + Random.Range(-1f, 1f) * RoundnessJitter); var offset = normal * (Random.Range(-1f, 1f) * modifiedBrushSize * Scatter) + positionOffset; var posOnTexture = (pos + offset) * textureScale; var sizeOnTexture = modifiedBrushSize * textureScale; var matrix = Matrix4x4.TRS(posOnTexture, localBrushRotation, new Vector3(roundness, 1f, 1f)) * Matrix4x4.TRS(-posOnTexture, Quaternion.identity, Vector3.one); GL.MultMatrix(matrix); var color = UseOwnColor ? Color : current.Color; color.a = Mathf.Clamp01(Flow + Random.Range(-1f, 1f) * FlowJitter); BrushMaterial.color = color; var rect = new Rect( posOnTexture.x - 0.5f * sizeOnTexture, posOnTexture.y - 0.5f * sizeOnTexture, sizeOnTexture, sizeOnTexture); Graphics.DrawTexture(rect, brushTexture, BrushMaterial); } if (_lastParameters.Count > 1) { _lastParameters.RemoveAt(1); } current.Position = pos; _lastParameters.Insert(0, current); GL.PopMatrix(); RenderTexture.active = null; }