OpenGL学习记录Day3(GLSL初识与Shader类的封装)

OpenGl学习记录

今天主要学习了如何去写shader,了解了GLSL语言的一些语法

参考文档:LearnOpenGL https://learnopengl-cn.github.io/

关于GLSL:
  • 向量类型
类型含义
vecn包含n个float分量的默认向量
bvecn包含n个bool分量的向量
ivecn包含n个int分量的向量
uvecn包含n个unsigned int分量的向量
dvecn包含n个double分量的向量

在使用时,我们可以通过类似vec.x、vec.y这种操作来获取它的分量,并且允许向量作为参数传给不同的向量构造函数

vec3 myVec = vec3(0.5, 0.5, 0.5);
vec4 otherVec = vec4(myVec, 1.0);

还有另一种重组的语法

vec3 myVec = vec3(0.5, 0.5, 0.5);
vec2 newVec = vec2(0.3, 0.3)
vec4 otherVec = vec3.zyxx + vec2.xyxy;

如上所示,我们可以随意的将一个向量的分量赋予到另一个向量的分量上,并且可以进行运算操作

  • 输入输出

GLSL中会运用 inout 关键字来定义输入输出

在片元着色器中,我们可以直接将顶点着色器的输出用作输入

而在顶点着色器中,我们是以一种特殊的形式接收数据的,所以需要加入 layout (location = 0) 这样的标识符,这个标识符定义了我们在获取数据的时候应该在哪一个位置获取

如下面所示的例子:

float vertices[] = {
       // 位置              // 颜色
        0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,   // 右下
       -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   // 左下
        0.0f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f    // 顶部
   };

这个顶点数据不仅含有位置信息,而且含有颜色信息,这时我们在接收数据时需要运用位置标识符将两组数据分开存储

layout (location = 0) in vec3 aPos;   // 位置变量的属性位置值为 0 
layout (location = 1) in vec3 aColor; // 颜色变量的属性位置值为 1

同时,我们需要更新顶点的格式,保证我们在运行shader时获取的数据是对的

// 位置属性
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 颜色属性
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3* sizeof(float)));
glEnableVertexAttribArray(1);
  • uniform

uniform是全局变量,在渲染过程的任何阶段都可以被访问,如下面代码所示,我们定义了一个uniform变量,并将它作为片元着色器颜色渲染的输出值

#version 330 core
out vec4 FragColor;

uniform vec4 ourColor; 

void main()
{
    FragColor = ourColor;
}

这时我们想要访问这个变量,对它进行动态修改,需进行如下操作

//获取到ourColor变量的位置
int ourColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
//通过 glUniform 函数设置uniform的值
glUniform4f(ourColorLocation, 0.0f, 1.0f, 0.0f, 1.0f);
封装一个着色器类:
class Shader
{
public:
	//shader程序的id
	unsigned int ID;

	Shader(const char* vertexPath, const char* fragmentPath);

	//激活程序
	void use();

	//uniform工具函数
	void setBool(const string& name, bool value) const;
	void setInt(const string& name, int value) const;
	void setFloat(const string& name, float value) const;
};

定义好了着色器类以后,我们开始实现里面的构造函数和成员函数

  • 构造函数
Shader::Shader(const char* vertexPath, const char* fragmentPath) {
	string vertexCode;
	string fragmentCode;
	ifstream vShaderFile;
	ifstream fShaderFile;
	vShaderFile.exceptions(ifstream::failbit | ifstream::badbit);
	fShaderFile.exceptions(ifstream::failbit | ifstream::badbit);
	try {
		//打开文件
		vShaderFile.open(vertexPath, ios::in);
		fShaderFile.open(fragmentPath, ios::in);
		
		//读取内容到数据流
		stringstream vShaderStream, fShaderStream;
		vShaderStream << vShaderFile.rdbuf();
		fShaderStream << fShaderFile.rdbuf();
		//关闭文件
		vShaderFile.close();
		fShaderFile.close();

		//将数据流转换成string
		vertexCode = vShaderStream.str();
		fragmentCode = fShaderStream.str();
	}
	catch (std::ifstream::failure e)
	{
		std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
	}
	const char* vShaderCode = vertexCode.c_str();
	const char* fShaderCode = fragmentCode.c_str();

	
	unsigned int vertexShader,fragmentShader;
	int  success;
	char infoLog[512];

	//顶点着色器
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, &vShaderCode, NULL);
	glCompileShader(vertexShader);
	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
		cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << endl;
	}

	//片元着色器
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fShaderCode, NULL);
	glCompileShader(fragmentShader);
	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
		cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << endl;
	}


	//着色器程序
	ID = glCreateProgram();
	glAttachShader(ID, vertexShader);
	glAttachShader(ID, fragmentShader);
	glLinkProgram(ID);
	glGetProgramiv(ID, GL_LINK_STATUS, &success);
	if (!success)
	{
		glGetProgramInfoLog(ID, 512, NULL, infoLog);
		cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << endl;
	}

	//删除着色器
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);

}
  • 成员函数
void Shader::use() {
	glUseProgram(ID);
}

void Shader::setBool(const string& name, bool value) const
{
	glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}
void Shader::setInt(const string& name, int value) const
{
	glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}
void Shader::setFloat(const string& name, float value) const
{
	glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}
  • 着色器类的使用

当上面的一切准备好之后,我们只需要传入顶点着色器和片元着色器就可以使用了

//创建一个VAO对象,将之后的顶点属性储存在这个VAO中
unsigned int VAO;
//构建顶点数据
draw(VAO);
//使用构造函数构造Shader
Shader myShader("vertexShader.vs", "fragmentShader.fs");

//渲染循环
while (!glfwWindowShouldClose(window)) {
  ...
  //渲染部分
  myShader.use();
  ...
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
区块链起源于比特币,2008年11月1日,一位自称中本聪(Satoshi Nakamoto)的人发表了《比特币:一种点对点的电子现金系统》一文 4  ,阐述了基于P2P网络技术、加密技术、时间戳技术、区块链技术等的电子现金系统的构架理念,这标志着比特币的诞生。两个月后理论步入实践,2009年1月3日第一个序号为0的创世区块诞生。几天后2009年1月9日出现序号为1的区块,并与序号为0的创世区块相连接形成了链,标志着区块链的诞生 5  。近年来,世界对比特币的态度起起落落,但作为比特币底层技术之一的区块链技术日益受到重视。在比特币形成过程中,区块是一个一个的存储单元,记录了一定时间内各个区块节点全部的交流信息。各个区块之间通过随机散列(也称哈希算法)实现链接,后一个区块包含前一个区块的哈希值,随着信息交流的扩大,一个区块与一个区块相继接续,形成的结果就叫区块链 6  。什么是区块链?从科技层面来看,区块链涉及数学、密码学、互联网和计算机编程等很多科学技术问题。从应用视角来看,简单来说,区块链是一个分布式的共享账本和数据库,具有去中心化、不可篡改、全程留痕、可以追溯、集体维护、公开透明等特点。这些特点保证了区块链的“诚实”与“透明”,为区块链创造信任奠定基础。而区块链丰富的应用场景,基本上都基于区块链能够解决信息不对称问题,实现多个主体之间的协作信任与一致行动 7  。区块链是分布式数据存储、点对点传输、共机制、加密算法等计算机技术的新型应用模式。区块链(Blockchain),是比特币的一个重要概念,它本质上是一个去中心化的数据库,同时作为比特币的底层技术,是一串使用密码学方法相关联产生的数据块,每一个数据块中包含了一批次比特币网络交易的信息,用于验证其信息的有效性(防伪)和生成下一个区块 8  。比特币白皮书英文原版 4  其实并未出现 blockchain 一词,而是使用的 chain of blocks。最早的比特币白皮书中文翻译版 9  中,将 chain of blocks 翻译成了区块链。这是“区块链”这一中文词最早的出现时间。国家互联网信息办公室2019年1月10日发布《区块链信息服务管理规定》,自2019年2月15日起施行 1  。作为核心技术自主创新的重要突破口,区块链的安全风险问题被视为当前制约行业健康发展的一大短板,频频发生的安全事件为业界敲响警钟。拥抱区块链,需要加快探索建立适应区块链技术机制的安全保障体系。 102008年由中本聪第一次提出了区块链的概念 4  ,在随后的几年中,区块链成为了电子货币比特币的核心组成部分:作为所有交易的公共账簿。通过利用点对点网络和分布式时间戳服务器,区块链数据库能够进行自主管理。为比特币而发明的区块链使它成为第一个解决重复消费问题的数字货币。比特币的设计已经成为其他应用程序的灵感来源。2014年,区块链2.0”成为一个关于去中心化区块链数据库的术语。对这个第二代可编程区块链,经济学家们认为它是一种编程语言,可以允许用户写出更精密和智能的协议 11  。因此,当利润达到一定程度的时候,就能够从完成的货运订单或者共享证书的分红中获得收益。区块链2.0技术跳过了交易和“价值交换中担任金钱和信息仲裁的中介机构”。它们被用来使人们远离全球化经济,使隐私得到保护,使人们“将掌握的信息兑换成货币”,并且有能力保证知产权的所有者得到收益。第二代区块链技术使存储个人的“永久数字ID和形象”成为可能,并且对“潜在的社会财富分配”不平等提供解决方案 12  。2016年1月20日,中国人民银行数字货币研讨会宣布对数字货币研究取得阶段性成果。会议肯定了数字货币在降低传统货币发行等方面的价值,并表示央行在探索发行数字货币。中国人民银行数字货币研讨会的表达大大增强了数字货币行业信心。这是继2013年12月5日央行五部委发布关于防范比特币风险的通知之后,第一次对数字货币表示明确的态度。 13 2016年12月20日,数字货币联盟——中国FinTech数字货币联盟及FinTech研究院正式筹建 14  。如今,比特币仍是数字货币的绝对主流,数字货币呈现了百花齐放的状态,常见的有bitcoin、litecoin、dogecoin、dashcoin,除了货币的应用之外,还有各种衍生应用,如以太坊Ethereum、Asch等底层应用开发平台以及NXT,SIA,比特股,MaidSafe,Ripple等行业应用 15  。公有区块链公有区块链(Public Block Chains)是指:世界上任何个体或者团体都可以发送交易,且交易能够获得该区块链的有效确认,任何人都可以参与其共过程。公有区块链是最早的区块链,也是应用最广泛的区块链,各大bitcoins系列的虚拟数字货币均基于公有区块链,世界上有且仅有一条该币种对应的区块链 16  。联合(行业)区块链 

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值