Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Paint In 3D ✍️ Paint In Editor✏️ Paint In 2D

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

  1. lukasynthetic

    lukasynthetic

    Joined:
    May 20, 2020
    Posts:
    30
    Hello, thank you very much for the new version.
    Unfortunately the asset doesn't work for me.
    Using unity version 2023.2.4 I created a brand new URP project.
    Then I installed Paint in Editor.
    I created a cube. Created a material and assigned to the cube.
    Used the menu to unwrap the UV.
    So far so good. Everything as shown in three tutorial videos.
    Unfortunately when trying to paint this cube with supplied textures, nothing works. I cannot see anything being painted.
    What should I do please?
     
  2. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    First, you should back up your project before trying anything.

    If Paint in 3D is the only asset you have installed, then you can delete the whole CW folder and then install the latest and see what happens.

    I don't think you will be able to keep the old and new versions installed at the same time at all even with different names, that will likely just break everything.


    I just created a new Unity 2023.2.3f1 URP 3D template project, made a sphere (default URP / Lit shader), and just by clicking the paint brush icon to open Paint in Editor I was able to click and drag in the Scene window and paint the sphere as expected. Can you try the same and see if it works?

    I don't think the difference between the 2023.2.3 and 2023.2.4 versions would cause this. It's probably something else. Maybe if you send me a unitypackage of your scene and materials/etc I can test it on my end.
     
  3. linenum

    linenum

    Joined:
    Nov 16, 2020
    Posts:
    58
    I deleted the CW folder and installed version 4. Initially the components were still called P3dPaintable, etc. Then I renamed what I had to to fix errors in the console. Then the component names changed to CwPaintableMesh, etc. Now when I run my game the texture painting isn't working and it initially says this many dozens of times:

    NullReferenceException: Object reference not set to an instance of an object
    PaintIn3D.CwPaintableMeshTexture.ApplyTexture (UnityEngine.Texture texture) (at Assets/Plugins/CW/PaintIn3D/Required/Scripts/CwPaintableMeshTexture.cs:26)
    PaintCore.CwPaintableTexture.Activate () (at Assets/Plugins/CW/PaintCore/Required/Scripts/CwPaintableTexture.cs:1025)
    PaintIn3D.CwPaintableMesh.DoActivate () (at Assets/Plugins/CW/PaintIn3D/Required/Scripts/CwPaintableMesh.cs:120)
    PaintIn3D.CwPaintableMesh.Activate () (at Assets/Plugins/CW/PaintIn3D/Required/Scripts/CwPaintableMesh.cs:105)
    PaintIn3D.CwPaintableMesh.Start () (at Assets/Plugins/CW/PaintIn3D/Required/Scripts/CwPaintableMesh.cs:265)

    Then while the game is running it keeps on generating this similar error:

    NullReferenceException: Object reference not set to an instance of an object
    PaintIn3D.CwPaintableMeshTexture.ApplyTexture (UnityEngine.Texture texture) (at Assets/Plugins/CW/PaintIn3D/Required/Scripts/CwPaintableMeshTexture.cs:26)
    PaintCore.CwPaintableTexture.ExecuteCommands (System.Boolean sendNotifications, System.Boolean doSort) (at Assets/Plugins/CW/PaintCore/Required/Scripts/CwPaintableTexture.cs:1258)
    PaintCore.CwPaintableManager.UpdateAll () (at Assets/Plugins/CW/PaintCore/Required/Scripts/CwPaintableManager.cs:148)
    PaintCore.CwPaintableManager.LateUpdate () (at Assets/Plugins/CW/PaintCore/Required/Scripts/CwPaintableManager.cs:128)
     
    Last edited: Jan 1, 2024
  4. ddsinteractive

    ddsinteractive

    Joined:
    May 1, 2013
    Posts:
    28
    The game is coming along swimmingly. To resolve what I was looking for with this I removed the alpha adjustment so that the full color is available to the user. In UX testing we found people avoided the dim colors because they looked too muted and "yucky" as one child said. LOL Progress!
     
    Darkcoder likes this.
  5. lukasynthetic

    lukasynthetic

    Joined:
    May 20, 2020
    Posts:
    30
    Hello and thank you for prompt response.
    Yes, just tried that as well and again no results.
    Here is a link to Unity project to check (I deleted the Library folder to shrink the size of download). Thank you.



    Update 2.01.2024
    I've just realised that I forgot possibly the most important information...
    Could the issue arise because of Apple Silicon?
    I found some assets don't play nice with that version of Unity.
    Using Apple M1 Pro.
    TBH not sure what else could cause the issues as the setup is really very basic (new project with no other assets).
    Hope this helps.
    Kind regards.
     
    Last edited: Jan 3, 2024
  6. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    It's hard to say without a really simple test scene that I can run on my end. Is it possible to make a really simple unitypackage of just your scene and send it to me via email or private message?
     
  7. The11thAlchemist

    The11thAlchemist

    Joined:
    Aug 10, 2020
    Posts:
    30
    Hi Carlos. When I initially press my mouse button down and drag, it initially does a streak across the model. Seems to always go up and left. Hard to tell, but appears to be converging towards a certain location.
     

    Attached Files:

  8. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    Could you let me know the exact Unity version and OS you're using? Also, do you have anything like a drawing tablet or touch monitor in use at the same time?
     
  9. ddsinteractive

    ddsinteractive

    Joined:
    May 1, 2013
    Posts:
    28
    Is there a way to have a touch gesture on an Android tablet rotate the model around so it can be painted from all sides? It works with a mouse right click, but we're developing for a touchscreen tablet.
     
  10. RPGia

    RPGia

    Joined:
    Jan 23, 2017
    Posts:
    44
    Hello, I'm trying to start with a fully transparent plane/quad/canvas, and then paint over that. Is there a way I can achieve this given the stock Paint In 3D shaders?
     
  11. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    The CwDragPitchYaw component used for the camera/object rotation is just a really simple example component. For more advanced controls you would have to modify this yourself, or use your own component, or use some mobile input asset like Lean Touch.

    Also keep in mind the CwPointerTouch component used in all the example scenes sends touch data to CwHitScreen for every finger on the screen. So for example if you want rotation to be a two finger swipe, then you would have to disable the CwHitScreen component while there are 2 fingers on screen.



    Yeah, the "48 Paint From Invisible" shows you how this can be done by initializing the paintable texture as transparent (assuming your object uses a material/shader that supports transparency).
     
    RPGia likes this.
  12. TommyTheITGuy

    TommyTheITGuy

    Joined:
    Jun 11, 2015
    Posts:
    53
    Yes, this occurs also in the 54 Color Counter demo scene. When debugging the color values of pixels read from the texture are slightly diffrent than the color values used with paint tools.

    Maybe there is some color space shenaningans going on?

    If you'd like, I can prepare a small reproduction project.
     
    Last edited: Jan 10, 2024
  13. moncastro

    moncastro

    Joined:
    Aug 13, 2015
    Posts:
    7
    Hello Carlos!
    Thank you very much for this great tool.

    At the moment I have some problems when trying to draw in the editor - my cursor has to be at the bottom right of the object to at least hit the object.
    Reproduced on 2021.3.33f1, 2023.2.3f1 with macOS 12.7.2.
     
  14. Alex_Heizenrader

    Alex_Heizenrader

    Joined:
    May 16, 2019
    Posts:
    100
    Would it be faster to calculate the percentages in the channelcounter only at certain points instead of in Update? Like when painting has stopped, or started, or in each command sent, just to optimize that.
     
  15. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    No I mean does the 54 demo scene without modification work as expected for you with correctly counted colors?

    You can also change the Spaceship/CwColorCounter.Threshold to 0, which should still work. If it's a color space issue then the counter won't work at all in this scene.


    Thanks, I'll test this out as soon as possible.

    [Edit] I can replicate the issue, I'll see if I can fix it.



    If you're using async reading then there shouldn't be much overhead to reading the colors, but yes of course doing it less frequently will be better. There is currently no event that tells you when your mouse/fingers have stopped touching/clicking though. As with all optimizations, you should first profile it and see if it's significant enough relative to other systems.
     
    Last edited: Jan 12, 2024
  16. TommyTheITGuy

    TommyTheITGuy

    Joined:
    Jun 11, 2015
    Posts:
    53
    I did the following steps
    - Made a new 2022.3.16f1 project, Windows platform, 3D URP template
    - Imported Paint in 3D newest version
    - opened scene 54 Color Counter in Play mode
    - replaced Blend Mode for yellow color from Alpha Blend to Replace
    - Painted the top of the spaceship with yellow color

    Now, depending on threshold setting in CWColorCounter component, I get diffrent counts of yellow-painted pixels:
    - 154688 pixels for threshold 0.0
    - 184832 pixels for threshold 0.5
    - 193728 pixels for threshold 1.0 (and 295808 for cyan, although it's unused).

    As far as I understand, with these settings, all painted pixels should have values #FFFF00FF, yet CWColorCounter is reading diffrent colors for some of them.

    How can I ensure, that pixels are painted only and in the exact color I pick?
     
  17. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    Is the "replaced Blend Mode for yellow color from Alpha Blend to Replace" step required? The painted colors should be the same, unless you change the opacity of the yellow to be something other than 1.

    I'll test it in URP with this version as soon as I can.
     
  18. moncastro

    moncastro

    Joined:
    Aug 13, 2015
    Posts:
    7
    Figured it out, that this is because of retina display on iMac, where the GUI point has 2 pixels, and the cursor position (from Event.current.mousePosition) is half less that it should be, so I replaced the line at CwEditorTool.cs:223
    from:
    Code (CSharp):
    1. NewPoint = Event.current.mousePositiont;
    into:
    Code (CSharp):
    1. NewPoint = Event.current.mousePosition * EditorGUIUtility.pixelsPerPoint;
    This solved the problem for me.
     
    Darkcoder likes this.
  19. Alex_Heizenrader

    Alex_Heizenrader

    Joined:
    May 16, 2019
    Posts:
    100
    Yes, I as I was sharing on my last question having a few paintables with channel counters kills performance see my previous post below

    In VR I cannot even have one channel counter without the performance tanking.
     
    Last edited: Jan 12, 2024
  20. lukasynthetic

    lukasynthetic

    Joined:
    May 20, 2020
    Posts:
    30
    Hello. I've just installed latest version (1.0.2) in Unity 2023.2.5. I can confirm that everything now works as expected on Mac. Thank you very much for the fix.
     
  21. Abnormalia_

    Abnormalia_

    Joined:
    Jul 23, 2013
    Posts:
    129
    I've upgraded to v4x and now in my scenario I am loading a modified texture and applying to mesh. Later when I want to paint I am dynamically add "CwPaintableMesh" "CwPaintableMeshTexture" ( Before also Cloner ) and in 4x it reverts to the default texture, not one I've loaded and replaced before. Also when saving modified texture using CwPaintableMeshTexture "GetPngData" to disk it saves the original non modified texture. Is there an example of this or how should it work now?
     
  22. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,089
    Are URP shaders available??
     
  23. Abnormalia_

    Abnormalia_

    Joined:
    Jul 23, 2013
    Posts:
    129
    Once again how to properly make this scenario in 4.x ?
    1. Load texture from disk and apply to material.
    2. Dynamically add Paint3D components before modifying.
    3. Start painting and change textures.
    4. End painting and remove all Paint3D components.
    5. Save modified data to external folder.

    Now issues are, after migrating:
    1. I have to use Cloner and configure it from code in order to see modified texture after I dynamically add paint3D components. I assume I can do this without cloner.
    2. Saving painted texture, saved material vanilla texture to disk. It was working fine in 3x.
     
  24. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    I can look into making the paint counters optionally update only when painting has stopped. However, this will still cause stutters as the paint needs to be read eventually. Do things improve if you increase the Downsample Steps?


    Great!


    All shaders can be painted, including URP ones. The example shaders that come with Paint in 3D work in all 3 pipelines.


    I can't replicate this issue. When the CwPaintableMeshTexture component activates, it reads the Material+Texture you specify in the Slot setting, stores it in the CwPaintableMeshTexture's Texture setting, and then intializes the paintable texture with this. If it's reading the old texture then this material must not have this texture at the time it's activated.

    If you see something different then please prepare a really simple demo scene that shows this and send it to me via email or private message.
     
  25. Abnormalia_

    Abnormalia_

    Joined:
    Jul 23, 2013
    Posts:
    129
    What I mean this code was working in 3x and now its saving clean texture.

    On Paint start :

    Code (CSharp):
    1.                
    2. item.mesh.MarkDynamic();
    3.  
    4.                 Material[] Mats = item.GetComponent<Renderer>().materials;
    5.  
    6.                 for ( int i = 0; i < Mats.Length; i++ )
    7.                 {
    8.                     PaintableDATA pC = new PaintableDATA();
    9.  
    10.                     pC.Paintable        = item.gameObject.GetOrAdd<CwPaintableMesh>();
    11.                     pC.matCloner        = item.gameObject.AddComponent<CwMaterialCloner>();
    12.                     pC.matCloner.Index  = i;
    13.                     pC.pTexture         = item.gameObject.AddComponent<CwPaintableMeshTexture>();
    14.                     pC.pTexture.Slot    = new CwSlot( i, UseTextParam );
    15.                     pC.Paintable.MaterialApplication = CwPaintableMesh.MaterialApplicationType.ClonerAndTextures;
    16.  
    17.                     pData.Add( pC );
    18.                 }
    and On Paint End:

    Code (CSharp):
    1.            CwPaintableMeshTexture[] p3dTexs = pRenderers[ i ].GetComponents<CwPaintableMeshTexture>();
    2.  
    3.                 for ( int texID = 0; texID < p3dTexs.Length; texID++ )
    4.                 {
    5.                     string saveFileName = Path.Combine( saveFolder, $"{pRenderers[ i ].gameObject.name.PaintNameStrip()}_M{texID}.png" );
    6.                     File.WriteAllBytes( saveFileName, p3dTexs[ texID ].GetPngData() );
    7.                 }
    So what I am asking should I do something differently now?
     
  26. DudoTheStampede

    DudoTheStampede

    Joined:
    Mar 16, 2015
    Posts:
    81
    Hi, I'm using latest version of your plugin (Paint In Editor) in Unity 2022.3.16 with URP.
    When I try to paint on one of my meshes (I've tried also on a simple cube) if I click only I get a spot of paint in the desired place. If I click and drag, the paint doesn't start from where I'm clicking.
    Here is a gif to show you:
    ezgif-5-0241a6115e.gif

    Is there some kind of setup I need to made?

    Thanks!
     
  27. Alex_Heizenrader

    Alex_Heizenrader

    Joined:
    May 16, 2019
    Posts:
    100
    I tried reducing the resolution of the texture manually to test, down to 256x256 but it is still really low performance with only one counter in the scene. I am going to try to change the interval it updates and see how that affects things (UPDATE: I just tried 1 counter updating every 0.5 seconds and it still really bad perf).

    I think updating only when painting stops would be great.

    Oh another thing I noticed is that adding a counter at runtime has an race condition. The counter Paint3dreader is not initialized so on first frame the counting is not on, and it won't update until you paint anything because its never set as dirty. A solution I found and am implementing is to do the following after adding the paintable, paintabletexture and counter:


    Code (CSharp):
    1.  //The following fixes an issue with timing for adding channelcounters at runtime, basically needs this to initialize correctly and start counting from frame 0
    2.             channelCounter.SendMessageUpwards("Update");
    3.             channelCounter.MarkCurrentReaderAsDirty();

    Another question unrelated to the above, but more in general as I look at performance of things. I noticed that the PaintableManager doubles the amount of batches and tris in the Statistics. See the pictures below for it active or innactive

    paintable_active.png
    paintable_innactive.png

    Also looking at the frame debugger it shows these <unknown scope> 382 all related to Paint in 3D, not sure what they are but seem to be a big performance issue.
    upload_2024-1-16_12-7-46.png

    Mmm I am thinking that it might be related to adding a paintable to a static piece in my environment and then it was re-rendering the whole "combined mesh" of the whole scene (its a mostly static scene)
     
    Last edited: Jan 16, 2024
  28. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,702
    Hi @Darkcoder
    In my project (which is URP), I am using a third-party material shader (FlatKit/Stylized Surface). I am wondering if I should expect any hiccups in regards to these two facts.

    Let me know, thanks!
     
  29. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    Calling this "item.GetComponent<Renderer>().materials" will clone all your materials, so there's no need for the material cloner in the first place.

    Regardless, I need a demo scene I can run.

    I've attached my test scene which does everything you originally described except it doesn't actually save/load the image data because I don't think that's relevant to the issue. As you can see, it can swap the texture, make it paintable, and remove the components without issue.

    Is this on Windows or Mac or?


    Thanks, I've added a setting to make it auto read the pixels at the start.

    The painting itself renders the mesh based on how many paint commands are in the pending list, so that's why you see elevated draw calls. Also reading the colors will incur draw calls. Basically everything is done on the GPU, which is done with draw calls.


    As long as your custom shader uses 2D textures, and these textured are rendered/mapped using your mesh UV data, then it should work fine with Paint in 3D. It's mostly shaders that don't use mesh UV at all that can't be painted, like completely triplanar shaders, skybox shaders, prcoedural color shaders, or similar.
     

    Attached Files:

    Last edited: Jan 17, 2024
  30. Wenpengfei

    Wenpengfei

    Joined:
    Sep 13, 2020
    Posts:
    1
  31. DudoTheStampede

    DudoTheStampede

    Joined:
    Mar 16, 2015
    Posts:
    81
    Sorry, I forgot to mention that! Both on Windows 10 and Windows 11.
     
  32. Abnormalia_

    Abnormalia_

    Joined:
    Jul 23, 2013
    Posts:
    129

    Yeah that code left when I was experimenting to find a solution but the problem was not there. I was setting texture using "MaterialPropertyBlock" and when I tried just Material.SetTexture everything worked with old code without changing and using the Cloner component as well. Bad news is now material is cloned every time I want to paint.
     
  33. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,702

    Hey: So regarding a third party asset material, they do support texture use, and in some cases I do use a texture on them. In some cases I do not, and simply access the color of the material for the renderer appearance.

    That said, I will get around to testing today. Thank you
     
  34. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,702
    @darkcoder53x
    Sorry I dictated this… so forgive the long winded eee.

    thanks



    Okay, so What I'm wondering is Can I break the color pattern down to RGB meaning Let's say I have a tree in full color There's even some grass below the tree there and there's Apples and the branches and there's leaves on tree branches and so See a lot of green some brown some black And some red and there's a blue sky behind it Now what I'm wondering is If I were to Turn off those colors and make it a grayscale image But then activate it via paint I'm sure that can be done but more specifically what if I were to paint it with only the red spectrum and Then apply the green spectrum and Then apply the blue spectrum And then The once all three are in place the the original color comes back in full so What I'm wondering is a does that make sense to you and B can it be something that can be Managed Given the technology that you have
     
  35. The11thAlchemist

    The11thAlchemist

    Joined:
    Aug 10, 2020
    Posts:
    30
    Just got back from holidays and retried the whole process of prepping meshes to be paintable and it is not happening now. If I run into the problem again, I'll try to figure out the cause and let you know
     
    Darkcoder likes this.
  36. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    Thanks, I can replicate the issue. I'll send you a test build soon.



    Ah yeah, I should add some code to check for a property block first.

    Alternatively, you could set the texture in the CwPaintableMeshTexture component's Texture slot, then you don't have to set it anywhere beforehand. You may also have to set Exiting = Ignore.


    Sure, one thing to keep in mind is that a Material's color will apply a tint to the material's final color. So if you set your color to black then you won't be able to paint anything because the texture's color will basically be wiped out by the tint and set everything to black/000. So if you're painting the texture you should set the material color to white almost always, and rely on the CwPaintableMeshTexture component's Color setting instead.


    Sure, you could make a greyscale and color version of your texture. You can make your CwPaintableMeshTexture begin with the greyscale texture in the Texture setting, and then afterwards in-game set its Texture setting to the color version. You can then paint your object using the ReplaceOriginal blending mode, which will read the CwPaintableMeshTexture's Texture setting. You can set your blending mode's Channels to be 1,0,0,0 to only paint back the red, etc.
     
    DudoTheStampede likes this.
  37. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,702

    Interesting, so in short, one could bring an item to full color, by iterating through each color channel? Example, only the (1,0,0,1), then (1,1,0,1) and finally (1,1,1,1)?

    In other words via the CwPaintableMeshTexture Texture Setting, I can control this aspect?
     
  38. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    Yes, using the paintable texture's Texture setting and paint component's BlendMode/Channels settings.
     
  39. The11thAlchemist

    The11thAlchemist

    Joined:
    Aug 10, 2020
    Posts:
    30
    Hello. I have a couple questions. I'm making a two player networked board game where each player will be able to customize their pieces while offline, but when they connect it will send the painted textures for the pieces to their opponent. While investigating how the textures are saved in your example, I learned that it is saving to a MaterialPropertyBlock (MPB). While trying to learn how that works, I found a bunch of articles saying MPB breaks SRP batching and there were some comments that said textures in MPB also breaks GPU instancing. Is it the presence of a MPB that breaks the SRP batching or is batching only broken if different textures are being used? Since my pieces will all the be the same, even if it is pulling a texture from a MPB shouldn't it still batch? I guess I'm trying to figure out during gameplay (where there won't be any painting occurring) if I should keep all the CW components and load the png into the MPB with your code, or if I should remove all the CW components but keep the original prefab material and write my own code that replaces the albedo texture, or if I should write my own code to create a completely fresh material that never had any MPB values/textures assigned. It all kinda depends on what aspect of MPB breaks the SRP batching.

    My second question is the proper way to save the texture as a png file so I can send it over the network. Your manual said to modify the CwPaintableMeshTexture and GetPngData(). I just went into the CwPaintableTexture script and added a few lines for the WriteAllBytes method and it works...but then I found your Cw_PaintableObjects_Scene script where you have an pretty thorough export process and was wondering if I'm just duplicating something you already had built in?

    Thanks
     
  40. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    I only tested the dynamic and static batching, where if the same MPB with the same textures is applied to multiple renderers, then they seem to batch as expected. This is used in the "64 Atlas Painting" demo scene, which you can see batches as expected if you enable Dynamic or Static Batching.

    I don't think GPU instancing would ever work with painting, because each mesh needs to be different and have its own UV which defeats the purpose. I imagine the SRP batcher would work though, but I haven't tested it yet.

    In your scenario it sounds like you should only expect batching to work before you paint anything, because once you begin painting they will each need unique textures and paint states and thus not be batchable... unless you merge all your objects into an atlas which might be more effort than its worth. As always, you should profile this and identify it as an actual source of lag before you make your game too complex with these kinds of optimizations.

    2) You don't need to modify anything. Simply call GetPngData when you need, send it over the network, and then call LoadFromData on the other side.
     
  41. spilat12

    spilat12

    Joined:
    Feb 10, 2015
    Posts:
    38
    Hi there, what an icredible asset! Could you please tell me whether multitouch is supported? Thanks!
     
  42. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    Yes, by default the paint will apply under each finger and the mouse.
     
    spilat12 likes this.
  43. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,702


    Thank you.
    So a few questions now, as I start to use the asset.

    Q1.
    I began to use a 3rd party Art- Asset to test. After Analyzing the Mesh, it showed all red, so I applied the fix option (using multiple methods) and if you look at pics, you can see the results. One with a non-paintable Mesh, but looks good in the scene. And one with a paintable mesh but looks bad in the scene.

    What do you reckon I do to have the mesh renderer maintain its visual aesthetic in the scene?


    *Notes:
    1. The Material Shader is a 3rd Party Asset, but the Texture is applied to the Albedo.
    2. The texture in the Albedo is a colour palette, not really a flattened image. So the mesh is likely grabbing points on the texture for colour, not just mapping the entire texture onto itself.

    image: orginal mesh in scene and analyzed



    image: updated mesh, and analyzed


    image: the albedo texture used in material





    ================================================
    Q2. Any time I fix a mesh the new mesh appears in the Assets Folder. Can I set it to be placed into a Custom Folder, say Assets/CW?
     
  44. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    1 - At the bottom of the Mesh Fixer tool asset is the Remap Texture tool, which you can use to update your textures to the new layout. You can read a bit more about it HERE, or HERE for Paint in Editor which uses the same code for this part. I will be making a tutorial video for this soon.

    2 - The mesh fixer asset should automatically be placed in the same folder as the source mesh you're trying to fix. Are you saying:

    A) It's placing it in /Assets all the time, regardless of where your source mesh is.
    or
    B) It's placing it alongside your source mesh, but you want to override this to always be in a specific folder?

    If it's A, could you post a screenshot of your Mesh Fixer asset settings, and a screenshot of the Project window of your sources mesh(es) inside the object with the object fully expanded so I can see its contents?
     
  45. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,702
    Thanks.
    1. ok, i dont have the time at the moment but is the idea to place the original texture into the Remap Texture slot, and select Generate?

    2. yes, you are correct, the fixer asset appeared in the folder of the source object. Thanks
     
  46. The11thAlchemist

    The11thAlchemist

    Joined:
    Aug 10, 2020
    Posts:
    30
    Thanks a bunch! Your comments led me down a informative little rabbit hole of knowledge. Sometimes you don't know what you don't know.
    I did some quick testing with the SRP batching:
    1) Gameobjects definitely won't batch even if they are identical or if they are duplicated at runtime when the CW components are active
    2) Disabling the CW components at runtime will not result in them batching
    3) swapping the material at runtime will not result in them batching
    4) Disabling or removing the CW components before runtime will allow all gameobjects to batch, even if they are using the same material as before
    5) Disabling the CW components at runtime and then duplicating the gameobject will result in all duplicates batching but original will not batch
    6) Starting with CW components disabled will allow them to batch, but as soon as CW components are enabled, it will break from the batch and disabling them will not result in them re-batching
    7) Starting with the CW components enabled, then deactivating the CW components at runtime, then deactivating and re-activating the gameobject, will still not result in them batching (it's almost as if once gameobjects are marked as unbatchable, they will never batch..not sure if that is how it works)

    I also did some digging into the GetPngData() function. thanks again for that little tip. It's really hard to traverse other's code, but eventually I figured out you are using EncodeToPng which creates a byte[] which you are converting to string and storing in playerPrefs. This led me to find out that is the unity recommended way of sending png data through the network. Secondly it led me down another road where I learned you can overwrite the original texture file assigned in a shader if you change the texture import compression setting from automatic to RGBA32 (or one of the other compatible formats). This allows me to permanently change the original textures even if the game is turned off or scene changed, no need to save and load.

    Anyway, thanks again. My next step is to investigate your ApplyTexture function to see if that constantly running is the reason for the SRP breaking (it's the only place I could find where you are using SetPropertyBlock property)
     
  47. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    Yeah, that will make a new version of your texture with the new UV layout.


    If you make two objects paintable then it will of course be impossible to batch them because they use separate textures. It might be possible to make them batch again once you remove the components, but it depends how it works. It's possible that the 'batchability' of objects is only checked once during edit/compile time, or when the object is first instantiated. It's also possible the removal of the painting components doesn't fully return their states to the original. For example, there's no way to specifically clear a MPB, only set them to null. I'm also not sure how MPB works with regards to specifying a material index and not, it's possible they use different types. This is one scenario where having source access to Unity would be nice and clear things up.
     
  48. The11thAlchemist

    The11thAlchemist

    Joined:
    Aug 10, 2020
    Posts:
    30
    I've got some good news. SRP batching works differently than the static batching, dynamic batching, and GPU instancing. It batches based on shader instead of material, so each object can have a different mesh and material but the same shader and it will batch them together. I just tested it tonight by SRP batching 3 different meshes, that have 3 different materials, but all with the same shader and Frame debugger shows RenderLoop.DrawSRPBatcher =1. This is where my idea originated that I would use your PaintIn3d asset to paint the meshes but because of the MPB I couldn't keep your components active. This prevents me from using your save/load method. Instead, every object will have their own material and textures, but with the same shader. When the player is done painting the object, a custom script will run the EncodeToPng function to create a byte[] but instead of saving to playerPrefs, it will immediately run a LoadImage from that byte[] to the texture assigned to that objects material. As long as the texture is not set to Automatic Compression, but instead to RGBA32 then it will overwrite the original pixels even when the game is off. Because the actual "game" portion of my game doesn't use painting, it will instantiate the object without the CW components active and they will batch even though they have different textures. Theoretically, I should be able to use the same method of EncodeToPng and LoadImage across the network and the client will have a permanent copy of paint for each object. The only downside I see is that once you trigger the EncodeToPng and LoadImage script, then there isn't any undo because the texture is now permanently changed, but you can still paint over it.

    Anyway, thanks again for a great asset. Not only am I able to use it in my project (so many assets I buy that I can't get working without an insane amount of custom work) but I also learned a ton from looking at how you do things.
     
  49. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,702
    Ok, thanks. I have a couple more questions.

    1. I have the Remapped Texture working, however with one peculiarity. It seems that areas that should be alpha zero/transparent are now black/opaque.

    Is there any way to adjust this?





    2. I have looked at examples and tried to recreate the activity in scene. However, there appears to be no interaction. What I mean is, despite having a PaintableMesh, PaitnableMeshTexture object with a collider, in the scene as well as the CwHitScreen component on another object there is zero interaction in regards to the paintableObject.

    As mentioned I have followed the examples, and believe all the steps required were made. Any suggestions?

    Thanks
     
    Last edited: Jan 22, 2024
  50. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,423
    Interesting, in that case, in the latest version of Paint in 3D I added the CwPaintableMesh component's Advanced/MaterialApplication setting, which you can set to ClonerAndTextures, which restores the original CwMaterialCloner and Material.SetTexture calls. This removes all MPB use, so it may work in your scenario. Just keep in mind you will need to add the CwMaterialCloner alongside CwPaintableMesh, otherwise the CwPaintableMeshTexture will do SetMaterial on the material that is shared with all your other objects.


    1 - This is intentionally done to 'dilate' the texture edges, which prevents seams at the edge of your triangle UV edges. In what scenario would you not want this dilation?


    2 - You can add the CwPaintDebug component alongside your CwHitScreen component. This will show you in the Scene window where the paint hits are being applied (if at all). If it looks correct then make sure your paint component (you have one right?) like CwPaintSphere/CwPaintDecal has a radius large enough. If you're painting decals then you may want to set Advanced/NormalFront to 2 to make sure it's not a backface painting issue. If still nothing works then please prepare a simple demo scene + meshes + textures and send me a unitypackage of it via email or private message so I can test it out.