iOS. OpenGL.在曲线下用渐变填充区域 [英] iOS. OpenGL. Fill area with gradient under curve line

查看:246
本文介绍了iOS. OpenGL.在曲线下用渐变填充区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要创建类似Siri的声波动画( SiriAnim ) 使用OpenGL,我的波形像波浪一样:

这是我的代码:

@property (strong, nonatomic) EAGLContext *context;
@property (strong, nonatomic) GLKBaseEffect *effect;

//    .....

- (void)setupGL {

    [EAGLContext setCurrentContext:self.context];
    glEnable(GL_CULL_FACE);

    self.effect = [[GLKBaseEffect alloc] init];

    self.effect.useConstantColor = GL_TRUE;
    self.effect.constantColor = GLKVector4Make(0.0f, 1.0f, 0.0f, 1.0f);
}

//    .....

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {

    glClearColor(_curRed, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    [self.effect prepareToDraw];

    GLfloat line[1440];

    for (int i = 0; i < 1440; i += 4) {

        float x = 0.002*i - 0.75;

        float K = 8.0f;
        float radians = DEGREES_TO_RADIANS(i/2);

        float func_x = 0.4 *
                       pow(K/(K + pow(radians-M_PI,4.0f)), K) *
                       cos(radians-M_PI);

        line[i]   = x;
        line[i+1] = func_x;

        line[i+2] = x;
        line[i+3] = -func_x;
    }

    GLuint bufferObjectNameArray;

    glGenBuffers(1, &bufferObjectNameArray);

    glBindBuffer(GL_ARRAY_BUFFER, bufferObjectNameArray);

    glBufferData(
                 GL_ARRAY_BUFFER,
                 sizeof(line),
                 line,
                 GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);

    glVertexAttribPointer(
                          GLKVertexAttribPosition,
                          2,
                          GL_FLOAT,
                          GL_FALSE,
                          2*4,
                          NULL);

    glLineWidth(15.0);
    glDrawArrays(GL_LINES, 0, 360);
}

但是!我很困惑,因为我找不到任何梯度解决方案.经过大量的搜索,我什至强烈怀疑这样的任务是不可能的(因为我认为GLKBaseEffect * effect.constantColor). 所以!有人可以帮我解决这个问题吗? 可以使用着色器或纹理(最差的解决方案)解决此问题吗?

祝福您的答案!

解决方案

尽管可以使用纹理来完成,但我认为最简单的方法是使用OpenGL的默认颜色插值.如果将线条的顶部顶点绘制为浅蓝色,将底部顶点绘制为深蓝色,则GPU会自动对它们之间的颜色进行插值以逐渐改变,并产生所需的渐变效果. /p>

在代码中实现此功能的最简单方法是在缓冲区(线"数组)中为该线的每个顶点的颜色腾出空间,并设置着色器以输出此值.这意味着您必须将此颜色的输入和输出添加到顶点和像素着色器.想法是将其从顶点传递到像素着色器,然后像素着色器输出未修改的值.硬件会自动为您处理颜色之间的插值(!).

许多现代OpenGL教程都提供了执行此操作的示例.一个免费的在线网站可以从学习OpenGL的着色器教程.不过,如果您有钱,我最喜欢的缓冲区,着色器和管道本身的说明在Graham Sellers的 OpenGL SuperBible .如果您打算经常使用OpenGL并真正学习它,那么它是无价的桌面参考.

I need to create a sound wave animation like Siri (SiriAnim) With OpenGL I'v got a shape of wave:

Here is my code:

@property (strong, nonatomic) EAGLContext *context;
@property (strong, nonatomic) GLKBaseEffect *effect;

//    .....

- (void)setupGL {

    [EAGLContext setCurrentContext:self.context];
    glEnable(GL_CULL_FACE);

    self.effect = [[GLKBaseEffect alloc] init];

    self.effect.useConstantColor = GL_TRUE;
    self.effect.constantColor = GLKVector4Make(0.0f, 1.0f, 0.0f, 1.0f);
}

//    .....

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {

    glClearColor(_curRed, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    [self.effect prepareToDraw];

    GLfloat line[1440];

    for (int i = 0; i < 1440; i += 4) {

        float x = 0.002*i - 0.75;

        float K = 8.0f;
        float radians = DEGREES_TO_RADIANS(i/2);

        float func_x = 0.4 *
                       pow(K/(K + pow(radians-M_PI,4.0f)), K) *
                       cos(radians-M_PI);

        line[i]   = x;
        line[i+1] = func_x;

        line[i+2] = x;
        line[i+3] = -func_x;
    }

    GLuint bufferObjectNameArray;

    glGenBuffers(1, &bufferObjectNameArray);

    glBindBuffer(GL_ARRAY_BUFFER, bufferObjectNameArray);

    glBufferData(
                 GL_ARRAY_BUFFER,
                 sizeof(line),
                 line,
                 GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);

    glVertexAttribPointer(
                          GLKVertexAttribPosition,
                          2,
                          GL_FLOAT,
                          GL_FALSE,
                          2*4,
                          NULL);

    glLineWidth(15.0);
    glDrawArrays(GL_LINES, 0, 360);
}

BUT! I'm confused because i can't find any solutions for gradient. After a lot of time of searching I even have a strong suspicion that such task is impossible (because GLKBaseEffect *effect . constantColor i think). So! Could anyone help me with any solution for this task? Can this problem be solved with shaders or textures (the worst solution)?

Bless you for your answers!

解决方案

Although this could be done with a texture, I think the easiest way to accomplish this is by using OpenGL's default color interpolation. If you make the top vertex of the lines you're drawing a light blue, and the bottom vertex a darker blue, the GPU will automatically interpolate the colors between them to gradually change, and produce the gradient effect you're looking for.

The easiest way to implement this in your code is to make room in your buffer, the "lines" array, for the color of every single vertex of the line, and set up your shaders to output this value. That means you'll have to add inputs and outputs for this color to your vertex and pixel shaders. The idea is to pass it from the vertex to the pixel shader, and the pixel shader outputs the value unmodified. The hardware handles the interpolation between colors automatically for you(!).

Many modern OpenGL tutorials have examples of doing this. One free online one is from LearnOpenGL's Shader tutorial. If you have the money, though, my favorite explanation of buffers, shaders, and the pipeline itself is in Graham Sellers' OpenGL SuperBible. If you plan on using OpenGL often and really learning it, it's an invaluable desktop reference.

这篇关于iOS. OpenGL.在曲线下用渐变填充区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆