繁体   English   中英

基本GLSL:两个片段着色器彼此后面,但是第一个片段着色器(绘制纹理)被覆盖

[英]Basic GLSL: Two fragment shaders behind each other, but first one (drawing a texture) is overwritten

我是OpenGL ES的新手,似乎缺少一个基本概念。 我在代码中使用了一些QT类,但是它接近普通的OpenGL ES。

我想对每个渲染帧执行以下操作:

  1. 渲染一个全屏简单的基于TRIANLGE_STRIP的矩形,上面带有纹理。 您可以将其视为背景图像。 这已经可以单独使用了。 自己的顶点和片段着色器(由QOpenGLShaderProgram包装)用于渲染它。 纹理最初来自QOpenGLFramebufferObject,有时会重新渲染它本身,但不是每个帧都被重新渲染。
  2. 绘制(1.)中的TRIANGLE_STRIP后,我想在顶部渲染另一个基本形状。 目前在底部还有一个小矩形。 这将使用另一个顶点和框架着色器。 这部分也可以单独使用。

我的问题是: 这两个步骤一起不起作用。 我仅从(2.)中看到屏幕底部的小矩形,但是纹理消失了。 应该显示纹理的区域将填充有清晰的颜色。

我的假设是,两个Frament着色器之间都存在某种冲突,或者我完全缺少与状态有关的东西。我很高兴为您提供有关此处缺少的内容的提示。

提前致谢!

这是我的一些代码:

这是步骤(1)的顶点和框架着色器代码:

static const char* vertexShaderSource =
    "attribute highp vec4 triangleCoords;\n"
    "attribute lowp vec2 textureCoords;\n"
    "varying lowp vec2 v_textureCoords;\n"
    "void main() {\n"
    "   v_textureCoords = textureCoords;\n"
    "   gl_Position = triangleCoords;\n"
    "}\n";

static const char* fragmentShaderSource =
    "varying lowp vec2 v_textureCoords;\n"
    "uniform sampler2D sampler;\n"
    "void main() {\n"
    "   gl_FragColor = vec4(texture2D(sampler, v_textureCoords).rgb, 1.0);\n"
    "}\n";

m_textureProgram = new QOpenGLShaderProgram();
m_textureProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
m_textureProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);   

这是步骤(2)的顶点和框架着色器代码:

static const char* vertexShaderSource =
    "attribute highp vec4 position;\n"
    "uniform lowp vec4 color;\n"
    "void main() {\n"
    "   gl_Position = position;\n"
    "}\n";

static const char* fragmentShaderSource =
    "uniform lowp vec4 color;\n"
    "void main() {\n"
    "   gl_FragColor = color;\n"
    "}\n";

m_shapeProgram->addShaderFromSourceCode( QOpenGLShader::Vertex, vertexShaderSource );
m_shapeProgram->addShaderFromSourceCode( QOpenGLShader::Fragment, fragmentShaderSource );

以及主要的渲染功能,将其简化了一些(我跳过了初始化部分,在那儿设置了着色器程序并绑定了属性位置):

m_context->makeCurrent(w);
glClear( GL_COLOR_BUFFER_BIT );

// Step (1.) begins here
m_textureProgram->bind();
glBindTexture(GL_TEXTURE_2D, textureId);
m_textureProgram->enableAttributeArray( LocationTriangleTextureCoords );
m_textureProgram->enableAttributeArray( LocationTextureCoords );
m_textureProgram->setAttributeArray( LocationTriangleTextureCoords, GL_FLOAT, s_triangleStripCoords, 2 );
m_textureProgram->setAttributeArray( LocationTextureCoords, GL_FLOAT, s_textureCoords, 2);
f.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
m_textureProgram->disableAttributeArray( LocationTriangleTextureCoords );
m_textureProgram->disableAttributeArray( LocationTextureCoords );
m_textureProgram->release();

// Step (2.) begins here:
m_shapeProgram->bind();
m_shapeProgram->setUniformValue( m_colorUniformId, m_color1 );
QPointF p0( -1, -0.7);
QPointF p1( -1, -1.0 );
QPointF p2( 0, -1.0 );
QPointF p3( 0, -0.7 );
GLfloat vertices[12] = { GLfloat(p0.x()), GLfloat(p0.y()),
                         GLfloat(p1.x()), GLfloat(p1.y()),
                         GLfloat(p2.x()), GLfloat(p2.y()),
                         GLfloat(p0.x()), GLfloat(p0.y()),
                         GLfloat(p3.x()), GLfloat(p3.y()),
                         GLfloat(p2.x()), GLfloat(p2.y())
                      };

m_buffer->bind();
m_buffer->write( 0, vertices, sizeof(vertices) );
m_shapeProgram->setAttributeBuffer( LocationShapePosition, GL_FLOAT, 0, 2 );
m_shapeProgram->enableAttributeArray( LocationShapePosition );
f.glDrawArrays( GL_TRIANGLES, 0, 6 );
m_shapeProgram->release();

// Done frame.
m_context->swapBuffers(w);

由于您是说这两个步骤可以独立正确地工作,所以我想说问题必须出在其他地方。

您的问题可能不清楚,但是以下情况是否成立:

  • 您正在绘制一个带有纹理的全屏矩形,该矩形在单独绘制时可以正确显示(填满整个屏幕)
  • 您正在绘制一个非全屏较小的形状,该形状在单独绘制时可以正确显示(未绘制形状时会看到清晰的颜色)
  • 尝试渲染时,您都应该在背景中看到全屏纹理,而形状较小的部分应该显示较小的形状
  • 您的结果与仅执行第二步的结果完全相同(您看到未绘制形状的清晰颜色)

然后,我看到2个可能的问题。 首先(我很确定您必须检查过)可能是您要清除两次渲染调用之间的颜色缓冲区。 仍然要仔细检查。

第二个原因是这两个程序存在某种冲突。 如果此代码在每个帧上执行,则可能有意义。 一种快速的测试是仅绘制一次,然后查看结果是否正确绘制。

因此,可能发生的情况是在第二部分中设置了一些值,这破坏了第一部分。 例如:

如果纹理被第二部分破坏,则下次调用时,提取的每个纹理像素可能会返回(0,0,0,0)的颜色,通过混合可能会产生透明背景,并且您认为您看到了背景清除颜色。 您可以通过修改纹理着色器以仅输出纯色以查看是否在此处绘制来轻松测试。

另一个问题可能是将某些值设置为错误的程序,并且第一次调用的顶点数据被第二次调用覆盖。 在这种情况下,纹理将恰好在小矩形后面。 您可以通过使一个小的矩形(半透明)透明来进行测试,并查看纹理是否显示在其后面。

唯一在代码中引起注意的是

m_textureProgram->release();
m_shapeProgram->release();

这个对吗? 我希望着色器能够持久存在。 如果不是,那么它们在哪里创建?

您的假设似乎是第二部分以某种方式覆盖了其他像素以清除缓冲区。 我向你保证这是不可能的。 当绘制三角形时,没有办法影响其他像素(至少我猜没有几何着色器),只有点内的像素将分配有片段着色器,并且只有那些可以更改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM