2017-02-20 9 views
1

頂点シェーダを使用してオブジェクトをアニメーション化する方法がわかりません。私は、窓の中のランダムな場所にポイントの束を持っています。私がやりたいことは、それらの点をウインドウの中心({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); 
} 

これは彼らのランダムな場所にあるすべてのポイントを示しています。私はそれらをセンターに移動する方法を知っていますが、実際に中心に移動しているポイントをどのように表示するのか分かりません。粒子の初期位置と原点とのlerp

答えて

1

使用mix()

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); 
} 

がホストタイマーに基づいてホスト・コードに1.00.0からtimeを変更します。

EDIT:すべて一緒:

#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; 
} 
関連する問題