2014-04-28 2 views
3

(3Ds Max에서 내 보낸) 3D 메시에 필요한 모든 정보가있는 사용자 지정 파일 형식이 있습니다. 버텍스, 버텍스 인덱스 및 법선에 대한 데이터를 추출했습니다.OpenGL - 인덱스 버퍼 문제

나는 OpenGL을에 정점 데이터, 정점의 인덱스 및 법선 데이터를 전달하고 난 지금 보이지만 법선 glDrawElements(GL_TRIANGLES,...)

모두를 호출 메쉬를 렌더링합니다. 문제는 법선이 다른 지수를가집니다. OpenGL은 하나의 인덱스 버퍼만을 사용할 수 있기 때문에 정점과 법선 모두에 인덱스 버퍼를 사용합니다.

나는 그 문제에 대해 어떻게 생각하는지 제안 해 주시면 정말 감사 할 것입니다.

중요한 점은 버텍스/일반 데이터는 "정렬"되어 있지 않으므로 glDrawArrays(GL_TRIANGLES,...)의 기능을 사용할 수 없다는 점입니다. 메시가 올바르게 렌더링되지 않습니다.

메시를 올바르게 그릴 수 있도록 데이터를 정렬하는 데 사용할 수있는 방법/알고리즘이 있습니까 glDrawArrays(GL_TRIANGLES,..)? 그러나 알고리즘이 있더라도 한 가지 더 문제가 있습니다 - 일부 꼭지점을 복제해야합니다 (내 꼭지점 버퍼가 고유 한 꼭지점으로 구성되어 있기 때문에 - 예를 들어 큐브에 8 개의 꼭지점 만있는 경우). 그리고 확실하지 않습니다. 그렇게하는 방법.

+0

"문제는 법선이 다른 인덱스를가집니다." 왜? 법선이 꼭지점과 일치하도록 인덱스 버퍼를 다시 정렬합니다. 더 나은 점은 정점 정보를 인터리브하는 것입니다. –

+0

일부 메시에서는 정점보다 법선이 더 많으므로 인덱스를 일치시킬 방법이 없습니다. 그거 보통입니까? – Geto

+0

아, 그래, 음영 효과의 경우 같은 점에서 다른 법선으로 정점을 얻을 수 있습니다. 속성과 사용중인 파일 형식에 따라 모든 내용이 정렬되도록 데이터를 다시 배열해야합니다. 그러나 지금 당장 당신은 실제로 질문을하지 않았기 때문에 나는 무엇을 대답해야할지 모른다. –

답변

0

내가 무슨 짓을 glDrawArrays(GL_TRIANGLES,..) 와 OpenGL과 인덱스 버퍼를 통과하지 않고 그것을 할 관리 다음과 같다. 그런 다음 정렬 된 데이터로 새 버텍스 및 일반 배열을 만들어 OpenGL에 전달했습니다.

for i = 0; i < vertexIndices.size(); ++i 
    newVertexArray[i] = oldVertexArray[vertexIndices[i]]; 

for i = 0; i < normalsIndices.size(); ++i 
    newNormalsArray[i] = oldNormalsArray[normalsIndices[i]]; 

색인 배열을 채우지 않고 조금 최적화했습니다. 그러나 최적화는 프로그래머가 메쉬 데이터를 읽는 방식에 달려 있습니다.

+4

음, 그렇습니다. 메모리 사용량, 효율성 및 전력 소비에 신경 쓰지 않는다면 간단합니다. 좀 더 규칙적인 메쉬에서 정점은 일반적으로 약 6 개의 삼각형으로 공유됩니다. 인덱스 방식의 버텍스 캐시 히트 레이트에 따라, GPU에서 버텍스 프로세싱에 대한로드의 3-6 배를 생성하고 해당 메모리 대역폭이 증가 할 것으로 기대합니다. 또한 여섯 배나 가까운 메모리를 사용합니다. 인덱스를 사용하여 메시를 만드는 것이 단지 몇 줄의 코드를 필요로한다는 것을 고려할 때, 필자는 그것이 절대적으로 가치가 있다고 생각합니다. –

9

정점 및 법선에 대해 별도의 인덱스를 사용하는 파일 유형은 OpenGL 정점 모델과 매우 직접 일치하지 않습니다. OpenGL은 하나의 인덱스 집합을 사용합니다.

입력에서 고유 (정점 인덱스, 일반 인덱스) 쌍 각각에 대해 OpenGL 정점을 작성해야합니다. 이는 약간의 작업을 필요로하지만 특히 사용 가능한 데이터 구조를 사용하는 경우에는 그리 어렵지 않습니다. STL map은 (정점 인덱스, 일반 인덱스) 쌍을 키로 사용하여 잘 작동합니다. 나는 전체 C++ 코드를 제공하지는 않겠지 만, 그것을 개략적으로 설명 할 수 있습니다.

어떤 종류의 배열/벡터 데이터 구조 inVertices으로 이미 정점을 읽었으며 인덱스가 vertexIdx 인 정점 좌표가 inVertices[vertexIdx]에 저장되어 있다고 가정 해 보겠습니다. 법선 벡터의 경우, normalIdx 인 법선 벡터는 inNormals[normalIdx]에 저장됩니다.

이제 각 삼각형의 각 모서리가 vertexIdxnormalIdx으로 표시되는 삼각형 목록을 읽게됩니다. 정점 및 법선 좌표를 모두 포함하는 새로운 combinedVertices 배열/벡터와 새로운 combinedIndices 색인 목록을 작성합니다. 의사 코드 : 는 정점 배열을 채우기 정점 인덱스 배열, 법선 배열과 법선 인덱스 배열 :

nextCombinedIdx = 0 
indexMap = empty 
loop over triangles in input file 
    loop over 3 corners of triangle 
     read vertexIdx and normalIdx for the corner 
     if indexMap.contains(key(vertexIdx, normalIdx)) then 
      combinedIdx = indexMap.get(key(vertexIdx, normalIdx)) 
     else 
      combinedIdx = nextCombinedIdx 
      indexMap.add(key(vertexIdx, normalIdx), combinedIdx) 
      nextCombinedIdx = nextCombinedIdx + 1 
      combinedVertices.add(inVertices[vertexIdx], inNormals[normalIdx]) 
     end if 
     combinedIndices.add(combinedIdx) 
    end loop 
end loop 
+0

고마워요, 오늘 그걸 시도해 볼게요. – Geto