2016-10-28 32 views
5

Tôi đang cố gắng triển khai trình đổ bóng tính toán đa năng để xử lý hình ảnh. Có hình ảnh đầu vào và hình ảnh đầu ra trong mỗi thẻ. Hình ảnh nhập 'hình ảnh đầu vào tiếp theo' là hình ảnh đầu ra trước đó.Trình đổ bóng tính toán OpenGL - kết quả lạ

Đây là lần đầu tiên tôi sử dụng tính năng đổ bóng trong OpenGL để có thể có một số vấn đề với thiết lập của tôi. Tôi đang sử dụng Mat của OpenCV làm vùng chứa để đọc/sao chép các hoạt động.

Có một số phần của mã không liên quan đến vấn đề nên tôi không bao gồm. Một số phần này bao gồm tải hình ảnh hoặc khởi tạo ngữ cảnh.

khởi:

//texture init 
glGenTextures(1, &feedbackTexture_); 
glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, feedbackTexture_); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glBindTexture(GL_TEXTURE_2D, 0); 

glGenTextures(1, &resultTexture_); 
glActiveTexture(GL_TEXTURE0+1); 
glBindTexture(GL_TEXTURE_2D, resultTexture_); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glBindTexture(GL_TEXTURE_2D, 0); 

// shader init 
computeShaderID = glCreateShader(GL_COMPUTE_SHADER); 
glShaderSource(computeShaderID, 1, &computeShaderSourcePtr, &computeShaderLength); 
glCompileShader(computeShaderID); 
programID = glCreateProgram(); 
glAttachShader(programID, computeShaderID); 
glLinkProgram(programID); 
glDeleteShader(computeShaderID); 

Shader Code:

//shader code (simple invert) 
#version 430 
layout (local_size_x = 1, local_size_y = 1) in; 

layout (location = 0, binding = 0, /*format*/ rgba32f) uniform readonly image2D inImage; 
layout (location = 1, binding = 1, /*format*/ rgba32f) uniform writeonly image2D resultImage; 

uniform writeonly image2D image; 

void main() 
{ 
    // Acquire the coordinates to the texel we are to process. 
    ivec2 texelCoords = ivec2(gl_GlobalInvocationID.xy); 

    // Read the pixel from the first texture. 
    vec4 pixel = imageLoad(inImage, texelCoords); 

    pixel.rgb = 1. - pixel.rgb; 

    imageStore(resultImage, texelCoords, pixel); 
} 

Cách sử dụng:

cv::Mat image = loadImage().clone(); 
cv::Mat result(image.rows,image.cols,image.type()); 
// These get the appropriate enums used by glTexImage2D 
GLenum internalformat = GLUtils::getMatOpenGLImageFormat(image); 
GLenum format = GLUtils::getMatOpenGLFormat(image); 
GLenum type = GLUtils::getMatOpenGLType(image); 

int dispatchX = 1; 
int dispatchY = 1; 

for (int i = 0; i < shaderPasses_.size(); ++i) 
{ 
    // Update textures 
    glBindTexture(GL_TEXTURE_2D, feedbackTexture_); 
    glTexImage2D(GL_TEXTURE_2D, 0, internalformat, result.cols, result.rows, 0, format, type, result.data); 
    glBindTexture(GL_TEXTURE_2D, resultTexture_); 
    glTexImage2D(GL_TEXTURE_2D, 0, internalformat, image.cols, image.rows, 0, format, type, 0); 
    glBindTexture(GL_TEXTURE_2D, 0); 

    glClear(GL_COLOR_BUFFER_BIT); 
    std::shared_ptr<Shader> shaderPtr = shaderPasses_[i]; 
    // Enable shader 
    shaderPtr->enable(); 
    { 
     // Bind textures 
     // location = 0, binding = 0 
     glUniform1i(0,0); 
     // binding = 0 
     glBindImageTexture(0, feedbackTexture_, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 
     // location = 1, binding = 1 
     glUniform1i(1,1); 
     // binding = 1 
     glBindImageTexture(1, resultTexture_, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 

     // Dispatch rendering 
     glDispatchCompute((GLuint)image.cols/dispatchX,(GLuint)image.rows/dispatchY,1); 
     // Barrier will synchronize 
     glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 
    } 
    // disable shader 
    shaderPtr->disable(); 

    // Here result is now the result of the last pass. 
} 

Đôi khi tôi nhận được kết quả kỳ lạ (glitchy kết cấu, kết cấu render một phần), cũng pixel đầu tiên (at 0,0) đôi khi không được viết. Tôi đã thiết lập mọi thứ chính xác hay tôi thiếu thứ gì đó? Dường như phương pháp này với kết cấu thực sự chậm, có cách nào khác thay đổi hiệu suất không?

Chỉnh sửa1:Cờ bộ nhớ chuyển đổi đã thay đổi.

Trả lời

3

Tôi có thể giải quyết vấn đề này cuối cùng!

Sự cố nằm trong cv :: hàm tạo của Mat. Các dòng sau chỉ tạo ra một tiêu đề cho cv :: Mat:

cv::Mat result(image.rows,image.cols,image.type()); 

DOES phân bổ dữ liệu nhưng nó KHÔNG khởi tạo dữ liệu, đó là lý do tại sao tôi có những kết quả lạ. Đó là rác trong ký ức.

Sử dụng bất kỳ chức năng mà phân bổ khởi dữ liệu này giải quyết vấn đề này:

cv::Mat::zeros 
cv::Mat::ones 
cv::Mat::create 
+1

Nói đúng, lệnh gọi ban đầu của bạn là 'cv :: Mat result (image.rows, image.cols, image.type());' nên _allocate_ bộ đệm hình ảnh, giống như 'cv :: Mat :: create', tuy nhiên nó không _initialize_ giá trị pixel. 'cv :: Mat :: zeros' và' cv :: Mat :: ones' đều phân bổ và khởi tạo các giá trị pixel. – AldurDisciple

+0

Có bạn đúng, tôi sẽ cập nhật câu trả lời của tôi. –

5
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 

Đây là rào cản sai. Hàng rào chỉ định how you intend to access the data after the incoherent accesses. Nếu bạn đang cố gắng đọc từ kết cấu với glGetTexImage, bạn phải sử dụng GL_TEXTURE_UPDATE_BARRIER_BIT.

+0

Oh tôi đã bỏ lỡ phần đó, nhờ làm rõ.Ngoài ra còn có phương pháp nào để tăng tốc độ tải lên/tải xuống một phần không? Hình ảnh của tôi sẽ hiếm khi thay đổi kích thước thông qua chương trình và chúng sắp tới khoảng 30 khung hình/giây. –

+0

Được rồi, có vẻ như sự thay đổi cờ không làm gì cả, điểm ảnh đầu tiên vẫn nhấp nháy, và đôi khi các hiện vật lạ xuất hiện trong toàn bộ hình ảnh. –

3

Tôi không chắc chắn 100% nếu điều này có khắc phục được sự cố của bạn hay không; nhưng tôi không thấy bất cứ điều gì dường như sai với cờ của bạn để khởi tạo các thiết lập kết cấu của bạn. Khi tôi so sánh mã của bạn với dự án của tôi, đó là thứ tự các cuộc gọi API thu hút sự chú ý của tôi. Trong nguồn của bạn, bạn có đơn hàng này:

glGenTextures(...); // Generate 
glActiveTexture(...); // Set Active 
glBindTexture(...); // Bind Texture 
glTexParameteri(...); // Wrap Setting 
glTexParameteri(...); // Wrap Setting 
glTexParameteri(...); // Mipmap Setting 
glTexParameteri(...); // Mipmap Setting 
glBindTexture(...); // Bind/Unbind 

và bạn lặp lại điều này cho mỗi kết cấu ngoại trừ việc truyền biến kết cấu và tăng giá trị id.

Tôi không biết nếu nó sẽ tạo sự khác biệt nhưng với động cơ của tôi và đi theo con đường hợp lý mà tôi đã thiết lập; cố gắng làm việc đó theo thứ tự này và xem nếu nó làm cho bất kỳ sự khác biệt

glGenTextures(...); // Generate 
glBindTexture(...); // Bind Texture 
glTexParameteri(...); // Wrap Setting 
glTexParameteri(...); // Wrap Setting 
glTexParameteri(...); // Mipmap Setting 
glTexParameteri(...); // Mipmap Setting 

glActiveTexture(...); // Set Active 
glBindTexture(...); // Bind/Unbind 

tôi không sử dụng shaders tính toán, nhưng trong động cơ của tôi, tôi có một vài lớp học quản lý những thứ khác nhau. Tôi có một Asset Storage sẽ lưu tất cả các tài sản vào một cơ sở dữ liệu bộ nhớ bao gồm các texture cho hình ảnh, tôi có một lớp ShaderManager để quản lý các shader khác nhau mà hiện tại chỉ sử dụng các vertex và fragment shaders. Nó sẽ đọc và biên dịch các tệp đổ bóng, tạo các chương trình đổ bóng, thiết lập các thuộc tính và đồng phục, liên kết các chương trình và chạy các trình đổ bóng. Tôi đang sử dụng một quá trình hàng loạt, trong đó tôi có một lớp lô và một lớp trình quản lý lô để hiển thị các kiểu nguyên thủy khác nhau.Vì vậy, khi tôi đã đi qua giải pháp của tôi và theo con đường hoặc dòng chảy của logic này là những gì tôi đã nhìn thấy trong mã của tôi.

Đây là lớp AssetStorage đã thiết lập thuộc tính cho họa tiết và nó đang gọi các lệnh gọi API này theo thứ tự này trong hàm add() để thêm họa tiết vào bộ nhớ.

glGenTextures(...); 
glBindTextures(...); 
glTexParameteri(...); 
glTexParameteri(...); 
glTexParameteri(...); 
glTexParameteri(...); 

Sau đó AssetStorage đang gọi những cũng

glPixelStorei(...); 
glTexImage2D(...) 

Và chức năng để thêm textures vào AssetStorage cuối cùng sẽ trở về một cấu trúc tùy chỉnh của một đối tượng TextureInfo.

Khi tôi kiểm tra Lớp Batch của mình dưới lệnh gọi render(), đây là nơi nó được gọi là chức năng của ShaderManager để đặt đồng phục sử dụng kết cấu, sau đó gọi hàm ShaderManager để thiết lập kết cấu và sau đó một lần nữa để đặt đồng phục kết cấu chứa một kênh alpha. Trong lớp ShaderManger cho hàm setTexture(), đây là nơi mà số glActiveTexture()glBindTexture() cuối cùng cũng được gọi.

Vì vậy, trong bản tóm tắt ngắn, hãy thử di chuyển cuộc gọi glActiveTexture() của bạn ở giữa số glTexParameter()glBindTexture() cuộc gọi cuối cùng cho cả hai họa tiết. Tôi nghĩ rằng nó cũng nên đến sau khi hai cuộc gọi này cũng như glPixelStorei() & glTexImage2D() do thực tế là bạn muốn làm cho kết cấu Hoạt động giống như bạn sắp render nó. Như tôi đã đề cập trước đó, tôi không chắc chắn 100% nếu đây là nguyên nhân gốc rễ của vấn đề của bạn nhưng tôi tin rằng nó là giá trị bắn thử nó để xem nếu nó giúp bạn hay không. Không. Xin vui lòng cho tôi biết những gì sẽ xảy ra nếu bạn thử điều này. Tôi muốn biết bản thân mình nếu thứ tự của các cuộc gọi API này có bất kỳ ảnh hưởng nào đến nó. Tôi sẽ thử nó trong giải pháp của riêng tôi nhưng tôi không muốn phá vỡ các lớp học của tôi hoặc dự án cho nó hiện đang làm việc đúng cách.

Như một lưu ý, điều duy nhất với cờ cho cài đặt kết cấu của bạn nằm trong các phần bọc/lặp lại. Thay vào đó, bạn có thể thử sử dụng GL_REPEAT cho hai cuộc gọi glTexParameteri() đầu tiên thay vì sử dụng GL_CLAMP_TO_EDGE và cho tôi biết những gì bạn nghĩ ra, bạn không cần phải lo lắng về cài đặt mipmap cho hai cuộc gọi glTexParameteri() cuối cùng vì dường như bạn không sử dụng mipmaps từ cài đặt bạn đang sử dụng.

+1

Cảm ơn bạn đã dành thời gian và chăm sóc giải pháp cho vấn đề của mình. Tôi đã có một giải pháp cách đây không lâu, câu trả lời thực sự không phải là thứ tự của các cuộc gọi gl hoặc các tham số kết cấu mà là hàm dựng Mat của OpenCV. Tôi sẽ cung cấp một câu trả lời ngay. –

+0

@ GáborFekete Oh okay, yeah luôn có khả năng là lỗi có thể xảy ra từ nguồn bên ngoài hoặc thư viện của bên thứ ba. –

+0

Nó thực sự là dễ dàng hơn để gỡ lỗi opencv hơn opengl. Các trạng thái cho opengl đều ổn, ngoại trừ một số cờ và 'glActiveTexture' mà bạn đã đề cập. Và tôi đã phạm sai lầm để dựa vào một trong các thư viện ... Không bao giờ tin tưởng họ! : D –

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