2018년 3월 26일 월요일

5.1.3 버퍼로부터 버텍스 쉐이더에 입력 전달하기


  1. 버텍스 배열 객체 (VAO : Vertex Array Object)
    1. 생성 및 바인딩
      1. GLuint vao;
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);
    2. 상태 설정
      1. glVertexAttribPointer
        1. void glVertexAttribPointer(GLuint index,
          GLint size,
          GLenum type,
          GLboolean normalized,
          GLsizei stride,
          const GLvoid * pointer);
          1. index : 버텍스 속성의 인덱스
            1. 셰이더에서 location index
            2. #version 430 core
              layout (location = 0) in vec4 offset;
              ~
          2. size : 각 버텍스에 대해 버퍼에 저장된 컴포넌트의 개수
          3. type: 데이터 타입
          4. normalized: 데이터를 정규화 할 것인지 (0.0~1.0 사이)
          5. stride: 버텍스 데이터의 시작과 다음 시작점 사이에 얼마나 많은 바이트가 있는지
          6. pointer: GL_ARRAY_BUFFER에 바인딩된 버퍼상에서 버텍스  속성데이터가 시작하는 위치에 대한 오프셋
        2. Example
          1. glBindBuffer(GL_ARRAY_BUFFER, buffer);
            glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
            1. 속성 0
            2. 4 컴포넌트
            3. 부동소수점
            4. 정규화 안함
            5. 촘촘히 패킹된 데이터
            6. 오프셋 0 (NULL 포인터)
        3. Shader
          1. #version 430 core

            layout (location = 0) in vec4 position;

            void main(void)
            {
              gl_Position = position;
            }
            1. 하드 코딩된 데이터가 삭제되고, position에 버텍스 데이터가 들어가게 된다.
    3. 설정
      1. void glEnableVertexAttribArray(GLuint index);
      2. 버퍼의 데이터를 사용해서 버텍스 속성을 채우라고 지시
      3. 몇 번째 인덱스의 속성을 활성화 할 것인지 설정 (셰이더의 속성 활성화)
    4. 해제
      1. void glDisableVertexAttribArray(GLuint index);
      2. 버텍스 속성 채우기 후 호출하여 속성 비활성화
    5. 그 외
      1. 여러 개의 버텍스 쉐이더 입력 사용하기
        1. Shader Example
          1. layout (location = 0) in vec3 position;
            layout (location = 1) in vec3 color;
        2. 입력 위치 알아내기
          1. glGetAttribLocation
            1. GLint glGetAttribLocation(GLuint program,
              const GLchar *name);
              1. program: 버텍스 쉐이더 프로그램
              2. name: 속성 이름 (쉐이더 내 변수명)
          2. 위의 쉐이더에서 "position"시 0을, "color"시 1을 리턴. 그 외에는 -1 리턴
          3. 쉐이더 코드에 위치를 설정하지 않은 경우, OpenGL이 자동으로 설정해주며 이 경우 위 함수를 사용하여 위치를 알아내야 한다.
      2. 버텍스 쉐이더 입력을 데이터로 연결시키는 방법
        1. 독립 속성
          1. 다른 버퍼에 위치해 있을 수 있거나, 적어도 동일한 버퍼에서 다른 위치에 있는 경우
          2. Example
            1. GLuint buffers[2];

              static const GLfloat positoins[] = {...};
              static const GLfloat colors[] = {...};

              glGenBuffers(2, &buffers);

              // positions(0)
              glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
              glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);
              glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
              glEnableVertexAttribArray(0);

              // colors(1)
              glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
              glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
              glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
              glEnableVertexAttribArray(1);
          3. 두 속성에 값을 전달하기 위해 촘촘히 패킹된 데이터 배열을 사용
          4. 배열-구조체 (SoA : Structure of Arrays) 데이터 라고 함.
        2. 인터리브 속성
          1. 구조체-배열 (AoS : Array of Structures) 데이터 사용
            1. struct vertex
              {
                float x;
                float y;
                float z;

                float r;
                float g;
                float b;
              }
            2. 두 개의 입력이 단일 구조체 안에 번갈아 들어 있음.
            3. stride 인자를 사용해야 한다.
          2. Example
            1. GLuint buffer;

              static const GLfloat vertices[] = {...};

              // 버퍼 객체 할당 및 초기화
              glGenBuffers(1, &buffer);
              glBindBuffer(GL_ARRAY_BUFFER, buffer);
              glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

              // position(0)
              glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (void *)offsetof(vertex, x));
              glEnableVertexAttribArray(0);

              // colors(1)
              glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (void *)offsetof(vertex, r));
              glEnableVertexAttribArray(1);
      3. 파일로부터 객체 로딩하기
        1. 모델 데이터를 파일에 저장하고 애플리케이션으로 로딩하는 방법

댓글 없음:

댓글 쓰기