Initial commit
This commit is contained in:
@@ -0,0 +1,461 @@
|
||||
Tileset Generator — Design Document
|
||||
1. Overview
|
||||
|
||||
Tileset Generator is a simple browser-based image tool that lets a user upload an image and convert it into a tileable texture. The tool hides obvious seams by offsetting the image, blending or healing the exposed center seams, and exporting the result as a resized .webp texture suitable for games, web backgrounds, 3D materials, and UI art.
|
||||
|
||||
The tool should run fully client-side in the browser. No server upload is required.
|
||||
|
||||
2. Core User Flow
|
||||
User opens the Tileset Generator page.
|
||||
User uploads or drags in an image.
|
||||
The app displays:
|
||||
Original preview
|
||||
Tileable preview
|
||||
Repeated texture preview
|
||||
The app shifts the image by 50% horizontally and vertically.
|
||||
The app hides the newly exposed seams using a selected seam-repair method.
|
||||
User adjusts settings:
|
||||
Output size
|
||||
Seam blend width
|
||||
Repair strength
|
||||
Export quality
|
||||
Crop or fit behavior
|
||||
User exports the result as a .webp file.
|
||||
3. Primary Features
|
||||
Image Upload
|
||||
|
||||
Supported formats:
|
||||
|
||||
.png
|
||||
.jpg
|
||||
.jpeg
|
||||
.webp
|
||||
|
||||
Input methods:
|
||||
|
||||
File picker
|
||||
Drag and drop
|
||||
Optional paste from clipboard
|
||||
|
||||
The image should be processed locally using browser APIs.
|
||||
|
||||
Seam Offset
|
||||
|
||||
The standard tile-generation operation is a 50% offset:
|
||||
|
||||
Original image:
|
||||
|
||||
[A B]
|
||||
[C D]
|
||||
|
||||
After 50% offset:
|
||||
|
||||
[D C]
|
||||
[B A]
|
||||
|
||||
This moves the original outer edges into the center of the image, making seams visible and easier to hide.
|
||||
|
||||
User-facing option:
|
||||
|
||||
Offset Mode:
|
||||
- Auto 50% offset
|
||||
- Horizontal only
|
||||
- Vertical only
|
||||
- Custom offset
|
||||
|
||||
For V1, Auto 50% offset is enough.
|
||||
|
||||
Seam Hiding
|
||||
|
||||
The exposed seam appears as a vertical and horizontal cross through the center of the offset image.
|
||||
|
||||
V1 should use a simple but effective blend-based repair approach.
|
||||
|
||||
V1 Seam Repair Method
|
||||
|
||||
Use a soft blur/blend region around the center seams:
|
||||
|
||||
Define a seam band around the vertical center.
|
||||
Define a seam band around the horizontal center.
|
||||
Sample pixels from both sides of the seam.
|
||||
Blend across the seam using a smooth falloff.
|
||||
Optionally add subtle noise preservation to avoid overly blurry lines.
|
||||
|
||||
User controls:
|
||||
|
||||
Seam Width: 8–128 px
|
||||
Blend Strength: 0–100%
|
||||
Detail Preservation: Low / Medium / High
|
||||
|
||||
Default:
|
||||
|
||||
Seam Width: 32 px
|
||||
Blend Strength: 70%
|
||||
Detail Preservation: Medium
|
||||
Repeated Preview
|
||||
|
||||
The app should show the generated texture repeated in a grid so the user can visually inspect tiling quality.
|
||||
|
||||
Preview modes:
|
||||
|
||||
Single Tile
|
||||
2x2 Repeat
|
||||
3x3 Repeat
|
||||
4x4 Repeat
|
||||
|
||||
Default:
|
||||
|
||||
3x3 Repeat
|
||||
|
||||
This is critical because a texture can look good alone but fail when repeated.
|
||||
|
||||
Resize and Export
|
||||
|
||||
The user can export the final image as .webp.
|
||||
|
||||
Output size options:
|
||||
|
||||
Original Size
|
||||
512 x 512
|
||||
1024 x 1024
|
||||
2048 x 2048
|
||||
Custom Width / Height
|
||||
|
||||
Resize behavior:
|
||||
|
||||
Crop to Square
|
||||
Fit Within Size
|
||||
Stretch to Size
|
||||
Keep Aspect Ratio
|
||||
|
||||
Default:
|
||||
|
||||
1024 x 1024
|
||||
Crop to Square
|
||||
WebP Quality: 90
|
||||
|
||||
Export filename pattern:
|
||||
|
||||
tileset-generator-[width]x[height].webp
|
||||
|
||||
Example:
|
||||
|
||||
tileset-generator-1024x1024.webp
|
||||
4. Interface Layout
|
||||
Suggested Layout
|
||||
+------------------------------------------------------+
|
||||
| Tileset Generator |
|
||||
| Upload image → Generate tileable WebP texture |
|
||||
+------------------------------------------------------+
|
||||
|
||||
+----------------------+-------------------------------+
|
||||
| Controls | Preview |
|
||||
| | |
|
||||
| Upload Image | [ Single / Repeated Preview ] |
|
||||
| Output Size | |
|
||||
| Seam Width | |
|
||||
| Blend Strength | |
|
||||
| Export Quality | |
|
||||
| | |
|
||||
| [Generate] [Export] | |
|
||||
+----------------------+-------------------------------+
|
||||
Control Panel
|
||||
|
||||
Controls should appear in this order:
|
||||
|
||||
Upload image
|
||||
Output size
|
||||
Resize behavior
|
||||
Seam width
|
||||
Blend strength
|
||||
Preview repeat count
|
||||
WebP quality
|
||||
Export button
|
||||
5. Recommended Tech Stack
|
||||
|
||||
For a lightweight browser tool:
|
||||
|
||||
Vite + React + TypeScript
|
||||
Canvas 2D API
|
||||
browser-image-compression optional
|
||||
FileSaver optional
|
||||
|
||||
Recommended stack:
|
||||
|
||||
React for UI
|
||||
TypeScript for safer image-processing code
|
||||
Canvas 2D API for pixel manipulation
|
||||
OffscreenCanvas / Web Worker optional for larger images
|
||||
WebP export via canvas.toBlob()
|
||||
|
||||
No backend required.
|
||||
|
||||
6. Image Processing Pipeline
|
||||
Step 1 — Load Image
|
||||
File → Object URL → ImageBitmap → Canvas
|
||||
|
||||
Use createImageBitmap() when available.
|
||||
|
||||
Step 2 — Normalize Image
|
||||
|
||||
Depending on the selected resize behavior:
|
||||
|
||||
Crop to square
|
||||
Fit within output bounds
|
||||
Stretch
|
||||
Preserve aspect ratio
|
||||
|
||||
For texture generation, square textures are strongly preferred.
|
||||
|
||||
Recommended internal working size:
|
||||
|
||||
1024 x 1024 by default
|
||||
Step 3 — Offset Image
|
||||
|
||||
Draw the source image into a new canvas in four wrapped quadrants.
|
||||
|
||||
Pseudo-code:
|
||||
|
||||
function offsetCanvas(source, offsetX, offsetY) {
|
||||
draw source shifted by offsetX / offsetY
|
||||
wrap overflowing regions to opposite edges
|
||||
}
|
||||
|
||||
For 50% offset:
|
||||
|
||||
offsetX = width / 2
|
||||
offsetY = height / 2
|
||||
Step 4 — Repair Seam
|
||||
|
||||
Repair the vertical seam centered at:
|
||||
|
||||
x = width / 2
|
||||
|
||||
Repair the horizontal seam centered at:
|
||||
|
||||
y = height / 2
|
||||
|
||||
For each pixel inside the seam band:
|
||||
|
||||
distanceFromSeam = abs(pixelPosition - seamCenter)
|
||||
blendAmount = 1 - smoothstep(0, seamWidth, distanceFromSeam)
|
||||
|
||||
Blend nearby pixels from both sides of the seam.
|
||||
|
||||
A simple practical V1 approach:
|
||||
|
||||
For each seam pixel:
|
||||
- Sample left/right or top/bottom neighbor pixels
|
||||
- Average them based on distance from seam center
|
||||
- Mix the averaged color with the original pixel
|
||||
|
||||
This gives a soft seam-hiding effect without needing AI/inpainting.
|
||||
|
||||
Step 5 — Preview Repetition
|
||||
|
||||
Create a preview canvas or CSS background using the generated image.
|
||||
|
||||
For repeated preview:
|
||||
|
||||
background-image: url(generated-texture.webp);
|
||||
background-repeat: repeat;
|
||||
background-size: tileSize tileSize;
|
||||
|
||||
Canvas-based repeated preview is also fine.
|
||||
|
||||
Step 6 — Export WebP
|
||||
|
||||
Use:
|
||||
|
||||
canvas.toBlob(
|
||||
blob => saveBlob(blob, filename),
|
||||
"image/webp",
|
||||
quality
|
||||
);
|
||||
|
||||
Where quality is:
|
||||
|
||||
quality = userQuality / 100;
|
||||
7. V1 Scope
|
||||
Include in V1
|
||||
Local image upload
|
||||
Canvas-based 50% offset
|
||||
Basic seam blending
|
||||
Output resize options
|
||||
Repeated texture preview
|
||||
WebP export
|
||||
Quality slider
|
||||
Drag-and-drop support
|
||||
Exclude from V1
|
||||
AI inpainting
|
||||
Multi-texture PBR export
|
||||
Normal map generation
|
||||
Roughness/metalness map generation
|
||||
Batch processing
|
||||
Account system
|
||||
Server-side processing
|
||||
8. Nice-to-Have Features
|
||||
|
||||
Good V2 additions:
|
||||
|
||||
Brush-based manual seam repair
|
||||
Clone-stamp tool
|
||||
Random patch sampling
|
||||
Content-aware seam healing
|
||||
Generate normal map
|
||||
Generate roughness map
|
||||
Batch export
|
||||
Presets:
|
||||
Pixel art
|
||||
Stone
|
||||
Fabric
|
||||
Terrain
|
||||
Sci-fi panel
|
||||
Organic texture
|
||||
Export as:
|
||||
.webp
|
||||
.png
|
||||
.jpg
|
||||
Save/load project settings
|
||||
Before/after comparison slider
|
||||
9. Data Model
|
||||
type ResizeMode =
|
||||
| "crop-square"
|
||||
| "fit"
|
||||
| "stretch"
|
||||
| "keep-aspect";
|
||||
|
||||
type PreviewMode =
|
||||
| "single"
|
||||
| "repeat-2"
|
||||
| "repeat-3"
|
||||
| "repeat-4";
|
||||
|
||||
type TilesetSettings = {
|
||||
outputWidth: number;
|
||||
outputHeight: number;
|
||||
resizeMode: ResizeMode;
|
||||
seamWidth: number;
|
||||
blendStrength: number;
|
||||
detailPreservation: "low" | "medium" | "high";
|
||||
webpQuality: number;
|
||||
previewMode: PreviewMode;
|
||||
};
|
||||
|
||||
Default settings:
|
||||
|
||||
const defaultSettings: TilesetSettings = {
|
||||
outputWidth: 1024,
|
||||
outputHeight: 1024,
|
||||
resizeMode: "crop-square",
|
||||
seamWidth: 32,
|
||||
blendStrength: 70,
|
||||
detailPreservation: "medium",
|
||||
webpQuality: 90,
|
||||
previewMode: "repeat-3",
|
||||
};
|
||||
10. Main Components
|
||||
App
|
||||
├── UploadPanel
|
||||
├── SettingsPanel
|
||||
├── PreviewPanel
|
||||
│ ├── OriginalPreview
|
||||
│ ├── TilePreview
|
||||
│ └── RepeatedPreview
|
||||
├── ExportPanel
|
||||
└── ProcessingWorker optional
|
||||
11. Performance Considerations
|
||||
|
||||
For V1, Canvas 2D is enough.
|
||||
|
||||
Recommended limits:
|
||||
|
||||
Max input image size: 4096 x 4096
|
||||
Default working size: 1024 x 1024
|
||||
Warning above: 2048 x 2048
|
||||
|
||||
For large files:
|
||||
|
||||
Downscale before seam repair.
|
||||
Use createImageBitmap() for efficient decoding.
|
||||
Consider Web Worker processing later.
|
||||
Avoid repeatedly processing on every slider movement.
|
||||
Debounce setting changes by 150–300 ms.
|
||||
12. Error Handling
|
||||
|
||||
Show user-friendly errors for:
|
||||
|
||||
Unsupported file type
|
||||
Image failed to load
|
||||
Image too large
|
||||
Browser does not support WebP export
|
||||
Canvas export failed
|
||||
|
||||
Example messages:
|
||||
|
||||
This file type is not supported. Please upload a PNG, JPG, or WebP image.
|
||||
This image is very large. The tool will resize it before processing.
|
||||
13. Export Behavior
|
||||
|
||||
Export button should be disabled until:
|
||||
|
||||
An image is uploaded
|
||||
Processing is complete
|
||||
A valid output size exists
|
||||
|
||||
Export metadata:
|
||||
|
||||
Format: WebP
|
||||
Quality: user-selected
|
||||
Dimensions: user-selected
|
||||
Color space: browser default / sRGB
|
||||
Transparency: preserve if source supports alpha
|
||||
14. Practical V1 Algorithm
|
||||
1. Load uploaded image.
|
||||
2. Resize/crop to target working canvas.
|
||||
3. Offset image by 50% width and 50% height.
|
||||
4. Blend center vertical seam.
|
||||
5. Blend center horizontal seam.
|
||||
6. Display single and repeated previews.
|
||||
7. Export final canvas as WebP.
|
||||
|
||||
Pseudo-code:
|
||||
|
||||
async function generateTileableTexture(file: File, settings: TilesetSettings) {
|
||||
const bitmap = await createImageBitmap(file);
|
||||
|
||||
const normalizedCanvas = normalizeImage(bitmap, settings);
|
||||
const offsetCanvas = applyWrappedOffset(
|
||||
normalizedCanvas,
|
||||
settings.outputWidth / 2,
|
||||
settings.outputHeight / 2
|
||||
);
|
||||
|
||||
const repairedCanvas = repairCenterSeams(offsetCanvas, {
|
||||
seamWidth: settings.seamWidth,
|
||||
blendStrength: settings.blendStrength,
|
||||
detailPreservation: settings.detailPreservation,
|
||||
});
|
||||
|
||||
return repairedCanvas;
|
||||
}
|
||||
15. Success Criteria
|
||||
|
||||
The tool is successful when:
|
||||
|
||||
A user can upload an image and export a tileable .webp in under a minute.
|
||||
The exported texture repeats without obvious hard seams.
|
||||
The UI is understandable without instructions.
|
||||
The tool runs fully in-browser.
|
||||
The output is usable in game engines, websites, and 3D material workflows.
|
||||
16. Suggested MVP Build Order
|
||||
Build image upload and preview.
|
||||
Add canvas normalization/resizing.
|
||||
Implement 50% wrapped offset.
|
||||
Add basic vertical/horizontal seam blend.
|
||||
Add repeated preview.
|
||||
Add WebP export.
|
||||
Add settings controls.
|
||||
Add drag-and-drop polish.
|
||||
Add error handling.
|
||||
Test with photos, fabric, stone, clouds, sci-fi panels, and terrain textures.
|
||||
Reference in New Issue
Block a user