OpenGL原理与实践——核心模式(二):Shader变量、Shader类的封装以及EBO

news2024/9/22 5:36:27

目录

Shader内的一些关键字

向量

举例:shader之间的数据传输,并实现渐变颜色

举例:C++向shader传输数据的过程

代码整理——shader类的封装

加入颜色信息

索引绘制——EBO

整体代码以及渲染结果


Shader内的一些关键字

  • in:上个阶段传来的变量
  • out:输出下个阶段的内容
  • uniform:在C++程序传入shader的内容
  • main 函数:进行一系列操作

向量

操作非常灵活

举例:shader之间的数据传输,并实现渐变颜色

vertexShader.glsl

#version 330 core
layout (location = 0) in vec3 aPos;//由C++代码中VBO绑定的锚定点输入。

out vec4 vertexColor;

void main()
{
   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
   vertexColor=vec4(0.5,0.0,0.0,1.0);
};

fragmentShader.glsl 

#version 330 core
out vec4 FragColor;

in vec4 vertexColor;

void main()
{
    //FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
    FragColor = vertexColor;
};

vertexShader中的aPos,由

//对哪个锚点进行操作:layout=0的锚点,读3个顶点,类型为float,不需要归一化,每次步长为3个float大小,从0处开始读
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

进行读入;

随后vertexShader输出一个vertexColor传入下一个阶段,也就是fragmentShader。

fragmentShader接受vertexShader的输入(vertexColor),同时再输出一个FragColor。

举例:C++向shader传输数据的过程

直接上代码,注意需要把glUserProgram放在前面,启用shaderProblem这个状态

//渲染
void render() {
	glUseProgram(shaderProgram);
	float _time = glfwGetTime();
	float _green = sin(_time) * 0.5f + 0.5f;
	int _location = glGetUniformLocation(shaderProgram, "ourColor");
	glUniform4f(_location, 0.0f, _green, 0.0f, 1.0f);

	glBindVertexArray(VAO);
	//以三角形模式绘制,从第0个顶点开始,起作用的有3个点
	glDrawArrays(GL_TRIANGLES, 0, 3);
	glUseProgram(0);
}

渲染结果:

代码整理——shader类的封装

创建一个新的Shader类,抽象出一些重合度比较高的代码:

Shader.h

#pragma once

#include "Base.h"

class Shader
{
private:
	unsigned int m_shaderProgram;
public:
	Shader() {
		m_shaderProgram = 0;
	}
	~Shader() {}
public:
	void initShader(const char* _vertexPath, const char* _fragPath);
	void start() { glUseProgram(m_shaderProgram); }
	void end() { glUseProgram(0); }
};

然后把之前的代码copy进initShader即可。

另外将一些常用的头文件集成到Base.h中:

//Base.h
#pragma once
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>

加入颜色信息

我们在vertices中为三个顶点新添加颜色信息:

	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,并且激活这个layout:

这里注意步长变更为6个float,同时颜色的开始地址为第三个float处。

	//对哪个锚点进行操作:layout=0的锚点,读3个顶点,类型为float,不需要归一化,每次步长为3个float大小,从0处开始读
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(sizeof(float)*3));
	
	//打开锚点:激活
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);

之后,我们既然已经分配了layout=1的GPU空间,并令他为颜色的信息,那么在shader中也应该有所体现,需要读取layout=1处的颜色信息:

//vertexShader.glsl
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;

out vec4 outColor;

void main()
{
   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
   outColor = vec4(aColor, 1.0f);
};

并将颜色信息传入到fragmentShader中:

//fragmentShader.glsl
#version 330 core
out vec4 FragColor;

in vec4 outColor;

void main()
{
    FragColor = outColor;
};

渲染结果如下: 

索引绘制——EBO

EBO就是用来存储顶点索引的一块区域。

EBO的创建与绑定

与VAO和VBO一样的流程:

	glGenBuffers(1, &EBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

 另外需要注意的是render中需要更换绘制函数:

void render() {
	_shader.start();
	glBindVertexArray(VAO);
	//以三角形模式绘制,从第0个顶点开始,起作用的有3个点
	//glDrawArrays(GL_TRIANGLES, 0, 3);

	//以三角形模式绘制,用顶点索引
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

	_shader.end();
}

整体代码以及渲染结果

#include "Base.h"
#include "Shader.h"


void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
void initModel();
void initShader(const char* _vertexPath, const char* _fragPath);
void render();

unsigned int VBO = 0;
unsigned int VAO = 0;
unsigned int EBO = 0;

Shader _shader;

int main() {
	//初始化OpenGL上下文环境,OpenGL是一个状态机,会保存当前状态下的渲染状态以及管线的状态
	glfwInit(); 
	//,3版本以上
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	//用OpenGL核心开发模式
	glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);

	//创建窗体
	GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGl Core", nullptr, nullptr);
	if (window == nullptr) {
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	//把当前上下文绑定至当前窗口
	glfwMakeContextCurrent(window);

	//通过glad绑定各种函数指针
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	//视口:需要渲染的东西在哪里
	glViewport(0, 0, 800, 600);
	//当Frame大小变动,调用回调函数调整视口大小
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

	initModel();
	initShader("vertexShader.glsl", "fragmentShader.glsl");

	//防止窗口结束退出
	while (!glfwWindowShouldClose(window)) {
		processInput(window);

		//擦除画布,用定义的颜色填充
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		render();

		//双缓冲
		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	//结束,释放资源
	glfwTerminate();
	return 0;

}

void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
	glViewport(0, 0, width, height);
}

void processInput(GLFWwindow* window) {
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
		glfwSetWindowShouldClose(window, true);
	}
}

//渲染
void render() {
	_shader.start();
	glBindVertexArray(VAO);
	//以三角形模式绘制,从第0个顶点开始,起作用的有3个点
	//glDrawArrays(GL_TRIANGLES, 0, 3);

	//以三角形模式绘制,用顶点索引
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

	_shader.end();
}

//构建模型数据:VBO,VAO
void initModel() {
	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.5f, -0.5f, 0.0f,		0.0f,0.0f,1.0f,
		-0.5f, 0.5f, 0.0f,		0.0f,1.0f,0.0f
	};

	unsigned int indices[] = {
		0,1,3,
		1,2,3
	};

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

	//EBO同样要位于VAO的管理之下
	glGenBuffers(1, &EBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

	//之后的VBO便属于了VAO的管理范围
	glGenBuffers(1, &VBO);
	//绑定哪一种buffer, 
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//分配显存:分配哪种buffer,分配显存大小,分配地址,使用数据的方式
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	//对哪个锚点进行操作:layout=0的锚点,读3个顶点,类型为float,不需要归一化,每次步长为3个float大小,从0处开始读
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(sizeof(float)*3));
	
	//打开锚点:激活
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);

	//解绑
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);
}

//
void initShader(const char* _vertexPath, const char* _fragPath) {
	
	_shader.initShader(_vertexPath, _fragPath);
}

渲染结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/33053.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网站被劫持勒索怎么办

互联网出现后的几十年时间里&#xff0c;世界便由一张张网串联了起来&#xff0c;给我们的生活带来了无限的便利。但在互联网飞速发展的同时&#xff0c;恶意网络攻击也随之而来&#xff0c;近年来&#xff0c;互联网攻击事件频发&#xff0c;不法分子利用常见的DDoS攻击、CC攻…

【生成式网络】入门篇(二):GAN的 代码和结果记录

GAN非常经典&#xff0c;我就不介绍具体原理了&#xff0c;直接上代码。 感兴趣的可以阅读&#xff0c;里面有更多变体。 https://github.com/rasbt/deeplearning-models/tree/master/pytorch_ipynb/gan GAN 在 MINIST上的代码和效果 import os # os.chdir(os.path.dirname(_…

springBoot集成websocket实现消息实时推送提醒

在浏览某些网页的时候&#xff0c;例如 WebQQ、京东在线客服服务、CSDN私信消息等类似的情况下&#xff0c;我们可以在网页上进行在线聊天&#xff0c;或者即时消息的收取与回复&#xff0c;可见&#xff0c;这种功能的需求由来已久&#xff0c;并且应用广泛,和pc端web系统待办…

新建anaconda使用jupyter出现的一系列问题

1&#xff0c;运行一段机器学习代码&#xff0c;报缺少h5py的错误. 使用conda install h5py1.8.0 安装无法安装&#xff0c;因为当前环境的python版本是3.9&#xff0c;只能用3.7及以下的版本。无奈只能新建一个conda 环境。 2&#xff0c;新建一个 python3.7的conda 环境。运行…

「风控算法服务平台」高性能在线推理服务设计与实现

本文作者&#xff1a;郁昌存 来自京东科技-风险管理中心 一、背景/目标 1&#xff09; 风控智能化体系建设依赖大量深度学习/机器学习模型进行实时在线的风险识别、智能决策。要求可以将算法模型快速部署为在线服务&#xff0c;供决策引擎调用。 2&#xff09; 风控决策引擎…

文献 | 教师主观幸福感变迁:横断历史研究的视角

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是莹~ 疫情带来的社会经济变化正在改变着我们的求职意向&#xff0c;越来越多的人参与到考公考编的大军中。其中&#xff0c;教师这一职业的稳定性和社会认同度吸引了越来越多的年轻人参加教资考试。 教…

Linux Top 详细介绍,包含task排序

Linux Top 当我们在终端输入 top 命令时&#xff0c;会弹出一个变化的页面&#xff0c;打印出当前系统的大量重要指标&#xff0c;以及很多进程当前的运行情况&#xff1a; 可以看到&#xff0c;top 命令主要是两部分&#xff0c;第一部分为 头部指标&#xff0c;打印的是当…

磨金石教育摄影技能干货分享|那些酷炫的照片是怎么拍出来的?

在网上我们经常会看到一些非常有创意&#xff0c;非常炫酷的照片。喜欢摄影的朋友肯定会想&#xff0c;这样的照片怎么拍呢&#xff1f;由于照片的创意度很高&#xff0c;导致很多人想模仿却不知道怎么模仿。以前学的那些构图、选景等技巧&#xff0c;好像不太够用。 今天我们…

2022年文化艺术品产权交易所研究报告

第一章 文化艺术品产权交易所发展概述 1.1 文交所概念 文化产权交易所&#xff08;简称“文交所”&#xff09;从事文化产权交易及相关投融资服务工作&#xff0c;促进文化产业要素跨行业、跨地域、跨所有制流动。文交所从事的创新业务主要是文化艺术品的份额化&#xff0c;即…

idea 配置ssm项目后配置文件的简要解析及功能类之间的联系

注&#xff1a;本文不包含怎么配置 idea ssm 项目&#xff0c;仅做个人向配置好之后&#xff0c;对于各个文件的分析及跳转之间的的浅解析&#xff08;之前照着配的文章找不到了qwq&#xff09;。 叠甲&#xff1a;新手&#xff0c;刚学&#xff0c;不太会&#xff0c;如有错请…

初识Python_数据容器_字符串str

一、再识字符串字符串---字符的容器。一个字符串可以存放任意数量的字符1、字符串的下标&#xff08;索引&#xff09;和其他容器如&#xff1a;列表、元组一样&#xff0c;字符串也可以通过下标进行访问从前向后 下标从0开始从后向前&#xff0c;下标从-1开始同元组一样&#…

11个精美网页——Web前端开发技术课程大作业,期末考试,Dreamweaver简单网页制作

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置&#xff0c;有div的样式格局&#xff0c;这个实例比较全面&#xff0c;有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 精彩专栏推荐&#x1f4…

罗茨气体流量计的结构设计

目 录 摘 要 I ABSTRACT II 1绪 论 1 1.1 引言 1 1.2 罗茨气体流量计的特点 1 1.&#xff13;罗茨气体流量计的应用场合[3] 2 1.4 发展前景[5] 6 2罗茨气体流量计的工作及结构原理 7 2.1 罗茨气体流量计的工作原理[3] 7 2.2罗茨气体流量计的结构原理 7 2.2.1 罗茨气体流量计的结…

echarts——实现3D地图+3D柱状图 效果——粗糙代码记录——技能提升

最近看到同事在弄下面的这个图&#xff0c;这个图是从网上看到的&#xff0c;是某个网站的收费项目&#xff1a; 收费模板&#xff1a;&#xffe5;29.9元购买&#xff0c;且必须是高级版尊享版才能够购买这个。。。 死贵&#xff01;&#xff01;&#xff01; 所以&#xf…

多臂PEG衍生物——8-Arm PEG-N3,8-Arm PEG-Azide,八臂-PEG-叠氮

多臂PEG衍生物八臂-聚乙二醇-叠氮&#xff0c;化学试剂其英文名为8-Arm PEG-Azide&#xff0c;8-Arm PEG-N3&#xff0c;它所属分类为Azide PEG Multi-arm PEGs。 八臂PEG叠氮的分子量均可定制&#xff0c;有&#xff1a;八臂-peg 5k-叠氮、八臂PEG 2k叠氮、叠氮-聚乙二醇 10k…

19 06-读取DTC扩展数据记录

诊断协议那些事儿 诊断协议那些事儿专栏系列文章&#xff0c;19服务作为UDS中子功能最多的服务&#xff0c;一共有28种子功能&#xff0c;本文将介绍常用的19 06服务&#xff1a;读取DTC扩展数据。 关联文章&#xff1a; 19服务List 19 01-通过状态掩码读取DTC数目 19 02-检…

PL/Java的安装及使用

安装步骤 1.1 下载相应扩展包 https://network.pivotal.io/products/vmware-tanzu-greenplum#/releases/1193700 1.2 上传并安装pljava-2.0.4-gp6-rhel7_x86_64.gppkg [gpadmingp_master ~]$ gppkg -i pljava-2.0.4-gp6-rhel7_x86_64.gppkg 重启数据库 [gpadmingp_master ~]$…

企业管理中,商业智能BI主要做哪些事情?

开门见山的告诉大家&#xff0c;在企业管理中商业智能BI 主要就做三件事&#xff1a;拉通数据、整合数据、数据可视化展现。 技术角度的商业智能BI 从技术的角度来讲&#xff0c;商业智能BI是一套完整的由数据仓库、查询报表、数据分析等组成的数据类技术解决方案。它有一个非…

【计算机毕业设计】23.图书馆管理系统源码

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 1 绪论 1.1 开发背景 图书馆管理系统的特点是从图书管理的角度出发&#xff0c;用集中的数据库将几乎所有与图书相关的数据统一管理起来&#xff0c;形成了集成的信息源。有好的用户界面&#xff0c;强有力的报表生…

AMR论文阅读之:ATP: AMRize Then Parse! Enhancing AMR Parsing with PseudoAMRs

文章目录AbstractIntroductionMethodologyAuxiliary Task selectionSRLDPAMRizationTranform SRL to PseudoAMRConnectivity FormationArgument ReductionReentrancy RestorationDependency Guided RestorationTransform Dependency Structure to PseudoAMRRedundant Relation …