Exemple #1
0
        public static void PrepareCPUBlit(this BrushConfig bc)
        {
            half = (bc.Size(false)) / 2;
            bool smooth = bc.Type(true) != BrushTypePixel.Inst;

            if (smooth)
            {
                _alphaMode = circleAlpha;
            }
            else
            {
                _alphaMode = noAlpha;
            }

            _blitMode = bc.BlitMode.BlitFunctionTex2D;//bliTMode_Texture2D.blitFunction();

            alpha = 1;

            r = bc.mask.GetFlag(BrushMask.R);
            g = bc.mask.GetFlag(BrushMask.G);
            b = bc.mask.GetFlag(BrushMask.B);
            a = bc.mask.GetFlag(BrushMask.A);

            csrc = bc.colorLinear.ToGamma();
        }
Exemple #2
0
        public void PrepareBlit(BrushConfig bc, ImageData id, float brushAlpha, StrokeVector stroke)
        {
            values      = id.pixelsForJob;
            pixelNumber = id.UvToPixelNumber(stroke.uvFrom);

            width   = id.width;
            height  = id.height;
            brAlpha = brushAlpha;

            half   = (bc.Size(false)) / 2;
            smooth = bc.Type(true) != BrushTypePixel.Inst;

            blitJobBlitMode = bc.BlitMode.BlitJobFunction();

            alpha = 1;

            r = bc.mask.GetFlag(BrushMask.R);
            g = bc.mask.GetFlag(BrushMask.G);
            b = bc.mask.GetFlag(BrushMask.B);
            a = bc.mask.GetFlag(BrushMask.A);

            csrc = bc.colorLinear.ToGamma();
        }
        public bool PaintTexture2D(StrokeVector stroke, float brushAlpha, ImageData image, BrushConfig bc, PlaytimePainter pntr)
        {
            if (pntr.IsAtlased())
            {
                Vector2 uvCoords = stroke.uvFrom;

                Vector2 AtlasedSection = GetAtlasedSection();

                sectorSize = image.width / atlasRows;
                atlasSector.From(AtlasedSection * sectorSize);

                Blit_Functions.brAlpha = brushAlpha;

                Blit_Functions.half = (bc.Size(false)) / 2;
                int ihalf = Mathf.FloorToInt(Blit_Functions.half - 0.5f);

                bool smooth = bc.Type(true) != BrushTypePixel.Inst;

                if (smooth)
                {
                    Blit_Functions._alphaMode = Blit_Functions.circleAlpha;
                }
                else
                {
                    Blit_Functions._alphaMode = Blit_Functions.noAlpha;
                }

                Blit_Functions._blitMode = bc.BlitMode.BlitFunctionTex2D;

                if (smooth)
                {
                    ihalf += 1;
                }

                Blit_Functions.alpha = 1;

                Blit_Functions.r = bc.mask.GetFlag(BrushMask.R);
                Blit_Functions.g = bc.mask.GetFlag(BrushMask.G);
                Blit_Functions.b = bc.mask.GetFlag(BrushMask.B);
                Blit_Functions.a = bc.mask.GetFlag(BrushMask.A);

                Blit_Functions.csrc = bc.colorLinear.ToGamma();

                MyIntVec2 tmp = image.UvToPixelNumber(uvCoords);//new myIntVec2 (pixIndex);

                int fromx = tmp.x - ihalf;

                tmp.y -= ihalf;


                var pixels = image.Pixels;

                for (Blit_Functions.y = -ihalf; Blit_Functions.y < ihalf + 1; Blit_Functions.y++)
                {
                    tmp.x = fromx;

                    for (Blit_Functions.x = -ihalf; Blit_Functions.x < ihalf + 1; Blit_Functions.x++)
                    {
                        if (Blit_Functions._alphaMode())
                        {
                            int sx = tmp.x - atlasSector.x;
                            int sy = tmp.y - atlasSector.y;

                            sx %= sectorSize;
                            if (sx < 0)
                            {
                                sx += sectorSize;
                            }
                            sy %= sectorSize;
                            if (sy < 0)
                            {
                                sy += sectorSize;
                            }

                            Blit_Functions._blitMode(ref pixels[((atlasSector.y + sy)) * image.width + (atlasSector.x + sx)]);
                        }

                        tmp.x += 1;
                    }

                    tmp.y += 1;
                }
                return(true);
            }

            return(false);
        }
        public bool PaintTexture2D(StrokeVector stroke, float brushAlpha, ImageData image, BrushConfig bc, PlaytimePainter pntr)
        {
            var volume = image.texture2D.GetVolumeTextureData();

            if (volume != null)
            {
                if (volume.VolumeJobIsRunning)
                {
                    return(false);
                }

                float volumeScale = volume.size;

                Vector3 pos = (stroke.posFrom - volume.transform.position) / volumeScale + 0.5f * Vector3.one;

                int height   = volume.Height;
                int texWidth = image.width;

                Blit_Functions.brAlpha = brushAlpha;
                bc.PrepareCPUBlit();
                Blit_Functions.half = bc.Size(true) / volumeScale;

                var pixels = image.Pixels;

                int  ihalf  = (int)(Blit_Functions.half - 0.5f);
                bool smooth = bc.Type(true) != BrushTypePixel.Inst;
                if (smooth)
                {
                    ihalf += 1;
                }

                Blit_Functions._alphaMode = Blit_Functions.SphereAlpha;

                int sliceWidth = texWidth / volume.h_slices;

                int hw = sliceWidth / 2;

                int y = (int)pos.y;
                int z = (int)(pos.z + hw);
                int x = (int)(pos.x + hw);

                for (Blit_Functions.y = -ihalf; Blit_Functions.y < ihalf + 1; Blit_Functions.y++)
                {
                    int h = y + Blit_Functions.y;

                    if (h >= height)
                    {
                        return(true);
                    }

                    if (h >= 0)
                    {
                        int hy         = h / volume.h_slices;
                        int hx         = h % volume.h_slices;
                        int hTex_index = (hy * texWidth + hx) * sliceWidth;

                        for (Blit_Functions.z = -ihalf; Blit_Functions.z < ihalf + 1; Blit_Functions.z++)
                        {
                            int trueZ = z + Blit_Functions.z;

                            if (trueZ >= 0 && trueZ < sliceWidth)
                            {
                                int yTex_index = hTex_index + trueZ * texWidth;

                                for (Blit_Functions.x = -ihalf; Blit_Functions.x < ihalf + 1; Blit_Functions.x++)
                                {
                                    if (Blit_Functions._alphaMode())
                                    {
                                        int trueX = x + Blit_Functions.x;

                                        if (trueX >= 0 && trueX < sliceWidth)
                                        {
                                            int texIndex = yTex_index + trueX;
                                            Blit_Functions._blitMode(ref pixels[texIndex]);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                return(true);
            }
            return(false);
        }
Exemple #5
0
        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);
            }
        }
Exemple #6
0
        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);
            }
        }
Exemple #7
0
        public virtual void PaintToTexture2D(PlaytimePainter pntr, BrushConfig br, StrokeVector st)
        {
            Vector2 delta_uv = st.uvTo - st.uvFrom;

            if (delta_uv.magnitude > (0.2f + st.avgBrushSpeed * 3))
            {
                delta_uv = Vector2.zero;                                                     // This is made to avoid glitch strokes on seams
            }
            else
            {
                st.avgBrushSpeed = (st.avgBrushSpeed + delta_uv.magnitude) / 2;
            }


            float alpha = Mathf.Clamp01(br.speed * (Application.isPlaying ? Time.deltaTime : 0.1f));


            bool worldSpace = pntr.NeedsGrid();

            var id = pntr.ImgData;

            float uvDist    = (delta_uv.magnitude * id.width * 8 / br.Size(false));
            float worldDist = st.Delta_WorldPos.magnitude;

            float steps = (int)Mathf.Max(1, worldSpace ? worldDist : uvDist);

            delta_uv /= steps;
            Vector3 deltaPos = st.Delta_WorldPos / steps;

            st.uvFrom  += delta_uv;
            st.posFrom += deltaPos;


            Blit_Functions.PaintTexture2DMethod pluginBlit = null;

            if (pluginBlit == null && tex2DPaintPlugins != null)
            {
                foreach (Blit_Functions.PaintTexture2DMethod p in tex2DPaintPlugins.GetInvocationList())
                {
                    if (p(st, alpha, id, br, pntr))
                    {
                        pluginBlit = p;
                        break;
                    }
                }
            }

            if (pluginBlit == null)
            {
                pluginBlit = Blit_Functions.Paint;
                pluginBlit(st, alpha, id, br, pntr);
            }


            for (float i = 1; i < steps; i++)
            {
                st.uvFrom  += delta_uv;
                st.posFrom += deltaPos;
                pluginBlit(st, alpha, id, br, pntr);
            }



            pntr.AfterStroke(st);
        }
Exemple #8
0
        public void Shader_BrushCFG_Update(BrushConfig brush, float brushAlpha, float textureWidth, bool RendTex, bool texcoord2, PlaytimePainter pntr)
        {
            var brushType = brush.Type(!RendTex);

            bool is3Dbrush = brush.IsA3Dbrush(pntr);
            bool isDecal   = (RendTex) && (brushType.IsUsingDecals);

            Color c = brush.colorLinear.ToGamma();

#if UNITY_EDITOR
            //      if (isLinearColorSpace) c = c.linear;
#endif

            Shader.SetGlobalVector("_brushColor", c);

            Shader.SetGlobalVector("_brushMask", new Vector4(
                                       brush.mask.GetFlag(BrushMask.R) ? 1 : 0,
                                       brush.mask.GetFlag(BrushMask.G) ? 1 : 0,
                                       brush.mask.GetFlag(BrushMask.B) ? 1 : 0,
                                       brush.mask.GetFlag(BrushMask.A) ? 1 : 0));

            if (isDecal)
            {
                Shader_UpdateDecal(brush);
            }

            if (brush.useMask && RendTex)
            {
                Shader.SetGlobalTexture("_SourceMask", Data.masks.TryGet(brush.selectedSourceMask));
            }

            Shader.SetGlobalVector("_maskDynamics", new Vector4(
                                       brush.maskTiling,
                                       RendTex ? brush.Hardness : 0, // y - Hardness is 0 to do correct preview for Texture2D brush
                                       (brush.flipMaskAlpha ? 0 : 1)
                                       , 0));

            Shader.SetGlobalVector("_maskOffset", new Vector4(
                                       brush.maskOffset.x,
                                       brush.maskOffset.y,
                                       0,
                                       0));

            Shader.SetGlobalVector("_brushForm", 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

            brushType.SetKeyword(texcoord2);

            if (texcoord2)
            {
                Shader.EnableKeyword(PainterDataAndConfig.BRUSH_TEXCOORD_2);
            }
            else
            {
                Shader.DisableKeyword(PainterDataAndConfig.BRUSH_TEXCOORD_2);
            }

            brush.BlitMode.SetKeyword().SetGlobalShaderParameters();

            if (brush.BlitMode.GetType() == typeof(BlitModeSamplingOffset))
            {
                Shader.EnableKeyword("PREVIEW_SAMPLING_DISPLACEMENT");

                Shader.DisableKeyword("PREVIEW_ALPHA");
                Shader.DisableKeyword("PREVIEW_RGB");
            }
            else
            {
                Shader.DisableKeyword("PREVIEW_SAMPLING_DISPLACEMENT");
                BlitModeExtensions.SetShaderToggle(TexMGMTdata.previewAlphaChanel, "PREVIEW_ALPHA", "PREVIEW_RGB");
            }

            if ((RendTex) && (brush.BlitMode.UsingSourceTexture))
            {
                Shader.SetGlobalTexture("_SourceTexture", Data.sourceTextures.TryGet(brush.selectedSourceTexture));
            }
        }
 public static float StrokeWidth(this BrushConfig br, float pixWidth, bool world) => br.Size(world) / (pixWidth) * 2 * PainterCamera.orthoSize;