IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> OpenGL超级宝典:使用缓冲为顶点着色器提供数据 -> 正文阅读

[游戏开发]OpenGL超级宝典:使用缓冲为顶点着色器提供数据

缓冲

缓冲,顾名思义,就是暂时不急着用的内容。
OpenGL中,缓冲是指内存的线性分配。每个缓冲都有个缓冲名,同时还有分配给缓冲的内存,叫做缓冲的数据库。
若得到一个缓冲的名称,则可以通过将它绑定到缓存绑定点并附加到OpenGL环境中。绑定点又叫做靶点(target)

创建缓冲和分配内存

在OpenGL中缓冲的创建和vao是一样的流程
glCreateBuffer(GLsizei n, GLuint* buffers)
glBindBuffer(GLenum target, GLuint buffer) //绑定缓冲到OpenGL中
分配内存
glBufferStorage(GLenum target, GLsizeiptr size, const void* data, GLbitfield flags) 这是给这类靶点分配内存空间的
glNamedBufferStorage(GLuint buffer, GLsizeiptr size, const void* data, GLbitfield flags) 这是给单独的缓冲分配空间的

将数据传入缓冲中去

glBufferSubData(GLenum targer, GLintptr offset, GLsizeptr size, const GLvoid* data);
glNamedBufferSubData(GLuint buffer, GLintptr offset, GLsizeptr size, const GLvoid* data);
还有一种就是映射缓冲的数据库
glMapNamedBuffer(GLuint buffer, GLenum usage)
这是生成一个指针指向缓冲的内存
还有一种就是限定映射内存的位置
glMapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeptr length, GLbitfield access)

使用缓冲为顶点着色器提供数据

自己封装的Shader类(修改)

上一版的Shader类有点小问题,所以这次做了修改,主要是在链接之前检查了shader对象

Shader.h

#pragma once
#include "sb7.h"
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <exception>
class Shader
{
public:
	Shader();
	Shader(const std::string vertexPath, const std::string fragmentPath);
	Shader(const std::string vertexPath, const std::string tescPath, const std::string tesePath, const std::string fragmentPath);

	//设置顶点着色器
	void setVertexShder(const std::string vertexPath);
	//设置曲面细分控制着色器
	void setTescShader(const std::string tescPath);
	//设置曲面细分评估着色器
	void setTeseShader(const std::string tesePath);
	//设置片段着色器
	void setFragmentShader(const std::string fragmentPath);

	//program对象使用
	void use();
private:
	GLuint program;

	//源代码
	std::string shaderString;
	const char* shaderSource;
	//用于读取shader文件
	std::ifstream shaderFile;
	//转换源码
	std::stringstream shaderSStream;

private:
	//查错程序,是否有编译错误
	void checkCompileErrors(unsigned int ID, std::string type);
	//读取文件,并且创建着色器对象
	void readShaderSource(std::string shaderFilePath);
	//链接着色器
	void linkShader(GLuint shaderObject, std::string type);
};

Shader.cpp

#include "Shader.h"

Shader::Shader() {}

Shader::Shader(const std::string vertexPath, const std::string fragmentPath)
{
	//创建程序对象
	program = glCreateProgram();

	setVertexShder(vertexPath);
	setFragmentShader(fragmentPath);

}

Shader::Shader(const std::string vertexPath, const std::string tescPath, const std::string tesePath, const std::string fragmentPath)
{
	//创建程序对象
	program = glCreateProgram();

	setVertexShder(vertexPath);
	setFragmentShader(fragmentPath);
	setTescShader(tescPath);
	setTeseShader(tesePath);
}

//设置顶点着色器
void Shader::setVertexShder(const std::string vertexPath)
{
	//读取shader源代码
	readShaderSource(vertexPath);
	//创建shader对象
	GLuint vertexShader;
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	//链接shader对象
	linkShader(vertexShader, "VERTEX");
}

//设置曲面细分控制着色器
void Shader::setTescShader(const std::string tescPath)
{
	//读取shader源代码
	readShaderSource(tescPath);
	//创建shader对象
	GLuint tescShader;
	tescShader = glCreateShader(GL_TESS_CONTROL_SHADER);
	//链接shader对象
	linkShader(tescShader, "TESC");
}

//设置曲面细分评估着色器
void Shader::setTeseShader(const std::string tesePath)
{
	//读取shader源代码
	readShaderSource(tesePath);
	//创建shader对象
	GLuint teseShader;
	teseShader = glCreateShader(GL_TESS_EVALUATION_SHADER);
	//链接shader对象
	linkShader(teseShader, "TESE");
}

//设置片段着色器
void Shader::setFragmentShader(const std::string fragmentPath)
{
	//读取shader源代码
	readShaderSource(fragmentPath);
	//创建shader对象
	GLuint fragmentShader;
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	//链接shader对象
	linkShader(fragmentShader, "FRAGMENT");
}

void Shader::use()
{
	glUseProgram(program);
}

//读取文件,并且创建着色器对象
void Shader::readShaderSource(std::string shaderFilePath)
{
	//将上一个shader的源码清理
	shaderSStream.str("");
	memset(&shaderSource, '\0', sizeof(shaderSource));
	//open shader file
	if (!shaderFilePath.empty())	//判断文件路径是否为空
	{

		//文件路径不为空,打开文件
		shaderFile.open(shaderFilePath);
		shaderFile.exceptions(std::ifstream::badbit || std::ifstream::failbit);

		try
		{
			if (!shaderFile.is_open())	//文件打开失败
			{
				throw std::exception("open fragment shader file fail");
			}
			//文件成功打开
			//字符串流读取文件中的数据
			shaderSStream << shaderFile.rdbuf();
			//读完了,把文件关了
			shaderFile.close();
			//把源代码读入字符串中去
			shaderString = shaderSStream.str();
			//把string转成系数需要的const char *类型
			shaderSource = shaderString.c_str();

		}
		catch (const std::exception& e)
		{
			std::cout << e.what() << std::endl;
		}
	}
}

//链接着色器
void Shader::linkShader(GLuint shaderObject, std::string type)
{
	//将源代码读入shader对象
	glShaderSource(shaderObject, 1, &shaderSource, NULL);
	//编译shader对象中的源码
	glCompileShader(shaderObject);
	//检查着色器对象是否有误
	checkCompileErrors(shaderObject, type);
	//将shader对象附加到program对象上去
	glAttachShader(program, shaderObject);
	//链接program对象上的shader对象
	glLinkProgram(program);
	//查错
	checkCompileErrors(program, "PROGRAM");
	//完事,可以把shader对象删了
	glDeleteShader(shaderObject);
}


/*
* 查错
*/
void Shader::checkCompileErrors(unsigned int ID, std::string type)
{
	int success;
	char infoLog[512];

	if (type != "PROGRAM")
	{
		glGetShaderiv(ID, GL_COMPILE_STATUS, &success);
		if (!success)
		{
			glGetShaderInfoLog(ID, 512, NULL, infoLog);
			std::cout << "shader compile error: " << infoLog << std::endl;
		}
	}
	else
	{
		glGetProgramiv(ID, GL_LINK_STATUS, &success);
		if (!success)
		{
			glGetProgramInfoLog(ID, 512, NULL, infoLog);
			std::cout << "program linking error: " << infoLog << std::endl;
		}
	}
}

shader

vertex shader

#version 450 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec4 aColor;

out vec4 vs_color;

void main()
{
	vs_color = aColor;
	gl_Position = vec4(aPos, 1.0);
}

fragment shader

#version 450 core
out vec4 color;
in vec4 vs_color;

void main()
{
	color = vs_color;
}

代码

#include "sb7.h"
#include "Shader.h"
#include <iostream>

class my_application : public sb7::application
{
public:
	void startup() {
		shader = new Shader("vs.vert", "fs.frag");
		//创建vao
		glCreateVertexArrays(1, &vertex_arrays_object);
		//绑定vao到上下文
		glBindVertexArray(vertex_arrays_object);

		//创建缓存对象
		glCreateBuffers(2, buffer);

		//分配缓存空间,并且设置模式
		//第一个参数是分配缓冲的名称,第二个参数是分配的内存大小
		//第三个是分配的数据,没有可以写NULL,第四个参数是分配内存的目的
		glNamedBufferStorage(buffer[0], sizeof(vertices), NULL, GL_DYNAMIC_STORAGE_BIT);
		//绑定缓存对象到OpenGL
		/*glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);
		glBindBuffer(GL_ARRAY_BUFFER, buffer[1]);*/
		
		//第一步,绑定一个缓存到vao
		//第一个参数是需要绑定缓存的vao,第二个参数是绑定的绑定点,
		//第三个参数是绑定的缓存,第4个参数是绑定的数据在缓存中的位置,第5个参数是每个顶点之间的距离
		glVertexArrayVertexBuffer(vertex_arrays_object, 0, buffer[0], 0, sizeof(float) * 3);

		//告诉OpenGL数据的布局和格式
		//第一个参数是哪个vao,第二个参数是顶点属性,第三个参数是顶点的分量数量
		//第4个参数是数据的数据类型,第5个参数是是否标准化,第6个参数是与起点处顶点的偏移量
		glVertexArrayAttribFormat(vertex_arrays_object, 0, 3, GL_FLOAT, GL_FALSE, 0);

		//指示vao的顶点属性(第二个参数)要从绑定点(第三个参数)拿数据
		glVertexArrayAttribBinding(vertex_arrays_object, 0, 0);

		//启动属性自动填充
		//第一个参数是启动的vao,第二个参数是顶点属性
		glEnableVertexArrayAttrib(vertex_arrays_object, 0);

		glNamedBufferStorage(buffer[1], sizeof(bindcolor), NULL, GL_DYNAMIC_STORAGE_BIT);
		glVertexArrayVertexBuffer(vertex_arrays_object, 1, buffer[1], 0, sizeof(float) * 4);
		glVertexArrayAttribFormat(vertex_arrays_object, 1, 4, GL_FLOAT, GL_FALSE, 0);
		glVertexArrayAttribBinding(vertex_arrays_object, 1, 1);
		glEnableVertexArrayAttrib(vertex_arrays_object, 1);
	}

	void render(double currentTime) {
		GLfloat color[] = { 1.0, 1.0, 1.0, 1.0 };
		glClearBufferfv(GL_COLOR, 0, color);

		//glEnable(GL_MULTISAMPLE);

		shader->use();
		
		glNamedBufferSubData(buffer[0], 0, sizeof(vertices), vertices);
		glNamedBufferSubData(buffer[1], 0, 4 * 4 * 1, bindcolor);

		glDrawArrays(GL_TRIANGLES, 0, 3);

	}

	void shutdown(){

	}

private:
	Shader* shader;
	GLuint vertex_arrays_object;
	GLuint buffer[2];

	GLfloat vertices[9] = {
		0.5, 0.0, 0.5, 
		0.0, 0.5, 0.5,
		-0.5, 0.0, 0.5
	};
	GLfloat bindcolor[4] = { 1.0, 1.0, 0.0, 1.0 };
};

DECLARE_MAIN(my_application);

效果

在这里插入图片描述

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-03-08 22:54:07  更:2022-03-08 22:54:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 17:38:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码