gl_PointCoord编译和链接,但在运行时崩溃

时间:2016-04-24 19:24:55

标签: opengl glsl shader point-sprites transform-feedback

我成功地编写了一个带有点精灵的标准基本变换反馈粒子系统。没有闪烁,粒子从一个缓冲区更新到下一个缓冲区,然后渲染,然后输出缓冲区在下一次迭代时变为输入缓冲区。所有GPU端标准变换反馈。 精彩!一个大问题:它只有在我不使用gl_PointCoord时才有效。使用平面颜色为我的点精灵工作正常。但我需要gl_PointCoord做任何有意义的事情。我的所有着色器,无论是否使用gl_PointCoord,编译和链接就好了。但是,在运行时,如果着色器使用gl_PointCoord(无论gl_PointCoord是否实际位于执行路径中),程序将崩溃。我明确地说glEnable(GL_POINT_SPRITE)。这没有任何效果。省略gl_PointCoord,并设置glPointSize(100.0f),并使用vec4(1.0,1.0,1.0,1。),粒子系统可以很好地渲染大的白色块状正方形(如预期的那样)。但是在成功编译和链接之后,以任何方式使用gl_PointCoord(作为标准纹理查找坐标或程序颜色或其他任何东西)都会在运行时使我的着色器崩溃。我根本不明白为什么。它传递了glShaderSource,glCompileShader,glAttachShader,glLinkProgram。我正在将我的着色器编译为#version 430和440,我甚至尝试了300 es。所有编译,链接和我检查了编译和链接的状态。都好。我正在使用高端微软表面书专业版,2015年视觉工作室.NVIDIA GeForce GPU。我还确保我的所有司机都是最新的。不幸的是,对于点精灵,我没有来自顶点着色器的广告牌顶点用于插入片段着色器作为纹理坐标。 gl_FragCoord也不起作用(正如我对点精灵的期望)。有没有人知道如何解决这个问题或者使用另一种技术来获得点精灵的纹理坐标?

glBeginTransformFeedback(GL_POINTS); //如果我的片段着色器使用了gl_PointCoord,那么它很难崩溃。

回复时,请理解我在GLSL和HLSL中编写着色器,顶点着色器,像素着色器,曲面细分控制,曲面细分评估和几何着色器方面非常有经验。但我并不声称知道一切。我本可以忘记一些简单的事情;我只是不知道那可能是什么。我认为它可能是一个我没有启用的状态。就变换反馈而言,我还通过glTransformFeedbackVaryings正确设置了不同的属性。 C ++:

void Render(void* pData)
{
    auto pOwner = static_cast<CPointSpriteSystem*>(pData);
    glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
    glEnable(GL_POINT_SPRITE);
    glEnable(GL_POINT_SMOOTH);
    //glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
    m_Shader.Activate();
    auto num_particles = pOwner->m_NumPointSprites;
    FeedbackIndex = 0;
    while (true)
    {
        m_Shader.SetSubroutine(GL_VERTEX_SHADER, "RenderPass", 
            vssubroutines[FeedbackIndex], 
            vsprevSubLoc[FeedbackIndex], 
            vsupdateSub[FeedbackIndex]);
        m_Shader.SetSubroutine(GL_FRAGMENT_SHADER, "RenderPixelPass",
            pssubroutines[0],
            psprevSubLoc[0],
            psrenderSub[0]);
        if (!FeedbackIndex)
        {
            glEnable(GL_RASTERIZER_DISCARD);
            glBindVertexArray(m_vao[bufferIndex]);
            glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_Feedback[bufferIndex]);
            glBeginTransformFeedback(GL_POINTS);//if feedback fragment shader uses gl_PointCoord, will always hard-crash here 
            glDrawArrays(GL_POINTS, 0, num_particles);
            glEndTransformFeedback();
            glFlush();
        }
        else
        {
            m_Shader.SetSubroutine(GL_FRAGMENT_SHADER, "RenderPixelPass",
                pssubroutines[(int)pOwner->m_ParticleType],
                psprevSubLoc[(int)pOwner->m_ParticleType],
                psrenderSub[(int)pOwner->m_ParticleType]);
            glPointSize(100.0f);
            glDisable(GL_RASTERIZER_DISCARD);
            glDrawTransformFeedback(GL_POINTS, m_Feedback[bufferIndex]);
            bufferIndex = 1 - bufferIndex;
            break;
        }
        FeedbackIndex = 1 - FeedbackIndex;
    }
}

VS反馈:

#version 310 es
subroutine void RenderPassType();
subroutine uniform RenderPassType RenderPass;
layout(location=0) in vec3 VertexPosition;
layout(location=1) in vec3 VertexVelocity;
layout(location=2) in float VertexStartTime;
layout(location=3) in vec3 VertexInitialVelocity;
out vec3 Position;
out vec3 Velocity;
out float StartTime;
out float Transp;
uniform float g_fCurSeconds;
uniform float g_fElapsedSeconds;
uniform float Time;
uniform float H;
uniform vec3 Accel;

#ifdef USE_VIEW_BLOCK
layout(std140) uniform view_block{
    mat4 g_mView,
         g_mInvView,
         g_mPrevView,
         g_mPrevInvView,
         g_mProj,
         g_mInvProj;
};
uniform mat4 g_mWorld;
#endif

subroutine(RenderPassType) void UpdateSphere(){
    Position=VertexPosition+VertexVelocity*g_fElapsedSeconds;
    Velocity=VertexVelocity;
    StartTime=VertexStartTime;
}
subroutine(RenderPassType) void Render(){
    gl_Position=g_mProj*g_mInvView*vec4(VertexPosition,1.0);
}

void main(){
    RenderPass();"
}

PS反馈:

#version 310 es //version 430 and 440 same results
subroutine void RenderPixelType();
subroutine uniform RenderPixelType RenderPixelPass;
uniform sampler2D tex0;
layout(location=0) out vec4 g_FragColor;

subroutine(RenderPixelType) void Basic(){
    g_FragColor=vec4(1.0,1.0,1.0,1.0);
}

subroutine(RenderPixelType) void ProceduralSphere(){
#if 1
    vec2 coord=gl_PointCoord;//at runtime: BOOM!
    coord=coord*2.0-1.0;
    float len=length(coord);
    if(len>1.0) discard;
    g_FragColor=vec4(1.0-len,1.0-len,1.0-len,1.0);
#else
    g_FragColor=vec4(1.0,1.0,1.0,1.0);//always works
#endif
}

subroutine(RenderPixelType) void StandardImage(){
    g_FragColor=texture2D(tex0,gl_PointCoord); //boom!!
    g_FragColor=vec4(1.0,1.0,1.0,1.0);
}

void main(){
    RenderPixelPass();
}

1 个答案:

答案 0 :(得分:3)

我解决了这个问题!问题实际上是我没有给Transp写一个值(声明浮动Transp; // in vs)。我随便以为我没有必要这样做。但是我开始削减一些脂肪,一旦我写出一个泛型浮点数(实际上并没有被后来的着色器阶段使用:Transp = 0.0f),然后编译为#version 430,它们都开始像最初预期的那样工作了:小白球