2015-02-02 2 views
0

У меня 2-й уровень с box2d, который делает физику. Я применил следующие water effect, описанные в этом уроке. Я использую одну OrthographicCamera, которая сосредоточена на главном символе спрайта. Камера следует за спрайтом, и по мере приближения к краям уровня камера перестает двигаться. В настоящее время шейдер просто отображает воду вдоль нижней части камеры. Мой вопрос заключается в том, как я мог бы сделать воду вдоль дна уровня, чтобы, когда спрайт удаляется от нижней части уровня, вода «движется» за кадром?Libgdx - map shader to world

public class GameRenderer { 

private ImageProvider imageProvider; 
private GameWorld world; 
private SpriteBatch spriteBatch; 
private OrthographicCamera camera; 
Vector2 camPos; 
private Player player; 
private Sprite itemPointer; 
private Sprite playerSprite; 
Sprite explosion; 
Box2DDebugRenderer debugRenderer = new Box2DDebugRenderer(); 
private Array<SimpleSpatial> mSpatials; // used for rendering rube images 
private static final Vector2 mTmp = new Vector2(); 
private Map<String, Texture> mTextureMap; 
private Map<Texture, TextureRegion> mTextureRegionMap; 

//From tutorial 
String vertexShader = 
     "attribute vec4 a_position; \n" 
       + "attribute vec2 a_texCoord0;\n" 
       + "uniform mat4 u_worldView;\n" 
       + "varying vec4 v_color;" 
       + "varying vec2 v_texCoords;" 
       + "void main()     \n" 
       + "{       \n" 
       + " v_color = vec4(1, 1, 1, 1); \n" 
       + " v_texCoords = a_texCoord0; \n" 
       + " gl_Position = u_worldView * a_position; \n" 
       + "}       \n"; 

String fragmentShader = "#ifdef GL_ES\n" 
     + "precision mediump float;\n" 
     + "#endif\n" 
     + "varying vec4 v_color;\n" 
     + "varying vec2 v_texCoords;\n" 
     + "uniform sampler2D u_texture;\n" 
     + "uniform sampler2D u_texture2;\n" 
     + "uniform float timedelta;\n" 
     + "void main()         \n" 
     + "{           \n" 
     + " vec2 displacement = texture2D(u_texture2, v_texCoords/6.0).xy;\n" // 
     + " float t=v_texCoords.y +displacement.y*0.1-0.1+ (sin(v_texCoords.x * 60.0+timedelta) * 0.005); \n" // 
     + " gl_FragColor = v_color * texture2D(u_texture, vec2(v_texCoords.x,t));\n" 
     + "}"; 

String fragmentShader2 = "#ifdef GL_ES\n" 
     + "precision mediump float;\n" 
     + "#endif\n" 
     + "varying vec4 v_color;\n" 
     + "varying vec2 v_texCoords;\n" 
     + "uniform sampler2D u_texture;\n" 
     + "void main()         \n" 
     + "{           \n" 
     + " gl_FragColor = v_color * texture2D(u_texture, v_texCoords);\n" 
     + "}"; 


ShaderProgram shader; 
ShaderProgram waterShader; 

Matrix4 matrix; 
float time; 

Mesh waterMesh; 

private Texture texture2; 
private Texture texture3; 

FPSLogger fpsLogger = new FPSLogger(); 


public GameRenderer(GameWorld gameWorld) { 

    imageProvider = GameManager.getInstance().getImageProvider(); 

    world = gameWorld; 
    spriteBatch = new SpriteBatch(); 
    camPos = new Vector2(); 

    loadBackgroundTextures(); 
    loadPlayerTextures(); 

    explosion = new Sprite(imageProvider.getExplosion()); 
    explosion.setScale(50 * Constants.WORLD_TO_BOX); 

    setupCamera(); 

    Gdx.input.setCatchBackKey(true); 
} 

public void show() { 

    initGame(); 
} 

private void initGame() { 

    player = world.getPlayer(); 
    playerSprite = new Sprite(playerTexture); 
    playerSprite.setScale(15 * Constants.WORLD_TO_BOX, 15 * Constants.WORLD_TO_BOX); 

    createSpatialsFromRubeImages(world.getScene()); 

    initialiseShaders(); 

} 

private void createSpatialsFromRubeImages(RubeScene scene) 
{ 

    Array<RubeImage> images = scene.getImages(); 
    if ((images != null) && (images.size > 0)) 
    { 
     mSpatials = new Array<>(); 
     for (int i = 0; i < images.size; i++) 
     { 
      RubeImage image = images.get(i); 
      mTmp.set(image.width, image.height); 
      String textureFileName = image.file; 
      Texture texture = mTextureMap.get(textureFileName); 
      if (texture == null) 
      { 
       texture = new Texture(textureFileName); 
       mTextureMap.put(textureFileName, texture); 
      } 
      SimpleSpatial spatial = new SimpleSpatial(texture, image.flip, image.body, image.color, mTmp, image.center, 
        image.angleInRads * MathUtils.radiansToDegrees); 
      mSpatials.add(spatial); 
     } 
    } 
} 

    //From tutorial 
public void initialiseShaders() { 

    texture2 =new Texture(Gdx.files.internal("gfx/shaders/water.png")); 
    texture2.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear); 

    texture3 = new Texture(Gdx.files.internal("gfx/shaders/waterdisplacement.png")); 
    texture3.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear); 
    texture3.bind(); 
    matrix = new Matrix4(); 


    ShaderProgram.pedantic=false; 

    shader = new ShaderProgram(vertexShader, fragmentShader); 

    waterShader = new ShaderProgram(vertexShader, fragmentShader2); 
    waterShader.setUniformMatrix("u_projTrans", matrix); 

    waterMesh = createQuad(); 

    time=1f; 
} 

//From tutorial 
public Mesh createQuad() { 
    float[] verts = new float[20]; 
    int i = 0; 

    verts[i++] = -1; // x1 
    verts[i++] = -1; // y1 
    verts[i++] = 0; 
    verts[i++] = 1f; // u1 
    verts[i++] = 1f; // v1 // 

    verts[i++] = 1f; // x2 
    verts[i++] = -1; // y2 
    verts[i++] = 0; 
    verts[i++] = 0f; // u2 
    verts[i++] = 1f; // v2 // 

    verts[i++] = 1; // x3 
    verts[i++] = -0.3f; // y2 
    verts[i++] = 0; 
    verts[i++] = 0f; // u3 
    verts[i++] = 0f; // v3 

    verts[i++] = -1; // x4 
    verts[i++] = -0.3f; // y4 
    verts[i++] = 0; 
    verts[i++] = 1f; // u4 
    verts[i++] = 0f; // v4 

    Mesh mesh = new Mesh(true, 4, 0, // static mesh with 4 vertices and no 
      // indices 
      new VertexAttribute(VertexAttributes.Usage.Position, 3, 
        ShaderProgram.POSITION_ATTRIBUTE), new VertexAttribute(
      VertexAttributes.Usage.TextureCoordinates, 2, 
      ShaderProgram.TEXCOORD_ATTRIBUTE + "0")); 

    mesh.setVertices(verts); 
    return mesh; 

} 

private void setupCamera() { 

    camera = new OrthographicCamera(imageProvider.getScreenWidth(), imageProvider.getScreenHeight()); 
    camera.position.x = 500; 
    camera.position.y = 500; 

    camera.zoom = Constants.ZOOM_FACTOR; 
    camera.update(); 
} 

public void render(float delta) { 

    spriteBatch.flush(); 

    Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT); 
    fpsLogger.log(); 


    Gdx.gl.glScissor(0, 0, (int)Constants.SCREEN_WIDTH, (int)Constants.SCREEN_HEIGHT); 
    Gdx.gl.glDisable(GL20.GL_SCISSOR_TEST); 
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 
    Gdx.gl.glEnable(GL20.GL_SCISSOR_TEST); 

    camera.update(); 
    spriteBatch.setProjectionMatrix(camera.combined); 

    drawBackground(); 
    updateCameraPosition(); 
    drawRest(delta); 
    drawPlayer(delta); 

    //Render water shader 
    drawWater(); 

    debugRenderer.render(world.getRubeWorld(), camera.combined); 
} 

public void drawWater() { 

    spriteBatch.setProjectionMatrix(camera.combined); 

    float dt = Gdx.graphics.getDeltaTime(); 
    time += dt; 
    float angle = time * (2 * MathUtils.PI); 
    if (angle > (2 * MathUtils.PI)) 
     angle -= (2 * MathUtils.PI); 

    //RENDER WATER 
    Gdx.gl20.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); 
    Gdx.gl20.glEnable(GL20.GL_BLEND); 


    texture2.bind(1); 
    texture3.bind(2); 
    shader.begin(); 
    shader.setUniformMatrix("u_worldView", matrix); 
    shader.setUniformi("u_texture", 1); 
    shader.setUniformi("u_texture2", 2); 
    shader.setUniformf("timedelta", -angle); 
    shader.setUniformf("v_texCoords.y", -10f); 

    waterMesh.render(shader, GL20.GL_TRIANGLE_FAN); 
    shader.end(); 

    Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0); 
    //Gdx.gl20.glDisable(GL20.GL_BLEND); 


} 
public void drawBackground() { 

    spriteBatch.begin(); 
    spriteBatch.setProjectionMatrix(parallaxCamera.combined); 
    spriteBatch.draw(backgroundImage, parallaxCamera.position.x - 400, parallaxCamera.position.y - 240); 
    spriteBatch.end(); 

} 

public void drawRest(float delta) { 

    camera.update(); 
    spriteBatch.setProjectionMatrix(camera.combined); 

    spriteBatch.begin(); 

    //Renders Box2d world 
    for (int i = 0; i < mSpatials.size; i++) 
    { 
     mSpatials.get(i).render(spriteBatch, 0); 
    } 

    spriteBatch.end(); 
} 

public void drawPlayer(float delta) { 

    if (!world.isGameOver()) { 

     spriteBatch.begin(); 

     playerSprite.setOrigin(playerSprite.getWidth()/2, playerSprite.getHeight()/2); 
     playerSprite.setPosition(world.getPlayer().getPosition().x - playerSprite.getWidth()/2, world.getPlayer().getPosition().y - playerSprite.getHeight()/2); 
     playerSprite.setRotation(world.getPlayer().getDirection() - 90); 
     playerSprite.draw(spriteBatch); 

     spriteBatch.end(); 
    } 
    else { 

     spriteBatch.begin(); 
     explosion.draw(spriteBatch); 
     spriteBatch.end(); 

    } 
} 

private void updateCameraPosition() { 

    camPos.lerp(world.getPlayer().getPosition(), 1.5f); 

    if (camPos.x * Constants.WORLD_TO_BOX < LEVELWIDTH && camPos.x * Constants.WORLD_TO_BOX > 0) { 

     camera.position.x = camPos.x; 
    } 

    if (camPos.y * Constants.WORLD_TO_BOX < LEVELHEIGHT && camPos.y * Constants.WORLD_TO_BOX > 0.75) { 

     camera.position.y = camPos.y; 
    } 
} 

}

ответ

0

Вы посылаете в camera.combined матрицу в u_worldView?

shader.setUniformMatrix("u_worldView", cam.combined); 

Если у вас есть фрагменты кода, которые были бы очень полезными.

+0

Я редактировал вопрос, чтобы включить образец кода моего класса GameRenderer. Как вы можете видеть, я передавал только Matrix4 i.e: shader.setUniformMatrix («u_worldView», матрица); Я отредактировал его, чтобы теперь я проходил camera.combined, однако шейдер не отображается на экране в любой точке мира. –

+0

Мне любопытно, вы когда-нибудь узнавали, что происходит? Я думал, что это не тот ответ, который вы искали. –

+0

Я думал, что это не так, но после перемещения некоторых вершин сетки строка shader.setUniformMatrix («u_worldView», cam.combined); был ключом к тому, чтобы заставить эффект шейдера прекратить следовать за камерой (возможно, потому, что я использую масштабирование, и поскольку мой мир box2d крошечный, основная камера фактически не перемещается). –