OpenGL自制3D游戏引擎入门VI

Shader II 创建自己的着色器类

一、从文件读取

  1. 我们从C++文件流读取着色器内容,存储到几个String对象中
    傅老师の奇妙手绘

Shader.h代码如下

    #pragma once
    #include <string>

    using namespace std;
    class Shader
    {
    public:
        Shader(const char* vertexPath, const char* fragmentPath);
        //~Shader();
        string vertexString;
        string fragmentString;
        const char* vertexSource;
        const char* fragmentSource;
    };

Shader.cpp代码如下

    #include <iostream>
    #include <fstream>
    #include <sstream>

    #include "Shader.h"

    using namespace std;

    Shader::Shader(const char* vertexPath, const char* fragmentPath)
    {
        ifstream vertexFile;
        ifstream fragmentFile;

        stringstream vertexSStream;
        stringstream frangmentSStream;

        vertexFile.open(vertexPath);
        fragmentFile.open(fragmentPath);
        vertexFile.exceptions(ifstream::failbit || ifstream::badbit);
        fragmentFile.exceptions(ifstream::failbit || ifstream::badbit);

        try
        {
            if (!vertexFile.is_open() || !fragmentFile.is_open())
            {
                throw exception("open File error");
            }

            vertexSStream << vertexFile.rdbuf();
            frangmentSStream << fragmentFile.rdbuf();

            vertexString = vertexSStream.str();
            fragmentString = frangmentSStream.str();

            vertexSource = vertexString.c_str();
            fragmentSource = fragmentString.c_str();

            printf(vertexSource);
            printf("\n");
            printf(fragmentSource);

        }
        catch (const exception& e)
        {
            printf(e.what());
        }
    }

main函数中声明着色器类并修改对应文件

    Shader* testShader = new Shader("vertexSource.txt", "fragmentSource.txt");

    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &testShader->vertexSource, NULL);
    glCompileShader(vertexShader);

    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &testShader->fragmentSource, NULL);
    glCompileShader(fragmentShader);

二、编译和链接着色器

  1. Shader.cpp

     #include <iostream>
     #include <fstream>
     #include <sstream>
    
     #include <GL/glew.h>
     #include <GLFW/glfw3.h>
    
     #include "Shader.h"
    
     using namespace std;
    
     Shader::Shader(const char* vertexPath, const char* fragmentPath)
     {
         ifstream vertexFile;
         ifstream fragmentFile;
    
         stringstream vertexSStream;
         stringstream frangmentSStream;
    
         vertexFile.open(vertexPath);
         fragmentFile.open(fragmentPath);
         vertexFile.exceptions(ifstream::failbit || ifstream::badbit);
         fragmentFile.exceptions(ifstream::failbit || ifstream::badbit);
    
         try
         {
             if (!vertexFile.is_open() || !fragmentFile.is_open())
             {
                 throw exception("open File error");
             }
    
             vertexSStream << vertexFile.rdbuf();
             frangmentSStream << fragmentFile.rdbuf();
    
             vertexString = vertexSStream.str();
             fragmentString = frangmentSStream.str();
    
             vertexSource = vertexString.c_str();
             fragmentSource = fragmentString.c_str();
    
             unsigned int vertex, fragment;
    
             vertex = glCreateShader(GL_VERTEX_SHADER);
             glShaderSource(vertex, 1, &vertexSource, NULL);
             glCompileShader(vertex);
    
             fragment = glCreateShader(GL_FRAGMENT_SHADER);
             glShaderSource(fragment, 1, &fragmentSource, NULL);
             glCompileShader(fragment);
    
             ID = glCreateProgram();
             glAttachShader(ID, vertex);
             glAttachShader(ID, fragment);
             glLinkProgram(ID);
             glDeleteShader(vertex);
             glDeleteShader(fragment);
         }
         catch (const exception& e)
         {
             printf(e.what());
         }
     }
    
     void Shader::use()
     {
         glUseProgram(ID);
     }
    
  2. Shader.h

     #pragma once
     #include <string>
    
     using namespace std;
     class Shader
     {
     public:
         Shader(const char* vertexPath, const char* fragmentPath);
         //~Shader();
         string vertexString;
         string fragmentString;
         const char* vertexSource;
         const char* fragmentSource;
         unsigned int ID;	// shaderProgram ID
         void use();
     };
    
  3. main函数中对应的部分就可以删掉啦

三、收集错误信息

  1. 添加一个私有函数checkCompileError

     void Shader::checkCompileError(unsigned int ID,string type)
     {
         int success;
         char infoLog[512];
    
         if (type != "PROGRAM")
         {
             glGetShaderiv(ID, GL_COMPILE_STATUS, &success);
             if (!success)
             {
                 glGetShaderInfoLog(ID, 512, NULL, infoLog);;
                 cout << "Shader compile error:" << infoLog << endl;
             }
         }
         else
         {
             glGetShaderiv(ID,GL_LINK_STATUS, &success);
             if (!success)
             {
                 glGetProgramInfoLog(ID, 512, NULL, infoLog);
                 cout << "Program compile error:" << infoLog << endl;
             }
         }
     }
    
  2. 放在glCompileShader、glLinkProgram函数之后收集错误信息

(下接 OpenGL入门VII)

和装少女❀ Pid:59452194


OpenGL自制3D游戏引擎入门VI
https://baifabaiquan.cn/2021/03/25/OpenGL入门VI/
作者
白发败犬
发布于
2021年3月25日
许可协议