Material Editing Guide
This guide covers 3Lens's live material editing capabilities, including property inspection, texture management, and real-time shader parameter adjustment.
Table of Contents
- Overview
- Material Inspector Panel
- Editing Material Properties
- Texture Management
- Shader Uniforms
- Material Comparison
- Copy & Paste Materials
- Material Templates
- Performance Considerations
Overview
3Lens provides comprehensive material editing tools:
- Live editing - See changes instantly in the scene
- All material types - Standard, Physical, Toon, Shader, and custom materials
- Texture preview - View and swap textures easily
- Uniform editing - Adjust shader uniforms in real-time
- Comparison mode - Compare different material settings
- History - Undo/redo material changes
Material Inspector Panel
Accessing the Panel
- Select an object with a material
- Open the Material tab in the inspector
- Or right-click an object and choose "Inspect Material"
Panel Layout
┌────────────────────────────────────┐
│ 🎨 Material: PhysicalMaterial │
├────────────────────────────────────┤
│ Type: MeshStandardMaterial │
│ UUID: abc123... │
├────────────────────────────────────┤
│ ▼ Base Properties │
│ Color: [■] #ff6b6b │
│ Opacity: ━━━━━━━● 1.0 │
│ Transparent: [ ] │
│ Side: FrontSide ▼ │
├────────────────────────────────────┤
│ ▼ PBR Properties │
│ Metalness: ━━━━●━━━ 0.5 │
│ Roughness: ━━●━━━━━ 0.3 │
│ Reflectivity: ━━━━━●━━ 0.7 │
├────────────────────────────────────┤
│ ▼ Maps │
│ Diffuse: [texture.jpg] 🔍 │
│ Normal: [normal.png] 🔍 │
│ Roughness: [none] + │
│ Metalness: [none] + │
│ AO: [ao.png] 🔍 │
├────────────────────────────────────┤
│ ▼ Advanced │
│ [Edit Shader] [Export] [Reset] │
└────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Editing Material Properties
Basic Properties
All materials share these common properties:
// Available in inspector or programmatically
material.visible = true;
material.opacity = 1.0;
material.transparent = false;
material.side = THREE.FrontSide; // FrontSide, BackSide, DoubleSide
material.depthTest = true;
material.depthWrite = true;
material.blending = THREE.NormalBlending;2
3
4
5
6
7
8
Color Properties
Click any color swatch to open the color picker:
- Color - Base diffuse color
- Emissive - Self-illumination color
- Specular - Highlight color (Phong materials)
// Programmatic color editing
probe.setMaterialProperty(material, 'color', new THREE.Color('#ff6b6b'));
probe.setMaterialProperty(material, 'emissive', new THREE.Color(0x222222));2
3
PBR Properties (StandardMaterial/PhysicalMaterial)
Physical materials expose these additional properties:
| Property | Range | Description |
|---|---|---|
| Metalness | 0-1 | How metallic the surface is |
| Roughness | 0-1 | Surface micro-roughness |
| Reflectivity | 0-1 | Fresnel reflectance at normal incidence |
| Clearcoat | 0-1 | Clear coat layer intensity |
| Clearcoat Roughness | 0-1 | Clear coat roughness |
| Sheen | 0-1 | Sheen layer intensity |
| Transmission | 0-1 | Transparency for glass-like materials |
| IOR | 1.0-2.5 | Index of refraction |
Real-Time Editing
All changes apply immediately to the scene:
// Edit through 3Lens
probe.editMaterial(mesh.material, {
metalness: 0.8,
roughness: 0.2,
color: new THREE.Color('gold'),
});
// Or directly on the material
mesh.material.metalness = 0.8;
mesh.material.needsUpdate = true;
// Notify 3Lens
probe.notifyMaterialChanged(mesh.material);2
3
4
5
6
7
8
9
10
11
12
13
Texture Management
Viewing Textures
Click the 🔍 icon next to any texture slot:
┌─────────────────────────────────┐
│ Texture Preview │
├─────────────────────────────────┤
│ ┌───────────────────────────┐ │
│ │ │ │
│ │ [texture image] │ │
│ │ │ │
│ └───────────────────────────┘ │
├─────────────────────────────────┤
│ Size: 2048x2048 │
│ Format: RGBA │
│ Filtering: LinearMipMapLinear │
│ Wrap: RepeatWrapping │
│ Anisotropy: 16 │
│ │
│ Memory: 16.0 MB │
└─────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Texture Slots
Common texture slots for PBR materials:
| Slot | Purpose |
|---|---|
| map | Diffuse/albedo color |
| normalMap | Surface normal details |
| roughnessMap | Per-pixel roughness |
| metalnessMap | Per-pixel metalness |
| aoMap | Ambient occlusion |
| emissiveMap | Emission areas |
| displacementMap | Vertex displacement |
| alphaMap | Transparency |
| envMap | Environment reflections |
Swapping Textures
// Load and assign a new texture
const loader = new THREE.TextureLoader();
const newTexture = await loader.loadAsync('/path/to/texture.jpg');
probe.setMaterialTexture(material, 'map', newTexture);2
3
4
5
Texture Properties
Edit texture settings in the expanded view:
// Wrapping
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
// Repeat/offset
texture.repeat.set(2, 2);
texture.offset.set(0.5, 0);
// Filtering
texture.minFilter = THREE.LinearMipMapLinearFilter;
texture.magFilter = THREE.LinearFilter;
// Anisotropic filtering
texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
// Notify update
texture.needsUpdate = true;
probe.notifyTextureChanged(texture);2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Shader Uniforms
ShaderMaterial Editing
For custom ShaderMaterial, 3Lens exposes uniforms:
┌────────────────────────────────────┐
│ 🎨 Material: CustomShader │
├────────────────────────────────────┤
│ Type: ShaderMaterial │
├────────────────────────────────────┤
│ ▼ Uniforms │
│ uTime: ━━━━●━━━━ 2.5 │
│ uColor: [■] #4ecdc4 │
│ uIntensity: ━━━━━●━━ 0.8 │
│ uTexture: [noise.png] 🔍 │
│ uResolution: [1920, 1080] │
├────────────────────────────────────┤
│ ▼ Vertex Shader │
│ [View] [Edit] │
│ ▼ Fragment Shader │
│ [View] [Edit] │
└────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Editing Uniforms
// Edit uniform through 3Lens
probe.setUniform(material, 'uIntensity', 0.8);
probe.setUniform(material, 'uColor', new THREE.Color('#4ecdc4'));
// Edit uniform directly
material.uniforms.uIntensity.value = 0.8;
material.uniforms.uColor.value = new THREE.Color('#4ecdc4');
// No needsUpdate required for uniforms2
3
4
5
6
7
8
9
Supported Uniform Types
3Lens auto-detects and provides appropriate editors:
| Type | Editor |
|---|---|
float | Slider or number input |
int | Number input |
bool | Checkbox |
vec2 | X, Y inputs |
vec3 | X, Y, Z inputs or color picker |
vec4 | X, Y, Z, W inputs or color+alpha |
mat3/mat4 | Matrix editor |
sampler2D | Texture picker |
Material Comparison
Side-by-Side Mode
Compare two materials to see differences:
- Right-click a material → "Compare Material"
- Select another object with a material
- View differences highlighted
┌──────────────────┬──────────────────┐
│ Material A │ Material B │
├──────────────────┼──────────────────┤
│ Color: #ff6b6b │ Color: #4ecdc4 │ ← Different
│ Metalness: 0.5 │ Metalness: 0.5 │
│ Roughness: 0.3 │ Roughness: 0.8 │ ← Different
│ Map: brick.jpg │ Map: stone.jpg │ ← Different
└──────────────────┴──────────────────┘2
3
4
5
6
7
8
A/B Toggle
Toggle between two material states:
// Save current state as A
probe.saveMaterialState(material, 'A');
// Make changes...
material.roughness = 0.9;
material.metalness = 0.1;
// Save as B
probe.saveMaterialState(material, 'B');
// Toggle between states
probe.toggleMaterialState(material); // A → B → A → ...2
3
4
5
6
7
8
9
10
11
12
Copy & Paste Materials
Copy Material
Right-click a material → "Copy Material" or Ctrl+C when material is selected:
// Programmatically copy material settings
const settings = probe.copyMaterialSettings(material);
// Returns JSON-serializable object2
3
Paste Material
Apply copied settings to another material:
- Select target object(s)
- Right-click → "Paste Material" or
Ctrl+V
// Paste to single material
probe.pasteMaterialSettings(targetMaterial, settings);
// Paste to multiple materials
const meshes = [mesh1, mesh2, mesh3];
meshes.forEach(mesh => {
probe.pasteMaterialSettings(mesh.material, settings);
});2
3
4
5
6
7
8
Selective Paste
Paste only specific properties:
probe.pasteMaterialSettings(targetMaterial, settings, {
include: ['color', 'metalness', 'roughness'],
// or
exclude: ['map', 'normalMap'], // Keep existing textures
});2
3
4
5
Material Templates
Built-in Templates
Quick-start with common material presets:
┌────────────────────────────────────┐
│ Material Templates │
├────────────────────────────────────┤
│ 🪨 Stone │
│ 🪵 Wood │
│ 🔩 Metal (Polished) │
│ 🔩 Metal (Brushed) │
│ 🧊 Glass │
│ 🌊 Water │
│ 🧱 Brick │
│ 💎 Crystal │
│ 🎨 Plastic │
│ 📦 Cardboard │
└────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
Apply Template
// Apply built-in template
probe.applyMaterialTemplate(material, 'polished-metal');
// Template applies:
// - metalness: 1.0
// - roughness: 0.1
// - color: #c0c0c0
// - envMapIntensity: 1.02
3
4
5
6
7
8
Create Custom Template
// Save current material as template
probe.saveMaterialTemplate('my-custom-metal', material, {
description: 'Weathered bronze appearance',
category: 'Metal',
});
// List custom templates
const templates = probe.getMaterialTemplates({ includeCustom: true });2
3
4
5
6
7
8
Performance Considerations
Material Optimization Tips
The inspector shows performance hints:
┌────────────────────────────────────┐
│ ⚠️ Performance Hints │
├────────────────────────────────────┤
│ • 4K textures detected - consider │
│ using 2K for mobile │
│ • Transparency enabled - may │
│ affect draw order │
│ • No normal map - consider adding │
│ for detail without geometry │
└────────────────────────────────────┘2
3
4
5
6
7
8
9
10
Batch Material Editing
Edit multiple materials at once:
// Select multiple meshes
const meshes = [mesh1, mesh2, mesh3];
meshes.forEach(m => probe.addToSelection(m));
// Edit all selected materials
probe.batchEditMaterials({
roughness: 0.5,
metalness: 0.3,
});2
3
4
5
6
7
8
9
Material Sharing
Identify and merge duplicate materials:
// Find duplicate materials
const duplicates = probe.findDuplicateMaterials();
// Returns groups of materials with identical settings
// Merge duplicates (share single material)
probe.mergeDuplicateMaterials(duplicates[0]);2
3
4
5
6
Keyboard Shortcuts
| Key | Action |
|---|---|
M | Open material editor for selection |
Ctrl+C | Copy material settings |
Ctrl+V | Paste material settings |
Ctrl+Z | Undo material change |
Ctrl+Shift+Z | Redo material change |
R | Reset material to defaults |
Framework Integration
React
import { useThreeLensProbe, useSelectedObject } from '@3lens/react-bridge';
import { useMemo } from 'react';
function MaterialEditor() {
const probe = useThreeLensProbe();
const { selectedNode } = useSelectedObject();
const material = useMemo(() => {
return selectedNode?.object?.material;
}, [selectedNode]);
if (!material) return null;
return (
<div className="material-editor">
<h3>Material: {material.name || 'Unnamed'}</h3>
<label>
Metalness
<input
type="range"
min="0"
max="1"
step="0.01"
value={material.metalness ?? 0}
onChange={(e) => {
probe.setMaterialProperty(material, 'metalness', parseFloat(e.target.value));
}}
/>
</label>
<label>
Roughness
<input
type="range"
min="0"
max="1"
step="0.01"
value={material.roughness ?? 0.5}
onChange={(e) => {
probe.setMaterialProperty(material, 'roughness', parseFloat(e.target.value));
}}
/>
</label>
</div>
);
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Vue
<script setup>
import { useThreeLens, useSelectedObject } from '@3lens/vue-bridge';
import { computed, ref } from 'vue';
const { probe } = useThreeLens();
const { selectedNode } = useSelectedObject();
const material = computed(() => selectedNode.value?.object?.material);
function updateProperty(prop, value) {
if (material.value && probe.value) {
probe.value.setMaterialProperty(material.value, prop, value);
}
}
</script>
<template>
<div v-if="material" class="material-editor">
<h3>Material: {{ material.name || 'Unnamed' }}</h3>
<label>
Metalness
<input
type="range"
min="0"
max="1"
step="0.01"
:value="material.metalness ?? 0"
@input="updateProperty('metalness', parseFloat($event.target.value))"
/>
</label>
<label>
Roughness
<input
type="range"
min="0"
max="1"
step="0.01"
:value="material.roughness ?? 0.5"
@input="updateProperty('roughness', parseFloat($event.target.value))"
/>
</label>
</div>
</template>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Troubleshooting
Changes Not Visible
- Ensure
material.needsUpdate = trueafter direct edits - Check if material is being overwritten in render loop
- Verify the correct mesh is selected
Texture Not Loading
- Check texture path (relative vs absolute)
- Verify CORS settings for cross-origin textures
- Check console for loading errors
Performance After Editing
- Large textures affect memory and rendering
- Transparent materials require special sorting
- Too many unique materials prevent batching