【问题标题】:How to move points in the vertex shader using a timer如何使用计时器移动顶点着色器中的点
【发布时间】:2017-02-21 06:21:55
【问题描述】:

我无法弄清楚如何使用顶点着色器使用计时器为我的对象设置动画。我有一堆点位于窗口中的随机位置。我想要做的是将这些点移动到窗口的中心(即 {0.0,0.0}),然后在一个点到达窗口中心时停在那里。这是我的顶点着色器代码:

layout(location = 0) in vec2 vertexPos;

uniform mat4 P;
uniform mat4 MV;
uniform float time;

void main() {
    gl_Position = P * MV * vec4(vertexPos, 0.0, 1.0);
}

这显示了它们随机位置的所有点。我知道如何将它们移动到中心,但我不知道如何显示实际移动到中心的点。

【问题讨论】:

    标签: opengl


    【解决方案1】:

    在粒子的初始位置和原点之间使用mix()lerp

    layout(location = 0) in vec2 vertexPos;
    
    uniform mat4 P;
    uniform mat4 MV;
    uniform float time;
    
    void main()
    {
        vec2 dest( 0.0, 0.0 );
        vec2 curPos = mix( vertexPos, dest, time );
        gl_Position = P * MV * vec4( curPos, 0.0, 1.0 );
    }
    

    根据主机计时器将主机代码中的 time0.0 更改为 1.0

    编辑:一起来:

    #include <GL/glew.h>
    #include <GL/freeglut.h>
    #include <iostream>
    #include <cstdarg>
    #include <vector>
    using namespace std;
    
    struct Program
    {
        static GLuint Load( const char* shader, ... )
        {
            GLuint prog = glCreateProgram();
            va_list args;
            va_start( args, shader );
            while( shader )
            {
                const GLenum type = va_arg( args, GLenum );
                AttachShader( prog, type, shader );
                shader = va_arg( args, const char* );
            }
            va_end( args );
            glLinkProgram( prog );
            CheckStatus( prog );
            return prog;
        }
    
    private:
        static void CheckStatus( GLuint obj )
        {
            GLint status = GL_FALSE;
            if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
            if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
            if( status == GL_TRUE ) return;
            GLchar log[ 1 << 15 ] = { 0 };
            if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
            if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
            std::cerr << log << std::endl;
            exit( EXIT_FAILURE );
        }
    
        static void AttachShader( GLuint program, GLenum type, const char* src )
        {
            GLuint shader = glCreateShader( type );
            glShaderSource( shader, 1, &src, NULL );
            glCompileShader( shader );
            CheckStatus( shader );
            glAttachShader( program, shader );
            glDeleteShader( shader );
        }
    };
    
    #define GLSL(version, shader) "#version " #version "\n" #shader
    
    const char* vert = GLSL
    (
        330 core,
        layout( location = 0 ) in vec2 vertexPos;
        uniform float time;
        void main()
        {
            vec2 dest = vec2( 0.0, 0.0 );
            vec2 curPos = mix( vertexPos, dest, time );
            gl_Position = vec4( curPos, 0.0, 1.0 );
        }
    );
    
    const char* frag = GLSL
    (
        330 core,
        out vec4 color;
        void main()
        {
            color = vec4( 1.0, 1.0, 1.0, 1.0 );
        }
    );
    
    float rnd( const float lo, const float hi )
    {
        return lo + ( hi - lo ) * ( rand() / (float)RAND_MAX );
    }
    
    GLuint prog = 0;
    GLint timeLoc = -1;
    void init()
    {
        GLuint vao = 0;
        glGenVertexArrays( 1, &vao );
        glBindVertexArray( vao );
    
        std::vector< float > verts;
        for( size_t i = 0; i < 100; ++i )
        {
            verts.push_back( rnd( -1, 1 ) );
            verts.push_back( rnd( -1, 1 ) );
        }
    
        GLuint vbo = 0;
        glGenBuffers( 1, &vbo );
        glBindBuffer( GL_ARRAY_BUFFER, vbo );
        glBufferData( GL_ARRAY_BUFFER, sizeof( float ) * verts.size(), &verts[0], GL_STATIC_DRAW );
    
        glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, 0 );
        glEnableVertexAttribArray( 0 );
    
        prog = Program::Load
            (
            vert, GL_VERTEX_SHADER,
            frag, GL_FRAGMENT_SHADER,
            NULL
            );
        glUseProgram( prog );
        timeLoc = glGetUniformLocation( prog, "time" );
    }
    
    float u = 0.0f;
    void timer( int value )
    {
        const int duration = 3000;
        static int startTime = glutGet( GLUT_ELAPSED_TIME );
        const int curTime = glutGet( GLUT_ELAPSED_TIME );
    
        if( curTime > startTime + duration )
        {
            startTime = curTime;
        }
    
        u  = ( curTime - startTime ) / (float)duration;
    
        glutTimerFunc( 16, timer, 0 );
        glutPostRedisplay();
    }
    
    void display()
    {
        glClear( GL_COLOR_BUFFER_BIT );
        glUniform1f( timeLoc, u );
        glDrawArrays( GL_POINTS, 0, 100 );
        glutSwapBuffers();
    }
    
    int main(int argc, char **argv)
    {
        glutInit( &argc, argv );
        glutInitContextVersion( 3, 3 );
        glutInitContextProfile( GLUT_CORE_PROFILE );
        glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
        glutInitWindowSize( 600, 600 );
        glutCreateWindow( "GLUT" );
    
        glewExperimental = GL_TRUE;
        glewInit();
    
        init();
    
        glutDisplayFunc( display );
        glutTimerFunc( 0, timer, 0 );
        glutMainLoop();
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-23
      • 1970-01-01
      • 2019-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多