Tôi có chương trình GLSL cực kỳ cơ bản không cập nhật đúng giá trị thống nhất sau lệnh gọi vẽ đầu tiên. Không có lỗi nào được nhận từ glGetError
, không có lỗi nào được báo cáo trong nhật ký thông tin khi biên dịch và liên kết các trình đổ bóng và tất cả các vị trí thống nhất đều hợp lệ.Đồng phục GLSL chỉ được cập nhật bằng các cuộc gọi không liên quan
Vertex Shader:
#version 120
uniform mat4 mvp;
uniform mat3 nmv;
attribute vec3 position;
attribute vec3 normal;
varying vec3 v_normal;
void main()
{
v_normal = normalize(nmv * normal);
gl_Position = mvp * vec4(position, 1.0);
}
Fragment Shader:
#version 120
uniform vec3 lightDir;
uniform vec3 lightColor;
uniform vec3 materialColor;
varying vec3 v_normal;
void main()
{
vec3 n = normalize(v_normal);
float nDotL = max(0.0, dot(n, lightDir));
gl_FragColor = vec4(materialColor * lightColor * nDotL, 1.0);
}
đang Rendering:
glUseProgram(program);
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, mvp);
glUniformMatrix3fv(nmvLoc, 1, GL_FALSE, nmv);
glUniform3fv(lightDirLoc, 1, lightDir);
glUniform3fv(lightColorLoc, 1, lightColor);
for (auto mesh: meshes)
{
glUniform3fv(materialColorLoc, 1, mesh.color);
mesh.draw();
}
Các mắt lưới trả lại tất cả đều được vẽ theo màu sắc của lưới đầu tiên, chỉ ra rằng sau khi thiết lập đồng phục materialColor
, các cuộc gọi tiếp theo đến chan ge đồng phục được bỏ qua. Tuy nhiên, đây là danh sách các điều kiện đặc biệt độc lập cho phép đồng phục được cập nhật đúng cách:
- Gọi
glUseProgram(program)
trong vòng lặp. - Đặt
mvp
hoặcnmv
đồng phục trong vòng lặp. - Đặt đồng phục
lightDir
trong vòng lặp. - Xóa một trong số
uniform vec3
s khỏi chương trình đổ bóng.
Xin lưu ý rằng cài đặt đồng phục lightColor
trong vòng lặp sẽ không cập nhật đồng phục materialColor
. Tôi cũng đã kiểm tra GL_CURRENT_PROGRAM
trong vòng lặp và trình đổ bóng vẫn bị ràng buộc trong suốt.
Tôi đã cố sửa lỗi này trong nhiều giờ và hoàn toàn không thể tìm thấy vấn đề. Thiết lập shader này đơn giản đến nỗi tôi không tin đó là lỗi trình điều khiển. Tôi đang sử dụng OpenGL 2.1 trên Mac OS X 10.8.3 với NVIDIA GeForce 9400M.
Dưới đây là một dấu vết cuộc gọi cho một khung duy nhất:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(1);
glUniformMatrix4fv(1, 1, 0, 0x7fff55512550); // mvp
glUniformMatrix3fv(5, 1, 0, 0x7fff55512528); // nmv
glUniform3fv(0, 1, 0x7fff55512670); // lightDir
glUniform3fv(9, 1, 0x7fff555124e8); // lightColor
// Mesh 0
glUniform3fv(8, 1, 0x7fab820cd7ec); // materialColor
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 1);
glEnableVertexAttribArray(0);
glVertexAttribPointerARB(0, 3, GL_FLOAT, 0, 24, 0x00000000);
glEnableVertexAttribArray(2);
glVertexAttribPointerARB(2, 3, GL_FLOAT, 0, 24, 0x0000000c);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 21);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// Mesh 1
glUniform3fv(8, 1, 0x7fab823000bc); // materialColor
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 2);
glEnableVertexAttribArray(0);
glVertexAttribPointerARB(0, 3, GL_FLOAT, 0, 24, 0x00000000);
glEnableVertexAttribArray(2);
glVertexAttribPointerARB(2, 3, GL_FLOAT, 0, 24, 0x0000000c);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 24);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// Mesh 2
glUniform3fv(8, 1, 0x7fab8231f8fc); // materialColor
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 3);
glEnableVertexAttribArray(0);
glVertexAttribPointerARB(0, 3, GL_FLOAT, 0, 24, 0x00000000);
glEnableVertexAttribArray(2);
glVertexAttribPointerARB(2, 3, GL_FLOAT, 0, 24, 0x0000000c);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 21);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// Mesh 3
glUniform3fv(8, 1, 0x7fab820cf41c); // materialColor
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 4);
glEnableVertexAttribArray(0);
glVertexAttribPointerARB(0, 3, GL_FLOAT, 0, 24, 0x00000000);
glEnableVertexAttribArray(2);
glVertexAttribPointerARB(2, 3, GL_FLOAT, 0, 24, 0x0000000c);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 18);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
CGLFlushDrawable();
EDIT: Đây là mã được sử dụng để có được những địa điểm thống nhất. Nó được thực hiện sau khi các shaders đã được biên dịch và liên kết, và tất cả các đồng phục được xác nhận là hợp lệ.
GLint mvpLoc = glGetUniformLocation(program, "mvp");
GLint nmvLoc = glGetUniformLocation(program, "nmv");
GLint lightDirLoc = glGetUniformLocation(program, "lightDir");
GLint lightColorLoc = glGetUniformLocation(program, "lightColor");
GLint materialColorLoc = glGetUniformLocation(program, "materialColor");
Dường như với tôi rằng sự khác biệt duy nhất giữa đồng phục lightColor và lightDir là vị trí của họ trong trình đổ bóng. Bạn đã thử chuyển đổi địa điểm của họ và nhìn thấy nếu lightColor thực sự kích hoạt sự thay đổi? Tôi cũng sẽ cố gắng để xem nếu một ATI hoặc Intel GPU sản xuất các hành vi tương tự. – Ani
Tôi vừa thử chuyển đổi thứ tự của họ và hành vi vẫn chính xác như cũ. 'lightColor' vẫn không kích hoạt thay đổi. Rất tiếc, tôi không có quyền truy cập vào một GPU khác tại thời điểm này. –
Tôi nhận thấy rằng việc hoán đổi thứ tự tuyên bố, hoặc vị trí của họ trong các hoạt động dẫn đến vị trí thống nhất của họ không thay đổi. –