>

OpenGL 4.3 및 OpenGL ES 3.1은 정점 배열을 지정하기위한 몇 가지 대체 함수를 추가했습니다. glVertexAttribFormat glBindVertexBuffers 등. 그러나 이미 정점 배열을 지정하는 함수가있었습니다. 즉 glVertexAttribPointer .

<올>
  • 이전 API와 동일한 기능을하는 새로운 API를 추가해야하는 이유

  • 새로운 API는 어떻게 작동합니까?


    • 답변 # 1

      glVertexAttribPointer  두 가지 결함이 있는데 그 중 하나는 반 주제이고 다른 하나는 목표입니다.

      첫 번째 결함은 GL_ARRAY_BUFFER 에 대한 의존성입니다 . 이것은 glVertexAttribPointer 의 행동을 의미합니다   GL_ARRAY_BUFFER 에 묶인 무엇이든에 달려있다  그것이 호출되었을 때. 그러나 일단 그것이 호출되면 GL_ARRAY_BUFFER 에 바인딩됩니다  더 이상 중요하지 않습니다. 버퍼 객체의 참조는 VAO에 복사됩니다. 이 모든 것은 반 경험이 많은 사용자에게도 직관적이지 않고 혼란 스럽습니다.

      또한 정수 바이트 오프셋이 아닌 "포인터"로 버퍼 객체에 오프셋을 제공해야합니다. 이것은 정수에서 포인터로의 어색한 캐스트를 수행함을 의미합니다 (드라이버의 똑같이 어색한 캐스트와 일치해야 함).

      두 번째 결함은 논리적으로 완전히 분리 된 두 가지 작업을 병합한다는 것입니다. OpenGL이 읽을 수있는 꼭짓점 배열을 정의하려면 다음 두 가지를 제공해야합니다.

      메모리에서 데이터를 가져 오는 방법

      그 데이터의 모습

      glVertexAttribPointer  이 두 가지를 동시에 제공합니다. 와이즈 비즈  버퍼 객체와 오프셋 "포인터"및 보폭은 데이터가 저장되는 위치와 데이터를 가져 오는 방법을 정의합니다. 다른 매개 변수는 단일 데이터 단위의 모양을 설명합니다. 이것을 배열의 꼭짓점 형식이라고하겠습니다.

      실제로 사용자는 정점 형식보다 정점 데이터의 위치를 ​​변경할 가능성이 훨씬 높습니다. 결국 장면의 많은 오브젝트는 동일한 방식으로 정점을 저장합니다. 어떤 식 으로든 위치는 3 개의 부동 소수점, 색상은 4 개의 부호없는 바이트, 텍스 코드의 부호없는 2 개의 반바지 등입니다. 일반적으로 몇 가지 정점 형식 만 있습니다.

      데이터를 가져 오는 훨씬 더 많은 위치가 있습니다. 객체가 모두 동일한 버퍼에서 온 경우에도 객체에서 객체로 전환하기 위해 해당 버퍼에서 오프셋을 업데이트하려고 할 수 있습니다.

      GL_ARRAY_BUFFER 와 함께 오프셋 만 업데이트 할 수 없습니다. 전체 format + buffer 정보를 한 번에 지정해야합니다. 매번

      VAO는 객체마다 모든 호출을해야하는 것을 완화 시키지만 실제로 문제를 해결하지는 않습니다. 확실히, 당신은 실제로 glVertexAttribPointer 를 호출 할 필요가 없습니다 . 그러나 정점 형식 변경이고가라는 사실은 바뀌지 않습니다.여기서 논의한 것처럼 정점 형식을 변경하는 것은 비용이 많이 듭니다. 새 VAO를 바인딩 할 때 (또는 새 VAO를 바인딩 한 후 렌더링 할 때) 구현시 정점 형식에 관계없이 정점 형식을 변경하거나 두 VAO를 비교하여 정점 형식이 다른지 확인해야합니다. 어느 쪽이든, 할 필요가없는 일을하고 있습니다.

      glVertexAttribPointer  그리고 glVertexAttribFormat  이 두 문제를 해결하십시오. 와이즈 비즈  직접 버퍼 객체를 지정하고 바이트 오프셋을 실제 (64 비트) 정수로 사용합니다. 따라서 glBindVertexBuffer 를 어색하게 사용하지 않습니다.  제본;바인딩은 버퍼 객체 조작에만 사용됩니다.

      그리고 두 개의 분리 된 개념은 이제 별도의 함수이므로, 형식을 저장하고 바인딩 한 다음 렌더링하는 각 객체 또는 객체 그룹에 대해 정점 버퍼를 바인딩하는 VAO를 가질 수 있습니다. 정점 버퍼 바인딩 상태를 변경하는 것이 정점 형식 상태보다 저렴합니다.

      이 구분은 GL 4.5의 직접 상태 액세스 API로 공식화되어 있습니다. 즉, glBindVertexBuffer 의 DSA 버전이 없습니다. ; GL_ARRAY_BUFFER필요해야합니다  다른 별도 형식 API도 있습니다.

      <시간> 별도의 속성 바인딩 함수는 다음과 같이 작동합니다. 와이즈 비즈  함수는 속성에 대한 모든 정점 형식 매개 변수를 제공합니다. 각 매개 변수는 glVertexAttribPointer 에 대한 동등한 호출의 매개 변수와 정확히 동일한 의미를 갖습니다. .

      상황이 약간 혼동되는 부분은 glVertexArrayAttribFormat 입니다. .

      첫번째 매개 변수는 색인입니다. 그러나 이것은 속성 위치가아닙니다. 버퍼 바인딩 포인트 일뿐입니다. 자체 최대 제한이있는 속성 위치에서별도의 배열입니다. 따라서 버퍼를 인덱스 0에 바인딩한다는 것은 속성 위치 0이 데이터를 가져 오는 위치에 대한아무것도을 의미합니다.

      버퍼 바인딩과 속성 위치 사이의 연결은 glVertexAttrib*Format 에 의해 정의됩니다. . 첫 번째 매개 변수는 특성 위치이고 두 번째 매개 변수는 해당 특성의 위치를 ​​가져올 버퍼 바인딩 인덱스입니다. 함수 이름은 "VertexAttrib"로 시작하므로이를vertex 형식상태의 일부로 간주하여 변경하는 데 비용이 많이 듭니다.

      오프셋의 특성은 처음에는 약간 혼란 스러울 수 있습니다. 와이즈 비즈  오프셋 매개 변수가 있습니다. 그러나 glVertexAttrib*Pointer 도 마찬가지입니다.. 그러나 이러한 오프셋은 다른 의미를 갖습니다. 차이점을 이해하는 가장 쉬운 방법은 인터리브 된 데이터 구조의 예를 사용하는 것입니다.

      glBindVertexBuffer
      
      
      정점 버퍼 바인딩 오프셋은 버퍼 객체의 시작에서 첫 번째 정점 인덱스까지의 바이트 오프셋을 지정합니다. 즉, 인덱스 0을 렌더링하면 GPU가 버퍼 객체의 주소 + 바인딩 오프셋에서 메모리를 가져옵니다.

      정점format오프셋은 각vertex의 시작에서 특정 속성의 데이터까지의 오프셋을 지정합니다. 버퍼의 데이터가 glVertexAttribBinding 에 의해 정의 된 경우 이면 각 속성의 오프셋은 다음과 같습니다.

      glVertexAttribFormat
      
      

      따라서 정점 0이 메모리에있는 곳에 바인딩 오프셋이 정의되고, 형식 오프셋은 각 속성의 데이터가 정점에서에서 오는 위치를 정의합니다.

      마지막으로 이해해야 할 것은 버퍼 바인딩이stride이 정의 된 위치입니다. 이상하게 보일 수 있지만 하드웨어 관점에서 생각하십시오.

      버퍼 바인딩은 꼭짓점 인덱스 또는 인스턴스 인덱스를 메모리 위치로 변환하기 위해 하드웨어에 필요한 모든 정보를 포함해야합니다. 완료되면 정점 형식은 해당 메모리 위치의 바이트를 해석하는 방법을 설명합니다.

      이 또한 인스턴스 제수가 glBindVertexBuffer 를 통해 버퍼 바인딩 상태의 일부인 이유입니다. . 인스턴스 인덱스를 메모리 주소로 변환하려면 하드웨어가 제수를 알아야합니다.

      물론 이것은 더 이상 보폭을 계산하기 위해 OpenGL에 의존 할 수 없다는 것을 의미합니다. 위의 캐스트에서는 단순히 struct Vertex { GLfloat pos[3]; GLubyte color[4]; GLushort texCoord[2]; }; 를 사용합니다. .

      별도의 속성 형식은 이전 Vertex 를 완전히 포함합니다.  이전 함수가 이제 완전히 새로운 용어로 정의되도록 모델을 잘 모델링하십시오.

      glVertexAttribFormat(0, ..., offsetof(Vertex, pos)); //AKA: 0
      glVertexAttribFormat(1, ..., offsetof(Vertex, color)); //Probably 12
      glVertexAttribFormat(2, ..., offsetof(Vertex, texCoord)); //Probably 16
      
      
      이 동등한 함수는 속성 위치 및 버퍼 바인딩 색인에 동일한 색인 값을 사용합니다. 인터리브 된 속성을 수행하는 경우 가능하면이를 피해야합니다. 대신 동일한 버퍼에서 인터리브 된 모든 속성에 단일 버퍼 바인딩을 사용하십시오.

      glVertexBindingDivisor

    관련 자료

  • 이전 Android 개발에 Java 8을 사용할 수 있습니까?
  • 다음 Chrome DevTools 기기가 연결되었을 때 기기를 감지하지 못합니다