2017-02-20 37 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); 
} 

這說明在他們的隨機位置的所有點。我知道如何將他們移動到中心,但我不知道如何顯示實際移動到中心的點。

回答

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.01.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; 
}