HTML 파일 하나로 실사풍 3D 비행 게임을 만든다면

외부 이미지도 모델 파일도 없이, HTML 한 장과 Three.js만으로 실사 느낌의 항공기 조종 게임을 만들 수 있을까. 하늘과 바다와 지형을 코드로 그려내고, 초안에 실속과 추락과 엔진음을 얹어 게임으로 완성해가는 과정을 담았다.

AI와 사회 · 2026-07-30

브라우저에서 더블클릭 한 번으로 뜨는 실사풍 3D 비행 게임을, 이미지 한 장 없이 HTML 파일 하나로 만들 수 있을까. 이 실습이 내놓은 답은 그렇다는 것이다. 외부 에셋을 전혀 쓰지 않고, Three.js 라이브러리를 CDN에서 불러온 뒤 하늘과 바다와 지형과 기체를 모두 코드로 생성한다.

핵심은 실사감이 고해상도 텍스처가 아니라 몇 가지 계산에서 나온다는 점이다. 텍스처를 내려받아 붙이는 대신, 화면에 보이는 거의 모든 것을 수식으로 그려낸다.

질감 대신 계산으로 만든 실사감

하늘은 단색 그라데이션에서 출발하지만, 최종본에서는 태양 디스크와 그 둘레의 헤일로, 지평선 쪽으로 붉게 번지는 산란까지 셰이더로 계산한다. 바다는 사인파를 겹쳐 물결의 법선을 만들고, 보는 각도에 따라 반사가 세지는 프레넬 효과와 태양이 수면에 부서지는 반짝임을 얹는다. 카메라를 따라다니게 해서 끝없이 이어지는 바다처럼 보이게 하는 것도 같은 발상이다.

지형 역시 여러 주기의 파형을 겹친 절차적 노이즈로 높이를 만들고, 그 높이에 따라 바다에서 해변, 숲, 바위, 설산으로 색을 나눈다. 구름은 캔버스에 그린 흐릿한 원 하나를 스프라이트로 수백 번 흩뿌린 것이다. 무거운 자원 없이도 장면이 그럴듯해지는 이유가 여기에 있다.

그림에서 게임으로

초안이 보기 좋은 비행 장면이었다면, 두 번째 손질은 그것을 조종할 만한 게임으로 바꾸는 작업이었다. 속도가 떨어지면 조종면이 잘 듣지 않고 기수가 스스로 처지는 실속이 들어갔고, 땅이나 바다에 부딪히면 파티클이 터지며 잠시 뒤 다시 살아난다.

여기에 스로틀에 따라 피치가 변하는 합성 엔진음, 롤과 피치를 그대로 비추는 인공수평의, 스로틀에 맞춰 도는 프로펠러가 더해진다. 실사풍이라는 목표가 결국 화면의 그림만이 아니라 조작의 감각까지 포함한다는 것을 보여주는 대목이다.

완성된 코드는 그대로 .html 파일로 저장해 브라우저에서 열면 바로 플레이된다. 화면을 클릭하면 사운드가 켜지고, 키보드로 피치와 롤과 요, 스로틀을 조종한다. 아래 전문에 두 번의 발화가 각각 실행 가능한 전체 코드로 남아 있어, 초안과 최종본을 직접 비교하며 무엇이 어떻게 달라졌는지 확인할 수 있다.

HTML 파일 하나로 실사풍 3D 비행 게임을 만든다면HTML 파일 하나로 실사풍 3D 비행 게임을 만든다면브라우저에서 더블클릭 한 번으로 뜨는 실사풍 3D 비행 게임을, 이미지 한 장 없이 HTML 파일 하나로 만들 수 있을까. 이 실습이 내놓은 답은 그렇다는 것이다. 외부 에셋을 전혀 쓰지 않고, Three.js 라이브러리를 CDN에서 불러온 뒤 하늘과 바다와 지형과 기체를 모두 코드로 생성한다.질감 대신 계산으로 만든 실사감초안이 보기 좋은 비행 장면이었다면, 두 번째 손질은 그것을 조종할 만한 게임으로 바꾸는 작업이었다. 속도가 떨어지면 조종면이 잘 듣지 않고 기수가 스스로 처지는 실속이 들어갔고, 땅이나 바다에 부딪히면 파티클이 터지며 잠시 뒤 다시 살아난다.출처 unpkg.com · Three.js (unpkg CDN)

fable5로 코딩을 해보자. 작성 기회는 2번임. 이전 ai가 작성한 것을 토대로 더 개선하고 쌓아나가면 됨. 첫번째 발화에서는 초안을 쓰고, 두번째 발화에서 한번 더 보태서 최종코드를 제출해. 코드 작성 주제는, HTML로 실행가능한 3d 실사 스타일 항공기 조종 게임 영상 만들기임.

fable 1 · claude-fable-5

좋습니다! 첫 번째 발화이니 초안을 작성하겠습니다. Three.js(CDN)를 사용해 단일 HTML 파일로 실행 가능한 3D 항공기 조종 게임을 만들겠습니다. 실사 느낌을 위해 대기 산란 하늘, 안개, 태양광, 바다/지형, 구름을 넣고, 기본 비행 물리와 조작(피치/롤/요/스로틀)을 구현합니다. html <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <title>Fable Flight - 3D 비행 시뮬레이터 (초안)</title> <style> html,body{margin:0;padding:0;overflow:hidden;background:#000;font-family:'Segoe UI',sans-serif} #hud{position:fixed;left:20px;bottom:20px;color:#9ff;text-shadow:0 0 4px #036; background:rgba(0,20,40,.45);padding:12px 16px;border-radius:10px; font-size:14px;line-height:1.6;user-select:none} #help{position:fixed;right:20px;top:20px;color:#cde;background:rgba(0,20,40,.45); padding:10px 14px;border-radius:10px;font-size:12px;line-height:1.7} b{color:#fff} </style> </head> <body> <div id="hud"></div> <div id="help"> <b>조작법</b><br> W/S : 피치(기수 하강/상승)<br> A/D : 롤 &nbsp; Q/E : 요<br> Shift/Ctrl : 스로틀 ↑/↓<br> C : 카메라 전환 </div> <script type="importmap"> {"imports":{"three":"https://unpkg.com/[email protected]/build/three.module.js"}} </script> <script type="module"> import * as THREE from 'three'; // ===== 기본 세팅 ===== const renderer = new THREE.WebGLRenderer({antialias…

fable 2 · claude-fable-5

두 번째(최종) 발화입니다. 초안을 기반으로 실사감과 게임성을 대폭 보강한 최종 코드를 제출합니다. 주요 개선점: 태양 디스크가 있는 대기 산란풍 하늘 셰이더, 물결 셰이더 바다, 프로펠러 회전·디테일 강화된 기체, 실속(stall) 물리, 지형 충돌 시 폭발·리스폰, WebAudio 엔진음, 인공수평의 HUD, 새·자유 카메라 흔들림 등. html <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <title>Fable Flight - 3D 비행 시뮬레이터 (최종)</title> <style> html,body{margin:0;padding:0;overflow:hidden;background:#000;font-family:'Segoe UI',sans-serif} #hud{position:fixed;left:20px;bottom:20px;color:#9ff;text-shadow:0 0 4px #036; background:rgba(0,20,40,.45);padding:12px 16px;border-radius:10px; font-size:14px;line-height:1.6;user-select:none;backdrop-filter:blur(4px)} #help{position:fixed;right:20px;top:20px;color:#cde;background:rgba(0,20,40,.45); padding:10px 14px;border-radius:10px;font-size:12px;line-height:1.7;backdrop-filter:blur(4px)} #att{position:fixed;right:20px;bottom:20px;width:130px;height:130px;border-radius:50%; border:3px solid rgba(255,255,255,.5);overflow:hidden;background:#000} #attIn{position:absolute;left:-50%;top:-50%;width:200%;height:200%} #attSky{position:absolute;width:100%;height:50%;top:0;background:linear-gradient(#2a64c8,#7fb2e8)} #attGnd{positi…