cowtrix / voxul

voxul is a voxel framework and voxel mesh editing tool for Unity.
Apache License 2.0
70 stars 7 forks source link

How to use textures? #9

Open R-N opened 11 months ago

R-N commented 11 months ago

I'd like to use texture with automatic UV mapping like in minecraft grass

cowtrix commented 11 months ago

Hi @R-N, thanks for your interest in voxul.

I've just pushed a commit which should hopefully re-enable texture painting in the editor. See below for a screenshot: just select your texture in the picker and it will get packed into a 3D texture. Note that 3D textures are not supported on all platforms (I think webGL doesn't support it from memory).

image

Make sure your voxel material is using the Voxul\DefaultVoxel shader and has the SPRITESHEET shader property enabled.

R-N commented 11 months ago

Thank you. Both the quick response and the framework itself.

I tried but it seems like it still doesn't use the texture. The color show just fine though. The blocks were made before setting texture and color, and then painted. That's why some are white. The rightmost block though, I added it after setting texture and color and I did not repaint it. It has the color out of the box. No errors are thrown.

image

I set them to various color because it did not seem to be doing anything when it was white, because the blocks are white by default and the texture doesn't apply, so it was painting white over white.

Here's the object properties ![image](https://github.com/cowtrix/voxul/assets/1442761/6d5f69eb-e75a-4473-99be-ae1e526cd21d) ![image](https://github.com/cowtrix/voxul/assets/1442761/17b08ab3-d00f-492f-88bf-9027591cc99c) ![image](https://github.com/cowtrix/voxul/assets/1442761/c4bf8d5c-9fef-4a4b-ba11-74c6c7ee5fe2)

By the way, although I don't know if it's related, clicking "Set voxels for selection (Shift + M)" throws error. If it's unrelated then it's fine, I don't use it for now. I don't even know what it does.

The error ``` InvalidOperationException: Collection was modified; enumeration operation may not execute. System.Collections.Generic.Dictionary`2+Enumerator[TKey,TValue].MoveNext () (at :0) System.Linq.Enumerable+WhereSelectEnumerableIterator`2[TSource,TResult].MoveNext () (at <59e7b6dabdf549b88aa5b4f75038790c>:0) Voxul.Edit.SelectTool.DrawInspectorGUI (Voxul.Edit.VoxelPainter voxelPainter) (at Assets/voxul/Scripts/Editor/Tools/SelectTool.cs:45) Voxul.Edit.VoxelPainter.DrawSpecificGUI () (at Assets/voxul/Scripts/Editor/VoxelPainter.cs:176) Voxul.Edit.VoxelObjectEditorBase`1[T].OnInspectorGUI () (at Assets/voxul/Scripts/Editor/VoxelObjectEditorBase.cs:62) UnityEditor.UIElements.InspectorElement+<>c__DisplayClass72_0.b__0 () (at <0be88e8ab6e346e9aff7a2ef25f50b89>:0) UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&) ```

Environment:

I took the textures from here.

I made the voxel by adding VoxelRenderer to a GameObject, then create scene mesh, save it, then add blocks using the editor.

R-N commented 11 months ago

Oh my bad. I didn't know I had to slide the "Texture Fade" to 1.

Okay so now it works, kinda. It's greyscale. Probably because the color is set to white. Can I have the original colors? Setting it to black or setting its alpha to 0 doesn't work.

image

R-N commented 11 months ago

I noticed another issue that the "Override" doesn't save. I saved the scene, closed Unity, then reopen it again, and now the "Override" section is empty.

image

Wait, the "Texture Fade" doesn't save either. Not sure if the color does since I left it to white.

The default texture did save though.

cowtrix commented 11 months ago

You can alter the ShaderGraph to change how the texture is blended with the input color, right now it's done with multiply. You'd change the following in voxul/Shaders/VoxelBase.asset: image (You probably also don't need that combine node after the two deleted nodes, just run the Lerp right into the Blend)

To save a set of voxel brush settings, create a new Voxel Brush (Create > voxul > Voxel Material Brush). It should then display in the "presets" list, if you refresh it.

By the way, although I don't know if it's related, clicking "Set voxels for selection (Shift + M)" throws error. If it's unrelated then it's fine, I don't use it for now. I don't even know what it does.

Set voxels for selection will apply the current Voxel Material you have configured to your selection. I'll look into that error, thanks for reporting it.

cowtrix commented 11 months ago

Hey @R-N, was this clear? Is your issue closed? If so, can we close this?

R-N commented 11 months ago

Sorry I had been too busy to try it. I'll try it now

R-N commented 11 months ago

Okay, it works, I can have the original colors now. I had to bypass the Combine node too. I also made it a boolean keyword to toggle between the behaviors.

image image

However, as you can see in the first picture, the UV mapping is weird. The way overriding menu is, I think it doesn't support minecraft-like texturing where the bottom right block should be full dirt, or does it? However the current behavior is inconsistent, how its tiled on one side but stretched on the other. It keeps changing as blocks are added. The stretch happens when the face is full square.

image image image

I try build it again and now the UV mapping is different. I did this one using a material brush.

image

Those were done with Local UV mapping. If I use Global, it's even weirder.

image

Local scaled.

image

image

Global scaled

image

Should I open a new issue for it? Since it's no longer about "How to use textures".

R-N commented 11 months ago

By the way, the material brush isn't loaded by default after I reopen the project, so I guess it's not tied to the GameObject. How do I add a block using a material brush, by code?

cowtrix commented 11 months ago

Ah yeah I understand what's going on here. Basically the uv mapping isn't being properly updated when we combine quads, that's why it works when there's only one voxel face but when they can be combined it looks stretched. I think it should be a relatively simple fix, let me have a look. The offending code is in FaceMerger.cs. You can actually disable the face merging optimization step if you want by selecting your Voxel Manager asset and removing it from the "default optimisers", until its fixed at least.

For your use case I would use Local Scaled, that means you have a 1:1 scaling to your voxel block which is what MineCraft does. I'll add looking at the other UV mapping modes.

cowtrix commented 11 months ago

By the way, the material brush isn't loaded by default after I reopen the project, so I guess it's not tied to the GameObject. How do I add a block using a material brush, by code?

You can add a reference to VoxelBrushAsset in your script, and then use it to generate a voxel object. A bit of the code that does this is the AddTool:

private IEnumerable<VoxelCoordinate> CreateVoxel(IEnumerable<VoxelCoordinate> coords, VoxelRenderer renderer)
{
    foreach (var brushCoord in coords)
    {
        UnityEngine.Random.InitState(brushCoord.GetHashCode());
        if (renderer.Mesh.Voxels.AddSafe(new Voxel(brushCoord, CurrentBrush.Generate(UnityEngine.Random.value))))
        {
            yield return brushCoord;
        }
    }
    renderer.Mesh.Invalidate();
    renderer.Invalidate(true, true);
}
cowtrix commented 11 months ago

I had a moment to fix UV mapping, hopefully. Grab latest and give it a go.

cowtrix commented 11 months ago

Pushed a breaking change - i.e. you'll lose the sprites you currently have and will have to re-add them - but a change which will hopefully greatly improve the experience of managing these textures. You now have the Spritesheet asset which contains the references to original textures as well as the packed texture that's given to the shader. One will be made by default within your VoxelManager, but you can also have per-renderer spritesheets. The picker in the painter now has a dropdown of all textures currently within the spritesheet, as well as an object field to add new ones.

R-N commented 11 months ago

Sorry I haven't tried the code yet.

The UV mapping is now consistent, thank you. The split faces are due to two separate voxel renderers, don't worry about them. image

However, this change seems to break the brush? I can't set the textures. Setting from the painter works fine. image

However the texture dropdown doesn't seem to work. I think it's populated by remembering textures I've set previously, but choosing from the dropdown doesn't change the texture. Not that I mind, I can just use the old picker.

The new Sprite asset confuse me. What's the difference between Albedo and Material texture? How do I use it? The spritesheet override? I set it and it broke the voxels, they're now all white. I tried rebuilding them but it's still white, despite the brush showing textures. Also, the brush doesn't respect the texture override I've set now. (The upward facing texture should be all grass)

image image image

I noticed that the dropdown is now populated by textures from the Spritesheet. However, selecting from the dropdown doesn't work so I selected from the old picker. Might this be the cause?

R-N commented 11 months ago

I tried the code. It works, but throws an error.

The error ``` Destroying assets is not permitted to avoid data loss. If you really want to remove an asset use DestroyImmediate (theObject, true); UnityEngine.Object:Destroy (UnityEngine.Object) Voxul.Utilities.Util:SafeDestroy (UnityEngine.Object) (at Assets/voxul/Scripts/Utilities/Util.cs:226) Voxul.Meshing.VoxelMeshWorker:Complete (System.Guid) (at Assets/voxul/Scripts/Meshing/VoxelMeshWorker.cs:262) Voxul.Meshing.VoxelMeshWorker/<>c__DisplayClass15_0:b__0 () (at Assets/voxul/Scripts/Meshing/VoxelMeshWorker.cs:201) Voxul.Utilities.UnityMainThreadDispatcher:Execute () (at Assets/voxul/Scripts/Utilities/UnityMainThreadDispatcher.cs:99) UnityEditor.EditorApplication:Internal_CallUpdateFunctions () ```
Code ``` using System.Collections; using System.Collections.Generic; using UnityEngine; using Voxul; public class Test : MonoBehaviour { // Start is called before the first frame update public VoxelRenderer voxelRenderer; public VoxelBrushAsset brush; void Start() { voxelRenderer = GetComponent(); voxelRenderer.Mesh.Voxels.AddSafe(new Voxel( new VoxelCoordinate(5, 5, 5, 0), brush.Material.Generate(0) )); voxelRenderer.Mesh.Invalidate(); voxelRenderer.Invalidate(true, true); } } ```

I think it's trying to destroy the old VoxelMesh, but it's an asset I created from the editor.

Also, I have some question.

R-N commented 11 months ago

Oh, right. I noticed that the sliders in the brush are range sliders. What's the range for? Random sample space?