自用:关于opengl的着色器如何与.cpp文件配合使用

#Shader Vertex
#version 330 core
layout(location = 0) in vec2 position;
layout(location = 1) in vec3 aColor;
out vec3 vertexColor; 
void main()
{
    gl_Position = vec4(position,0.0,1.0);
    vertexColor = aColor;

}

#Shader fragment
#version 330 core
in vec3 vertexColor;
out vec4 FragColor; 

void main()
{
    FragColor = vec4(vertexColor, 1.0); 
}

我的理解是在顶点着色器书写完之后,片段着色器就会将这个out的参数传递给片段着色器,然后片段着色器再out出去的函数就是最终的颜色变化

如何在.cpp文件中读取文件
 

struct ShaderProgramSource {
    string VertexSource;
    string FragmentSource;
};


static ShaderProgramSource ParseShader(const string& filepath)
{
    ifstream stream(filepath);

    enum class ShaderType
    {
        NONE = -1, VERTEX = 0, FRAGMENT = 1
    };

    string line;
    stringstream ss[2];
    ShaderType type = ShaderType::NONE;
    while (getline(stream, line))
    {
        if (line.find("#Shader") != string::npos)
        {
            if (line.find("Vertex") != string::npos)
                type = ShaderType::VERTEX;
            else if (line.find("fragment") != string::npos)
                type = ShaderType::FRAGMENT;

        }
        else
        {
            ss[(int)type] << line << '\n';
        }
    }
    return { ss[0].str(),ss[1].str() };
}

基本的逻辑就是读取给定的文件地址,然后定义一个enum用来标记当前读取的字符串是那种类型的文件,然后将读取出来的文件全部传出去就行了

 

static unsigned int CompileShader(unsigned int type, const string& source)
{
    unsigned int id = glCreateShader(type);//创建一个着色器对象,type传入的是着色器的类型
    const char* src = source.c_str();
    glShaderSource(id, 1, &src, nullptr);//将源代码和着色器链接起来
    glCompileShader(id);//编译着色器

    int result;
    glGetShaderiv(id, GL_COMPILE_STATUS, &result);
    if (result == GL_FALSE)
    {
        int length;
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
        char* message = (char*)alloca(length * sizeof(char));
        glGetShaderInfoLog(id, length, &length, message);
        cout << "Failed to compile" << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << "shader!" << endl;
        cout << message << endl;
        glDeleteShader(id);
        return 0;
    }
    return id;
}

这个就是编译着色器的程序 第一个参数代表编译一个什么类型的程序,是顶点还是片段,这里要先创建一个编译的句柄,用无符号整形
 

参数说明(glShaderSource)

  1. shader:

    • 这是要设置源代码的着色器对象的 ID。通常是在调用 glCreateShader 时生成的。
  2. count:

    • 这是源代码字符串的数量。可以一次传入多个字符串,这对于大的着色器源代码非常有用。
  3. string:

    • 这是指向字符串的指针数组,包含着色器的源代码。在你的代码中,这个参数是 &src,这是一个指向 const char* 的指针。
  4. length:

    • 这是一个可选参数,可以用来指定每个字符串的长度。如果这个参数为 nullptr,OpenGL 将假设字符串以空字符(\0)结束。

其实到这里,也就是调用完这个参数后就可以结束了,但是为了检测哪里有错,就要增加一些错误日志输出
 

static unsigned int CreateShader(const string& vertexShader, const string& fragmentShader)
{
    unsigned int program = glCreateProgram();//创建一个着色器程序
    unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
    unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);

    glAttachShader(program, vs);
    glAttachShader(program, fs);//将编译好的着色器给到这个着色器程序
    glLinkProgram(program);//将这个着色器程序和原来的程序链接
    glValidateProgram(program);//验证程序

    glDeleteShader(vs);
    glDeleteShader(fs);//链接完以后就不再需要了

    return program;
}


最后就是先创建一个主着色器程序,将刚刚编译好的着色器都连接到这个上面
然后就是将这个着色器程序作为渲染管线,并且要进行验证,为了资源不被浪费记得删除编译好的着色器文件,只要返回着色器程序就行了

 

ShaderProgramSource source = ParseShader("Shader.shader");
unsigned int shader = CreateShader(source.VertexSource, source.FragmentSource);

cout << "Vertex" << endl;
cout << source.VertexSource << endl;
cout << "FRAGMENT" << endl;
cout << source.FragmentSource << endl;
glUseProgram(shader);


最后就是运行着色器了glUseProgram(shader)就可以只用渲染管线了,在结尾别忘了删除这个管线

 glDeleteProgram(shader);//删除着色器



下面是我的两个文件的代码,里面的Parseshader()里面的路径写自己的
 

#include<GL/glew.h>
#include <GLFW/glfw3.h>
#include<iostream>
#include<string>
#include<fstream>
#include<sstream>
using namespace std;


//以下三个函数是编译着色器文件的函数
struct ShaderProgramSource {
    string VertexSource;
    string FragmentSource;
};


static ShaderProgramSource ParseShader(const string& filepath)
{
    ifstream stream(filepath);

    enum class ShaderType
    {
        NONE = -1, VERTEX = 0, FRAGMENT = 1
    };

    string line;
    stringstream ss[2];
    ShaderType type = ShaderType::NONE;
    while (getline(stream, line))
    {
        if (line.find("#Shader") != string::npos)
        {
            if (line.find("Vertex") != string::npos)
                type = ShaderType::VERTEX;
            else if (line.find("fragment") != string::npos)
                type = ShaderType::FRAGMENT;

        }
        else
        {
            ss[(int)type] << line << '\n';
        }
    }
    return { ss[0].str(),ss[1].str() };
}


static unsigned int CompileShader(unsigned int type, const string& source)
{
    unsigned int id = glCreateShader(type);//创建一个着色器对象,type传入的是着色器的类型
    const char* src = source.c_str();
    glShaderSource(id, 1, &src, nullptr);//将源代码和着色器链接起来
    glCompileShader(id);//编译着色器

    int result;
    glGetShaderiv(id, GL_COMPILE_STATUS, &result);
    if (result == GL_FALSE)
    {
        int length;
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
        char* message = (char*)alloca(length * sizeof(char));
        glGetShaderInfoLog(id, length, &length, message);
        cout << "Failed to compile" << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << "shader!" << endl;
        cout << message << endl;
        glDeleteShader(id);
        return 0;
    }
    return id;
}

static unsigned int CreateShader(const string& vertexShader, const string& fragmentShader)
{
    unsigned int program = glCreateProgram();//创建一个着色器程序
    unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
    unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);

    glAttachShader(program, vs);
    glAttachShader(program, fs);//将编译好的着色器给到这个着色器程序
    glLinkProgram(program);//将这个着色器程序和原来的程序链接
    glValidateProgram(program);//验证程序

    glDeleteShader(vs);
    glDeleteShader(fs);//链接完以后就不再需要了

    return program;
}




void setVBOVAO(GLuint& VAO, GLuint& VBO, GLfloat* vertices, GLsizei vertexCount)
{
    glGenVertexArrays(1, &VAO);//由传入的参数创建一个VAO
    glBindVertexArray(VAO);//绑定到当前的VBO

    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);
    glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(GLfloat), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void*)0);//当只有顶点信息的时候stride可以是零
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, 0); //解绑VBO
    glBindVertexArray(0); // 解绑VAO


}


int main(void)
{
    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    // Initialize GLEW
    if (glewInit() != GLEW_OK) {
        return -1;
    }

    GLuint VAO[4], VBO[4];//分别用来存储点和三角形和直线的坐标

    float point[] = {
        -0.5f,0.0f
    };

    float line[] = {
        -0.4f,0.8f
    };

    float Rectangle[] = {
        0.4f,0.4f,1.0f,1.0f,1.0f,
        0.5f,0.5f,1.0f,1.0f,1.0f,
        0.5f,0.3f,1.0f,1.0f,1.0f
    };

    float rect[] = {
        -0.2f,-0.2f, 1.0,1.0,0.0,
         0.2f,-0.2f, 1.0,1.0,0.0,
         -0.2f, 0.2f, 1.0,1.0,0.0,
         -0.2f, 0.2f, 1.0,1.0,0.0,
         0.2f, 0.2f, 1.0,1.0,0.0,
         0.2f,-0.2f, 1.0,1.0,0.0
        
    };

    setVBOVAO(VAO[2], VBO[2], Rectangle, 15);
    setVBOVAO(VAO[3], VBO[3], rect, 30);

    ShaderProgramSource source = ParseShader("Shader.shader");
    unsigned int shader = CreateShader(source.VertexSource, source.FragmentSource);

    cout << "Vertex" << endl;
    cout << source.VertexSource << endl;
    cout << "FRAGMENT" << endl;
    cout << source.FragmentSource << endl;
    glUseProgram(shader);

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT);

        // 绘制三角形
        glBindVertexArray(VAO[2]);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        glBindVertexArray(VAO[3]);
        glDrawArrays(GL_TRIANGLES, 0, 6);

        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }
    glDeleteProgram(shader);//删除着色器
    glfwTerminate();
    return 0;
}


Shader.shader

#Shader Vertex
#version 330 core
layout(location = 0) in vec2 position;
layout(location = 1) in vec3 aColor;
out vec3 vertexColor; 
void main()
{
    gl_Position = vec4(position,0.0,1.0);
    vertexColor = aColor;

}

#Shader fragment
#version 330 core
in vec3 vertexColor;
out vec4 FragColor; 

void main()
{
    FragColor = vec4(vertexColor, 1.0); 
}

基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CNN硬件加速器入门级项目),该项目是个人毕设项目,答辩评审分达到98分,代码都经过调试测试,确保可以运行!欢迎下载使用,可用于小白学习、进阶。该资源主要针对计算机、通信、人工智能、自动化等相关专业的学生、老师或从业者下载使用,亦可作为期末课程设计、课程大作业、毕业设计等。项目整体具有较高的学习借鉴价值!基础能力强的可以在此基础上修改调整,以实现不同的功能。 基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CNN硬件加速器入门级项目)基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CNN硬件加速器入门级项目)基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CNN硬件加速器入门级项目)基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CNN硬件加速器入门级项目)基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CNN硬件加速器入门级项目)基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CNN硬件加速器入门级项目)基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CNN硬件加速器入门级项目)基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CNN硬件加速器入门级项目)基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CNN硬件加速器入门级项目)基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CNN硬件加速器入门级项目)基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CNN硬件加速器入门级项目)基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CNN硬件加速器入门级项目)基于PYNQ-Z2实现手写数字识别卷积神经网络硬件加速器源代码(CN
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值