OpenGL C++ 基本框架 - VBO, IBO, VAO, Shader, Scene

4 篇文章 0 订阅
3 篇文章 0 订阅

    class VertexBuffer
    {
    public:
      GLuint m_ID=0;
      GLfloat* m_Data=0;
      size_t m_Size=0;

      VertexBuffer() {};
      VertexBuffer(float* data, size_t size);
      ~VertexBuffer() { if(m_ID>0) glDeleteBuffers(1, &m_ID); };
      void create(float* data, size_t size)
      {
        m_Data = data; m_Size = size; 
        glGenBuffers(1, &m_ID); Bind(); glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
      }

      void Bind() const { glBindBuffer(GL_ARRAY_BUFFER, m_ID); }
      void Unbind() const {  glBindBuffer(GL_ARRAY_BUFFER, 0); }
    };


    class IndexBuffer
    {
    public:
      GLuint m_ID=0;
      GLuint* m_Data = 0;
      size_t m_Size = 0;
      int m_Count = 0;

      IndexBuffer() { }
      IndexBuffer(unsigned int* data, size_t size) { create(data, size); }

      void create(unsigned int* data, size_t size)
      {
        m_Data = data; m_Size = size; m_Count = (int)(m_Size / sizeof(GLuint));
        glGenBuffers(1, &m_ID); Bind(); glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
      }

      ~IndexBuffer() { if (m_ID > 0) glDeleteBuffers(1, &m_ID); };

      void Bind() const { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ID);  }
      void Unbind() const { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); }

    };


    struct VertexBufferAttribute
    {
      GLuint offset;     // offset/start position in stride
      GLuint type;       // data type
      GLuint count;      // data count
      GLuint size;       // count * sizeof(type)
    };


    class VertexArray
    {
    public:
      GLuint m_ID = 0;
      std::vector<VertexBufferAttribute> m_Attributes;
      GLuint m_Stride = 0;

      VertexArray() { glGenVertexArrays(1, &m_ID); Bind(); }
      ~VertexArray() { if (m_ID > 0) glDeleteVertexArrays(1, &m_ID); }


      void Bind() const { glBindVertexArray(m_ID); }
      void Unbind() const { glBindVertexArray(0); }

      template<typename T>
      void Push(GLuint count) {  }

      template<>
      void Push<GLfloat>(GLuint count)
      {
        GLuint size = sizeof(GLfloat) * count; m_Attributes.push_back({ m_Stride, GL_FLOAT, count, size }); m_Stride += size;
      }

      template<>
      void Push<GLuint>(GLuint count)
      {
        GLuint size = sizeof(GLuint) * count; m_Attributes.push_back({ m_Stride, GL_UNSIGNED_INT, count, size }); m_Stride += size;
      }

      void SetAttributes()
      {
        int location = 0;
        for (auto& a : m_Attributes)
        {
          glVertexAttribPointer(location, a.count, a.type, GL_FALSE, m_Stride, (void*)(uint64_t)a.offset);
          glEnableVertexAttribArray(location);
          location++;
        }
      }
    };



    class Shader
    {
    public:
      GLuint m_ID = 0;
      std::map<const char*, GLint> m_Uniforms;

      Shader() {  }
      ~Shader() { if (m_ID > 0) glDeleteProgram(m_ID); }

      GLuint Compile(const char* source, GLenum type)
      {
        GLuint shader = glCreateShader(type); glShaderSource(shader, 1, &source, 0); glCompileShader(shader);
        int success; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success)
        {
          int len; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); char* info = (char*)malloc(len * sizeof(char));
          glGetShaderInfoLog(shader, len, &len, info); printf("compile shader error: %s\n\nshader source: %s\n", info, source); free(info);
          glDeleteShader(shader); return -1;
        }
        return shader;
      }

      GLuint CreateProgram(const char* vertex_shader_source, const char* fragment_shader_source)
      {
        GLint64 vertex_shader = Compile(vertex_shader_source, GL_VERTEX_SHADER); if (vertex_shader < 0) throw std::invalid_argument("vertex_shader_source compile fail");
        GLint64 fragment_shader = Compile(fragment_shader_source, GL_FRAGMENT_SHADER); if (fragment_shader < 0) throw std::invalid_argument("fragment_shader_source compile fail");
        m_ID = glCreateProgram(); glAttachShader(m_ID, (GLuint)vertex_shader); glAttachShader(m_ID, (GLuint)fragment_shader); glLinkProgram(m_ID); // glValidateProgram(program);
        int success; glGetProgramiv(m_ID, GL_LINK_STATUS, &success); if (!success)
        {
          int len;  glGetProgramiv(m_ID, GL_INFO_LOG_LENGTH, &len);  char* info = (char*)malloc(len * sizeof(char));
          glGetProgramInfoLog(m_ID, len, &len, info); printf("link shader program error: %s\n", info); free(info);
          throw std::invalid_argument("shader source compile and link fail.");
        }
        // glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); // keep source for debug
        return m_ID;
      }

      void GetUniforms(std::vector<const char*> names)
      {
        Bind();
        for (auto& name : names)
        {
          auto location = m_Uniforms[name] = glGetUniformLocation(m_ID, name);
          if (location < 0) { printf("error when getting uniform location by name %s\n", name); throw std::invalid_argument("get uniform fail."); }
        }
      }


      void Bind() const { glUseProgram(m_ID); }
      void Unbind() const { glUseProgram(0); }

    };



    class SceneCombine_red : public Scene
    {
    public:
      SceneCombine_red(float ww, float wh)
      {
        this->ww = ww; this->wh = wh;

        float vertexes[] = {
          -0.5f,   0.5f,  0.0f,     0.0f, 0.0f, 1.0f, 1.0f,  // 0  右下角
           0.5f,  -0.1f,  0.0f,     0.0f, 0.0f, 1.0f, 1.0f,  // 1  中左点
           0.5f,   0.5f,  0.0f,     0.0f, 0.0f, 1.0f, 1.0f,  // 2  左下脚
          -0.5f,  -0.1f,  0.0f,     0.0f, 0.0f, 1.0f, 1.0f,  // 3  中右点                      
          -0.3f,   0.2f,  0.0f,     1.0f, 0.0f, 0.0f, 0.0f,   // 4  顶方块左下
           0.8f,  -0.5f,  0.0f,     1.0f, 0.0f, 0.0f, 0.0f,   // 5  顶方块左上
          -0.3f,  -0.5f,  0.0f,     1.0f, 0.0f, 0.0f, 0.0f,   // 6  顶方块右下
           0.8f,   0.2f,  0.0f,     1.0f, 0.0f, 0.0f, 0.0f,   // 7  顶方块右上
        };
        unsigned int indices[] = {
            0, 1, 2,
            0, 1, 3,
            4, 5, 6,
            4, 5, 7,
        };

        m_VertexShaderSource = (char*)"#version 460 core\n"
          "layout(location=0) in vec4 a_Position;\n"
          "layout(location=1) in vec4 a_Color;\n"
          "uniform mat4 u_Mvp;\n"
          "out vec4 v_Color;\n"
          "void main()\n"
          "{\n"
          "  gl_Position = a_Position;  v_Color=a_Color;  \n"
          "}\n\0";

        m_FragmentShaderSource = (char*)"#version 460 core\n"
          "out vec4 FragColor;\n"
          "in vec4 v_Color;\n"
          "void main()\n"
          "{\n"
          "  FragColor = v_Color;\n"
          "}\n\0";


        m_VB.create(vertexes, sizeof(vertexes));
        m_VA.Push<float>(3); // position
        m_VA.Push<float>(4); // color
        m_IB.create(indices, sizeof(indices));
        m_VA.SetAttributes();
        m_VA.Unbind();

        m_Shader.CreateProgram(m_VertexShaderSource, m_FragmentShaderSource);
        //m_Shader.GetUniforms({ u_Mvp });

        //m_Proj = glm::ortho(0.0f, ww, 0.0f, wh, -1.0f, 1.0f);     // the values are the edges of vertexes positions
        //m_Model = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0));
        //m_View = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0));
        //m_Mvp = m_View * m_Model * m_Proj; //glUniformMatrix4fv(m_Shader.m_Uniforms[u_Mvp], 1, GL_FALSE, &m_Mvp[0][0]);
      }

      void Bind() override
      {
        m_Shader.Bind(); m_VA.Bind();
      }
      void Render() override
      {        
        glDrawElements(GL_TRIANGLES, m_IB.m_Count, GL_UNSIGNED_INT, nullptr);
      }
      void RenderSettings() override
      {

      }

      const char* u_Mvp = "u_Mvp";
      const char* u_Color = "u_Color";
    };

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qiuzen

您的资助将帮助我创作更好的作品

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值