OpenGL中三角形颜色无法平滑渐变的问题排查
问题:三角形颜色光谱渐变卡顿,无法平滑过渡
我尝试让三角形颜色沿光谱平滑渐变,在渲染循环的每次迭代中逐步调整颜色值,并传递给uniform变量。但当前问题是颜色切换卡顿,无法平滑过渡;主程序中的RGB值已实现逐步变化,但三角形颜色并未同步渐变。不过用glClearColor实现全屏颜色渐变时完全正常。
三角形光谱渐变程序代码
主程序
#include <stdio.h> #include <stdlib.h> #include <math.h> #define GLFW_INCLUDE_NONE #include "include/glad/glad.h" #include <GLFW/glfw3.h> void framebufferSizeCallback(GLFWwindow* window, int width, int height){ glViewport(0, 0, width, height); } void processInput(GLFWwindow* window){ ; } char * parseFile(const char * fileName){ FILE *fp = fopen(fileName, "r"); if (!fp) perror(fileName),exit(1); fseek(fp, 0L, SEEK_END); // 移动到文件末尾 long lsize = ftell(fp); // 获取文件大小 rewind(fp); // 重置到文件开头 char *buffer = calloc(1, lsize+1); // 分配内存 if (!buffer) fclose(fp),fputs("Failed to allocate memory.",stderr),exit(1); if(1!=fread(buffer,lsize,1,fp)) fclose(fp),free(buffer),fputs("Failed to read file.", stderr),exit(1); fclose(fp); return buffer; } int main(void){ glfwInit(); if (glfwInit() != GLFW_TRUE){ printf("Failed to initialize GLFW."); glfwTerminate(); return -1; } glfwWindowHint(GLFW_VERSION_MAJOR, 4); glfwWindowHint(GLFW_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); int windowSize = 600; GLFWwindow* window; window = glfwCreateWindow(windowSize, windowSize, "spectrum", NULL, NULL); if (window == NULL){ printf("Failed to create window.\n"); glfwTerminate(); return -1; } glfwMakeContextCurrent(window); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){ printf("Failed to initialize GLAD.\n"); return 1; } glViewport(0, 0, windowSize, windowSize); glfwSetFramebufferSizeCallback(window, framebufferSizeCallback); /*------------------------------------------------------------------------*/ const char *vertexShader = parseFile("timeTriangleShaders/vert.glsl"); const char *fragmentShader = parseFile("timeTriangleShaders/frag.glsl"); unsigned int vertexShaderID = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShaderID, 1, &vertexShader, NULL); glCompileShader(vertexShaderID); unsigned int fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShaderID, 1, &fragmentShader, NULL); glCompileShader(fragmentShaderID); unsigned int shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShaderID); glAttachShader(shaderProgram, fragmentShaderID); glLinkProgram(shaderProgram); free((char*)vertexShader); free((char*)fragmentShader); glDeleteShader(vertexShaderID); glDeleteShader(fragmentShaderID); /*------------------------------------------------------------------------*/ float vertices[] = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f }; unsigned int 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, 1); // 解绑VBO glBindVertexArray(0); // 解绑VAO /*------------------------------------------------------------------------*/ float min = 0; float max = 255; float rgb[] = {min, max, min}; // 用g,r,b顺序模拟光谱 int pos = 0; int increment = 10; while (!glfwWindowShouldClose(window)){ glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(shaderProgram); int colorUniformLocation = glGetUniformLocation(shaderProgram, "color"); if ((rgb[pos] >= max && increment > 0) || (rgb[pos] <= min && increment < 0)){ rgb[pos] = rgb[pos] > max ? max : min; pos = pos == 2 ? 0 : ++pos; increment = -increment; } else rgb[pos] += increment; printf("rgb: (%3.f, %3.f, %3.f) | %3d\n", rgb[1], rgb[0], rgb[2], increment); glUniform4f(colorUniformLocation, rgb[1], rgb[0], rgb[2], 1.0f); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 3); glfwSwapBuffers(window); glfwPollEvents(); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteProgram(shaderProgram); glfwTerminate(); return 0; }
片段着色器(timeTriangleShaders/frag.glsl)
#version 460 core out vec4 FragColor; uniform vec4 color; void main(){ FragColor = color; }
顶点着色器(timeTriangleShaders/vert.glsl)
#version 460 core layout (location = 0) in vec3 aPos; void main(){ gl_Position = vec4(aPos.xyz, 1.0); }
程序效果
三角形颜色无法平滑渐变,切换时存在明显卡顿。
glClearColor实现的正常光谱渐变代码
#include <stdio.h> // #define GLFW_INCLUDE_NONE #include "include/glad/glad.h" #include <GLFW/glfw3.h> void framebufferSizeCallback(GLFWwindow* window, int width, int height){ glViewport(0, 0, width, height); } int main(void){ glfwInit(); if (glfwInit() != GLFW_TRUE){ printf("Failed to initialize GLFW."); glfwTerminate(); return -1; } glfwWindowHint(GLFW_VERSION_MAJOR, 4); glfwWindowHint(GLFW_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); int windowSize = 600; GLFWwindow* window; window = glfwCreateWindow(windowSize, windowSize, "spectrum", NULL, NULL); if (window == NULL){ printf("Failed to create window.\n"); glfwTerminate(); return -1; } glfwMakeContextCurrent(window); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){ printf("Failed to initialize GLAD.\n"); return 1; } glViewport(0, 0, windowSize, windowSize); glfwSetFramebufferSizeCallback(window, framebufferSizeCallback); float min = 0; float max = 255; float rgb[] = {min, max, min}; // 用g,r,b顺序模拟光谱 int pos = 0; int increment = 10; while (!glfwWindowShouldClose(window)){ glClearColor(rgb[1]/255, rgb[0]/255, rgb[2]/255, 1.0f); glClear(GL_COLOR_BUFFER_BIT); if ((rgb[pos] >= max && increment > 0) || (rgb[pos] <= min && increment < 0)){ rgb[pos] = rgb[pos] > max ? max : min; pos = pos == 2 ? 0 : ++pos; increment = -increment; } else rgb[pos] += increment; glfwSwapBuffers(window); glfwPollEvents(); } glfwTerminate(); return 0; }
程序效果
全屏颜色平滑渐变,无卡顿现象。
已尝试的解决方法
- 调整颜色递增逻辑的位置,无效
- 将uniform从
vec4改为vec3并修改片段着色器,无效 - 复刻LearnOpenGL中三角形从绿色渐变为无色的代码,可完美运行(该效果为颜色平滑过渡)
内容的提问来源于stack exchange,提问作者Creui
相关产品推荐
相关产品推荐

