Prototype fidelity

프로토타입 충실도

Tuning a prototype's realism — from a rough concept mockup to a production-finish model — to match exactly what question it needs to answer.

Also known as: Low-fi vs. high-fi prototype목업 단계
···
html
<div class="pf-cap"></div>
css
.pf-cap{position:absolute;left:0;right:0;bottom:6%;text-align:center;font-size:clamp(9px,2.4vmin,13px);color:#f1f0eccc}
js
import * as THREE from 'three';
import { RoundedBoxGeometry } from 'three/addons/geometries/RoundedBoxGeometry.js';
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0d0d12);
const camera = new THREE.PerspectiveCamera(40, 1, 0.1, 100);
camera.position.set(0, 0.4, 5.6);
const canvas = document.createElement('canvas');
canvas.width = 128; canvas.height = 128;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#8a8a8a'; ctx.fillRect(0, 0, 128, 128);
ctx.strokeStyle = '#6f6f6f'; ctx.lineWidth = 2;
for (let y = 4; y < 128; y += 8) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(128, y); ctx.stroke(); }
const layerTex = new THREE.CanvasTexture(canvas);
const geo = new RoundedBoxGeometry(1.3, 2, 0.6, 3, 0.1);
const stages = [
  { mat: new THREE.MeshStandardMaterial({ color: 0x9a9a94, roughness: 1, metalness: 0 }), label: 'stage 1 — foam block' },
  { mat: new THREE.MeshStandardMaterial({ map: layerTex, roughness: 0.85, metalness: 0 }), label: 'stage 2 — 3D print' },
  { mat: new THREE.MeshPhysicalMaterial({ color: 0x5b5bf7, roughness: 0.15, metalness: 0.1, clearcoat: 1 }), label: 'stage 3 — production finish' },
];
const mesh = new THREE.Mesh(geo, stages[0].mat);
scene.add(mesh);
const key = new THREE.DirectionalLight(0xffffff, 2.1); key.position.set(3, 4, 5); scene.add(key);
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
const cap = document.querySelector('.pf-cap');
function resize() { renderer.setSize(innerWidth, innerHeight); camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); }
addEventListener('resize', resize); resize();
let idx = 0;
cap.textContent = stages[0].label;
setInterval(() => {
  idx = (idx + 1) % stages.length;
  mesh.material = stages[idx].mat;
  cap.textContent = stages[idx].label;
}, 1600);
renderer.setAnimationLoop((t) => {
  mesh.rotation.y = t * 0.00045;
  camera.lookAt(0, 0, 0);
  renderer.render(scene, camera);
});

Making every prototype maximally polished is wasted effort and a trap. A hand-carved foam block has no color, no finish, but answers a shape question — "does this size fit a hand," "is this proportion right" — in a single day. Try to give that same block a perfect paint finish, and if the shape turns out wrong, all that finishing work gets thrown away with it.

A 3D-printed prototype is the next rung — it can validate real dimensions and how parts actually fit together (does this button really press, do these two halves actually mate), but it's usually one color (whatever the printer material is) and its surface shows visible layer lines. This stage answers "does the interaction work," and color and finish get deferred again. A final high-fidelity prototype is painted and finished in the real CMF (color, material, finish) the production part will ship in — used for exec reviews or user research to answer "does this look and feel like a real product."

The three stages map directly onto a digital product's wireframe → clickable prototype → pixel-perfect UI progression: each stage raises fidelity only as far as the question it needs to answer requires, and spends no time polishing beyond that. Fine-tuning pixels at the wireframe stage is the same mistake as sanding a foam block smooth.

When to use

Decide which question a prototype needs to answer — shape, interaction, or final impression — before raising its fidelity that far and no further.