Learn OpenGL

  • 어쩌다 보니 6/30 꺼 복습

Shaders

  • GPU에서 실행되는 작은 프로그램들
  • 특징
    • 위치: CPU가 아닌 GPU에서 실행
    • 역할: 입력을 받아서 변환하여 출력으로 내보내는 변환 프로그램
    • 격리성: shader들은 서로 직접 통신할 수 없고, 오직 입력과 출력을 통해서만 소통
  • why GPU?: GPU는 병렬 처리에 특화되어있음
  • 버텍스 데이터 -> [버텍스 셰이더] -> 기하학적 처리 -> [프래그먼트 셰이더] -> 픽셀 출력

GLSL

  • C와 유사한 언어
// 버전 선언, 사용할 OpenGL 버전 명시
#version 330 core

// 입력 변수(in)
in type aPos; // 위치 데이터
in type aColor; // 색상 데이터
// 출력 변수 (out)
out type out_variable_name; // 다음 셰이더로 전달할 데이터
// 유니폼
uniform type uniform_name; // CPU에서 전달받는 전역 변수
// 모든 처리 로직이 들어가는 main 함수
void main()
{
    // 입력을 처리하고 그래픽 관련 작업 수행
    ...
    // 처리된 결과를 출력 변수에 저장
    out_variable_name = weird_stuff_we_processed;
}
  • C언어와 차이점: 벡터/행렬 연산, 그래픽 전용 함수들, 내장 변수들

Types

  • basic types: int, float, double, uint, bool
  • container types: vectors, matrices
  • float가 대부분의 목적에 충분하기 때문에 vecn을 사용함

Vectors

  • 기본 접근 방법: vec.x -> .x, .y, .z, .w
  • 다양한 접근 방식: 색상(rgba), 텍스처 좌표(stpq)
  • swizzling: 벡터의 구성요소들을 재배열, 복제, 선택하여 새로운 벡터를 만드는 기법, ex) vec.xyxx

Ins and outs

  • 개별 shader들에게 입력과 출력을 가져서 데이터를 주고받을 수 있기를 원함
  • in ,out 키워드로 지정하고, 출력 변수가 다음 shader 스테이지의 입력 변수와 일치하면 데이터가 전달됨

vertext shader의 특별한 점

  1. 입력 데이터
    • vertex data로 부터 직접 입력을 받음
  2. layout 지정자
    • 어느 위치의 데이터를 받을지 알려주는 주소 표시

fragment shader의 특별한 점

  • fragment shader는 vec4 색상 출력 변수가 필요함
  • out 사용은 CPU 코드에서 프레임 버퍼 구성시 정암

Uniforms

  • CPU에서 GPU로 데이터를 전달하는 전역 변수
  • GPU 메모리에 한 번 전송함, constant cache 사용
  • 너무 자주 업데이트, 너무 많으면 성능 문제 발생
  • 선언은 했지만 사용하지 않으면 자동으로 제거됨
  • OpenGL은 C 라이브러리이므로 함수 오버로딩을 지원하지 않음, 타입에 따른 접미사를 붙인 glUniform 함수들이 있음

More Attributes

  • 캐시 효율성을 위해 인터리브드(Interleaved) 데이터를 사용함
  • 메모리 접근 패턴에 의해 분리된 배열보다 효율이 좋음
  • 타입에 무관한 메모리 주소를 가리키기 위해 (void*) 사용

Fragment Interpolation

  • 과정
    • vertex shader 실행
    • primitive를 assemble
    • rasterization이 일어나서 primitive에 해당하는 모든 픽셀을 결정하고, fragment shader 실행
    • rasterization 전에 클리핑이 수행되어 뷰 밖에 있는 모든 프래그먼트를 버려서 성능 향상
  • 보간 과정
    • OpenGL이 해줌
    • 기본적으로 Linear Interpolation
    • GLSL에서 보간 방식을 제어할 수 있음