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 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> OpenGL超级宝典:渲染管线(一) -> 正文阅读

[C++知识库]OpenGL超级宝典:渲染管线(一)

自己封装的Shader类(后面继续改进)

shader.h

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

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

	//源代码
	std::string vertexString;
	const char* vertexSource;

	std::string fragmentString;
	const char* fragmentSource;

private:
	void checkCompileErrors(unsigned int ID, std::string type);
};

shader.cpp

#include "Shader.h"
#include <fstream>
#include <sstream>
#include <iostream>
#include <exception>
Shader::Shader(){}

Shader::Shader(const std::string vertexPath, const std::string fragmentPath)
{
	//用于读取shader文件
	std::ifstream vertexFile;
	std::ifstream fragmentFile;

	//转换源码
	std::stringstream vertexSStream;
	std::stringstream fragmentSStream;

	//创建程序对象
	program = glCreateProgram();

	//vertex shader
	if (!vertexPath.empty())	//判断文件路径是否为空
	{
		//打开文件
		vertexFile.open(vertexPath);
		//检测文件是否有误
		vertexFile.exceptions(std::ifstream::badbit || std::ifstream::failbit);

		try
		{

			if (!vertexFile.is_open())	//判断文件是否打开
			{
				throw std::exception("open vertex shader file fail");
			}
			//读取源代码到字符串流
			vertexSStream << vertexFile.rdbuf();
			//读取完毕,可以关闭文件了
			vertexFile.close();
			//将源代码输入到字符串中去
			vertexString = vertexSStream.str();
			//由于读取的是const char*类型的,所以用一个string转换一下
			vertexSource = vertexString.c_str();

			//创建顶点着色器对象
			GLuint vertexShader;
			vertexShader = glCreateShader(GL_VERTEX_SHADER);
			//将shader的源代码传递给shader对象
			glShaderSource(vertexShader, 1, &vertexSource, NULL);
			//编译着色器中的源代码
			glCompileShader(vertexShader);
			//将shader对象附加到program对象上去
			glAttachShader(program, vertexShader);
			//连接program对象上的shader对象
			glLinkProgram(program);
			//查错
			checkCompileErrors(program, "VERTEX");
			//可以把已经附加并且链接好的shader对象删除了
			glDeleteShader(vertexShader);
		}
		catch (const std::exception& e)
		{
			std::cout << e.what() << std::endl;
		}
		
	}

	//fragment shader
	if (!fragmentPath.empty())	//判断文件路径是否为空
	{
		//文件路径不为空,打开文件
		fragmentFile.open(fragmentPath);
		fragmentFile.exceptions(std::ifstream::badbit || std::ifstream::failbit);

		try
		{
			if (!fragmentFile.is_open())	//文件打开失败
			{
				throw std::exception("open fragment shader file fail");
			}
			//文件成功打开
			//字符串流读取文件中的数据
			fragmentSStream << fragmentFile.rdbuf();
			//读完了,把文件关了
			fragmentFile.close();
			//把源代码读入字符串中去
			fragmentString = fragmentSStream.str();

			//把string转成系数需要的const char *类型
			fragmentSource = fragmentString.c_str();

			//创建shader对象
			GLuint fragmentShader;
			fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
			//将源代码读入shader对象
			glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
			//编译shader对象中的源码
			glCompileShader(fragmentShader);
			//将shader对象附加到program对象上去
			glAttachShader(program, fragmentShader);
			//链接program对象上的shader对象
			glLinkProgram(program);
			//查错
			checkCompileErrors(program, "PROGRAM");
			//完事,可以把shader对象删了
			glDeleteShader(fragmentShader);
		}
		catch (const std::exception& e)
		{
			std::cout << e.what() << std::endl;
		}

		
	}
}

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


/*
* 查错
*/
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
//VAO的第0个位置的数据
layout(location = 0) in vec4 offset;
//VAO的第1个位置的数据
layout(location = 1) in vec4 color;

//输出的数据,输出到下一个shader
out vec4 vs_color;

void main()
{
	const vec4 vertices[3] = vec4[3](vec4(0.25, -0.25, 0.5, 1.0),
	vec4(-0.25, -0.25, 0.5, 1.0),
	vec4(0.25, 0.25, 0.5, 1.0));
	
	vs_color = color;
	//gl_VertexID是内置对象,每次自动+1,直到数组的大小为止,offset是偏移量,这里是一个椭圆的参数方程
	gl_Position = vertices[gl_VertexID] + offset;
}

fragment shader

#version 450 core

//从vertex shader传过来的数据,in就是上一个shader的out
in vec4 vs_color;
//输出到屏幕或者窗口
out vec4 color;

void main()
{
	color = vs_color;
}

代码

#include "sb7.h"
#include "Shader.h"
#include <math.h>
class my_application : public sb7::application
{
	void startup()
	{
		shader = new Shader("vertexShader.vert", "fragShader.frag");

		//创建数组对象
		glCreateVertexArrays(2, vertex_arrays_object);
		//绑定array对象到OpenGL上下文,让OpenGL知道这些数据
		glBindVertexArray(vertex_arrays_object[0]);
		glBindVertexArray(vertex_arrays_object[1]);
	}

	void render(double currentTime)
	{
		const GLfloat color[] = {
			(float)sin(currentTime) * 0.5f + 0.5f,
			(float)cos(currentTime) * 0.5f + 0.5f, 0.0f, 1.0f
		};
		glClearBufferfv(GL_COLOR, 0, color);

		shader->use();
		//三角形的位置变化,这个就是vertex shader传入的offset
		GLfloat attrib[]{
			(float)sin(currentTime) * 0.5f,
			(float)cos(currentTime) * 0.6f, 0.0, 0.0f
		};
		//三角形的颜色变化,这个是vertex shader里面传入的color
		GLfloat triangleColor[] = {
			(float)sin(currentTime) * 0.2f + 0.5f,
			(float)cos(currentTime) * 0.2f + 0.5f, 0.0f, 1.0f
		};
		
		//使用glVertexAttrub4fv(GLuint index, const GLfloat* v)填充变量,这里的index与vertex shader里面的location对应
		glVertexAttrib4fv(0, attrib);
		glVertexAttrib4fv(1, triangleColor);
		glDrawArrays(GL_TRIANGLES, 0, 3);
	}

	void shutdown() 
	{

	}

private:
	Shader* shader;
	//顶点数组对象
	GLuint vertex_arrays_object[2];
};

DECLARE_MAIN(my_application);

出现过的问题

忽略了vao的创建和绑定

  //创建数组对象
  glCreateVertexArrays(2, vertex_arrays_object);
  //绑定array对象到OpenGL上下文,让OpenGL知道这些数据
  glBindVertexArray(vertex_arrays_object[0]);
  glBindVertexArray(vertex_arrays_object[1]);

一开始我没有写上面的代码,导致一直无法绘制出图形,并且出现错误。
GL_INVALID_OPERATION error generated. Array object is not active.
在这里插入图片描述

展示

在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 11:12:28  更:2022-02-26 11:12:55 
 
开发: 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/24 6:29:20-

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