OpenGL着色器--3

参考:这里

1.未使用Shader类,设置顶点颜色,从顶点着色器传递到片段着色器(颜色会进行线性插值)
在这里插入图片描述
源码如下:

//顺序不能错
#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>

using namespace std;

void framebuffer_size_callback(GLFWwindow* windwo, int width, int height);
void processInput(GLFWwindow* window);

const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;


//硬编码顶点、片元源码
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location=1)in vec3 aColor;"
"out vec3 color;"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"	color=aColor;"
"}\0";

const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"in vec3 color;"
"void main()\n"
"{\n"
"   FragColor = vec4(color, 1.0);\n"
"}\0";


int main()
{
	//init
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

	//create window object
	GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
	if (window == NULL)
	{
		cout << "Failed to create GLFW window!" << endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	//regiester callback
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

	//init GLAD
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		cout << "Failed to init GLAD!" << endl;
		return -1;
	}


	//configure options
	//设置线框模式
	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	//关闭线框模式:填充
	//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	//compile and build shader program

	//1.create vertex shader
	unsigned int vertexShader;
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
	glCompileShader(vertexShader);

	//error check
	int success;
	char infoLog[512];
	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
		cout << "error::vertex compile failed!\n" << infoLog << endl;
	}

	//2.create fragment shader
	unsigned int fragmentShader;
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
	glCompileShader(fragmentShader);

	//error check
	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
		cout << "error::fragment compile failed!\n" << infoLog << endl;
	}

	//3.link shader
	unsigned int shaderProgram, shaderProgram2;
	shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);
	glLinkProgram(shaderProgram);

	//error check
	glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
	}

	//4.delete shader
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);

	float firstTriangle[] = {
		// 位置              // 颜色
   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    // 顶部
	};

	//set vertex
	unsigned int VBO, VAO;
	glGenBuffers(1, &VBO);
	glGenVertexArrays(1, &VAO);

	//OpenGL核心模式必须用VAO才能显示要画的图形
	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);

	glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle), firstTriangle, GL_STATIC_DRAW);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
	//set pointer
	glEnableVertexAttribArray(0);

	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
	glEnableVertexAttribArray(1);

	//unbind:解除绑定
	//glBindVertexArray(0);

	//render loop
	while (!glfwWindowShouldClose(window))
	{
		//input
		processInput(window);

		//render
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		//use shader program
		glUseProgram(shaderProgram);

		float f = glfwGetTime();
		float colorValue = sin(f) * 0.5 + 0.5;


		glBindVertexArray(VAO);

		glDrawArrays(GL_TRIANGLES, 0, 3);

		//swap buffer
		glfwSwapBuffers(window);
		//call events
		glfwPollEvents();
	}

	//clear
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	glDeleteProgram(shaderProgram);

	//terminate software
	glfwTerminate();
	return 0;
}


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

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

2.使用封装的Shader类,shader文件放到工程目录下可以用相对路径,也可用绝对路径,shader源码和上面的硬编码的shader源码一样!
源码如下:

//顺序不能错
#include <glad/glad.h>
#include <GLFW/glfw3.h>

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


using namespace std;

void framebuffer_size_callback(GLFWwindow* windwo, int width, int height);
void processInput(GLFWwindow* window);

const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

int main()
{
	//init
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

	//create window object
	GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
	if (window == NULL)
	{
		cout << "Failed to create GLFW window!" << endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	//regiester callback
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

	//init GLAD
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		cout << "Failed to init GLAD!" << endl;
		return -1;
	}


	//configure options
	//设置线框模式
	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	//关闭线框模式:填充
	//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	//compile and build shader program	
	Shader shader("Shaders/useShader.vs","Shaders/useShader.fs");

	float firstTriangle[] = {
		// 位置              // 颜色
   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    // 顶部
	};

	//set vertex
	unsigned int VBO, VAO;
	glGenBuffers(1, &VBO);
	glGenVertexArrays(1, &VAO);

	//OpenGL核心模式必须用VAO才能显示要画的图形
	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);

	glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle), firstTriangle, GL_STATIC_DRAW);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
	//set pointer
	glEnableVertexAttribArray(0);

	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
	glEnableVertexAttribArray(1);

	//unbind:解除绑定
	//glBindVertexArray(0);

	//render loop
	while (!glfwWindowShouldClose(window))
	{
		//input
		processInput(window);

		//render
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		//use shader program
		shader.Use();
		glBindVertexArray(VAO);
		glDrawArrays(GL_TRIANGLES, 0, 3);

		//swap buffer
		glfwSwapBuffers(window);
		//call events
		glfwPollEvents();
	}

	//clear
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	shader.Delete();

	//terminate software
	glfwTerminate();
	return 0;
}


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

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

3.封装类Shader:创建、编译、链接、检查错误、使用、删除、设置uniform类型数据,可根据需要修改,后续会进行完善!

注:创建的Shader.h头文件可以放到自定义的Include文件夹下,这样新建项目,就可以直接用了,目前是放到当前项目的头文件文件夹下。

#ifndef SHADER_H
#define SHADER_H

#include <glad/glad.h>

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

class Shader
{
public:
	//shader 程序ID
	unsigned int ID;

	//构造函数:读取shader源文件,编译,链接,生成shader程序
	Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
	{
		//1.从文件路径获取顶点和片段着色器
		//读取到的源码
		std::string vertexCode;
		std::string fragmentCode;

		//输入文件流
		std::ifstream vShaderFile;
		std::ifstream fShaderFile;

		//保证ifstream对象可以抛出异常
		vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
		fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);

		try
		{
			
			vShaderFile.open(vertexPath);
			fShaderFile.open(fragmentPath);

			//字符串流
			std::stringstream vShaderStream, fShaderStream;

			//读取文件的缓冲内容到数据流中
			vShaderStream << vShaderFile.rdbuf();
			fShaderStream << fShaderFile.rdbuf();

			//关闭文件流
			vShaderFile.close();
			fShaderFile.close();

			//转换数据流到string
			vertexCode = vShaderStream.str();
			fragmentCode = fShaderStream.str();
		}
		catch (std::ifstream::failure e)
		{
			std::cout << "error::shader file not succesfully read!" << std::endl;
		}

		//转换为C风格的字符串
		const char* vShaderCode = vertexCode.c_str();
		const char* fShaderCode = fragmentCode.c_str();

		//2.编译着色器
		unsigned int vertex, fragment;
		int success;
		char infoLog[512];

		//顶点着色器
		vertex = glCreateShader(GL_VERTEX_SHADER);
		glShaderSource(vertex, 1, &vShaderCode, NULL);
		glCompileShader(vertex);

		//错误检查
		glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);

		if (!success)
		{
			glGetShaderInfoLog(vertex, 512, NULL, infoLog);
			std::cout << "error::vertex shader compile error!" << infoLog << std::endl;
		}

		fragment = glCreateShader(GL_FRAGMENT_SHADER);
		glShaderSource(fragment, 1, &fShaderCode, NULL);
		glCompileShader(fragment);

		//错误检查
		glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);

		if (!success)
		{
			glGetShaderInfoLog(fragment, 512, NULL, infoLog);
			std::cout << "error::fragment shader compile error!" << infoLog << std::endl;
		}

		//着色器程序
		ID = glCreateProgram();
		glAttachShader(ID, vertex);
		glAttachShader(ID, fragment);
		glLinkProgram(ID);

		//错误检查
		glGetProgramiv(ID, GL_LINK_STATUS, &success);
		if (!success)
		{
			glGetProgramInfoLog(ID, 512, NULL, infoLog);
			std::cout << "error::program shader link error!" << infoLog << std::endl;
		}

		//删除着色器,已经在程序中,不需要了
		glDeleteShader(vertex);
		glDeleteShader(fragment);
	}

	//使用程序
	void Use()
	{
		glUseProgram(ID);
	}

	//删除程序
	void Delete()
	{
		glDeleteProgram(ID);
	}

	//uniform类型值设置函数
	void SetBool(const std::string& name, bool value)const
	{
		glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
	}
	void SetInt(const std::string& name, int value)const
	{
		glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
	}
	void SetFloat(const std::string& name, float value)const
	{
		glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
	}
};

#endif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值