在使用 OpenGLES 2.0 的 Android 上使用 Gaffer 的固定时间戳时出现口吃

我的游戏循环出现了一些细微的卡顿。 我正确地实现了(我认为)来自 https://gafferongames.com/post/fix_your_timestep/

的固定时间戳技术

我认为当技术正确实施时,精灵运动是完全平滑的。我的代码没有产生 100% 的平滑,但一点也不差。

表面类:

public static final int FRAME_RATE = 30;
public static final double DELTA_TIME = 1/(double)FRAME_RATE;

private double lastTimeStamp;
private double accumulator;

// An entity position in the game
public float oldX,x;

@Override
public void onDrawFrame(GL10 unused) {
    double now = (System.nanoTime() - lastTimeStamp)/1000000 * 0.001;

    if (now > 0.25) {
        now = 0.25;
    }

    lastTimeStamp = System.nanoTime();
    accumulator += now;

    while (accumulator >= DELTA_TIME) {
        tick(DELTA_TIME);
        accumulator -= DELTA_TIME;
    }

    double alpha = accumulator/DELTA_TIME;

    render(alpha);
}

public void tick(double dt) {
    oldX = x;

    x++; // increment entity x position
}

public void render(double alpha) {
    float xx = (x - oldX) * (float)alpha + oldX; // interpolated x position

    ShaderBasic.render(fooTexture,xx,0); // render class
}

着色器类:

public void render(Texture texture,float x,float y) {
    //RENDERING
    glUseProgram(glIdProgram);

    //VERTICES
    glEnableVertexAttribArray(glPosition);
    glVertexAttribPointer(glPosition,2,GL_FLOAT,false,texture.vertexBuffer);

    //UVS
    glEnableVertexAttribArray(glUv);
    glVertexAttribPointer(glUv,texture.uvBuffer[0]);

    //MODEL
    glUniform2f(glTrans,x,y); 

    //RENDERING
    glactiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D,texture.glIdTexture);
    glUniform1i(glTexture,0);
    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_SHORT,texture.indexBuffer);

    //DISABLE
    glDisableVertexAttribArray(glPosition);
    glDisableVertexAttribArray(glUv);
    glBindTexture(GL_TEXTURE_2D,0);

}

顶点着色器部分:

void main() {                       
    mat4 model = mat4(1.0,0.0,1.0,v_trans.x,v_trans.y,1.0);

    mat4 projection = mat4(0.0036764,0.0041666,1.0);

    gl_Position = projection * model * vec4(v_position,1.0);
    v_texCoord  = v_uv;                                           

}

纹理加载器类:

    private void loadImage(String imgPath,int frames) throws IOException {
        int[] id = new int[1];
        glGenTextures(1,id,0);

        Bitmap img = BitmapFactory.decodeStream(Utils.getassets().open(imgPath));
        glBindTexture(GL_TEXTURE_2D,id[0]);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // question
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
        GLUtils.texImage2D(GL_TEXTURE_2D,img,0);
        glBindTexture(GL_TEXTURE_2D,0);

        glIdTexture = id[0];
        width = img.getWidth();
        height = img.getHeight();

        this.frameWidth = width/frames;
        this.frameHeight = height;

        img.recycle();
}

另一个问题:当我们使用小数部分大于0的(x,y)坐标时,纹理过滤一定是GL_LINEAR吗?我注意到当我使用 GL_NEAREST 时,屏幕上渲染的精灵在屏幕的某些位置被切片。我认为 GL_NEAREST 当我们有十进制不精确时不会过滤所有的纹理像素......

谢谢!!!!

lxwtsqr 回答:在使用 OpenGLES 2.0 的 Android 上使用 Gaffer 的固定时间戳时出现口吃

我的代码没有产生 100% 的平滑,但一点也不差。

您是否始终达到 60 FPS?如果不是,那么您会遇到一些微卡顿,因为 Android OpenGL ES 使用三重缓冲和垂直同步,因此显示交换永远不会完全匹配您的应用程序端帧时序。

另一个问题:当我们使用小数部分大于0的(x,y)坐标时,纹理过滤一定是GL_LINEAR吗?我注意到当我使用 GL_NEAREST 时,屏幕上渲染的精灵在屏幕的某些位置被切片。我认为 GL_NEAREST 当我们有十进制不精确时不会过滤所有的纹理像素......

正确,顾名思义,GL_NEAREST 只返回距离采样点最近的纹素,没有进行任何过滤。对于不是 1:1 texel-to-pixel 的任何东西,它通常永远不会是您想要使用的。

以后每个帖子只能问一个问题。

本文链接:https://www.f2er.com/270937.html

大家都在问