Flash/Away3D

얼사마 2011. 4. 12. 12:48

ambient ambientColor


 

 

위 그림은 04. 라이팅(Lighting)의 결과물이다.

직접적으로 Light 오브젝트를 두 개 생성하여,

주광과 보조광으로 이용하여 나타낸 모습이다.

 

모든 Material에는 ambient ambientColor 속성이 있다.

ambient는 환경광의 영향을 받는 세기이며,

ambientColor는 환경광의 색상이다.

 

이전의 결과물에서 주광만 놓아두고, 렌더링을 해보자.



 

빛의 반대 방향은 완전히 검은 색으로 나타난다.

보조광이 없을 뿐더러, 환경광 속성도 설정하지 않았기 때문이다.

 

이제 보조광을 위한 라이트 오브젝트를 추가로 생성하지 않고, 환경광 설정을 통해 적절한 이미지가 되도록 해보겠다.

 

WireFrameMaterial을 제외한 모든 Material DefaultMaterialBase를 상속 받는다.

따라서 DefaultMaterialBase.ambient DefaultMaterialBase.ambientColor를 사용할 수 있다.

 

floorMaterial.ambient = 0.3;

floorMaterial.ambientColor = 0xffffff;

 

위와 같이 모든 Material ambient ambientColor 값을 셋팅하고 렌더링을 하면 아래와 비슷한 결과물을 얻을 수 있다.

 

모든 물체가, 모든 방향에서 동일한 세기의 환경광의 영향을 받아서, 주광이 비치는 방향이 아닌 곳도

적절한 빛의 영향을 받게 됐다.

 

 

Shadow

Away3D 4.0에서는 3가지 타입의 그림자 생성 클래스를 제공한다.

  1. HardShadowMapMethod
  2. SoftShadowMapMethod
  3. SlowFilteredShadowMapMethod

 

  HardShadowMapMethod

경계면이 날카로운 그림자를 생성한다.

 

Class 정의

away3d.materials.methods.HardShadowMapMethod.HardShadowMapMethod(castingLight:LightBase)

 

  • 파라미터 설명
    • castingLight : 그림자를 생성시킬 광원

 

예제 코드

var floorMaterial:BitmapMaterial = new BitmapMaterial(this._imageGround.bitmapData, true, false, true);

floorMaterial.lights = [leftLight];

floorMaterial.shadowMethod = new HardShadowMapMethod(leftLight);  // 그림자 생성 방법

floorMaterial.ambient = 0.3;  // 환경광 세기

floorMaterial.ambientColor = 0xffffff;  // 환경광 색상

 

var floor:Plane = new Plane(floorMaterial, 1500, 1500, 1, 1, false);

this._scene.addChild(floor);

결과물


바닥 역할을 하고 있는 Plane Material, 이제 그림자를 표현하게 된다.

위 스크린샷의 그림자 부분을 보면, 그림자의 경계면이 매우 날카로운 것을 볼 수 있다.

 

 SoftShadowMapMethod

경계면이 부드러운 그림자를 생성한다.

SoftShadow는 기본적으로 HardShadow(RayTracing)과 같은 방법이나,

주광원을 여러 방향으로 움직여서 생긴 여러개의 HardShadow를 합친 것이다.

 

Class 정의

away3d.materials.methods.SoftShadowMapMethod.SoftShadowMapMethod(castingLight:LightBase, stepSize:Number=.00025)

 

  • 파라미터 설명
    • castingLight : 그림자를 생성시킬 광원
    • stepSize : 확산 정도, 주광원의 흔들림 정도. 기본값 0.00025

 

예제 코드

var floorMaterial:BitmapMaterial = new BitmapMaterial(this._imageGround.bitmapData, true, false, true);

floorMaterial.lights = [leftLight];

floorMaterial.shadowMethod = new SoftShadowMapMethod(leftLight,0.00025);  // 그림자 생성 방법

floorMaterial.ambient = 0.3;  // 환경광 세기

floorMaterial.ambientColor = 0xffffff;  // 환경광 색상

 

var floor:Plane = new Plane(floorMaterial, 1500, 1500, 1, 1, false);

this._scene.addChild(floor);

결과물


그림자의 경계면이 부드럽게 처리되었다.

 

stepSize를 크게 하면, 아래와 같이 주광원을 움직여서 여러개의 HardShadow가 만들어진 것을 볼 수 있다.


 

 SlowFilteredShadowMapMethod

SoftShadow와 비슷한, 경계면이 부드러운 그림자를 생성한다.

 

아직 Document나 주석이 완벽치 않아, 정확한 설명은 어려우나, Class명으로 유추해 볼 수 있는 부분은,
HardShadow에 Filter를 적용하여 부드러운 그림자를 생성하는 것으로 보인다.
또한, 범용적인 ShadowMap 이름이 아니고, SoftShadow와 비슷한 역할을 하고, SoftShadow의 성격으로 볼 때,
두 가지 중 한 가지의 목적을 달성하기 위함일텐데,
첫번째는 SoftShadow와 비슷한 결과물을 내면서, 좀 더 나은 퍼포먼스를 도모하기 위한...
두번째는 SoftShadow보다 더 높은 퀄러티를 도모하기 위한 Class가 아닐까 짐작해 본다.
개인적인 바램(?)으로는 전자였으면 하는...

 

Class 정의

away3d.materials.methods.SlowFilteredShadowMapMethod.SlowFilteredShadowMapMethod(castingLight:LightBase)

 

  • 파라미터 설명
    • castingLight : 그림자를 생성시킬 광원


예제 코드

var floorMaterial:BitmapMaterial = new BitmapMaterial(this._imageGround.bitmapData, true, false, true);

floorMaterial.lights = [leftLight];

floorMaterial.shadowMethod = new SlowFilteredShadowMapMethod(leftLight);  // 그림자 생성 방법

floorMaterial.ambient = 0.3;  // 환경광 세기

floorMaterial.ambientColor = 0xffffff;  // 환경광 색상

 

var floor:Plane = new Plane(floorMaterial, 1500, 1500, 1, 1, false);

this._scene.addChild(floor);

결과물

 

 

좌측이 SlowFilteredShadowMapMethod, 우측이 SoftShadowMapMethod를 적용한 결과물이다.

 

 

모든 오브젝트에 shadowMap 적용

Plane에만 shadowMap을 적용하였기 때문에, Plane에만 그림자가 보인다.

서로 인접해 있는 오브젝트 간에도 그림자가 생겨야 사실적으로 보일 것이다.

따라서, 모든 오브젝트의 Material shadowMap을 적용 시키면 아래와 같은 결과물을 얻을 수 있다.



 

 

본 강좌 첫 부분에서 ambient ambientColor부터 설명해 온 결과라서 이런 결과물이지만,

만약 이 환경광을 설정하지 않으면 아래와 같이 된다.


주광원이 비추지 않고, 그림자가 지는 부분은 완전히 검은 색이 된다.

 

 
 
 

Flash/Away3D

얼사마 2011. 4. 12. 12:34

두 개 이상의 오브젝트를 하나의 그룹으로 묶기

private var _container:ObjectContainer3D;

private function loadObject():void

{

       // 중간 생략

       var box:Cube = new Cube(boxMaterial, 100,200,300);  // Cube 생성

       var sphere:Sphere = new Sphere(sphereMaterial, 100, 16, 12);  // Sphere 생성

       var container = new ObjectContainer3D();  // Container 생성

       container.addChild(box);  // Container Cube 추가

       container.addChild(sphere);  // Container Shpere 추가

       container.y = 200;  // Container 이동

       this._scene.addChild(container);  // Scene Container 추가

}

위와 같이 ObjectContainer3D에 오브젝트를 추가하게 되면,

해당 오브젝트들은 컨테이너에 종속적이게 된다.

 

Sprite Sprite를 추가(addChild)하는 것과 같이,

ObjectContainer3D ObjectContainer3D를 추가(addChild)할 수도 있다.

 

하위 오브젝트들은 상위 컨테이너에 종속적이기 때문에,

상위 컨테이너의 속성이 변경되면, 하위 오브젝트들 역시 같이 변경되게 된다.

예를 들어, x,y,z의 공간 이동이나, ratationX/Y/Z 또는 scaleX/Y/Z 등의 변경 역시 마찬가지이다.

 

 
 
 

Flash/Away3D

얼사마 2011. 4. 11. 18:19

키보드 입력 인터랙션

private var _moveObject:Object3D;

 

public function TestAway3D()

{

       // 중간 생략

      

       this.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);

}

 

private function keyDown(e:KeyboardEvent):void

{

       // 키보드 입력을 받아, XZ 평면상으로 움직이게 한다.

       switch(e.keyCode){

             case Keyboard.LEFT:

                    this._moveObject.x -= 5;

                    break;

             case Keyboard.RIGHT:

                    this._moveObject.x += 5;

                    break;

             case Keyboard.UP:

                    this._moveObject.z += 5;

                    break;

             case Keyboard.DOWN:

                    this._moveObject.z -= 5;

                    break;

       }

}

private function loadObject():void

{

       // 중간 생략

       // 키보드로 움직일 대상을 지정한다.

       this._moveObject = sphere as Object3D;

}


이전까지의 예제에서 위와 같이 코드를 추가하면,

Sphere가 방향키에 따라서, xz 평면을 따라 이동하는 모습을 볼 수 있다.

 

 

마우스 입력 인터랙션

private var _moveObject:Object3D;

private var _mouseDrag:Drag3D;

public function TestAway3D()

{

       // 중간 생략

       this.initDrag();

}

private function initDrag():void

{

       // Drag3D 사용할, View 설정

       this._mouseDrag = new Drag3D(this._view);

}

private function mouseDown(e:MouseEvent3D):void

{

       // MOUSE_DOWN 이벤트를 발생시킨 오브젝트 저장

       this._moveObject = e.target as Object3D;

       // 드래그 대상으로 지정

       this._mouseDrag.object3d = ObjectContainer3D(this._moveObject);

}

 

private function mouseUp(e:MouseEvent3D):void

{

       // 움직일 대상 삭제

       this._moveObject = null;

}

private function loadObject():void

{

       // 중간 생략

      

       // 아래와 같이, 마우스를 통해 움직일 대상의 mouseEnabled 속성과, 이벤트 리스너를 등록한다.

       box.mouseEnabled = true;

       box.addEventListener(MouseEvent3D.MOUSE_DOWN, mouseDown);

       box.addEventListener(MouseEvent3D.MOUSE_UP, mouseUp);

      

       sphere.mouseEnabled = true;

       sphere.addEventListener(MouseEvent3D.MOUSE_DOWN, mouseDown);

       sphere.addEventListener(MouseEvent3D.MOUSE_UP, mouseUp);

}

private function render(e:Event):void

{

       // 움직일 대상이 있는 경우, Drag3D 업데이트

       if (this._moveObject){

             this._mouseDrag.updateDrag();

       }

       this._view.render();

}


box, sphere 외에도, 이벤트 리스너를 등록한 대상은 모두 마우스로 드래그가 가능한 모습을 볼 수 있다.

 

 

카메라가 움직이는 객체 따라다니도록 하기

private function render(e:Event):void

{

       if (this._moveObject){

             this._camera.x = this._moveObject.x + 500;

             this._camera.y = this._moveObject.y + 500;

             this._camera.z = this._moveObject.z - 500;

       }

       this._view.render();

}


움직이는 객체(_moveObject)가 지정이 됐다면,

해당 객체를 카메라가 항상 일정한 거리에서 대각선 아래로 바라보면서 같이 움직이게 된다.

 


키보드, 마우스 이벤트와, 3D 공간상의 드래그 정도면, 일단 기본적인 부분은 다 다룬 셈이라, 더 복잡한 케이스를 다루진 않았다.


좋은 글이네요. ㅋㅋ