Search Unity

  1. Unity 2018.3 is now released.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Want more efficiency in your development work? Sign up to receive weekly tech and creative know-how from Unity experts.
    Dismiss Notice
  4. Build games and experiences that can load instantly and without install. Explore the Project Tiny Preview today!
    Dismiss Notice
  5. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  6. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

Paint In 3D - In Game & In Editor & Skinned Mesh Painting

Discussion in 'Assets and Asset Store' started by Darkcoder, Jul 10, 2018.

  1. JohnnyFactor

    JohnnyFactor

    Joined:
    May 18, 2018
    Posts:
    32
    Thanks, that helps.

    Also, how do I see the UVs in the scene window with the green and blue lines, like how you mention in the pdf docs?
     
  2. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    "If you want to see the result of the seam fixing, set the Debug Scale setting to 10 or so."

    Keep in mind the UVs will be shown at 0,0,0 in world space, so you may have to move your scene view camera to see this.

    You can also use the 'Analyze Mesh' button in the P3dPainter component to see this in 2D.
     
  3. JohnnyFactor

    JohnnyFactor

    Joined:
    May 18, 2018
    Posts:
    32
    I have attached to a gameObject two Paintable Texture components and two Pixel Counter components. I can see in the inspector during runtime they are both working but I need to access GetComponent<P3dPixelCounter>().TotalR from a C# script.

    How can I tell them apart since they have the same name?
     
  4. arrnav

    arrnav

    Joined:
    Nov 6, 2016
    Posts:
    25
    Hi,

    I'm using this asset with dynamic meshes (mesh which deforms when a finger presses on it, using raycast) in my game.

    First, I set up the Paint with mouse raycast right click script under the camera.

    Now upon clicking play, when I try to paint on the mesh which has an existing standard shader material with a 256*256 albedo, it doesn't paint at all. The texture on this material does have read write enabled.

    Also, if I try to use the Secondary Albedo Detail Map in the material as the selected texture instead of the primary Albedo for painting, the painted texture completely overlaps the primary Albedo texture as the secondary Detail map starts shows a white background with the painted lines instead of just transparent background "above" the primary Albedo.

    Secondly, any sort of painting on this deformable low poly mesh causes massive lag (2-3 fps) when pressing mouse to paint. When I stop pressing mouse button, the lag goes away. It returns when i resume painting. I'm guessing this has something to do with the mesh being deformable.

    The lag completely goes away when I disable any P3D scripts and just leave the mesh to deform using mouse as it was before without painting.

    Please help. Thanks.
     
    Last edited: Oct 12, 2018
  5. faisal_tekfirst

    faisal_tekfirst

    Joined:
    Feb 21, 2017
    Posts:
    7
    Hi,
    i am trying to get pixel count for the colour values on 3D Paintable Texture and from a sprite texture, which is a screenshot taken from 3D Paintable Texture. both of the textures pixel counter is different. why is that so? any help regarding this is appreciated. thanks
     
  6. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    The easiest way is to drag and drop them into accessible inspector fields. If you have to do it from code then you must call GetComponents<P3dPixelCounter>(), and find out which is which from the array or list.


    When you say dynamic meshes, do you mean the mesh vertices are modified at runtime? Or you move the bones of a skinned mesh? Or a skinned animated mesh?

    Does the mesh have UV data?

    If you post a screenshot of the P3d components used to setup your object it would help a lot. Also, a picture of the P3dPaintable -> Analyze Mesh view.


    If the pixel count is different then the textures must be different, or your P3dPixelCounter settings are different. Are you sure your screenshot is the same size as the original? Also, if your original texture is transparent then it's possible to paint the RGB values and not see a change, even though the counter will change. Then depending on how you take the screenshot these unseen RGB values from the original may not exist in the copy. You should be able to see the RGB & A channels of your textures by double clicking them in the material inspector and looking at the texture preview at the bottom.
     
  7. faisal_tekfirst

    faisal_tekfirst

    Joined:
    Feb 21, 2017
    Posts:
    7
    for the other texture i am taking screenshot using snipping tool and then getting texture 2D from sprite and doing GetPixels32.
     
  8. arrnav

    arrnav

    Joined:
    Nov 6, 2016
    Posts:
    25
    Yes, the mesh vertices are modified at run-time. I've used an asset called "Obi Cloth" for these dynamic meshes. The mesh vertices are re-positioned and given velocities according to which mesh vertex the mouse pointer selects (Think of a "cloth" being dragged by mouse).

    The mesh is not skinned and doesn't have any bones. It has 1035 vertices (low poly). It's UV unwrapped in blender before being imported to unity as an FBX, but textured using a new material created inside Unity, with it's texture being a read-writable 256*256 PNG albedo. It has a PNG as a normal map as well.

    These are my settings, along with what the mesh looks like. That's the mesh I would like to draw on.

    11.PNG 12.PNG 13.PNG 14.PNG 15.PNG

    I couldn't find the "Analyze Mesh View" option anywhere. Couldn't find directions to it in documents either.

    My goal here is to draw on top of this textured mesh, even when it changes it's shape.
     
    Last edited: Oct 12, 2018
  9. arrnav

    arrnav

    Joined:
    Nov 6, 2016
    Posts:
    25
    This is what my profiler shows. The framerate with both mesh deformation and painting enabled is 2-3 fps.

    16.PNG
     
  10. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    Can you compare the pixels from code or visually in the inspector? There's probably a disparity there. All the pixel counter does is downsample the texture a few times, convert it to an array of pixels, and total all the RGBA values. If they're different then your source images are different.


    I see, you're using an old version of Paint in 3D. The latest version paints on the GPU so this kind of thing should be much faster than before, where the mesh was baked and calculated on the CPU. You can improve performance a bit by increasing the 'Update Interval', but not much else.
     
  11. faisal_tekfirst

    faisal_tekfirst

    Joined:
    Feb 21, 2017
    Posts:
    7
    upload_2018-10-12_18-57-40.png Drawing4.PNG
    this is the the screen shot taken from unity of a Paintable3DTexture Object and PixelCounter says about the Paintable3DTexture that values are R : 32768 G : 0 B :0 and A : 32752 but when we calculate pixels from the screenshot taken, Debug log screen shot for that is attached too. have a look please.
     
  12. JohnnyFactor

    JohnnyFactor

    Joined:
    May 18, 2018
    Posts:
    32
    Unfortunately, both of those methods return only the first PixelCounter during runtime. The array members [0] and [1] contain the same PixelCounter and both inspector fields return the same PixelCounter. I have used Component Usages to confirm that all fields are unique, but during runtime the second PixelCounter is overwritten by the first.
     
  13. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    If you're getting numbers that high then your texture is either huge, or your 'DownsampleSteps' is set to 0. As I said though, if the numbers are different then your input texture is different, or the pixel counter settings are different. Your screenshot is probably of a slightly scaled texture or something. You have to compare them and see what the difference is.


    I'm pretty sure there's no way GetComponents is returning an array of two components where both components are the same. Your code to go through them must be wrong.
     
  14. JohnnyFactor

    JohnnyFactor

    Joined:
    May 18, 2018
    Posts:
    32
    Indeed. I wasn't understanding that P3dPixelCounter is a type.

    I was using:
    public Component[] countPixels;


    The revised code is:
    public P3dPixelCounter[] countPixels;


    Everything is working now. Thanks for your help with this.
     
    Darkcoder likes this.
  15. faisal_tekfirst

    faisal_tekfirst

    Joined:
    Feb 21, 2017
    Posts:
    7
    what is the recommended size for texture?
     
  16. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    Depends on your project. The lowest where it still looks good.
     
  17. faisal_tekfirst

    faisal_tekfirst

    Joined:
    Feb 21, 2017
    Posts:
    7
    and there is no green or blue colour, only red colour is drawn, then why is there green and blue colour count?
     
  18. arrnav

    arrnav

    Joined:
    Nov 6, 2016
    Posts:
    25
    Just updated the asset to latest and it worked brilliantly!

    1. Also, is there a way to put a pre-painted texture on a prefab's material albedo when it's instantiated? What I mean is let's say I have a mesh prefab with an albedo, spawned at a certain point in runtime. I would like this mesh to instantly show another texture on top of it's current albedo when it's instantiated.

    An example scenario is dirt particles on a cloth mesh. I would like them to appear instantly, without any actual "painting" work involved from user.

    Is that possible?

    2. If I'm using normal map painting, is there a way to make the painted normal map lines slowly fade away with time?

    For example, if I'm painting bullet marks on a car body, I would like them to slowly fade away visually (not suddenly disappear) after a certain time.

    Thanks.
     
    Last edited: Oct 15, 2018
  19. faisal_tekfirst

    faisal_tekfirst

    Joined:
    Feb 21, 2017
    Posts:
    7
    http://wiki.unity3d.com/index.php/TextureScale
    i have used this script to scale my texture 2D, but it still has the higher amount of RGB values.
     
  20. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    If your texture is scaled then it will give different results, since there are less pixels. Just double click the texture in your inspector to see it, and you will see every pixel of it. My guess is that it has a white border or background, and white is R+G+B.


    Great!

    1 - This is already done automatically if the P3dPaintableTexture is set to a texture slot that contains a texture. The zombie in the "Zombie Blood" demo scene for example already has a texture on, and the P3dPaintableTexture used to paint that automatically detects this, and duplicates it before usage.

    2 - You can use the P3dGraduallyFade component to fade a texture to a target color. The "Shield Impacts" scene uses this to fade the shield out to transparent, but you can use the same component for normal maps. However... fading normal maps properly requires using the 'Replace' blending mode, which currently doesn't work with the P3dGraduallyFade component, so I'll have to fix that and send you a new build.
     
  21. arrnav

    arrnav

    Joined:
    Nov 6, 2016
    Posts:
    25
    Hi, I don't think you got my question right. I just had a look at the zombie scene. The zombie basically uses blood stains directly on the main albedo texture, which is not what I'm after.

    I basically want another ready-made texture to be applied ON-TOP of the main albedo texture. Basically I want a secondary texture to be applied on top of an existing albedo texture, not replacing it.

    For example, think of a clean car body's metallic material, having a main texture albedo for paint detail. As I drive the car more in game, I would like an additional dust texture to slowly overlay on top of the car's existing metallic body material. The secondary texture will basically be an transparent PNG with dust particles spread on it.

    To elaborate further, think of how the painting using a brush is done in P3D. It paints on top of the existing main texture. What I'm looking for is a scenario where this "painting" has already been done in the form of a ready texture and applied on top of the main texture.

    This is what I mean -

    cardust.png
     
    Last edited: Oct 16, 2018
  22. JohnnyFactor

    JohnnyFactor

    Joined:
    May 18, 2018
    Posts:
    32
    I had to deal with this same dilemma recently and came up with a solution.

    I use Amplify Shader Editor to make most shaders. In my particular case, I want to be able to sand and paint furniture. I connected a 2048x2048 black image node to the alpha input of a lerp node (mixes two nodes together), and a white image node to another lerp node. The black and white image nodes are set to be paintable. When painting, it reveals what's underneath-- in this case a different image. It could be a full set of nodes underneath instead if I choose. In fact, I attached the paintable node to Albedo, Normal, and Smoothness all at the same time. This achieves the effect of painting an entirely different material.

    Combined with a shader editor, Paint in 3D is extremely versatile because any combination becomes possible. See the attached screenshots for an example.

    amplify.jpg furniture.jpg
     
    Last edited: Oct 16, 2018
  23. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    Ah, I see. To do this you can either:

    1 - Make/use a custom shader that has this second albedo layer, and your P3dPaintableTexture targets this instead of the normal albedo, for example: Slot = 0, _MainTex2

    2 - Add a second material layer to your renderer, and make that layer transparent. You can then use P3dPaintableTexture to target this with: Slot = 1, _MainTex

    This is what the "Pixel Counter" and "Team Paint Counter" demo scenes do, because otherwise they would count the color of the grass/rocks/etc, which isn't desired. These examples use the "Overlay Cutout" material that comes with P3D for the second layer, but you could use the "Overlay" material instead.

    Just keep in mind this uses material 1, so your P3dMaterialCloner needs to target material 1, otherwise it will paint the same shared material and not work properly.


    Great work, this looks fantastic!
     
  24. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    In case you missed it,

    Version 1.5.9 & 1.6.0 Out Now!
    - Added Replace + Alpha Blend Advanced support to P3dGraduallyFade.
    - Moved IPaintHandler out of Examples.
    - Fixed Multiply blending mode when painting complex meshes.
    - Added UV channel selection to Seam Fixer.


    The runtime save/load demo scene will be added soon. I had to get these bugs fixed first though!
     
  25. keithejc

    keithejc

    Joined:
    Aug 30, 2018
    Posts:
    4
    Hi - I am intending to use this to paint annotations on architectural models. These will then be saved and then loaded on demand.
    The models tend to have a lot of textures adding up to a lot of disk space so i'm trying to optimize this.

    Is there any way to see which of the textures have been modified so i can only save and load these ones?

    I had a look at
    P3dPaintableTexture.NotifyOnModified()
    but this gets called for every texture regardless.

    Thanks..
     
  26. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    To save memory the first thing you should do is set P3dPaintable.Activation = OnFirstUse, otherwise every texture will be initialized on awake.

    P3dPaintableTexture.NotifyOnModified only gets called on textures that receive paint events, and paint events are sent from painters (e.g. P3dPainterDecal/Sphere) that paint within the bounds of the renderer associated with those textures. This means if you paint in one location then potentially many nearby textures will be painted as well. This is done because checking to see if it was actually painted or not is very expensive compared to assuming it was because it was nearby.

    If in your scenario you have many overlapping bounds then you may want to actually check if it was painted before saving it. To do this you can use the P3dPixelCounter and only save when a change is detected.

    To save even more memory it would be a good idea to then deactivate textures that don't receive paint after being activated for some time, but currently there's no method to deactive them as it wasn't a scenario I considered.
     
  27. MagicK47

    MagicK47

    Joined:
    Sep 5, 2017
    Posts:
    8
    I tried to enlarge my model. After enlarging it several times, the map became blurred. Is there any other way to improve the resolution? Because the resolution will be more expensive, and the phone is too laggy.
     

    Attached Files:

  28. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    The most important step is to improve the UV map by increasing the size of important parts, decreasing the size of unimportant parts, and packing it together well to minimize wasted space. For example, you probably don't need so much detail on the legs, ears, etc, but the head needs a lot of detail.

    If it's still too low resolution and you can't increase the texture size due to performance issues then you must change the shader, but this introduces some limitations. For example, instead of using basic alpha blending like you're doing, you can use a cutout shader, and instead of painting normal decals like this, you paint a 'signed distance field' style texture. This will give you very sharp decal edges, but it limits the kind of detail you can add to the decal, and it limits how you can paint colors.
     
  29. arrnav

    arrnav

    Joined:
    Nov 6, 2016
    Posts:
    25
  30. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    That video looks surprisingly gross, and the effect is achieved using vertex position modification. Basically you just move the vertices under the finger in the direction of the finger movement, and over time you slowly revert them back. You could kind of achieve something similar using Paint in 3D with a vertex displacement shader, but it wouldn't be the best approach. My LeanTouch+ asset has the "Select3DDeformMesh" demo scene which implements something similar though, but you would have to modify the code to implement the mesh reversion aspect.
     
  31. nosebleed_dre

    nosebleed_dre

    Joined:
    Jul 25, 2013
    Posts:
    15
    Hi,

    Just purchased and it looks like this will fit our needs very well. I have a bit of a noob question about in Editor decal placing. It seems to be working okay, but for some reason each time I place a decal the entire texture (I'm just adding to the albedo) seems to get darker and the resolution of the images reduces. I'm pretty sure it's something I'm doing wrong, but any pointers would be great.
     
  32. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    Can you post a picture of your Paint in 3D editor window brush settings? This sounds like it might be an issue with the decal painting.
     
  33. nosebleed_dre

    nosebleed_dre

    Joined:
    Jul 25, 2013
    Posts:
    15
    Hi Carlos,

    I've recorded a video of my steps here.
     
  34. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    Thanks for the video! Unfortunately, I can't replicate it despite using exactly the same settings and Unity version as you.

    Are you using the latest version of P3D? (1.6.0 seen in Change Log.pdf)
     

    Attached Files:

  35. nosebleed_dre

    nosebleed_dre

    Joined:
    Jul 25, 2013
    Posts:
    15
    Yeah looks like it. 1.6.0

    On re-watching the video I'm not sure the resolution is actually changing, just the darkness, so any pixels with alpha values (like the anti-aliasing on the ducks) get darker and look like they're dropping in rez. Is there a function that shows the object selection by darkening it?
     
  36. nosebleed_dre

    nosebleed_dre

    Joined:
    Jul 25, 2013
    Posts:
    15
    Actually, I've done a bit more poking about and setting the texture format to ARGB4444 seems to not darken it each time, however the resolution is definitely dropping each time. It's less noticeable if the material texture rez is big (like 2048*2048) but it still happens, and it's very noticeable on a smaller texture rez.
     
  37. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    Interesting. When painting (or preview painting) in the editor the texture is temporarily switched out to a render texture that has no mip maps, so it may look slightly different at that time, but the resolution and colors should be copied exactly the same. However, as you point out it does indeed look like the resolution is being dropped each time.

    Is your texture exactly 512x512?

    What GPU are you using?

    I'll test this some more next week.
     
  38. nosebleed_dre

    nosebleed_dre

    Joined:
    Jul 25, 2013
    Posts:
    15

    I've left work now but it's some fairly high end ATI GPU. I did have the project set to Nintendo Switch earlier in the week and I think we maybe disabled mip maps for a test build so I wonder if the texture isn't able to render into a mip map? I'll poke about some more on Monday.
     
  39. nosebleed_dre

    nosebleed_dre

    Joined:
    Jul 25, 2013
    Posts:
    15
    Oh and I've tried 512*512, 128*128 and 2048*2048 and while it takes longer to notice the drop at higher resolutions it's still happens.

    Strange that it all seems to work seamlessly at runtime.
     
  40. nosebleed_dre

    nosebleed_dre

    Joined:
    Jul 25, 2013
    Posts:
    15
    I'll get someone to try on an Nvidia card too
     
  41. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    Based on your findings I think it may be due to a half texel offset. This would cause a low-resolution like transformation you describe, and would be less apparent at higher resolutions. I didn't notice this in my testing across D3D or OGL so I didn't add any code to perform this offset, but I'll send you a build on Monday that implements it to see if that fixes anything.
     
  42. nosebleed_dre

    nosebleed_dre

    Joined:
    Jul 25, 2013
    Posts:
    15
    cool I'll give that a shot tomorrow (I'm on UK time :))
     
  43. RikuTheFuffs

    RikuTheFuffs

    Joined:
    Sep 9, 2013
    Posts:
    10
    Hi, is there an easy way to add "Paint Drips" while painting (at runtime, not in editor) with this package?
     
  44. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    I assume you want to paint a circle, and have it automatically drip down into a shape like this over time? If so, there's currently no way to do this. I'll add it in the future though, it would be nice to see.
     
  45. RikuTheFuffs

    RikuTheFuffs

    Joined:
    Sep 9, 2013
    Posts:
    10
    Hi Dark, thank you for your fast reply! The image was just an example, what I want to do is just to let the painting drip from where the brush is. That said, do you confirm that it is still impossible to do at the moment?

    EDIT: Searching around on google, I found someone saying this:
    "Randomly create "drip points" on your canvas and make them generate small circular sprites of the same color. Then make those "drip points" go down and kill them after a few seconds".

    Is there any tool in the package that allows us to do this?
     
  46. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    You may be able to do this now with particles/objects, but I haven't experimented with it. Basically, if you can get particles or objects to stick to your wall when you paint, then you could have them slowly 'drip' down, and paint lines over time. This is probably the easiest way to do it.

    A more difficult but potentially better looking method is to bake a flow map of your model, and have the paint drift according to the flow, and have it 'dry' up over time. Calculating this flow map probably wouldn't be too efficient though, and may not work well with any kind of rotating or deforming object.
     
  47. RikuTheFuffs

    RikuTheFuffs

    Joined:
    Sep 9, 2013
    Posts:
    10
    Awesome, thanks!
     
  48. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    1,326
    I experimented some more and I don't think a half texel offset would cause this issue, because if introduce one then the image just appears to blur over time, rather than degrade in resolution. I think it may be my use of temporary render textures that is causing this. Perhaps there is a 'clever optimization' done on Switch, where instead of returning the exact render texture resolution you specify, it picks one close enough? That's my best guess at least, but testing this would require writing a wrapper around the Get/Release temporary calls. I can send you an updated build soon with these changes.
     
  49. nosebleed_dre

    nosebleed_dre

    Joined:
    Jul 25, 2013
    Posts:
    15
    That new version works a treat. Thanks for the quick turnaround.
     
    Darkcoder likes this.
  50. nosebleed_dre

    nosebleed_dre

    Joined:
    Jul 25, 2013
    Posts:
    15
    Me again. Might be a dumb question, and a feature that's already there, but I can't seem to find a way to paint (in editor) using sprites from an atlas. If this isn't something that works already it would be a REALLY useful feature. Also is it possible to rotate the decals within the editor.... Really I should look at the documentation shouldn't I! :D
     
    Last edited: Nov 8, 2018