OpenGL Super Bible 그래픽스 공부하기 - 1. OpenGL 기본개념이해
Part2. 첫번째 OpenGL 프로그램
- 쉐이더 코드 생성 / 컴파일
- OpenGL로 그리기
- AppFw이용, 프로그램 초기화 정리
2.1 간단한 애플리케이션 ->(SDL+GL 사용한 샘플, 간단하게 glClearBuffv를 사용하고 있다.)
- 모든 OpenGL 함수는 gl로 시작, 일부 인자 타입을 함수 이름 끝에 접미사로 줄여쓰는 등 여러 네이밍 컨벤션을 따름
1 2 | void glClearBufferfv(GLenum buffer, GLint drawBuffer, const GLfloat *value) //접미사, f(floating point) + v(vector) | cs |
-> value(r,g,b,a) ---(clear)--->buffer //a - 0:완전투명(Transparent), 1:불투명(Opaque)
-> drawBuffer는 지울 출력 버퍼가 여럿일 때 사용
2.2 Shader
- OpenGL은 Shader라 불리는 여러 작은 프로그램을 연결시켜 작동.
- OpenGL Shading Language(GLSL)로 작성, C기반, 컴파일러는 OpenGL에 내장
- (Shader Source)---(Compile)--->(Shader Object),
(Shader Object)+(Shader Object)+(Shader Object) ---(Link)--->(Program Object, 프로그램 객체)
* 작성한 쉐이더 소스 코드는 쉐이더 객체로 바뀌어 컴파일 되고, 여러 쉐이더 객체들이 하나의 프로그램 객체로 링크된다.
예제1) 첫번째 버텍스 쉐이더
1 2 3 4 5 6 | #version 430 core void main(void) { gl_Position = vec4(0.0, 0.0, 0.5, 1.0); } | cs |
- #version 430 core : shader language 4.3 사용, OpenGL Core profile 사용
- main : 쉐이더 시작 부분, 일반적인 C프로그램과 동일, 단 main 함수는 인자가 없다.
- gl_Position : gl_로 시작하는 모든 변수는 OpenGL의 일부이며 쉐이더와 다른 부분 또는 고정함수 기능의 여러 부분과 연결하는 역할
gl_Position은 vertex의 출력 위치를 나타낸다.
- vec4(0.0, 0.0, 0.5, 1.0) : OpenGL의 클립 공간(Clip Space)의 중앙에 위치
*클립공간 : OpenGL 파이프라인의 다음 스테이지에서 적용되는 좌표계
예제2) 첫번째 프래그먼트 쉐이더
1 2 3 4 5 6 7 8 | #version 430 core out vec4 color; void main(void) { color = vec4(0.0, 0.8, 1.0, 1.0); } | cs |
- out : color 변수를 출력 변수로 선언, 출력 변수값은 윈도우나 화면으로 보내진다.
- vec4(0.0, 0.8, 1.0, 1.0) : r, g, b, a 의미, 청록색
이제 실행시켜보자...실행은 SDL2와 OpenGL을 이용하여 사용할 예정이다.
아래에서 간단하게 세팅은 확인할 수있다. (SDL2+GL 기본 프레임워크 기반에서 수정해나가자)
SDL을 사용하는 이유는 SDL이 GL을 사용하는데 있어서 간단하고, 샘플코드도 직관적으로 이해하기 쉽기 때문이다.
무엇보다 나한테 익숙하단 장점이 있다...ㅎㅎ
이제 위의 쉐이더 코드를 사용하기 위해 SDL2+GL 기본 프레임워크에서 compile_shaders() 함수를 추가하자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | GLuint compile_shaders(void) { GLuint vertex_shader; GLuint fragment_shader; GLuint program; //vertext shader source code static const GLchar * vertex_shader_source[] = { "#version 430 core \n" " \n" "void main(void) \n" "{ \n" " gl_Position = vec4(0.0, 0.0, 0.5, 1.0); \n" "} \n" }; //fragment shader source code static const GLchar * fragment_shader_source[] = { "#version 430 core \n" " \n" "out vec4 color; \n" " \n" "void main(void) \n" "{ \n" " color = vec4(0.0, 0.8, 1.0, 1.0); \n" "} \n" }; //create vertex shader and compile vertex_shader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); glCompileShader(vertex_shader); //create fragment shader and compile fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); glCompileShader(fragment_shader); //create program->attach shader->link program = glCreateProgram(); glAttachShader(program, vertex_shader); glAttachShader(program, fragment_shader); glLinkProgram(program); //delete shader, 프로그램이 쉐이더를 소유하므로 삭제 필요 glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); return program; } | cs |
create_shaders()는 작성한 shader source code를 이용하여 쉐이더를 생성 후 컴파일한다.
이후 생성한 쉐이더를 프로그램에 붙이고 링크, 생성된 프로그램을 리턴한다.
1) glCreateShader() : 빈 쉐이더 객체 생성, 소스를 받은 후 컴파일
2) glShaderSource() : 쉐이더 소스코드를 쉐이더 객체로 전달 후 복사본 유지
3) glCompileShader() : 쉐이더 객체에 포함된 소스코드 컴파일
4) glCreateProgram0 : 쉐이더 객체에 attach시킬 프로그램 객체 생성
5) glAttachShader() : 쉐이더 객체를 프로그램 객체에 어태치
6) glLinkProgram() : 프로그램 객체에 어태치된 모든 쉐이더 객체 링크
7) glDeleteShader() : 쉐이더 객체를 삭제
*쉐이더 프로그램 객체에 링크되면 프로그램이 바이너리 코드를 보관하며 쉐이더는 필요하지 않는다.
사용자는 생성한 프로그램을 glUseProgram()을 호출하여 사용하면 된다.
1 2 3 4 5 | static const GLfloat red[] = {1.0f, 0.0f, 0.0f, 1.0f}; glClearBufferfv(GL_COLOR, 0, red); glUseProgram(rendering_program); glDrawArrays(GL_POINTS,0, 1); SDL_GL_SwapWindow(win); | cs |
- glUseProgram() : OpenGL에 해당 프로그램 객체를 사용하여 렌더링 시킨다.
- glDrawArrays() : mode : 어떤 타입의 프리미티브로 그릴지 설정(GL_POINTS, GL_LINES, GL_TRIANGLES)
-> drawing명령어로 vertex를 파이프라인으로 보내게 된다.
1 2 3 | void glDrawArrays( GLenum mode, GLint first, GLsizei count); | cs |
이대로 프로그램을 실행시켜도 이전과 차이가 없는데, 점의 크기가 너무 작아서 그렇다.
메인루프 이전에 점의 크기를 키워주는 glPointSize()를 호출해준다.
1 | glPointSize(40); | cs |
다시 실행시키면 아래와 같이 나오는 걸 볼 수 있다.
'Software Development > Graphics' 카테고리의 다른 글
OpenGL Super Bible 그래픽스 공부하기 - 2.3 처음 그리는 삼각형 (0) | 2018.01.14 |
---|---|
우분투 환경에서 SDL2 + GL 설정하고 빌드해보기 (0) | 2018.01.14 |
OpenGL Super Bible 그래픽스 공부하기 - 1. OpenGL 기본개념이해 (0) | 2018.01.13 |
[Unity] Unity Build Error_Bundle Identifier has not been set up correctly (0) | 2016.03.26 |
[Unity] 3. Unity 조작하기 (0) | 2016.03.26 |