Originally I wanted to make the very cool d20 with holofoil and sparkles I own...but then I got distracted by texture coords. Oops!
I semi-jest. Focusing on how I could manipulate those was an interesting challenge.
The idea was: Make a texture for dice sides- but just 0 to 9- no double digits, and indicators (the dot and underline) on separate spots so they could be swapped/disabled without channel packing.
The last line was intended for togglable icons for critical numbers, though I ran out of time to implement that.
RG for normal, mask in B
Red is often interchangeable for the x-axis, green for y-axis, and blue for the z-axis. Texture coordinates use UVs/XY. We can see in the image on the left that...from left to right, red increases, and top to bottom, green increases. That means 0,0 is at the top left, and 1,1 at the bottom right. (That's why a tiling texture increases size with the top left as the origin- you're multiplying by 0 there!)
So when a texture sampler is receiving texture coordinates, the texture coordinate node says "in this area, get the information from [x,y] on the texture. Multiplication, panners, and any other math you add further change that.
When I started making the d20 I immediately realized a problem: I wanted to keep each UV island as big as possible so more of the texture could be used for the actual numbers. The triangle shape meant either overlapping islands or having to shrink the numbers...but what if I could fix it in the shader instead?
My texture is divided into a 4x4 grid, so the origin for each square can be calculated. The entire square will need to be the same color/coordinate point. Ceil rounds to the next highest integer, which I need to get rid of the gradient. I multiply by 4 so ceil can do its thing, then divide by 4 to return to the 0-1 range.
Now the squares on the top row are (0.25,0.25) , (0.5,0.25) , (0.75,0.25) , (1,0.25)
Note: eyedropping this previewed value in Photoshop or wherever won't return the right numbers- srgb stuff I'm guessing- and I would use the nice DebugFloat nodes to check the numbers if I could, but since I can't sample a specific pixel of this... I just use the IF node instead.
Then I subtract both axis by 0.125 to get the origin.
The original texture gets moved back by the origin point of each square, scales, then gets moved back into place by the origin. After making a few other dice I realized a mistake- the d20's numbers were smaller by default because of their UV islands, and were the only ones requiring a scale adjustment. A whole material instance just to correct the d20 would be silly, so instead I made it so any dice with green vertex colors will get scaled.
This can cause multiple numbers to overlap on the same face when scaled small, but I mask this out later.
UV islands of course can go outside the 0-1 area, but TexCoord can also generate coordinates over 1 for them! So for numbers in the tens, I put the UV island 1 unit higher (lower according to TexCoord), 2 for twenties, etc. Hypothetically I can make a d100, though I didn't account for nineties or 100 here yet.
^ Zoomed out pic
d20 UVs
Test mesh with only 2nd digit applied. 0-1 has been replaced by 4, but that doesn't matter since it won't be sampled anyways.
The two subtract nodes force all squares on the grid to map to square 1. Then I offset it again to move it to the proper digit. Could've used a switch node here...
The second digit gets moved left, and the original first digit moves right. In order to combine the two, I used a texture mask.
Admittedly I was trying to avoid texture masking in this process, but this offered the most precise mask I could get, which I reckon is important for shapes that may have differing sizes and risk overlap.
The two options for indicators are a line and a dot, which sometimes get overlaid on 6 and 9 on dice to differentiate them. All that these nodes are doing is creating a mask at both squares, and offsetting the uvs to sample the indicator square instead.
"6 offset" and "9 offset" are the amounts needed to move the indicator to those squares. Adding another (0.25,0) if switch param is set to Line will sample the line square instead of dot.
The A input for BoxMask and Spheremask is the coordinates it's working in, and B input is the origin that region it's masking.
To get "." to "6," offset by (0.25,0.25)!
Given some scale adjustments, some numbers may be overlapping. Some kind of mask is needed.
By getting the distance between the origin points of each square and the Base Number UV (coordinates containing scale adjustments), we can create circles for each square which adapt with the scale of the number. Subtract and multiply sharpen this mask.
Overlap
Fixed!
I'm using MakeMaterialAttributes nodes for convenient organization for the numbers vs the dice texture itself. The FaceMaskCircle is used in conjunction with the Numbers Texture's mask stored in the B channel to mask between the two materials.
Second contender for title of this page was "Math Rocks" because dice+over half of this material blueprint is texture coordinates.
Wood: Quixel
Fingerprint Texture: https://ambientcg.com/view?id=Fingerprints009
Marble: https://ambientcg.com/view?id=Marble010
Misc Masks: https://nielsdewitte.be/VFExtra/