OpenGL——外部读档+异常报错

从外部读取shader文件:

先添加Shader类:

再创建vertexSource.txt和fragmentSource.txt两个文件:

如图填入shader:

在shader.h宣告:

 在shader.cpp中从外部读档:

#include "Shader.h"
#include <iostream>
#include<fstream>
#include <sstream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>

using namespace std;

Shader::Shader(const char* vertexPath,const char* fragmentPath)
{ // 1. 从文件路径中获取顶点/片段着色器
    ifstream vertexFile;
    ifstream fragmentFile;
    stringstream vertexSStream;
    stringstream fragmentSStream;

    // 打开文件
    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();//从硬盘读取资料
        fragmentSStream << fragmentFile.rdbuf();//从硬盘读取资料

        vertexString = vertexSStream.str();//转成字符串
        fragmentString = fragmentSStream.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);
        checkCompileErrors(vertex, "VERTEX");//异常报错提示

        fragment = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragment, 1, &fragmentSource, NULL);
        glCompileShader(fragment);
        checkCompileErrors(fragment, "FRAGMENT");//异常报错提示

        ID = glCreateProgram();
        glAttachShader(ID, vertex);
        glAttachShader(ID, fragment);
        glLinkProgram(ID);
        checkCompileErrors(ID, "PROGRAM");//异常报错提示

        glDeleteShader(vertex);
        glDeleteShader(fragment);

    }
    catch (const std::exception&ex)
    {
        printf(ex.what());//如果错误就跳到这执行 
    }
}

void Shader::use() {
    glUseProgram(ID);
}

void Shader::checkCompileErrors(unsigned int ID, std::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
    {
        glGetProgramiv(ID, GL_LINK_STATUS, &success);
        if (!success)
        {
            glGetProgramInfoLog(ID, 512, NULL, infoLog);
            cout << "progam Linking error:" << infoLog << endl;
        }
    }
};

main.cpp写入:

#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "Shader.h"

float vertices[] = {
        -0.5f,-0.5f,0.0f,1.0f,0,0,
        0.5f,-0.5f,0.0f,0,1.0f,0,
        0.5f,0.5f,0.0f,0,0,1.0f,
        -0.5f,0.5f,0.0f,1.0f,0,1.0f
};

unsigned int indices[] = { // 注意索引从0开始! 
    0, 1, 2,  //第一个三角形
    0, 2, 3   //第二个三角形
};


//函数在main之前存档
void processInput(GLFWwindow* window) {
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
    {//退出键关闭窗口
        glfwSetWindowShouldClose(window, true);
    }
}
int main(int argc, char* argv[]) {

    glfwInit();//初始化和创建窗口
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//提示用主版本号为3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//次版本号为3,即为3.3版本的OpenGL
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    //open GLFW window
    GLFWwindow* window = glfwCreateWindow(800, 600, "Test window", NULL, NULL);//800*600的窗口

    if (window == NULL) {//如果为空指针
        //std::cout << "open window failed." << std::endl;//打印失败
        printf("open window failes.");
        glfwTerminate();//终止
        return -1;
        //return EXIT_FAILURE;
    }

    glfwMakeContextCurrent(window);

    //init GLEW
    glewExperimental = true;

    if (glewInit() != GLEW_OK)
    {
        printf("Init GLEW failed.");
        //std::cout << "glew init failed." << std::endl;
        glfwTerminate();
        return -1;//-1代表不正常退出
    }

    glViewport(0, 0, 800, 600);//前两个参数控制窗口左下角的位置,后两个参数设置可绘制的像素大小

    //第一个参数表示我们打算将其应用到所有的三角形的正面和背面,第二个参数告诉我们用线来绘制
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//线框模式
    //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);//关掉线框模式

    Shader* myshader = new Shader("vertexSource.txt", "fragmentSource.txt");//指针调用

    unsigned int VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    unsigned int VBO;//顶点缓冲对象
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);//顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER,使用glBindBuffer函数把新创建的缓冲绑定到GL_ARRAY_BUFFER目标上
    //调用glBufferData函数,它会把之前定义的顶点数据复制到缓冲的内存中
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    unsigned int EBO;
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    //顶点属性,顶点属性的大小(vec3),数据类型,是否数据被标准化,步长,强制类型转换(表示位置数据在缓冲中起始位置的偏移量)
    glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(6);//启用顶点属性
    glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float)));
    glEnableVertexAttribArray(7);//启用顶点属性
    while (!glfwWindowShouldClose(window))
    {

        processInput(window);
        glClearColor(0.2f, 0.3f, 0.3f, 1.0);//清屏颜色填充RGB,透明度
        glClear(GL_COLOR_BUFFER_BIT);

        glBindVertexArray(VAO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

        myshader->use();
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);//改为glDrawElements即可。6为索引个数,0表示偏移。
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwTerminate();

    return 0;
}

 运行结果:没错!

 现在,修改vertexSource文件内容:

 运行:没出现图像,并且命令窗口报异常。

莫说我穷的叮当响,大袖揽清风。 莫讥我困时无处眠,天地做床被。 莫笑我渴时无美酒,江湖来做壶。
原文地址:https://www.cnblogs.com/huang--wei/p/10571940.html