Vertex Shader
#version 330 core //OpenGL 버전(330 => 3.3 버전)
//Vertex Shader은 vec3타입의 데이터를 aPos라는 변수로 받는다. 이 입력 변수의 위치는 0.
layout (location = 0) in vec3 aPos; //0: 입력변수 위치. aPos: vertex shader 입력 변수 타입
void main()
{
//gl_Position : vertex shader 출력 변수. vec4 타입(vec3아님!!)
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
Vertex Buffer Object(VBO)
unsigned int VBO;
glGenBuffers(1, &VBO); //(생성할 버퍼 오브젝트 네임의 개수, 생성한 버퍼 오브젝트 네임을 저장할 변수의 주소값)
glBindBuffer(GL_ARRAY_BUFFER, VBO); //(바인딩하는 버퍼 오브젝트의 사용 방법, 바인딩할 버퍼 오브젝트)
- Vertex 데이터를 저장하기 위한 GPU의 메모리, 버퍼
- glGenBuffers를 통해 VBO를 생성함
- Vertex 버퍼객체의 유형은 GL_ARRAY_BUFFER 등 여러가지로 glBindBuffer 함수로 설정
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
- glBufferData 함수 : 어떤 버퍼로부터 데이터를 복사해올 것인지 복사해올 버퍼를 지정하는 작업
- 변수 등을 통해서 정의된 vertex 데이터를 버퍼 메모리로 복사
- 첫번째 인자: 복사할 버퍼 유형
- 두번째 인자: 복사할 버퍼의 크기
- 세번째 인자: 복사할 데이터 주소
- 네번째 인자: GL_STREAM_DRAW: 데이터가 한번만 지정되고 GPU가 수회 사용 GL_STATIC_DRAW: 데이터가 한번만 지정되고 GPU가 여러 번 사용 GL_DYNAMIC_DRAW: 데이터가 자주 변하고 GPU가 여러 번 사용
Vertex Shader Compile
unsigned int vertexShader
vertexShader=glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
- glCreateShader
- Vertex shader, geometry shader, fragment shader 객체를 생성. GL_VERTEX_SHADER는 vertex shader 생성
- glShaderSource
- 생성한 셰이더에 셰이더가 실행할 GLSL 프로그램 소스코드를 지정(생성한 셰이더, 입력 문자열의 개수, Shader string 주소, 문자열들의 길이 배열)
- glCompileShader
- 셰이더 컴파일
Fragment Shader
#version 330 core
out vec4 FragColor; //vec4: fragment shader 출력 변수 타입
void main()
{
FragColor = vec4(1.0f, 0.5, 0.2f, 1.0f); //출력 색상, 출력 알파값
}
Fragment Shader Compile은 앞에 Vertex Shader Compile이랑
glCreateShader(GL_FRAGMENT_SHADER); 입력인자가 다른거 말고는 동일
Shader Program
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
여러 개의 shader가 링크된 최종 버전의 프로그램 객체
객체를 렌더링할 때 shader program을 활성화해 실행
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram); //Vertex Shader와 Fragment Shader를 한번에 링크
컴파일된 shader들을 프로그램으로 링크할때, 각 shader의 입출력 형식이 같아야됨.
다르면 링크 에러 발생
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
Shader program에 링크된 후 shader 객체는 삭제해도 됨
while (!glfwWindowShouldClose(pWindow)) {
...
glUseProgram(shaderProgram);
...
}
링크된 shader program 객체는 렌더링 루프에서 glUseProgram 함수를 호출하여 활성화
Linking Vertex Attributes
[예제 1]
- Vertex 위치(좌표) 데이터는 float(4 byte) 형식으로 저장
- 예시에서 각 vertex 좌표는 3개의 float 값(x, y, z)로 구성
- 1차원 배열에 담겨있는 이 정보를 3개씩 끊어서 써야한다고 알려줘야됨
- Vertex 사이에 다른 데이터는 들어가지 않음
- 예시에서 vertice 포인터에서 offset은 0
glVertexAttribPointer : 속성 지정해주는 함수
- 데이터 구분 번호 = 속성의 인덱스
- layout(location = 0) in vec3 aPos; 에서 location에 해당
- vertex 구성 요소의 수 ⇒ x,y,z 이므로 3개
- vertex data type ⇒ float 형 데이터
- 정규화 플래그 : 각 데이터를 normalize할지 그대로 쓸지
- stride : vertex마다 사용할 데이터의 간격.
- float 형 3개 ⇒ 4 * 3 =12
- 시작 위치 ⇒ 0부터 시작하므로 (void*) 0
- 만든 속성은 glEnableVertexAttrbArray() 함수를 사용해 VAO에 등록
[예제 2]
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
색상을 뽑아냄 ⇒ 처음 offset에 12를 주어 12byte를 건너뛴 위치부터 3개씩 가져옴
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)3*sizeof(float));
glEnableVertexAttribArray(1);
Vertex Array Object (VAO)
VAO : vertex array 속성에 대한 설정을 저장하고 있는 object
unsigned int VAO;
glGenVertexArrays(1, &VAO); //1. vertex array 객체 생성
// 1. bind Vertex Array Object
glBindVertexArray(VAO); //2. vertex array 객체 바인드
// 2 copy our vertices array in a buffer for OpenGL to use
glBindBuffer(GL_ARRAY_BUFFER, VBO); //3. vertex buffer 객체 바인드&vertex data 할당
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//4. 데이터에서 입력 속성 범위 설정
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
vertex attributes pointer 속성 호출을 한번 VAO에 바인드하고, 렌더링 루프에서 해당 VAO에 바인드하면 렌더링됨.
while (!glfwWindowShouldClose(pWindow)) {
..
glUseProgram(shaderProgram); //Shader 프로그램 설정
glBindVertexArray(VAO); //입력 VAO 바인드(입력 데이터 설정)
glDrawArrays(GL_TRIANGLES, 0, 3); //Drawing
...
}
Element Buffer Object (EBO)
OpenGL이 vertex를 그리는 순서에 대한 인덱스를 저장하는 버퍼
VBO 바인드할 때 EBO를 함께 바인드
unsigned int EBO;
glGenBuffers(1, &EBO); //버퍼 생성, 데이터 할당은 VBO와 동일
:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); //차이! VBO는 GL_ARRAY_BUFFER
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
while(!glfwWindowShouldClose(pWindow)){
:
//(무엇을 그릴지, 인덱스 수, 인덱스 타입, 인덱스 오프셋)
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); //차이! VBO는 glDrawArrays
:
}
'강의 > HCI' 카테고리의 다른 글
[HCI] Graphics & OpenGL 4 (0) | 2025.04.22 |
---|---|
[HCI] Graphics & OpenGL 3 (0) | 2025.04.03 |
[HCI] Graphics & OpenGL 1 (1) | 2025.03.26 |