• Hello Shader之Hello Trangle


    这两天配了一下现代OpenGL的开发环境,同时看了一下基础知识和编程规范

    写了一个编译GLSL语言的前端程序和一个Hello trangle的程序

    另外,推荐两个资源

    1.学习网站Learn Opengl

    2.OpenGL编程指南第八版(俗称红宝书)

    网站有的地方降得不好可以看书

    接下来总结一下知识点:

    1.现代GPU内部的管线,其中蓝色部分是可编程的部分,gpu内部有许许多多的微程序,他们可以并行地执行,

    可编程的微程序为蓝色部分,称为shader,即着色器程序,其中顶点着色器和片段着色器应用最多。

    2.着色器语言GLSL的使用,着色器程序的编译,链接

      这个我专门造了一个轮子,封装了一下

    #ifndef _SHADER_H_
    #define _SHADER_H_
    
    #include <GLEW/glew.h>
    #include <iterator>     // std::istreambuf_iterator
    #include <string>       
    #include <vector>
    #include <iostream>
    #include <fstream>
    
    struct ShaderFile
    {
    	GLenum shaderType;
    	const char* filePath;
    	ShaderFile(GLenum type, const char* path) 
    		:shaderType(type), filePath(path){}
    };
    
    class Shader
    {
    public:
    	Shader(const char* vertexPath, const char* fragPath) :programId(0)
    	{
    		std::vector<ShaderFile> fileVec;
    		fileVec.push_back(ShaderFile(GL_VERTEX_SHADER, vertexPath));
    		fileVec.push_back(ShaderFile(GL_FRAGMENT_SHADER, fragPath));
    		loadFromFile(fileVec);
    	}
    	Shader(const char* vertexPath, const char* fragPath, const char* geometryPath) :programId(0)
    	{
    		std::vector<ShaderFile> fileVec;
    		fileVec.push_back(ShaderFile(GL_VERTEX_SHADER, vertexPath));
    		fileVec.push_back(ShaderFile(GL_FRAGMENT_SHADER, fragPath));
    		fileVec.push_back(ShaderFile(GL_GEOMETRY_SHADER, geometryPath));
    		loadFromFile(fileVec);
    	}
    	void use()
    	{
    		glUseProgram(this->programId);
    	}
    	~Shader()
    	{
    		if (this->programId)
    		{
    			glDeleteProgram(this->programId);
    		}
    	}
    	GLuint GetProgramID()
    	{
    		return programId;
    	}
    public:
    	GLuint programId;
    private:
    	/*
    	* 从文件加载顶点和片元着色器
    	* 传递参数为 [(着色器文件类型,着色器文件路径)+]
    	*/
    	void loadFromFile(std::vector<ShaderFile>& shaderFileVec)
    	{
    		std::vector<GLuint> shaderObjectIdVec;
    		std::string vertexSource, fragSource;
    		std::vector<std::string> sourceVec;
    		size_t shaderCount = shaderFileVec.size();
    		// 读取文件源代码
    		for (size_t i = 0; i < shaderCount; ++i)
    		{
    			std::string shaderSource;
    			if (!loadShaderSource(shaderFileVec[i].filePath, shaderSource))
    			{
    				std::cout << "Error::Shader could not load file:" << shaderFileVec[i].filePath << std::endl;
    				return;
    			}
    			sourceVec.push_back(shaderSource);
    		}
    		bool bSuccess = true;
    		// 编译shader object
    		for (size_t i = 0; i < shaderCount; ++i)
    		{
    			GLuint shaderId = glCreateShader(shaderFileVec[i].shaderType);
    			const char *c_str = sourceVec[i].c_str();
    			glShaderSource(shaderId, 1, &c_str, NULL);
    			glCompileShader(shaderId);
    			GLint compileStatus = 0;
    			glGetShaderiv(shaderId, GL_COMPILE_STATUS, &compileStatus); // 检查编译状态
    			if (compileStatus == GL_FALSE) // 获取错误报告
    			{
    				GLint maxLength = 0;
    				glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &maxLength);
    				std::vector<GLchar> errLog(maxLength);
    				glGetShaderInfoLog(shaderId, maxLength, &maxLength, &errLog[0]);
    				std::cout << "Error::Shader file [" << shaderFileVec[i].filePath << " ] compiled failed,"
    						  << &errLog[0] << std::endl;
    				bSuccess = false;
    			}
    			shaderObjectIdVec.push_back(shaderId);
    		}
    		// 链接shader program
    		if (bSuccess)
    		{
    			this->programId = glCreateProgram();
    			for (size_t i = 0; i < shaderCount; ++i)
    			{
    				glAttachShader(this->programId, shaderObjectIdVec[i]);
    			}
    			glLinkProgram(this->programId);
    			GLint linkStatus;
    			glGetProgramiv(this->programId, GL_LINK_STATUS, &linkStatus);
    			if (linkStatus == GL_FALSE)
    			{
    				GLint maxLength = 0;
    				glGetProgramiv(this->programId, GL_INFO_LOG_LENGTH, &maxLength);
    				std::vector<GLchar> errLog(maxLength);
    				glGetProgramInfoLog(this->programId, maxLength, &maxLength, &errLog[0]);
    				std::cout << "Error::shader link failed," << &errLog[0] << std::endl;
    			}
    		}
    		// 链接完成后detach 并释放shader object
    		for (size_t i = 0; i < shaderCount; ++i)
    		{
    			if (this->programId != 0)
    			{
    				glDetachShader(this->programId, shaderObjectIdVec[i]);
    			}
    			glDeleteShader(shaderObjectIdVec[i]);
    		}
    	}
    	/*
    	* 读取着色器程序源码
    	*/
    	bool loadShaderSource(const char* filePath,std::string& source)
    	{
    		source.clear();
    		std::ifstream in_stream(filePath);
    		if (!in_stream)
    		{
    			return false;
    		}
    		source.assign(std::istreambuf_iterator<char>(in_stream),
    			std::istreambuf_iterator<char>()); // 文件流迭代器构造字符串
    		return true;
    	}
    };
    #endif
    

      

    3.关于VBO和VAO

    这两个的使用函数等等我就不搬上来了,没什么意义

    只解释下两者的实质和容易出错的地方

    VBO译名顶点缓冲对象,用来从CPU内存读取数据到GPU内存(以后称作显存)中,VBO的内存是独立的,真正存在的,同时一个VBO只能存一段内存

    VAO称为顶点数组对象,用来负责组织,解释VBO,记录渲染环境,VAO并不是占有独立内存,仅仅相当于做个索引的作用,可以想象成指针,也就是说VAO是依托于VBO存在的,一旦VBO改变了,VAO也就改变了

    最后,鹅厂的面试经历和个人这一段时间和大学生活的总结展望在论坛上开了个坑,最近踪迹应该在论坛上:

    传送门:

    腾讯实习生面试经历(不打算一次写完,开个坑,慢慢更,同时也算是帮助自己思考些未来)

  • 相关阅读:
    COBBLER无人值守安装
    消息头 Content-Type引发的问题:Jmeter请求中postdata不是期望的,响应数据请求参数为null;已经请求没问题,可变量还是为空
    python爬虫-'gbk' codec can't encode character 'xa0' in position 134: illegal multibyte sequence
    正则表达式30分钟入门教程-链接
    linux常见命令学习汇总3-控制语句
    postman循环操作及响应判断-支持文本多变量输入
    linux常见命令学习汇总2-运算符
    linux常见命令学习汇总1
    Jmeter连接数据库方法与问题:Cannot load JDBC driver class 'com.mysql.jdbc.Driver'
    mysql学习笔记-ifnull()函数与nullif()函数
  • 原文地址:https://www.cnblogs.com/YTYMblog/p/6767933.html
Copyright © 2020-2023  润新知