public static void Paint(PaintCommand.WorldSpace command) { Brush br = command.Brush; Stroke st = command.Stroke; br.GetBlitMode(false).PrePaint(command); PrepareSphereBrush(command); TexMGMT.brushRenderer.Prepare(command); TexMGMT.Render(); br.GetBrushType(false).AfterStroke(command); }
public override void PaintRenderTexture(PlaytimePainter pntr, BrushConfig br, StrokeVector st) { ImageData id = pntr.ImgData; BeforeStroke(pntr, br, st); PrepareSphereBrush(id, br, st, pntr); if (!st.mouseDwn) { TexMGMT.brushRendy.UseMeshAsBrush(pntr); TexMGMT.Render(); } AfterStroke(pntr, br, st); }
private static void PrepareSphereBrush(TextureMeta id, BrushConfig br, StrokeVector stroke, out bool alphaBuffer, PlaytimePainter painter = null) { // if (stroke.mouseDwn) // stroke.posFrom = stroke.posTo; TexMGMT.SHADER_STROKE_SEGMENT_UPDATE(br, br.Speed * 0.05f, id, stroke, out alphaBuffer, painter); var offset = id.offset - stroke.unRepeatedUv.Floor(); stroke.SetWorldPosInShader(); PainterShaderVariables.BRUSH_EDITED_UV_OFFSET.GlobalValue = new Vector4(id.tiling.x, id.tiling.y, offset.x, offset.y); PainterShaderVariables.BRUSH_ATLAS_SECTION_AND_ROWS.GlobalValue = new Vector4(0, 0, 1, 0); }
public static void PaintAtlased(RenderTexture rt, GameObject go, Mesh mesh, BrushConfig br, StrokeVector st, List <int> subMeshIndex, int aTexturesInRow) { br.GetBlitMode(false).PrePaint(null, br, st); PainterDataAndConfig.BRUSH_ATLAS_SECTION_AND_ROWS.GlobalValue = new Vector4(0, 0, aTexturesInRow, 1); bool alphaBuffer; PrepareSphereBrush(rt.GetImgData(), br, st, null, out alphaBuffer); TexMGMT.brushRenderer.UseMeshAsBrush(go, mesh, subMeshIndex); TexMGMT.Render(); AfterStroke_NoPainter(br, alphaBuffer, rt); PainterDataAndConfig.BRUSH_ATLAS_SECTION_AND_ROWS.GlobalValue = new Vector4(0, 0, 1, 0); }
private void RenderTexture_To_Texture2D(Texture2D tex) { if (!texture2D) { return; } var rt = renderTexture; TexMGMT.TryApplyBufferChangesTo(this); if (!rt && TexMGMT.imgMetaUsingRendTex == this) { rt = RenderTextureBuffersManager.GetDownscaledBigRt(width, height); } //Graphics.CopyTexture(); if (!rt) { return; } tex.CopyFrom(rt); PixelsFromTexture2D(tex); var converted = false; if (PainterCamera.Inst.IsLinearColorSpace) { if (!tex.IsColorTexture()) { converted = true; PixelsToLinear(); } } if (converted) { SetAndApply(); } else { texture2D.Apply(true); } }
public override void PaintRenderTextureInWorldSpace(PaintCommand.WorldSpace command) //PlaytimePainter painter, Brush br, Stroke st) { var id = command.TextureData; //painter.TexMeta; BeforeStroke(command); //br, st, painter); //bool alphaBuffer; PrepareSphereBrush(command); //id, br, st, out alphaBuffer, painter); if (!command.Stroke.MouseDownEvent) { TexMGMT.brushRenderer.Prepare(command); TexMGMT.Render(); } AfterStroke(command); //painter, br, st, alphaBuffer, id); }
public override void PaintRenderTexture(PlaytimePainter painter, BrushConfig br, StrokeVector st) { var id = painter.TexMeta; BeforeStroke(br, st, painter); bool alphaBuffer; PrepareSphereBrush(id, br, st, out alphaBuffer, painter); if (!st.MouseDownEvent) { TexMGMT.brushRenderer.UseMeshAsBrush(painter); TexMGMT.Render(); } AfterStroke_Painter(painter, br, st, alphaBuffer, id); }
public virtual void AfterStroke(PlaytimePainter pntr, BrushConfig br, StrokeVector st) { pntr.AfterStroke(st); if (!br.IsSingleBufferBrush() && !br.IsA3Dbrush(pntr)) { TexMGMT.UpdateBufferSegment(); } if ((br.useMask) && (st.mouseUp) && (br.randomMaskOffset)) { br.maskOffset = new Vector2(UnityEngine.Random.Range(0f, 1f), UnityEngine.Random.Range(0f, 1f)); } foreach (var p in pntr.plugins) { p.AfterGPUStroke(pntr, br, st, this); } }
private static void PrepareSphereBrush(PaintCommand.WorldSpace command) { Brush br = command.Brush; var td = command.TextureData; // if (stroke.mouseDwn) // stroke.posFrom = stroke.posTo; command.strokeAlphaPortion = Mathf.Clamp01(br.Flow * 0.05f); TexMGMT.SHADER_STROKE_SEGMENT_UPDATE(command); // br, br.Speed * 0.05f, id, stroke, out alphaBuffer, painter); var offset = command.TextureData.offset - command.Stroke.unRepeatedUv.Floor(); command.Stroke.SetWorldPosInShader(); PainterShaderVariables.BRUSH_EDITED_UV_OFFSET.GlobalValue = new Vector4(td.tiling.x, td.tiling.y, offset.x, offset.y); PainterShaderVariables.BRUSH_ATLAS_SECTION_AND_ROWS.GlobalValue = new Vector4(0, 0, 1, 0); }
static void PrepareSphereBrush(ImageData id, BrushConfig br, StrokeVector stroke, PlaytimePainter pntr) { if (TexMGMT.BigRT_pair == null) { TexMGMT.UpdateBuffersState(); } if (stroke.mouseDwn) { stroke.posFrom = stroke.posTo; } TexMGMT.ShaderPrepareStroke(br, br.speed * 0.05f, id, stroke, null); Vector2 offset = id.offset - stroke.unRepeatedUV.Floor(); stroke.SetWorldPosInShader(); Shader.SetGlobalVector(PainterDataAndConfig.BRUSH_EDITED_UV_OFFSET, new Vector4(id.tiling.x, id.tiling.y, offset.x, offset.y)); Shader.SetGlobalVector(PainterDataAndConfig.BRUSH_ATLAS_SECTION_AND_ROWS, new Vector4(0, 0, 1, 0)); }
public virtual void AfterStroke(PaintCommand.UV command) { PaintCommand.ForPainterComponent painterCommand = command as PaintCommand.ForPainterComponent; Brush br = command.Brush; Stroke st = command.Stroke; TextureMeta id = command.TextureData; command.OnStrokeComplete(); if (br.useMask && st.MouseUpEvent && br.randomMaskOffset) { br.maskOffset = new Vector2(Random.Range(0f, 1f), Random.Range(0f, 1f)); } if (command.usedAlphaBuffer) { var sh = br.GetBlitMode(false).ShaderForAlphaBufferBlit; if (painterCommand == null || painterCommand.painter.NotUsingPreview) { TexMGMT.UpdateFromAlphaBuffer(id.CurrentRenderTexture(), sh); } else { TexMGMT.AlphaBufferSetDirtyBeforeRender(id, sh); } } else if (!br.IsSingleBufferBrush() && !command.Is3DBrush) { TexMGMT.UpdateBufferSegment(); } if (painterCommand != null) { foreach (var p in painterCommand.painter.Modules) { p.AfterGpuStroke(painterCommand); } } }
public virtual void PaintRenderTexture(TextureMeta textureMeta, BrushConfig br, StrokeVector st, PlaytimePainter painter = null) { BeforeStroke(br, st, painter); if (st.CrossedASeam()) { st.uvFrom = st.uvTo; } bool alphaBuffer; TexMGMT.SHADER_STROKE_SEGMENT_UPDATE(br, br.Speed * 0.05f, textureMeta, st, out alphaBuffer, painter); var rb = RtBrush; rb.localScale = Vector3.one; var direction = st.DeltaUv; var length = direction.magnitude; BrushMesh = PainterCamera.BrushMeshGenerator.GetLongMesh(length * 256, br.StrokeWidth(textureMeta.width, false)); rb.localRotation = Quaternion.Euler(new Vector3(0, 0, (direction.x > 0 ? -1 : 1) * Vector2.Angle(Vector2.up, direction))); rb.localPosition = StrokeVector.BrushWorldPositionFrom((st.uvFrom + st.uvTo) * 0.5f); TexMGMT.Render(); if (painter) { AfterStroke_Painter(painter, br, st, alphaBuffer, textureMeta); } else { AfterStroke_NoPainter(br, alphaBuffer, textureMeta.CurrentRenderTexture()); } }
public override bool Inspect() { if (ProcessEnumerator != null) { "Running Coroutine".nl(); _processEnumerator.Inspect_AsInList(); return(false); } var changed = false; if ("CPU blit options".conditional_enter(this.TargetIsTexture2D(), ref inspectedItems, 0).nl()) { "Disable Continious Lines".toggleIcon("If you see unwanted lines appearing on the texture as you paint, enable this.", ref disableContiniousLine).nl(ref changed); "CPU blit repaint delay".edit("Delay for video memory update when painting to Texture2D", 140, ref _repaintDelay, 0.01f, 0.5f).nl(ref changed); "Don't update mipMaps".toggleIcon("May increase performance, but your changes may not disaplay if you are far from texture.", ref dontRedoMipMaps).changes(ref changed); } if ("GPU blit options".enter(ref inspectedItems, 1).nl()) { "Update Texture2D after every stroke".toggleIcon(ref updateTex2DafterStroke).nl(); } #region Processors var newWidth = Cfg.SelectedWidthForNewTexture(); //PainterDataAndConfig.SizeIndexToSize(PainterCamera.Data.selectedWidthIndex); var newHeight = Cfg.SelectedHeightForNewTexture(); if ("Texture Processors".enter(ref inspectedItems, 6).nl()) { if (errorWhileReading) { "There was en error reading texture pixels, can't process it".writeWarning(); } else { if ("Resize ({0}*{1}) => ({2}*{3})".F(width, height, newWidth, newHeight).enter(ref _inspectedProcess, 0).nl_ifFoldedOut()) { "New Width ".select(60, ref PainterCamera.Data.selectedWidthIndex, PainterDataAndConfig.NewTextureSizeOptions).nl(ref changed); "New Height ".select(60, ref PainterCamera.Data.selectedHeightIndex, PainterDataAndConfig.NewTextureSizeOptions).nl(ref changed); if (newWidth != width || newHeight != height) { bool rescale; if (newWidth <= width && newHeight <= height) { rescale = "Downscale".Click(); } else if (newWidth >= width && newHeight >= height) { rescale = "Upscale".Click(); } else { rescale = "Rescale".Click(); } if (rescale) { Resize(newWidth, newHeight); } } pegi.nl(); } if (_inspectedProcess == -1) { if ((newWidth != width || newHeight != height) && icon.Size.Click("Resize").nl(ref changed)) { Resize(newWidth, newHeight); } pegi.nl(); } if ("Clear ".enter(ref _inspectedProcess, 1, false)) { "Clear Color".edit(80, ref clearColor).nl(); if ("Clear Texture".Click().nl()) { Colorize(clearColor); SetApplyUpdateRenderTexture(); } } if (_inspectedProcess == -1 && icon.Refresh.Click("Apply color {0}".F(clearColor)).nl()) { Colorize(clearColor); SetApplyUpdateRenderTexture(); } if ("Color to Alpha".enter(ref _inspectedProcess, 2).nl()) { "Background Color".edit(80, ref clearColor).nl(); if (Pixels != null) { if ("Color to Alpha".Click("Will Convert Background Color with transparency").nl()) { bool wasRt = WasRenderTexture(); for (int i = 0; i < _pixels.Length; i++) { _pixels[i] = BlitFunctions.ColorToAlpha(_pixels[i], clearColor); } SetAndApply(); if (wasRt) { ReturnToRenderTexture(); } } if ("Color from Alpha".Click("Will subtract background color from transparency").nl()) { bool wasRt = WasRenderTexture(); for (int i = 0; i < _pixels.Length; i++) { var col = _pixels[i]; col.a = BlitFunctions.ColorToAlpha(_pixels[i], clearColor).a; _pixels[i] = col; } SetAndApply(); if (wasRt) { ReturnToRenderTexture(); } } } } if ("Signed Distance Filelds generator".enter(ref _inspectedProcess, 4).nl()) { if (texture2D.IsColorTexture()) { "Texture is a color texture, best to switch to non-color for SDF. Save any changes first, as the texture will reimport.".writeWarning(); #if UNITY_EDITOR var ai = texture2D.GetTextureImporter(); if (ai != null && "Convert to non-Color".ClickConfirm("SDFnc", "This will undo any unsaved changes. Proceed?") && ai.WasWrongIsColor(false)) { ai.SaveAndReimport(); } #endif } "Will convert black and white color to black and white signed field".nl(); "SDF Max Inside".edit(ref sdfMaxInside).nl(); "SDF Max Outside".edit(ref sdfMaxOutside).nl(); "SDF Post Process".edit(ref sdfPostProcessDistance).nl(); if ("Generate Assync".Click("Will take a bit longer but you'll be able to use Unity")) { bool wasRt = WasRenderTexture(); var p = PlaytimePainter.inspected; if (p) { p.UpdateOrSetTexTarget(TexTarget.Texture2D); } _processEnumerator = QcAsync.StartManagedCoroutine( DistanceFieldProcessor.Generate(this, sdfMaxInside, sdfMaxOutside, sdfPostProcessDistance), () => { SetAndApply(); if (wasRt) { ReturnToRenderTexture(); } }); } pegi.nl(); } if ("Curves".enter(ref _inspectedProcess, 5).nl()) { var crv = TexMGMT.InspectAnimationCurve("Channel"); if (Pixels != null) { if ("Remap Alpha".Click()) { for (int i = 0; i < _pixels.Length; i++) { var col = _pixels[i]; col.a = crv.Evaluate(col.a); _pixels[i] = col; } SetApplyUpdateRenderTexture(); } if ("Remap Color".Click()) { for (int i = 0; i < _pixels.Length; i++) { var col = _pixels[i]; col.r = crv.Evaluate(col.r); col.g = crv.Evaluate(col.g); col.b = crv.Evaluate(col.b); _pixels[i] = col; } SetApplyUpdateRenderTexture(); } } } if ("Save Textures In Game ".enter(ref _inspectedProcess, 7).nl()) { "This is intended to test playtime saving. The functions to do so are quite simple. You can find them inside ImageData.cs class." .writeHint(); pegi.nl(); "Save Name".edit(70, ref saveName); if (icon.Folder.Click("Open Folder with textures").nl()) { QcFile.Explorer.OpenPersistentFolder(SavedImagesFolder); } if ("Save Playtime".Click("Will save to {0}/{1}".F(Application.persistentDataPath, saveName)).nl()) { SaveInPlayer(); } if (Cfg && Cfg.playtimeSavedTextures.Count > 0) { "Playtime Saved Textures".write_List(Cfg.playtimeSavedTextures, LoadTexturePegi); } } if ("Fade edges".enter(ref _inspectedProcess, 8).nl()) { ("This will cahange pixels on the edges of the texture. Useful when wrap mode " + "is set to clamp.").writeHint(); if (texture2D) { #if UNITY_EDITOR var ti = texture2D.GetTextureImporter(); if (ti) { if (ti.wrapMode != TextureWrapMode.Clamp && "Change wrap mode from {0} to Clamp" .F(ti.wrapMode).Click().nl(ref changed)) { ti.wrapMode = TextureWrapMode.Clamp; ti.SaveAndReimport(); } } #endif if ("Set edges to transparent".Click().nl(ref changed)) { SetEdges(Color.clear, ColorMask.A); SetAndApply(); } if ("Set edges to Clear Black".Click().nl(ref changed)) { SetEdges(Color.clear); SetAndApply(); } } } if ("Add Background".enter(ref _inspectedProcess, 9).nl()) { "Background Color".edit(80, ref clearColor).nl(); if ("Add Background".Click("Will Add Beckground color and make everything non transparent").nl()) { bool wasRt = WasRenderTexture(); for (int i = 0; i < _pixels.Length; i++) { _pixels[i] = BlitFunctions.AddBackground(_pixels[i], clearColor); } SetAndApply(); if (wasRt) { ReturnToRenderTexture(); } } } if ("Offset".enter(ref _inspectedProcess, 10).nl()) { "X:".edit(ref _offsetByX); if ((_offsetByX != width / 2) && "{0}/{1}".F(width / 2, width).Click()) { _offsetByX = width / 2; } pegi.nl(); "Y:".edit(ref _offsetByY); if ((_offsetByY != height / 2) && "{0}/{1}".F(height / 2, height).Click()) { _offsetByY = height / 2; } pegi.nl(); if (((_offsetByX % width != 0) || (_offsetByY % height != 0)) && "Apply Offset".Click()) { OffsetPixels(); SetAndApply(); } } } } #endregion if ("Enable Undo for '{0}'".F(NameForPEGI).toggle_enter(ref enableUndoRedo, ref inspectedItems, 2, ref changed).nl()) { "UNDOs: Tex2D".edit(80, ref _numberOfTexture2DBackups).changes(ref changed); "RendTex".edit(60, ref _numberOfRenderTextureBackups).nl(ref changed); "Backup manually".toggleIcon(ref backupManually).nl(); if (_numberOfTexture2DBackups > 50 || _numberOfRenderTextureBackups > 50) { "Too big of a number will eat up lot of memory".writeWarning(); } "Creating more backups will eat more memory".writeOneTimeHint("backupIsMem"); "This are not connected to Unity's Undo/Redo because when you run out of backups you will by accident start undoing other operations.".writeOneTimeHint("noNativeUndo"); "Use Z/X to undo/redo".writeOneTimeHint("ZxUndoRedo"); } if (inspectedItems == -1) { if (isAVolumeTexture) { "Is A volume texture".toggleIcon(ref isAVolumeTexture).nl(ref changed); } } return(changed); }
public RenderBrush CopyBuffer(Texture tex, RenderTexture onto, Material material, Shader shade) { if (tex != null && onto != null) { float size = PainterCamera.orthoSize * 2; float aspectRatio = (float)tex.width / (float)tex.height; float ar2 = (float)onto.width / (float)onto.height; #if UNITY_2018_1_OR_NEWER if (tex.GetType() == typeof(RenderTexture)) { aspectRatio = ar2 / aspectRatio; } else { aspectRatio = 1; } #else aspectRatio = ar2 / aspectRatio; #endif TexMGMT.rtcam.targetTexture = onto; transform.localScale = new Vector3(size * aspectRatio, size, 0); transform.localPosition = Vector3.forward * 10; transform.localRotation = Quaternion.identity; meshFilter.mesh = brushMeshGenerator.inst().GetQuad(); Shader.SetGlobalFloat(PainterDataAndConfig.bufferCopyAspectRatio, 1f / aspectRatio); if (material) { var tmpMat = meshRendy.material; meshRendy.material = material; if (tex) { Set(tex); } TexMGMT.Render(); meshRendy.material = tmpMat; } else { if (shade == null) { shade = TexMGMTdata.pixPerfectCopy; } Set(shade); Set(tex); TexMGMT.Render(); } if (aspectRatio != 1) { Shader.SetGlobalFloat(PainterDataAndConfig.bufferCopyAspectRatio, 1); } } return(this); }
public override void PaintRenderTexture(PlaytimePainter painter, BrushConfig br, StrokeVector st) { BeforeStroke(br, st, painter); var id = painter.TexMeta; if (st.firstStroke || br.decalContentious) { if (br.rotationMethod == RotationMethod.FaceStrokeDirection) { var delta = st.uvTo - _previousUv; var portion = Mathf.Clamp01(delta.magnitude * id.width * 4 / br.Size(false)); var newAngle = Vector2.SignedAngle(Vector2.up, delta) + br.decalAngleModifier; br.decalAngle = Mathf.LerpAngle(br.decalAngle, newAngle, portion); _previousUv = st.uvTo; } bool alphaBuffer; TexMGMT.SHADER_STROKE_SEGMENT_UPDATE(br, 1, id, st, out alphaBuffer, painter); var tf = RtBrush; tf.localScale = Vector3.one * br.Size(false); tf.localRotation = Quaternion.Euler(new Vector3(0, 0, br.decalAngle)); BrushMesh = PainterCamera.BrushMeshGenerator.GetQuad(); st.uvTo = st.uvTo.To01Space(); var deltaUv = st.DeltaUv; var uv = st.uvTo; if (br.rotationMethod == RotationMethod.FaceStrokeDirection && !st.firstStroke) { var length = Mathf.Max(deltaUv.magnitude * 2 * id.width / br.Size(false), 1); var scale = tf.localScale; if ((Mathf.Abs(Mathf.Abs(br.decalAngleModifier) - 90)) < 40) { scale.x *= length; } else { scale.y *= length; } tf.localScale = scale; uv -= deltaUv * ((length - 1) * 0.5f / length); } tf.localPosition = StrokeVector.BrushWorldPositionFrom(uv); TexMGMT.Render(); AfterStroke_Painter(painter, br, st, alphaBuffer, id); } else { painter.AfterStroke(st); } }
public PlaytimePainter Paint(StrokeVector stroke, PlaytimePainter pntr) { var id = pntr.ImgData; if (id == null) { pntr.InitIfNotInited(); id = pntr.ImgData; if (id == null) { return(pntr); } } var cpu = id.TargetIsTexture2D(); var t = Type(cpu); BlitMode.PrePaint(pntr, this, stroke); if (cpu) { pntr.RecordingMGMT(); t.PaintToTexture2D(pntr, this, stroke); } else { var md = pntr.MatDta; if (id.renderTexture == null && !TexMGMT.materialsUsingTendTex.Contains(md)) { TexMGMT.ChangeBufferTarget(id, md, pntr.MaterialTexturePropertyName, pntr); //materialsUsingTendTex.Add(md); pntr.SetTextureOnMaterial(id); //Debug.Log("Adding RT target"); } bool rendered = false; foreach (var pl in TexMGMT.Plugins) { if (pl.PaintRenderTexture(stroke, id, this, pntr)) { rendered = true; break; } } if ((pntr.terrain != null) && (!t.SupportedForTerrain_RT)) { return(pntr); } pntr.RecordingMGMT(); if (!rendered) { t.PaintRenderTexture(pntr, this, stroke); } } return(pntr); }
public PlaytimePainter Paint(StrokeVector stroke, PlaytimePainter painter) { var imgData = painter.TexMeta; if (imgData == null) { painter.InitIfNotInitialized(); imgData = painter.TexMeta; if (imgData == null) { return(painter); } } var cpu = imgData.TargetIsTexture2D(); var brushType = GetBrushType(cpu); var blitMode = GetBlitMode(cpu); blitMode.PrePaint(painter, this, stroke); if (cpu) { foreach (var module in imgData.Modules) { module.OnPainting(painter); } brushType.PaintToTexture2D(painter, this, stroke); } else { var materialData = painter.MatDta; if (!imgData.renderTexture && !TexMGMT.materialsUsingRenderTexture.Contains(materialData)) { TexMGMT.ChangeBufferTarget(imgData, materialData, painter.GetMaterialTextureProperty, painter); painter.SetTextureOnMaterial(imgData); } var rendered = false; foreach (var pl in CameraModuleBase.BrushPlugins) { if (pl.IsEnabledFor(painter, imgData, this)) { pl.PaintRenderTexture(stroke, imgData, this, painter); rendered = true; break; } } if (!painter.terrain || brushType.SupportedForTerrainRt) { foreach (var module in imgData.Modules) { module.OnPainting(painter); } if (!rendered) { brushType.PaintRenderTexture(painter, this, stroke); } } } return(painter); }
public override void AfterRender() { TexMGMT.UpdateBufferTwo(); TexMGMT.bigRTversion++; }
public override void PaintRenderTexture(PlaytimePainter pntr, BrushConfig br, StrokeVector st) { BeforeStroke(pntr, br, st); // Vector2 outb = new Vector2(Mathf.Floor(st.uvTo.x), Mathf.Floor(st.uvTo.y)); // st.uvTo -= outb; // st.uvFrom -= outb; Vector2 delta_uv = st.Delta_uv;//uv - st.uvFrom;//.Previous_uv; float magn = delta_uv.magnitude; var id = pntr.ImgData; float width = br.Size(false) / ((float)id.width) * 4; //const float followPortion = 0.5f; //float follow = width; float trackPortion = (delta_uv.magnitude - width * 0.5f) * 0.25f; if ((trackPortion > 0) || (st.mouseUp)) { if (st.firstStroke) { previousDirectionLazy = st.previousDelta = delta_uv; LazySpeedDynamic = delta_uv.magnitude; LazyAngleSmoothed = 0; // Debug.Log("First stroke"); } float angle = Mathf.Deg2Rad * Vector2.Angle(st.previousDelta, delta_uv); bool smooth = angle < Mathf.PI * 0.5f; if ((st.CrossedASeam()) && (magn > previousDirectionLazy.magnitude * 8)) { // Debug.Log("Crossed a seam"); st.mouseUp = true; st.uvTo = st.uvFrom;// painter.Previous_uv; delta_uv = Vector2.zero; smooth = false; } previousDirectionLazy = delta_uv; if (!st.mouseUp) { if (smooth) { float clockwise = Vector3.Cross(st.previousDelta, delta_uv).z > 0 ? 1 : -1; float sin = Mathf.Sin(angle) * clockwise; float maxSinus = 8; if (Mathf.Abs(LazyAngleSmoothed) > Mathf.Abs(sin)) { LazyAngleSmoothed = sin; } else { LazyAngleSmoothed = Mathf.Lerp(LazyAngleSmoothed, sin, 0.2f); } sin = LazyAngleSmoothed; if ((sin * sin > maxSinus * maxSinus) || ((sin > 0) != (maxSinus > 0))) { float absSin = Mathf.Abs(sin); float absNSin = Mathf.Abs(maxSinus); if (absSin < absNSin) { maxSinus = maxSinus * absSin / absNSin; } st.uvTo = st.uvFrom + st.previousDelta.normalized.Rotate(maxSinus * clockwise) * trackPortion; LazySpeedDynamic = trackPortion; } else { LazySpeedDynamic = Mathf.Min(delta_uv.magnitude * 0.5f, Mathf.Lerp(LazySpeedDynamic, delta_uv.magnitude * 0.5f, 0.001f)); LazySpeedDynamic = Mathf.Max(trackPortion, LazySpeedDynamic); st.uvTo = st.uvFrom + st.previousDelta.normalized.Rotate(sin) * LazySpeedDynamic; } } else { LazySpeedDynamic = delta_uv.magnitude; LazyAngleSmoothed = 0; st.uvTo = st.uvFrom + delta_uv.normalized * trackPortion; } } PainterCamera r = TexMGMT; //RenderTexturePainter.inst.RenderLazyBrush(painter.Previous_uv, uv, brush.speed * 0.05f, painter.curImgData, brush, painter.LmouseUP, smooth ); if (TexMGMT.BigRT_pair == null) { TexMGMT.UpdateBuffersState(); } float meshWidth = br.StrokeWidth(id.width, false); //.Size(false) / ((float)id.width) * 2 * rtp.orthoSize; Transform tf = Rtbrush; Vector2 direction = st.Delta_uv; //uvTo - uvFrom; bool isTail = st.firstStroke; //(!previousTo.Equals(uvFrom)); if ((!isTail) && (!smooth)) { var st2 = new StrokeVector(st) { firstStroke = false }; r.ShaderPrepareStroke(br, br.speed * 0.05f, id, st2, pntr); Vector3 junkPoint = st.uvFrom + st.previousDelta * 0.01f; BrushMesh = brushMeshGenerator.inst().GetStreak(UvToPosition(st.uvFrom), UvToPosition(junkPoint), meshWidth, true, false); tf.localScale = Vector3.one; tf.localRotation = Quaternion.identity; tf.localPosition = new Vector3(0, 0, 10); r.Render();//Render_UpdateSecondBufferIfUsing(id); st.uvFrom = junkPoint; isTail = true; } r.ShaderPrepareStroke(br, br.speed * 0.05f, id, st, pntr); BrushMesh = brushMeshGenerator.inst().GetStreak(UvToPosition(st.uvFrom), UvToPosition(st.uvTo), meshWidth, st.mouseUp, isTail); tf.localScale = Vector3.one; tf.localRotation = Quaternion.identity; tf.localPosition = new Vector3(0, 0, 10); st.previousDelta = direction; r.Render(); AfterStroke(pntr, br, st); } }
public override void PaintRenderTexture(PlaytimePainter pntr, BrushConfig br, StrokeVector st) { BeforeStroke(pntr, br, st); ImageData id = pntr.ImgData; if ((st.firstStroke) || (br.decalContinious)) { if (br.decalRotationMethod == DecalRotationMethod.StrokeDirection) { Vector2 delta = st.uvTo - previousUV; // if ((st.firstStroke) || (delta.magnitude*id.width > br.Size(false)*0.25f)) { float portion = Mathf.Clamp01(delta.magnitude * id.width * 4 / br.Size(false)); float newAngle = Vector2.SignedAngle(Vector2.up, delta) + br.decalAngleModifier; br.decalAngle = Mathf.LerpAngle(br.decalAngle, newAngle, portion); previousUV = st.uvTo; //} } if (TexMGMT.BigRT_pair == null) { TexMGMT.UpdateBuffersState(); } TexMGMT.ShaderPrepareStroke(br, 1, id, st, pntr); Transform tf = Rtbrush; tf.localScale = Vector3.one * br.Size(false); tf.localRotation = Quaternion.Euler(new Vector3(0, 0, br.decalAngle)); BrushMesh = brushMeshGenerator.inst().GetQuad(); st.uvTo = st.uvTo.To01Space(); Vector2 deltauv = st.Delta_uv; /* * * int strokes = Mathf.Max(1, (br.decalContinious && (!st.firstStroke)) ? (int)(deltauv.magnitude*id.width/br.Size(false)) : 1); * * deltauv /= strokes; * * for (int i = 0; i < strokes; i++) { * st.uvFrom += deltauv;*/ Vector2 uv = st.uvTo; if ((br.decalRotationMethod == DecalRotationMethod.StrokeDirection) && (!st.firstStroke)) { float length = Mathf.Max(deltauv.magnitude * 2 * id.width / br.Size(false), 1); Vector3 scale = tf.localScale; if ((Mathf.Abs(Mathf.Abs(br.decalAngleModifier) - 90)) < 40) { scale.x *= length; } else { scale.y *= length; } tf.localScale = scale; uv -= deltauv * ((length - 1) * 0.5f / length); } tf.localPosition = StrokeVector.BrushWorldPositionFrom(uv); TexMGMT.Render(); AfterStroke(pntr, br, st); } else { pntr.AfterStroke(st); } }
public void RenderTexture_To_Texture2D(Texture2D tex) { if (!texture2D) { return; } var rt = renderTexture; TexMGMT.TryApplyBufferChangesTo(this); if (!rt && TexMGMT.imgMetaUsingRendTex == this) { rt = RenderTextureBuffersManager.GetDownscaledBigRt(width, height); } if (!rt) { return; } tex.CopyFrom(rt); PixelsFromTexture2D(tex); var converted = false; /* MAC: * Linear Space * Big RT * Editor * Linear Texture = To Linear * sRGB Texture = * Playtime * Linear Texture = To Linear * sRGB Texture = * Exclusive * Editor * Linear Texture = * sRGB Texture = * Playtime * Linear Texture * sRGB Texture = * Gamma Space * Big RT * Editor * Linear Texture = * sRGB Texture = * Playtime * Linear Texture * sRGB Texture = * Exclusive * Editor * Linear Texture = * sRGB Texture = * Playtime * Linear Texture = * sRGB Texture = */ if (PainterCamera.Inst.IsLinearColorSpace) { if (!tex.IsColorTexture()) { converted = true; PixelsToLinear(); } #if UNITY_2017 if (renderTexture != null) { PixelsToGamma(); converted = true; } #endif } //if (!RenderTexturePainter.inst.isLinearColorSpace) //pixelsToLinear (); if (converted) { SetAndApply(); } else { texture2D.Apply(true); } // }
public void Paint(PaintCommand.UV command) { var imgData = command.TextureData; var cpu = command.TextureData.TargetIsTexture2D(); var brushType = GetBrushType(cpu); var blitMode = GetBlitMode(cpu); var isWorldSpace = command.Is3DBrush; var painterCommand = command as PaintCommand.ForPainterComponent; PlaytimePainter painter = painterCommand?.painter; blitMode.PrePaint(command); if (cpu) { if (painter) { foreach (var module in imgData.Modules) { module.OnPainting(painter); } } brushType.PaintPixelsInRam(command); } else { if (painter) { var materialData = painter.MatDta; if (!imgData.renderTexture && !TexMGMT.materialsUsingRenderTexture.Contains(materialData)) { TexMGMT.ChangeBufferTarget(imgData, materialData, painter.GetMaterialTextureProperty(), painter); painter.SetTextureOnMaterial(imgData); } var rendered = false; foreach (var pl in CameraModuleBase.BrushPlugins) { if (pl.IsEnabledFor(painter, imgData, this)) { pl.PaintRenderTextureUvSpace(command); rendered = true; break; } } if (!painter.terrain || brushType.SupportedForTerrainRt) { foreach (var module in imgData.Modules) { module.OnPainting(painter); } if (!rendered) { if (isWorldSpace) { brushType.PaintRenderTextureInWorldSpace(command as PaintCommand.WorldSpace); } else { brushType.PaintRenderTextureUvSpace(command); } } } } else { if (isWorldSpace) { brushType.PaintRenderTextureInWorldSpace(command as PaintCommand.WorldSpace); } else { brushType.PaintRenderTextureUvSpace(command); } } } }
private RenderTexture CopyBuffer(Texture tex, RenderTexture onto, Material material, Shader shade) { if (!tex || !onto) { return(onto); } const float size = PainterCamera.OrthographicSize * 2; var aspectRatio = tex.width / (float)tex.height; var ar2 = onto.width / (float)onto.height; if (tex.GetType() == typeof(RenderTexture)) { aspectRatio = ar2 / aspectRatio; } else { aspectRatio = 1; } TexMGMT.TargetTexture = onto; var tf = transform; tf.localScale = new Vector3(size * aspectRatio, size, 0); tf.localPosition = Vector3.forward * 10; tf.localRotation = Quaternion.identity; meshFilter.mesh = PainterCamera.BrushMeshGenerator.GetQuad(); PainterShaderVariables.SourceTextureSize = tex; PainterShaderVariables.BufferCopyAspectRatio.GlobalValue = 1f / aspectRatio; if (material) { var tmpMat = meshRenderer.material; meshRenderer.material = material; if (tex) { Set(tex); } TexMGMT.Render(); meshRenderer.material = tmpMat; } else { if (!shade) { shade = TexMgmtData.pixPerfectCopy; } Set(shade); Set(tex); TexMGMT.Render(); } if (Math.Abs(aspectRatio - 1) > float.Epsilon) { PainterShaderVariables.BufferCopyAspectRatio.GlobalValue = 1; } return(onto); }