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); }
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); }
void Paint() { RaycastHit hit; // bool anyHits = false; //bool anyRecivers = false; var texturesNeedUpdate = new List <ImageData>(); for (int i = 0; i < shoots; i++) { if (Physics.Raycast(new Ray(transform.position, transform.forward + transform.right * Random.Range(-spread, spread) + transform.up * Random.Range(-spread, spread)), out hit)) { var recivers = hit.transform.GetComponentsInParent <PaintingReciever>(); PaintingReciever reciver = null; // Debug.Log("Hit"); if (recivers.Length > 0) { var submesh = 0; reciver = recivers[0]; // IF FEW SUBMESHES if (hit.collider.GetType() == typeof(MeshCollider)) { submesh = ((MeshCollider)hit.collider).sharedMesh.GetSubmeshNumber(hit.triangleIndex); if (recivers.Length > 1) { var mats = reciver.Rendy.materials; var material = mats[submesh % mats.Length]; reciver = null; foreach (var r in recivers) { if (r.Material == material) { reciver = r; break; } } } } else { submesh = reciver.materialIndex; } // ACTUAL PAINTING if (reciver != null) { var tex = reciver.GetTexture(); if (tex != null) { var rendTex = (reciver.texture.GetType() == typeof(RenderTexture)) ? (RenderTexture)reciver.texture : null; // WORLD SPACE BRUSH if (rendTex != null) { var st = new StrokeVector(hit.point) { unRepeatedUV = hit.collider.GetType() == typeof(MeshCollider) ? (reciver.useTexcoord2 ? hit.textureCoord2 : hit.textureCoord).Floor() : reciver.meshUVoffset, useTexcoord2 = reciver.useTexcoord2 }; if (reciver.type == PaintingReciever.RendererType.Skinned && reciver.skinnedMeshRenderer != null) { BrushTypeSphere.Paint(rendTex, reciver.gameObject, reciver.skinnedMeshRenderer, brush, st, submesh); } else if (reciver.type == PaintingReciever.RendererType.regular && reciver.meshFilter != null) { var mat = reciver.Material; if (mat != null && mat.IsAtlased()) { BrushTypeSphere.PaintAtlased(rendTex, reciver.gameObject, reciver.originalMesh ? reciver.originalMesh : reciver.meshFilter.sharedMesh, brush, st, new List <int> { submesh }, (int)mat.GetFloat(PainterDataAndConfig.atlasedTexturesInARow)); } else { BrushTypeSphere.Paint(rendTex, reciver.gameObject, reciver.originalMesh ? reciver.originalMesh : reciver.meshFilter.sharedMesh, brush, st, new List <int> { submesh }); } } } // TEXTURE SPACE BRUSH else if (reciver.texture.GetType() == typeof(Texture2D)) { if (hit.collider.GetType() != typeof(MeshCollider)) { Debug.Log("Can't get UV coordinates from a Non-Mesh Collider"); } Blit_Functions.Paint(reciver.useTexcoord2 ? hit.textureCoord2 : hit.textureCoord, 1, (Texture2D)reciver.texture, Vector2.zero, Vector2.one, brush, null); var id = reciver.texture.GetImgData(); if (!texturesNeedUpdate.Contains(id)) { texturesNeedUpdate.Add(id); } } else { Debug.Log(reciver.gameObject.name + " doesn't have any combination of paintable things setup on his PainterReciver."); } } } } } } foreach (var t in texturesNeedUpdate) { t.SetAndApply(true); // True for Mipmaps. Best to disable mipmaps on textures and set to false } //Not to waste performance, don't SetAndApply after each edit, but at the end of the frame (LateUpdate maybe) and only if texture was changed. //Mip maps will slow things down, so best is to disable them. // if (!anyHits) Debug.Log("No hits"); // else if (!anyRecivers) Debug.Log("Attach PaintingReciever script to objects you want to Paint on."); }