Data Shader와 함께 사용하기 위해 OpenGL 인덱스 버퍼 배열에서 여러 텍스처를 어떻게 처리합니까?
-
16-09-2019 - |
문제
나는 구현을 시도하고있다 이 종이. 나는 대부분의 것이 있지만, 기하학적 모서리를 결정하고 표시하는 데 사용하기 위해 임의의 비 초 지명 데이터를 셰이더로 전송하는 것에 대한 부분은 문제를 일으킨다. VBOS에 대해 알고있는 것을 사용하여 대부분의 데이터를 잘 보냈습니다. 그러나 많은 양의 데이터를 보내야하므로 여러 텍스처 좌표를 사용해야합니다.
나는 이미 여러 세트의 텍스처 좌표를 설정하는 올바른 방법이라고 생각하는 몇 가지 변형을 이미 구현했으며 많은 포럼 포스터의 지침을 따랐습니다. 지금까지 솔루션이 작동하지 않습니다.
컨텍스트를 위해이 프로그램은 모델의 각 고유 한 가장자리에 대해 4 개의 정점, 2 개의 정상 벡터, 플로트 및 정수 (플로트로 저장)의 거의 동일한 사본 4 개를 보내고 있습니다. 나는 다음과 같은 데이터를 배치했습니다.
v0 is stored in gl_Vertex (vec3)
v1 is stored in gl_Color (vec3)
v2 is stored in gl_MultiTexCoord0 (vec3)
v3 is stored in gl_MultiTexCoord1 (vec3)
n0 is stored in gl_Normal (vec3)
n1 is stored in gl_SecondaryColor (vec3)
r and i are stored in gl_MultiTexCoord2 (vec2)
4 개의 사본의 유일한 차이점은 I 값으로,이 값이 값을 찾을 수있는 경우 정점을 구성하는 방법을 결정하는 데 도움이됩니다.
보시다시피 적어도 3 개의 텍스처 좌표가 필요합니다. 나는 첫 번째로 작동하는 것을 얻을 수 있었지만 (GL_MULTITEXCOORD0)는 잘 어울 렸지만, 그래픽 카드에서는 다음과 같은 텍스처 좌표가 통제 할 수없는 행동을 가지고 있지만 때로는 작동하지 않는 것처럼 보입니다.
내 렌더링 기능은 다음과 같이 보였습니다.
void Mesh::RenderLineEdgesGPU()
{
// Enable client state
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Turn on edge shader
edgeProgram.Activate();
// Link buffers
// v0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
// v1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[1]);
glColorPointer(3, GL_FLOAT, 0, 0);
// v2
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[2]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
// v3
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[3]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
// n0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[4]);
glNormalPointer(GL_FLOAT, 0, 0);
// n1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[5]);
glSecondaryColorPointer(3, GL_FLOAT, 0, 0);
// r and i
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[6]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
// Indicies
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, edgeMeshHandles[7]);
// Draw
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
// Turn off edge shader
edgeProgram.Deactivate();
// Disable client state
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
이것은 나의 원래의 원래였습니다. V0, V1 및 V2에서 확실히 작동합니다. "R과 I"에 효과가있는 것처럼 보이지만 그것은 환상 일 수 있습니다. 아직 N0 또는 N1을 테스트 할 수있는 능력이 없습니다. v3는 확실히 작동하지 않습니다. 보시다시피, 나는 그것들을 포인트로 그리는데, 그들이 거기에 있는지 여부를 알려줍니다 (셰이더를 통해). V0, V1 및 V2가 모두 있습니다. V3에 대해 동일한 작업을 시도하면 원점에서 단일 지점 또는 전혀 아무것도 생성됩니다.
온라인 제안을 살펴본 후 다음은 새로운 설정입니다.
void Mesh::RenderLineEdgesGPU()
{
// Enable client state
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
// Turn on edge shader
edgeProgram.Activate();
// Link buffers
// v0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
// v1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[1]);
glColorPointer(3, GL_FLOAT, 0, 0);
// v2
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[2]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// v3
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[3]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// n0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[4]);
glNormalPointer(GL_FLOAT, 0, 0);
// n1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[5]);
glSecondaryColorPointer(3, GL_FLOAT, 0, 0);
// r and i
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[6]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
// Indicies
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, edgeMeshHandles[7]);
// Draw
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
// Turn off edge shader
edgeProgram.Deactivate();
// Disable client state
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
}
내가 어떻게했는지 주목하십시오 glEnableClientState
/ glDisableClientState
각 텍스처 좌표 목록의 실제 "로드"주변을 호출합니다. 나도 사용합니다 glActiveTextureARB
그리고 glEnable(GL_TEXTURE_2D)
. 나는 그 이유를 이해할 수 있다고 생각하지만 glActiveTextureARB
여기서 필요합니다. 다른 하나는 나를 당황하게합니다. 에 따르면 GLSL 일반적인 실수 페이지, 당신은 사용해서는 안됩니다 glEnable(GL_TEXTURE_2D)
자신만의 셰이더를 만들 때 셰이더를 사용하면 어쨌든이 호출을 무시하기 때문입니다.
그래서 그게 다야. 나는 텍스처 좌표로 비 텍스트 좌표 데이터를 보내는 방법을 다루는 튜토리얼을 찾을 수 없었습니다. 아마도 누군가가 그것에 대한 튜토리얼을 알고 있다면 내 문제가 완화 될 것입니다. 시간 내 줘서 고마워!
해결책
glClientActiveTextureARB
호출 후 특정 텍스처 좌표 단위를 변경합니다 glEnableClientState(GL_TEX_COORD_ARRAY)
그리고 glTexCoordPointer
변경 될 것입니다.
glActiveTextureARB
영향을 미칩니다 glEnable(GL_TEXTURE_2D)
, 당신이 언급했듯이, 당신은 셰이더가 필요하지 않습니다.
코드를 면밀히 살펴보면 5 개의 통화 (및 해당 비활성화) 만 선택하면 다음과 같습니다.
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
좋아, 우리는 이미 GlactiveTextUrearb와 Glenable이 유용하지 않다고 말했습니다 (그건 그렇고, 당신은 활성화/비활성화 GL_TEXTURE_2D
그 사이에 아무런 추첨이 없으면 유용하지 않습니다).
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
지금 눈에 띄는 것은 무엇입니까? 2 가지 문제 :
- 드로우를 실행하기 전에 고객 상태를 비활성화합니다
- 텍스처에 대한 활성화 비트를 설정하지 않습니다 2
무엇을 써야합니까? 그 줄을 따라 무언가 : (조심하십시오. 각 포인터 호출에 bindbuffer 호출을 추가해야합니다) : :
// texture coord 0
glClientActiveTextureARB(GL_TEXTURE0_ARB); // program texcoord unit 0
glEnableClientState(GL_TEXTURE_COORD_ARRAY); // enable array data to shader
glTexCoordPointer(3, GL_FLOAT, 0, 0); // say what data
// texture coord 1
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
// texture coord 2
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
// done with those texcoord units, turn them off
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
Bindbuffer에 대한 더 많은 의견 : glBindBufferARB(GL_ARRAY_BUFFER_ARB,...)
하다 ~ 아니다 영향을받습니다 glClientActiveTextureARB
, 그러나 그러나 그것은 하다 다음에 영향을 미칩니다 glTexCoordPointer
전화. 본질적으로 생각하십시오 glClientActiveTextureARB
그리고 glBindBufferARB
추가 논쟁을 제공합니다 glTexCoordPointer
.
마지막으로, 당신은 아마도 그 VBO 중 일부를 덜 버퍼로 그룹화하고 싶을 것입니다. 또 다른 질문에 대한 것이 있습니까? (힌트, 두 가지 논쟁 glTexCoordPointer
0이 될 필요는 없습니다)