If you haven't already, please consider writing a review. They really help me out!
First, make sure you back up your project files.
Next, install the latest version.
If for some reason the latest updates breaks your project (e.g. errors in the console), then try deleting the root folder for this asset, and reinstalling it.
If it still doesn't work then go back to your previous version, and let me know what the errors are, so I can fix it.
Paint in 3D supports all 3 render pipelines (Standard, URP, HDRP) in a seamless way that automatically detects your current project settings, and makes the required modifications to the scene so they look similar.
This compatibility was made possible using the Better Shaders system (not required).
The Better Shaders asset generates multiple variants of each shader ahead of time, so even if you don't have this asset, you will still be able to have full render pipeline compatibility with Paint in 3D.
BetterShaders (and therefore Paint in 3D) currently supports:
Standard - All versions supported by Paint in 3D.
URP - Unity 2019 LTS
URP - Unity 2020.2 to 2021.1
HDRP - Unity 2019 LTS
HDRP - Unity 2020.2 to 2021.1
Support for newer versions will appear when it does in this asset.
Each rendering pipeline handles lighting differently. To make the scenes look consistent, each light has the P3dLight component attached to it, which overrides the light intensity for each pipeline.
If you don't like this behavior then you can set the values (for example IntensityInHDRP) to -1.
If you want to use the SgtBlackHole feature, then you must enable the Opaque Texture setting in your pipeline settings asset.
To make HDRP compatibility seamless, each demo scene contains the P3dSceneManager GameObject, which adds the Volume component in HDRP.
This volume will adjust the scene exposure, disable the visual environment, and disable fog. These are all done to make the scenes look consistent with the other rendering pipelines. If you want to adjust these settings yourself then delete this GameObject, and create your own volume.
However, for your own scenes you may want to remove this volume component and use your own exposure settings.
Yes, Paint in 3D is compatible with almost all custom shaders/materials.
The only requirements are that:
1 - The texture you want to paint must be sampled in your shader using the mesh UV data (e.g. uv, uv2, texcoord, texcoord2).
2 - The mesh UV data shouldn't be modified in any significant way (e.g. no tiling or offset).
3 - The mesh positions shouldn't be modified in any significant way.
Keep in mind that shaders that perform minor modifications to the position or UV data will still work, but the paint may appear slightly offset (depending on the magnitude of modification performed). Minor modifications would include parallax mapping shaders, tessellated displacement, heat distortion, etc. If you want to paint these kinds of shaders/materials and notice this offset, then I recommend adding some kind of effect to your object when it gets painted to disguise the offset (e.g. particle effects).
The reason for these requirements is that Paint in 3D applies paint to your mesh using the mesh position and UV data. Paint in 3D doesn't know how your shader is modifying this data, so any modifications the shader performs will result in a discrepancy between where the texture is painted, and where it actually maps to when rendered with your custom shader.
Yes, this asset has been developed and tested in VR, and supports both multi-pass & single-pass rendering modes.
Demo scenes like VR HVLP and VR Pen show you how to implement painting using Unity's XR system. While these demo scenes don't have integrations for third party VR systems (e.g. VRTK), integrating them yourself should be easy enough, as the components are designed to work using any system that support inspector events, and thus they shouldn't require any code changes.
Most of the example components and scenes that come with Paint in 3D are designed for mouse/touch inputs. For example the P3dHitScreen component uses mouse and touch data to paint, so it will not work in VR.
To paint in VR, you can use the P3dHitBetween component, which allows you to paint between two Transform points. The Paint Between demo scene shows you how to use it, and you can apply the same approach to your VR tool. Most of the example scenes can be modified to work in VR with this change alone.
Alternatively, the P3dHitNearby component can be used, which will paint anything near the current GameObject. The Asteroid Holes demo scene shows you how this can be used.
Keep in mind that by default both of these components paint continuously with the same pressure/strength. If you want to be able to toggle painting on and off, or associate your VR trigger pressure with paint pressure, then you will have to write a simple script to connect the two together. If you want to be able to preview the painting without applying it (e.g. when not pulling the trigger), then you will have to control the Preview setting yourself.
Yes, while in play mode open the Window/Paint in 3D from the top menu bar.
On the Scene tab you can see a list of paintable objects in your scene. Under each object you can see a list of its paintable materials, and under those you can see a lise of its paintable textures.
If you want to save each texture individually, then click the Export button next to the texture name, and you can choose where to save it in your project. It will then be saved there as a .png file.
If you want to save a copy of the material with all of its paintable textures, then click the Export button next to the material name, and you can choose where to save it in your project. It will then be saved as a material, and all its textures as .png files.
This can also be done in-game from code too, using the P3dPaintableTexture component's GetPngData() method, which you can then save to file, and later load back using the LoadData(byte) method.
Yes, all of the non-VR comonents should work automatically in either input system.
If you're using the VR components then you must manually create a PlayerInput component, bind some VR controls to an input, and use the events to send the CallbackContext information to the P3dVrManager component.
The VR examples use the P3dInputAxis component to send (legacy) input axis data to functions like P3dVrManager.SetLeftTrigger, and you can replace these using the new system.
Any GameObject that has a MeshFilter + MeshRenderer or SkinnedMeshRenderer can be painted.
Next, you need to mark which textures you want to paint. Your MeshRenderer or SkinnedMeshRenderer component has the Materials array, and each texture used by these materials can be painted.
You should now see the P3dPaintableTexture component added to your GameObject.
Inside this component, you can click the dropdown to the right of the Slot setting, allowing you to pick from a list of materials and texture slots.
For most objects, the default 0, _MainTex setting is all you need. But if you have multiple materials or need to do advanced painting you may need to change this. For example, to paint normal maps you may need to choose 0, _BumpMap or similar, the exact texture name depends on the shader/material.
The rest of the settings should be OK at their default values for now.
The P3dPaintableTexture component takes over the texture slot of the material you specify, which means all other objects using this material will see the same paint. To fix this you must make sure the material is turned into a unique clone before your paintable textures are applied.
You should now see the P3dMaterialCloner component added to your GameObject.
Finally, make sure the P3dMaterialCloner.Index setting matches your P3dPaintableTexture.Slot index. For example, if your slot is 0, _MainTex, then your Index should also be set to 0.
Paint in 3D comes with many ways to paint objects.
One simple method is to make a new GameObject, and add the P3dHitScreen and P3dPaintDecal components. These components will automatically work together, allowing you to paint using the mouse (or your finger if you run it on a mobile device).
You can now adjust the P3dPaintDecal settings to your liking. I recommend you at least change the Color or Texture, because the default paint color is white, and if you paint on a white texture then it may look like nothing is happening!
Once done, press play. You should now be able to click on your object in the Game window, and have the decal you paint on your object under the mouse.
For more advanced ways to paint I recommend you go through the demo scenes in the PaintIn3D/InGame/Examples folder and see how they're put together!
Before you paint objects in-editor, I recommend you make a new scene (e.g. copy+paste your objects into a new scene). This is because configuring your objects for painting requires the scene to be modified (these modifications can easily be removed though).
To open the main Paint in 3D window, click on Window > Paint in 3D from the top menu bar, or select the Paint in 3D tool from the top left tool bar.
Make sure you're on the Scene tab.
Select at least one GameObject in your scene that you want to paint, and it should appear in the list.
On the right of each object you should see the Make Paintable button, which you can click to configure the GameObject for painting.
After you make an object paintable, you must choose which of its materials you want to paint. Below the object you can see a list of its materials, and on the right side you can click the +Preset button to open a list of preset configurations available for this material.
After you add a material preset, you can see a new Export button next to it. If you click this, then you can save a copy of this material and all its textures to the location you specify.
Once you finish painting you can use this new material with painted textures in your scenes.
Make sure you're on the Paint tab.
At the top you can see 3 boxes: Tool, Material, and Shape.
If you click the Tool box, then you can choose a paint tool. These control how the paint is applied in the scene (e.g. dots, line, triangles).
If you click the Material box, then you can choose a paint material. These define a set of textures that allow you to paint a type of surface (e.g. brick, dirt, chrome).
If you click the Shape box, then you can choose the paint shape. These change the shape of the material as you paint, giving more interesting edges.
Make sure you're on the Scene tab.
After you've painted your textures, you can click the Re-Export All button at the bottom right. This will automatically save all previously exported textures with the current paint state.
For Paint in 3D to work, the mesh you want to paint must have UV data. Not only that, but for best results the UV data shouldn't have overlapping areas (e.g. no mirroring), or exceed the 0..1 range (e.g. no texture tiling).
If your mesh fails any of these requirements, then I recommend you modify the UV data in your favorite 3d modelling program (e.g. Blender).
Unity can automatically do it for you. Just keep in mind that doing it manually will allow you to achieve better results.
To automatically generate UV data, you can enable the Generate Lightmap UVs setting in your mesh import settings. This will generate UV data suitable for painting, and they will be stored in the second UV channel.
Yes, Paint in 3D comes with several shaders designed to solve this issue.
If you want to keep your original shader/material that uses the first UV channel, then you can use the Paint in 3D / Overlay shader on top of your base material. Paint in 3D already comes with a pre-configured material called Overlay (Second UV Coord), which you can add on top of your base material. Keep in mind you will now be painting the second material (index 1), so you must update your P3dMaterialCloner and P3dPaintableTexture component settings to target the second material slot index (1).
This technique is demonstrated in the UV Requirements / Automatic Overlay demo scene.
If you don't mind replacing your original shader/material, then the Paint in 3D / Solid shader can be used instead. This shader uses the first UV channel for base textures, and then allows you to override the albedo/opacity/smoothness/etc using secondary textures that use the second UV channel.
This technique is demonstrated in the UV Requirements / Automatic Secondary demo scene.
Paint in 3D comes with the Coord Copier tool, which allows you to do this.
To use this tool, select your mesh in the Project window, and click the context menu (gear) icon at the top right of the inspector, and select the Coord Copier (Paint in 3D) option.
Your Project window should now contain a Coord Copier (YOUR_MESH_NAME) prefab, and you can click Generate to copy the coords over.
The generated mesh with the copied coords is now placed as a child of the Coord Copier prefab, and you can drag and drop it into your Mesh Filter or Skinned Mesh Renderers.
Kind of. Using the following steps you can get it working using the detail texture. Just keep in mind this isn't the best solution, because it doesn't replace the albedo exactly.
Most shaders only the first UV channel, so you will need to make an alternative shader that uses the second.
For example, instead of using uv_MainTex you use uv2_MainTex, or instead of using texcoord0 : TEXCOORD0, you use texcoord1 : TEXCOORD1.
Paint in 3D comes with a range of shaders that allow you to specify the UV channel used (e.g. P3d Opaque).
When you make complex 3d models it's inevitable your mesh will have UV seams, where one part of the texture is disconnected from another.
This normally isn't a problem with clever texturing, but when painting it can result in visual seams between these disconnected UV islands (see the seams around the shoulders on the zombie image).
To fix these UV seams, Paint in 3D comes with a tool that can convert a normal mesh with UV seams into a fixed mesh without UV seams.
To access the tool, select any mesh in your project, click the context menu icon (gear) at the top right, and select Fix Seams (Paint in 3D).
This creates a seam fixer in your project, and automatically sets the Source mesh to the one you picked.
If you want to see the result of the seam fixing, set the Debug Scale setting to 10 or so.
You can now press the Generate button to generate the fixed mesh.
If it was successful, you should see something like this in your Scene window:
Where the green lines are the original seams, and the blue lines are the new fixed seams. The blue lines should be outside of your original green lines. If your blue lines are overlapping then try reducing the Border setting a little, or the Threshold setting.
The generated mesh will be placed as a child of the seam fixer in your Project window.
To use it, just drag and drop it from here into your MeshFilter or SkinnedMeshRenderer that uses this mesh.
If the above steps seem too tedious for you, then you can let Paint in 3D automatically do the seam fixing for you.
Your mesh will now be auto seam fixed just before you paint it for the first time.
If either of these caveats is an issue, then I recommend you follow the previous section and manually seam fix the mesh.
Below are some examples of different kinds of UV maps.
To view these yourself for any mesh, simply open the cotext menu for a mesh (gear icon), and select Analyze Mesh.
This is an example of what a good UV map looks like.
As you can see, the whole mesh is unwrapped making good use of the texture space. All triangles are within the standard (0..1) boundary, none of the triangles overlap, and there is sufficient spacing/padding between each UV 'island'.
This is an example of what a bad UV map looks like.
As you can see, most of the triangles have no UV data, so they cannot be painted. The remaining triangles have UV data, but it's all overlapping, which means painting one area will cause paint to appear in multiple areas, because they share the same pixels.
This is another example of what a bad UV map looks like.
As you can see, most of the triangles are out of bounds. This means most of the mesh can't be directly painted. If you paint the remaining areas, the paint will appear on the out of bounds areas due to texture tiling.
Paint in 3D supports runtime undo & redo, but to save memory it's disabled by default.
To enable it, you need to follow these steps:
The first step is to select your P3dPaintableTexture components, and enable the UndoRedo setting.
If you're painting animated objects then you should set this to FullTextureCopy, but for most scenarios you can use LocalCommandCopy.
If you use the FullTextureCopy state mode then you must also set the State Limit setting. A value of 10 means you can undo paint operations 10 times, and then redo them 10 times. If you paint 11 times with this setting then your initial paint state will be deleted, and you will only be able to undo 10 times to your first paint operation.
You can read the P3dPaintableTexture documentation for more details.
The next step is to find your painting components, and enable the Store States setting.
This setting will automatically call the StoreState method on each P3dPaintableTexture in your scene, letting Paint in 3D know that you're about to paint on them.
For example, the P3dHitScreen component has the StoreStates setting, as well as P3dToggleParticles, and P3dTapThrow.
Finally, you can add the P3dUndoAll and P3dRedoAll components to your UI elements, and they will automatically be set up so when you click them they perform an undo or redo operation.
And that's it, your game should now have Undo & Redo paint functionality!
Keep in mind that when using the FullTextureCopy mode, each undo/redo state is stored as a full texture state. This means that if your texture is 1024x1024 using the RGBA32 format, then each undo/redo state will consume 1024x1024x4 bytes of memory, or 4 megabytes.
If your game requires a lot of undo states and you want to reduce memory usage, then you should use the LocalCommandCopy mode instead, which will store a list of all paint commands (e.g. decal texture + paint orientation). This approach can reduce memory usage a lot, and it allows unlimited undo levels, but performing an undo requires rebuilding the texture from scratch, which can be slow if you have a lot of undo states. It also may not work correctly if your mesh is animated, because the paint will apply to different areas if your mesh has changed.
The undo & redo functionality listed above works well for most games, but it's not suitable for all scenarios. To get full control you can manage it yourself using the following methods in the P3dPaintableTexture class:
Call StoreState before you apply paint to your objects.
Call Undo/Redo after, when you want to undo or redo.
These methods can also be accessed from the P3dPaintableTexture inspector context menu (gear icon at top right), so you can test it from the editor.
Blend modes allow you to change the way your painted pixels are applied to your textures.
If you're using in-editor painting, then you can right click a material to select it, and change the Blend Mode of the P3dPaintDecal components you wish to modify.
If you're using in-game painting, then you can change the Blend Mode in the painting components (e.g. P3dPaintSphere, P3dPaintDecal).
This blend mode increases the alpha channel of your texture, and blends the RGB channels of your texture toward the color of your paint, based on the opacity of your paint.
This blend mode works similar to Alpha Blend, but it applies the blending in reverse.
This allows you to paint 'behind' the current painted areas, or fill them in.