簡體   English   中英

GLSL渲染到紋理無法正常工作

[英]GLSL Render to Texture not working

我正在嘗試進行一次計算傳遞,在其中渲染到稍后將在繪制傳遞中使用的紋理。 我最初的實現基於着色器存儲緩沖區對象,並且運行良好。 但是我想應用一種將利用GPU混合硬件優勢的計算方法,因此我開始將SSBO實現移植到RTT。 不幸的是,該代碼已停止工作。 現在,當我讀回紋理時,它得到了錯誤的值。

這是我的紋理和幀緩沖區設置代碼:

glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);

// Create render textures
glGenTextures(NUM_TEX_OUTPUTS, m_renderTexs);
m_texSize = square_approximation(m_numVertices);
cout << "Textures size: " << glm::to_string(m_texSize) << endl;
GLenum drawBuffers[NUM_TEX_OUTPUTS];
for (int i = 0 ; i < NUM_TEX_OUTPUTS; ++i)
{
    glBindTexture(GL_TEXTURE_2D, m_renderTexs[i]);
    // 1st 0: level, 2nd 0: no border, 3rd 0: no initial data
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_texSize.x, m_texSize.y, 0, GL_RGBA, GL_FLOAT, 0);
    // XXX: do we need this?
    // Poor filtering. Needed !
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glBindTexture(GL_TEXTURE_2D, 0);

    // 0: level
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, m_renderTexs[i], 0);
    drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
}
glDrawBuffers(NUM_TEX_OUTPUTS, drawBuffers);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
    cout << "Error when setting frame buffer" << endl;
    // throw exception?
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);

這是開始計算過程的代碼:

m_shaderProgram.use();

// setup openGL
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glViewport(0, 0, m_texSize.x, m_texSize.y); // setup viewport (equal to textures size)
// make a single patch have the vertex, the bases and the neighbours
glPatchParameteri(GL_PATCH_VERTICES, m_maxNeighbours + 5);

// Wait all writes to shader storage to finish
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

glUniform1i(m_shaderProgram.getUniformLocation("curvTex"), m_renderTexs[2]);
glUniform2i(m_shaderProgram.getUniformLocation("size"), m_texSize.x, m_texSize.y);
glUniform2f(m_shaderProgram.getUniformLocation("vertexStep"), (umax - umin)/divisoes,
            (vmax-vmin)/divisoes);

// Bind buffers 
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
glBindBufferBase(GL_UNIFORM_BUFFER, m_mvp_location, m_mvp_ubo);

// Make textures active
for (int i = 0; i < NUM_TEX_OUTPUTS; ++i)
{
    glActiveTexture(GL_TEXTURE0 + i);
    glBindTexture(GL_TEXTURE_2D, m_renderTexs[i]);
}

// no need to pass index array 'cause ibo is bound already
glDrawElements(GL_PATCHES, m_numElements, GL_UNSIGNED_INT, 0);

然后,我使用以下內容回讀紋理:

bool readTex(GLuint tex, void *dest)
{
    glBindTexture(GL_TEXTURE_2D, tex);
    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, dest);
    glBindTexture(GL_TEXTURE_2D, 0);

    // TODO: check glGetTexImage return values for error
    return true;
}

for (int i = 0; i < NUM_TEX_OUTPUTS; ++i)
{
    if (m_tensors[i] == NULL) {
        m_tensors[i] = new glm::vec4[m_texSize.x*m_texSize.y];
    }
    memset(m_tensors[i], 0, m_texSize.x*m_texSize.y*sizeof(glm::vec4));
    readTex(m_renderTexs[i], m_tensors[i]);
}

最后,片段着色器代碼為:

#version 430
#extension GL_ARB_shader_storage_buffer_object: require

layout(pixel_center_integer) in vec4 gl_FragCoord;

layout(std140, binding=6) buffer EvalBuffer {
    vec4 evalDebug[];
};

uniform ivec2 size;

in TEData {
    vec4 _a;
    vec4 _b;
    vec4 _c;
    vec4 _d;
    vec4 _e;
};

layout(location = 0) out vec4 a;
layout(location = 1) out vec4 b;
layout(location = 2) out vec4 c;
layout(location = 3) out vec4 d;
layout(location = 4) out vec4 e;

void main()
{
    a= _a;
    b= _b;
    c= _c;
    d= _d;
    e= _e;
    evalDebug[gl_PrimitiveID] = gl_FragCoord;
}

片段坐標是正確的(每個片段都指向紋理中的ax,y坐標),所有輸入值(_a到_e)也是正確的,但是回讀時我看不到它們正確地輸出到紋理。 我還嘗試訪問着色器中的紋理,以查看是否只是回讀錯誤,但是我的調試SSBO返回了全零。

我是否缺少一些設置步驟? 我已經在Linux和Windows(Titan和540M geforces)上進行了測試,並且使用的是openGL 4.3。

正如derhass在上面的評論中指出的那樣,問題在於紋理格式。 我假設通過將GL_FLOAT作為數據類型傳遞,它將對每個RGBA通道使用32位浮點數。 事實並非如此。 正如derhass所說,此處的數據類型參數不會更改紋理格式。 我必須將internalFormat參數更改為所需的參數(GL_RGBA32F),以便它可以按預期工作。 因此,將glTexImage2D更改為:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_texSize.x, m_texSize.y, 0, GL_RGBA, GL_FLOAT, 0);

我能夠正確地將結果渲染到紋理並讀回。 :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM