Graphics Programming
픽셀 벤더 개발자 안내서 [1/2] 본문
픽셀 벤더 툴킷 1.5 Build 01판에 든 PDF 파일을 번역했습니다.
ADOBE® PIXEL BENDER™
PIXEL BENDER DEVELOPER’S GUIDE
Copyright © 2009 Adobe Systems Incorporated. All rights reserved.
Adobe Pixel Bender Developer’s Guide.
If this guide is distributed with software that includes an end user agreement, this guide, as well as the software described in it, is furnished under license and may be used or copied only in accordance with the terms of such license. Except as permitted by any such license, no part of this guide may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, recording, or otherwise, without the prior written permission of Adobe Systems Incorporated. Please note that the content in this guide is protected under copyright law even if it is not distributed with software that includes an end user license agreement.
The content of this guide is furnished for informational use only, is subject to change without notice, and should not be construed as a commitment by Adobe Systems Incorporated. Adobe Systems Incorporated assumes no responsibility or liability for any errors or inaccuracies that may appear in the informational content contained in this guide.
Please remember that existing artwork or images that you may want to include in your project may be protected under copyright law. The unauthorized incorporation of such material into your new work could be a violation of the rights of the copyright owner. Please be sure to obtain any permission required from the copyright owner.
Any references to company names in sample templates are for demonstration purposes only and are not intended to refer to any actual organization.
Adobe, the Adobe logo, After Effects, Flash, Flex, Photoshop, and Pixel Bender are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries.
Microsoft and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. Apple, Mac, Mac OS, and Macintosh are trademarks of Apple Computer, Incorporated, registered in the United States and other countries. Sun and Java are trademarks or registered trademarks of Sun Microsystems, Incorporated in the United States and other countries. UNIX is a registered trademark of The Open Group in the US and other countries.
All other trademarks are the property of their respective owners.
Adobe Systems Incorporated, 345 Park Avenue, San Jose, California 95110, USA. Notice to U.S. Government End Users. The Software and Documentation are “Commercial Items,” as that term is defined at 48 C.F.R. §2.101, consisting of “Commercial Computer Software” and “Commercial Computer Software Documentation,” as such terms are used in 48 C.F.R. §12.212 or 48 C.F.R. §227.7202, as applicable. Consistent with 48 C.F.R. §12.212 or 48 C.F.R. §§227.7202-1 through 227.7202-4, as applicable, the Commercial Computer Software and Commercial Computer Software Documentation are being licensed to U.S. Government end users (a) only as Commercial Items and (b) with only those rights as are granted
to all other end users pursuant to the terms and conditions herein. Unpublished-rights reserved under the copyright laws of the United States. Adobe Systems Incorporated, 345 Park Avenue, San Jose, CA 95110-2704, USA. For U.S. Government End Users, Adobe agrees to comply with all applicable equal opportunity laws including, if appropriate, the provisions of Executive Order 11246, as amended, Section 402 of the Vietnam Era Veterans Readjustment Assistance Act of 1974 (38 USC 4212), and Section 503 of the Rehabilitation Act of 1973, as amended, and the regulations at 41 CFR Parts 60-1 through 60-60, 60-250, and 60-741. The affirmative action clause and regulations contained in the preceding sentence shall be incorporated by reference.
목차
서문
1 픽셀 벤더 툴킷 개요
픽셀 벤더 툴킷 설치하기
픽셀 벤더 툴킷 패키지의 내용물
시작하기
예제들
픽셀 벤더 개념들
파일 포맷
커널 프로그램 부분
내장 함수
픽셀 벤더 필터와 이펙트 사용하기
포토샵용으로 개발하기
애프터 이펙트용으로 개발하기
플래시용으로 개발하기
2 시작하기
픽셀 벤더 툴킷 IDE에 익숙해지기
새 픽셀 벤더 커널 프로그램 제작하기
커널 프로그램 편집하고 실행하기
그림 채널 분리하기
필터 연산을 감마로 바꾸기
매개변수 추가하기
매개변수 통제하기
최종 소스
3 픽셀 벤더 필터 작성하기
커널의 부분들
커널 메타데이터
커널 멤버
매개변수와 변수
픽셀 벤더 좌표계
픽셀 좌표에 접근하기
좌표 넘기기
입력 그림 그리고 추출
정사각형이 아닌 픽셀
여러 입력 그림
종속 값 사용하기
보조 함수
영역 함수 예제
보조 함수 예제
4 영역으로 작업하기
픽셀 벤더가 커널을 실행하는 방법
그래프에서 영역 추론하기
영역 결정하기
경계에서 하는 계산을 위해 그림 크기 조절하기
안전한 영역 경계
필요역 계산하기
needed() 함수 안에서 커널 매개변수에 접근하기
DOD로 필요역 계산하기
변경역 계산하기
한층 복잡한 예제
생성역 계산하기
5 픽셀 벤더 그래프 언어
그래프 요소들
간단한 그래프 예제
진짜 간단한 예제
복잡한 그래프
그래프 정의하기
그래프 매개변수와 커널 매개변수 정의하기
여러 마디 정의하기
복잡한 연결 정의하기
진짜 복잡한 예제
그래프 편집기 사용하기
6 애프터 이펙트용으로 개발하기
애프터 이펙트 커널 메타데이터
채널 넷인 값에 접근하기
회선 예제
애프터 이펙트에서의 커널 매개변수
회선 커널 확장
종속 함수
7 플래시용으로 개발하기
픽셀 벤더 필터를 SWF에 끼워넣기
픽셀 벤더 필터를 액션스크립트 라이브러리로 만들기
필터를 액션스크립트 클래스로 감싸기
SWC 라이브러리 만들기
서문
어도비® 픽셀 벤더™ 기술로 이질적인 하드웨어들에서 런타임에 자동으로 최적화하는 일반적인 그림, 비디오 처리 기반 구조를 만들 수 있습니다. 픽셀 벤더 커널 언어를 사용하여 하드웨어에 독립적인 방식으로 그림을 처리하는 알고리즘(필터 또는 이펙트)을 구현할 수 있습니다.
픽셀 벤더 툴킷에는 픽셀 벤더 커널 언어, 그래프 언어, 픽셀 벤더 툴킷 IDE(픽셀 벤더를 위한 통합 개발 환경), 예제 필터들, 문서가 포함됩니다.
이 문서(Pixel Bender Developer's Guide)에는 픽셀 벤더 툴킷 IDE에 대한 소개와 튜토리얼, 픽셀 벤더 커널 언어와 그래프 언어로 필터를 개발하는 방법에 대한 튜토리얼과 예제가 있습니다. 이 문서는 애프터 이펙트®, 플래시®, 포토샵® 같은 어도비 제품용으로 그림 필터를 개발하려는 프로그래머들을 위해 쓰였습니다.
짝 문서인 Pixel Bender Reference는 완전한 레퍼런스 안내서이자 픽셀 벤더 커널 언어와 그래프 언어를 위한 명세입니다.
픽셀 벤더로 개발하면 이점이 많습니다.
▶ 낮은 학습 곡선 픽셀 벤더에는 복잡한 그림 처리 알고리즘을 작성하기에 충분한 도구만 조금 있습니다. 픽셀 벤더는 C/C++와 각 애플리케이션의 플러그인 SDK보다 배우기 쉽습니다. 그래픽스 쉐이딩 언어나 다중 쓰레딩 API를 몰라도 됩니다.
▶ 병렬 처리 픽셀 벤더는 멀티코어 시스템과 멀티프로세서 시스템을 포함하여 여러 GPU와 CPU 아키텍쳐에서 같은 필터를 효율적으로 실행합니다. 픽셀 벤더는 어도비 제품에서 뛰어난 그림 처리 수행능력을 보입니다.
▶ 모든 비트 심도(bit-depth) 지원 한 커널이 애플리케이션에서 8 비트로도, 16 비트로도,32 비트로도 실행됩니다.
* bit-depth : 색심도(비트 심도라고도 함)는 비트맵 그림이나 비디오 프레임 버퍼에서 한 픽셀의 색상을 표현하는 데 쓰인 비트 개수를 나타내는 컴퓨터 그래픽스 용어입니다. 픽셀 당 비트(bpp)라고도 합니다. 색심도가 높을 수록 표현할 수 있는 색상이 많습니다. 출처 위키디피아 http://en.wikipedia.org/wiki/Color_depth
▶ 여러 어도비 애플리케이션에서 지원 픽셀 벤더는 여러 어도비 애플리케이션과 통합되었습니다. 픽셀 벤더로 다양한 어도비 제품 사이에 이식 가능한 필터를 개발할 수 있습니다. 개발자들이 필터를 공유하는 활기찬 Pixel Bender Exchange가 있습니다.
픽셀 벤더는 다른 픽셀값에 거의 의존하지 않고 픽셀을 처리하는 알고리즘에 가장 적합합니다. 예를 들어 각 픽셀의 밝기를 따로따로 바꿀 수 있기 때문에 그림의 밝기를 조작하는 커널을 작성할 수 있습니다. 히스토그램은 그림의 모든 픽셀값이 필요하기 때문에 픽셀 벤더로 히스토그램을 계산하려 하면 안 됩니다.
픽셀 벤더의 문법은 OpenGL Shading Language(GLSL)에 기반해 C 비슷하며 친숙합니다. 이 안내서에서는 독자가 프로그래밍과 그림 처리의 기본을 알고 대상 애플리케이션에 익숙하다고 가정합니다.
▶ 여기서 그림 처리 기본 배경 지식을 보세요.
▷ Image Processing Fundamentals: http://www.ph.tn.tudelft.nl/Courses/FIP/noframes/fip.html
▶ 그림 처리에 대한 더 수준 높은 자료는 이것들을 보세요.
▷ Digital Image Processing (3rd Edition), Rafael C. Gonzalez and Richard E. Woods, Prentice Hall, 2006. ISBN 013168728X
▷ Digital Image Warping, George Wolberg, IEEE Computer Society Press, 1990, ISBN 0818689447,
9780818689444
▷ Handbook of Image and Video Processing, Alan Conrad Bovik, Academic Press, 2005 ISBN
0121197921, 9780121197926
1 픽셀 벤더 툴킷 개요
픽셀 벤더 툴킷에는 다음이 포함됩니다.
▶ 그림 처리를 위한 고품격 그래픽스 프로그래밍 언어인 픽셀 벤더 커널 언어.
▶ 픽셀 처리 연산들(커널들)을 복잡한 필터로 묶기 위한 XML 기반 언어인 픽셀 벤더 그래프 언어.
▶ 픽셀 벤더 커널을 제작하고, 컴파일하고, 미리보기 위한 상호작용 개발 환경인 픽셀 벤더 툴킷 IDE.
▶ 픽셀 벤더 커널을 플래시 플레이어 10에서 쓸 수 있는 바이트코드 파일로 변환하기 위한 명령줄 유틸리티.
▶ 예제 필터, 예제 그림, 문서.
픽셀 벤더 툴킷 IDE로 픽셀 벤더 그림 처리 엔진을 사용하는 프로그램을 편집하고 실행할 수 있습니다. 픽셀 벤더 런타임 엔진은 많은 어도비 애플리케이션과 통합되었기 때문에 여러분이 직접 만든 픽셀 벤더 필터와 이펙트를 이 미리 준비된 애플리케이션들에 추가할 수 있습니다.
픽셀 벤더 툴킷 설치하기
여기서 픽셀 벤터 툴킷을 얻을 수 있습니다.
http://www.adobe.com/go/pixelbender_toolkit
윈도우즈에서 픽셀 벤더 툴킷을 설치하려면
1. 픽셀 벤더 툴킷 ZIP 파일을 내려받으세요.
2. 패키지를 풀고 압축을 푼 곳에서 Setup.exe를 실행하세요. 픽셀 벤더 툴킷 파일은 여기 설치됩니다.
Program Files\Adobe\Adobe Utilities\Pixel Bender Toolkit
맥 OS에서 픽셀 벤더 툴킷을 설치하려면
1. 픽셀 벤더 툴킷 DMG 파일을 내려받으세요.
2. 인스톨러를 가상 디스크에 마운트하기 위해 DMG 아이템을 더블 클릭하세요.
3. 가상 디스크에서 Setup 애플리케이션을 더블 클릭하세요. 픽셀 벤더 툴킷 파일은 여기 설치됩니다.
/Applications/Utilities/Adobe Utilities/Pixel Bender Toolkit
픽셀 벤더 툴킷 패키지의 내용물
픽셀 벤더 툴킷에는 다음 폴더들과 파일들이 포함됩니다. (경로는 내려받은 위치 PBTKroot에 상대적입니다)
최상위 수준 (공유 라이브러리 제외) | |
PixelBenderToolkitReadMe.pdf | 픽셀 벤더 툴킷에 대한 짧은 소개. |
pixel_bender_toolkit.exe | 픽셀 벤더 툴킷 IDE 실행용. |
pbutil.exe | 픽셀 벤더 커널을 플래시 플레이어 10에서 쓸 수 있는 바이트코드 파일로 변환하는 명령줄 유틸리티. "File formats"를 보세요. |
PixelBenderUtilityReadMe.pdf | 명령줄 유틸리티 지침. |
덤 Additional folders: |
|
docs/ | 픽셀 벤더 개발자 가이드, 픽셀 벤더 레퍼런스, 이 문서가 들어 있습니다. |
legal/ | 라이센스. |
pixel bender files/ | 예제 프로그램들. "Samples"를 보세요. Sample programs; see “Samples” on page 9. |
sample images/ | 배우고 실험하는 데 쓸 예제 그림 모음. A set of sample images for use in learning and testing. |
시작하기
1. 픽셀 벤더 툴킷 IDE를 실행하세요.
▷ 윈도우즈면 시작 메뉴에서 실행하세요.
▷ 맥 OS면 Application 폴더에서 실행하세요.
/Applications/Utilites/Adobe Utilities/Pixel Bender Toolkit/Pixel Bender Toolkit
2. 픽셀 벤더 커널 파일(.pbk)를 픽셀 벤더 툴킷 IDE로 불러오려면, File -> Open Pixel Bender File을 선택하거나 Ctrl+O를 누르세요.
3. 프로그램을 실험해보려면 픽셀 벤더 툴킷 IDE의 오른쪽 아래 구석에 있는 Run을 누르세요. 코드 편집창 밑입니다.
▷ 프로그램에 처리를 위한 그림이 필요하면 그림 파일을 요구받습니다.
▷ 프로그램에 매개변수가 있으면 오른쪽 구석의 패널에 있는 컨트롤들을 만져서 입력할 수 있습니다. 2장 "시작하기"에서 개발 환경 소개와 사용 방법을 보세요.
예제들
픽셀 벤더 툴킷에는 여러 기법과 사용법을 익힐 수 있는 예제 프로그램들이 들어 있습니다.
Checkerboard | 두 입력 그림을 결합해 바둑판 이펙트를 만듭니다. |
Pixelate | 추출 방법의 예시입니다. |
BasicBoxBlur SimpleBoxBlur |
지금 좌표의 주변 픽셀들을 평균내어 흐리게 출력합니다. 정사각형이 아닌 픽셀에 대처하는 방법을 보여줍니다. BasicBoxBlur는 루프를 사용하는데 플래시 플레이어에서는 쓰지 못합니다. SimpleBoxBlur판은 같은 연산을 루프 없이 구현하고 플래시에서도 작동합니다. |
Twirl | 그림을 비틀며 사용자가 반지름과 중심점 매개변수에 값을 할당하여 조절할 수 있습니다. |
Crossfade | 두 그림을 겹치게 합니다. |
InvertRGB | 그림의 적색, 녹색, 청색 채널을 반전시킵니다. |
Sepia | 간단한 색공간(color-space) 변환으로 그림을 세피아 색조로 만듭니다. Performs a simple color-space transformation that results in a sepia-toned image. |
픽셀 벤더 개념들
픽셀 벤더에서 그림 처리의 기본 단위는 커널입니다. 커널은 출력 픽셀 하나를 생산합니다. 보통 픽셀 벤더 커널은
▶ 하나 이상의 입력 그림에서 하나 이상의 픽셀을 추출해
▶ 추출한 픽셀들의 색상을 가지고 계산하여
▶ 그 결과를 출력 픽셀에 할당합니다.
픽셀 벤더 커널 언어에서 각 프로그램에는 이름 있는 커널 하나가 정의됩니다. 커널은 임의 개수의 입력 픽셀에 대한 한 출력 픽셀의 결과를 함수로서 정의하는 한 객체입니다. 입력 픽셀들의 출처 그림은 서로 다를 수 있습니다.
각 커널에는 반드시 evaluatePixel() 함수가 정의되어야 합니다. 이 함수는 출력 그림을 만들기 위해 모든 출력 픽셀에 병렬적으로 실행됩니다. 커널은 매개변수를 어떤 데이터 타입이든 몇 개든지 받을 수 있습니다.
픽셀 벤더 커널은 출력 그림의 모든 픽셀에 대해 한 번씩 실행됩니다. 각 실행 전후로 아무 상태 정보도 저장되지 않기 때문에 각 실행에서 추출한 픽셀들을 축적해 평균 픽셀 값을 모으는 건 불가능합니다. 커널의 각 실행에서 필요한 모든 정보를 계산해야 합니다. 여러분이 정보를 미리 계산하고 입력이나 매개변수로 넘길 수 있기는 합니다.
여러 커널을 연결하는 픽셀 벤더 그래프 언어로 정교한 그림 처리 이펙트를 만들 수 있습니다. 그래프는 5장 "픽셀 벤더 그래프 언어"에서 다룹니다.
파일 형식
픽셀 벤더에서 파일 형식은 PBK, PBJ, PBG 세 개입니다.
▶ 커널 프로그램은 일반 텍스트 파일에 .pbk 확장자로 저장됩니다.
▶ 플래시 플레이어에서 쓰려면 커널을 바이트코드 프로그램으로 내보내야 하며 프로그램은 .pbj 확장자의 바이너리 파일에 저장됩니다. 픽셀 벤더 툴킷 IDE는 내보내기 명령을 제공하며 명령줄 변환 유틸리티인 pbutil.exe를 쓸 수도 있습니다.
▶ 그래프 기술(記述)은 일반 텍스트 파일에 .pbj 확장자로 저장됩니다.
커널 프로그램 부분
모든 곳에 단색을 반환하는 아주 간단한 픽셀 벤더 프로그램입니다.
<languageVersion : 1.0;> 헤더
kernel FillWithBlack
<
namespace : "FillWithBlack";
vendor : "Pixel Bender Guide"; <>로 감싼 메타데이터 부분
version : 1;
description : "simplest kernel";
>
{
output pixel4 result; {}로 감싼 커널 정의
void evaluatePixel()
{
result = pixel4(0,0,0,0);
}
}
▶ languageVersion 요소, namespace, vendor, version 메타데이터 값은 필수입니다. 픽셀 벤더 툴킷 IDE에서 새 커널을 만들면 이것들이 기본으로 채워지며 필요하면 수정할 수 있습니다.
▶ 위 커널 정의에 픽셀 벤더 데이터 타입인 pixel4가 쓰였는데, 보통 적색, 녹색, 청색, 알파 채널이라 말하는 4 채널 픽셀이 저장됩니다.
밑의 좀 더 흥미로운 예제는 입력 그림 src를 받고 각 픽셀을 어둡게 해 출력합니다.
<languageVersion : 1.0;>
kernel DarkenedOutput
<
namespace : "Tutorial";
vendor : "Pixel Bender Guide";
version : 1;
description : "slightly more complex kernel";
>
{
input image4 src;
output pixel4 dst;
void evaluatePixel() {
dst = 0.5 * sampleNearest(src, outCoord());
}
}
▶ 여기서 evaluatePixel() 함수는 내장 그림 추출 함수 중 하나인 sampleNearest()를 호출하여 지금 가장 가까운 입력 픽셀을 읽습니다.
▶ 그림을 어둡게 하기 위해 * 연산으로 픽셀 값에 0.5를 곱합니다. pixel4 값의 각 채널에 0.5가 곱해집니다.
위 프로그램들이 출력 그림이 아니라 출력 픽셀을 정의하는 것에 주목하세요. 여기서는 한 픽셀에만 접근했는데, 커널은 입력 그림의 모든 픽셀에 접근할 수 있고, 반면에 출력은 픽셀 하나만 됩니다. 픽셀 벤더 런타임 엔진은 커널을 출력 그림의 모든 픽셀에 대해 실행합니다.
내장 함수들
픽셀 벤더 커널 언어에는 일반적인 픽셀 조작 작업을 위한 내장 함수가 많습니다. 내장 함수는 이렇게 분류됩니다.
함수 유형 | 설명 |
산술Mathematical | 이 함수들은 도와 라디안 수치를 전환하고, 삼각함수 값을 얻고, 로그, 제곱, 부호 조작, 비교 같은 기본적인 산술 연산을 합니다. 보간을 위한 함수도 여러 종류가 있습니다. |
기하 Geometric |
이 함수들은 벡터를 계산하고 행렬 산술, 비교를 합니다. (픽셀 벤더에는 요소가 둘, 셋, 넷인 벡터 타입이 정의되었습니다.) |
영역 Region |
이 함수들은 사각 영역을 받아 변환합니다. region 데이터 타입에 대해 작동합니다. |
추출 Sampling |
각 추출 함수는 그림을 받아 그림과 채널 수가 같은 픽셀을 반환합니다. 이게 프로그램이 입력 그림에서 데이터를 읽는 방법입니다. |
고유 속성 Intrinsics |
이 함수들로 시스템의 컴파일타임 또는 런타임 속성에 접근할 수 있습니다. dod() (정의역), pixelSize()가 그 예입니다. |
많은 함수의 사용법이 픽셀 벤더 툴킷에 포함된 예제 프로그램들에 설명되어 있습니다.
픽셀 벤더 필터와 이펙트 사용하기
다음 어도비 애플리케이션들에서 픽셀 벤더 필터와 이펙트를 지원합니다.
▶ 어도비 포토샵® CS4 (픽셀 벤더 플러그인 이용)
▶ 어도비 애프터 이펙트® CS4 (애프터 이펙트 CS4를 깔 때 픽셀 벤더 툴킷이 자동으로 깔립니다)
▶ 어도비 플래시 플레이어 10과 어도비 플래시 CS4 전문가용 (플래시 CS4 전문가용을 깔 때 픽셀 벤더 툴킷이 자동으로 깔립니다)
애플리케이션마다 픽셀 벤더 런타임 엔진을 다르게 구현합니다. 그래서 애플리케이션마다 특징이 있으며, 제한도 조금 있습니다. 어떤 경우에는 픽셀 벤더 프로그램의 일부(표시되는 이름 따위)가 런타임에 조금 해석되어 각 애플리케이션마다 픽셀 벤더 필터를 UI에 내장 필터와 이펙트와 무리없이 통합할 수 있게 됩니다. 사실 몇 내장 필터와 이펙트는 이미 픽셀 벤더로 구현되었습니다.
서드 파티에서 개발한 픽셀 벤더 필터와 이펙트를 찾아보려면 Pixel Bender Exchange로 가보세요.
http://www.adobe.com/go/pixelbender
조금만 신경쓰면 애플리케이션들 사이에 이식 가능한 필터를 제작할 수 있습니다. 이 절에서는 애플리케이션 플랫폼들 사이의 차이점을 훑으며 뒤에 있는 장들에서는 특정 애플리케이션 전용 예제와 지침을 제공합니다.
포토샵용으로 개발하기
어도비 포토샵 CS4의 픽셀 벤더 플러그인은 포토샵 CS4에서 연 그림을 픽셀 벤더 필터로 처리하는 것을 지원합니다. 이 플러그인은 여기서 내려받습니다.
http://www.adobe.com/go/pixelbender_toolkit
픽셀 벤더 플러그인 인스톨러는 Extension Manager CS4 인스톨러로 제공됩니다. 설치하려면 Extension Manager CS4는 필수입니다. 픽셀 벤더 필터는 컴퓨터의 그래픽 카드(GPU)나 CPU에서 실행됩니다. 지원 그래픽 카드가 플러그인 ReadMe 파일에 나열되어 있습니다.
플러그인은 Pixel Bender Gallery를 생성합니다. 포토샵의 픽셀 벤더 플러그인을 쓰려면
1. 어도비 포토샵 CS4를 실행하세요.
2. 그림을 여세요.
3. Filter > Pixel Bender > Pixel Bender Gallery를 선택하세요.
필터 추가하기
픽셀 벤더 플러그인은 커널(PBK)와 그래프(PBG) 프로그램 둘 다 지원합니다.
처음에는 픽셀 벤더 플러그인를 깔 때 함께 깔린 픽셀 벤더 필터들이 Pixel Bender Gallery에 나타납니다. 이 필터들은 어도비 픽셀 벤더 팀은 물론 픽셀 벤더 사용자들에게도 인정받았습니다.
Pixel Bender Gallery에 필터를 더 설치하려면
1. Gallery를 닫으세요.
2. 픽셀 벤더 프로그램을 이 폴더로 복사하세요.
Adobe Photoshop CS4\Pixel Bender Files\
플러그인이 초기화된 다음부터는 추가한 필터를 Pixel Bender Gallery에서 사용할 수 있습니다.
Smart Object 만들기
픽셀 벤더 플러그인은 Smart Object에 대한 비왜곡(non-destructive) 렌더링을 지원합니다. Smart Object를 만들려면
1. 그림을 여세요.
2. 레이어를 선택하세요.
3. fly-out 메뉴인 Layer에서 "Convert to Smart Object"를 선택하세요.
From the Layer fly-out menu, choose "Convert to Smart Object."
fly-out 메뉴 = 콤보 박스 메뉴?
필터의 렌더링은 원래 그림과 구분된 레이어에 저장되고, 필터가 사용 가능하면 그 후에야 수정됩니다.
The rendering of the filter is stored in a layer separate from the original image and may be subsequently modified if the filter is available.
포토샵 CS4를 써 본 적이 없어서 무슨 말인지 잘 모르겠습니다.
포토샵 특성과 제한
▶ 플러그인은 불투명하거나 투명한 RGB-8, 16비트 그림을 지원합니다. 지원되지 않는 그림 유형을 열면 Pixel Bender Gallery가 메뉴에서 비활성화되어 픽셀 벤더 필터를 그림에 적용할 수 없습니다. 그림에 픽셀 벤더 필터를 적용하려면 그림을 지원되는 유형으로 변환해야 합니다.
▶ 각 필터의 커널 이름은 유일해야 합니다. 이름이 같은 여러 커널 중 마지막으로 컴파일된 커널이 Pixel Bender Gallery에 표시됩니다.
애프터 이펙트용으로 개발하기
픽셀 벤더는 애프터 이펙트와 무리없이 통합됩니다. 애프터 이펙트 플러그인 SDK를 배우지 않아도 픽셀 벤더로 이펙트를 제작할 수 있습니다.
애프터 이펙트는 픽셀 벤더 커널 프로그램과 그래프 프로그램을 위한 PBK, PBG 파일 유형 둘 다를 지원합니다. Pixel Bender Plug-ins 폴더에 있는 모든 커널 프로그램과 그래프 프로그램은 Effects and Presets 패널에 이펙트로 표시됩니다. 커널, 그래프 프로그램은 애프터 이펙트 플러그인 SDK로 작성한 이펙트처럼 작동합니다. 커널, 그래프의 매개변수들은 Effect Controls 패널에 나타나고, 다른 애프터 이펙트 매개변수들처럼 애니메이션을 만들 수 있습니다.
이펙트 추가하기
픽셀 벤더 커널 프로그램이나 그래프 프로그램을 애프터 이펙트의 이펙트로서 불러오려면
1. 애프터 이펙트가 꺼져 있는 걸 확인하세요.
2. 이 경로에 Pixel Bender Plug-ins 폴더를 만드세요.
윈도우즈 XP에서: C:\Documents and Settings\<username>\My Documents\Adobe\After Effects CS4\Pixel Bender Plug-ins\
윈도우즈 비스타에서: C:\Users\<username>\Documents\Adobe\After Effects CS4\Pixel Bender Plug-ins\
맥 OS에서: ~/Documents/Adobe/After Effects CS4/Pixel Bender Plug-ins/
3. 이 새 폴더에 커널 프로그램 파일이나 그래프 프로그램 파일을 놓으세요.
4. 애프터 이펙트를 실행하세요.
애프터 이펙트 특성과 제한
▶ 애프터 이펙트는 두 커널 메타데이터 속성을 옵션으로 정의합니다.
displayname | Effects and Presets 패널에 보일 이펙트 이름. 명시되지 않으면 커널 이름이 쓰입니다. |
category | 이펙트의 분류. 기본값은 'Pixel Bender' 분류입니다. |
▶ 애프터 이펙트는 4 채널 입력과 출력만 지원합니다. 4 채널 아래의 입력이나 출력을 쓰는 커널을 애프터 이펙트에서 사용하려면 커널을 고쳐야 합니다.
▶ 애프터 이펙트는 고유의 이펙트 매개변수 모음에 맞추기 위해 추가적인 매개변수 메타데이터를 정의합니다. 6장 "애프터 이펙트용으로 개발하기"를 보세요.
▶ 비점별 필터에 needed() 함수와 changed() 함수를 정의해야 합니다. 그렇게 하지 않으면 커널은 작동하는 것처럼 보여도 비능률적으로 실행되고 잘못된 그림을 생산합니다. 41쪽의 "영역 정의하기"를 보세요.
점별(pointwise)은 필터가 커널을 실행할 때마다 지금 픽셀 하나만 처리하는 걸 일컫습니다.
▶ 애프터 이펙트는 비디오 데이터를 처리하며, 비디오 데이터는 보통 정사각형이 아닌 픽셀을 사용합니다. 커널에서 픽셀 크기와 영상비를 고려해야 합니다. 31쪽의 "정사각형이 아닌 픽셀"을 보세요.
▶ 애프터 이펙트는 high dynamic range (HDR)를 지원합니다. 그림 데이터가 항상 0.0에서 1.0 사이라고 생각하면 큰일나요.
RGBA 색상에서 각 채널값의 범위는 0x00~0xff이지만 픽셀 벤더에서는 0.0~1.0입니다.
▶ 애프터 이펙트는 무한 영역을 만들어내는 everywhere()를 지원하지 않습니다. 이 내장 함수를 사용하는 커널을 애프터 이펙트에서 쓰려면 커널이 제한된 영역 안에서 출력을 수행하게 고쳐야 합니다.
추가 정보
▶ 여기에서 어도비 애프터 이펙트 CS4에서 픽셀 벤더를 쓰는 것에 대한 추가 정보를 보세요.
http://help.adobe.com/en_US/AfterEffects/9.0/
플래시용으로 개발하기
플래시 플레이어 10에서 픽셀 벤더 이펙트는 그림, 벡터 그래픽, 디지털 비디오를 포함하여 어느 표시 객체에든 적용할 수 있습니다. 실행 속도는 엄청나게 빠릅니다. 액션스크립트로는 프레임마다 수 초 걸리던 이펙트가 픽셀 벤더 커널로는 실시간으로 가능합니다.
커널 프로그램을 저장할 때 기본으로 PBK 유형의 파일로 저장됩니다. 플래시에서 쓰려면 PBJ 유형으로 내보내야 합니다.
▶ 픽셀 벤더 툴킷 IDE에서 File > Export Kernel Filter for Flash Player를 선택하세요. 이 명령은 플래시 플레이어에서 쓰기 위해 커널을 .pbj 확장자의 파일로 컴파일하고 내보냅니다.
▶ 픽셀 벤더 툴킷과 함께 제공되는 명령줄 변환 유틸리티인 pbutil.exe에 대한 지침이 관련 read-me 파일에 있습니다. 이 유틸리티는 입력된 PBK 파일을 PBJ 포맷으로 변환합니다.
플래시 플레이어로 커널 불러오기
PBJ 파일 안에 컴파일된 바이트 코드는 Shader 객체 안에 불러오거나 끼워넣어 SWF 컨텐트에서 쓸 수 있습니다.
▶ 런타임에 커널을 불러올 수 있습니다. 이 예제는 URLLoader 클래스를 사용하여 커널을 불러옵니다.
var camellia_mc:MovieClip;
var urlRequest:URLRequest = new URLRequest( "channelscrambler.pbj" );
var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
urlLoader.addEventListener( Event.COMPLETE, applyFilter );
urlLoader.load( urlRequest );
function applyFilter( event:Event ):void {
trace("apply");
urlLoader.removeEventListener( Event.COMPLETE, applyFilter );
var shader:Shader = new Shader( event.target.data );
var shaderFilter:ShaderFilter = new ShaderFilter( shader );
camellia_mc.filters = [ shaderFilter ];
}
▶ Embed 태그(플래시 CS4 전문가용에서 지원)는 커널을 불러오는 가장 쉬운 방법입니다. Embed 태그는 액션스크립트 컴파일러에게 SWF 파일을 생성할 때 픽셀 벤더 커널을 끼워넣으라고 명령합니다. Embed 태그는 Class 유형의 변수 정의와 함께 쓰입니다.
[Embed(source="myFilter.pbj", mimeType="application/octet-stream")]
var MyFilterKernel:Class;
커널을 사용하려면 클래스(위 예제에서는 MyFilterKernel)의 인스턴스를 생성합니다. 예를 들어 다음 코드는 끼워넣은 커널을 사용해 새 Shader 객체와 ShaderFilter 객체를 생성하여 스테이지의 MovieClip 인스턴스에 적용합니다.
var camellia_mc:MovieClip;
//Embed the PixelBender kernel in the output SWF
[Embed(source="myFilter.pbj", mimeType="application/octet-stream")]
var MyFilterKernel:Class;
var shader:Shader = new Shader(new MyFilterKernel() );
var shaderFilter:ShaderFilter = new ShaderFilter( shader );
camellia_mc.filters = [ shaderFilter ];
Embed 태그를 사용할 때 플래시 CS4 전문가용은 플렉스 SDK의 Flex.swc 라이브러리를 사용합니다. 이 SDK는 플래시 CS4 전문가용과 함께 깔리고 보통 플래시 CS4 전문가용이 설치된 폴더 아래에서 Common/Configuration/ActionScript 3.0/libs/flex_sdk_3에 있습니다. Embed 태그를 사용하는 무비를 처음 시험하거나 제작할 때 플렉스 SDK의 경로를 확인할 것을 요구받습니다. 플래시 CS4 전문가용과 함께 깔린 플렉스 SDK를 사용하려면 그냥 OK를 누르면 되고, 다른 버전의 플렉스를 사용하고 싶으면 경로를 바꿀 수 있습니다. 프로젝트에 쓰인 설정은 나중에 Library path 탭 아래 Advanced ActoinScript 3.0 Settings 대화 상자에서 바꿀 수 있습니다. (Publish Settings의 Flash 탭에서 펼침 메뉴 Script 옆의 Settings 버튼을 눌러 Advanced ActionScript 3.0 Settings 대화 상자에 들어가세요.)
Publish Settings는 File > Publish Settings 또는 Ctrl+Shift+F12로 엽니다.
액션스크립트에서 커널의 매개변수에 접근하기
다음 매개변수 구문은 메타데이터가 있는 float3 매개변수를 선언합니다.
parameter float3 weights
<
defaultValue : float3( 0.5, 0.5, 0.5 );
minValue : float3( 0.1, 0.1, 0.1 );
maxValue : float3( 0.9, 0.9, 0.9 );
description : "A three element vector of weight values.";
>;
플래시 플레이어에서 매개변수 값에 접근하려면 커널을 감싸는 액션스크립트 Shader 객체의 data 속성을 사용합니다. 액션스크립트에서 이렇게 이 매개변수의 minimum, maximum 값에 접근할 수 있습니다. (myShader는 이 매개변수가 있는 커널을 감싸는 Shader 객체라고 칩니다)
var currentWeights:Array = myShader.data.weights.value;
var minWeights:Array = myShader.data.weights.minimumValue;
var maxWeights:Array = myShader.data.weights.maximumValue;
이 매개변수가 float3 벡터 타입이기 때문에 반환되는 액션스크립트 배열은 요소가 셋입니다. float 같은 스칼라 타입에 대한 배열은 요소가 하나입니다.
액션스크립트와 달리 픽셀 벤더는 타입을 알아서 변환하지 않습니다. 픽셀 벤더 프로그램에서 부동소수점 수를 입력하려면 소수점을 넣어야 합니다. 그러지 않으면 픽셀 벤더 컴파일러는 수를 실수 값이 아니라 정수로 다룹니다. 예를 들어 1.0이 아니라 1을 입력하면 타입 충돌 때문에 경고나 오류가 납니다만, 오류 알림은 문제를 알아채는 데 별로 유용하지 않을 것입니다.
플래시 특성과 제한
▶ 플래시 플레이어에서 픽셀 벤더는 다음을 지원하지 않습니다.
▷ if-else를 제외한 루프와 반복 구문
▷ 직접 만든 보조 함수와 라이브러리 영역 함수
▷ 배열
▷ 종속 값
▷ 벡터 값에 대한 상수 아닌 인덱스
픽셀 벤더 툴킷 IDE에서 플래시 플레이어용으로 픽셀 벤더 커널을 개발할 때는 항상 플래시 경고(Flash Player Warnings and Errors에서 Build > Turn)를 켜세요. 이 옵션을 켜면 여러분이 플래시 플레이어에서 지원하지 않는 픽셀 벤더 커널 언어 특성을 사용할 때 컴파일러가 즉시 알립니다. 이러지 않으면 커널을 플래시 플레이어용으로 내보내려 하기 전까지 이 오류들이 보고되지 않습니다.
▶ 픽셀 벤더 그림은 채널마다 32비트지만 플래시 CS4 전문가용에서 그래픽은 채널마다 8비트입니다. 커널을 플래시 플레이어에서 실행할 때 입력 그림 데이터는 채널 당 32 비트로 변환되며 커널 실행이 끝나면 도로 채널 당 8비트로 변환됩니다.
▶ 플래시 플레이어는 항상 1x1 사각 픽셀을 사용합니다.
▶ 픽셀 벤더 그래프는 플래시 플레이어에서 지원하지 않습니다.
추가 정보
▶ 플래시 CS4 전문가용에서 픽셀 벤더를 사용하는 것에 대한 추가 정보는 Programming ActionScript 3.0의 Working with Pixel Bender shaders장이나 ActionScript Component and Language Reference의 Shader class 부분을 보세요. 이 문서들에는 플래시 CS4 전문가용에서 픽셀 벤더와 함께 사용할 수 있는 객체들에 대한 자세한 설명이 들어 있습니다.
▶ 7장 "플래시용으로 개발하기"에서 플래시와 액션스크립트에 초점을 맞춘 예제들을 보세요.
▶ Pixel Bender Exchange에 어도비가 운영하는 공공 커널 보관소가 있습니다. 커널 프로그램 제작자들은 픽셀 벤더 개발자 커뮤니티와 공유하는 것을 흔쾌히 수락했습니다. 픽셀 벤더 프로그래밍에 대해 토론하는 포럼도 있습니다.
2 시작하기
이 장에서는 픽셀 벤더 툴킷 IDE를 소개하고 픽셀 벤더 커널 언어로 커널 필터를 제작하는 과정을 대강 밟습니다.
픽셀 벤더 툴킷 IDE에 익숙해지기
픽셀 벤더 툴킷 IDE는 세 영역으로 나뉩니다.
▶ 소스 편집기 영역은 픽셀 벤더 소스 코드를 입력하고 편집하는 곳입니다. 구문 강조나 자동 코드 완성 같은 기본적인 코드 개발 기능을 제공합니다.
▶ 필터 매개변수 UI 영역은 여러분이 노출한 매개변수에 대한 사용자 인터페이스를 IDE가 자동으로 생성해 표시하는 곳입니다.
▶ 그림 창 영역은 불러온 그림에 필터를 적용한 결과를 표시합니다.
필터를 불러오지 않았다면, File > Load Image 1로 불러온 그림 파일이 그대로 표시됩니다. Load Image 1 명령은 파일 브라우저를 열고, 여기서 그림을 찾아 선택합니다. 픽셀 벤더 툴킷은 JPEG와 PNG 파일 유형을 지원합니다.
픽셀 벤더 커널 프로그램 제작하기
커널 프로그램을 제작하려면 "Create a new filter"를 누르거나 File > New Kernel Filter를 선택합니다.
소스 편집기에 픽셀 벤더 커널의 기본 구조가 표시됩니다. 새 필터에는 그림에 대해 기본적인 확인 기능을 수행하는 코드가 포함되어 있습니다. 그러니까, 그림을 전혀 수정하지 않지만 모든 필수 기반 구조가 들어 있습니다.
커널 프로그램 편집하고 실행하기
이 프로그램이 기본적인 필터 작업을 수행하게 간단히 고쳐보겠습니다.
▶ evaluatePixel() 함수의 정의를 수정하세요.
evaluatePixel() {
dst = 0.5 * sampleNearest(src, outCoord());
}
▶ 소스 편집기의 오른쪽 아래 Run을 눌러 프로그램을 실행하세요.
이 필터를 실행하면 투명도를 포함하여 모든 채널이 반으로 줄어들어 그림이 어두워집니다. 그림 창 영역에 결과가 표시됩니다.
기본적인 프로그래밍 기법 몇 가지를 익히기 위해 이 프로그램을 더 수정하겠습니다.
그림 채널 분리하기
이 단계에서는 알파 채널(그림의 투명도)은 놔두고 색상 채널들만 어둡게 하기 위해 입력 채널들을 분리합니다.
▶ evaluatePixel() 함수의 정의를 수정하세요.
evaluatePixel() {
float4 inputColor = sampleNearest(src, outCoord());
dst.rgb = 0.5 * inputColor.rgb;
dst.a = inputColor.a;
}
적색, 녹색, 청색 채널이 처음 세 요소, 알파 채널이 마지막 요소인 float4 타입의 임시 변수에 입력 색상을 저장합니다. r, g, b, a를 점(.) 연산자와 함께 사용하여 개별 값에 접근합니다.
필터 작업을 감마로 바꾸기
감마 : 명암의 정도
이 단계에서는 알고리즘을 크기 조정에서 감마 변경으로 바꿉니다. 그러기 위해 내장 함수 pow()로 색상 채널을 가지고 지수 계산을 합니다. (Pixel Bender Reference에서 다른 내장 함수들의 목록을 보세요.)
▶ evalutePixel() 함수의 정의를 수정하세요.
evaluatePixel() {
float4 inputColor = sampleNearest(src, outCoord());
float3 exp = float3(0.5);
dst.rgb = pow(inputColor.rgb, exp);
dst.a = inputColor.a;
}
색상 채널 세 개를 다 함수 하나에 넘긴 것을 보세요. pow()를 비롯해 많은 내장 함수가 벡터 값을 성분별로 작업하는 능력이 있습니다. 그러니까, 벡터의 각 값을 따로따로 다룹니다. pow()에 넘긴 두 벡터 인수의 요소 수가 같아야 연산이 바르게 됩니다. float3(0.5)는 (0.5, 0.5, 0.5)로 초기화되는 부동소수점 요소 셋 벡터를 생성하는 빠른 방법입니다.
주의: pow()의 결과는 0 미만인 inputColor 값에 대해서는 정의되지 않습니다. 애프터 이펙트나 high dynamic range(HDR) 그림을 지원하는 프로그램에서 일어날 수 있는 일입니다.
매개변수 추가하기
감마 변경량이 지금은 상수이지만 사용자가 제공하는 변량으로 바꾸는 것도 일리가 있습니다. 이 단계에서는 감마 값을 사용자가 제어하는 매개변수로 바꿉니다.
▶ 다음 코드를 evaluatePixel() 함수 앞에 추가하세요.
{
input image4 src;
output pixel4 dst;
parameter float gamma;
void
evaluatePixel ()
{...}
▶ evaluatePixel() 함수의 정의를 수정하세요.
void
evaluatePixel() {
float4 inputColor = sampleNearest(src, outCoord());
dst.rgb = pow(inputColor.rgb, float3(1.0 - gamma));
dst.a = inputColor.a;
}
▶ Run을 누르세요. 이제 IDE의 필터 매개변수 UI 부분에 감마 매개변수용 슬라이더가 보입니다.
이 컨트롤로 그림을 조작할 수 있습니다. 1.0에서 입력한 값을 빼면 양수고, 그러므로 그림은 밝아집니다. 슬라이더를 끌어 그림 창에서 밝기 변화를 볼 수 있습니다.
매개변수 통제하기
지금은 감마의 범위가 0에서 1까지기 때문에 그림을 밝게만 할 수 있고 어둡게는 할 수 없습니다. 다음 단계는 감마에 제한을 걸어 범위를 바꾸는 것입니다.
▶ 매개변수 명세에 제한을 추가하세요.
parameter float gamma
<
minValue:float(-0.5);
maxValue:float(0.5);
defaultValue:float(0.0);
>;
▶ Run을 누르세요. IDE의 필터 매개변수 UI에서 이제 0이 값 범위의 처음이 아니라 가운데 있는 게 보입니다.
이제 슬라이더를 왼쪽으로 끌어 그림을 어둡게 하거나 오른쪽으로 끌어 밝게 할 수 있습니다.
최종 소스
우리가 만든 프로그램입니다.
<languageVersion : 1.0;>
kernel NewFilter
< namespace : "your namespace";
vendor : "your vendor";
version : 1;
description : "your description";
>
{
input image4 src;
output pixel4 dst;
parameter float gamma
<
minValue:float(-0.5);
maxValue:float(0.5);
defaultValue:float(0.0);
>;
void
evaluatePixel() {
float4 inputColor = sampleNearest(src, outCoord());
dst.rgb = pow(inputColor.rgb, float3(1.0 - gamma));
dst.a = inputColor.a;
}
}
3 픽셀 벤더 필터 작성하기
이 절에서는 픽셀 벤더 커널 언어 프로그래밍의 독특한 특징들을 설명합니다.
커널의 각 부분
픽셀 벤더에서 그림 처리의 기본 단위는 커널입니다. 각 픽셀 벤더 커널 언어 프로그램은 커널 하나를 정의하며, 이 커널은 language-version 요소와 커널 구문을 포함하는 문자열로 기술됩니다.
<languageVersion : 1.0;> ← 필수인 language-version 요소
kernel name
<
kernel metadata pairs ← 대괄호로 감싼 메타데이터 부분
>
{
kernel members ← 중괄호로 감싼 변수, 함수 부분
}
이름 하나, 대괄호로 감쌌으며 커널을 설명하는 메타데이터 모음, 중괄호로 감쌌으며 필터링 작업을 정의하는 멤버 모음이 커널 구문에 포함됩니다.
커널 메타데이터
language-version 요소는 필터 정의 앞에 있어야 합니다. 이 구문과 메타데이터 부분은 픽셀 벤더 툴킷 IDE에서 필터를 새로 제작하면 자동으로 생기며 고칠 수 있습니다.
메타데이터 부분에는 이름공간, 커널 버전 외 식별, 서술 정보가 들었습니다. 복잡한 작업을 위해 여러 커널을 그래프로 모을 때 특히 중요합니다. 다음은 예시입니다.
<
namespace : "Tutorial";
vendor : "Adobe";
version : 1;
description: "My Filter";
>
namespace, vendor, version 값은 필수입니다. description은 선택 사항입니다.
▶ vendor는 필터를 제작한 회사나 개인의 이름입니다.
▶ version은 1로 시작하며 커널의 새 버전을 만들 때마다 올리는 정수 값입니다. 필터의 이전 버전을 남겨두고, 버그를 고치거나 수행 능력을 올려 새 버전을 소개할 수 있습니다.
▶ namespace는 회사나 제작자가 필터를 더 상세히 구분하기 위한 방법입니다. 예를 들어 어도비가 버전이 다른 포토샵용과 애프터 이펙트용 가우시안 흐림 필터를 가져서 둘을 구별하기 위해 namespace 필드에 제품의 이름을 썼을 수도 있습니다.
kernel GaussianBlur
<
namespace : "Photoshop";
vendor : "Adobe Systems";
version : 1;
>
{
// ... 포토샵용 가우시안 흐림 필터
}
kernel GaussianBlur
<
namespace : "After Effects";
vendor : "Adobe Systems";
version : 1;
>
{
// ... 애프터 이펙트용 가우시안 흐림 필터
}
실제 이름공간을 결정하기 위해 namespace 값은 다른 필터 식별자들과 함께 쓰이기 때문에 전세계에서 유일해야 하는 건 아닙니다.
이 장에서는 간결함을 위해 커널 이름과 멤버 부분만 보여줍니다. 예제를 실천해 보려면 커널 멤버 부분을 복사해 language-version 요소와 메타데이터 부분이 들어 있는 커널 정의에 붙여넣으면 됩니다.
커널 멤버들
커널은 C++의 클래스처럼 멤버 변수, 함수와 함께 정의됩니다. 커널 멤버 부분에는 선언, 함수 정의들이 포함됩니다. 모든 커널에는 적어도 evaluatePixel() 함수와 픽셀 타입의 output 매개변수 하나가 있어야 합니다.
이 아주 간단한 픽셀 벤더 프로그램은 모든 곳에 단색을 반환하는 커널로 구성됩니다.
kernel FillWithBlack
< ... >
{
output pixel4 result;
void evaluatePixel()
{
result = pixel4(0,0,0,0);
}
}
이 커널은 output pixel4 result 선언 그대로, 채널이 넷(적색, 녹색, 청색, 알파)인 출력 그림을 만들어냅니다. 커널이 출력 그림의 모든 픽셀에 대해 실행되기 때문에 픽셀 출력 매개변수는 그림 전체를 결정합니다.
픽셀 벤더는 타입을 상당히 따집니다. 기본 수치 (스칼라) 타입 외에도 멤버나 채널이 하나 두이 서이 너이 있는 픽셀이나 그림을 위한 일련의 벡터 타입이 정의되어 있습니다. Pixel Bender Reference에서 픽셀 벤더 데이터 타입에 관한 완전한 목록과 설명을 보세요.
매개변수와 변수
함수 정의 앞에 매개변수를 기입할 수 있습니다. 매개변수는 커널 프로그램으로 넘어가 커널 안에서 값이 고정됩니다. 종속 변수는 evaluateDependents() 함수에서 값을 할당 받으며 읽기 전용이 됩니다. ("종속 값 사용하기"를 보세요)
커널은 매개변수를 어느 타입이든 얼마든지 받을 수 있습니다. 매개변수들은 픽셀 벤더 런타임 시스템에 넘어가고 매개변수들의 값은 모든 픽셀에 대해 상수이며 3D 쉐이딩 언어에서 쓰이는 "uniform" 변수와 많이 비슷합니다.
커널을 실행하는 애플리케이션이 사용자가 매개변수 값을 설정할 수 있는 UI를 제공합니다. 예를 들어 애플리케이션은 필터를 실행하면 대화상자를 표시할 것입니다. 픽셀 벤더 툴킷 IDE가 이런 UI를 제공합니다.
이 예제에서는 채움 색상을 정의하는 데 쓰이는 매개변수를 FillWithBlack 커널에 추가합니다.
kernel FillWithColor
< ... >
{
parameter pixel4 color;
output pixel4 result;
void evaluatePixel()
{
result = color;
}
}
모든 픽셀 벤더 프로그램에 작성하는 데 쓴 픽셀 벤더 커널 언어의 버전을 languageVersion 구문을 써서 기입해야 한다는 것 기억하세요. 이 코드를 실행하려면 필수 기반 구조가 포함된 커널 프로그램에 붙여넣으세요.
픽셀 벤더 툴킷 IDE에서 이 예제를 실행해 보려면 코드 몸체를 커널 정의의 멤버 부분에 붙여 넣고 커널 이름을 적으세요.
호스트 애플리케이션에서는 매개변수의 데이터 타입을 보고 매개변수 값 설정에 알맞은 컨트롤을 고릅니다. 매개변수 값을 제한하면 UI에 최소값, 최대값, 기본값도 표시됩니다.
parameter pixel4 color
<
minValue: float4(0.0,0.0,0.0,0.0);
maxValue: float4(1.0,1.0,1.0,1.0);
defaultValue: float4(0.0,0.0,0.0,1.0);
>;
픽셀 벤더 좌표계
픽셀 벤더에 좌표계는 세계 좌표계(세계 공간이라고도 합니다) 하나 뿐입니다. 세계 좌표계는 네모나고 고르고 끝없습니다. X 축은 오른쪽으로 Y 축은 아래로 증가합니다.
픽셀 벤더 모형에서 그림은 크기가 없습니다. 그림을 이산 픽셀 좌표계 속 무한 평면이라 생각하세요. 커널을 실행하는 픽셀 벤더 런타임 엔진은 픽셀들을 저장하고 처리하는 데 필요한 버퍼 크기를 결정합니다. 픽셀 하나하나만 크기가 있습니다.
픽셀 벤더 좌표 모형은 필터 설계와 관련있습니다. 중심 같은 게 없으니 그림 "중심"을 반영하는 픽셀 벤더 커널은 작성하지 못합니다. 대신 그 원의 좌표를 커널 매개변수로 넘겨 뚜렷히 나타내야 합니다. ("좌표 넘기기"를 보세요)
좌표 변환은 불가능합니다. 그림은 출력 격자에 맞춰 재추출되어 변형됩니다. 이 제약이 혹독하게 보이겠지만, 일련의 그림 처리 작업을 똑 부러지게 나눠 실행하기 위해서입니다. 그림을 연이어 변형할 때 연계나 순서를 어떻게 할 것인가처럼, 좌표계에 관련된 정교한 추론은 커널 실행에 앞서 더 높은 수준에서 수행해야 합니다.
픽셀의 좌표에 접근하기
커널은 출력 그림의 모든 픽셀에 대해 같은 매개변수 값을 가지고 병렬적으로 실행됩니다. 각 픽셀에서 오직 현재 출력 픽셀의 좌표만이 바뀝니다.
현재 좌표값에 접근하려면 내장 함수 outCoord()를 사용하세요. 이 함수는 지금 evaluatePixel() 함수 실행에서 평가되는 출력 픽셀의 중심인 (x, y) 좌표를 나타내며 타입이 float2(실수 두 개가 담긴 벡터)인 값을 반환합니다. 현재 출력 좌표는 그림의 픽셀마다 다르지만 evalutePixel() 함수를 한 번 호출하고 있을 때는 불변입니다.
픽셀이 정사각형이라 치고(정사각형이 아닐 수도 있습니다. "정사각형이 아닌 픽셀"을 보세요), 4 x 3 픽셀 출력 그림에 대해 outCoord() 함수는 다음 값들을 반환합니다.
이 커널은 원점이 중심이고 색상과 반지름은 매개변수로 기입하고 계단 현상이 생기고 속이 채워진 원을 그립니다.
kernel RenderFilledCircle
< ... >
{
parameter float radius
<
minValue: 0.0;
maxValue: 600.0;
defaultValue: 100.0;
>;
parameter pixel4 color
<
minValue: float4(0.0,0.0,0.0,0.0);
maxValue: float4(1.0,1.0,1.0,1.0);
defaultValue: float4(0.0,0.0,0.0,1.0);
>;
input image4 src;
output pixel4 result;
void evaluatePixel() {
float2 coord_for_this_pixel = outCoord();
float cur_radius = length(coord_for_this_pixel);
if (cur_radius < radius) {
result = color;
}
else {
result = sampleNearest(src, coord_for_this_pixel);
}
}
}
좌표 넘기기
이 커널은 원점이 아니라 넘겨준 좌표를 중심으로 기입한 반지름과 색상을 이용해 원을 그립니다.
kernel PassCenterPoint
< ... >
{
parameter float2 center
<
minValue: float2(0);
maxValue: float2(500);
defaultValue: float2(180);
>;
parameter float radius
<
minValue: 0.0;
maxValue: 100.0;
defaultValue: 30.0;
>;
parameter pixel4 color
<
minValue: float4(0.0,0.0,0.0,0.0);
maxValue: float4(1.0,1.0,1.0,1.0);
defaultValue: float4(0.0,0.0,0.0,1.0);
>;
input image4 src;
output pixel4 result;
void evaluatePixel(){
// where are we relative to the center of the circle
float2 coord_for_this_pixel = outCoord() - center;
float cur_radius = length(coord_for_this_pixel);
if (cur_radius < radius) {
result = color;
}
else {
result = sampleNearest(src, coord_for_this_pixel + center);
}
}
}
입력 그림 그리고 추출
입력 그림이 없는 커널을 소스 또는 제너레이터라고 합니다. 제너레이터의 실례로 절차적 질감 작업이 있습니다. 하지만 커널 대부분은 입력을 하나 이상 받습니다.
커널에다 입력 그림을 하나 이상 선언하고 내장 추출 함수 중 하나에 그림과 픽셀 좌표를 넘겨 픽셀 값에 접근할 수 있습니다.
▶ sampleNearest() 함수는 넘긴 좌표와 중심이 가장 가까운 픽셀의 값을 반환합니다.
▶ sampleLinear() 함수는 넘긴 좌표 근처 네 픽셀을 이중 선형 보간합니다.
결과는 추출 좌표와 가장 가까운 픽셀의 색상입니다. 여기서는 중심이 (1.5, 0.5)인 픽셀이 제일 가깝습니다.
결과는 추출 영역이 덮는 네 픽셀의 가중 평균입니다.
다음은 추출을 하고 그림을 내버려 두는 간단한 커널입니다.
kernel Identity
< ... >
{
input image4 source;
output pixel4 result;
void evaluatePixel()
{
result = sampleNearest( source, outCoord() );
}
}
추출 함수에 어느 좌표든 넣을 수 있지만 그림 정의 영역 밖의 점을 추출하면 함수는 투명한 검정(0.0, 0.0, 0.0, 0.0)을 반환합니다. 모든 추출 함수는 넘긴 그림과 채널 수가 같은 픽셀 값을 반환합니다.
정사각형이 아닌 픽셀
픽셀이 정사각형이면 그림에 대한 픽셀 격자는 항상 그 밑의 세계 좌표계와 맞아떨어집니다.
사실 픽셀이 항상 정사각형인 건 아닙니다. 예를 들어 애프터 이펙트는 보통 정사각형이 아닌 픽셀로 이루어진 비디오 그림을 다룹니다. 픽셀이 폭 1.1 높이 1.0이라면 픽셀 격자는 세계 공간과 맞아 떨어지지 않습니다.
픽셀 크기가 변했지만 여전히 모든 좌표가 세계 좌표계 안에 있습니다. 예를 들어 4 x 3 픽셀 그림에 대해 outCoord()가 반환하는 값들은 이제 이렇습니다.
▶ outCoord() 함수의 반환값.
▶ 추출 함수에 넘긴 좌표.
▶ needed(), changed(), generated(), dod() 따위의 영역 함수에 넘긴 영역이나 이 함수들이 반환하는 영역
흐림 반지름 같은 거리나 영역을 측정하는 커널에 넘긴 어떤 매개변수든 세계 좌표로 기입해야 합니다.
출력 그림과 처음 입력 그림의 픽셀 크기가 같다고 가정해도 됩니다. 하지만 모든 입력이나 출력 그림의 픽셀 크기가 같다고는 할 수 없습니다. 임의의 입력 그림과 출력 그림의 픽셀 크기는 서로 다를 수도 있습니다. 임의의 입력 그림이나 출력 그림의 픽셀 크기를 알려면 pixelSize()와 pixelAspectRatio() 함수를 사용하세요.
▶ 내장 함수 pixelSize()는 해당 입력 그림이나 출력 그림의 픽셀 크기를 반환합니다. 결과는 세계 좌표계에서 측정한 픽셀 크기입니다.
▶ 내장 함수 pixelAspectRatio()는 해당 그림의 픽셀 너비를 픽셀 폭으로 나눈 값을 반환합니다.
pixelAspectRatio( i ) == pixelSize( i ).x / pixelSize( i ).y
정사각형 픽셀의 가로세로비는 1입니다.
플래시 주석: pixelSize() 함수와 pixelAspectRatio() 함수는 플래시 플레이어에서도 쓸 수 있지만 플래시 플레이어는 항상 1 x 1 픽셀을 씁니다.
그림 속 픽셀이 정사각형이 아닐 수도 있을 때 추출 결과가 정확하다고 확신하려면 픽셀 크기를 고려해야 합니다. 예를 들어 이웃한 픽셀들을 추출하려면 입력 그림의 픽셀 크기를 알아내어 추출 함수에 넘길 좌표를 고쳐야 합니다.
이 커널은 그 예로 픽셀마다 바로 양옆의 이웃을 평균내어 수평으로 가볍게 흐리게 만듭니다.
kernel HorizontalAverage
< ... >
{
input image4 source;
output pixel4 result;
void evaluatePixel()
{
float2 coord = outCoord();
float2 hOffset = float2(pixelSize(source).x, 0.0);
pixel4 left = sampleNearest(source, coord - hOffset);
pixel4 center= sampleNearest(source, coord);
pixel4 right = sampleNearest(source, coord + hOffset);
result = (left + center + right)/3.0;
}
}
다음 예제에서는 세계 좌표로 받은 반지름을 픽셀 크기에 맞춘 반지름으로 변환하기 위해 evaluateDependents()를 사용합니다.
kernel HorizontalTentBlur3
< ... >
{
input image4 src;
output pixel4 dst;
parameter float radius;
dependent int intRadius;
dependent float weights[ 100 ];
void evaluateDependents() {
float w = 1.0 / float( radius );
float s = w / float( radius );
intRadius = int( ceil( radius / pixelSize(src).x ) );
weights[ 0 ] = w;
for( int i = 1; i <= intRadius; ++i ) {
w -= s;
weights[ i ] = w;
}
}
void evaluatePixel() {
pixel4 total = sampleNearest( src, outCoord() ) * weights[ 0 ];
for( int i = 1; i <= intRadius; ++i ) {
float x = float( i ) * pixelSize( src ).x;
total += sampleNearest( src, outCoord() + float2( x, 0 ) ) * weights[ i ];
total += sampleNearest( src, outCoord() + float2( -x, 0 ) ) * weights[ i ];
}
}
}
여기 입력 그림 추가요
커널은 채널 수가 다른 입력 그림을 얼마든지 받을 수 있습니다. 다음 커널은 채널 넷인 image와 채널 하나인 matte를 곱합니다.
kernel MatteRGBA
< ... >
{
input image4 source;
input image1 matte;
output pixel4 result;
void evaluatePixel()
{
pixel4 in_pixel = sampleNearest( source, outCoord() );
pixel1 matte_value = sampleNearest( matte, outCoord() );
result = in_pixel * matte_value;
}
}
종속 값 사용하기
dependent value를 그냥 '종속 값'이라고 번역했지만 뭐라고 옮겨야 정확한 것일지 모르겠습니다.
플래시 주석: 종속 값은 플래시 플레이어에서 픽셀 벤더를 사용할 때는 쓸 수 없습니다.
Consider a convolution operation with a procedurally generated look-up table of pixel weights:
<languageVersion : 1.0;>
kernel GaussianBlur
<
namespace:"Tutorial";
vendor:"Adobe";
version:1;
>
{
input image4 source;
output pixel4 result;
void evaluatePixel()
{
const float sigma = 2.0;
float c = 1.0 / ( sqrt(2.0 * 3.1415926535 ) * sigma );
float ec = 2.0 * sigma * sigma;
float weight0 = exp( -( 0.0 * 0.0 ) / ec ) * c;
float weight1 = exp( -( 1.0 * 1.0 ) / ec ) * c;
float weight2 = exp( -( 2.0 * 2.0 ) / ec ) * c;
float weight3 = exp( -( 3.0 * 3.0 ) / ec ) * c;
float weight4 = exp( -( 4.0 * 4.0 ) / ec ) * c;
float4 acc = float4( 0.0 );
acc += sampleNearest( source, outCoord() ) * weight0;
acc += sampleNearest( source, outCoord() + float2( 1.0, 0.0 ) ) * weight1;
acc += sampleNearest( source, outCoord() + float2( -1.0, 0.0 ) ) * weight1;
acc += sampleNearest( source, outCoord() + float2( 2.0, 0.0 ) ) * weight2;
acc += sampleNearest( source, outCoord() + float2( -2.0, 0.0 ) ) * weight2;
acc += sampleNearest( source, outCoord() + float2( 3.0, 0.0 ) ) * weight3;
acc += sampleNearest( source, outCoord() + float2( -3.0, 0.0 ) ) * weight3;
acc += sampleNearest( source, outCoord() + float2( 4.0, 0.0 ) ) * weight4;
acc += sampleNearest( source, outCoord() + float2( -4.0, 0.0 ) ) * weight4;
result = acc;
}
}
이 코드는 작동은 하지만 참조표가 픽셀마다 재생성되어서 참조표를 쓰나 마나입니다. 값들을 한 번만 계산하고 모든 픽셀에 적용하길 원하는데 말입니다. 이 값들을 커널 매개변수로 받을 수도 있겠지만 그러면 값들을 계산하는 데 외부 코드가 필요합니다.
커널 안에서 계산을 하는데 한 번만 하려면 참조표를 종속 변수들의 모음으로 선언합니다. 그 다음 evaluateDependents() 함수로 변수들의 값을 계산합니다. dependent로 선언한 변수는 픽셀을 처리하기 전에 evaluateDependents() 몸체에서 한 번만 실행되어 초기화됩니다. 이 값들은 읽기 전용이고 evaluatePixel()이 실행될 때 모든 픽셀에 대해 상수입니다.
여기 종속 변수를 쓰게 수정한 GaussianBlur 커널 완성품입니다.
<languageVersion : 1.0;>
kernel GaussianBlur
<
namespace : "Tutorial";
vendor : "Adobe";
version : 1;
>
{
dependent float weight0;
dependent float weight1;
dependent float weight2;
dependent float weight3;
dependent float weight4;
input image4 source;
output pixel4 result;
void evaluateDependents()
{
const float sigma = 2.0;
float c = 1.0 / ( sqrt( 2.0 * 3.1415926535 ) * sigma );
float ec = 2.0 * sigma * sigma;
weight0 = exp( -( 0.0 * 0.0 ) / ec ) * c;
weight1 = exp( -( 1.0 * 1.0 ) / ec ) * c;
weight2 = exp( -( 2.0 * 2.0 ) / ec ) * c;
weight3 = exp( -( 3.0 * 3.0 ) / ec ) * c;
weight4 = exp( -( 4.0 * 4.0 ) / ec ) * c;
}
void evaluatePixel()
{
float4 acc = float4( 0.0 );
acc += sampleNearest( source, outCoord() ) * weight0;
acc += sampleNearest( source, outCoord() + float2( 1.0, 0.0 ) ) * weight1;
acc += sampleNearest( source, outCoord() + float2( -1.0, 0.0 ) ) * weight1;
acc += sampleNearest( source, outCoord() + float2( 2.0, 0.0 ) ) * weight2;
acc += sampleNearest( source, outCoord() + float2( -2.0, 0.0 ) ) * weight2;
acc += sampleNearest( source, outCoord() + float2( 3.0, 0.0 ) ) * weight3;
acc += sampleNearest( source, outCoord() + float2( -3.0, 0.0 ) ) * weight3;
acc += sampleNearest( source, outCoord() + float2( 4.0, 0.0 ) ) * weight4;
acc += sampleNearest( source, outCoord() + float2( -4.0, 0.0 ) ) * weight4;
result = acc;
}
}
보조 함수
플래시 주석: 보조 함수는 플래시 플레이어에서 픽셀 벤더를 사용할 때는 쓸 수 없습니다.
▶ 커널에 영역 함수를 정의할 수 있습니다. 영역 함수들은 이름과 시그너쳐가 미리 정의되었으며 커널이 다루는 픽셀들에서 출력 그림을 뽑기 위해 공간을 얼마나 할당해야 하는가에 대한 정보를 픽셀 벤더 런타임 엔진에다 제공합니다. 자세한 건 4장 "영역으로 작업하기"를 보세요.
▶ 커널에 evaluatePixel()이나 evaluateDependents()에서만 호출할 수 있는 임의의 보조 함수를 더 정의할 수 있습니다.
영역 함수 예제
RotateAndComposite 커널은 한 입력을 변형하고 다른 입력의 위에 올려 섞습니다. 미리 계산한 전치 행렬을 종속 변수에 담는다거나, 여러 입력을 따로따로 다룬다거나, 복잡한 영역 함수들을 활용합니다. 행렬들은 행 우선으로 저장됩니다. 픽셀 벤더 레퍼런스에서 자세한 내용을 보세요.
<languageVersion : 1.0;>
kernel RotateAndComposite
<
namespace : "Tutorial";
vendor : "Adobe";
version : 1;
>
{
parameter float theta; // 회전각
parameter float2 center // 회전 중심
<
minValue: float2(0);
maxValue: float2(1000);
defaultValue: float2(200);
>;
dependent float3x3 back_xform; // 회전 행렬
dependent float3x3 fwd_xform; // 회전 행렬의 역행렬
input image4 foreground;
input image4 background;
output pixel4 result;
// 이동 행렬과 이동 행렬의 역행렬을 계산합니다
void evaluateDependents()
{
// 중심을 원점으로 옮깁니다
float3x3 translate = float3x3(
1, 0, 0,
0, 1, 0,
-center.x, -center.y, 1 );
// theta만큼 회전합니다
float3x3 rotate = float3x3(
cos(theta), sin(theta), 0,
-sin(theta), cos(theta), 0, 0, 0, 1 );
// 조립하여 완전한 역변환 행렬을 얻습니다
fwd_xform = -translate*rotate*translate;
// sin 항의 부호를 바꿔 역회전을 얻습니다
rotate[0][1] = -rotate[0][1];
rotate[1][0] = -rotate[1][0];
// 조립하여 완전한 변환 행렬을 얻습니다
back_xform = translate*rotate*-translate;
}
// 메인 함수는 outCoord를 변환해 전경 픽셀을 알아냅니다
void evaluatePixel()
{
// 후경 좌표는 그냥 원래 좌표입니다
float2 bg_coord = outCoord();
// 전경 좌표는 outCoord를 변형한 것입니다.
// float3로 스펙 상향시키고 휘저어서 w는 버린 것에 주목하세요
float2 fg_coord =
(back_xform*float3(bg_coord.x, bg_coord.y, 1)).xy;
// 전경과 후경의 알파를 혼합합니다
pixel4 bg_pixel = sampleNearest(background, bg_coord);
pixel4 fg_pixel = sampleLinear(foreground, fg_coord);
result = mix(bg_pixel, fg_pixel, fg_pixel.a);
}
// needed 함수는 입력에 따라 결과가 다릅니다
region needed(
region output_region,
imageRef input_index )
{
region result;
if( input_index == background )
{
// 후경은 변형되지 않으니까 관심 가질 필요 없습니다
result = output_region;
}
else
{
// 출력 영역을 전경 공간으로 변형합니다
result = transform( back_xform, output_region );
}
return result;
}
// changed 함수는 needed 함수와 비슷하지만 다르게 변형합니다
region changed(
region input_region,
imageRef input_index )
{
region result;
if( input_index == background )
{
result = input_region;
}
else
{
result = transform( fwd_xform, input_region );
}
return result;
}
}
보조 함수 예제
보조 함수를 정의하여 코드 반복을 줄일 수 있습니다. 이 예제에서는 가우시안 가중을 계산하는 코드를 보조 함수로 옮겼습니다.
<languageVersion : 1.0;>
kernel GaussianBlur
<
namespace : "Tutorial";
vendor : "Adobe";
version : 1;
>
{
dependent float weight0;
dependent float weight1;
dependent float weight2;
dependent float weight3;
dependent float weight4;
input image4 source;
output pixel4 result;
float calculateWeight( float r, float sigma )
{
float c = 1.0 / ( sqrt( 2.0 * 3.1415926535 ) * sigma );
float ec = 2.0 * sigma * sigma;
return exp( -( r * r ) / ec ) * c;
}
void evaluateDependents()
{
const float sigma = 2.0;
weight0 = calculateWeight( 0.0, sigma );
weight1 = calculateWeight( 1.0, sigma );
weight2 = calculateWeight( 2.0, sigma );
weight3 = calculateWeight( 3.0, sigma );
weight4 = calculateWeight( 4.0, sigma );
}
void evaluatePixel()
{
float4 acc = float4( 0.0 );
acc += sampleNearest( source, outCoord() ) * weight0;
acc += sampleNearest( source, outCoord() + float2( 1.0, 0.0 ) ) * weight1;
acc += sampleNearest( source, outCoord() + float2( -1.0, 0.0 ) ) * weight1;
acc += sampleNearest( source, outCoord() + float2( 2.0, 0.0 ) ) * weight2;
acc += sampleNearest( source, outCoord() + float2( -2.0, 0.0 ) ) * weight2;
acc += sampleNearest( source, outCoord() + float2( 3.0, 0.0 ) ) * weight3;
acc += sampleNearest( source, outCoord() + float2( -3.0, 0.0 ) ) * weight3;
acc += sampleNearest( source, outCoord() + float2( 4.0, 0.0 ) ) * weight4;
acc += sampleNearest( source, outCoord() + float2( -4.0, 0.0 ) ) * weight4;
result = acc;
}
}
- 비트맵 데이터를 이용한 가변 지형 구현 2009.11.21
- getTimer()로 며칠까지 잴 수 있을까? 2009.10.21
- undefined와 null는 미묘하게 다르다 2009.10.21
- 픽셀 벤더 개발자 안내서 [2/2] 2009.10.14