gl_PointCoord компилирует и связывает, но вылетает во время выполнения

Я успешно написал стандартную базовую систему частиц с обратной связью и точечными спрайтами. Нет мерцания, частицы обновляются из одного буфера в следующий, который затем визуализируется, затем выходной буфер становится входным буфером на следующей итерации. Вся сторона графического процессора, стандартная обратная связь преобразования. Замечательно! ОДНА БОЛЬШАЯ ПРОБЛЕМА: Это работает, только если я не использую 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. Все компиляция, ссылка, и я проверил статус компиляции и ссылки. Все хорошо. Я использую высококлассную Microsoft Surface Book Pro, Visual Studio 2015. Графический процессор NVIDIA GeForce. Я также удостоверился, что все мои водители обновлены. К сожалению, с точечными спрайтами у меня нет вершин билбордов из вершинного шейдера, чтобы использовать их для интерполяции в фрагментный шейдер в качестве координат текстуры. 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 ответ

Я решил проблему! На самом деле проблема была в том, что я не записывал значение в Transp (объявил float Transp;// в vs). Я случайно подумал, что мне не нужно этого делать. Но я начал обрезать немного жира, и как только я написал общий тип float (фактически не использовавшийся на более поздних этапах шейдера: Transp=0.0f), а затем скомпилированный как #version 430, все это заработало, как и ожидалось.: маленькие белые сферы

Другие вопросы по тегам