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.
In addition to the written documentation here, you can also find tutorial videos HERE.
Any GameObject that has a MeshFilter + MeshRenderer or SkinnedMeshRenderer can be painted.
Once the CwPaintableMesh component has been added, you can click the Analyze Mesh button to see if your mesh is suitable for painting.
Next, you need to pick which textures you want to paint.
Your MeshRenderer or SkinnedMeshRenderer component has the Materials array, which usually has one material. Each material is rendered using a shader, and each shader has a list of textures that it uses. Most shaders have the Albedo/Color texture, but some more advanced shaders can have a Normal Map texture, Emission texture, etc.
You should now see the CwPaintableMeshTexture component added to your GameObject.
Inside this component, you can see the Slot setting. Next to this setting is a dropdown arrow button which you can click, and this allows you to pick from a list of all textures in your renderer.
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.
Paint in 3D comes with many ways to paint objects.
One simple method is to make a new GameObject, and add the CwHitScreen and CwPaintDecal 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 CwPaintDecal 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/Examples folder and see how they're put together!
When you make an object paintable, you add the CwPaintableMesh component.
Inside this component inspector is the Analyze Mesh button.
If you click this, then it will open the Mesh Analysis window with the current mesh you're trying to paint.
If your mesh is suitable for painting, it should look something like this.
As you can see, there are few overlapping triangles, few out of bounds triangles, few triangles with no UV, and the texture space is fairly well utilized.
If your mesh is NOT suitable for painting, it will look something like this.
As you can see, there are large areas of overlap in red, or many out of bounds triangles, or many triangles with no UV map.
In any of these scenarios, your mesh will need to be UV unwrapped before you can paint it.
It's best to manually UV unwrap your meshes in your favorite 3D modeling software (e.g. Blender), because you will have full control over how it is unwrapped and can therefore give priority to certain areas and perhaps make better use of the texture space.
However, Paint in 3D comes with a tool to perform this UV unwrap for you.
To use it, click the Fix button at the top right of the Mesh Analysis window, and read the next tutorial section HERE.
Paint in 3D comes with the Mesh Fixer tool, which allows you to UV Unwrap your mesh so it can be painted, and/or fix UV seams.
This will add a Mesh Fixer asset to your project.
Next to your mesh, you can click the Analyze Old button to see what the current non-fixed UV map looks like.
This setting allows you to choose which UV channel/coordinate you want to fix. For most meshes this should be set to First.
For a mesh to be paintable, the UV data must be within the standard 0..1 range on the X and Y axes. However, some assets or mesh workflows put the meshes in slightly different ranges like 1..2 or 2..3, typically across the X axis.
When the UVs are recentered, it detects this scenario, and shifts the UVs to the typical 0..1 range.
If you enable this setting, then your mesh will have entirely new UV data generated.
If you enable this setting, then the UV island edges of your mesh will be extended so they can be painted without seams appearing.
Once you're happy with your mesh fixer settings, you can click the Generate button.
This will make duplicates of all meshes in the Meshes list, process them based on your settings, and then save them as child assets of the mesh fixer.
Next to your mesh, you can click the Analyze New button to see what the new fixed UV map looks like.
If your scene contains CwPaintableMesh components that still use the old non-fixed meshes, then they will show up at the bottom of the mesh fixer under the SWAP MESHES list, allowing you to quickly update them.
If you enable GenerateUV, then your meshes will have their UV data completely replaced with an entirely new layout.
This is fine if your meshes will then be painted from scratch. However, if your meshes originally had a texture, then those textures must be remapped to the new UV data.
To remap them, simply drag and drop your textures into the Remap Texture field one at a time. This will reveal a list of meshes you can use for the remapping, and once chosen you will be prompted to save the texture.
This remapping feature is very useful with low-poly style meshes, which are typically colored using an atlas style color palette, where the UV data for each triangle is flattened to a point on a specific color.
If your mesh UV data isn't paintable, then using the Mesh Fixer is usually the best approach. However, in some scenarios you may want to keep the original mesh UV data, but still want to be able to paint your mesh.
In this scenario, another approach is to paint using the second channel of UV data. The second channel of UV data is usually used for lightmapping, but lightmap UVs are also perfect for painting.
To automatically generate this secondary UV data, you can enable the Generate Lightmap UVs setting in your model/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 CwPaintableMeshTexture 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.
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. PaintIn3D/Opaque).
To make an object paintable, you must add and configure the CwPaintableMesh and CwPaintableMeshTexture components.
However, this can be time confusing to do if you have many objects, or a complex configuration.
To speed things up, Paint in 3D comes with the presets system.
Select the Window/CW/Paintable Objects menu option.
This will open the Paintable Objects window.
You can now select some GameObjects in the Scene or Hierarchy window.
Any GameObject or child GameObject you select that has a MeshFilter + MeshRenderer or SkinnedMeshRenderer will appear as a list in this window.
Next to each GameObject will be the Make Paintable button.
If you click this, it will list all possible presets for this Renderer and Material's Shader type.
You can then choose one.
Paint in 3D comes with presets for most of Unity's built-in shaders. However, if you've made your own shaders, or you have another asset with custom shaders, then you will have to add them to an existing preset.
All presets can be found in the Plugins/CW/PaintIn3D/Extras/Presets folder.
For example, the Basic - AA preset allows you to paint the _MainTex, which is usually the albedo (+ optional Alpha/Opacity). If you want to add your custom shader to this preset, then you can add it to the Shader Paths list.
If you're unsure what your shader is called, or want to add multiple shaders to this preset, then you can click the Find Shaders button, which will find all shaders in the current project that have all textures used by the preset (in this case of the Basic - AA preset, all shaders with _MainTex will be listed).
If the presets that come with Paint in 3D aren't suitable for your project, then feel free to right click in the Project window, and select the Create/CW/Paint in 3D/Preset option.
This will add a new prefab to your project with the CwPreset, MeshFilter, MeshRenderer, and CwPaintableMesh components attached.
You must then set the ShaderPaths to include your shader, add all the CwPaintableMeshTexture components you want for this preset, and configure their Slot settings.
You can now use this preset from the Make Paintable button in the Paintable Objects window.
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.
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 (⋮ button) at the top right, and select Fix Mesh (Paint in 3D).
This creates a seam fixer in your project, and automatically sets the Source mesh to the one you picked.
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.
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 CwPaintableMeshTexture 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 CwPaintableMeshTexture 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 CwPaintableMeshTexture in your scene, letting Paint in 3D know that you're about to paint on them.
For example, the CwHitScreen component has the StoreStates setting, as well as CwToggleParticles, and CwTapThrow.
Finally, you can add the CwUndoAll and CwRedoAll 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 CwPaintableMeshTexture 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 CwPaintableMeshTexture inspector context menu (⋮ button 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 CwPaintDecal 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. CwPaintSphere, CwPaintDecal).
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.
This blend mode works similar to Alpha Blend, but the alpha channel is not modified. This is ideal when you want to paint on only the solid parts of an already transparent texture.
This blend mode works by increasing the RGBA values of your texture based on the paint color.
This blend mode works similar to Additive, but the strength of the blending fades based on how bright the texture already is.
This works by decreasing the RGBA values of your texture based on the paint color.
This blend mode works similar to Subtractive, but the strength of the blending fades based on how dark the texture already is.
This blending mode works like Alpha Blend, but the alpha channel of the texture will transition toward the paint alpha channel value, rather than just increase. In effect, this blends all channels toward the paint color at the same rate.
This is useful for painting advanced textures (e.g PBR), where you want to paint a specific alpha channel value.
This blending mode works similar to Replace, but instead of transitioning to the paint color, the paint color will be based on the original color of the texture.
This color is defined by the CwPaintableMeshTexture component's Texture and Color settings.
This blending mode works similar to Replace Original, but instead of transitioning to the original texture color, you can specify a custom texture and color to transition to.
This blend mode allows you to darken your texture based on the paint color.
To make it easier to use, the blending is inversed. This means your decal should be white where you want the color to be multiplied, and black where you want no change.
This blend mode allows you to blur your texture based on the paint opacity.
This blend mode allows you to paint a normal map with another, and both normal maps will combine together.
This blend mode allows you to paint a normal map on top of another, and the original normal map will be replaced by the new one.
This blend mode allows you to move the pixels in the texture you're painting. The direction and distance the pixels will move is based on the normal map you specify.
By default, Paint in 3D performs all painting using the visual mesh of your paintable objects, and doesn't inherently require colliders.
For example, the CwHitNearby and CwHitThrough components send hit data to paint components like CwPaintDecal using positions you manually specify, so colliders aren't required at all.
However, components like CwHitScreen and CwHitParticles perform raycasts to find hit point information, which means your paintable objects need colliders.
Since the paint is applied using the visual mesh, your colliders don't need to match your visual meshes, so for optimization purposes they can be much lower resolution.
However, depending on the size/radius of your paint brush, your colliders do have to be within a certain distance of the visual mesh.
For example, if you're painting your objects using the CwPaintSphere component with a total Size/Radius of 10 meters (units), then the maximum distance between your collider surface and visual mesh surface must always be below 10 meters, otherwise there will be areas you cannot paint.
Paint in 3D allows you to paint skinned meshes. The set up is almost the same, where you add the CwPaintableMesh component alongside the SkinnedMeshRenderer component. However, there are some things to keep in mind.
Normal non-skinned meshes are usually static, so you can just add a MeshCollider. However, skinned meshes usually bend and deform such that you cannot use a MeshCollider, because as soon as it animates, the collider surface will not match the visual mesh, which causes the paint to apply to the wrong area.
While the collider doesn't have to match the visual mesh, it needs to be close enough relative to the size/radius of your paint tool (e.g. CwPaintDecal's Radius & Scale settings). If you have a complex skinned mesh, this usually means you must add many colliders to your object (e.g. BoxColliders and CapsuleColliders, perhaps one per bone).
However, if your game doesn't require precise painting (e.g. bullet wounds only), then there is one alternative strategy that is simpler to configure that is shown in the "PaintIn3D/Examples/Zombie Blood" demo scene. In this scene, the skinned zombie mesh is given one large BoxCollider, that encapsulates the whole zombie animation cycle. The CwHitScreen component's RotateTo setting is set to Normal, and RotateTo/Direction is set to RayDirection. The CwPaintDecal component's Scale.z setting is then set to 15 (the exact value depends on the size of the skinned mesh). With this configuration, the paint is aligned to and stretched along the hit direction, so it goes through the skinned mesh.
Inside the CwPaintableMesh component is the IncludeScale setting. Depending on your skinned mesh, you may need to enable this setting for the painting to work.
I wasn't able to identify exactly when this setting needs to be enabled or disabled, so it can't be automatically set. I think it has something to do with the software used to export the mesh, or the export settings, so for now you must manually try toggling this if you find your mesh can't be painted even if every other setting looks correct.
When painting using components like CwHitScreen, you may notice your paint can appear as separate dots. This can easily happen if the object you're painting is far away, your paint brush radius is low, or the surface you're painting is at a sharp angle relative to your camera.
This happens because the paint is actually applied as a dot, and to make a continuous line the dots are simply placed close enough together that they no longer appear as dots. However, under certain circumstances this illusion can be broken.
To improve this, the easiest way to is to just lower the CwHitScreen component's Interval setting. This will increase the amount of dots drawn by reducing the pixel distance between them. However, this carries a performance penalty, and it only makes the issue less apparent, it doesn't solve it.
To solve this issue you want to have each separate dot connect together to form a continuous line, and this can be done by enabling the Advanced / Connect Hits setting. This setting appears on components like CwHitScreen, CwHitNearby, and CwHitBetween. Instead of sending hit point information to paint components, it will instead connect the hits points, and send out hit lines.
When using connected hits, the connected lines are drawn separately, which causes the overlapping corners to receive double the paint. This is an issue with semi-transparent painting, because they will appear stronger than the main line body.
To fix this, you must enable the Advanced / Clip Connected setting, which eliminates this issue in most scenarios.
Paint in 3D allows you to paint multiple textures at the same time (e.g. Albedo + Normal).
To set this up you must first add multiple CwPaintableMeshTexture components to your object, and make them target different texture slots in your current material/shader. For example, the first texture could be for the _MainTex slot, and the second texture could be for the _BumpMap slot.
Next, you must choose a different paint Group for each component. By default all textures are assigned to group "0: Albedo (RGB) Alpha(A)". If your first texture is albedo then you can keep this value. If your second texture is a normal map then you can change it to group "10: Normal (RGBA)".
Next, you must make multiple paint components (e.g. CwPaintDecal / Paint Decal), and change their Group setting to match the texture groups you previously set.
You can now paint two textures at the same time! These same steps can be repeated for any number of textures.
Although paint in 3D is very optimized, it's still easy to make it run slow, especially on mobile devices. Here are some tips and tricks on how to optimize your scene and maximize performance.
The easiest way to optimize painting performance is to reduce the size of your CwPaintableMeshTexture. If you halve the width & height of your texture, then there are now only 1/4 of the pixels being painted, which means your paint will apply up to 4x faster.
I recommend you reduce the texture resolution as much as possible, until you find the perfect balance between performance and visual quality.
Another easy way to optimize your painting is to paint less often.
For example, the CwHitScreen component has the Interval setting, which allows you to choose the pixel distance between each paint hit. If you set this to 3 pixels and move your mouse/finger 300 pixels in one frame, then this will result in your scene being painted 100 times. If you increase this to 6 pixels, then it will result in the scene being painted 50 times, or a 2x optimization. You can also set the Frequency to OnceEveryFrame, which will paint the scene no more than once per frame.
For example, the CwHitParticles component by default paints every time a particle hits something. This can be optimized using the Advanced / Skip setting, which allows you to paint once every n times.
If your object has a large texture and you cannot reduce its resolution, then you can still optimize the painting without a loss in detail. This is done by splitting your mesh up into smaller parts, and setting them up as separate objects. If done correctly, when you paint your object only a small area of it will be painted, and thus less pixels will be processed overall.
The easiest example of this is painting a large wall. Instead of having one wall mesh, you can split it up into a grid of smaller sections. If done correctly you will still have the same overall texture resolution, but when painting you will only every paint a small number of meshes in this grid, and thus your painting performance will be greatly improved.
If you're using URP or HDRP, then you may notice painting _MainTex (Albedo) doesn't work, even though it shows up in the inspector list.
This is because these shaders seem to have a 'fake' _MainTex slot that doesn't do anything.
To fix this, you must instead paint the _BaseMap, which is the 'real' albedo texture.
This device can incorrectly paint on Android 7 with the OpenGL ES3 graphics API. Previously painted pixels are observed to randomly become transparent and otherwise change.
If you need to support this device:
This should allow you to paint properly again.
While the painting features can work with any VR asset/toolkit, the Paint in 3D VR examples are only configured to work with Unity's legacy XR system.
Setting up an object to be paintable can be time consuming, so to speed things up Paint in 3D comes with the Preset system.
To use a preset, you can click the Window/CW/Paintable Objects menu option, which will open the Paintable Objects window.
If you select a MeshFilter + MeshRenderer or SkinnedMeshRenderer GameObject, then it will be listed in this window's Scene tab.
Next to each selected object, you will see the Make Paintable button. If you click this button, then you will see a list of presets you can apply to your object.
You can find all built-in presets in the PaintIn3D/Extras/Presets folder.
As you can see, each preset has a list of shader paths that it applies to, as well as a list of CwPaintableMesh and CwPaintableMeshTexture components pre-configured for those shader types.
Feel free to add your own custom shader paths to these presets, or to create your own presets if you have different texture types.
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 this asset) currently supports:
Standard Rendering Pipeline from Unity 2019 on
URP7.x in Unity 2019.3LTS
URP10.x in Unity 2020.3LTS
URP12.x in Unity 2021.2
URP14.x in Unity 2022.2->2022.3LTS
HDRP7.x in Unity 2019.3LTS
HDRP10.x in Unity 2020.3LTS
HDRP12.x in Unity 2021.3LTS
HDRP14.x in Unity 2022.2->2022.3LTS
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 CwLight 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 CwSceneManager 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 CwHitScreen component uses mouse and touch data to paint, so it will not work in VR.
To paint in VR, you can use the CwHitBetween 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 CwHitNearby 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/CW/Paintable Objects 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 CwPaintableMeshTexture 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 CwVrManager component.
The VR examples use the CwInputAxis component to send (legacy) input axis data to functions like CwVrManager.SetLeftTrigger, and you can replace these using the new system.
No, Paint in 3D is only designed for painting in the editor's Game window in play mode or in playable builds.
If you want to be able to paint in the editor's Scene view without play mode, you must get the separate Paint in Editor asset.
Yes, there are two general techniques to do this depending on your requirements.
Paint hits are the high-level data used to paint your scene (e.g. the CwHitScreen component sends hit data to components like CwPaintDecal). Depending on the paint hit type, this just stores the world space position, rotation, seed, and other basic data.
This is the easiest data to send, but since the data is handled in world space and applied to everything in the scene, it's not suitable for moving objects.
To listen for paint hits you can create a new component and add it to the GameObject that has your CwHit___ component. You can then implement any of the IHit___ interfaces, to get specific hit data. For example, the CwHitScreen component can send point and line hit data, so you can implement the IHitPoint and IHitLine interfaces.
When a hit occurs, the HandleHitPoint and HandleHitLine and methods from these interfaces will be invoked. You can then store the given parameters to a file, or send it over the network.
Once this data is loaded/received, you can then broadcast it again using code like this:
// Loop through all components that implement IHitPointforeach (var hitPoint in GetComponentsInChildren
()) {
// Ignore this one so we don't recursively paint
if ((Object)hitPoint != this)
{
// Submit the hit point
hitPoint.HandleHitPoint(preview, priority, pressure, seed, position, rotation);
}
}
You can see the CwPaintMultiplayer.cs code for an example of this.
Paint commands are the low-level data used to paint each individual paintable texture. These store everything about the paint that was applied (e.g. texture references), so it's not as simple to serialize it all.
To allow for de/serialization of this data, you must first provide unique hash codes to the CwPaintableMeshAtlas, CwPaintableMesh, and CwPaintableMeshTexture components. This is done via the Advanced / Hash setting.
In addition to these hashes, you must provide hashes for all textures used by your paint commands. For example, if you use decal painting then the decal texture must have a hash.
Since the Texture class is made by Unity and can't be modified, you must assign a hash to a texture using the CwTextureHash component. You can add this component to your scene, assign the texture, and assign a hash code.
You can now listen for paint commands using the static CwPaintableTexture.OnAddCommandGlobal event, or the instance OnAddCommand event. These events will give you every paint command for a specific paintable texture.
The paint command can then be stored or sent over the network using JsonUtility serialization, or similar.
Once this data is loaded/received, you can apply it using your paintable texture component's AddCommand() method.
You can see the CwCommandSerialization.cs code for an example of this.
This is a list of the in-game example scenes and a description of what it shows.
This shows you how the Spaceship GameObject can be made paintable. This is done by adding the CwPaintableMesh and CwPaintableMeshTexture components. You can then paint the spaceship using the mouse/finger with the Paint GameObject, which has the CwHitScreen and CwPaintSphere components. Keep in mind that CwHitScreen uses raycasts, so your mesh must have a collider to work.
This shows you how to remove painting seams from your mesh using the Mesh Fixer tool. Seams are caused by gaps/islands in the mesh UV data, which are usually present at the edges of complex meshes. To use the mesh fixer, simply click the context menu button (⋮ icon) at the top right of your mesh inspector window. You can then select Fix Mesh (Paint in 3D), adjust the settings, and click Generate. You can double click the Spaceship GameObject's MeshFilter.Mesh setting to see it in action.
This shows you how to automatically fix seams in your mesh without using the Seam Fixer tool. This is done by changing the CwPaintableMesh component''s Advanced / UseMesh setting to AutoSeamFix. Keep in mind this mode doesn''t give you control over the seam fix settings (the defaults should be suitable for most meshes). Also keep in mind there will be a small performance hit the first time you paint your object when its seam fixed mesh is generated.
This shows you what happens when you paint a mesh that isn''t suitable for painting. For a mesh to be paintable, it shouldn''t have overlapping UV, or UV areas that exceed the 0..1 range (e.g. tiling). Notice the paint appears in unexpected areas on this mesh, because it contains both tiling UV, and overlapping areas.
This shows you how painting meshes with overlapping UV data can cause unexpected results. The left shows you what painting the standard Unity Cube mesh looks like, and the right shows what painting the Separated Cube mesh that comes with Paint in 3D looks like.
This shows you how painting the standard Unity Cylinder mesh can give unexpected results, and how the Separated Cylinder mesh that comes with Paint in 3D can avoid these issues.
This shows you how a mesh with UV data unsuitable for painting can still be painted. This is done by enabling the Generate Lightmap UVs setting in the mesh import settings. This setting will generate new UV data in the second UV channel/coord, which can be used by custom shaders. The Paint in 3D / Solid shader has this feature if you enable the Use Second UV setting. If you use this configuration then make sure the CwPaintableMeshTexture.Coord is set to the Second UV channel.
This shows you how the Unsuitable UV demo scene can be modified to allow correct painting on top. This is done by generating mesh data for the second UV channel/coord as seen in the Auto UV demo scene, and using a second transparent material layer on top of the base material. This second material uses the Paint in 3D / Overlay shader, which allows you to paint on top of the base material using the second UV channel. If you use this configuration then make sure the CwPaintableMeshTexture.Coord is set to the Second UV channel.
This shows you an alternative way to paint objects using secondary UV data. The overlay approach requires multiple materials, which may not be suitable for your project. In this scenario, you can use a shader that is specifically designed to allow you to paint on both the first and second UV channels. The P3D Solid shader has the basic albedo/metallic/etc textures that use the first UV channel, but you can also override these using secondary albedo/metallic/etc textures that use the second UV channel. This is done by painting the _AlbedoTex/_MetallicTex/etc, which will override the base texture based on the opacity of the secondary paint. Keep in mind this shader requires you to paint the override textures using the Premultiplied blending mode.
This shows you what happens when you paint objects that have materials with different color settings (top row). Notice how the color tint also applies to the paint, because the material color is multiplied with the painted texture color. To make the painted color apply without tinting you can set the material color to white, and instead change the CwPaintableMeshTexture.Color setting to the base color you want (middle row). You can also set the material color to white, and instead change the default texture (e.g. Albedo texture) to the color you want (bottom row).
This shows you how decreasing the CwPaintSphere.Radius setting and/or increasing the CwHitScreen.Interval setting allows you to draw dotted lines.
This shows you how the CwHitScreen component''s Advanced / ConnectHits setting can be enabled, allowing paint dots to be joined together. A similar result can also be achieved using a lower Interval setting, but that has a performance penalty.
This shows you how the CwButtonClearAll component can be added to a UI element, which makes it clear the paint of all textures in your scene. This also shows you how you can clear the texture of a specific texture by connecting the OnClick event to the CwPaintableMeshTexture.Clear method.
This shows you how the CwButtonIsolate component can be added to UI elements. This turns them into buttons that can enable a GameObject, and disable its siblings. This allows you to switch between different painting tools.
This shows you how the CwPaintSphere component''s Advanced / Tile settings can be used to paint seamless textures across your objects. This is done using triplanar mapping.
This shows you how the paint component''s BlendMode setting can be changed to Blur. This blending mode blurs the pixels of the paintable texture.
This shows you how to prevent the Blur blending mode from causing the pixels outside the edges of your mesh UV islands from ''bleeding'' into your main texture. This is done by setting the CwPaintableMeshTexture component''s Advanced / LocalMask texture. This texture can be created using Paint in 3D if you begin with a black paintable texture, paint it white, and then export the painted texture via the main Paint in 3D window.
This shows you how the CwPaintableMeshTexture component''s Advanced / LocalMask texture can be automatically generated with a mask suitable for use with the Blur blending mode. This is done by adding the CwGenerateMask component alongside your CwPaintableMeshTexture component, and setting its Mesh setting to be the non-seam-fixed (original) version of your mesh. Automatically generating the mask like this means your build size doesn''t increase.
This shows you how the CwHitScreen and CwPaintDecal components can be combined to paint decals. Decals allow you to paint a custom texture on an object at a specific location. The CwPaintDecal settings give you control over the angle, size, opacity, etc.
This shows you how the CwPaintDecal component''s Wrapping setting can be used to control how the decal is applied to curved surfaces. When set to 0, the decal is applied using planar projection without any wrapping. When set to 1 the decal is wrapped around curved surfaces.
This shows you how the CwHitScreen component''s Emit setting can be set to PointsOnUV, allowing you to apply decals directly to your paintable texture in UV space. This is useful when painting complex curved surfaces, because the texture can apply without distortion if your mesh is suitably UV mapped. Keep in mind this mode requires a non-convex MeshCollider for UV data, and for your objects to all have consistent texel sizes. Keep in mind this mode does not support painting between UV seams, and you may get paint bleeding if your UV islands are too close together. This scene also makes use of the Group setting (works like Layers) to avoid cross painting.
This shows you how the CwHitScreen component''s Advanced / Normal settings can be used to control the visibility of the decal based on to the the angle between the decal and the surface being painted. This allows you to enable or disable painting of steep angles, behind surfaces, etc.
This shows you how the CwPaintDecal component''s Advanced / NormalFront setting can be used to force paint to only appear on surfaces that have a surface normal (direction) similar to the surface normal of the hit point (mouse point).
This shows you how the CwPaintDecal component''s Advanced / NormalFade setting can be used to control the sharpness of the normal cut-off transition.
This shows you how the CwPaintDecal settings can be modified from UI buttons by calling the various functions like IncrementAngle, FlipVertical, etc.
This shows you how the Mirror GameObject has the CwCloneMirror component attached. This automatically mirrors all paint across a 3D plane defined by its Transform position and rotation. If you select the Mirror GameObject then you can see a preview of the mirror plane in the Scene view.
This shows you how the Mirrored Painting demo scene can be modified to prevent decals from appearing backwards when mirrored. This is done by enabling the CwCloneMirror.Flip setting, which makes the decals appear the same on both sides.
This shows you how mirrors can combine together, creating interesting symmetries.
This shows you how to apply paint when a Rigidbody collides with something. The CwTapThrow component can be used to spawn and throw the Ball prefab when you click or tap the screen. The ball then paints the spaceship on impact using the CwHitCollisions and CwPaintDecal components.
This shows you how to automatically destroy a GameObject itself when it hits something. This is done by adding the CwDestroyer component alongside the CwHitCollisions component.
This shows you how to spawn an explosion effect when a Rigidbody hits something. This is done by adding the CwSpawner component alongside the CwHitCollisions component. The spawned prefab contains a ParticleSystem, and uses the CwDestroyAfterTime component to destroy itself.
This shows you how the CwHitBetween component can be used to paint between two Transform points. The CwHitBetween.Line can be used to visualize the current beam, and the CwHitBetween.Point setting can be used to vislize the hit point with particles.
This shows you how to paint everything at the center of the screen directly in front of the camera, like a laser eye beam. This is done using the CwHitBetween component, which is set to hit between the Main Camera Transform, and the In Front Of Camera Transform, which is a child GameObject placed in front. This will then automatically call CwPaintSphere on the first hit point it finds between these two points, and paint them red. The camera can then be rotated using the CwPitchYaw component.
This shows you how the CwHitThrough component can be used to paint trhough two Transform points. The CwHitThrough.Line setting can be used to visualize the current beam. Unlike CwHitBetween, this component paints all surfaces between the two points.
This shows you how the CwHitParticles component can be added to your ParticleSystem GameObjects. This allows you to paint with components like CwPaintSphere when particles hit objects in the scene. Keep in mind you must enable collision in your particle system for this to work.
This shows you how particle painting can be greatly optimized. By default, the CwHitParticles component paints once per particle collision. However, this can be incredibly slow if you emit too many particles. To optimize this, you can use the CwHitParticles component's Advanced / Skip setting, which allows you to paint once every 'Skip' particles. In this scene Skip = 10, which means for every particle collision that would result in a call to CwPaintSphere, 9 calls are skipped.
This shows you how the CwHitNearby and CwPaintSphere components can be combined to paint any surfaces within the specified sphere shape.
This shows you how the CwTapThrow component can spawn and throw the Ball prefab. This prefab has the CwHitNearby component, which can paint surfaces near the current Transform position. This effect can be used to create fireballs that pass through objects, and paint them on the way.
This shows you how the CwPaintableMeshTexture.SaveName setting can be used to enable automatic save/load. Paint something, then run the scene again to see it in action. Keep in mind these save names should be unique, so using the same name with multiple prefabs may not work as expected.
This shows you how the CwPaintableMeshTexture.UndoRedo setting can be used to store undo and redo states. You can then add the CwButtonUndoAll and CwButtonRedoAll components to UI elements to cycle through them. Keep in mind storing of states requires the StoreStates setting to be enabled, this is on components like CwHitScreen.
This shows you how the paint settings can be randomly adjusted before the paint is applied. This is done by clicking the Add Modifier button inside the paint component (e.g. CwPaintDecal), and selecting a value to modify (e.g. Angle), and then the type of modification (e.g. Random). Keep in mind these modifiers can be combined together to make even more interesting results.
This shows you how to gradually fade a texture back to its original state after you paint it. This is done using the CwGraduallyFade component, and dragging and dropping the texture you want to have fade into the PaintableTexture setting. You can then set the BlendMode setting to ReplaceOriginal, and it will gradually fade to its original state as defined by the CwPaintableMeshTexture component''s Texture and Color settings.
This shows you how the Gradually Fade demo scene can be modified to blur the texture over time.
This shows you how the Gradually Fade demo scene can be modified to fade a normal map to its original state. This is done by using the Normal Replace blending mode and the DefaultNormal texture. Keep in mind the ReplaceOriginal blending mode can''t be used with normal maps, because the original texture and color are converted into normal maps, and this would cause them to be replaced by their non-converted state.
This shows you how to paint holes in your paintable objects. This is done using the Subtractive blending mode, which allows you to reduce the alpha/opacity of the pixels in your texture. Keep in mind this requires you to use a shader/material that supports transparency, like the P3d Solid one used here. Keep in mind the underlying mesh still remains, so you can''t paint through the holes you create.
This shows you how the CwPaintReplace component can be used to replace every pixel in the currently painting texture. Keep in mind the GameObject with the CwPaintableMeshTexture must have a collider for this to work, and CwHitScreen.Emit must be set to PointsOnUV.
This shows you how the CwPaintFill component can be used to blend every pixel in the painted texture. This allows you to gradually change it, rather than instantly like CwPaintReplace does. Keep in mind the GameObject with the CwPaintableMeshTexture must have a collider for this to work, and CwHitScreen.Emit must be set to PointsOnUV.
This shows you how to paint an object in from an invisible state. This is done by changing the CwPaintableMeshTexture.Color setting''s alpha/opacity value to 0, which causes the texture to initialize as invisible. You can then reveal the object by painting the alpha/opacity back in, which is automatically done when using the Alpha Blend blending mode. Keep in mind this requires you to use a transparent material/shader like the Paint in 3D / Solid one used here.
This shows you how a textured mesh can be hidden, and then revealed by painting on it. This is done by changing the CwPaintableMeshTexture.Color alpha/opacity value to 0. The texture can then be revealed by painting with the Additive blending mode, with a color of RGBA 0,0,0,1. Keep in mind this requires your mesh to use a transparent (e.g. cutout) shader/material.
This shows you how to paint on top of a transparent material. This is done using the Alpha Blend blending mode. Notice how the erase tool erases both the paint, and the original dirt.
This shows you how the Glass Painting demo scene can be modified so the paint is applied to secondary albedo and opacity textures that override the base values. Notice how the erase tool only erases the new paint, and keeps the original dirt. This technique also allows you to paint at a lower resolution, but keep the original higher resolution texture, allowing you to optimize performance. Keep in mind this configuration requires you to use a special mater/shader designed to override the base texture values (the Paint in 3D / Alpha shader is used here). Keep in mind the override textures use premultiplied alpha, so you must set your paint tools to use the Premultiplied blending mode (though erasing can use the subtractive blending mode).
This shows you how the CwChannelCounter component can be used to count the total pixels in the specified CwPaintableMeshTexture that exceed the threshold value in each R/G/B/A channel. The CwChannelCounterText component can then be used to display these in the UI.
This shows you how the Channel Counter demo scene can be modified to accurately display how much of a mesh you have painted. This is done by setting the Spaceship GameObject\u2019s CwChannelCounter.Mesh setting to the original non-seam-fixed mesh. The paint percentage can then be displayed using the CwChannelCounterText and CwChannelCounterFill components. To make the paint work with any color this spaceship paint uses a second layer on top, similar to the Paint On Top demo scene.
This shows you how the CwColorCounter component can be used to count the total pixels in the specified CwPaintableMeshTexture that are within the threshold color of a CwColor. The CwColorCounterText component can then be used to display these in the UI.
This shows you how the CwChangeCounter component can be used to count how many pixels in the specified texture are different to a reference state. The reference state can be set using the CwChangeCounter component''s Texture and Color settings.
This shows you how the Alpha Blend Inverse blending mode can be used to paint transparent areas of your texture. This gives the effect of painting undernearth your existing paint.
This shows you how the Replace Original blending mode can be used to paint your object back to its original state based on the CwPaintableMeshTexture component''s Texture and Color settings.
This shows you how the Replace Custom blending mode can be used. This works similar to Replace Revert, but you can specify custom Texture and Color values per paint tool.
This shows you how to paint decals with dynamically changing content. This is done using a RenderTexture, making a second camera, and changing its TargetTexture setting to the RenderTexture. Keep in mind you must correctly set up your layers and Camera.CullingMask values to keep each camera isolated. Also keep in mind dynamic decals can''t be undone using the CwPaintableMeshTexture.State = LocalCommandCopy setting.
This shows you how to create live paint that can be repositioned in game. This is done using the CwHitNearby component with the Preview setting enabled. You can control the draw order of these decals using the Priority setting.
This shows you how live paint can be applied to your objects when you press a button. This is done by linking the button's OnClick event to the CwHitNearby component's ManuallyHitNow function.
This shows you how the CwTranslate component can be used to move a live decal around the scene using UI button events that call the CwTranslate.TranslateX/Y/Z functions.
This shows you how to optimize painting speed using different LOD meshes for visuals and painting. The Knot_High GameObject is used to render the high poly visual mesh. The Knot_Low GameObject is used for the low poly MeshCollider, and for painting. To make the paint apply on the high poly mesh, the CwPaintableMesh.OtherRenderers list contains the Knot_High MeshRenderer.
This shows you how to paint multiple separate objects that share the same texture. This is done by setting up one paintable object normally, and then dragging and dropping the other objects into the CwPaintableMesh component's Advanced / OtherRenderers list. You must then add the CwPaintableMeshAtlas component to the other objects, and drag and drop the first object into the CwPaintableMeshAtlas.Parent setting.
This shows you how to paint filled in polygon shapes. This is done by replacing the CwHitScreen component with the CwHitScreenFill component. This causes the polygon shape you draw to be filled in with a grid of points. Keep in mind the points are drawn in screen space, so the resolution depends on the camera distance to the paint surface.
This shows you how the CwMask component can be added to the scene. This allows you to define an area where paint will be blocked, allowing you to paint within a specific shape. You can see the location of the mask in the Scene window after you select the mask.
This shows you how the CwMask component''s Stretch setting can be used to extend the edges of the mask without modifying the mask texture. This allows you to more easily block painting across a large area without requiring a high resolution mask texture.
This shows you how normal maps can be painted. This is done by opening the advanced settings for the CwPaintableMeshTexture component, and changing the Conversion setting to Normal, as well as changing the Slot to _BumpMap. You can then paint using the Normal Blend blending mode. Keep in mind the normal maps use all four RGBA channels to store data, so you must set the shape of the decal separately with the Shape setting.
This shows you how to read the paint pixel color under the mouse/finger. This is done using the CwReadColor component, which can be added alongside any CwHit___ component that works using raycasts like CwHitScreen and CwHitBetween. Keep in mind the hit component must be set to emit PointsOnUV. The OnColor event is then used to change the UI Image color to the read color.
This shows you how to detect when a specific color has been read, and trigger an action from it. This is done using the CwReadColorEvent component, which can be added alongside the CwReadColor component. When you read a color within the Threshold distance of your specified Color, it will trigger the OnColor event, which can be used to perform any action.
This shows you how the CwReadColor and CwPaintBetween components can be combined, allowing you to read the color under a specific GameObject, and display that color in the UI.
This shows you how the CwPaintMultiplayer component can be added to your paint tool to simulate painting over a network. To make this work using actual multiplayer, the SimulateNetworkTransmission coroutine must be replaced with actual network transmission code, which will differ depending on the network solution you''re using.
This shows you how to set up a GameObject to be paintable from scratch using C# code. See the CwProceduralSetup script in the PaintIn3D/Examples/Scripts folder for more details.
This shows you how to paint the underlying triangles of your mesh. This is done by changing the CwHitScreen component's Emit setting to TrianglesIn3D.
This shows you how basic painting can be used to reveal a complex design. This is done using the ReplaceOriginal blending mode on your paint tool, which will revert a CwPaintableMeshTexture to its current Texture and Color settings. The texture that will be revealed is first hidden using the CwPaintableMeshTexture.Color setting with 0 alpha. The CwPaintableMesh.OnActivated event is then used to reset this back to full alpha using the CwPaintableMesh.SetColor event, with a hex color of #FFFF.
This shows you how the Graffiti scene can be modified to count the % of the design you have painted. This is done using the CwChangeCounter component, which monitors the graffiti texture. This component''s MaskTexture is set to read the final graffiti design''s alpha channel so it ignores pixels outside of the design. The Texture setting is then set to the final design, so the currently painted/revealed graffiti texture is compared against the final design.
This shows you how to make painted decals change direction based on the angle of your mouse/finger as you paint. This is done by changing the CwHitScreen component''s RelativeTo setting to DrawAngle when RotateTo = Normal. Keep in mind the draw angle isn''t known on the first frame your mouse/finger touches the screen, so the first paint hit is skipped.
This shows you how to mask specific areas of your texture using your mesh UV, rather than being in 3D like with CwMask. This is done using the CwPaintableMeshTexture component''s LocalMask setting inside the Advanced settings.
This shows you how to paint decals under the mouse from code. Check out the PaintIn3D/Examples/Scripts/CwPaintFromCode.cs code to see how it works!
This shows you how the Flow blend mode can be used to move the pixels in the texture you paint using a normal map that defines which direction and how far they should move. The maximum distance of the flow samples can be controlled from the Kernel setting.
This shows you how to make paint flow across the surface of your object over time. This is done using the CwGraduallyFade component with BlendMode = Flow. This allows you to set a normal map in the Texture setting that allows you to control how the paint should flow.
This shows you how the Flow / Gradually demo scene can be modified so the paint begins at full speed, but gradually slows down until it stops. This is done by adding a second paintable ''Speed'' texture to your object. Since this speed texture isn''t applied to the material, you must enable the Advanced / IsDummy setting. Like the albedo texture, this speed texture uses CwGraduallyFade to twist the texture around, but it also has a second CwGraduallyFade to fade it to black to slow down the speed. The albedo texture''s CwGraduallyFade.MaskPaintableTexture is then set to this speed texture, which will cause its flow speed to depend on the speed texture''s red channel. You can then paint both the albedo and speed textures at the same time to make the effect work. Keep in mind both of these textures must use a different CwGraduallyFadeGroup setting.
This shows you how to make a liquefy paint effect, where the painted pixels will move based on the direction you move the mouse/finger when painting. This is done using the Flow blend mode with a normal map pointing up. The flow is rotated using the CwHitScreen component''s RotateTo / Relative To = DrawAngle setting.
This shows you how to configure the four basic primitives to be paintable, so that any paintable pixels that enter them get painted. This is done using a combination of CwHitNearby and CwHitThrough components with the CwPaintSphere and CwPaintDecal components to continuously paint any pixels that enter the current volume. Keep in mind the CwPaintDecal.NormalFront setting should be set to 2 to apply paint even if it's applying to steep or back faces.
This shows you how to paint points or lines between the mouse/finger start and end positions. This is done using the CwHitScreenLine component, which can be combined with the CwPaintSphere/Decal component. This component''s Frequency setting can be used to control how many and where the points/lines are drawn. The ConnectHits setting can also be used to switch between drawing points and lines. Keep in mind painting lines on complex geometry requires you to paint many points, otherwise they will go through the geometry.
This shows you how the CwHitScreen and CwHitScreenLine components can be used together to draw lines. This is using a combination of other settings, like Frequency, and setting Rotate To / Relative To to Draw Angle.
This shows you how the CwPaintDebug component can be added alongside your other paint components. This will show you where Paint in 3D is applying the paint in the Scene view. This allows you to easily diagnose painting problems. Keep in mind this feature requires you to enable Gizmos.
This shows you how to make paint gradually appear after you paint it, rather than instantly. This is done by configuring two CwPaintableMeshTexture components as normal. However, the first should have its Group setting changed to an unused group (e.g. DUMMY), and the second should have its Advanced/IsDummy setting enabled to prevent it from applying to the object''s material. A CwGraduallyFade component is then used on the first paintable texture with the Replace blend mode, and the BlendPaintableTexture set to the second paintable texture. In effect this means your paint will apply to the second paintable texture, and this paint will be gradually copied over to the first. The other settings are just to prevent paint from applying directly to the first paintable texture.
This shows you how to listen for and store paint commands that get added to any CwPaintableMeshTexture component in the scene. You can then click a button to reset all paintable textures, and randomly apply one of the recorded paint commands. See the PaintIn3D/Examples/Scripts/CwCommandSerialization.cs code to see how this works. Keep in mind this is an advanced technique that requires good C# knowledge.
This shows you how to eliminate the overlap points from transparent painting when using the Advanced / Connect Hits setting. This is done by enabling the Advanced / Clip Connected setting, which blends connected lines together.
This shows you how to make a mask texture at runtime from a camera. This is done by making a new camera with its TargetTexture set to a RenderTexture in your project. A separate Screen Space - Camera UI is used to render to this camera (you could also render 3D objects). The RenderTexture is then added to a CwMask in the scene. In this example only the Red channel of the mask is used, so the RenderTexture uses the R8 format to save memory.
This shows you how to initialize a paintable texture with texture tiling. This is done using the CwHitNearby component with the PaintIn setting set to Start. The CwPaintSphere component is then used to apply the paint. This component's Advanced/TileTransform can be set to any GameObject/Transform that has scaling, and you can set the Advanced/TileTexture to your desired texture. When you enter play mode, these components will activate and apply the paint to your scene. Make sure the CwPaintSphere.Radius setting is large enough to encompass your object. To isolate painting to just one paintable texture you can drag and drop your object into the CwPaintSphere component's Advanced/TargetModel setting.
This shows you how to mask paint behind foreground objects. This is done with the CwRenderDepth component, which can render the scene depth from the perspective of a camera. All paint components with the Advanced / FindDepthMask enabled (it''s enabled by default) will then be depth masked.
This shows you how to make paint that expands or rotates over time. This is done using the CwHitScreen and CwSpawner components, which will spawn a prefab under the mouse/finger when you click/tap the screen. The spawned prefab has the CwHitNearby and CwPaintDecal components, which make the spawned prefab paint every frame/Update. The prefab also has the CwPaintAction component, which is used to call the CwPaintDecal.MultiplyScale or CwPaintDecal.IncrementAngle functions to animate the paint. Finally, the CwDestroyAfterTime component is used to destroy the prefab after some time.
This shows you how to paint holes and dents on a transparent target object. The bullet mark ignores transparent areas using the Alpha Blend blending mode, with only the RGB channels (1, 1, 1, 0), skipping modifications to the alpha channel.
This shows you how the Undo Redo demo scene can be combined with Sphere and Decal painting so you can paint on a car.
This shows you how the Seamless Painting and Blur Painting demo scenes can be combined to create a chalkboard you can draw on and erase from in a realistic way.
This shows you how to apply dirt to an object using the P3D/Solid shader''s albedo override texture. You can then clear the paint by changing your brush to the Replace blending mode, with a color of transparent black (RGBA = 0000). The CwColorCounter/Fill/Event components can then be used to show how much has been cleaned, and show the "CLEAN" text when it''s below 2%.
This shows you how the Collision Painting and Flow / Time demo scenes can be combined to create a paint dripping effect that slows to a stop over time. Unlike the Flow / Time demo scene, this uses a downward facing flow texture, so the albedo and speed textures flow down the wall.
This shows you how the Nearby Painting / Throw demo scene can be modified to cut holes through an object.
This shows you how the Color Counter demo scene can be modified to paint splats of color.
This shows you how to paint the Albedo, Normal, and PBR (Metallic + AO + Smoothness) textures at the same time using the Group feature. You can assign a texture group using the CwPaintableMeshTexture.Group setting, and to paint these textures a matching CwPaintSphere.Group/CwPaintDecal.Group setting can be used.
This shows you how the albedo and normals can be painted at the same time, creating a rock engraving effect.
This shows you how two CwPaintCollisions components can be used with different layer filtering and different Root settings, allowing you to apply different kinds of paint to different objects. The CwPaintDecal component and CwPaintableTexture''s GameObject must have matching layers for this to work.
This shows you how CwHitCollisions and CwPaintSphere can be added to a Rigidbody GameObject. This allows them to paint the Spaceship_Shield GameObject with a special impact pattern. The CwGraduallyFade component is then used to gradually fade the texture back to transparent black, simulating a spaceship shield effect.
This shows you how to paint a background skybox without seams or distortion. Notice the skybox mesh is a subdivided cube turned into a sphere with cube mapped UV coordinates. The mesh is then run through the Seam Fixer tool.
This shows you how to paint an RGBA splat map. This is done using the Splat (R, G, B, A) group, with the Replace blending mode. Each paint tool replaces the splat texture with a specific channel color (e.g. 0,1,0,0 for green). It''s also possible to use the Additive & Subtractive blending modes on each channel instead. Keep in mind splat maps require your object to have a special material/shader that implements splat maps.
This shows you how to paint an object using a spray can that emits paint particles. This is done using the CwToggleParticles component.
This shows you how the albedo of a transparent object with overlapping UV data can be painted using auto generated UVs and secondary textures.
This shows you how PBR spray painting can be implemented in VR using Unity''s XR library. Make sure to enable Virtual Reality Supported in your project settings. Also, make sure to select the VR Manager GameObject, and check to see if each input axis is set up. If you''re using the new InputSystem, then please read the documentation for it.
This shows you how VR pen painting can be implemented in VR using Unity''s XR library. Make sure to enable Virtual Reality Supported in your project settings. Also, make sure to select the VR Manager GameObject, and check to see if each input axis is set up. If you''re using the new InputSystem, then please read the documentation for it.
This shows you how to particle collision painting can be used to apply dirt to a car as its wheel kick up dust.
This shows you how to paint dynamic blood decals on an animated SkinnedMeshRenderer GameObject. These decals are painted using the Multiply RGB blending mode, which causes them to stack and get darker. Keep in mind the zombie uses a big BoxCollider, so the decal must extend quite far into the zombie to paint it. This is done using a high CwPaintDecal.Scale.z setting, and with the CwHitScreen.Normal = RayDirection setting, to rotate the depth so it faces the paint direction.
Here's a list of all my other assets, please check them out!
You can also view this list on my Asset Store page.
Rapidly develop your game with consistent input across desktop & mobile using Lean Touch. This lightweight asset comes with many modular components, allowing you to customize them to your exact project needs!
Lean Touch+ is an extension to the popular Lean Touch asset, adding many more example scenes.
Lean Localization is a localization library that's designed to be as simple to use as possible for both designers, and programmers.
Quickly optimize the performance of your games using Lean Pool. Within minutes you can use this lightweight asset to preload, recycle, and limit the spawning of your prefabs.
Quickly polish your games using Lean Transition. This asset allows you to easily tween or animate almost anything in your game, making it transition smoothly.
Lean GUI is a colllection of components that extend Unity's GUI system, allowing you to rapidly enhance the user experience (UX) of your game's UI.
Lean GUI Shapes allows you to quickly add lines, rounded boxes, polygons, and much more to your GUI!
Lean Texture allows you quickly modify textures in your project with a range of filters, pack them together into channels, and much more!
Lean Texture+ is an extension to Lean Texture, adding many new types of texture modification tools!
Unlock a universe of visual possibilities with Modular Backgrounds. Simply drag and drop these graphics into the background of your scenes.
Paint all your objects using Paint in 3D - both in game, and in editor. All features are optimized with GPU accelerated texture painting, so you can enjoy consistent performance, even if you paint your objects one million times!
Paint all your sprites with Paint in 2D. With incredible performance on mobile, WebGL, and much more!
Paint in Editor unlocks the ability to paint objects in your scene - great for making small tweaks, or even creating entirely new texture sets!
FLOW allows you to add large scale interactive fluids to your scene - all highly optimized using GPU acceleration.
Unlock the full potential of your 2D games using Destructible 2D, this asset allows you to quickly convert all your boring solid sprites into fully destructible ones!
Quickly make the space scene of your dreams using Space Graphics Toolkit. This huge collection of space effects can be customized and combined in any way you like, allowing you to quickly make realistic or fantasy worlds. Each feature has been heavily optimized to run on almost any device and platform.
Enhance your space scenes using this large pack of high detail volumetric planets. These planets are finished using the powerful planet features from Space Graphics Toolkit (not required).
Unity sounds only emanate from a single point source. This is great for explosions and footsteps, but quite often you need something more advanced. Volumetric Audio is an easy to use package that allows you to define boxes, spheres, capsules, paths, or meshes that sounds can emanate from.
Added Car Decals Advanced demo scene.
Added Clean Dirt demo scene.
Added HasRead property to all Cw___Counter components.
Fixed Cw___CounterEvent components firing on the first frame before the counters have updated.
Added Show setting to example shaders to change backface culling.
Added Multitap setting to CwRenderDepth component to remove edge seams.
Rewrote MeshFixer's FixSeams setting when fixing meshes with multiple UV sets.
Updated shaders to latest version.
Added CwPaintableTexture.ClearCommand method.
Added CwPaintSphere.MultiplyOpacity method.
Added CwPaintSphere.IncrementRadius method.
Added CwPaintSphere.IncrementScale method.
Added CwPaintDecal.MultiplyOpacity method.
Added CwPaintDecal.IncrementRadius method.
Added CwPaintDecal.IncrementScale method.
Added WaitUntilNotPainting setting to all Cw___Counter components.
Added ReadAtStart setting to all Cw___Counter components.
Enabled manual editing of CwChannelCounter component's Total and CountR/G/B/A values.
Enabled manual editing of CwChangeCounter component's Total and Count values.
Rewrote non-async texture reading to be spread across multiple frames.
Added ReadPixelsBudget setting to CwPaintableManager component.
Moved most hit components from PaintCore to PaintIn3D.
Added Advanced/AutoStoreState setting to CwPaintableSpriteTexture component.
Undo/Redo states are now only created if you actually paint something (when a hit command is sent to a texture).
Added Expanding Paint demo scene.
Fixed potential CwPaintableMeshTexture error when creating paintable objects from script.
Added Advanced/MaterialApplication setting to CwPaintableMesh component.
Removed TargetTexture setting from CwRenderDepth component (it's now auto generated).
Fixed CwDepthMask not working in some scenarios.
Replaced CwPaintSphere component's DepthMask setting with FindDepthMask toggle.
Replaced CwPaintDecal component's DepthMask setting with FindDepthMask toggle.
Added Advanced/FindMask setting to CwPaintDecal component.
Added Advanced/FindMask setting to CwPaintSphere component.
Disabled Mesh Fixer asset's Fix Seams setting by default.
Showed Mesh Fixer asset's Recenter UV setting.
Fixed Mesh Fixer asset's naming when fixing non-imported meshes.
Fixed Mesh Fixer asset's Remap feature.
WARNING: This is a massive update that includes file structure changes, so before installing you should delete the "PaintCore" and "PaintIn3D" and "PaintInEditor" folders.
Removed in-editor painting features (customers prior to the release of this version can download the new Paint in Editor asset for free).
Renamed all scripts to have Cw prefix instead of P3d prefix.
Renamed Paint in 3D window to Paintable Objects.
Renamed P3dPaintable to P3dPaintableMesh.
Renamed P3dPaintableTexture to P3dPaintableMeshTexture.
The Material Cloner is no longer required.
The Seam Fixer tool has been replaced with the Mesh Fixer tool.
The new Mesh Fixer implements UV unwrapping.
The new Mesh Fixer can fix meshes that go outside the 0..1 UV range.
The Preset system is now much simpler and intuitive to use.
Fixed normal map painting when Normal Map Encoding is set to DXT5nm.
Fixed P3dHitScreen painting bug with connected preview hits.
Fixed P3dHitScreen not showing clip connected preview hits.
Renamed SlidingToolButton to ToolButton.
Adding the P3dHitScreen component will automatically add the P3dPointerMouse/Touch/Pen components.
Moved main build to Unity 2021.3.0f1.
Updated shaders to latest version.
Fixed P3dCloneMirror component when the Flip setting is enabled.
Fixed P3dCoordCopier index counts.
Fixed P3d___Counter components updating when not necessary.
Added P3dRenderDepth component.
Added Advanced/DepthMask setting to P3dPaintSphere component.
Added Advanced/DepthMask setting to P3dPaintDecal component.
Added Depth Mask demo scene.
Fixed P3dHitScreen component's GuiLayers setting.
Fixed P3dHitScreenLine component painting.
Fixed P3dHitScreenFill component painting.
WARNING: To update from an earlier version: back up your project, delete the old Plugins/CW/PaintIn3D folder, and then install the new version.
Moved main build to Unity 2020.3.0f1.
Moved in-editor painting features to Plugins/CW/PaintInEditor folder.
Fixed in-editor triangle painting.
Fixed manual disabling of P3dPaintable components.
Fixed in-editor painting not painting alpha.
Added P3dPointerMouse component.
Added P3dPointerTouch component.
Added P3dPointerPen component.
Added AlphaFromAlbedo setting to P3dMaterial component.
Added Min blending mode.
Added Max blending mode.
Added Initial Tiling demo scene.
Moved main build to Unity 2020.3.0f1.
Fixed in-editor triangle painting.
Fixed manual disabling of P3dPaintable components.
Fixed in-editor painting not painting alpha.
Added AlphaFromAlbedo setting to P3dMaterial component.
Fixed P3dHitBetween when Orientation = WorldUp.
Improved P3dMask component gizmo rendering.
Added NormalReplaceOriginal blending mode.
Added NormalReplaceCustom blending mode.
Fixed P3dGraduallyFade colors being incorrect during transition.
Added Default Format setting to Config tab of the Paint In 3D window.
Added unlit versions of the 4 main example shaders.
Removed global shader keywords.
Fixed P3dChannelCounter component setting changes not being reflected.
Fixed P3dChangeCounter component setting changes not being reflected.
Fixed P3dColorCounter component setting changes not being reflected.
Every P3dColorCounter now updates when a P3dColor is enabled or disabled.
Fixed P3dReadColor reading incorrect UV location on the Metal graphics API.
Changed Solid shader's Tiling setting to be a vector.
Changed Alpha shader's Tiling setting to be a vector.
This component invokes the Action event when this component is enabled.
The event that will be invoked.
This defines the blending mode used by a painting operation.
This is the index of the currently selected blending mode.
When using the ReplaceCustom blending mode, this allows you to specify the replacement color.
When using the ReplaceCustom blending mode, this allows you to specify the replacement texture.
When using the Blur or Flow blending modes, this allows you to set the maximum pixel distance of samples.
This allows you to control which channels will be modified by this blending mode.
1,1,1,1 = All channels will be modified.
1,0,0,0 = Only red will be modified.
This component allows you to perform the Clear action. This can be done by attaching it to a clickable object, or manually from the ClearAll method.
When clearing a texture, should its undo states be cleared too?
This component allows you to perform the Undo All action. This can be done by attaching it to a clickable object, or manually from the RedoAll method.
The renderer whose color will be changed.
The material index in the target renderer.
The material property that will be changed.
How should the new color be applied to the target renderer?
If you want to manually trigger Recolor, then call this function.
This component allows you to perform the Redo All action. This can be done by attaching it to a clickable object, or manually from the RedoAll method.
If you want to manually trigger RedoAll, then call this function.
This component allows you to perform the Undo All action. This can be done by attaching it to a clickable object, or manually from the RedoAll method.
If you want to manually trigger UndoAll, then call this function.
This component will check all pixels in the specified paintable texture, compare them to the reference state defined in this component, and tell you how many of them differ by more than the threshold value.
This stores all active and enabled instances.
The RGBA values must be within this range of a color for it to be counted.
The texture we want to compare change to.
None/null = white.
The color we want to compare change to.
The previously counted amount of pixels with a RGBA value difference above the threshold.
The Count / Total value.
This will return true once this counter has updated at least once.
The Total of the specified counters.
The Count of the specified counters.
The Ratio of the specified counters.
This component allows you to perform an event when the specified CwChangeCounter instances are painted a specific amount.
This allows you to specify the counters that will be used.
None = All active and enabled counters in the scene.
This paint ratio must be inside this range to be considered inside.
This tells you if the paint ratio is within the current Range.
This event will be called on the first frame Inside becomes true.
This event will be called on the first frame Inside becomes false.
This tells you the current paint ratio of the specified Color, where 0 is no paint, and 1 is fully painted.
This component fills the attached UI Image based on the total amount of pixels that have been painted in the specified CwChangeCounterFill components.
This allows you to specify the counters that will be used.
Zero = All active and enabled counters in the scene.
Inverse the fill?
This component will output the total pixels for the specified team to a UI Text component.
This allows you to specify the counters that will be used.
Zero = All active and enabled counters in the scene.
Inverse the Count and Percent values?
This allows you to set the amount of decimal places when using the percentage output.
This allows you to set the format of the team text. You can use the following tokens:
{TOTAL} = Total amount of pixels that can be painted.
{COUNT} = Total amount of pixel that have been painted.
{PERCENT} = Percentage of pixels that have been painted.
The color count will be output via this event.
This component will total up all RGBA channels in the specified CwPaintableTexture that exceed the threshold value.
This stores all active and enabled instances.
The RGBA value must be higher than this for it to be counted.
The previously counted amount of pixels with a red channel value above the threshold.
The previously counted amount of pixels with a green channel value above the threshold.
The previously counted amount of pixels with a blue channel value above the threshold.
The previously counted amount of pixels with a alpha channel value above the threshold.
The CountR/Total value, allowing you to easily see how much % of the red channel is above the threshold.
The CountG/Total value, allowing you to easily see how much % of the green channel is above the threshold.
The CountB/Total value, allowing you to easily see how much % of the blue channel is above the threshold.
The CountA/Total value, allowing you to easily see how much % of the alpha channel is above the threshold.
The RatioR/G/B/A values packed into a Vector4.
This will return true once this counter has updated at least once.
The Total of the specified counters.
The CountR of the specified counters.
The CountG of the specified counters.
The CountB of the specified counters.
The CountA of the specified counters.
The CountR / Total of the specified counters.
The CountG / Total of the specified counters.
The CountB / Total of the specified counters.
The CountA / Total of the specified counters.
The GetCountR/G/B/A / GetTotal of the specified counters stored in a Vector4.
This component allows you to perform an event when the specified CwChannelCounter instances are painted a specific amount.
This allows you to specify the counters that will be used.
None = All active and enabled counters in the scene.
This allows you to choose which channel will be output to the UI Text.
This paint ratio must be inside this range to be considered inside.
This tells you if the paint ratio is within the current Range.
This event will be called on the first frame Inside becomes true.
This event will be called on the first frame Inside becomes false.
This tells you the current paint ratio of the specified Channel, where 0 is no paint, and 1 is fully painted.
This component fills the attached UI Image based on the total amount of opaque pixels that have been painted in all active and enabled CwChannelCounter components in the scene.
This allows you to specify the counters that will be used.
Zero = All active and enabled counters in the scene.
This allows you to choose which channel will be output to the UI Image.
Inverse the fill?
This component allows you to output the totals of all the specified pixel counters to a UI Text component.
This allows you to specify the counters that will be used.
Zero = All active and enabled counters in the scene.
This allows you to choose which channel will be output to the UI Text.
Inverse the Count and Percent values?
This allows you to set the amount of decimal places when using the percentage output.
This allows you to set the format of the team text. You can use the following tokens:
{TOTAL} = Total amount of pixels that can be painted.
{COUNT} = Total amount of pixel that have been painted.
{PERCENT} = Percentage of pixels that have been painted.
The color count will be output via this event.
This is the base class for all components that repeat paint commands (e.g. mirroring).
This stores all active and enabled instances in the open scenes.
This component grabs paint hits and connected hits, mirrors the data, then re-broadcasts it.
When a decal is mirrored it will appear backwards, should it be flipped back around?
This component allows you to define a color that can later be counted from the CwColorCounter component.
The color associated with this component and GameObject name.
This stores all active and enabled instances in the open scenes.
This tells you how many pixels this color could be painted on.
This tells you how many pixels this color has been painted on.
This is Solid/Total, allowing you to quickly see the percentage of paintable pixels that have been painted by this color.
This component will search the specified paintable texture for pixel colors matching an active and enabled CwColor.
This stores all active and enabled instances.
The RGBA values must be within this range of a color for it to be counted.
Each color contribution will be stored in this list.
This will return true once this counter has updated at least once.
The Total of the specified counters.
The Count of the specified counters.
The Ratio of the specified counters.
This tells you how many pixels of the specified color are in the current PaintableTexture.
This component allows you to perform an event when the specified CwColorCounter instances are painted a specific amount.
This allows you to specify the counters that will be used.
None = All active and enabled counters in the scene.
This allows you to set which color will be handled by this component.
This paint ratio must be inside this range to be considered inside.
This tells you if the paint ratio is within the current Range.
This event will be called on the first frame Inside becomes true.
This event will be called on the first frame Inside becomes false.
This tells you the current paint ratio of the specified Color, where 0 is no paint, and 1 is fully painted.
This component fills the attached UI Image based on the total amount of pixels that have been painted in the specified CwColorCounter components.
This allows you to specify the counters that will be used.
Zero = All active and enabled counters in the scene.
This allows you to set which color will be handled by this component.
Inverse the fill?
This component will output the total pixels for the specified color to the OnString event.
This allows you to specify the counters that will be used.
Zero = All active and enabled counters in the scene.
This allows you to set which color will be handled by this component.
Inverse the Count and Percent values?
This allows you to set the amount of decimal places when using the percentage output.
This allows you to set the format of the team text. You can use the following tokens:
{TOTAL} = Total amount of pixels that can be painted.
{COUNT} = Total amount of pixel that have been painted.
{PERCENT} = Percentage of pixels that have been painted.
The color count will be output via this event.
This is the base class for all paint commands. These commands (e.g. paint decal) are added to the command list for each CwPaintableTexture, and are executed at the end of the frame to optimize state changes.
This is the original array index, used to stable sort between two commands if they have the same priority.
Is this preview painting, or real painting?
The draw order priority of this command for this frame.
The hash of the Material used to apply this paint command.
The material pass that will be used.
The hash of the Model used to apply this paint command.
The mesh submesh that will be painted.
The LocalMask that will be used when painting.
The channel of the LocalMaskTexture that will be used.
This class manages the decal painting command.
This method allows you to set the shape and rotation of the decal.
This component shows you how to listen for and store paint commands added to any CwPaintableTexture component in the scene.
This component can then reset each paintable texture, and randomly apply one of the recorded paint commands.
Should this component listen for added commands?
This method will pool and clear all commands.
This method will clear all paintable textures, and apply one random paint command that was recorded.
This class contains some useful methods used by this asset.
This method allows you to save a byte array to PlayerPrefs, and is used by the texture saving system.
If you want to save to files instead then just modify this.
This method allows you to load a byte array from PlayerPrefs, and is used by the texture loading system.
If you want to save to files instead then just modify this.
This method tells if you if there exists save data at the specified save name.
This method allows you to clear save data at the specified save name.
This tool allows you to copy UV1 data into UV0. This is useful if you let Unity automatically generate lightmap UV data for you and you want to use them to paint normally.
The original mesh whose UV seams you want to fix.
The coord that will be copied into the first UV channel of the output mesh.
The coord that will be copied into the second UV channel of the output mesh.
The coord that will be copied into the third UV channel of the output mesh.
The coord that will be copied into the fourth UV channel of the output mesh.
This component automatically destroys this GameObject after some time.
If this component has been active for this many seconds, the current GameObject will be destroyed.
-1 = DestroyNow must be manually called.
This component automatically destroys the specified GameObject when sent a hit point. Hit points will automatically be sent by any CwHit___ component on this GameObject, or its ancestors.
This GameObject will be destroyed.
This component adds basic Pitch/Yaw controls to the current GameObject (e.g. camera) using mouse or touch controls.
Rotation will be active if all of these tools are deactivated.
The key that must be held for this component to activate on desktop platforms.
None = Any mouse button.
Fingers that began touching the screen on top of these UI layers will be ignored.
The target pitch angle in degrees.
The speed the pitch changed relative to the mouse/finger drag distance.
The minimum value of the pitch value.
The maximum value of the pitch value.
The target yaw angle in degrees.
The speed the yaw changed relative to the mouse/finger drag distance.
How quickly the rotation transitions from the current to the target value (-1 = instant).
This component allows you to fade the pixels of the specified CwPaintableTexture.
This allows you to choose which paintable texture will be modified by this component.
Once this component has accumulated this amount of fade, it will be applied to the PaintableTexture. The lower this value, the smoother the fading will appear, but also the higher the performance cost.
The speed of the fading.
1 = 1 Second.
2 = 0.5 Seconds.
This component will paint using this blending mode.
The texture that will be faded toward.
The paintable texture that will be faded toward.
The color that will be faded toward.
If you want the gradually fade effect to be masked by a texture, then specify it here.
If you want the gradually fade effect to be masked by a paintable texture, then specify it here.
This allows you to specify the channel of the mask.
This object allows you to define information about a paint group like its name, which can then be selected using the CwGroup setting on components like CwPaintableTexture and CwPaintDecal.
This allows you to set the ID of this group (e.g. 100).
This static property returns a list of all cached CwGroupData instances.
This method allows you to get the name of the current group, with an optional prefix of the Index (e.g. "100: Albedo").
This static method calls GetAlias on the CwGroupData with the specified Index setting, or null.
This static method returns the CwGroupData with the specified Index setting, or null.
This static method forces the cached instance list to update.
This struct can be used to reference a Material by instance or hash for de/serialization.
This struct can be used to reference a Material by instance or hash for de/serialization.
This struct can be used to reference a Texture by instance or hash for de/serialization.
This stores information about a scene point on a mesh. This is usually generated from a RaycastHit, but it can also be filled manually.
The world position that was hit.
The world normal that was hit.
The Transform that was hit.
The triangle index that was hit.
The world distance that was hit.
The Collider that was hit.
This component raycasts between two points, and fires hit events when the ray hits something.
Where in the game loop should this component hit?
The time in seconds between each raycast.
0 = Every frame.
-1 = Manual only.
The start point of the raycast.
The end point of the raycast.
The end point of the raycast.
The layers you want the raycast to hit.
How should the hit point be oriented?
WorldUp = It will be rotated to the normal, where the up vector is world up.
CameraUp = It will be rotated to the normal, where the up vector is world up.
ThisRotation = The current Transform.rotation will be used.
ThisLocalRotation = The current Transform.localRotation will be used.
CustomRotation = The specified CustomTransform.rotation will be used.
CustomLocalRotation = The specified CustomTransform.localRotation will be used.
Orient to a specific camera?
None = MainCamera.
If you use Orientation = CustomRotation/CustomLocalRotation, this allows you to set the transform.
Which normal should the hit point rotation be based on?
If you want the raycast hit point to be offset from the surface a bit, this allows you to set by how much in world space.
Should the applied paint be applied as a preview?
This allows you to override the order this paint gets applied to the object during the current frame.
This allows you to control the pressure of the painting. This could be controlled by a VR trigger or similar for more advanced effects.
This allows you to control the hit data this component sends out.
PointsIn3D = Point drawing in 3D.
PointsOnUV = Point drawing on UV (requires non-convex MeshCollider).
TrianglesIn3D = Triangle drawing in 3D.
If you want to display something at the hit point (e.g. particles), you can specify the Transform here.
If you want to draw a line between the start point and the his point then you can set the line here.
This allows you to connect the hit points together to form lines.
This method will immediately submit a non-preview hit. This can be used to apply real paint to your objects.
This component sends hit events to a cached list of components that can receive them. If this list changes then you must manually call this method.
If this GameObject has teleported and you have ConnectHits or HitSpacing enabled, then you can call this to prevent a line being drawn between the previous and current points.
This class stores lists of IHit__ instances, allowing components like CwHit__ to easily invoke hit events.
This component can be added to any Rigidbody, and it will fire hit events when it hits something.
This allows you to control the hit data this component sends out.
PointsIn3D = Point drawing in 3D.
PointsOnUV = Point drawing on UV (requires non-convex MeshCollider).
TrianglesIn3D = Triangle drawing in 3D.
When emitting PointsOnUV or TrianglesIn3D, this setting allows you to specify the world space distance from the hit point a raycast will be fired. This is necessary because collisions by themselves don't provide the necessary information.
This allows you to filter collisions to specific layers.
If there are multiple contact points, skip them?
If this component is generating too many hits, then you can use this setting to ignore hits for the specified amount of seconds.
0 = Unlimited.
How should the hit point be oriented?
WorldUp = It will be rotated to the normal, where the up vector is world up.
CameraUp = It will be rotated to the normal, where the up vector is world up.
Orient to a specific camera?
None = MainCamera.
Should the applied paint be applied as a preview?
If the collision impact speed is below this value, then the collision will be ignored.
This allows you to set how the pressure value will be calculated.
Constant = The PressureConstant value will be directly used.
ImpactSpeed = The pressure will be 0 when the collision impact speed is PressureMin, and 1 when the impact speed is or exceeds PressureMax.
The impact strength required for a hit to occur with a pressure of 0.
The impact strength required for a hit to occur with a pressure of 1.
The pressure value used when PressureMode is set to Constant.
The calculated pressure value will be multiplied by this.
If you want the raycast hit point to be offset from the surface a bit, this allows you to set by how much in world space.
This allows you to override the order this paint gets applied to the object during the current frame.
Hit events are normally sent to all components attached to the current GameObject, but this setting allows you to override that. This is useful if you want to use multiple CwHitCollisions components with different settings and results.
This component sends hit events to a cached list of components that can receive them. If this list changes then you must manually call this method.
This component continuously fires hit events using the current Transform position.
Where in the game loop should this component hit?
The time in seconds between each hit.
0 = Every frame.
Should the applied paint be applied as a preview?
This allows you to override the order this paint gets applied to the object during the current frame.
This allows you to control the pressure of the painting. This could be controlled by a VR trigger or similar for more advanced effects.
This allows you to connect the hit points together to form lines.
This method will immediately submit a non-preview hit. This can be used to apply real paint to your objects.
This component sends hit events to a cached list of components that can receive them. If this list changes then you must manually call this method.
If this GameObject has teleported and you have ConnectHits or HitSpacing enabled, then you can call this to prevent a line being drawn between the previous and current points.
This component can be added to any ParticleSystem with collisions enabled, and it will fire hits when the particles collide with something.
This allows you to control the hit data this component sends out.
PointsIn3D = Point drawing in 3D.
PointsOnUV = Point drawing on UV (requires non-convex MeshCollider).
TrianglesIn3D = Triangle drawing in 3D.
When emitting PointsOnUV or TrianglesIn3D, this setting allows you to specify the world space distance from the hit point a raycast will be fired. This is necessary because particles by themselves don't provide the necessary information.
This allows you to filter collisions to specific layers.
How should the hit point be oriented?
WorldUp = It will be rotated to the normal, where the up vector is world up.
CameraUp = It will be rotated to the normal, where the up vector is world up.
Orient to a specific camera?
None = MainCamera.
Which normal should the hit point rotation be based on?
If you want the raycast hit point to be offset from the surface a bit, this allows you to set by how much in world space.
If you have too many particles, then painting can slow down. This setting allows you to reduce the amount of particles that actually cause hits.
0 = Every particle will hit.
5 = Skip 5 particles, then hit using the 6th.
Should the particles paint preview paint?
This allows you to override the order this paint gets applied to the object during the current frame.
This allows you to set how the pressure value will be calculated.
Constant = The PressureConstant value will be directly used.
Distance = A value will be calculated based on the distance between this emitter and the particle hit point.
Speed = A value will be calculated based on the hit speed of the particle.
This allows you to specify the distance/speed that gives 0.0 pressure.
This allows you to specify the distance/speed that gives 1.0 pressure.
The pressure value used when PressureMode is set to Constant.
The calculated pressure value will be multiplied by this.
Hit events are normally sent to all components attached to the current GameObject, but this setting allows you to override that. This is useful if you want to use multiple CwHitParticles components with different settings and results.
This component sends hit events to a cached list of components that can receive them. If this list changes then you must manually call this method.
This this is the base class for hit screen components that receive data from CwPointer___ components.
Fingers that began touching the screen on top of these UI layers will be ignored.
This component will perform a raycast under the mouse or finger as it moves across the screen. It will then send hit events to components like CwPaintDecal, allowing you to paint the scene.
This allows you to control how often the screen is painted.
PixelInterval = Once every Interval pixels.
ScaledPixelInterval = Like PixelInterval, but scaled to the screen DPI.
TimeInterval = Once every Interval seconds.
OnceOnRelease = When the finger/mouse goes down a preview will be shown, and when it goes up the paint will apply.
OnceOnPress = When the finger/mouse goes down the paint will apply.
OnceEveryFrame = Every frame the paint will apply.
This allows you to set the pixels/seconds between each hit point based on the current Frequency setting.
This allows you to connect the hit points together to form lines.
This component sends hit events to a cached list of components that can receive them. If this list changes then you must manually call this method.
If this GameObject has teleported and you have ConnectHits or HitSpacing enabled, then you can call this to prevent a line being drawn between the previous and current points.
This class contains common code for screen based mouse/finger hit components.
Orient to a specific camera?
None = MainCamera.
The layers you want the raycast to hit.
This allows you to control the hit data this component sends out.
PointsIn3D = Point drawing in 3D.
PointsOnUV = Point drawing on UV (requires non-convex MeshCollider).
TrianglesIn3D = Triangle drawing in 3D (requires non-convex MeshCollider).
This allows you to control how the paint is rotated.
Normal = The rotation will be based on a normal direction, and rolled relative to an up axis.
World = The rotation will be aligned to the world, or given no rotation.
ThisRotation = The current Transform.rotation will be used.
ThisLocalRotation = The current Transform.localRotation will be used.
CustomRotation = The specified CustomTransform.rotation will be used.
CustomLocalRotation = The specified CustomTransform.localRotation will be used.
Which direction should the hit point rotation be based on?
Based on the normal direction, what should the rotation be rolled relative to?
WorldUp = It will be rolled so the up vector is world up.
CameraUp = It will be rolled so the up vector is camera up.
DrawAngle = It will be rolled according to the mouse/finger movement on screen.
This allows you to specify the Transform when using RotateTo = CustomRotation/CustomLocalRotation.
Should painting triggered from this component be eligible for being undone?
This allows you to override the order this paint gets applied to the object during the current frame.
If you want the raycast hit point to be offset from the surface a bit, this allows you to set by how much in world space.
This component works like CwHitScreen, but it will fill in the shape you draw.
This allows you to set the pixel distance between each grid point.
This component will perform a raycast under the mouse or finger as it moves across the screen. It will then send hit events to components like CwPaintDecal, allowing you to paint the scene.
This allows you to control how many hit points will be generated along the drawn line.
StartAndEnd = Once at the start, and once at the end.
PixelInterval = Once at the start, and then every Interval pixels.
ScaledPixelInterval = Once at the start, and then every Interval scaled pixels.
StretchedPixelInterval = Like ScaledPixelInterval, but the hits are stretched to reach the end.
StretchedScaledPixelInterval = Like ScaledPixelInterval, but the hits are stretched to reach the end.
Once = Once at the specified Position and PixelOffset along the line.
This allows you to set the pixels between each hit point based on the current Frequency setting.
When using Frequency = Once, this allows you to set the 0..1 position along the line.
When using Frequency = Once, this allows you to set the pixel offset along the line.
This allows you to connect the hit points together to form lines.
This component sends hit events to a cached list of components that can receive them. If this list changes then you must manually call this method.
If this GameObject has teleported and you have ConnectHits or HitSpacing enabled, then you can call this to prevent a line being drawn between the previous and current points.
This component constantly draws lines between the two specified points.
Where in the game loop should this component hit?
The time in seconds between each hit.
0 = Every frame.
-1 = Manual only.
The start point of the raycast.
The end point of the raycast.
How should the hit point be oriented?
WorldUp = It will be rotated to the normal, where the up vector is world up.
CameraUp = It will be rotated to the normal, where the up vector is world up.
Orient to a specific camera?
None = MainCamera.
This allows you to control the pressure of the painting. This could be controlled by a VR trigger or similar for more advanced effects.
Should the applied paint be applied as a preview?
This allows you to override the order this paint gets applied to the object during the current frame.
If you want to draw a line between the start point and the his point then you can set the line here.
This allows you to connect the hit points together to form lines.
This method will immediately submit a non-preview hit. This can be used to apply real paint to your objects.
This component sends hit events to a cached list of components that can receive them. If this list changes then you must manually call this method.
If this GameObject has teleported and you have ConnectHits or HitSpacing enabled, then you can call this to prevent a line being drawn between the previous and current points.
This component allows you to convert input axis values to a boolean event. This can be used to map VR buttons to other components.
The name of the input axis in the Project Settings.
The index of the input axis in the Project Settings.
This class allows you to easily create components that can have their paint lines connected together to form quads.
The world space distance between each paint point.
0 = No spacing.
When using HitSpacing, this prevents scenarios where something goes wrong and you attempt to paint too many times per frame.
If you enable this then the hit lines generated by this component will be connected into quads, allowing you to paint continuously.
If you enable ConnectHits, then each connected quad will overlap with the next. When using semi-transparent painting, this causes the overlap to become double opacity and look obvious. If you enable this setting, then this overlapping area will be removed.
This component sends hit events to a cached list of components that can receive them. If this list changes then you must manually call this method.
If this GameObject has teleported and you have ConnectHits or HitSpacing enabled, then you can call this to prevent a quad being drawn between the previous and current lines.
This component allows you to block paint from being applied at the current position using the specified shape.
The mask will use this texture shape.
The mask will use pixels from this texture channel.
By default, opaque/white parts of the mask are areas you can paint, and transparent/black parts are parts that are masked. Invert this?
If you want the sides of the mask to extend farther out, then this allows you to set the scale of the boundary.
1 = Default.
2 = Double size.
This stores all active and enabled instances in the open scenes.
This component allows you to duplicate a material before you paint on it. This is useful if the material is shared between multiple GameObjects (e.g. prefabs).
The material index that will be cloned. This matches the Materials list in your MeshRenderer/SkinnedMeshRenderer, where 0 is the first material.
If this shader needs specific keywords enabled, you can add them here.
The cloned material also belongs to these external GameObjects. This is used with texture atlasing.
This lets you know if this component has already been activated and has executed.
This allows you to manually activate this component, cloning the specified material.
This reverses the material cloning.
This window allows you to examine the UV data of a mesh. This can be accessed from the context menu (⋮ button at top right) of any mesh in the inspector.
This tool allows you to process any mesh so that it can be painted.
The fixed meshes will be placed as a child of this tool in your Project window.
To use the fixed mesh, drag and drop it into your MeshFilter or SkinnedMeshRenderer.
This tool can be accessed from the context menu (⋮ button at top right) of any mesh/model inspector.
The original mesh.
The fixed mesh.
The meshes we will fix.
The UV channel whose seams will be fixed.
Generate UV data for the meshes?
Maximum allowed angle distortion (0..1).
Maximum allowed area distortion (0..1).
This angle (in degrees) or greater between triangles will cause seam to be created.
How much uv-islands will be padded.
If UV data is shifted out of the 0..1 range (e.g. 3..4), it will be wrapped back to 0..1.
However, if these wrapped triangles still go outside the 0..1 range, should they be wrapped to the other side so it can still be fully painted?
Fix the seams of the meshes?
The thickness of the UV borders in the fixed mesh.
This allows you to add a mesh to the seam fixer.
This static method allows you to fix any mesh at runtime.
This is the base code for the CwPaintableMesh and CwPaintableMeshAtlas components.
Transform the mesh with its position, rotation, and scale? Some skinned mesh setups require this to be disabled.
This allows you to choose how the Mesh attached to the current Renderer is used when painting.
AsIs = Use what is currently set in the renderer.
AutoSeamFix = Use (or automatically generate) a seam-fixed version of the mesh currently set in the renderer.
Materials will give you a cached CachedRenderer.sharedMaterials array. If you have updated this array externally then call this to force the cache to update next them it's accessed.
This component marks the current GameObject as being paintable, as long as this GameObject has a MeshFilter + MeshRenderer, or a SkinnedMeshRenderer.
The hash code for this model used for de/serialization of this instance.
If you want the paintable texture width/height to be multiplied by the scale of this GameObject, this allows you to set the scale where you want the multiplier to be 1.
This stores all active and enabled instances in the open scenes.
This will return a list of all paintables that overlap the specified bounds
This will scale the specified width and height values based on the current BaseScale setting.
This is the base class for all paint modifiers. To make a paint modifier, simply inherit this class, and implement one of the virtual methods to modify its data.
Should this modifier apply to preview paint as well?
Should this modifier use a unique seed?
This class maintains a list of CwModifier instances, and contains helper methods to apply them.
This is used instead of a normal list so the modifiers can be de/serialized with polymorphism.
The amount of modifiers in the list.
This stores all modifiers in this list.
This class allows you to randomize the painting angle of the attached component (e.g. CwPaintDecal).
This is the minimum random angle that will be picked.
This is the maximum random angle that will be picked.
The way the picked angle value will be blended with the current one.
This class allows you to randomize the painting color of the attached component (e.g. CwPaintDecal).
This is the gradient containing all the possible colors. A color will be randomly picked from this.
The way the picked color value will be blended with the current one.
This class allows you to change the painting hardness based on the paint pressure.
The paint component's Hardness value will be modified using this value based on the current Blend setting.
This allows you to control how this new Hardness value will modify the old value in the paint component.
Replace = Transition between [old, new] based on pressure.
Multiply = Transition between [old, old*new] based on pressure.
Increment = Transition between [old, old+new] based on pressure.
This class allows you to randomize the painting hardness of the attached component (e.g. CwPaintDecal).
This is the minimum random hardness that will be picked.
This is the maximum random hardness that will be picked.
The way the picked hardness value will be blended with the current one.
This class allows you to change the painting opacity based on the paint pressure.
The paint component's Opacity value will be modified using this value based on the current Blend setting.
This allows you to control how this new Opacity value will modify the old value in the paint component.
Replace = Transition between [old, new] based on pressure.
Multiply = Transition between [old, old*new] based on pressure.
Increment = Transition between [old, old+new] based on pressure.
This class allows you to randomize the painting opacity of the attached component (e.g. CwPaintDecal).
This is the minimum random opacity that will be picked.
This is the maximum random opacity that will be picked.
The way the picked opacity value will be blended with the current one.
This class allows you to randomize the painting position of the attached component (e.g. CwPaintDecal).
The position will be offset up to this radius away in world space.
This class allows you to change the painting radius based on the paint pressure.
The paint component's Radius value will be modified using this value based on the current Blend setting.
This allows you to control how this new Radius value will modify the old value in the paint component.
Replace = Transition between [old, new] based on pressure.
Multiply = Transition between [old, old*new] based on pressure.
Increment = Transition between [old, old+new] based on pressure.
This class allows you to randomize the painting radius of the attached component (e.g. CwPaintDecal).
This is the minimum random radius that will be picked.
This is the maximum random radius that will be picked.
The way the picked radius value will be blended with the current one.
This class allows you to randomize the painting scale of the attached component (e.g. CwPaintDecal).
This is the minimum random scale that will be picked.
This is the maximum random scale that will be picked.
The way the picked scale value will be blended with the current one.
If you disable this then each x, y, and z value will be scaled separately.
This class allows you to change the painting texture of the attached component (e.g. CwPaintDecal) based on the paint pressure.
The painting texture will be changed to this.
The paint pressure must be at least this value.
The paint pressure must be at most this value.
This class allows you to randomize the painting texture of the attached component (e.g. CwPaintDecal).
A random texture will be picked from this list.
This component automatically updates all CwModel and CwPaintableTexture instances at the end of the frame, batching all paint operations together.
This stores all active and enabled instances in the open scenes.
If the current GPU doesn't support async texture reading, this setting allows you to limit how many pixels are read per frame to reduce lag.
This event is called before a component paints something, where 'object' is a reference to the component or link that will do the painting.
Before a component submits paint hits/commands, it will register the 'object' reference to track the painting.
If a component is currently painting, it can call this method.
This component marks the current GameObject as being paintable.
This allows you to control when this component actually activates and becomes ready for painting. You probably don't need to change this.
This allows you to specify how the paintable textures will be applied to this paintable object.
PropertyBlock = Using MaterialSetPropertyBlock feature.
ClonerAndTextures = Using (Optional) CwMaterialCloner and Material.SetTexture calls.
If this material is used in multiple renderers, you can specify them here. This usually happens with different LOD levels.
This event will be invoked before this component is activated.
This event will be invoked after this component is activated.
This event will be invoked before this component is deactivated.
This event will be invoked after this component is deactivated.
This lets you know if this paintable has been activated.
Being activated means each associated CwMaterialCloner and CwPaintableTexture has been Activated.
This gives you all CwPaintableTexture components that have been activated with this paintable mesh.
This method will remove all CwPaintableMesh and CwPaintableTexture and CwMaterialCloner components from this GameObject.
This allows you to manually activate all attached CwMaterialCloner and CwPaintableTexture components.
This reverses the material cloning.
This allows you to clear the pixels of all activated CwPaintableTexture components associated with this CwPaintable with the specified color.
This allows you to clear the pixels of all activated CwPaintableTexture components associated with this CwPaintable with the specified color and texture.
This allows you to manually register a CwPaintableTexture.
This allows you to manually unregister a CwPaintableTexture.
If you want to paint a mesh that is part of a texture atlas, except for the main mesh, you can add this component to all other GameObjects that are part of the texture atlas. You can then set the Parent setting to the main mesh.
The paintable mesh this atlas mesh is associated with.
This component allows you to make one texture on the attached Renderer paintable.
This window shows you all paintable objects in the scene, and it also allows you to make objects paintable from all paintable presets in your project.
You can open this window from the Window/CW/Paintable Objects menu.
This class stores information about a particular paintable texture state. Either a full texture copy, or a list of commands used to draw it.
This base class allows you to quickly create components that listen for changes to the specified CwPaintableTexture.
This is the paintable texture whose pixels we will count.
Should this counter only read when you're not currently painting?
This allows you to specify the minimum delay between when your texture is painted, and when the data is read.
0 = As fast as possible.
1 = Once a second.
If you disable this, then the texture will be updated immediately, which may cause slowdown.
If you enable this, then the reader will update as soon as it starts. If not, you must manually populate it with default data.
Testing all the pixels of a texture can be slow, so you can pick how many times the texture is downsampled. One downsample = half width & height or 1/4 of the pixels.
This event is invoked each time this texture monitor updates its pixel counts.
This will be true after Register is successfully called.
This forces the specified CwPaintableTexture to be registered.
This forces the specified CwPaintableTexture to be unregistered.
This base class allows you to quickly create components that listen for changes to the specified CwPaintableTexture.
If you want this component to accurately count pixels relative to a mask mesh, then specify it here.
If you have a MaskMesh set, then this allows you to choose which submesh of it will be used for the mask.
If you want this component to accurately count pixels relative to a mask texture, then specify it here.
This allows you to specify which channel of the MaskTexture will be used to define the mask.
The previously counted total amount of pixels.
This component performs an action every time a paint hit is received. Hit points will automatically be sent by any CwHit___ component on this GameObject, or its ancestors.
The event that will be invoked.
This component allows you to debug hit points into the Scene tab. Hit points will automatically be sent by any CwHit___ component on this GameObject, or its ancestors.
The color of the debug.
The duration of the debug.
The size of the debug.
This allows you to paint a decal at a hit point. Hit points will automatically be sent by any CwHit___ component on this GameObject, or its ancestors.
Only the CwPaintable___ GameObjects whose layers are within this mask will be eligible for painting.
If this is set, then only the specified CwPaintable___ will be painted, regardless of the layer setting.
Only the CwPaintableTexture components with a matching group will be painted by this component.
If this is set, then only the specified CwPaintableTexture will be painted, regardless of the layer or group setting.
This allows you to choose how the paint from this component will combine with the existing pixels of the textures you paint.
The decal that will be painted.
This allows you to specify the shape of the decal. This is optional for most blending modes, because they usually derive their shape from the RGB or A values. However, if you're using the Replace blending mode, then you must manually specify the shape.
This allows you specify the texture channel used when sampling Shape.
The color of the paint.
The opacity of the brush.
The angle of the decal in degrees.
This allows you to control the mirroring and aspect ratio of the decal.
1, 1 = No scaling.
-1, 1 = Horizontal Flip.
The radius of the paint brush.
This allows you to control the sharpness of the near+far depth cut-off point.
This allows you to control how much the decal can wrap around uneven paint surfaces.
This allows you to control how much the paint can wrap around the front of surfaces.
For example, if you want paint to wrap around curved surfaces then set this to a higher value.
This works just like Normal Front, except for back facing surfaces.
This allows you to control the smoothness of the normal cut-off point.
This allows you to apply a tiled detail texture to your decals. This tiling will be applied in world space using triplanar mapping.
This allows you to adjust the tiling position + rotation + scale using a Transform.
This allows you to control the triplanar influence.
0 = No influence.
1 = Full influence.
This allows you to control how quickly the triplanar mapping transitions between the X/Y/Z planes.
If your scene contains a CwMask, should this paint component use it?
If your scene contains a CwRenderDepth, should this paint component use it?
This stores a list of all modifiers used to change the way this component applies paint (e.g. CwModifyColorRandom).
This method will invert the scale.x value.
This method will invert the scale.y value.
This method increments the angle by the specified amount of degrees, and wraps it to the -180..180 range.
This method multiplies the Opacity by the specified value.
This method increments the Opacity by the specified value.
This method multiplies the Radius by the specified value.
This method increases the Radius by the specified value.
This method multiplies the Scale by the specified value.
This method increases the Scale by the specified value.
This method paints all pixels at the specified point using the shape of a decal.
This method paints all pixels between the two specified points using the shape of a decal.
This method paints all pixels between three points using the shape of a decal.
This method paints all pixels between two pairs of points using the shape of a decal.
This method paints the scene using the current component settings at the specified CwHit.
This component implements the fill paint mode, which will modify all pixels in the specified texture in the same way.
This is useful if you want to gradually fade a texture to a specific color.
Only the CwPaintableTexture components with a matching group will be painted by this component.
This allows you to choose how the paint from this component will combine with the existing pixels of the textures you paint.
The color of the paint.
The color of the paint.
The opacity of the brush.
The minimum RGBA value change. This is useful if you're doing very subtle color changes over time.
This stores a list of all modifiers used to change the way this component applies paint (e.g. CwModifyColorRandom).
This method increments Opacity by the specified value.
This component listens for point and line painting events. It then simulates transmitting them over a network with a delay, and then painting the received data.
This allows you to specify the simulated delay between painting across the network in seconds.
This component implements the replace paint mode, which will replace all pixels in the specified texture.
Only the CwPaintableTexture components with a matching group will be painted by this component.
The texture that will be painted.
The color of the paint.
This stores a list of all modifiers used to change the way this component applies paint (e.g. CwModifyColorRandom).
This component implements the replace channels paint mode, which will replace all pixels in the specified textures and channel weights.
Only the CwPaintableTexture components with a matching group will be painted by this component.
This allows you to paint a sphere at a hit point. Hit points will automatically be sent by any CwHit___ component on this GameObject, or its ancestors.
Only the CwPaintable___ GameObjects whose layers are within this mask will be eligible for painting.
Only the CwPaintableTexture components with a matching group will be painted by this component.
If this is set, then only the specified model will be painted, regardless of the layer setting.
If this is set, then only the specified CwPaintableTexture will be painted, regardless of the layer or group setting.
This allows you to choose how the paint from this component will combine with the existing pixels of the textures you paint.
The color of the paint.
The opacity of the brush.
The angle of the paint in degrees.
By default this component paints using a sphere shape, but you can override this here to paint an ellipsoid.
The radius of the paint brush.
The hardness of the paint brush.
This allows you to apply a tiled detail texture to your decals. This tiling will be applied in world space using triplanar mapping.
This allows you to adjust the tiling position + rotation + scale using a Transform.
This allows you to control the triplanar influence.
0 = No influence.
1 = Full influence.
This allows you to control how quickly the triplanar mapping transitions between the X/Y/Z planes.
If your scene contains a CwMask, should this paint component use it?
If your scene contains a CwRenderDepth, should this paint component use it?
This stores a list of all modifiers used to change the way this component applies paint (e.g. CwModifyColorRandom).
This method increments the angle by the specified amount of degrees, and wraps it to the -180..180 range.
This method multiplies the Opacity by the specified value.
This method increments the Opacity by the specified value.
This method multiplies the Radius by the specified value.
This method increases the Radius by the specified value.
This method multiplies the Scale by the specified value.
This method increases the Scale by the specified value.
This method paints all pixels at the specified point using the shape of a sphere.
This method paints all pixels between the two specified points using the shape of a sphere.
This method paints all pixels between three points using the shape of a sphere.
This method paints all pixels between two pairs of points using the shape of a sphere.
This method paints the scene using the current component settings at the specified CwHit.
This class allows you to easily create components that can have their paint points connected together to form lines.
The world space distance between each paint point.
0 = No spacing.
When using HitSpacing, this prevents scenarios where something goes wrong and you attempt to paint too many times per frame.
If you enable this then the hit points generated by this component will be connected into lines, allowing you to paint continuously.
If you enable ConnectHits, then each connected line will overlap with the next. When using semi-transparent painting, this causes the overlap to become double opacity and look obvious. If you enable this setting, then this overlapping area will be removed.
This component sends hit events to a cached list of components that can receive them. If this list changes then you must manually call this method.
If this GameObject has teleported and you have ConnectHits or HitSpacing enabled, then you can call this to prevent a line being drawn between the previous and current points.
This this is the base class for any component that sends pointer information to any CwHitScreen component.
This component sends pointer information to any CwHitScreen component, allowing you to paint with the mouse.
If you enable this, then a paint preview will be shown under the mouse as long as the RequiredKey is not pressed.
This component will paint while any of the specified mouse buttons or keyboard keys are held.
This component sends pointer information to any CwHitScreen component, allowing you to paint with a pen.
If you enable this, then a paint preview will be shown under the pen as long as the tip is not pressed.
If you want the paint to appear above the pen, then you can set this number to something positive.
This component sends pointer information to any CwHitScreen component, allowing you to paint with a touchscreen.
If you want the paint to appear above the finger, then you can set this number to something positive.
This component allows you to define a set of CwPaintableTexture and CwMaterial components that are configured for a specific set of Materials.
This allows you to name this preset.
None/null = The GameObject name will be used.
This preset is designed to work with the specified shaders.
This gives you a list of all presets in the project.
This method applies the preset components to the specified paintable.
This component can be added to an empty GameObject, and it will set it up with a procedurally generated quad that is ready for painting.
The Material applied to the renderer.
The size of the generated quad in local space.
This component allows you to read the paint color at a hit point. A hit point can be found using a companion component like: CwHitScreen, CwHitBetween.
Only the CwPaintableTexture components with a matching group will be painted by this component.
Should the color be read during preview painting too?
How should the texture be read?
Immediate = The reading method will block until the pixel is fetched from the GPU.
Async = The pixel value will be read after some time, giving you better performance.
The last read color value.
When a color is read, this event will be invoked.
Color = The color that was read.
This component allows you to perform an event when the attached CwReadColor component reads a specific color.
This color we want to detect.
The RGBA values must be within this range of a color for it to be counted.
When the expected color is read, this event will be invoked.
Color = The expected color.
This component renders scene depth to a RenderTexture. This scene depth can be set in a CwPaint___ component's Advanced/DepthMask setting, which allows you to paint on the first surface in the view of the specified camera.
The camera whose depth information will be read.
The transformation matrix of the camera when the depth texture was generated.
If this is 0, the RenderTexture size will match the viewport. If it's above 0, then the RenderTexture size will be set to the viewport size divided by this value.
The rendered depth must be at least this mant units different from the painted surface for the paint to be masked out.
If you enable this, then the depth mask will be sampled multiple times per pixel, allowing you to paint both foreground and background objects with little to no edge seams.
Should the scene depth be rendered in Start?
Should the scene depth be rendered every frame in Update?
This stores all active and enabled instances in the open scenes.
This method will update the TargetTexture with what the SourceCamera currently sees.
This component allows you to rotate the current Transform.
This allows you to set the coordinate space the movement will use.
The position will be incremented by this each second.
This class handles the low level de/serialization of different paint objects to allow for things like networking.
This stores an association between a Material hash code and the Material instance, so it can be de/serialized.
This stores an association between a Material instance and the Material hash code, so it can be de/serialized.
This stores an association between a CwModel hash code and the CwModel instance, so it can be de/serialized.
This stores an association between a CwModel instance and the CwModel hash code, so it can be de/serialized.
This stores an association between a Texture hash code and the Texture instance, so it can be de/serialized.
This stores an association between a Texture instance and the Texture hash code, so it can be de/serialized.
This stores an association between a CwModel hash code and the CwModel instance, so it can be de/serialized.
This stores an association between a CwModel instance and the CwModel hash code, so it can be de/serialized.
This struct stores a reference to a texture on a GameObject.
The material index in the attached renderer.
The name of the texture in the specified material.
This allows you to spawn a prefab at a hit point. Hit points will automatically be sent by any CwHit___ component on this GameObject, or its ancestors.
A random prefab from this list will be spawned.
The spawned prefab will be randomly offset by a random point within this radius in world space.
If the prefab contains a Rigidbody, it will be given this velocity in local space.
The spawned prefab will be offset from the hit point based on the hit normal by this value in world space.
The spawned prefab will be offset from the hit point based on this value in world space.
Call this if you want to manually spawn the specified prefab.
This component allows you to manage undo/redo states on all CwPaintableTextures in your scene.
This method will call StoreState on all active and enabled CwPaintableTextures.
This method should be called if you're about to send paint hits that might apply paint to objects. If so, StoreState will be called on all active and enabled CwPaintableTextures
This method will call ClearStates on all active and enabled CwPaintableTextures.
This method will call Undo on all active and enabled CwPaintableTextures.
This method will call Redo on all active and enabled CwPaintableTextures.
This component will spawn and throw Rigidbody prefabs from the camera when you tap the mouse or a finger.
The key that must be held for this component to activate on desktop platforms.
None = Any mouse button.
Fingers that began touching the screen on top of these UI layers will be ignored.
The prefab that will be thrown.
The speed that the object will be thrown at.
Should painting triggered from this component be eligible for being undone?
This component allows you to manually associate a Texture with a hash code so it can be de/serialized.
The texture that will be hashed.
The hash code for the texture.
This component enables or disables the specified ParticleSystem based on mouse or finger presses.
Fingers that began touching the screen on top of these UI layers will be ignored.
The key that must be held for this component to activate.
None = Any mouse button or finger.
The particle system that will be enabled/disabled based on mouse/touch.
Should painting triggered from this component be eligible for being undone?
This component allows you to enable/disable the target component while the specified key is held down.
The key that must be held for this component to activate.
None = Any mouse button or finger.
The component that will be enabled or disabled.
Should painting triggered from this component be eligible for being undone?
This component allows you to move the current Transform using editor events (e.g. UI buttons).
This allows you to set the coordinate space the movement will use.
The movement values will be multiplied by this before use.
If you want this component to change smoothly over time, then this allows you to control how quick the changes reach their target value.
-1 = Instantly change.
1 = Slowly change.
10 = Quickly change.
The position will be incremented by this each second.
This method allows you to translate along the X axis, with the specified value.
This method allows you to translate along the Y axis, with the specified value.
This method allows you to translate along the Z axis, with the specified value.
This method allows you to translate along the specified vector.
This method allows you to translate along the specified vector in world space.
This component performs an action every time you undo/redo/etc.
Listen for CwStateManager.UndoAll calls?
Listen for CwStateManager.RedoAll calls?
The event that will be invoked.
This component attached the current GameObject to a tracked hand.
This key allows you to reset the VR orientation.
The default distance in world space a hand must be to grab a tool.
This key allows you to simulate a left hand VR trigger.
This key allows you to simulate a left hand VR grip.
This key allows you to simulate a right hand VR trigger.
This key allows you to simulate a right hand VR grip.
When simulating a VR tool, it will be offset by this Euler rotation.
When simulating a VR tool, it will be offset by this local position.
When simulating a VR tool, it will be moved away from the hit surface by this.
The simulated left VR eye will be offset this much.
When simulating a VR tool, this will control how much the hit surface normal influences the tool rotation.
This stores all active and enabled instances in the open scenes.
This component attached the current GameObject to a tracked hand.
The XR node this GameObject will follow.
Should painting triggered from this component be eligible for being undone?
This tool will be offset by this vector in local space.
When simulating a VR tool, it will be offset by this local position.
The SimulatedOffset value will be offset by this when the simulated key is held.
This allows you to control the speed of the simulated transform changes.
This will drop the current tool.
This will drop the current tool and grab the next in the scene.
This method allows you to find the tool currently on the specified node.
This method allows you to drop all tools on the specified node.
All IHit___ interfaces implement this interface so they can all be easily found with GetComponent.
This interface allows you to make components that can paint points defined by UV coordinates.
This interface allows you to make components that can paint lines defined by two points.
This interface allows you to make components that can paint 3D points with a specified orientation.
This interface allows you to make components that can paint quads defined by a pair of two points.
This interface allows you to make components that can paint triangles defined by three points.
Thank you for using Paint in 3D ❤️
Are custom shaders/materials supported?
Can I save my in-game paint to my project?
Is the new InputSystem supported?
Can I paint in the editor's Scene window?
Can Each Individual Paint Be De/Serialized? (e.g. networking)