管理3D图形数据

14 篇文章 0 订阅
/*
* 管理3D图形数据:
* 想要绘制一个对象,它的顶点数据需要被发送给顶点着色器。
* 通常会把顶点数据在C++端放入一个缓冲区,并把这个缓冲区和着色器中声明的顶点属性相关联。
* 有些步骤只需要一次,如果是动画场景的话,有些步骤需要每帧一次
*/

/*
* 缓冲区和顶点属性——————————————————————//
* 只做一次的步骤(一般在init()函数中)
* 1、创建一个缓冲区
* 2、将顶点数据复制到缓冲区
* 每帧都要做的步骤(一般在display()函数中)
* 1、启用包含了顶点数据的缓冲区
* 2、将这个缓冲区和一个顶点属性相关联
* 3、启用这个顶点属性
* 4、使用glDrawArrays(...)绘制对象
*/

/*
* VBO顶点缓冲对象
* VAO顶点数组对象
*/

//假设想要显示两个对象
//在C++端,可以声明一个VAO和两个相关的VBO(每个对象一个)
#include<GL/glew.h>
#include<GL/glut.h>
#include<GLFW/glfw3.h>
#include<iostream>
#include<glm/glm.hpp>
#include<glm/gtc/type_ptr.hpp>
#include<glm/gtc/matrix_transform.hpp>
int main()
{
	GLuint vao[1];//OpenGL要求这些数值以数组的形式指定
	GLuint vbo[2];
	//glGenVertexArrays()和glGenBuffers()这两个OpenGL命令分别创建VAO和VBO,并返回它们的整数型ID
	//把这些整数型ID存进整数型数组vao和vbo中
	glGenVertexArrays(1, vao);
	//(创建多少个ID,保存返回的ID的数组)
	glBindVertexArray(vao[0]);
	//将指定的vao标记为活跃,这样生成的缓冲区就会和这个vao相关联
	glGenBuffers(2, vbo);
	//(创建多少个ID,保存返回的ID的数组)

/*
* 顶点属性变量:
* 每个缓冲区都需要有在顶点着色器中声明相应的顶点属性变量。
* 顶点属性通常是着色器中首先被声明的变量
*/
//比如,用来接收立方体顶点的顶点属性可以在顶点着色器中这样声明
//layout(location = 0) in vec3 position
/*
* in表示输入,表示这个顶点属性会从缓冲区中接收数值
* vec3的意思是着色器的每次调用会抓到3个浮点型数值
* 变量名字是position
* "layout(location = 0)"叫做layout修饰符,这个顶点属性的识别号是0
* 也就是把顶点属性和特定缓冲区关联起来的方法
*/

//假设顶点存储在名为vPosition的浮点型数组中,以下代码会将这些值复制到第0个VBO中
	float vPositions[3];
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	//将缓冲区标记为活跃
	glBufferData(GL_ARRAY_BUFFER, sizeof(vPositions), vPositions, GL_STATIC_DRAW);
	//将包含顶点数据的数组复制进活跃区中
//以下代码将缓冲区中的值发送到着色器中的顶点属性。
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);//标记第0个缓冲区为活跃
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);//将第0个属性关联到缓冲区
	glEnableVertexAttribArray(0);//启用第0个顶点属性
//现在当执行glDrawArrays()时,第0个VBO中的数据将被传输给拥有位置0的layout修饰符的顶点属性中
//这会将立方体的顶点数据发送到着色器

/*
* 统一变量——————————————————————//
* 想要渲染一个场景使它看起来是3D的,需要构建适当的变换矩阵,并将它们应用于模型的每个顶点
* 在顶点着色器中应用所需的矩阵运算是最有效的
* 并且习惯上会将这些矩阵从C++/OpenGL应用程序发送给着色器中的统一变量。
*/

/* 使用uniform关键字在着色器中声明统一变量
 * uniform mat4 mv_matrix;//声明了用于存储模型-视图的变量
 * uniform mat4 proj_matrix;//声明了用于存储投影矩阵的变量
 * 关键字“mat4”表示这是4x4矩阵,因为3D变换是4x4的
 * 因此mat4是GLSL着色器统一中常用的数据类型
*/

/*
* 假设链接的渲染程序保存在名为“renderingProgram”的变量中
* 以下代码表示把模型-视图和投影矩阵发送到两个统一变量中:
* mnLoc = glGetUniformLocation(renderingProgram,"mv_matrix");//获取着色器程序中的统一变量位置
* projLoc = glGetUniformLocation(renderingProgram,"proj_matrix");
* glUniformMatrix4fv(mvLoc,1,GL_FALSE,glm::value_ptr(mvMat));//将矩阵数据发送到统一变量中
* glUniformMatrix4fv(projLoc,1,GL_FALSE,glm::value_ptr(pMat));
*/

/*
* 顶点属性插值——————————————————————//
* 光栅化过程会线性插值顶点属性值,以便显示的像素能无缝连接建模的曲面
* 统一变量的行为类似于初始化过的常量,并且在每次顶点着色器调用(即从缓冲区发送的每个顶点)中保持不变
* 统一变量本身不是插值的,无论有多少顶点,它始终包含相同的值
* 通过缓冲区发送到顶点属性的所有值都将在管线中被进一步插值
*/

/*
* 模型-视图和透视矩阵——————————————————————//
* 渲染3D对象的一个基础步骤是创建适当的变换矩阵并将它们发送到统一变量。
* 首先需要定义三个矩阵:模型矩阵、视图矩阵、透视矩阵
* 模型矩阵:在世界坐标空间中表示对象的位置和朝向。
* 视图矩阵:移动并旋转世界中的模型,以模拟相机在所需位置的效果
* 透视矩阵:是一种变换,它根据所需的视锥提供3D效果
* 永远不会改变的矩阵可以在init()中构建
* 会改变的矩阵需要在display()中构建,以便为每个帧重建它们
*/

/*
* 假设模型是动画的,相机是可移动的,那么:
* 需要为每个模型和每个帧都创建模型矩阵
* 视图矩阵需要每一帧创建一次(因为相机可以移动),但是对于在这一帧期间渲染的所有对象,它都是一样的
* 透视矩阵只需要创建一次[在init()中],它需要使用屏幕窗口的宽度和高度,除非调整窗口大小,否则通常保持不变
* 然后在display()函数中生成模型和视图转换矩阵,如下:
* 1、根据所需的摄像机位置和朝向构建视图模型
* 2、将模型和视图矩阵结合成单个“MV”矩阵
* i.根据模型的位置和朝向构建模型矩阵
* ii.将模型和视图矩阵结合成单个的“MV”矩阵
* iii.将MV和投影矩阵发送到相应的着色器统一变量
*/

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Spray!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值