'pv3d'에 해당하는 글 2건

스케칭이된 표면을 만들기 까지는 성공했으나..

가장 큰 숙제로 남아 있던 문제가 표면의 각도에 따라 해칭이 이루어지지 않아서 동적인 화면에 스케치 쉐이더필터를 적용했을때 화면에 스크레치가 생긴듯한 현상을 일으키는 문제였다.

이를 해결하기 위한 방법으로 각 표면의 각도에 맞게 텍스쳐를 회전시키는 것을 생각해봤지만.. 그 표면의 각도를 알기 위해선 표면의 법선 벡터 (Normal Vector)를 알아야 한다. 그 정보는 Rasterize 되기전의 정보이므로 Fragment Shader에서나 가능한 내용이다. 결국 PV3D 에서 출력해낸 2D 이미지에 Pixel Bender를 적용해야하므로 한계가 있다는 말이다.

그래서 짱구를 굴리고 굴려서 생각해낸 방법이...

생상정보 RGBA 중에서 A는 Light에 관한 정보를 담고, RGB에 Normal Vector를 담는 방법이겠다. 즉 R에는 Normal Vector의 x 값을, G에는 y값을, B에는 z값을 넣어 Pixel Bender에서 각 픽셀에서의 법선 정보를 알 수 있게끔 하고, 음영정보는 A에 담긴 정보를 사용한다는 뜻!

그러나 그런 방법은 있지만 PV3D에는 그렇게 렌더링 할 수 있는 방법이 없다.. 그런 이유로 Pixel Bender에 불탔던 열정이 잠시 식었었으나! 방법을 찾았다.

AbstractSmoothShadeMaterial 클래스를 상속받은 Custom Material을 만들면 되는것. 어렵지 않을까해서 EnvMapMaterial 이나 CellMaterial을 열어봤지만 크게 복잡한건 없는것 같다. 둘다 AbstractSmoothShadeMaterial의 서브클래스. 물론 EnvMapMaterial은 수식 자체가 뭘 하겠다는건지 알아먹을 수 없었으나 Custom Material을 만드는데에 문제가 있어보이지는 않는다.

 package org.papervision3d.materials.shadematerials

{

import fl.motion.Color;

import flash.display.BitmapData;

import flash.display.Graphics;

import flash.geom.Matrix;

import org.papervision3d.cameras.Camera3D;

import org.papervision3d.core.math.Number3D;

import org.papervision3d.core.proto.CameraObject3D;

import org.papervision3d.core.geom.renderables.Triangle3D;

import org.papervision3d.core.geom.renderables.Vertex3DInstance;

import org.papervision3d.core.material.AbstractSmoothShadeMaterial;

import org.papervision3d.core.math.Matrix3D;

import org.papervision3d.core.proto.LightObject3D;

import org.papervision3d.core.render.data.RenderSessionData;

import org.papervision3d.core.render.draw.ITriangleDrawer;

/**

* @Author Buzzler

*/

public class NormalMaterial extends AbstractSmoothShadeMaterial implements ITriangleDrawer

{

private static var x1:Number;

private static var x0:Number;

private static var x2:Number;

private static var y0:Number;

private static var y1:Number;

private static var y2:Number;

private var camera:CameraObject3D;

private var tmpN:Number3D;

private var tmpL:Number3D;

private var tmpR:uint;

private var tmpG:uint;

private var tmpB:uint;

private var tmpRGB:uint;

public function NormalMaterial(light:LightObject3D, camera:CameraObject3D)

{

super();

this.light = light;

this.camera = camera;

}

private static var useMap:BitmapData;

override public function drawTriangle(face3D:Triangle3D, graphics:Graphics, renderSessionData:RenderSessionData, altBitmap:BitmapData = null, altUV:Matrix = null):void

{

x0 = face3D.v0.vertex3DInstance.x;

   y0 = face3D.v0.vertex3DInstance.y;

x1 = face3D.v1.vertex3DInstance.x;

y1 = face3D.v1.vertex3DInstance.y;

x2 = face3D.v2.vertex3DInstance.x;

y2 = face3D.v2.vertex3DInstance.y;

triMatrix.a = x1 - x0;

triMatrix.b = y1 - y0;

triMatrix.c = x2 - x0;

triMatrix.d = y2 - y0;

triMatrix.tx = x0;

triMatrix.ty = y0;


tmpN = face3D.faceNormal.clone();

tmpL = new Number3D(-light.x,-light.y,-light.z);

tmpR = uint((tmpN.x + 1.0) * 127.5);

tmpG = uint((tmpN.y + 1.0) * 127.5);

tmpB = uint((tmpN.z + 1.0) * 127.5);

tmpRGB = (tmpR << 16) | (tmpG << 8) | (tmpB);

graphics.beginFill(tmpRGB, brightness(tmpN, tmpL));

   graphics.moveTo( x0, y0 );

graphics.lineTo( x1, y1 );

graphics.lineTo( x2, y2 );

graphics.lineTo( x0, y0 );

graphics.endFill();

renderSessionData.renderStatistics.shadedTriangles++;

}

private function brightness(n1:Number3D, n2:Number3D):Number

{

n1.normalize();

n2.normalize();

var result:Number = Math.acos(Number3D.dot(n1, n2)) - Math.PI / 2;

result = Math.max(result, 0) / (Math.PI / 2);

return 1 - result;

}

}

}

 

이게 NormalMaterial 이라는 직접 만든 재질을 입혀 많은 구(Sphere)이다.
알파값으로 Light와의 관계를 알 수 있고, 색상으로 면의 방향을 나타내는 법선 벡터를 알 수 있다.

자.. 숙제가 또 남았다. Face3D 단위가 아닌 Vertex 단위로 Color Interpolation이 필요해 보인다. 그래야 더욱 자연스러운 법선 백터가 생성되지 않을까. 안그럼 엄청나게 폴리곤이 많은 모델이어야 자여스럽게 보이는 상황이 발생 할 테니. 어쨌거나 당장 필요한 수준의 Material을 만들었으니 일단 만족.

추가: 3포인트 그래디언트를 만들어주는 픽셀벤더 필터가 있으니 도움이 되지 않을까

'Pixel Bender' 카테고리의 다른 글

PixelBender Outline View  (0) 2008.11.05
Flex와 Pixel Bender로 iChat 흉내내기  (0) 2008.09.25
Human Detector!  (2) 2008.09.25
Sketch Shader  (0) 2008.09.18
Sobel Operation 의 간단한 응용  (0) 2008.09.18

WRITTEN BY
buzzler

,

Sketch Shader

Pixel Bender 2008. 9. 18. 18:53
원본 이미지를 스케치한 이미지로 필터링해주는 것.
텍스쳐소스의 x,y 좌표는 원본 이미지의 좌표 그대로 사용하되,
원본 픽셀의 음영값으로 텍스쳐를 바꿈으로써 합성된 결과물이 나온다.
그리고 두가지 톤의 텍스쳐 중간값을 가지는 음영은 두개의 텍스쳐를 비율만큼 합성한다.

texture image

pixel bender 에서는 input 이미지와 output 픽셀 이외에 또다른 input 을 받을 수 있다.

앞서 만들었던 Sobel Operation과 함께 사용하면 외곽선이 들어간 스케치 화면을 얻을 수 있을것으로 기대하고 만들었지만 난항중.
그리고 정지된 영상이나 2차원 이미지에는 꽤 좋은 효과를 가지고 있지만
3차원 영상에서는 움직이지 않고 고정된 텍스쳐 때문에
마치 기스난 유리막이 덮여있는 것으로 보인다.
이러한 문제는 normal vector 정보를 텍스쳐의 기울임에 적용함으로써 해결할 예정이다.
normal vector 정보를 RGB값에 저장하고 음영값을 A에 저장하면 pixel bender 에서 응용할 수 있을것.
아래는 3D에 응용예제.

'Pixel Bender' 카테고리의 다른 글

PixelBender Outline View  (0) 2008.11.05
Scketch Shader를 위한 PV3D 튜닝  (0) 2008.10.07
Flex와 Pixel Bender로 iChat 흉내내기  (0) 2008.09.25
Human Detector!  (2) 2008.09.25
Sobel Operation 의 간단한 응용  (0) 2008.09.18

WRITTEN BY
buzzler

,