我正在为桌面编写一个类似着色器的工具。它使用GLFW(OpenGL)、Glad和ImGui来渲染图像。
我现在已经到了一个点,我修复了我以前所有的问题,但我现在坚持在一个特定的问题,一直困扰着我过去几天。
我希望能够热重新加载着色器。现在,它采取了一个简单的mandelbulb光线行进GLSL片段,绘制它,也绘制了一个小的ImGui面板与“重新加载着色器”按钮。
我一直在想如何取消当前着色器程序的链接,并重新加载一个新的着色器,但我一无所获。代码没有任何错误,但它肯定不工作。当我点击按钮时,OpenGL视口就变黑了。
我试过在网上寻找,但基本上没有坚实的解决方案,我已经看到的大多数问题从来没有真正得到回答。
这是我当前重置着色器的代码(并再次从文件中获取它)
if (ImGui::Button("Reload Shader", ImVec2(0, 0))) {
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
gladLoadGL();
glViewport(0, 0, width, height);
vertexShader = glCreateShader(GL_VERTEX_SHADER);
fragmentShader = loadShaderFromFile("assets\\round.glsl", GL_FRAGMENT_SHADER);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
GLuint VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glUseProgram(shaderProgram);
GLint resUniform = glGetUniformLocation(shaderProgram, "iResolution");
glUniform3f(resUniform, width, height, width / height);
double mxpos, mypos;
glfwGetCursorPos(window, &mxpos, &mypos);
GLint mouseUniform = glGetUniformLocation(shaderProgram, "iMouse");
glUniform4f(mouseUniform, mxpos, mypos, mxpos, mypos);
GLint timeUniform = glGetUniformLocation(shaderProgram, "iTime");
glUniform1f(timeUniform, currentTime);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
这是当前github提交的所有代码/整个程序,如果需要的话:
https://github.com/ArctanStudios/OpenGL-Sandbox/tree/e7ba32310b898d1a60eae89f8969179600f5d391
实际的Main.cpp文件以及我的GLFW代码的其余部分:
https://github.com/ArctanStudios/OpenGL-Sandbox/blob/e7ba32310b898d1a60eae89f8969179600f5d391/Main.cpp
2条答案
按热度按时间j9per5c41#
所以在摆弄了一会儿之后,我真的弄明白了。
结果发现我做的比要求的要多得多。
我所需要做的就是在开始时分离片段,然后删除所有内容,然后重新附加一个新的片段,再次链接程序,然后再次分离并删除它。
现在,我可以在运行时重新加载着色器。
初始化期间使用的代码I:
它所做的只是抓取frag + vert,将它们都附加,将程序缓存/链接到渲染器,然后分离frag,删除vertex + frag以保存内存,并准备随时覆盖。
下面是我在reload按钮中使用的代码:
这样做的目的是获取当前的着色器程序,没有片段,并且已经存在的顶点仍然缓存在其中。
然后它附加新的片段,再次链接/缓存程序到渲染器,然后从初始的一个重复该过程。它分离片段,删除它以保存内存,然后它准备再次被覆盖。
你也可以使用顶点着色器,只是分离和删除它,就像片段一样。我决定不这样做,因为我的程序的目的是渲染2D着色器到一个平面上,类似于shadertoy
7fyelxc52#
要为当前程序使用着色器,只需执行以下操作。