2010-12-07 170 views
4

將頂點屬性傳遞給正在運行的着色器程序時出現問題。我想通過兩個屬性,位置和一個RGBA顏色。綁定屬性位置適用於該位置。但是,它不適用於顏色。因此,所有的幾何圖形最終都會呈現黑色。GLSL 1.5和OpenGL 3.3:將顏色傳遞給頂點着色器似乎失敗

這是我做的:

GLuint programHandler; 

// create program 
// compile & attach vertex shader 
// compile & attach fragment shader 

glBindAttribLocation(programHandler, 0, "InPosition"); 
glBindAttribLocation(programHandler, 1, "InColor"); 
glBindFragDataLocation(programHandler, 1, "FragColor"); 

glLinkProgram(programHandler); 
glUseProgram(programHandler); 

// initialize uniform variables 

// I'm trying to get the attribute locations now. 
// I expect location "0" for InPosition and location "1" for InColor. 
// In fact, it gets me a "-1" for InColor. I simply cannot see the reason for that behaviour 

GLint positionLocation = glGetAttribLocation(programHandler, "InPosition"); // returns 0 
GLint colorLocation = glGetAttribLocation(programHandler, "InColor"); // returns -1 

glEnableVertexAttribArray(positionLocation); 
glEnableVertexAttribArray(colorLocation); // fails! 

我的頂點着色器是非常基本的。我真正要做的是轉變頂點並通過顏色的片段着色器:

#version 150 core 

// input 
uniform mat4 ModelviewMatrix; 
uniform mat4 ProjectionMatrix; 
in vec3 InPosition; 
in vec4 InColor; 

// output 
out vec4 PassColor; 

void main(void) { 
    // passing color through to fragment shader 
    PassColor = InColor; 

    // transformation 
    gl_Position = ProjectionMatrix * ModelviewMatrix * vec4(InPosition, 1.0); 
} 

我的片段着色器應該簡單地返回顏色:

#version 150 core 
precision highp float; 

// input 
in vec4 PassColor; 

// output 
out vec4 FragColor; 

void main(void) { 
    FragColor = PassColor; 
} 

爲什麼綁定「器就位」工作和「InColor」纔不是?我知道GLSL編譯器會優化着色器代碼,以便不能綁定未使用的變量。但是,我不明白爲什麼這裏應該優化顏色。畢竟,我通過將它傳遞給片段着色器來使用它。

+0

任何`glGetError()`在那裏?另外,你的GPU和驅動程序版本是什麼? – Kos 2010-12-07 12:00:38

回答

1

盲拍,我認爲這是錯誤的:

glBindFragDataLocation(programHandler, 1, "FragColor"); 

它應該是:

glBindFragDataLocation(programHandler, 0, "FragColor"); 
+0

我明白了。但是如果我想渲染到多個渲染目標。我目前渲染到附加到幀緩衝區對象的紋理。我原本打算不僅僅將那個紋理附加到顏色緩衝區中。這就是「1」作爲第二個參數的原因。我相信gl_FragData []數組已被棄用。我如何正確地綁定它並在片段着色器中聲明? – Walter 2010-12-07 04:19:42

0

如果片段着色器應寫入多個顏色平面,然後幀緩衝區必須是已創建,其中已附加了多個顏色平面,其中可以寫入片段。

彩色平面既可以使緩衝區,

GLuint renderbuffer[2]; 
glGenRenderbuffers(2, &renderbuffer[0]); 
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer[0]); 
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); 
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer[1]); 
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); 

,也可以是紋理。

GLuint colorTexture[2]; 
glGenTextures(2, &colorTexture[0]); 
glBindTexture(GL_TEXTURE_2D, colorTexture[0]); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
glBindTexture(GL_TEXTURE_2D, colorTexture[1]); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 

紋理或渲染緩衝區必須附加到幀緩衝區。

渲染緩衝器

GLuint frameBuffer; 
glGenFramebuffers(1, &frameBuffer); 
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer[0]); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer[1]); 

紋理

GLuint frameBuffer; 
glGenFramebuffers(1, &frameBuffer); 
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture[0], 0); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, colorTexture[1], 0); 

注意,當然渲染緩衝器和紋理可以被混合,並且可以附連到一個不同的色彩平面,並且在同一幀緩衝。
如果需要深度緩衝區或模板緩衝區,則必須將GL_DEPTH_ATTACHMENT,GL_STENCIL_ATTACHMENTGL_DEPTH_STENCIL_ATTACHMENT附加到幀緩衝區。

如果farme緩衝器已經成功完成可以與glCheckFramebufferStatus進行評估:

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 
{ 
    // error 
} 

其可以連接到單個幀緩衝器顏色緩衝器的最大數量可以通過OGL功能glGetIntegerv來確定,通過使用參數GL_MAX_COLOR_ATTACHMENTS

GLint maxColAttchemnts = 0; 
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColAttchemnts); 

並非所有的顏色附件必須在同一時間被激活。可以用glDrawBuffers來定義片段着色器數據的輸出寫入其中的緩衝器陣列。

GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT1 }; 
glDrawBuffers(1, &drawBuffers[0]); 

在片段着色器都將被聲明爲每個激活的顏色附着一個out變量。

out fragColor0; 
out fragColor1; 

void main() 
{ 
    .... 
    fragColor0 = ....; 
    .... 
    fragColor1 = ....; 
} 

一個out變量到幀緩衝器顏色附着的指數可以通過glBindFragDataLocation明確指定的結合。這必須在着色器程序被鏈接之前完成。

GLuint prog = ....; 
glBindFragDataLocation(prog, 0, "fragColor0"); 
glBindFragDataLocation(prog, 1, "fragColor1"); 
glLinkProgram(prog); 

在特定輸出寫入的現代OpenGL緩衝區索引中,可以通過佈局位置明確指定。這允許放棄使用glBindFragDataLocation

layout(location = 0) out fragColor0; 
layout(location = 1) out fragColor1;