2017-12-03 3 views
2

나는 혼란스러워하는 것을 접했지만 그 답을 찾을 수 없습니다. 나는이 같은 쉐이더를 쓸 때 :유니폼 및 변형을위한 OpenGL 및 GLSL 메모리 정렬

layout (location = 0) in vec3 inPosition; 
layout (location = 1) in vec3 inNormal; 
layout (location = 2) in vec2 inTexCoords; 

을 나는 VEC3의의 많은의이 vec4, 또는 SIMD 호환 가능한 데이터 유형으로 정렬 16 바이트 아니라는 것을 알고있다.

struct Vertex 
{ 
    vec3 position; 
    vec3 normal; 
    vec2 texCoords; 
}; 

각 벡터는 크기가 8 *의를 sizeof (플로트), 32 바이트 인, 아니 패딩, 서로 꼭 앉아 내 C++ 코드 내 데이터이기 때문에 나는, (내가 생각하는)이 알고있다. 나는 그것을 유니폼에 전달하고 쉐이더는 그것을 잘 읽습니다, 그래서 그들은 둘 다 정렬되어 있습니다.

그러나 그것은 또 다른 VEC3 또는 vec4 추가하기 전에 예와 GLSL에서 균일 한 블록에 VEC3이 추가로 4 바이트 패딩해야 std140 표준을 때 : 멤버가 인 경우

  1. 을 N 기본 기계 단위를 소비하는 구성 요소 세 가지 구성 요소 벡터, 기본 정렬은

당신은 또한 압축하는 VEC3와 다음 VEC3 사이에 4 바이트 INT 또는 4 바이트 부울을 저장할 수 있습니다 그러나 4N입니다 크기. 그렇다면 꼭지점 레이아웃의 attrib 포인터 값이 std140 레이아웃을 따르지 않는다는 뜻입니까? 또한 예를 들어, 내 C++ 코드에서 SIMD 16 바이트 정렬 된 벡터를 사용하면 더 이상 attrib 포인터 값을 vec3, vec3, vec2로 설정할 수 없으며 모든 vec4를 가질 수 있습니까?

또한 나는 문서에 다음과 같은 경고를 보았다 :

경고 : 구현 가끔 VEC3 구성 요소에 대한 잘못 std140 레이아웃을 얻을. 구조체/배열을 수동으로 채우고 vec3을 전혀 사용하지 않는 것이 좋습니다.

여기 vec3을 전혀 사용하지 않는 것이 좋지만, vec3 뒤에 int 또는 bool을 4 바이트로 압축하는 것은 공간 절약 기술이라고 생각했습니다.

답변

4

std140 레이아웃은 버퍼 내용이나 인터페이스 블록 외부의 속성이 아닌 interface blocks에만 적용됩니다. 인터페이스 블록은 버텍스 쉐이더의 입력이나 프래그먼트 셰이더의 출력으로 사용할 수 없으므로 std140은 어떤 식 으로든 영향을 미치지 않으며 glVertexAttribPointer이 설정되거나 버텍스 데이터가 저장되는 방식에 영향을 미치지 않습니다.

경고 : 예, vec3 뒤에 공간을 사용하고 int/float/bool을 사용하는 것이 현명한 기술입니다. 그러나 경고 상태에서 드라이버 구현은 때로는 잘못 이해합니다. 따라서 코드가 어디에서나 안정적으로 실행되도록하려면 테스트를 많이하거나 vec3을 전혀 사용하지 않아야합니다. 다시 말하지만, 이는 인터페이스 블록의 경우에만 관련이 있습니다. 일반 vec3 유니폼은 이것으로 만지지 않습니다.

당신이 할 수있는 일은 3 플로트와 int를 C++ 측에 저장하는 것이지만, 인터페이스 블록의 vec4를 통해 액세스 할 수 있습니다. floatBitsToInt(myBlock.myVec4.w)을 사용하여 정수를 검색 할 수 없습니다.

+0

도움이되었습니다. 그 floatBitsToInt 완전히 내 마음을 날려, 처음에는 0 - 255 RGBA를 저장 u8vec4를 찾으려고했는데, 그럼 glsl은 전혀 단일 바이트 데이터 형식을 다루지 않는 것으로 나타났습니다, 그래서 내 다음 아이디어는 int를 보내고 사용하는 것이 었습니다. 비트 연산자를 사용하여 올바른 색상 채널을 출력 할 수 있습니다. – Zebrafish

+0

조금만 기다려 봐. 방금 깨달은 floatBitsToInt 와도 관계가있다. 내 0 - 255 색상이 vec4.w 인 경우 올바른 바이트를 이동하고 추출해야합니다. – Zebrafish