简体   繁体   English

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

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

I'm semi-new to OpenGL ES and looks like I'm missing one basic concept. 我是OpenGL ES的新手,似乎缺少一个基本概念。 I'm using some QT classes in my code, but it's near plain OpenGL ES. 我在代码中使用了一些QT类,但是它接近普通的OpenGL ES。

I want to do the following per rendered frame: 我想对每个渲染帧执行以下操作:

  1. Render a fullscreen simple TRIANLGE_STRIP-based rectangle with a texture on it. 渲染一个全屏简单的基于TRIANLGE_STRIP的矩形,上面带有纹理。 You can see it as a background image. 您可以将其视为背景图像。 This already works on it's own. 这已经可以单独使用了。 An own vertex and fragment shader (wrapped by QOpenGLShaderProgram) is used to render it. 自己的顶点和片段着色器(由QOpenGLShaderProgram包装)用于渲染它。 The texture originally comes from a QOpenGLFramebufferObject and this itself is re-rendered sometimes, but not every frame. 纹理最初来自QOpenGLFramebufferObject,有时会重新渲染它本身,但不是每个帧都被重新渲染。
  2. After TRIANGLE_STRIP from (1.) is drawn, I want to render another basic shape on top. 绘制(1.)中的TRIANGLE_STRIP后,我想在顶部渲染另一个基本形状。 Currently also a small rectangle on the bottom. 目前在底部还有一个小矩形。 This uses another vertex and frament shader. 这将使用另一个顶点和框架着色器。 This part also works on it's own. 这部分也可以单独使用。

My problem is: Both steps together don't work. 我的问题是: 这两个步骤一起不起作用。 I only see the the small rectangle on the bottom of the screen from (2.), but the texture is gone. 我仅从(2.)中看到屏幕底部的小矩形,但是纹理消失了。 The area, where the texture should be shown, is filled with the clear color. 应该显示纹理的区域将填充有清晰的颜色。

My assumption is, the both frament shaders conflict somehow with each other or I'm missing something completely with states.. I'd be pleased for a hint on what is missing here. 我的假设是,两个Frament着色器之间都存在某种冲突,或者我完全缺少与状态有关的东西。我很高兴为您提供有关此处缺少的内容的提示。

Thanks in advance! 提前致谢!

Here's some of my code: 这是我的一些代码:

This is the vertex and frament shader code of step (1): 这是步骤(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);   

This is the vertex and frament shader code of step (2): 这是步骤(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 );

And the main rendering function, a little bit stripped down (I'm skipping the initialization part, where the shader programs are setup and attribute locations bound): 以及主要的渲染功能,将其简化了一些(我跳过了初始化部分,在那儿设置了着色器程序并绑定了属性位置):

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);

Since you are saying that the two steps work correctly independently I would say the issue must be somewhere else. 由于您是说这两个步骤可以独立正确地工作,所以我想说问题必须出在其他地方。

It might be a bit unclear from your question but if the following is true: 您的问题可能不清楚,但是以下情况是否成立:

  • You are drawing a fullscreen rectangle with texture which shows correctly when drawn on its own (fills the whole screen) 您正在绘制一个带有纹理的全屏矩形,该矩形在单独绘制时可以正确显示(填满整个屏幕)
  • You are drawing a non-fullscreen smaller shape which shows correctly when drawn on its own (you see a clear color where the shape is not drawn) 您正在绘制一个非全屏较小的形状,该形状在单独绘制时可以正确显示(未绘制形状时会看到清晰的颜色)
  • When you try to render both you should see a full screen texture in background and the part with the small shape should show the small shape 尝试渲染时,您都应该在背景中看到全屏纹理,而形状较小的部分应该显示较小的形状
  • Your result is exactly the same as if only the second step was executing (you see a clear color where the shape is not drawn) 您的结果与仅执行第二步的结果完全相同(您看到未绘制形状的清晰颜色)

Then I see 2 possible issues. 然后,我看到2个可能的问题。 First (I am pretty sure you must have checked) might be that you are clearing the color buffer in between the 2 rendering calls. 首先(我很确定您必须检查过)可能是您要清除两次渲染调用之间的颜色缓冲区。 Double check for that anyway. 仍然要仔细检查。

The second is that the 2 programs are somehow in conflict. 第二个原因是这两个程序存在某种冲突。 If this code executes on every frame it might make sense. 如果此代码在每个帧上执行,则可能有意义。 A quick test would be to only draw it once and see if the result is drawn correctly. 一种快速的测试是仅绘制一次,然后查看结果是否正确绘制。

So what may happen is that some value is being set in the second part which destroys the first part. 因此,可能发生的情况是在第二部分中设置了一些值,这破坏了第一部分。 For instance: 例如:

If texture is destroyed by the second part then the next time you call it would be possible that each texel fetched returns a color of (0,0,0,0) which with blending may produce a transparent background and you think you see a background cleared color. 如果纹理被第二部分破坏,则下次调用时,提取的每个纹理像素可能会返回(0,0,0,0)的颜色,通过混合可能会产生透明背景,并且您认为您看到了背景清除颜色。 You may easily test this by modifying the textured shader to only output a solid color just to see if it gets drawn there. 您可以通过修改纹理着色器以仅输出纯色以查看是否在此处绘制来轻松测试。

Another problem might be some values are set to a wrong program and the vertex data for the first call gets overwritten by the second call. 另一个问题可能是将某些值设置为错误的程序,并且第一次调用的顶点数据被第二次调用覆盖。 In this case the texture would be exactly behind the small rectangle. 在这种情况下,纹理将恰好在小矩形后面。 You could test that by having a small rectangle (semi) transparent and see if the texture shows behind it. 您可以通过使一个小的矩形(半透明)透明来进行测试,并查看纹理是否显示在其后面。

The only thing that draws attention in your code though is 唯一在代码中引起注意的是

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

Is this correct? 这个对吗? I would expect the shaders to be persistent. 我希望着色器能够持久存在。 If not then where are they created? 如果不是,那么它们在哪里创建?

It seems your assumption is that the second part somehow overwrites other pixels to clear buffer. 您的假设似乎是第二部分以某种方式覆盖了其他像素以清除缓冲区。 I assure you that is not possible. 我向你保证这是不可能的。 When drawing triangles there is no way to influence other pixels (at least without geometry shader I guess), ONLY the pixels within the points will have assigned fragment shaders and only those may be changed. 当绘制三角形时,没有办法影响其他像素(至少我猜没有几何着色器),只有点内的像素将分配有片段着色器,并且只有那些可以更改。

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

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