1

我正在尝试制作一个使用 OpenGL 的框架。

然而,重新加载着色器程序时遇到问题。

成功链接

这就是我现在所拥有的。

我加载并编译了一个顶点着色器和一个片段着色器(两者都包含主)。

比我与他们链接一个程序。

起初,它没有问题。无论我刷新着色器多少时间。(如果我按下 Refresh Shader,应用程序会创建新的着色器、程序资源并用它们替换原来的)

比,如果我加载一个网格并执行一些绘图调用(使用 VBO),这次刷新着色器失败并显示以下消息。

链接失败

我不知道我的绘图调用或 VBO 函数调用如何可能与着色器链接相关......

我什至不确定这是否是确切的原因。

着色器类:

  class Shader : public Named
  {

    // -------------------------------------------------------
    // --------------- Defs ----------------------------------
  public:
    typedef void (*ErrFunc)( Shader* pShader, const char* const errMsg );



    // -------------------------------------------------------
    // --------------- Funcs ---------------------------------
  public:

    //
    // Shader Controls
    //
    // pre: source is string contains source
    Shader( const std::string& name, GLenum type);

    ~Shader( void );

    // pre: file to loast source. Give nullptr to load from lastly loaded file
    void ShaderSourceFromFile( const char* file );

    void ShaderSource( const std::string& source );

    void Compile( void );

    void AttachTo( GLuint program );

    void DetachFrom( GLuint program );

    GLuint GetId( void );

    void SetId( GLuint shaderId );

    GLint GetType( void );

    GLint GetCompileStatus( void );

    const char* const GetShaderInfoLog( void );


    //
    // Err Control
    //
  public:

    void Error ( const char* pErrMsg );

    static ErrFunc SetErrFunc( ErrFunc fpNewErrFunc );


    // -------------------------------------------------------
    // ----------- Vars --------------------------------------
  private:
    // id of the shader
    GLuint  _shaderId;

    // type of the shader
    GLenum  _type;

    // error func
    static ErrFunc s_fpErrFunc;





  }; // class Shader

  //
  // Shader
  //

  Shader::ErrFunc Shader::s_fpErrFunc = nullptr;


  Shader::Shader( const std::string& name, GLenum type) :
    Named(name),
    _shaderId(GL_INVALID_RESOURCE_ID),
    _type(type)
  {
    // Create shader
    GLint id = glCreateShader(type);

    // Failed to create shader?
    if ( id == GL_INVALID_RESOURCE_ID )
      Error("(Shader::Shader) Failed to create shader resource");

    // Set shader id
    SetId(id);

  }

  Shader::~Shader( void )
  {
    // Delete shader
    glDeleteShader(GetId());

    // Error Check
    if( glGetError() == GL_INVALID_VALUE )
      Error("(Shader::~Shader) given id to delete was not shader");
  }

  void Shader::Compile( void )
  {
    // Compile shader
    glCompileShader(_shaderId);

    switch( glGetError() )
    {
    case GL_NO_ERROR:break;
    case GL_INVALID_VALUE:     Error("shader is not a value generated by OpenGL.");break;
    case GL_INVALID_OPERATION: Error("shader is not a shader object.");break;
    default:Error("Unkown Error");
    }
    // ErrorCheck
    if( GetCompileStatus() == GL_FALSE )
      Error("(Shader::Compile) Compilation Failed.");

  }

  void Shader::ShaderSourceFromFile( const char* file  )
  {
      ShaderSource(ReadEntireFile(file));
  }
  // pre: source is string contains source
  void Shader::ShaderSource( const std::string& source )
  {
    const GLchar* pSource = source.c_str();
    glShaderSource( GetId(),  // shader id
                    1,        // count of source. only one at a time at the moment
                    &pSource, // buffer that source is stored
                    nullptr); // length is not specified, yet null terminated
    switch( glGetError() )
    {
    case GL_NO_ERROR:
      break;
    case GL_INVALID_VALUE:
      Error("invalid shader or bufsize is less than 0");
      break;
    case GL_INVALID_OPERATION:  
      Error("shader is not a shader object."); 
      break;
    default:
      Error("Unkown Error");
      break;
    }
  }
  void Shader::AttachTo( GLuint program )
  {
    glAttachShader(program, GetId());

    if( glGetError() != GL_NO_ERROR )
    {
      Error("(Shader::AttachTo) Error Happend Performing glAttachShader");
    }
  }

  void Shader::DetachFrom( GLuint program )
  {
    glDetachShader(program, GetId());

    switch( glGetError() )
    {
    case GL_NO_ERROR:
      break;
    case GL_INVALID_VALUE:
      Error("(Shader::DetachFrom)either program or shader is a value that was not generated by OpenGL.");
      break;
    case GL_INVALID_OPERATION:
      Error("(Shader::DetachFrom)program is not a program object. or "
      "shader is not a shader object. or "
      "shader is not attached to program.");
      break;
    default:
      Error("(Shader::DetachFrom)Unkown Error");
        break;
    }
  }

  GLuint Shader::GetId( void )
  {
    return _shaderId;
  }

  void Shader::SetId( GLuint shaderId )
  {
    _shaderId = shaderId;
  }

  GLint Shader::GetType( void )
  {
    return _type;
  }

  void Shader::Error ( const char* pErrMsg )
  {
    if( s_fpErrFunc )
      s_fpErrFunc(this, pErrMsg);
  }

  Shader::ErrFunc Shader::SetErrFunc( ErrFunc fpNewErrFunc )
  {
    ErrFunc prev = s_fpErrFunc;
    s_fpErrFunc = fpNewErrFunc;
    return prev;
  }

  GLint Shader::GetCompileStatus( void )
  {
    GLint status;
    glGetShaderiv(GetId(), GL_COMPILE_STATUS, &status );
    GLint err = glGetError();
    switch( err )
    {
    case GL_NO_ERROR:
      break;
    case GL_INVALID_ENUM:
      Error("(Shader::GetCompileStatus) Invalid Enum passed to glGetShaderiv");
      break;
    case GL_INVALID_VALUE:
      Error("(Shader::GetCompileStatus) Invalid Shader id passed to glGetShaderiv");
      break;
    case GL_INVALID_OPERATION:
      Error("(Shader::GetCompileStatus) Invalid Shader id or shader does not support");
      break;
    default:
      Error("(Shader::GetCompileStatus) Unkown Error");
      break;

    }
    return status;
  }
  const char* const Shader::GetShaderInfoLog( void )
  {
    static const unsigned s_bufSize = 0x1000;
    static GLchar s_buf[s_bufSize] = {0};

    // Get InfoLog
    glGetShaderInfoLog(GetId(), s_bufSize, nullptr, s_buf);

    // Error Check
    if( glGetError() != GL_NO_ERROR )
      Error("(Shader::GetCompileStatus) There was Error performing glGetShaderInfoLog");

    // return buffer
    return s_buf;
  }

提神功能:

 void GLShaderManager::Refresh( void )
  {



  // Gets current shader
  Shader* pVertexPrev = _shaderMap["Vertex"];
  Shader* pFragPrev = _shaderMap["Fragment"];


  // Delete them(glDeleteShader call is included)
  if( pVertexPrev && pFragPrev )
  {
    delete pVertexPrev;
    delete pFragPrev;
  }


  // Loads shader
  LoadShader("Vertex", GL_VERTEX_SHADER, s_vertexFile);
  LoadShader("Fragment", GL_FRAGMENT_SHADER, s_fragmentFile);

  // Delete Current Program
  glDeleteProgram(_program);

  // Create new Program
  GLuint newProgram = glCreateProgram();
  _program = newProgram;

  // Attach Shaders
  UseShader("Vertex");
  UseShader("Fragment");

  // Linking
  glLinkProgram(_program);
  const unsigned bufSize = 0x1000;
  char buf[bufSize] = { '\0' };
  GLint status = 0;
  glGetProgramiv(_program, GL_LINK_STATUS, &status );
  if( status )
    Gui::Get().Output("Shader program linked successfully.");
  glGetProgramInfoLog(_program, bufSize, nullptr, buf);
  Gui::Get().Output(buf);


  s_uniformErrHistory.clear();
}

void GLShaderManager::LoadShader( const std::string& name, GLenum type, const std::string& sourceFile )
    {
      Shader* pShader = _shaderMap[name] = new Shader(name, type);
      if( pShader )
      {
        pShader->ShaderSourceFromFile(sourceFile.c_str());
        pShader->Compile();
        if( pShader->GetCompileStatus() )
          Gui::Get().Output( (pShader->GetName() + " shader successfully compiled.").c_str());
        Gui::Get().Output(pShader->GetShaderInfoLog());
      }
    }
    void GLShaderManager::UseShader( const std::string& name )
    {
      Shader* pShader = _shaderMap[name];
      if( pShader )
      {
          pShader->AttachTo(_program);
      }
    }
4

0 回答 0