2013-05-17 21 views
11

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ặc nmv đồ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"); 
+1

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

+1

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. –

+1

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. –

Trả lời

0
  1. Đôi khi lái xe sẽ tối ưu hóa một số trang phục của bạn (ngay cả khi nó không nên đặt biệt với trình điều khiển cũ). để thử nghiệm sử dụng màu vật liệu của bạn trong đổ bóng đỉnh (sao chép nó vào một số biến khác nhau và sử dụng đổ bóng đổ biến thay vì đồng nhất, đôi khi làm việc cho tôi, ... tất nhiên nó giảm hiệu năng một chút)

  2. cố gắng sử dụng phiên bản hồ sơ khác. Trong một số trường hợp trình điều khiển mới hơn không mô phỏng các phiên bản cũ hơn đúng cách. Bạn đã thử cấu hình cốt lõi chưa?(Tôi biết nó rất khó khăn để thực hiện với mã cũ)

  3. bạn có thể thử nvemulate để kiểm tra các thiết lập trình điều khiển khác nhau

đôi khi quên glEnd(); gây ra rất nhiều sự cố khi thử thêm mã này trước khi mã kết xuất khung của bạn:

glEnd(); 
glEnd(); 
glEnd(); 
glEnd(); 
glEnd(); 
glEnd(); 
glEnd(); 
glEnd(); 
glEnd(); 
glEnd(); 
glEnd(); 
... here comes your rendering code 

nếu điều này giúp bạn tha thứ gọi glEnd(); một nơi nào đó hoặc có glEnd; thay vì glEnd();

+1

Sự cố 'glEnd' sẽ kích hoạt lỗi GL, mà OP đã kiểm tra. – rotoglup

0

Vẫn chưa được giải quyết?

là những gì các loại mesh.color

nhìn vào địa chỉ chuyển vào dấu vết cuộc gọi họ có vẻ khá cao, có lẽ bạn nên đi qua trong một địa chỉ để các dữ liệu không phải là dữ liệu thực tế, 0x7fab823000bc

glUniform3fv (materialColorLoc, 1, & mesh.color); có thể thử mã hóa cứng và sử dụng glUniform3f()

0

Từ tất cả các địa chỉ trong dấu vết tôi đoán bất kỳ vec3 nào bạn gửi cho GL đều thuộc loại float name[3], phải không? Giả sử điều này tôi không thể phát hiện một lỗi trong mã của bạn. Như bạn đã nói không có trạng thái lỗi được trả về bởi glGetError, nó PHẢI là một lỗi trình điều khiển.

Tôi thấy trong dấu vết rằng bạn bắt đầu mỗi lưới làm một glBindBuffer (GL_ARRAY_BUFFER, 0) - điều này là không thực sự cần thiết. Nhưng dù sao đi nữa, tôi cũng không thể tưởng tượng điều này là nguồn gốc.

Đáng buồn thay, bạn không thể kiểm tra các nội dung như glBindUniformLocation trước khi liên kết, vì đó không phải là một phần của OpenGL.

Trải nghiệm của tôi cho thấy: nếu bạn phát hành glUniform3fv và tất cả thông số là chính xác, thì đồng phục sẽ được cập nhật và thay đổi đó sẽ hiển thị ngay lập tức. Vì đó không phải là trường hợp, ở đây, nó phải là một lỗi trình điều khiển, vì vậy những điều duy nhất bạn có thể làm là: thêm các cuộc gọi không cần thiết khác vào vòng lặp kết xuất của bạn để hiển thị thay đổi (mà bạn đã làm nếu đọc chính xác) .

Các vấn đề liên quan