OpenGL 中的非渐变颜色变化

问题描述 投票:0回答:1

我正在尝试将三角形的颜色逐渐更改为光谱上的每种颜色。颜色基本上在渲染循环的每次迭代中增量变化,并将颜色信息传递给统一变量。问题在于它在多次迭代之间存在滞后并且不会逐渐改变。主程序上的rgb值是逐渐变化的,但最终三角形的颜色却没有变化。然而,我在没有三角形的整个窗口上执行此操作(逐渐改变颜色)没有问题。

这是三角波谱程序的代码及其输出预览:

#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); // go to the end
    long lsize = ftell(fp);  // size is how far it is from the start
    rewind(fp);              // reset to the start to prepare for reading

    char *buffer = calloc(1, lsize+1); //assign (lsize) blocks of memory to buffer
    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); // unbind VBO
    glBindVertexArray(0);             // unbind VAO

    /*------------------------------------------------------------------------*/

    float min = 0;
    float max = 255;
    float rgb[] = {min, max, min}; // g,r,b instead of r,g,b to emulate spectrum
    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;
}

光谱三角形程序的Fragment Shader:

#version 460 core
out vec4 FragColor;
uniform vec4 color;

void main(){
    FragColor = color;
}

光谱三角形程序的Vertex Shader:

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

void main(){
    gl_Position = vec4(aPos.xyz, 1.0);
}

频谱三角程序的输出: spectrum triangle program NOT changing colors gradually

使用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 instead of r,g,b to emulate spectrum
    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;
}

使用 GlClearColor 的简单光谱程序的输出: spectrum program with glClearColor gradually changing colors

我尝试更改颜色增加的逻辑点,但无济于事。使用 vec3 而不是 vec4 然后调整片段着色器也没有帮助。复制 LearnOpenGL 的代码(从绿色逐渐变为无)可以完美地工作。

LearnOpenGL Triangle changing from green to nothing gradually

c opengl glsl glfw opengl-4
1个回答
0
投票

片段着色器颜色输出的通道应在 [0.0, 1.0] 范围内,而不是 [0.0, 255.0]。

rgb[]
除以 255 主机端,就像在
glClearColor()
示例中或在着色器中所做的那样,然后再分配给
FragColor
:

FragColor = color / 255.0;
© www.soinside.com 2019 - 2024. All rights reserved.