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

http://blog.joa-ebert.com/2008/10/08/pixelbender-outline-view/

'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
Sketch Shader  (0) 2008.09.18
Sobel Operation 의 간단한 응용  (0) 2008.09.18

WRITTEN BY
buzzler

트랙백  0 , 댓글  0개가 달렸습니다.
secret
스케칭이된 표면을 만들기 까지는 성공했으나..

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

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

트랙백  0 , 댓글  0개가 달렸습니다.
secret
어제 포스팅했던 Human Detector에 관한 구현이다.
입력소스는 한가지. 컴에 연결된 웹캠을 이용해서 배경을 뽑아내고
이후에 사람을 찾는다.

1. 배경을 설정한다. 사람이 있다면 옆으로 빠진다.

2. 이제 사람이 들어온다.

3. 이미지와 영상을 XOR 한다. 동시에 빈공간을 다른 배경을 섞어주면 센스 만점

4. 움직여도 보고.

잠깐 테스트한 결과 일단 90% 만족스러운데..
노이즈 없이 뽑아내는것만 좀 어떻게 된다면 활용해볼 가치가 더 올라가지 않을까.
숙제.
이 플래시 파일을 브라우져에서 보기 위해선 Flash Player 10 버전 또는 그 이상의 버전이 설치되어 있어야 함.

'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
Sketch Shader  (0) 2008.09.18
Sobel Operation 의 간단한 응용  (0) 2008.09.18

WRITTEN BY
buzzler

트랙백  0 , 댓글  0개가 달렸습니다.
secret

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
Human Detector!  (2) 2008.09.25
Sketch Shader  (0) 2008.09.18
Sobel Operation 의 간단한 응용  (0) 2008.09.18

WRITTEN BY
buzzler

트랙백  0 , 댓글  2개가 달렸습니다.
  1. 김해정 2010.08.01 01:40
    안녕하세요~~
    플래시에서 배경합성에 대해서 알아보다가 검색을 통해
    건너 건너 여기까지 왔습니다.
    픽셀벤더는 사용해본적이 없어서, 이글 보고 다른 글 보면서
    해보고있는데요.
    위 소스를 가지고 pbj만들어서 플래시에서 임포트까지는 했는데
    적용을 못하겠어요.
    위 소스는 파라미터가 없어서 플래시에서 변수로 어떻게
    지정해야 될지도 모르겠고요...ㅜㅜ
    혹시 방법이 없나요~??쩝..
    아님 위 소스중
    input image4 bg;
    input image4 mix;
    둘중에 하나를 매개변수로 만들어서 사용할수는 없나요~???
    넘 궁금하네요..ㅜㅜ
    • 만든지 너무 오래돼서 기억이 안나네요 : )
      배경합성은 어떤 소스로 하실지에따라 달라질 이야기긴 합니다만..
      ShaderInput 도 하나의 매개변수 입니다.
      ShaderParameter는 필수값이 아니구요. ShaderInput은 필수 매개변수라고 보시면 되겠네요.
      합성을 하려면 반드시 두개의 이미지가 필요하니까요.
      Shader 클래스를 다루는 사용법을 찾아보심이 좋겠네요 ^~^
      전 다 까먹었어요. 다시 보려면 시간 좀 걸릴듯 ㅎㅎ
secret

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
Sketch Shader  (0) 2008.09.18
Sobel Operation 의 간단한 응용  (0) 2008.09.18

WRITTEN BY
buzzler

트랙백  0 , 댓글  0개가 달렸습니다.
secret
2차원 기반의 외곽선 검출 방법을 찾던중 Sobel Operation에 대해서 알게되었다.
이 연산을 통해서 외곽선의 방향과 강도 따위를 결정할 수 있다.

그리고 Sobel Operation을 통해서 검출된 외곽선과 원본 이미지를 합성하여 보았다.
단지 그것뿐.

PIxel Bender Language는 함수도 가능하고 기타 다른 내장 함수도 사용할 수 있지만
Flash Player 10 용으로 사용할 때에는 제약상 evaluatePixel 함수만 사용하기 때문에
코드가 살짝 길어졌다. 또한 내장 함수는 아직 무엇이 있는지 잘 몰라서 행렬연산을
직접 하나씩 풀어내었더니 더 길어진듯.
어쨌거나 잘 동작한다. 코드는 다음과 같고

 <languageVersion : 1.0;>


kernel SobelFilter

<   namespace : "buzzler";

    vendor : "Mobsword Systems";

    version : 1;

    description : "Sobel Operation";

>

{

    input   image4  src;

    output  pixel4  dst;

    const   pixel4  black   = pixel4(0.0, 0.0, 0.0, 1.0);

    const   float   low     = 1.0;

    const   float   high    = 2.0;

    const   float   p_width = 1.0;


    void    evaluatePixel()

    {

        float   g, gx, gy;

        float2  coord = outCoord();

        pixel4  sampled;

        float   tone;

        

        sampled = sampleLinear(src, float2(coord[0]-p_width , coord[1]-p_width));

        tone = (sampled.r + sampled.g + sampled.b) / 3.0;

        gx += low * tone;

        gy += low * tone;

        

        sampled = sampleLinear(src, float2(coord[0] , coord[1]-p_width));

        tone = (sampled.r + sampled.g + sampled.b) / 3.0;

        gy += high * tone;

        

        sampled = sampleLinear(src, float2(coord[0]+p_width , coord[1]-p_width));

        tone = (sampled.r + sampled.g + sampled.b) / 3.0;

        gx -= low * tone;

        gy += low * tone;

        

        sampled = sampleLinear(src, float2(coord[0]-p_width , coord[1]));

        tone = (sampled.r + sampled.g + sampled.b) / 3.0;

        gx += high * tone;

        

        sampled = sampleLinear(src, float2(coord[0]+p_width , coord[1]));

        tone = (sampled.r + sampled.g + sampled.b) / 3.0;

        gx -= high * tone;

        

        sampled = sampleLinear(src, float2(coord[0]-p_width , coord[1]+p_width));

        tone = (sampled.r + sampled.g + sampled.b) / 3.0;

        gx += low * tone;

        gy -= low * tone;

        

        sampled = sampleLinear(src, float2(coord[0] , coord[1]+p_width));

        tone = (sampled.r + sampled.g + sampled.b) / 3.0;

        gy -= high * tone;

        

        sampled = sampleLinear(src, float2(coord[0]+p_width , coord[1]+p_width));

        tone = (sampled.r + sampled.g + sampled.b) / 3.0;

        gx -= low * tone;

        gy -= low * tone;

        

        g = sqrt(pow(gx, 2.0) + pow(gy, 2.0));

        dst = mix(sampled, black, g);

    }

}



출력된 이미지

출력된 이미지

입력된 이미지

입력된 이미지

'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
Sketch Shader  (0) 2008.09.18
Sobel Operation 의 간단한 응용  (0) 2008.09.18

WRITTEN BY
buzzler

트랙백  0 , 댓글  0개가 달렸습니다.
secret