public static void PrepareCpuBlit(this BrushConfig bc, ImageMeta id) { half = (bc.Size(false)) / 2; var smooth = bc.GetBrushType(true) != BrushTypePixel.Inst; if (smooth) { alphaMode = CircleAlpha; } else { alphaMode = NoAlpha; } blitMode = bc.GetBlitMode(true).BlitFunctionTex2D(id); alpha = 1; var m = bc.mask; r = m.HasFlag(BrushMask.R); g = m.HasFlag(BrushMask.G); b = m.HasFlag(BrushMask.B); a = m.HasFlag(BrushMask.A); cSrc = bc.Color; }
public void SHADER_STROKE_SEGMENT_UPDATE(BrushConfig bc, float brushAlpha, TextureMeta id, StrokeVector stroke, out bool alphaBuffer, PlaytimePainter pntr = null) { CheckPaintingBuffers(); var isDoubleBuffer = !id.renderTexture; var useSingle = !isDoubleBuffer || bc.IsSingleBufferBrush(); var blitMode = bc.GetBlitMode(false); alphaBuffer = !useSingle && bc.useAlphaBuffer && bc.GetBrushType(false).SupportsAlphaBufferPainting&& blitMode.SupportsAlphaBufferPainting; Shader shd = null; if (pntr) { foreach (var pl in CameraModuleBase.BrushPlugins) { var bs = useSingle ? pl.GetBrushShaderSingleBuffer(pntr) : pl.GetBrushShaderDoubleBuffer(pntr); if (!bs) { continue; } shd = bs; break; } } if (!shd) { if (alphaBuffer) { shd = blitMode.ShaderForAlphaOutput; AlphaBufferSetDirtyBeforeRender(id, blitMode.ShaderForAlphaBufferBlit); } else { shd = useSingle ? blitMode.ShaderForSingleBuffer : blitMode.ShaderForDoubleBuffer; } } if (!useSingle && !RenderTextureBuffersManager.secondBufferUpdated) { RenderTextureBuffersManager.UpdateBufferTwo(); } //if (stroke.firstStroke) SHADER_BRUSH_UPDATE(bc, brushAlpha, id, pntr); TargetTexture = alphaBuffer ? AlphaBuffer : id.CurrentRenderTexture(); if (isDoubleBuffer) { PainterShaderVariables.DESTINATION_BUFFER.GlobalValue = BackBuffer; } CurrentShader = shd; }
public static void Paint(StrokeVector stroke, float brushAlpha, ImageMeta image, BrushConfig bc, PlaytimePainter painter) { if (image?.Pixels == null) { return; } var uvCoords = stroke.uvFrom; brAlpha = brushAlpha; bc.PrepareCpuBlit(image); var iHalf = (int)(half); Vector2 offset; var tmp = image.UvToPixelNumber(uvCoords, out offset); var smooth = bc.GetBrushType(true) != BrushTypePixel.Inst; if (smooth) { iHalf += 1; offset = Vector2.zero; } var hf = half - 0.5f; var halfFromX = Mathf.RoundToInt(-hf + offset.x); var halfFromY = Mathf.RoundToInt(-hf + offset.y); var halfToX = Mathf.RoundToInt(hf + offset.x); var halfToY = Mathf.RoundToInt(hf + offset.y); var fromX = tmp.x + halfFromX; tmp.y += halfFromY; var pixels = image.Pixels; for (y = halfFromY; y <= halfToY; y++) { tmp.x = fromX; for (x = halfFromX; x <= halfToX; x++) { if (alphaMode()) { blitMode(ref pixels[image.PixelNo(tmp)]); } tmp.x += 1; } tmp.y += 1; } }
public static void PrepareCpuBlit(this BrushConfig bc, TextureMeta id) { half = (bc.Size(false)) / 2; var smooth = bc.GetBrushType(true) != BrushTypes.Pixel.Inst; if (smooth) { alphaMode = CircleAlpha; } else { alphaMode = NoAlpha; } blitMode = bc.GetBlitMode(true).BlitFunctionTex2D(id); alpha = 1; Set(bc.mask); cSrc = bc.Color; }
public bool BrushConfigPEGI(ref bool overrideBlitMode, BrushConfig br) { var changed = false; var p = InspectedPainter; var volTex = p.GetVolumeTexture(); if (volTex) { overrideBlitMode = true; var id = p.ImgMeta; if (BrushConfig.showAdvanced) { "Grid".toggle(50, ref _useGrid).nl(); } var cpuBlit = id.TargetIsTexture2D().nl(); br.showingSize = !_enableRayTracing || cpuBlit; if (!cpuBlit) { if (BrushConfig.showAdvanced || _enableRayTracing) { "Ray-Tracing".toggleIcon(ref _enableRayTracing, true).changes(ref changed); if (br.useAlphaBuffer) { icon.Warning.write( "Ray Tracing doesn't use Alpha buffer. Alpha buffer will be automatically disabled"); } } if ("Ray Trace Camera".conditional_enter(_enableRayTracing && PainterCamera.depthProjectorCamera, ref _exploreRayTaceCamera).nl_ifFoldedOut()) { "Min".edit(40, ref minFov, 60, maxFov - 1).nl(ref changed); "Max".edit(40, ref maxFov, minFov + 1, 170).nl(ref changed); rayTraceCameraConfiguration.Nested_Inspect().nl(ref changed); } if (_enableRayTracing && BrushConfig.showAdvanced) { pegi.nl(); // "Bounced brightness mltpl".edit(ref arbitraryBrightnessIncrease, 1, 2).changes(ref changed); //"A completely arbitrary value that increases the amount of bounced light. Used to utilize the full 0-1 range of the texture for increased percision" // .fullWindowDocumentationClick(); pegi.nl(); } if (!_exploreRayTaceCamera && _enableRayTracing) { var dp = PainterCamera.depthProjectorCamera; if (!dp) { if ("Create Projector Camera".Click().nl()) { PainterCamera.GetProjectorCamera(); } } else if (dp.pauseAutoUpdates) { pegi.nl(); "Light Projectors paused".toggleIcon(ref dp.pauseAutoUpdates).nl(ref changed); } pegi.nl(); } } if (cpuBlit) { /*if (_enableRayTracing) * icon.Warning.write("CPU Brush is slow for volumes");*/ } else { pegi.nl(); if (!br.GetBrushType(false).IsAWorldSpaceBrush) { "Only World space brush can edit volumes".writeHint(); pegi.nl(); if ("Change to Sphere brush".Click()) { br.SetBrushType(false, BrushTypeSphere.Inst); } } } pegi.nl(); if (!_exploreRayTaceCamera && PainterCamera.Data.showVolumeDetailsInPainter && (volTex.name + " " + VolumeEditingExtensions.VolumeSize(id.texture2D, volTex.hSlices)).foldout(ref _exploreVolumeData).nl()) { volTex.Nested_Inspect().changes(ref changed); } if (volTex.NeedsToManageMaterials) { var painterMaterial = InspectedPainter.Material; if (painterMaterial != null) { if (!volTex.materials.Contains(painterMaterial)) { if ("Add This Material".Click().nl()) { volTex.AddIfNew(p); } } } } if (!cpuBlit) { MsgPainter.Hardness.GetText().edit(MsgPainter.Hardness.GetDescription(), 70, ref br.hardness, 1f, 22f).nl(ref changed); } var tmpSpeed = br._dSpeed.value; if (MsgPainter.Speed.GetText().edit(40, ref tmpSpeed, 0.01f, 4.5f).nl(ref changed)) { br._dSpeed.value = tmpSpeed; } if (br.showingSize) { var maxScale = volTex.size * volTex.Width * 4; "Scale:".edit(40, ref br.brush3DRadius, 0.001f * maxScale, maxScale * 0.5f).changes(ref changed); if (cpuBlit && !_brushShaderFroRayTrace && br.brush3DRadius > BrushScaleMaxForCpu(volTex)) { icon.Warning.write( "Size will be reduced when panting due to low performance of the CPU brush for volumes"); } } pegi.nl(); /* * if (br.GetBlitMode(cpuBlit).UsingSourceTexture && id.TargetIsRenderTexture()) * { * if (TexMGMTdata.sourceTextures.Count > 0) * { * "Copy From:".write(70); * changed |= pegi.selectOrAdd(ref br.selectedSourceTexture, ref TexMGMTdata.sourceTextures); * } * else * "Add Textures to Render Camera to copy from".nl(); * }*/ } if (changed) { this.SetToDirty_Obj(); } return(changed); }
public void PaintPixelsInRam(StrokeVector stroke, float brushAlpha, ImageMeta image, BrushConfig bc, PlaytimePainter painter) { var volume = image.texture2D.GetVolumeTextureData(); if (!volume) { return; } if (volume.VolumeJobIsRunning) { return; } bc.brush3DRadius = Mathf.Min(BrushScaleMaxForCpu(volume), bc.brush3DRadius); var volumeScale = volume.size; var pos = (stroke.posFrom - volume.transform.position) / volumeScale + 0.5f * Vector3.one; var height = volume.Height; var texWidth = image.width; BlitFunctions.brAlpha = brushAlpha; bc.PrepareCpuBlit(image); BlitFunctions.half = bc.Size(true) / volumeScale; var pixels = image.Pixels; var iHalf = (int)(BlitFunctions.half - 0.5f); var smooth = bc.GetBrushType(true) != BrushTypePixel.Inst; if (smooth) { iHalf += 1; } BlitFunctions.alphaMode = BlitFunctions.SphereAlpha; var sliceWidth = texWidth / volume.hSlices; var hw = sliceWidth / 2; var y = (int)pos.y; var z = (int)(pos.z + hw); var x = (int)(pos.x + hw); for (BlitFunctions.y = -iHalf; BlitFunctions.y < iHalf + 1; BlitFunctions.y++) { var h = y + BlitFunctions.y; if (h >= height) { return; } if (h < 0) { continue; } var hy = h / volume.hSlices; var hx = h % volume.hSlices; var hTexIndex = (hy * texWidth + hx) * sliceWidth; for (BlitFunctions.z = -iHalf; BlitFunctions.z < iHalf + 1; BlitFunctions.z++) { var trueZ = z + BlitFunctions.z; if (trueZ < 0 || trueZ >= sliceWidth) { continue; } var yTexIndex = hTexIndex + trueZ * texWidth; for (BlitFunctions.x = -iHalf; BlitFunctions.x < iHalf + 1; BlitFunctions.x++) { if (!BlitFunctions.alphaMode()) { continue; } var trueX = x + BlitFunctions.x; if (trueX < 0 || trueX >= sliceWidth) { continue; } var texIndex = yTexIndex + trueX; BlitFunctions.blitMode(ref pixels[texIndex]); } } } }
public static bool IsSingleBufferBrush(this BrushConfig b) => (PainterCamera.Inst.IsLinearColorSpace && b.GetBlitMode(false).SupportedBySingleBuffer&& b.GetBrushType(false).SupportedBySingleBuffer&& b.PaintingRGB);
public bool PaintTexture2D(StrokeVector stroke, float brushAlpha, TextureMeta image, BrushConfig bc, PlaytimePainter painter) { if (!painter.IsAtlased()) { return(false); } var uvCoords = stroke.uvFrom; var atlasedSection = GetAtlasedSection(); sectorSize = image.width / atlasRows; atlasSector.From(atlasedSection * sectorSize); BlitFunctions.brAlpha = brushAlpha; BlitFunctions.half = (bc.Size(false)) / 2; var iHalf = Mathf.FloorToInt(BlitFunctions.half - 0.5f); var smooth = bc.GetBrushType(true) != BrushTypes.Pixel.Inst; if (smooth) { BlitFunctions.alphaMode = BlitFunctions.CircleAlpha; } else { BlitFunctions.alphaMode = BlitFunctions.NoAlpha; } BlitFunctions.blitMode = bc.GetBlitMode(true).BlitFunctionTex2D(image); if (smooth) { iHalf += 1; } BlitFunctions.alpha = 1; BlitFunctions.Set(bc.mask); BlitFunctions.cSrc = bc.Color; var tmp = image.UvToPixelNumber(uvCoords); var fromX = tmp.x - iHalf; tmp.y -= iHalf; var pixels = image.Pixels; for (BlitFunctions.y = -iHalf; BlitFunctions.y < iHalf + 1; BlitFunctions.y++) { tmp.x = fromX; for (BlitFunctions.x = -iHalf; BlitFunctions.x < iHalf + 1; BlitFunctions.x++) { if (BlitFunctions.alphaMode()) { var sx = tmp.x - atlasSector.x; var sy = tmp.y - atlasSector.y; sx %= sectorSize; if (sx < 0) { sx += sectorSize; } sy %= sectorSize; if (sy < 0) { sy += sectorSize; } BlitFunctions.blitMode(ref pixels[((atlasSector.y + sy)) * image.width + (atlasSector.x + sx)]); } tmp.x += 1; } tmp.y += 1; } return(true); }
public void SHADER_BRUSH_UPDATE(BrushConfig brush = null, float brushAlpha = 1, TextureMeta id = null, PlaytimePainter painter = null) { if (brush == null) { brush = GlobalBrush; } if (id == null && painter) { id = painter.TexMeta; } brush.previewDirty = false; if (id == null) { return; } float textureWidth = id.width; var rendTex = id.TargetIsRenderTexture(); var brushType = brush.GetBrushType(!rendTex); var blitMode = brush.GetBlitMode(!rendTex); var is3DBrush = brush.IsA3DBrush(painter); var useAlphaBuffer = (brush.useAlphaBuffer && blitMode.SupportsAlphaBufferPainting && rendTex); PainterShaderVariables.BrushColorProperty.GlobalValue = brush.Color; PainterShaderVariables.BrushMaskProperty.GlobalValue = brush.mask.ToVector4(); float useTransparentLayerBackground = 0; PainterShaderVariables.OriginalTextureTexelSize.GlobalValue = new Vector4( 1f / id.width, 1f / id.height, id.width, id.height ); if (id.isATransparentLayer) { var md = painter.MatDta; var mat = md.material; if (md != null && md.usePreviewShader && mat) { var mt = mat.mainTexture; PainterShaderVariables.TransparentLayerUnderProperty.GlobalValue = mt; useTransparentLayerBackground = (mt && (id != mt.GetImgDataIfExists())) ? 1 : 0; } } brushType.OnShaderBrushUpdate(brush); if (rendTex) { PainterShaderVariables.SourceMaskProperty.GlobalValue = brush.useMask ? Data.masks.TryGet(brush.selectedSourceMask) : null; } PainterShaderVariables.MaskDynamicsProperty.GlobalValue = new Vector4( brush.maskTiling, rendTex ? brush.hardness * brush.hardness : 0, // y - Hardness is 0 to do correct preview for Texture2D brush ((brush.flipMaskAlpha && brush.useMask) ? 0 : 1), // z - flip mask if any (brush.maskFromGreyscale && brush.useMask) ? 1 : 0); PainterShaderVariables.MaskOffsetProperty.GlobalValue = brush.maskOffset.ToVector4(); PainterShaderVariables.BrushFormProperty.GlobalValue = new Vector4( brushAlpha, // x - transparency brush.Size(is3DBrush), // y - scale for sphere brush.Size(is3DBrush) / textureWidth, // z - scale for uv space brush.blurAmount); // w - blur amount PainterShaderVariables.AlphaBufferConfigProperty.GlobalValue = new Vector4( brush.alphaLimitForAlphaBuffer, brush.worldSpaceBrushPixelJitter ? 1 : 0, useAlphaBuffer ? 1 : 0, 0); PainterShaderVariables.AlphaPaintingBuffer.GlobalValue = AlphaBuffer; brushType.SetKeyword(id.useTexCoord2); QcUnity.SetShaderKeyword(PainterShaderVariables.BRUSH_TEXCOORD_2, id.useTexCoord2); //if (blitMode.SupportsTransparentLayer) QcUnity.SetShaderKeyword(PainterShaderVariables.TARGET_TRANSPARENT_LAYER, id.isATransparentLayer); blitMode.SetKeyword(id).SetGlobalShaderParameters(); if (rendTex && blitMode.UsingSourceTexture) { PainterShaderVariables.SourceTextureProperty.GlobalValue = Data.sourceTextures.TryGet(brush.selectedSourceTexture); PainterShaderVariables.TextureSourceParameters.GlobalValue = new Vector4( (float)brush.srcColorUsage, brush.clampSourceTexture ? 1f : 0f, useTransparentLayerBackground, brush.ignoreSrcTextureTransparency ? 1f : 0f ); } }
public void SHADER_BRUSH_UPDATE(BrushConfig brush = null, float brushAlpha = 1, ImageMeta id = null, PlaytimePainter painter = null) { if (brush == null) { brush = GlobalBrush; } if (!painter) { painter = PlaytimePainter.selectedInPlaytime; } if (id == null && painter) { id = painter.ImgMeta; } brush.previewDirty = false; if (id == null) { return; } float textureWidth = id.width; var rendTex = id.TargetIsRenderTexture(); var brushType = brush.GetBrushType(!rendTex); var blitMode = brush.GetBlitMode(!rendTex); var is3DBrush = brush.IsA3DBrush(painter); //var isDecal = rendTex && brushType.IsUsingDecals; var useAlphaBuffer = (brush.useAlphaBuffer && blitMode.SupportsAlphaBufferPainting && rendTex); BrushColorProperty.GlobalValue = brush.Color; BrushMaskProperty.GlobalValue = new Vector4( BrushExtensions.HasFlag(brush.mask, BrushMask.R) ? 1 : 0, BrushExtensions.HasFlag(brush.mask, BrushMask.G) ? 1 : 0, BrushExtensions.HasFlag(brush.mask, BrushMask.B) ? 1 : 0, BrushExtensions.HasFlag(brush.mask, BrushMask.A) ? 1 : 0); float useTransparentLayerBackground = 0; if (id.isATransparentLayer) { var md = painter.MatDta; if (md != null && md.usePreviewShader && md.material) { var mt = md.material.mainTexture; TransparentLayerUnderProperty.GlobalValue = mt; useTransparentLayerBackground = (mt && (id != mt.GetImgDataIfExists())) ? 1 : 0; } } brushType.OnShaderBrushUpdate(brush); //if (isDecal) // SHADER_DECAL_UPDATE(brush); if (rendTex) { SourceMaskProperty.GlobalValue = brush.useMask ? Data.masks.TryGet(brush.selectedSourceMask) : null; } MaskDynamicsProperty.GlobalValue = new Vector4( brush.maskTiling, rendTex ? brush.hardness * brush.hardness : 0, // y - Hardness is 0 to do correct preview for Texture2D brush ((brush.flipMaskAlpha || brush.useMask) ? 0 : 1), (brush.maskFromGreyscale && brush.useMask) ? 1 : 0); MaskOffsetProperty.GlobalValue = brush.maskOffset.ToVector4(); BrushFormProperty.GlobalValue = new Vector4( brushAlpha, // x - transparency brush.Size(is3DBrush), // y - scale for sphere brush.Size(is3DBrush) / textureWidth, // z - scale for uv space brush.blurAmount); // w - blur amount AlphaBufferConfigProperty.GlobalValue = new Vector4( brush.alphaLimitForAlphaBuffer, brush.worldSpaceBrushPixelJitter ? 1 : 0, useAlphaBuffer ? 1 : 0, 0); AlphaPaintingBuffer.GlobalValue = AlphaBuffer; brushType.SetKeyword(id.useTexCoord2); UnityUtils.SetShaderKeyword(PainterDataAndConfig.BRUSH_TEXCOORD_2, id.useTexCoord2); if (blitMode.SupportsTransparentLayer) { UnityUtils.SetShaderKeyword(PainterDataAndConfig.TARGET_TRANSPARENT_LAYER, id.isATransparentLayer); } blitMode.SetKeyword(id).SetGlobalShaderParameters(); if (rendTex && blitMode.UsingSourceTexture) { SourceTextureProperty.GlobalValue = Data.sourceTextures.TryGet(brush.selectedSourceTexture); TextureSourceParameters.GlobalValue = new Vector4( (float)brush.srcColorUsage, brush.clampSourceTexture ? 1f : 0f, useTransparentLayerBackground, brush.ignoreSrcTextureTransparency ? 1f : 0f ); } }