Skip to main content

Three.js Rendering & Texture System

Is Three.js the Right Choice?

Yes, Three.js is an excellent choice for your requirements. Here's why:

Three.js Strengths

  1. Web-Based: Runs in browsers, no plugins needed
  2. Texture Support: Excellent support for textures, materials, and decals
  3. Text Rendering: Can render text on 3D surfaces via:
    • Canvas textures (render text to canvas, apply as texture)
    • SVG textures
    • Decal systems (project textures onto surfaces)
    • HTML overlays (for UI elements)
  4. Material System: Supports PBR (Physically Based Rendering) materials
  5. Performance: Hardware-accelerated via WebGL
  6. Ecosystem: Large community, extensive documentation
  7. Mobile Support: Works on mobile devices

Architecture Overview

3D Modeling Pipeline:

  1. Model Creation: Models created in external tools (Blender, Maya, 3ds Max, etc.)
  2. Export: Models exported to GLTF/GLB format (industry standard)
  3. Storage: GLTF/GLB files stored in S3/CDN
  4. Rendering: Three.js loads and renders models in browser
  5. Customization: Textures, decals, and text applied dynamically

Texture & Customization System

ModelTexture Entity

Supports multiple customization types:

1. Paint Jobs

var paintJob = new ModelTexture
{
BoatId = boatId,
TextureType = TextureType.PaintJob,
PaintJobName = "Custom Blue Flake",
PaintType = "Metallic",
BaseColor = "#0066CC",
Metallic = 0.8f,
Roughness = 0.2f,
IsCustomPaintJob = true
};

2. Brand Logos/Decals

var brandDecal = new ModelTexture
{
BoatId = boatId,
TextureType = TextureType.BrandLogo,
DecalType = DecalType.BrandLogo,
BrandId = rangerBrandId,
BrandName = "Ranger",
TextureUrl = "https://cdn.example.com/decals/ranger-logo.png",
PlacementLocation = "Transom",
PositionX = 0.5f, // Center
PositionY = 0.8f, // Near bottom
HasBrandLicense = true,
BrandLicenseInfo = "Licensed dealer - License #12345"
};

3. User-Created Boat Names

var boatName = new ModelTexture
{
BoatId = boatId,
TextureType = TextureType.UserText,
DecalType = DecalType.UserText,
UserText = "The Reel Deal",
FontFamily = "Arial",
FontSize = 48,
FontColor = "#FFFFFF",
FontStyle = "bold",
TextAlignment = TextAlignment.Center,
PlacementLocation = "Transom",
PositionX = 0.5f, // Center
PositionY = 0.7f,
Rotation = 0f,
ScaleX = 1.0f,
ScaleY = 1.0f
};

4. Custom Images/Decals

var customDecal = new ModelTexture
{
BoatId = boatId,
TextureType = TextureType.Decal,
DecalType = DecalType.CustomImage,
TextureUrl = "https://s3.amazonaws.com/user-uploads/decal-123.png",
PlacementLocation = "Port Side",
PositionX = 0.3f,
PositionY = 0.5f,
ScaleX = 0.5f,
ScaleY = 0.5f
};

Three.js Implementation Examples

Rendering Text on 3D Surface (Boat Name)

// Option 1: Canvas Texture (Recommended)
function createTextTexture(text, font, fontSize, color) {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');

// Set canvas size based on text
context.font = `${fontSize}px ${font}`;
const metrics = context.measureText(text);
canvas.width = metrics.width + 20;
canvas.height = fontSize + 20;

// Draw text
context.fillStyle = color;
context.font = `${fontSize}px ${font}`;
context.fillText(text, 10, fontSize + 10);

// Create texture
const texture = new THREE.CanvasTexture(canvas);
texture.needsUpdate = true;
return texture;
}

// Option 2: SVG Texture (Better quality, scalable)
function createSVGTexture(text, font, fontSize, color) {
const svg = `
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="100">
<text x="50%" y="50%" font-family="${font}" font-size="${fontSize}"
fill="${color}" text-anchor="middle" dominant-baseline="middle">
${text}
</text>
</svg>
`;
const blob = new Blob([svg], { type: 'image/svg+xml' });
const url = URL.createObjectURL(blob);
const texture = new THREE.TextureLoader().load(url);
return texture;
}

// Option 3: Decal System (Project onto surface)
import { DecalGeometry } from 'three/examples/jsm/geometries/DecalGeometry.js';

function applyDecal(mesh, texture, position, rotation, scale) {
const decalGeometry = new DecalGeometry(
mesh,
position,
rotation,
scale
);
const decalMaterial = new THREE.MeshPhongMaterial({
map: texture,
transparent: true,
depthTest: true,
depthWrite: false,
polygonOffset: true,
polygonOffsetFactor: -4
});
const decal = new THREE.Mesh(decalGeometry, decalMaterial);
scene.add(decal);
}

Applying Paint Job

// Load base model
const loader = new THREE.GLTFLoader();
loader.load('boat-model.glb', (gltf) => {
const boat = gltf.scene;

// Apply custom paint job
boat.traverse((child) => {
if (child.isMesh) {
// Update material properties
child.material.color.setHex(0x0066CC); // Blue
child.material.metalness = 0.8;
child.material.roughness = 0.2;

// Or load custom texture
const textureLoader = new THREE.TextureLoader();
textureLoader.load('custom-paint-job.jpg', (texture) => {
child.material.map = texture;
child.material.needsUpdate = true;
});
}
});

scene.add(boat);
});

Applying Brand Decals

function applyBrandDecal(boatMesh, decalData) {
const { textureUrl, position, rotation, scale } = decalData;

// Load decal texture
const textureLoader = new THREE.TextureLoader();
textureLoader.load(textureUrl, (texture) => {
// Create decal
const decalGeometry = new DecalGeometry(
boatMesh,
new THREE.Vector3(position.x, position.y, position.z),
new THREE.Euler(rotation.x, rotation.y, rotation.z),
new THREE.Vector3(scale.x, scale.y, scale.z)
);

const decalMaterial = new THREE.MeshPhongMaterial({
map: texture,
transparent: true,
opacity: 1.0
});

const decal = new THREE.Mesh(decalGeometry, decalMaterial);
scene.add(decal);
});
}

Brand Licensing

License Tracking

The ModelTexture entity includes:

  • HasBrandLicense: Boolean flag indicating user has license
  • BrandLicenseInfo: License details (number, expiration, etc.)
  • BrandId: Link to brand entity

License Validation

// Check if user can display brand logo
public bool CanDisplayBrandLogo(Guid userId, Guid brandId)
{
var texture = context.ModelTextures
.FirstOrDefault(mt => mt.UserId == userId &&
mt.BrandId == brandId &&
mt.DecalType == DecalType.BrandLogo);

return texture?.HasBrandLicense == true;
}

// Validate license before displaying
public bool ValidateBrandLicense(Guid userId, Guid brandId, string licenseNumber)
{
// Check against license database or API
// This would integrate with brand licensing system
return true; // Placeholder
}

UV Mapping

UV maps define which part of the texture applies to which part of the model:

  • Hull: Main boat body
  • Deck: Top surface
  • Transom: Back of boat (where boat name goes)
  • Port Side: Left side
  • Starboard Side: Right side
  • Bow: Front of boat

The UvMapName field stores which UV map to use, and UvMappingJson can store custom UV coordinates if needed.

Material Properties

Three.js supports PBR (Physically Based Rendering) materials:

  • BaseColor: Base color of the material
  • Metallic: How metallic the surface is (0.0 = non-metallic, 1.0 = metallic)
  • Roughness: Surface roughness (0.0 = mirror-like, 1.0 = matte)
  • Opacity: Transparency (0.0 = transparent, 1.0 = opaque)
  • Normal Map: Surface detail (bumps, scratches)
  • Roughness Map: Variable roughness across surface
  • Metallic Map: Variable metallic properties

Performance Considerations

  1. Texture Compression: Use compressed texture formats (KTX2, Basis)
  2. LOD (Level of Detail): Multiple detail levels for different distances
  3. Texture Atlasing: Combine multiple textures into one atlas
  4. Caching: Cache textures and models in browser
  5. Lazy Loading: Load textures on-demand

Alternative Rendering Engines

While Three.js is excellent, alternatives include:

  1. Babylon.js: More features, slightly steeper learning curve
  2. A-Frame: Higher-level, easier for simple scenes
  3. PlayCanvas: Game engine, more features but heavier
  4. Unity WebGL: Full game engine, exports to WebGL

Recommendation: Stick with Three.js for your use case - it's the most popular, well-documented, and has excellent texture/decal support.

Future Enhancements

  1. Texture Editor: In-browser texture painting tool
  2. Decal Library: Pre-made decals users can apply
  3. Paint Job Templates: Pre-configured paint job presets
  4. Brand License Marketplace: Users can purchase brand licenses
  5. 3D Text Editor: Visual editor for placing boat names
  6. Material Presets: Factory paint jobs, custom finishes