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, все это заработало, как и ожидалось.: маленькие белые сферы