自定义着色器类

声明

#pragma once#include<string>class Shaders
{public:Shaders(const char* vertexPath, const char* fragmentPath);~Shaders();std::string vertexString;std::string fragmentString;const char* vertexSource;const char* fragmentSource;unsigned int ID; // shaderProgram 的idvoid use();
private:void checkCompileErrors(unsigned int id, std::string type);};

源文件

#include "Shaders.h"
#include<fstream>
#include<iostream>
#include<sstream>
#define GLEW_STATIC // 这个一定要加不然报错 静态链接库
#include<GL/glew.h>
#include<GLFW/glfw3.h>Shaders::Shaders(const char* vertexPath, const char* fragmentPath ) {std::ifstream vertexFile;std::ifstream fragmentFile;std::stringstream vertexSStream;std::stringstream fragmentSStream;vertexFile.open(vertexPath);fragmentFile.open(fragmentPath);vertexFile.exceptions(std::ifstream::failbit || std::ifstream::badbit);fragmentFile.exceptions(std::ifstream::failbit || std::ifstream::badbit);try {if (!vertexFile.is_open() || !fragmentFile.is_open()) {throw std::exception("open file error");}//  将 输入流的内容输出给 stringstreamvertexSStream << vertexFile.rdbuf();fragmentSStream << fragmentFile.rdbuf();vertexString = vertexSStream.str();fragmentString = fragmentSStream.str();vertexSource = vertexString.c_str();fragmentSource = fragmentString.c_str();unsigned int vertex, fragment;// 创建这个着色器vertex = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertex, 1, &vertexSource, NULL);// 编译glCompileShader(vertex);checkCompileErrors(vertex, "VERTEX");fragment = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragment, 1, &fragmentSource, NULL);// 编译glCompileShader(fragment);checkCompileErrors(fragment, "FRAGMENT");//创建一个着色器程序对象ID = glCreateProgram();// 将之前编译的着色器附加到程序对象上glAttachShader(ID, vertex);glAttachShader(ID, fragment);// 用glLinkProgram链接它们glLinkProgram(ID);checkCompileErrors(ID, "PROGRAM");//删除着色器glDeleteShader(vertex);glDeleteShader(fragment);}catch (const std::exception& ex) {std::cout << ex.what() << std::endl;}
}
void Shaders::use() {glUseProgram(ID);
}
void Shaders::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 compile error:" << infoLog << std::endl;}}
}
Shaders::~Shaders() {}

程序入口

#define GLEW_STATIC // 这个一定要加不然报错 静态链接库
#include<GL/glew.h>
#include<GLFW/glfw3.h>
#include<iostream>
#include "Shaders.h"
using namespace std;
void processInput(GLFWwindow);
void processInput(GLFWwindow* window) {//如果键盘输入esc 则触发 退出if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {// 设置 要求退出glfwSetWindowShouldClose(window, true);}
}
// 逆时针方向绘制  默认情况下,逆时针的顶点连接顺序被定义为三角形的正
// 逆时针或顺时针都是相对于观察者方向的
float vertices[] {-0.5f, 0.5f, 0.0f, 1.0f, 0,0, // 左上角 0  0.5f, -0.5f, 0.0f, 0,1.0f,0, // 右下角 10.5f, 0.5f, 0.0f, 0,0,1.0f,  // 右上角 2// 第二个三角形//0.5f, -0.5f, 0.0f,  // 右下角-0.5f, -0.5f, 0.0f , 1.0f,0,1.0f // 左下角  3//-0.5f, 0.5f, 0.0f   // 左上角
};
// 使用索引来减小画点的开销 (未用索引缓冲对象时,每个点都需要画一次(即使重复了))
unsigned int indices[] {0,1,2, //第一个三角形的索引1,3,0 //第二个三角形的索引
};int main() {// 初始化GLFWglfwInit();// 提示 我们使用的版本是3.3// 主版本glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);// 次版本glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);// 简介glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// 创建一个窗口对象GLFWwindow* window = glfwCreateWindow(800, 600, "Test window", NULL, NULL);if (window == NULL) {cout << "open window failed." << endl;// 终止 glfwglfwTerminate();}// 绑定window到上下文对象 创建完窗口我们就可以通知GLFW将我们窗口的上下文设置为当前线程的主上下文了glfwMakeContextCurrent(window);glewExperimental = true;// GLEW_OK 0//init GLEWif (glewInit() != GLEW_OK) {cout << "glew init failed." << endl;// 终止 glfwglfwTerminate();return -1;}// OpenGL渲染窗口的尺寸大小 // glViewport函数前两个参数控制窗口左下角的位置。第三个和第四个参数控制渲染窗口的宽度和高度(像素)glViewport(0, 0, 800, 600);// 设置剔除 (opegl默认正面背面都显示(不剔除))//glEnable(GL_CULL_FACE);// 剔除背面 GL_BACK 剔除正面 GL_FRONT//glCullFace(GL_BACK);// 线框模式 //第一个参数表示我们打算将其应用到所有的三角形的正面和背面,第二个参数告诉我们用线来绘制//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//VAO对象unsigned int VAO;// 生成一个VAO对象 这个方法可以生成多个 由第一个参数决定glGenVertexArrays(1, &VAO);// 绑定 VAOglBindVertexArray(VAO);unsigned int VBO; //如果多个可以用 VBO[]数组 这个方法可以生成多个 由第一个参数决定glGenBuffers(1, &VBO);//将新创建的缓冲绑定到 GL_ARRAY_BUFFER目标上glBindBuffer(GL_ARRAY_BUFFER, VBO);// glBufferData 是一个专门用来把用户定义的数据复制到当前绑定缓冲的函数// GL_STATIC_DRAW 数据不会或几乎不会改变。glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);unsigned int EBO;glGenBuffers(1, &EBO);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);Shaders* shaders = new Shaders("./vertexSource.txt", "./fragmentSource.txt");// glVertexAttribPointer函数告诉OpenGL该如何解析顶点数据(应用到逐个顶点属性上)// 从 0号栏位 开始 将数据每三个为一组 单位为float 每次跳6*float字节 偏移为0glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);// 以顶点属性位置值作为参数,启用顶点属性;顶点属性默认是禁用的//读取到0号栏位上glEnableVertexAttribArray(0);// 读取颜色属性 从 1号栏位 开始 将数据每三个为一组 单位为float 每次跳6*float字节 偏移为3个floatglVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float)));// 读取到1号栏位上 glEnableVertexAttribArray(1);//渲染循环 ,它能在我们让GLFW退出前一直保持运行。下面几行的代码就实现了一个简单的渲染循环://glfwWindowShouldClose 我们每次循环的开始前检查一次GLFW是否被要求退出while (!glfwWindowShouldClose(window)) {//自定义事件 当键盘触发esc 退出processInput(window);glClearColor(0.2, 0.3, 0.3, 1.0);// GL_COLOR_BUFFER_BIT 颜色,GL_DEPTH_BUFFER_BIT 深度 和 GL_STENCIL_BUFFER_BIT 模板// 清除前面的那一帧的颜色glClear(GL_COLOR_BUFFER_BIT);// 绑定 VAO glBindVertexArray(VAO);shaders->use();// 画三角形 从0开始 绘制三个顶点  和VBO的顶点数据(通过VAO间接绑定)来绘制图元//glDrawArrays(GL_TRIANGLES, 0, 6); 这个是不用索引画的glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//可以不需要这个 绑定VAO的同时也会自动绑定EBO//glDrawElements函数从当前绑定到GL_ELEMENT_ARRAY_BUFFER目标的EBO中获取索引glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);//解绑VAOglBindVertexArray(0);glfwSwapBuffers(window);glfwPollEvents();}// 最后终止 glfwglfwTerminate();return 0;
}

着色器

顶点着色器

#version 330 core
// 0号栏位读取顶点坐标
layout (location = 0) in vec3 aPos;
//1号栏位读取颜色颜色
layout (location = 1) in vec3 aColor;
out vec4 vertexColor;
void main()
{
//  gl_Position 是固定的名称 用来保存 顶点坐标的gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);   vertexColor = vec4(aColor.x+0.5,aColor.y,aColor.z,1.0);
}

片段着色器

#version 330 core
out vec4 FragColor;
//uniform vec4 outColor;
in vec4 vertexColor;
void main()
{                                          FragColor = vertexColor;
}

未报错效果

报错的效果

OpenGL 自定义着色器(Shaders)相关推荐

  1. OpenGL shader class自定义着色器的实例

    OpenGL shader class自定义着色器 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <glad/glad.h> #in ...

  2. Unreal Engine 4 使用HLSL自定义着色器(Custom Shaders)教程(下)

    本文是<Unreal Engine 4 自定义着色器(Custom Shaders)教程>的下半部分,上半部分请见<Unreal Engine 4 自定义着色器(Custom Sha ...

  3. OpenGL ES之GLSL自定义着色器编程实现粒子效果

    效果展示 实现流程 一.自定义着色器 顶点着色器:YDWPointParticleShader.vsh // 位置 attribute vec3 a_emissionPosition; // 速度 a ...

  4. unity烘培单个物体_Unity可编程渲染管线(SRP)教程:二、自定义着色器

    本文翻译自Catlike Coding,原作者:Jasper Flick. 本文经原作者授权,转载请说明出处. 原文链接在下: https://catlikecoding.com/unity/tuto ...

  5. OpenGL ES着色器语言之变量和数据类型

    所有变量和函数在使用前必须声明.变量和函数名是标识符. 没有默认类型,所有变量和函数声明必须包含一个声明类型以及可选的修饰符.变量在声明的时候首先要标明类型,后边可以跟多个变量,之间用逗号隔开.很多情 ...

  6. OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)...

    OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...

  7. Qt Creator使用自定义着色器

    Qt Creator使用自定义着色器 使用自定义着色器 可用的自定义着色器实用程序 可用的自定义着色器命令 使用自定义着色器 您可以使用Qt Quick 3D着色器实用程序和命令来创建自己的效果和材质 ...

  8. OpenGL 几何着色器细分的实例

    OpenGL 几何着色器细分 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <vmath.h> #include <cmath ...

  9. OpenGL 几何着色器剔除的实例

    OpenGL 几何着色器剔除 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <vmath.h> #include <objec ...

最新文章

  1. LatentFusion:华盛顿大学与英伟达联合提出6D姿态估计新方法
  2. vue.js安装问题
  3. jQuery 人脸识别插件,支持图片和视频
  4. VTK:图片之ImageAnisotropicDiffusion2D
  5. 以对象的形式动态获取宽高
  6. Tensorboard --logdir=logs 无法显示图像的处理办法
  7. php分析图片中水印的位置,图像处理技术之图片添加水印
  8. Super VLAN原理
  9. DL_C1_week4_2(build a deep neural network 2)
  10. ArcGIS三维制作步骤
  11. android 禁止软键盘弹出自动弹出,Android屏蔽软键盘自动弹出的解决方案
  12. 太阳能发电与蓄电池研究(Matlab代码实现)
  13. Java对接企业微信消息推送
  14. 如何准备全国计算机二级Python,二级Python考试技巧
  15. 手把手教你搭建免流服务器(只限于联通)
  16. 教你游泳【附动画组图】
  17. 增量式分级判别回归树(IHDR)|翻译与笔记
  18. 每日一词: 战略 2022.3.30
  19. 数据库 数据仓库 数据集市的区别
  20. 【搜索】洛谷 P1460 健康的荷斯坦奶牛 Healthy Holsteins

热门文章

  1. Iptables详解+实例
  2. ansible: Linux批量管理神器
  3. Swift使用CoreLocation,你必须要看这一篇
  4. VTP实现VLAN同步
  5. 介绍MFSideMenu左右滑动控件的使用
  6. .NET配置文件读写实例(附SosoftConfigHelper类)
  7. python setup.py install 出错_python setup.py install 失败
  8. pb blob存储到image_【Filecoin相关】速懂 Filecoin 自认证存储设计
  9. 前端网页广告无线翻滚_从小白到web前端工程师进阶之路 从0到1到更深
  10. [转载] 【Java】将一个字符串的字符排序,按ASCII表的顺序从小到大