Created
March 8, 2025 00:57
-
-
Save Denchyaknow/e2dec246b7f540daf10a6acb6051c6bd to your computer and use it in GitHub Desktop.
HowTo_CalculateTilingAndOffset
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//This logic is good for when you have a childed Quad whos UV coodinates need to match another parent Quads UV Coods. | |
public class UVMapper | |
{ | |
private float scaleFactorX = 1.0f; | |
private float scaleFactorY = 1.0f; | |
private float quad_aspect = 1f;//LocalScale Aspect of Quads LocalScale X/Y | |
private float frame_aspect = 1f;//Pixel Aspect of ImageFrames Width/Height | |
private float pixelHeight = 1f; | |
private float pixelWidth = 1f; | |
Vector3 quad_scale = Vector3.one; | |
const float MIN_SCALE = 0.001f; | |
const float PAN_VALUE = 0.5f;//For Tiling and Offsetting UV Coordinates | |
public void UpdateQuadUVs(IRenderSurface surface) | |
{ | |
// Get the Transform of the IRenderSurface (ImageFrame.Quad) | |
Vector3 quadWorldScale = surface.Scale; | |
quadWorldScale.x = Mathf.Max(quadWorldScale.x, MIN_SCALE); | |
quadWorldScale.y = Mathf.Max(quadWorldScale.y, MIN_SCALE); | |
float frameWidth = Mathf.Max(surface.PixelWidth, 1f); | |
float frameHeight = Mathf.Max(surface.PixelHeight, 1f); | |
if (!adjustUVs) | |
{ | |
//This bit works but not what we wanted, it scales the child quad relative to the parent quad | |
frame_aspect = frameWidth >= frameHeight ? frameWidth / frameHeight: frameHeight / frameWidth; | |
scaleFactorX = Mathf.Abs(quadWorldScale.x); | |
scaleFactorY = Mathf.Abs(quadWorldScale.y); | |
if (scaleFactorX > scaleFactorY) | |
{ | |
quad_aspect = scaleFactorX / scaleFactorY; | |
quad_scale.x = 1f; | |
quad_scale.y = quad_aspect; | |
} | |
else if (scaleFactorY > scaleFactorX) | |
{ | |
quad_aspect = scaleFactorY / scaleFactorX; | |
quad_scale.x = quad_aspect; | |
quad_scale.y = 1f; | |
} | |
transform.localScale = quad_scale; | |
} | |
} | |
void DrawLine(Color brushColor, float brushSize, Vector2 startUnscaled, Vector2 endUnscaled) | |
{ | |
Vector2 start_pix = Vector2.zero; | |
Vector2 end_pix = Vector2.zero; | |
Vector2 start = Vector2.one; | |
Vector2 end = Vector2.one; | |
if (!adjustUVs) | |
{ | |
// Convert to pixel coordinates for the shader | |
// This is the Original Drawing Logic | |
start_pix = startUnscaled * TEXTURE_SIZE; | |
end_pix = endUnscaled * TEXTURE_SIZE; | |
} | |
else | |
{ | |
//Apply the tiling and offset to the UV coordinates just like the shader does | |
start = ApplyTilingAndOffset(startUnscaled); | |
end = ApplyTilingAndOffset(endUnscaled); | |
//Convert to UVs to pixel coordinates for the shader | |
start_pix = start * TEXTURE_SIZE; | |
end_pix = end * TEXTURE_SIZE; | |
} | |
if (verbose) | |
{ | |
Debug.Log($"UVAdjusted: start({start.x}, {start.y}) end({end.x}, {end.y})"); | |
Debug.Log($"UVOriginal: startUnscaled({startUnscaled.x}, {startUnscaled.y}), endUnscaled({endUnscaled.x}, {endUnscaled.y})"); | |
} | |
shader_instance.SetVector(start_position_id, start_pix); | |
shader_instance.SetVector(end_position_id, end_pix); | |
shader_instance.SetFloat(stroke_smoothing_id, strokeSmoothingInterval); | |
shader_instance.SetFloat(brush_size_id, brushSize); | |
shader_instance.SetVector(brush_color_id, brushColor); | |
// Set all required textures for kernel_update | |
SetShaderTexturesForKernelUpdate(); | |
shader_instance.Dispatch(kernel_update, thread_groups_x, thread_groups_y, 1); | |
SwapBuffers(current_page); | |
} | |
Vector2 CalculateTiling(Vector3 localScale) | |
{ | |
Vector2 tiling = Vector2.one; | |
var widthAspect = localScale.x / localScale.y; | |
var heightAspect = localScale.y / localScale.x; | |
if(widthAspect > heightAspect) | |
{ | |
tiling.x = widthAspect; | |
} | |
else | |
{ | |
tiling.y = heightAspect; | |
} | |
return tiling; | |
} | |
Vector2 CalculateOffset(Vector3 localScale, float panning) | |
{ | |
Vector2 offset = Vector2.zero; | |
var widthAspect = localScale.x / localScale.y; | |
var heightAspect = localScale.y / localScale.x; | |
if (widthAspect > heightAspect) | |
{ | |
offset.y = Mathf.Lerp(0f, (1f - heightAspect), panning); | |
} | |
else | |
{ | |
offset.x = Mathf.Lerp(0f, (1f - widthAspect), panning); | |
} | |
return offset; | |
} | |
/// <summary> | |
/// Applies tiling and offset to UV coordinates | |
/// </summary> | |
/// <param name="uv">Original UV coordinates</param> | |
/// <param name="tiling">Tiling factor (x, y)</param> | |
/// <param name="offset">Offset value (x, y)</param> | |
/// <returns>Transformed UV coordinates</returns> | |
Vector2 ApplyTilingAndOffset(Vector2 uv) | |
{ | |
Vector2 tiling = Vector2.one; | |
Vector2 offset = Vector2.zero; | |
//The Scale of my parent Quad, my scale is always 1,1,1 | |
var widthAspect = quad_scale.x / quad_scale.y; | |
var heightAspect = quad_scale.y / quad_scale.x; | |
if (widthAspect > heightAspect) | |
{ | |
tiling.y = heightAspect; | |
offset.y = Mathf.Lerp(0f, (1f - heightAspect), PAN_VALUE); | |
} | |
else | |
{ | |
tiling.x = widthAspect; | |
offset.x = Mathf.Lerp(0f, (1f - widthAspect), PAN_VALUE); | |
} | |
// First apply tiling (scale) | |
Vector2 scaledUV = new Vector2(uv.x * tiling.x, uv.y * tiling.y); | |
// Then apply offset (translation) | |
Vector2 finalUV = new Vector2(scaledUV.x + offset.x, scaledUV.y + offset.y); | |
return finalUV; | |
} | |
/// <summary> | |
/// Extended version with additional parameters visible in the shader graph | |
/// </summary> | |
/// <param name="uv">Original UV coordinates</param> | |
/// <param name="tiling">Tiling factor (x, y)</param> | |
/// <param name="offset">Offset value (x, y)</param> | |
/// <param name="sample">Optional sample texture coordinates for more complex effects</param> | |
/// <param name="shapeTexture">Optional shape texture influence</param> | |
/// <returns>Transformed UV coordinates</returns> | |
Vector2 ApplyAdvancedTilingAndOffset(Vector2 uv, Vector2 tiling, Vector2 offset, Vector2 sample = default, float shapeInfluence = 0f) | |
{ | |
// Basic tiling and offset | |
Vector2 tiledUV = new Vector2(uv.x * tiling.x, uv.y * tiling.y); | |
// Apply sample influence if provided | |
if (sample != default) | |
{ | |
tiledUV += new Vector2(sample.x * shapeInfluence, sample.y * shapeInfluence); | |
} | |
// Apply offset | |
Vector2 finalUV = new Vector2(tiledUV.x + offset.x, tiledUV.y + offset.y); | |
return finalUV; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment