'Pixel Bender'에 해당하는 글 3건

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

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

이를 해결하기 위한 방법으로 각 표면의 각도에 맞게 텍스쳐를 회전시키는 것을 생각해봤지만.. 그 표면의 각도를 알기 위해선 표면의 법선 벡터 (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

,

Human Detector!

Pixel Bender 2008. 9. 25. 00:16
레오파드를 발표하는 자리에서 iChat의 시연을 기억하는사람이 있을까.
iChat은 화상대화에 재미있는 효과(effect)를 추가할 수가 있었다.
가령...
배경을 폭포나 롤로코스터 영상으로 바꾼다던지, 아래와같이 홀로그램 스러운 효과를 넣는다던지.
이 영상을 시연하면서 초큼 웃었던 기억이 있는데 내용은 직접 보고 판단하자.

이런식의 효과.

간단한 원리다. 배경을 먼저 찍고 그 이후의 영상에서 배경과 중복되지 않는 부분을 사람이나 기타 다른 움직이는 물체라고 판별하는것.
사실 실제로 그렇게 구현한 것인지는 알 수 없지만 내가 생각하는 가장 간단한 방법은 그거다.
pixel bender로서 플래시에서도 충분히 가능하다. 물론 pixel bender가 아니었어도 가능했지만 gpu로 좀더 원활한 효과가 가능한 것이다.
똑같은 원리로 pixel bender에서 구현해봤다.
참고로 pixel bender에서 플래시용 바이너리로 export하기 위해서는 입력 이미지가 두개여야 하는 등의 제약이 따른다는것을 잊지말자.

이게 배경이라고 설정한 이미지.. 

그리고 사람(답게 생긴 짐승)을 추가해서..
이런 이미지를 넣고 (뻔뻔하게 보정도 없이 그냥 섞었다)

단순하게 같은 좌표의 픽셀값을 비교해서 아래의 결과물을 얻는다.
인물을 제외한 나머지 영역은 투명하기 때문에 또 다른 배경을 삽입해서 합성 할 수도 있고,
미리 저장된 배경을 다시 깔아 넣고 뽑아낸 인물 이미지만 다른 효과를 삽입할 수도 있다.
아래는 소스코드

 <languageVersion : 1.0;>


kernel HumanDetect

<   namespace : "buzzler";

    vendor : "Mobsword Systems";

    version : 1;

    description : "your description";

>

{

    input image4 bg;

    input image4 mix;

    output pixel4 dst;

    const pixel4 mask = pixel4(0.0, 0.0, 0.0, 0.0);


    void

    evaluatePixel()

    {

        float2 coord = outCoord();

        pixel4 pixel_bg = sampleNearest(bg, coord);

        pixel4 pixel_mix = sampleNearest(mix, coord);


        float r = abs(pixel_bg.r - pixel_mix.r);

        float g = abs(pixel_bg.g - pixel_mix.g);

        float b = abs(pixel_bg.b - pixel_mix.b);

        float a = abs(pixel_bg.a - pixel_mix.a);


        if ((r < 0.01)&&(g < 0.01)&&(b < 0.01)&&(a < 0.01))

            dst = mask;

        else

            dst = pixel_mix;

    }

}


 10분만에 대충 짜놓은거라 꼼꼼하게 살펴보진 말고 그냥 보자.
핵심은 굵게 해놓았다. 인물이 없는 배경과, 인물이 있는 이미지에서 각각 pixel4 데이타를 추출(sampling)하고, 두 데이타를 비료해서 큰 차이가 없다면 투명하게 만들고 차이가 좀 난다면 인물이 있는 이미지의 데이타를 출력한다는 의미.

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

PixelBender Outline View  (0) 2008.11.05
Scketch Shader를 위한 PV3D 튜닝  (0) 2008.10.07
Flex와 Pixel Bender로 iChat 흉내내기  (0) 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

,