요약
6명의 예술가가 VR로 그림, 디자인, 조각 작업을 할 수 있도록 초청받았습니다. 이것은 세션을 기록하고, 데이터를 변환하고, 웹 브라우저에서 실시간으로 볼 수 있습니다.
https://g.co/VirtualArtSessions
정말 생존할 시간이야! 소비자가 가상 현실을 도입하면서 새로운 가능성이 발견되고 있다는 것을 의미합니다. 틸트 브러시, HTC Vive에서 구매할 수 있는 Google 제품은 3가지 나타냅니다. 처음으로 Tilt Brush를 사용해 보았을 때 "애니메이션 컨트롤러"라는 놀라운 힘이 있는 방' 문제가 발생할 수 있습니다. 사실 이곳저곳을 돌아다닐 수 있는 마치 주변의 빈 공간에 그림을 그릴 수 있는 것처럼 말이죠.
Google의 데이터 아트팀은 가상 현실 체험을 할 수 있습니다. 작동한다는 것입니다. 이를 위해 팀은 조각가, 일러스트레이터, 컨셉 디자이너, 패션 아티스트, 설치 예술가, 거리 예술가 새로운 매체에서 자신만의 스타일로 아트워크를 만들 수 있습니다
가상 현실에서 그림 녹화하기
Unity에 내장된 Tilt Brush 소프트웨어 자체는
룸스케일 VR을 사용하여 머리 위치 추적 (HMD)
각 손에 있는 컨트롤러입니다. Tilt Brush로 만든 포스터
기본적으로 .tilt
파일로 내보내집니다. 웹에서 이러한 경험을 제공하기 위해
예술작품 데이터만 필요한 것이 아니라는 사실을 깨달았습니다. Google은 사이버 범죄자로부터
Tilt Brush팀에서 실행취소/삭제 작업도 내보낼 수 있도록 Tilt Brush를 수정했습니다.
초당 90번의 속도로 머리와 손을 움직일 수 있습니다.
그림을 그릴 때 Tilt Brush가 컨트롤러의 위치와 각도를 받아서 하나의 '획'으로 만들 수 있습니다. 예를 들어 여기에서 확인할 수 있습니다. 우리는 이러한 스트로크를 추출하여 원시 JSON으로 출력하는 플러그인을 작성했습니다.
{
"metadata": {
"BrushIndex": [
"d229d335-c334-495a-a801-660ac8a87360"
]
},
"actions": [
{
"type": "STROKE",
"time": 12854,
"data": {
"id": 0,
"brush": 0,
"b_size": 0.081906750798225,
"color": [
0.69848710298538,
0.39136275649071,
0.211316883564
],
"points": [
[
{
"t": 12854,
"p": 0.25791856646538,
"pos": [
[
1.9832634925842,
17.915264129639,
8.6014995574951
],
[
-0.32014992833138,
0.82291424274445,
-0.41208130121231,
-0.22473378479481
]
]
}, ...many more points
]
]
}
}, ... many more actions
]
}
위의 스니펫은 스케치 JSON 형식의 형식을 간략히 설명합니다.
여기서 각 획은 'STROKE' 유형의 작업으로 저장됩니다. 또한 아티스트가 실수를 하거나 획을 교정하는 모습을 그러니 'DELETE'를 저장하는 것이 중요했습니다. 액션, 즉 획 전체를 지우거나 실행취소합니다.
각 획의 기본 정보가 저장되므로 브러시 유형, 브러시 크기, 색상 모두 수집됩니다.
마지막으로 획의 각 꼭짓점은 저장되며, 여기에는 위치,
각도, 시간, 컨트롤러의 트리거 압력 강도 (p
로 표시됨)
합니다.
회전은 4개 구성요소로 이루어진 쿼터니언입니다. 이것은 나중에 짐벌 잠금을 방지하기 위해 획을 렌더링합니다.
WebGL로 스케치 재생
웹 브라우저에서 스케치를 표시하기 위해 THREE.js에서 지오메트리를 모방한 도형 생성 코드를 작성함 자세히 살펴보겠습니다.
Tilt Brush가 사용자의 손을 기반으로 실시간으로 삼각형 스트립을 생성하는 동안 스케치 전체가 '완료'된 것입니다. 50,000개의 문자를 있습니다. 따라서 대부분의 실시간 계산을 우회하고 로드 시 도형을 처리합니다.
획에 있는 각 꼭짓점 쌍은 방향 벡터 (파란색 선
위의 코드 스니펫에서는 moveVector
)을 사용하여 각 포인트를 연결합니다.
또한 각 점은 방향, 즉 점의 방향을 나타내는
컨트롤러의 현재 각도입니다. 삼각형 스트립을 만들기 위해
방향과 직각에 수직인 법선을 만들어
변경할 수 있습니다.
각 획의 삼각형 스트립을 계산하는 프로세스는 거의 동일합니다. 을 다음과 같이 Tilt Brush에 사용된 코드에 추가합니다.
const V_UP = new THREE.Vector3( 0, 1, 0 );
const V_FORWARD = new THREE.Vector3( 0, 0, 1 );
function computeSurfaceFrame( previousRight, moveVector, orientation ){
const pointerF = V_FORWARD.clone().applyQuaternion( orientation );
const pointerU = V_UP.clone().applyQuaternion( orientation );
const crossF = pointerF.clone().cross( moveVector );
const crossU = pointerU.clone().cross( moveVector );
const right1 = inDirectionOf( previousRight, crossF );
const right2 = inDirectionOf( previousRight, crossU );
right2.multiplyScalar( Math.abs( pointerF.dot( moveVector ) ) );
const newRight = ( right1.clone().add( right2 ) ).normalize();
const normal = moveVector.clone().cross( newRight );
return { newRight, normal };
}
function inDirectionOf( desired, v ){
return v.dot( desired ) >= 0 ? v.clone() : v.clone().multiplyScalar(-1);
}
획 방향과 방향을 자체적으로 결합하면 수학적으로 모호한 결과 여러 개의 표준이 파생되고 종종 나타냅니다.
획의 지점을 반복할 때 '선호 권리'가 유지됩니다.
벡터를 생성하고 computeSurfaceFrame()
함수에 전달합니다. 이 함수
주어진 공식을 기반으로 쿼드 스트립에서 쿼드를 도출할 수 있는 법칙을 제공합니다.
획의 방향 (마지막 지점에서 현재 지점까지) 및
컨트롤러의 방향 (양수)입니다. 더 중요한 것은
새로운 '선호 권리' 벡터를 생성합니다.
각 획의 제어점을 기반으로 쿼드를 생성한 후 쿼드를 만들 수 있습니다.
function fuseQuads( lastVerts, nextVerts) {
const vTopPos = lastVerts[1].clone().add( nextVerts[0] ).multiplyScalar( 0.5
);
const vBottomPos = lastVerts[5].clone().add( nextVerts[2] ).multiplyScalar(
0.5 );
lastVerts[1].copy( vTopPos );
lastVerts[4].copy( vTopPos );
lastVerts[5].copy( vBottomPos );
nextVerts[0].copy( vTopPos );
nextVerts[2].copy( vBottomPos );
nextVerts[3].copy( vBottomPos );
}
또한 각 쿼드에는 다음 단계로 생성되는 UV가 포함됩니다. 일부 브러시 다양한 획 패턴을 포함하여 모든 획이 마치 페인트 붓을 칠한 듯한 느낌이 들었습니다. 이 작업은 _텍스처 아틀래싱: _각 브러시 텍스처에 가능한 모든 있습니다. 피사체의 UV 값을 수정하여 올바른 텍스처를 선택합니다. 합니다.
function updateUVsForSegment( quadVerts, quadUVs, quadLengths, useAtlas,
atlasIndex ) {
let fYStart = 0.0;
let fYEnd = 1.0;
if( useAtlas ){
const fYWidth = 1.0 / TEXTURES_IN_ATLAS;
fYStart = fYWidth * atlasIndex;
fYEnd = fYWidth * (atlasIndex + 1.0);
}
//get length of current segment
const totalLength = quadLengths.reduce( function( total, length ){
return total + length;
}, 0 );
//then, run back through the last segment and update our UVs
let currentLength = 0.0;
quadUVs.forEach( function( uvs, index ){
const segmentLength = quadLengths[ index ];
const fXStart = currentLength / totalLength;
const fXEnd = ( currentLength + segmentLength ) / totalLength;
currentLength += segmentLength;
uvs[ 0 ].set( fXStart, fYStart );
uvs[ 1 ].set( fXEnd, fYStart );
uvs[ 2 ].set( fXStart, fYEnd );
uvs[ 3 ].set( fXStart, fYEnd );
uvs[ 4 ].set( fXEnd, fYStart );
uvs[ 5 ].set( fXEnd, fYEnd );
});
}
각 스케치에는 획 수가 제한되지 않으며 획을 전부 그릴 필요는 없습니다. 획 도형을 미리 계산하고 하나의 단일 메시로 구성할 수 있습니다 새로운 브러시 유형은 각각 자체 브러시 유형이어야 하지만 머티리얼을 사용합니다. 이 경우에도 그리기 호출이 브러시당 하나로 줄어듭니다.
<ph type="x-smartling-placeholder">시스템에 스트레스 테스트를 하기 위해, 우리는 스케치를 만들어 20분 만에 가능한 한 많은 꼭짓점과 공간을 만듭니다. 그 결과 만들어진 스케치는 WebGL의 경우 60fps
획의 각 원래 꼭짓점에는 시간도 포함되어 있기 때문에 데이터를 쉽게 재생할 수 있습니다 프레임당 획을 다시 계산하는 것은 대신 로드 시 전체 스케치를 미리 계산하여 그렇게 할 때가 되었습니다.
쿼드를 숨기는 것은 꼭짓점을 0,0,0 점으로 축소하는 것을 의미합니다. 이 쿼드가 표시되어야 하는 시점에 도달하면 꼭짓점을 제자리에 다시 배치합니다.
개선이 필요한 부분은 셰이더. 현재 구현은 꼭짓점을 순환하여 배치합니다. 현재 타임스탬프로부터의 배열, 표시해야 하는 꼭짓점 확인 도형을 업데이트합니다. 이로 인해 CPU에 많은 부하가 가중되고 선풍기가 돌아가게 되어 배터리 수명을 낭비하게 됩니다.
아티스트 녹음
스케치만으로는 충분하지 않다고 생각했습니다. 이 프로젝트에서는 붓자국을 칠 때마다 그림을 그립니다.
아티스트를 촬영하기 위해 Microsoft Kinect 카메라를 사용하여 아티스트들의 있습니다. 이를 통해 입체 도형이 있어야 합니다.
예술가의 몸이 자신을 가리지 않기 때문에 그 뒤에는 방의 양쪽에 Kinect 이중 시스템을 사용했습니다. 가운데를 가리키세요.
깊이 정보 외에도, 빛의 색 정보를 생생하게 느낄 수 있습니다. 우리는 뛰어난 보정 및 병합을 위한 DepthKit 소프트웨어 심도 카메라와 컬러 카메라의 영상입니다. Kinect는 DSLR을 사용하기로 했습니다. 노출을 설정하고, 아름다운 고급 렌즈를 사용하고, 고화질로 녹화할 수 있습니다.
영상을 녹화하기 위해 YouTube는 아티스트 HTC Vive를 보관할 수 있는 카메라입니다. 모든 표면이 적외선을 흡수하는 소재로 덮여 있었음 깨끗한 점 구름 (벽면의 이불, 골이 덧댄 고무줄)을 바닥재 매트). 포인트 클라우드에 자료가 표시된 경우 동영상을 만들 때처럼 산만하지 않도록 검정색을 흰색이었습니다.
그 결과로 녹화된 동영상을 통해 입자를 투영하기에 충분한 정보를 얻을 수 있었습니다. 있습니다. 이 과정에서 다룬 몇 가지 추가 도구는 openFrameworks를 사용해 영상을 더욱 정돈하는 특히 바닥, 벽, 천장을 제거합니다.
<ph type="x-smartling-placeholder">아티스트를 보여주는 것 외에도 HMD와 사용할 수 있게 되었습니다. 이것은 HMD를 로컬 컴퓨터에 표시하는 것뿐만 아니라 최종 결과물을 명확하게 보여야 합니다 (HTC Vive의 반사 렌즈가 Kinect의 IR 측정) 입자를 디버깅할 수 있는 접점을 제공했습니다. 스케치에 맞춰 동영상을 정리합니다.
<ph type="x-smartling-placeholder">이는 텍스트를 추출하는 맞춤 플러그인을 Tilt Brush로 작성하여 각 프레임의 HMD 및 컨트롤러의 위치를 나타냅니다. Tilt Brush는 90fps로 실행되므로 대량의 데이터가 스트리밍되고 스케치의 입력 데이터는 20MB가 넘었습니다. 압축되지 않습니다. 또한 이 기법을 사용하여 기록되지 않은 이벤트를 캡처했습니다. 아티스트가 옵션을 선택하는 경우 등 일반적인 Tilt Brush 저장 파일에서 도구 패널과 미러 위젯의 위치가 표시됩니다.
캡처한 4TB의 데이터를 처리하는 과정에서 가장 큰 과제 중 하나는 정렬해야 합니다. DSLR 카메라의 모든 동영상 Kinect를 사용하여 Kinect로 정렬해야 하므로 시공간이기도 합니다. 그런 다음 이 두 카메라 장비의 영상은 한 명의 아티스트를 이루기 위해 협력합니다. 그런 다음에는 각 위치의 3D를 데이터를 수집하고 관리합니다. 다양한 혜택이 마음에 드셨나요? 브라우저 기반 직접 사용해 볼 수 있습니다. 여기
데이터가 정렬되면 NodeJS로 작성된 몇 가지 스크립트를 사용하여 데이터를 처리했습니다. 모두 잘라낸 후 동영상 파일과 일련의 JSON 파일을 출력합니다. 있습니다. 파일 크기를 줄이기 위해 세 가지 작업을 했습니다. 첫째, 최대 3이 되도록 각 부동 소수점 수의 정확도 십진수로 표현할 수 있습니다. 둘째, 포인트 수를 3분의 1만큼 줄여 30fps, 클라이언트 측 위치를 보간했습니다. 마지막으로 키-값 쌍이 있는 일반 JSON을 사용하는 대신 값의 순서가 HMD와 컨트롤러의 위치와 회전을 위해 생성됩니다. 파일이 잘렸습니다 유선으로 전송할 수 있을 정도로 크기를 3MB로 줄였습니다.
동영상 자체는 WebGL 질감이 입자가 되려면 동영상 자체가 있습니다. 셰이더는 깊이 이미지의 색상을 3D 공간 제임스 조지가 전하는 좋은 사례 몇 가지 방법을 알아보겠습니다.
iOS는 인라인 동영상 재생에 대한 제한이 있는데, 이는 사용자가 자동 재생되는 웹 동영상 광고에 성가시지 않도록 하세요. 우리는 사이트의 다른 해결 방법과 웹인 캔버스에 옮기고 동영상 탐색 시간을 1초마다
videoElement.addEventListener( 'timeupdate', function(){
videoCanvas.paintFrame( videoElement );
});
function loopCanvas(){
if( videoElement.readyState === videoElement.HAVE\_ENOUGH\_DATA ){
const time = Date.now();
const elapsed = ( time - lastTime ) / 1000;
if( videoState.playing && elapsed >= ( 1 / 30 ) ){
videoElement.currentTime = videoElement.currentTime + elapsed;
lastTime = time;
}
}
}
frameLoop.add( loopCanvas );
우리의 접근 방식에는 iOS의 Android 기기 사용자 수가 픽셀 버퍼를 동영상에서 캔버스로 복사하는 것은 매우 간단하기 때문에 CPU 집약적입니다. 이 문제를 해결하기 위해 iPhone 6에서 최소 30fps를 허용하는 동일한 동영상이 필요합니다.
결론
2016년 현재 VR 소프트웨어 개발에 대한 일반적인 합의는 기하학 및 셰이더가 간단하므로 HMD에서 90+fps로 실행할 수 있습니다. 이 실제로 WebGL 데모의 타겟이 되었음이 밝혀졌습니다. WebGL에 아주 잘 연동됩니다.
웹 브라우저가 복잡한 3D 메시를 표시하는 것은 가상 현실 작업과 가상 현실의 교차 수분이라는 개념 증명이 완전히 가능합니다.