본문 바로가기

Next WEB

웹 브라우저에서 3D게임을 하는 시대가 오는가?

이제 머지않아 웹브라우저에서도 3D게임을 할 수 있을지도 모르겠습니다.

WebGL

얼마전에 OpenGL을 담당하고 있는 Khronos consortium에서 WebGL이라는 기술을 발표했습니다.
WebGL 은 HTML5의 canvas element의 3D context에 OpegnGL ES 2.0을 자바스크립트에서 이용할 수 있도록 바인딩했기 때문에 브라우저에서 플러그인 형태로 접근하지 않아도 하드웨어 가속이 되는 3D그래픽을 이용할 수 있습니다. 

현재 Google, Mozilla, NVIDIA, Opera, AMD, Ericsson등과 같은 굵직한 회사들이 참여하고 있습니다.

http://ext3d.com/news/images/webgl.jpg

웹기술과 3D를 결합하려고 한 시도들은 예전에도 많이 있었습니다. 그중 대표적인 기술이 VRML이라는 것이었죠. 2000년대 초반에는 상당히 인기가 많았으나 여러 문제로 사라지고 말았습니다.
그리고 얼마 전에 구글이 내놓은 O3D라는 것이 있습니다. (현재 구글은 둘다 진행하고 있는데, 언젠가는 통합되겠죠.)

자바스크립트와 OpenGL ES의 결합이라...  다소 생소할 수도 있을텐데요. 아래와 같은 형태로 개발할 수 있습니다. 참고로 큐브 예제입니다.




<!DOCTYPE html>
<html>
<head>
<title>Spinning Box</title>
<script src="resources/CanvasMatrix.js"> </script>
<script src="resources/utils3d.js"> </script>
<script id="vshader" type="x-shader/x-vertex">
uniform mat4 pMatrix;
uniform mat4 mvMatrix;
uniform vec3 lightDir;

attribute vec3 vNormal;
attribute vec4 vColor;
attribute vec4 vPosition;

varying float v_Dot;

void main()
{
gl_FrontColor = vColor;
vec4 transNormal = mvMatrix * vec4(vNormal,1);
v_Dot = max(dot(transNormal.xyz, lightDir), 0.0);
gl_Position = pMatrix * mvMatrix * vPosition;
}
</script>
    <script id="fshader" type="x-shader/x-fragment">
varying float v_Dot;

void main()
{
gl_FragColor = vec4(gl_Color.xyz * v_Dot, gl_Color.a);
}
</script>

<script>
function init()
{
var gl = initWebGL("example", "vshader", "fshader",
[ "vNormal", "vColor", "vPosition"],
[ 0, 0, 0, 1 ], 10000);

gl.uniform3f(gl.getUniformLocation(gl.program, "lightDir"), 0, 0, 1);

gl.box = makeBox(gl);

// color array
var colors = new CanvasUnsignedByteArray(
[ 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, // v0-v1-v2-v3 front
1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, // v0-v3-v4-v5 right
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, // v0-v5-v6-v1 top
1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, // v1-v6-v7-v2 left
1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, // v7-v4-v3-v2 bottom
0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 ] // v4-v7-v6-v5 back
);

gl.box.colorObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, gl.box.colorObject);
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);

return gl;
}

width = -1;
height = -1;

function reshape(gl)
{
var canvas = document.getElementById('example');
if (canvas.clientWidth == width && canvas.clientHeight == height)
return;

width = canvas.clientWidth;
height = canvas.clientHeight;

gl.viewport(0, 0, width, height);
var pMatrix = new CanvasMatrix4();
pMatrix.lookat(0,0,10, 0, 0, 0, 0, 1, 0);
pMatrix.perspective(30, width/height, 1, 10000);
gl.uniformMatrix4fv(gl.getUniformLocation(gl.program, "pMatrix"), false, pMatrix.
getAsCanvasFloatArray());
}

function drawPicture(gl)
{
reshape(gl);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

var mvMatrix = new CanvasMatrix4();
mvMatrix.rotate(currentAngle, 0,1,0);
mvMatrix.rotate(20, 1,0,0);
gl.uniformMatrix4fv(gl.getUniformLocation(gl.program, "mvMatrix"), false, mvMatrix.
getAsCanvasFloatArray());

gl.enableVertexAttribArray(0);
gl.enableVertexAttribArray(1);
gl.enableVertexAttribArray(2);

gl.bindBuffer(gl.ARRAY_BUFFER, gl.box.vertexObject);
gl.vertexAttribPointer(2, 3, gl.FLOAT, false, 0, 0);

gl.bindBuffer(gl.ARRAY_BUFFER, gl.box.normalObject);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);

gl.bindBuffer(gl.ARRAY_BUFFER, gl.box.colorObject);
gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, false, 0, 0);

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.box.indexObject);
gl.drawElements(gl.TRIANGLES, gl.box.numIndices, gl.UNSIGNED_BYTE, 0);

gl.flush();

framerate.snapshot();

currentAngle += incAngle;
if (currentAngle > 360)
currentAngle -= 360;
}

function start()
{
var gl = init();
currentAngle = 0;
incAngle = 0.5;
framerate = new Framerate("framerate");
setInterval(function() { drawPicture(gl) }, 10);
}
</script>
<style type="text/css">
canvas {
border: 2px solid black;
width:90%;
height:90%;
}
.text {
position:absolute;
top:100px;
left:20px;
font-size:2em;
color: blue;
}
</style>
</head>
<body onload="start()">
<canvas id="example">
There is supposed to be an example drawing here, but it's not important.
</canvas>
    <div class="text">This is some text under the canvas</div>
<div id="framerate"></div>
</body>
</html>

향후 전망은??

제 짧은 생각으로는 일단 넘어야 할 산은 많아 보입니다.

1. 하드웨어 가속을 쓰더라도 자바스크립트 자체와 바인딩에서 속도문제가 있을 수 있습니다.
현재도 자바스크립트 엔진들은 많이 발전하였으나, OpenGL과의 바인딩에 대해서는 아직 많은 것들을 최적화해야 할것으로 보입니다.
또한 방대한 양의 3D데이타들을 어떻게 처리할지는... 많은 것들이 있겠네요.

2. 또한 3D 개발에 관련된 문제로 제가 잘은 모르지만, low level API인 OpenGL만으로 개발한다는 것을 상당히 힘든 내용으로 알고 있습니다.
그래서 여러 엔진과 툴들이 나와 있는데, WebGL을 지원하는 편리한 툴이 없다면 개발자들에게 외면당해 성공하기 힘들수도 있습니다.
웹 개발자가 3D까지 알기에는 힘들수도 있죠. 따라서 전문 개발자들이 많아지거나 상당히 편리한 툴이 개발되어야 승산이 있을 것 같습니다.
즉 기존의 웹개발자들과 3D관련 개발자들을 모두 수용할 수 있는 환경이 필요하다고 생각합니다.

3. 플래시, 실버라이트와 같은 RIA진영에서의 반격도 지켜봐야 할 것 같습니다.
아무리 좋은 기술이라도 시장에서 성공한다는 것은 많은 것들을 필요로 하죠.
요즘 공격적으로 플래시를 확대시키고 있는 Adobe는 mobile 시장뿐만 아니라 스크린이 있는 시장이라면 어디든 공략할 태세입니다.
MS는 아직까지는 크게 성공시킨것 같지는 않지만, 조용히 시장을 넓혀가고 있는 것은 사실입니다.
이와 같이 너무나도 커진 RIA진영에서는 WebGL에 적극적으로 대응한다면 조용히 사라질수도 있습니다.

하지만, 이런 문제들에도 불구하고, 브라우저 진영에서도 가만히 있지는 않겠죠.
우선 Webkit에서 WebGL을 지원하는 버전이 나왔습니다. 아쉽게도 현재는 Mac에서만 동작하네요. - -
Webkit r49073(October 4, 2009)에서 동작하며 자세한 내용은 http://webkit.org/blog/603/webgl-now-available-in-webkit-nightlies/를 참고하시길 바랍니다.

Webkit을 기반으로 하는 Google chrome, Safari등의 브라우저에서도 조만간 볼수 있겠네요.
오페라에서는 아직 소식은 없으나, 조만간에 모습을 선보일것 같습니다.
또한 Mozilla 재단에서 Firefox 3.7 개발 버전에서 WebGL을 지원한다고 합니다.

위와 같이 브라우저 진영에서도 HTML5등과 같이 발빠르게 대응하고 있습니다.

앞으로 넘어야 할 산도 많지만, 브라우저가 궁극적으로 가야할 산인것 같습니다.

시행착오는 있겠지만 꼭 WebGL이 성공해서 어디서나 와우, 리니지와 같은 게임도 할 수 있고, 플러그인 없이도 보다 편리하고 화려한 UI를 제공받을 수 있는 시대가 되었으면 하는 바램입니다.

참고

[Wikipedia] http://en.wikipedia.org/wiki/WebGL
[khronos] http://www.khronos.org/news/press/releases/khronos-webgl-initiative-hardware-accelerated-3d-graphics-internet
[O3D] http://code.google.com/intl/ko-KR/apis/o3d/
http://www.khronos.org/developers/library/2009_siggraph_bof_opengl/OpenGL-BOF-WebGL-Siggraph-Aug09.pdf
http://webkit.org/blog/603/webgl-now-available-in-webkit-nightlies/


반응형