Programmable shader Hanyang University Jungsik Park Objective n
Programmable shader Hanyang University Jungsik Park
Objective n Introduction n GLSL language definition v Data types v Qualifiers v Operators v Constructor and component selector v Flow control and function n Vertex shader n Fragment shader n Example v Simple shader v Phong shading shader Division of Electrical and Computer Engineering, Hanyang University
INTRODUCTION Division of Electrical and Computer Engineering, Hanyang University
Conventional Open. GL rendering pipeline n 파이프라인의 각 박스는 고정된 기능만을 수행 Division of Electrical and Computer Engineering, Hanyang University
Programmable pipeline n 사용자는 vertex shader, fragment shader를 작성하여 다양 한 음영처리 기법을 적용할 수 있다. Division of Electrical and Computer Engineering, Hanyang University
GLSL(OPENGL SHADING LANGUAGE) Division of Electrical and Computer Engineering, Hanyang University
Qualifiers n 타입 한정자 v 사용 예 v v v attribute Ø 버텍스 속성에는 built-in vertex attribute와 user-defined vertex attribute가 있 다. Ø user-defined vertex attribute의 경우 ‘attribute’ 한정자를 사용하여 선언하여 야 한다. uniform Ø 모든 버텍스 처리에서 동일하게 사용되는 전역 상수 varying Ø 버텍스 쉐이더에서 프래그먼트 쉐이더로 전달되는 변수 Ø user-defined varying variable의 경우 버텍스 쉐이더 및 프래그먼트 쉐이더 두 곳 모두에서 선언되어야 한다. Division of Electrical and Computer Engineering, Hanyang University
Operators n 연산자 v C 언어 연산자와 유사하나, 포인터 관련 연산자 및 비트 연산자, 형변환 연산자는 지원하지 않는다. Division of Electrical and Computer Engineering, Hanyang University
Flow control n 흐름 제어 구문 n 반복문 v C/C++과 동일한 방식의 for, while, do/while 반복문이 지 원되고, 중첩도 가능하다. n if/else v C/C++과 동일한 방식의 if/else 조건문이 지원되고, 중첩 도 가능하다. Division of Electrical and Computer Engineering, Hanyang University
VERTEX SHADER Division of Electrical and Computer Engineering, Hanyang University
Application n Moving vertices v Morphing v Wave motion v Fractals v Particle systems n Lighting v More realistic lighting models v Cartoon shaders Division of Electrical and Computer Engineering, Hanyang University
Built-in vertex shader variables n Built-in attribute input variables v gl. Vertex*(), gl. Normal*(), gl. Color*(), gl. Tex. Coord*() 등의 함수에 의해 전달되는 버텍스 속성 n 그 외의 다른 속성을 전달하는 경우, user-defined attribute variables로 전달 Division of Electrical and Computer Engineering, Hanyang University
Built-in vertex shader variables n Special output variables v 버텍스에 대한 출력값 n Varying output variables v 프래그먼트 쉐이더에서 사용되기 위한 변수로 같은 폴리곤을 구성하는 버텍스의 출력들간의 보간된 값이 프래그먼트 쉐이 더에 전달된다. Division of Electrical and Computer Engineering, Hanyang University
FRAGMENT SHADER Division of Electrical and Computer Engineering, Hanyang University
Application n Per fragment lighting calculations n Texture mapping environment mapping n Image processing bump mapping Division of Electrical and Computer Engineering, Hanyang University
Built-in fragment shader variables n Input variables v 버텍스 출력 변수들이 보간되어 전달되는 변수 n Output Variables Division of Electrical and Computer Engineering, Hanyang University
SETUP FOR USING GLSL SHADER Division of Electrical and Computer Engineering, Hanyang University
Setup Steps n Step 1: Create Shaders v Create handles to shaders n Step 2: Specify Shaders v load strings that contain shader source n Step 3: Compiling Shaders v Actually compile source (check for errors) n Step 4: Creating Program Objects v Program object controls the shaders n Step 5: Attach Shaders to Programs v Attach shaders to program obj via handle n Step 6: Link Shaders to Programs v Another step similar to attach n Step 7: Enable Program v Finally, let GPU know shaders are ready Division of Electrical and Computer Engineering, Hanyang University
App Setup GLhandle. ARB v. Shader, f. Shader, prog; // handles to objects // Step 1: Create a vertex & fragment shader object v. Shader = gl. Create. Shader. Object. ARB(GL_VERTEX_SHADER_ARB); f. Shader = gl. Create. Shader. Object. ARB(GL_FRAGMENT_SHADER_ARB); // Step 2: Load source code strings into shaders gl. Shader. Source. ARB(v. Shader, 1, &VS_String, NULL); gl. Shader. Source. ARB(f. Shader, 1, &FS_String, NULL); 여기서 VS_String은 버텍스 쉐이 더 코드가 저장된 문자형 배열, FS_String은 프래그먼트 쉐이더 코드가 저장된 문자형 배열 // Step 3: Compile the vertex, fragment shaders. gl. Compile. Shader. ARB(v. Shader); gl. Compile. Shader. ARB(f. Shader); // Step 4: Create a program object prog = gl. Create. Program. Object. ARB(); // Step 5: Attach the two compiled shaders gl. Attach. Object. ARB(prog, v. Shader); gl. Attach. Object. ARB(prog, f. Shader); // Step 6: Link the program object gl. Link. Program. ARB(prog); 버텍스 쉐이더나 프래그먼트 쉐이 더 중 어느 하나를 attach하지 않 는 경우, 해당 쉐이더 대신 고정 기 능 쉐이더가 작동하게 된다. // Step 7: Finally, install program object as part of current state gl. Use. Program. Object. ARB(prog); 고정 기능 쉐이더를 사용하고 자 하는 경우 인자에 0을 지정 Division of Electrical and Computer Engineering, Hanyang University
Set attribute/uniform values n 쉐이더가 링크될 때, attribute/uniform 변수 테이블이 생성된다 . n 쉐이더 내에 선언된 attribute/uniform 이름으로 변수의 테이블 인덱스를 얻어 온다. v GLint i =gl. Get. Attrib. Location(P, ”my. Attrib”) GLint j =gl. Get. Uniform. Location(P, ”my. Uniform”) n Attribute/uniform 변수 인덱스를 통해 해당 변수에 값을 할당 v gl. Vertex. Attrib 1 f(i, value) gl. Uniform 1 f(j, value) n 포인터를 이용하여 전달하는 경우 v gl. Vertex. Attrib. Pointer(i, …) // passing attributes using vertex array Division of Electrical and Computer Engineering, Hanyang University
EXAMPLE – SIMPLE SHADER Division of Electrical and Computer Engineering, Hanyang University
Simple shader n Simple. vert void main() { gl_Position = gl_Model. View. Projection. Matrix*gl_Vertex; gl_Front. Color = gl_Color; } n Simple. frag void main() { gl_Frag. Color = gl_Color; } Division of Electrical and Computer Engineering, Hanyang University
Prepare. Shader function n 버텍스 쉐이더 혹은 프래그먼트 쉐이더를 로드 및 컴파일 한 후, 프로그램 객체에 부착하여 링크시키는 함수 작성 v v 파일 입출력 필요 컴파일 및 링크 에러 발생시 에러 내용을 쿼리하여 출력해 주 는 부분 필요 // 쉐이더를로드, 컴파일, 프로그램객체에부착후링크 int Prepare. Shader(GLhandle. ARB *p. Program, char *filename, GLuint flag) { int ret; GLhandle. ARB *p. Shader = (GLhandle. ARB*)malloc(sizeof(GLhandle. ARB)); FILE *f. Shader; if (flag != GL_VERTEX_SHADER_ARB && flag != GL_FRAGMENT_SHADER_ARB) return FALSE; f. Shader = fopen(filename, "rb"); if (f. Shader == NULL) return FALSE; Division of Electrical and Computer Engineering, Hanyang University
Prepare. Shader function(cont’d) int leng, log. Length, success; char **src, *log = NULL; fseek(f. Shader, 0, SEEK_END); leng = ftell(f. Shader); src = (char **)malloc(sizeof(char*)); src[0] = (char *)malloc(sizeof(char) *(leng+1)); fseek(f. Shader, 0, SEEK_SET); fread(src[0], 1, leng, f. Shader); src[0][leng] = 0; *p. Shader = gl. Create. Shader. Object. ARB(flag); 컴파일 오류 체크 gl. Shader. Source. ARB(*p. Shader, 1, (const GLchar. ARB **)src, NULL); 및 오류 내용 출력 free(src[0]); free(src); fclose(f. Shader); gl. Compile. Shader. ARB(*p. Shader); gl. Get. Object. Parameteriv. ARB(*p. Shader, GL_OBJECT_COMPILE_STATUS_ARB, &success); if (!success) { gl. Get. Object. Parameteriv. ARB(*p. Shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log. Length); log = (char *)malloc(sizeof(char)*log. Length); gl. Get. Info. Log. ARB(*p. Shader, log. Length, NULL, log); fprintf(stderr, "%s : shader compile error. n", filename); fprintf(stderr, "%sn", log); free(log); ret = FALSE; } Division of Electrical and Computer Engineering, Hanyang University
Prepare. Shader function(cont’d) else{ gl. Attach. Object. ARB(*p. Program, *p. Shader); gl. Link. Program. ARB(*p. Program); gl. Get. Object. Parameteriv. ARB(*p. Program, GL_OBJECT_LINK_STATUS_ARB, &success); if (!success) { gl. Get. Object. Parameteriv. ARB(*p. Program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log. Length); log = (char *)malloc(sizeof(char)*log. Length); gl. Get. Info. Log. ARB(*p. Program, log. Length, NULL, log); fprintf(stderr, "program link error. n"); fprintf(stderr, "%sn", log); free(log); ret = FALSE; } else{ gl. Validate. Program. ARB(*p. Program); gl. Get. Object. Parameteriv. ARB(*p. Program, GL_OBJECT_VALIDATE_STATUS_ARB, &success); if (!success){ gl. Get. Object. Parameteriv. ARB(*p. Program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log. Length); log = (char*)malloc(sizeof(char)*log. Length); gl. Get. Info. Log. ARB(*p. Program, log. Length, NULL, log); fprintf(stderr, "program validate error. n"); fprintf(stderr, "%sn", log); free(log); ret = FALSE; } else ret = TRUE; } } free(p. Shader); return ret; } 링크 오류 체크 및 오 류 내용 출력 Division of Electrical and Computer Engineering, Hanyang University
n Setup. RC()에서 v glew. Init() 실행 v 프로그램 객체 생성 및 Prepare. Shader() 실행 v 쉐이더가 올바르게 준비되었으면 gl. Use. Program. ARB() 로 해당 프로그램 객체 사용 Open. GL 확장기능을사용할수있도록초기화 // if (ret) 에러가없는경우프로그램객체사용 // glew. Init(); // 프로그램객체(vert+frag) 생성 simple. Program = gl. Create. Program. Object. ARB(); // 쉐이더를로드하여컴파일및링크후프로그램객체에부착 int ret = Prepare. Shader(&simple. Program, "simple. vert", GL_VERTEX_SHADER_ARB); ret |= Prepare. Shader(&simple. Program, "simple. frag", GL_FRAGMENT_SHADER_ARB); gl. Use. Program. Object. ARB(simple. Program); Division of Electrical and Computer Engineering, Hanyang University
n 프로그램 객체를 전역 변수로 선언 GLhandle. ARB simple. Program; v 프로그램 객체 및 쉐이더 객체는 GLhandle. ARB 형을 갖 는다. n Main() 함수에서 v glut. Main. Loop()가 끝난 후 v 프로그램 객체 제거 // 프로그램객체제거 if (simple. Program) gl. Delete. Programs. ARB(1, &simple. Program); Division of Electrical and Computer Engineering, Hanyang University
Result n Simple. Shader 프로젝트를 빌드 후 실행 Division of Electrical and Computer Engineering, Hanyang University
EXAMPLE – PHONG SHADING Division of Electrical and Computer Engineering, Hanyang University
Shader code n Phong_shading. vert varying vec 3 N; varying vec 3 L; varying vec 3 E; void main() { gl_Position = gl_Model. View. Projection. Matrix*gl_Vertex; // 시점좌표계상에서조명효과를계산하기위해 // 버텍스좌표를시점좌표계로변환 vec 4 eye. Position = gl_Model. View. Matrix*gl_Vertex; // 광원좌표는자동으로시점좌표계로변환되어 // built-in 구조체에저장되어있다. vec 4 eye. Light. Pos = gl_Light. Source[0]. position; // homogeneous 좌표계형태의법선벡터, 광원벡터, 시점벡터를 // 3차원유클리드 좌표 형태로 varying 변수에저장 N = normalize(gl_Normal. Matrix*gl_Normal); L = eye. Light. Pos. xyz - eye. Position. xyz; E = -eye. Position. xyz; } Division of Electrical and Computer Engineering, Hanyang University
Shader code n Phong_shading. frag varying vec 3 N; varying vec 3 L; varying vec 3 E; void main() { vec 3 Normal = normalize(N); vec 3 Light = normalize(L); vec 3 Eye = normalize(E); vec 3 Half = normalize(Eye+Light); float f = 1. 0; // diffuse 및specular 반사에서vector 내적에의한요소계산 // max() 함수는내적결과가음수인경우 0. 0으로만들기위함. float Kd = max(dot(Normal, Light), 0. 0); float Ks = pow(max(dot(Half, Normal), 0. 0), gl_Front. Material. shininess); // diffuse, specular, ambient 반사성분계산 vec 4 diffuse = Kd*gl_Front. Light. Product[0]. diffuse; if (dot(Normal, Light)<0. 0) f = 0. 0; vec 4 specular = f*Ks*gl_Front. Light. Product[0]. specular; vec 4 ambient = gl_Front. Light. Product[0]. ambient; gl_Frag. Color = ambient + diffuse + specular; } Division of Electrical and Computer Engineering, Hanyang University
Result n Gouraud shading n Phong shading Division of Electrical and Computer Engineering, Hanyang University
- Slides: 44