OpenGL计算着色器Compute Shader的一个简单实例

OpenGL计算着色器Compute Shader的一个简单实例

起因

之前因为老师让实现一下Tiled Deffered Shading,所以便去查了一下相关资料,发现在计算的时候需要用到计算着色器Compute Shader,于是又去学习,却在第一个Sample卡住了。。。捣鼓了好久,终于是将其实现了,但依然有很多地方不明白。之前的有关图形学和OpenGL的知识都是在LearnOpenGL(一个很有名的OpenGL教程网站,非常通俗易懂,简单粗暴)上学的,但其确实在讲解过程中省略了很多东西,并且其对应的OpenGL版本也比较落后了,所以我决定还是踏踏实实、认认真真把《OpenGL编程指南》给看一遍,打好基础,不好高骛远,等以后有时间再来完完整整的写下关于计算着色器的理解,在这里先用一篇博客把瞎凑出来的程序代码和着色器代码记下来,免得以后忘记(代码太短了,还是不想放在Github上)。

程序代码

#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 

#include 
#include 
#include 

constexpr int SCR_WIDTH = 800;
constexpr int SCR_HEIGHT = 600;

float deltaTime = 0.0f;
float lastFrame = 0.0f;

Camera OurCamera(glm::vec3(0.0f, 0.0f, 5.0f));

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

void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
	OurCamera.ProcessMouseMove(xpos, ypos);
}

void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
	OurCamera.ProcessScrollZoom(yoffset);
}

void processInput(GLFWwindow* window)
{
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
	{
		glfwSetWindowShouldClose(window, true);
	}
	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
	{
		OurCamera.ProcessKeyboard(FORWARD, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
	{
		OurCamera.ProcessKeyboard(BACKWARD, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
	{
		OurCamera.ProcessKeyboard(LEFT, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
	{
		OurCamera.ProcessKeyboard(RIGHT, deltaTime);
	}
}

unsigned int loadTexture(std::string texturePath)
{
	unsigned int textureID;
	glGenTextures(1, &textureID);

	int width, height, nrChannels;
	unsigned char* data = stbi_load(texturePath.c_str(), &width, &height, &nrChannels, 0);
	if (data)
	{
		GLenum Format;
		switch (nrChannels)
		{
		case 1:
			Format = GL_RED;
			break;
		case 3:
			Format = GL_RGB;
			break;
		case 4:
			Format = GL_RGBA;
			break;
		default:
			break;
		}

		glBindTexture(GL_TEXTURE_2D, textureID);
		glTexImage2D(GL_TEXTURE_2D, 0, Format, width, height, 0, Format, GL_UNSIGNED_BYTE, data);
		glGenerateMipmap(GL_TEXTURE_2D);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	}
	else
	{
		std::cerr << "Failed to load texture." << std::endl;
	}

	stbi_image_free(data);
	return textureID;
}

unsigned int loadCubemap(std::vector<std::string> vFaces)
{
	unsigned int TextureID;
	glGenTextures(1, &TextureID);
	glBindTexture(GL_TEXTURE_CUBE_MAP, TextureID);

	int Width, Height, NrChannels;
	for (int i = 0; i < vFaces.size(); i++)
	{
		unsigned char* data = stbi_load(vFaces[i].c_str(), &Width, &Height, &NrChannels, 0);
		if (data)
		{
			GLenum Format;
			switch (NrChannels)
			{
			case 1:
				Format = GL_RED;
				break;
			case 3:
				Format = GL_RGB;
				break;
			case 4:
				Format = GL_RGBA;
				break;
			default:
				break;
			}

			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, Format, Width, Height, 0, Format, GL_UNSIGNED_BYTE, data);
		}
		else
		{
			std::cerr << "Cubemap texture failed to load at path: " << vFaces[i] << std::endl;
		}

		stbi_image_free(data);
	}

	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	return TextureID;
}

int main()
{
	glfwInit();
	glfwInitHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwInitHint(GLFW_CONTEXT_VERSION_MINOR, 6);
	glfwInitHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	
	/*glfwWindowHint(GLFW_SAMPLES, 4);*/

	GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "StudyOpenGL", NULL, NULL);
	if (window == nullptr)
	{
		std::cerr << "Failed to Create GLFW Window" << std::endl;
		return -1;
	}
	glfwMakeContextCurrent(window);

	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
	glfwSetCursorPosCallback(window, mouse_callback);
	glfwSetScrollCallback(window, scroll_callback);
	//glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cerr << "ERROR::Failed to initalize GLAD" << std::endl;
		return -1;
	}

	Shader NormalShader("shader\\normalshader.vs.txt", "shader\\normalshader.fs.txt");
	ComputeShader ComShader("shader\\computeshader.txt");

	float quadVertices[] = {
		-1.0f,  1.0f,
		-1.0f, -1.0f,
		 1.0f, -1.0f,

		-1.0f,  1.0f,
		 1.0f, -1.0f,
		 1.0f,  1.0f
	};

	GLuint QuadVAO, QuadVBO;
	glGenVertexArrays(1, &QuadVAO);
	glBindVertexArray(QuadVAO);
	glGenBuffers(1, &QuadVBO);
	glBindBuffer(GL_ARRAY_BUFFER, QuadVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
	glBindVertexArray(0);

	GLuint tex;
	glGenTextures(1, &tex);
	glBindTexture(GL_TEXTURE_2D, tex);
	glTexStorage2D(GL_TEXTURE_2D, 8, GL_RGBA32F, 256, 256);

	while (!glfwWindowShouldClose(window))
	{
		float currentFrame = glfwGetTime();
		deltaTime = currentFrame - lastFrame;
		lastFrame = currentFrame;

		processInput(window);

		ComShader.use();
		glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
		glDispatchCompute(16, 16, 1);

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

		NormalShader.use();

		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, tex);
		glBindVertexArray(QuadVAO);
		glDrawArrays(GL_TRIANGLES, 0, 6);

		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	glDeleteVertexArrays(1, &QuadVAO);
	glDeleteBuffers(1, &QuadVBO);

	glfwTerminate();

	return 0;
}


main函数上面的代码,都是之前做其它实验留下的遗产,不用管,和Compute Shader有关的代码,只在main函数里

顶点着色器

#version 460 core
layout (location = 0) in vec2 aPos;

void main()
{
	gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
}

片段着色器

#version 460 core

out vec4 FragColor;

uniform sampler2D ComTexture;

void main()
{
	FragColor = texture(ComTexture, vec2(gl_FragCoord.xy) / vec2(textureSize(ComTexture, 0)));
}

计算着色器

#version 460 core
layout (local_size_x = 16, local_size_y = 16) in;

layout (binding = 0, rgba32f) uniform image2D data;

void main()
{
	imageStore(data, ivec2(gl_GlobalInvocationID.xy), vec4(vec2(gl_LocalInvocationID.xy) / vec2(gl_WorkGroupSize.xy), 0.0, 0.0));
}

你可能感兴趣的:(OpenGL计算着色器Compute Shader的一个简单实例)