2014-03-29 2 views
1

어레이의 Vertex 구조체에 제공된 완전한 정점 데이터가 있다고 가정합니다. 버텍스 쉐이더에 데이터를 보내기 위해서, 을 호출하여 Vertex 멤버와 셰이더의 매개 변수 사이의 올바른 매핑을 설정해야합니다.glVertexAttribPointer 템플릿의 멤버 오프셋 가져 오기

오픈 템플릿 함수 glVertexAttribPointer을 멋진 템플릿 방식으로 캡슐화하려고합니다.

glVertexAttribPointer

specification에 따라 다음 인수를 고려 GPU를 CPU에서 데이터 업로드 유형 설명의 일종으로 역할 :

  • GLUint index - 핸들을
  • GLint size - 구성 요소의 수 (대한 무관 이 문제)
  • GLenum type - 타입 (GL_FLOAT, GL_SHORT을 represeting 열거 값 등)
  • GLboolean normalized - [0..1] 또는 [-1..1] 로의 정규화 (이 문제와 관련 없음)
  • GLsizei stride - 연속 된 정점 요소 간 바이트 차이. 내 경우에는 그 크기가 Vertex입니다.
  • const GLvoid* pointer - 데이터 시작과 관련하여 첫 번째 요소에 대해 오프셋. 제 경우에는, 그것은 Vertex의 시작과 관련하여 회원의 상쇄가 될 것입니다.

나는 다음과 같은 해결책을 온 내 목표를 달성하기 opengl_type

template <typename WholeVertex, typename Element> 
void attribute(GLuint shaderProgram, const char* name, Element WholeVertex::* memberPointer) { 
    GLint handle = glGetAttribLocation(shaderProgram, name); 
    glVertexAttribPointer (
     handle, 
     opengl_type<Element>::arity, 
     opengl_type<Element>::type, 
     GL_FALSE, 
     sizeof(WholeVertex), 
     (const GLvoid*)(memberPointer) //error 
    ); 
} 

A A 지정된 형태에 대한 올바른 GLenum 값을 계산 내 자신의 특성 클래스입니다.

불행히도이 솔루션은 멤버 포인터가 단지 정수 오프셋이고 캐스팅 될 수 있다고 가정합니다. (const GLvoid*)입니다. 내 지식으로는 WholeVertexstandard layout이 있다는 가정하에 사실입니다. 아직도, 일반적인 경우에 그것은 사실이 아닐 수도 있고 컴파일러는 이런 종류의 캐스트를 완성하는 것을 금지합니다. 사실 객체가없는 memberPointer으로는 아무 것도 할 수 없습니다.

내가 원하는 것을 계산할 수있는 매크로와 비슷한 기능을 가진 매크로가 있다는 것을 알았지 만, 멤버 이름이 인수로 사용되므로 이름을 알 수없는 경우 사용할 수 없게됩니다.

그렇다면이 래퍼 함수를 ​​구현하는 방법에 대해 알고 계신가요? 아마도 오프셋을 계산하는 다른 방법일까요? 또는 그것을 다른 종류의 매개 변수로 전달할 수 있습니까?

+0

'Element WholeVertex :: * memberPointer'는 실제로 나를 혼란스럽게하지만, 구조체의 멤버에게 포인터를 전달하고있는 것 같습니다. 구조체의 첫 번째 요소 주소를 알고 있다면 할 수 있습니다. 오프셋을 계산하기위한 포인터 연산. 구조체의 멤버 이름을 모른 채 쉽게이 작업을 수행 할 수 있지만 추가 포인터를 어딘가에 저장해야합니다. –

+0

'attribute'와 궁극적으로'glVertexAttribPointer'는 실제 데이터에서 작동하지 않습니다 (따라서'this' 포인터 나 첫 번째 요소에 대한 포인터가 없습니다). 이 함수들은 단순히 실제 데이터가 제공되기 전에 GL 시스템에 오프셋을 알리는'WholeVertex' 타입을 기술합니다. – CygnusX1

+0

@Andron : '.. 날 믿어.'예. 그것은 멤버에 대한 (오프셋 된) 포인터이다. 하나는'& MyVertex :: nx'와 같은 형태로 전달 될 수 있는데,'.nx'는 일부 struct MyVertex에서 일반적인 데이터 멤버의 시작이됩니다. CygnusX1이 지적했듯이. 그것은 MyVertex 형식의 인스턴스화 된 객체와 아무런 관련이 없습니다. – violet313

답변

1

멤버 포인터의 constance에서 벗어나는 것은 쉽지 않습니다.

것은이 매우 해킹 좋아하지 않을 것이다 그러나 그것은 작동합니다

template <typename WholeVertex, typename Element> 
void attribute(GLuint shaderProgram, const char* name, Element WholeVertex::* memberPointer) 
{ 
    GLint handle = glGetAttribLocation(shaderProgram, name); 

    GLvoid *offset=0; 
    memcpy(&offset, &memberPointer, sizeof(GLvoid*)); 

    printf("ooook:%p\n",offset); 

    glVertexAttribPointer (
     handle, 
     opengl_type<Element>::arity, 
     opengl_type<Element>::type, 
     GL_FALSE, 
     sizeof(WholeVertex), 
     offset 
    ); 
} 


아마도 노조 캐스트 해킹 사용하여보다 바람직한 방법 (원하는대로 그래서 아마 아직도 비 규격을 중) :

template <typename WholeVertex, typename Element> 
void attribute(GLuint shaderProgram, const char* name, Element WholeVertex::* memberPointer) 
{ 
    GLint handle = glGetAttribLocation(shaderProgram, name); 

    union 
    { 
     Element WholeVertex::* x; 
     GLvoid* y; 
    } 
    offset; 

    offset.x=memberPointer; 

    glVertexAttribPointer (
     handle, 
     opengl_type<Element>::arity, 
     opengl_type<Element>::type, 
     GL_FALSE, 
     sizeof(WholeVertex), 
     offset.y 
    ); 
} 


& 마지막으로, de-referencing하여 포인터 (:/정지 해킹을하지만) : null로

이러한 해킹 방어에서3210
GLvoid* offset=reinterpret_cast<GLvoid*>(&((static_cast<WholeVertex*>(NULL))->*memberPointer)); 


:

  1. 나의 이해는 POD 객체에 대해, 현재의 C++ 표준 memberPointer의 값이 간단한 오프셋 계산됩니다 을 보장한다는 것입니다.

  2. glVertexAttribPointer은 하위 호환성을 유지하려고 시도 할 때 시간이 지나면 끔찍한 유산을 가진 API입니다. 비 호환 수단이 허용됩니다.

+0

이 모든 것은 멤버 포인터의 바이너리 표현이 바이트 단위로 오프셋되어 있다는 사실에 크게 의존합니다. 좋은 가정은 아닙니다. – lisyarus

+0

@lisyarus : duh. 'offsetof' 매크로 *는 그 자체로 비 POD 타입에서 실패하는 해킹입니다. 어쨌든 더 조심스럽게 영업 이익을 읽으십시오 .. – violet313

+0

downvotes grrr 무슨 고통 : 1) downvoter, 만약 당신이 lisyarus pls 이유를 설명하지; 2) @lisyarus FTR, 귀하의 제안 된 답변이 여기에 귀하의 의견과 OP 요구 사항에 따라 분명히 터무니없는 수준이지만, 여전히 기술적으로 올바르지 않습니다. 그래서 나는 * 당신을 downvote하지 않았다 (다만 말하는). – violet313

관련 문제