之前因为老师让实现一下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));
}