2013-08-31 20 views
4

我想在我的OpenGL程序中實現實例化。通過將Model-View-Projection乘法矩陣作爲GLSL程序的輸入,我決定讓GLSL代碼更加高效,以便CPU針對每個實例計算它,而不是GPU。這裏是我的頂點着色器的代碼(大部分是不相關的我的問題):GLSL Instancing - 頂點數據的最大輸入數量?

#version 330 core 

// Input vertex data, different for all executions of this shader. 
layout(location = 0) in vec3 vertexPosition_modelspace; 
layout(location = 2) in vec3 vertexColor; 
layout(location = 3) in vec3 vertexNormal_modelspace; 
layout(location = 6) in mat4 models; 
layout(location = 10) in mat4 modelsV; 
layout(location = 14) in mat4 modelsVP; 

// Output data ; will be interpolated for each fragment. 
out vec3 newColor; 

out vec3 Position_worldspace; 

out vec3 Normal_cameraspace; 
out vec3 EyeDirection_cameraspace; 

// Values that stay constant for the whole mesh. 
uniform mat4 MVP; 
uniform mat4 MV; 
uniform mat4 P; 
uniform mat4 V; 
uniform mat4 M; 
uniform int num_lights; 
uniform vec3 Lights[256]; 

void main(){ 

// Output position of the vertex, in clip space : MVP * position 
gl_Position = P * modelsV * vec4(vertexPosition_modelspace,1); 

// Position of the vertex, in worldspace : M * position 
Position_worldspace = (models * vec4(vertexPosition_modelspace,1)).xyz; 

// Vector that goes from the vertex to the camera, in camera space. 
// In camera space, the camera is at the origin (0,0,0). 
vec3 vertexPosition_cameraspace = (modelsV * vec4(vertexPosition_modelspace,1)).xyz; 
EyeDirection_cameraspace = vec3(0,0,0) - vertexPosition_cameraspace;  

// Normal of the the vertex, in camera space 
Normal_cameraspace = (modelsV * vec4(vertexNormal_modelspace,0)).xyz; 

// UV of the vertex. No special space for this one. 
newColor = vertexColor; 

} 

上面的代碼工作,但只是因爲我不使用最後輸入modelsVP計算GL_POSITION。如果我使用它(而不是計算P * modelsV),實例將無法繪製,而我得到這個錯誤:

Linking program 
Compiling shader : GLSL/meshColor.vertexshader 
Compiling shader : GLSL/meshColor.fragmentshader 
Linking program 
Vertex info 
0(10) : error C5102: input semantic attribute "ATTR" has too big of a numeric index (16) 
0(10) : error C5102: input semantic attribute "ATTR" has too big of a numeric index (16) 
0(10) : error C5041: cannot locate suitable resource to bind variable "modelsVP". Possibly large array. 

我敢肯定,我將它鏈接正確地在我的OpenGL代碼,因爲如果我將輸入位置模型VP與modelsV交換爲10而不是14,我可以使用它,但不能使用modelsV。您可以爲頂點着色器提供最大數量的輸入嗎?我真的想不出任何其他的想法,爲什麼我會得到這個錯誤...

我會包括更多我的OpenGL代碼,這裏是相關的,但我敢肯定,這是正確的不是所有在同一個類或方法):

// Buffer data for VBO. The numbers must match the layout in the GLSL code. 
#define position 0 
#define uv 1 
#define color 2 
#define normal 3 
#define tangent 4 
#define bitangent 5 
#define model 6  // 4x4 matrices take 4 positions 
#define modelV 10 
#define modelVP 14 
#define num_buffers 18 

GLuint VBO[num_buffers]; 
glGenBuffers(num_buffers, VBO); 

for(int i=0; i<ModelMatrices.size(); i++) 
{ 
mvp.push_back(projection * view * ModelMatrices.at(i)); 
mv.push_back(view * ModelMatrices.at(i)); 
} 

glBindBuffer(GL_ARRAY_BUFFER, VBO[model]); 
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * ModelMatrices.size(), &ModelMatrices[0], GL_DYNAMIC_DRAW); 
for (unsigned int i = 0; i < 4 ; i++) { 

glEnableVertexAttribArray(model + i); 
glVertexAttribPointer(model + i, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), 
(const GLvoid*)(sizeof(GLfloat) * i * 4)); 
glVertexAttribDivisor(model + i, 1); 
} 

glBindBuffer(GL_ARRAY_BUFFER, VBO[modelV]); 
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * mv.size(), &mv[0], GL_DYNAMIC_DRAW); 
for (unsigned int i = 0; i < 4 ; i++) { 

glEnableVertexAttribArray(modelV + i); 
glVertexAttribPointer(modelV + i, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), 
(const GLvoid*)(sizeof(GLfloat) * i * 4)); 
glVertexAttribDivisor(modelV + i, 1); 
} 

glBindBuffer(GL_ARRAY_BUFFER, VBO[modelVP]); 
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * mvp.size(), &mvp[0], GL_DYNAMIC_DRAW); 
for (unsigned int i = 0; i < 4 ; i++) { 

glEnableVertexAttribArray(modelVP + i); 
glVertexAttribPointer(modelVP + i, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (const GLvoid*)(sizeof(GLfloat) * i * 4)); 
glVertexAttribDivisor(modelVP + i, 1); 
} 
+2

世界對相機和相機到透視矩陣*不會更改每個實例。所以他們不需要成爲每個實例的數據。另外,你根本不應該使用任何世界空間。你應該從模型到相機的空間。一個屬性矩陣和一個統一矩陣。 –

+0

世界對照相機矩陣是Model * View,因此每個實例都會改變,因爲它是每次都會改變的Model matrix,不是嗎?而且,我認爲讓CPU計算模型到攝像頭矩陣而不是GPU會更好。 (模型 - 相機空間和世界 - 相機空間是相同的東西,對吧?) – Darius

+1

「*世界對相機矩陣是模型*視圖*」不,這是*模型* - 相機矩陣;世界對相機只是「視圖」。是的,它確實會改變每個實例,但這是我的觀點。您需要*每個實例更改一個*矩陣。它應該是模型到照相機的矩陣,因爲在世界空間工作是一個可怕的想法。 –

回答

9

OpenGL的任務的實現提供至少16 4分量頂點屬性。因此,16的索引不能保證被所有實現支持;有關更多詳情,請參閱GL_MAX_VERTEX_ATTRIBS

您的mat4頂點屬性計爲4個4分量屬性,因此在僅支持16個4分量頂點屬性的實現中,索引14超出範圍。

+0

我這麼認爲!我想我必須讓GPU做額外的矩陣乘法。 – Darius

7

您使用的頂點屬性太多。以下是如何減少屬性數量而不用更改任何有關代碼的內容(並且任何功能更改都是改進)。下面假設models是「模型到世界」的矩陣,modelsV是「模型到相機」矩陣,並且modelsVP是「模型到投影」矩陣:

#version 330 core 

// Input vertex data, different for all executions of this shader. 
layout(location = 0) in vec3 vertexPosition_modelspace; 
layout(location = 2) in vec3 vertexColor; 
layout(location = 3) in vec3 vertexNormal_modelspace; 
layout(location = 6) in mat4 modelsV; 

// Output data ; will be interpolated for each fragment. 
out vec3 newColor; 

//The fragment shader should work in *camera* space, not world space. 
out vec4 Position_cameraspace; 

out vec3 Normal_cameraspace; 
//out vec3 EyeDirection_cameraspace; Can be computed from Position_cameraspace in the FS. 

// Values that stay constant for the whole mesh. 
uniform mat4 P; 

void main() 
{ 
    Position_cameraspace = modelsV * vec4(vertexPosition_modelspace, 1.0); 

    gl_Position = P * Position_cameraspace; 

    Normal_cameraspace = (modelsV * vec4(vertexNormal_modelspace,0)).xyz; 

    newColor = vertexColor; 
} 

見?沒那麼簡單嗎?頂點着色器中的制服較少,片段着色器的輸出較少,數學計算較少,頂點屬性較少。

所有你需要做的就是改變你的片段着色器使用相機空間位置,而不是世界空間的位置。這應該是一個相當容易的變化。

+0

我花了很多時間來解釋所有這些,我無法感謝你。我的代碼現在更高效,更易於閱讀,另外我對矩陣空間有了更多的瞭解。儘管我仍然在處理2D圖像的着色器程序中使用了世界空間,因爲它不使用視圖或投影矩陣。 – Darius