2016-04-24 116 views
1

我成功地写了一个标准的基本变换反馈粒子系统与点精灵。没有闪烁,粒子从一个缓冲区更新到下一个,然后渲染,然后输出缓冲区在下一次迭代时变为输入缓冲区。所有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个。所有的编译,链接和我检查了编译和链接的状态。都好。我正在使用高端微软表面图书专业版,Visual Studio 2015. NVIDIA GeForce GPU。我也确保我所有的司机都是最新的。不幸的是,对于点精灵来说,我没有顶点着色器中的广告牌顶点用来作为纹理坐标插入到片段着色器中。 gl_FragCoord也不起作用(正如我所期望的点精灵)。有谁知道如何解决这个问题,或者使用另一种技术来绘制点精灵的纹理坐标?gl_PointCoord编译和链接,但在运行时崩溃

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(); 
} 
+0

您能否提供您的源代码,以便我们可以尝试重现该问题? – datenwolf

+0

只是更新了原始帖子 – Frankoguy

+0

它可能是驱动程序或程序中的某个地方的错误。没有完整的源代码(什么是pOwner?)很难说。 – Rei

回答

3

我解决了这个问题!问题实际上是我没有给Transp写一个值(声明为float Transp; //在vs中)。我随便以为我不必这样做。但是我开始修剪一些脂肪,并且一旦我写出了一个泛型浮动(实际上未被以后的着色器阶段使用:Transp = 0.0f),然后编译为#version 430,它就开始按最初预期工作:小白球