2016-04-24 114 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,它就開始按最初預期工作:小白球