You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 05:08:12