2016-11-04 28 views
0

我試圖在我的2D遊戲中實現爆炸衝擊波效果 這些是我嘗試的步驟 1)將所有東西繪製到幀緩衝區(紋理區域和網格) 2)從幀緩衝器獲取紋理和垂直翻轉 3)繪製所得紋理着色器來篩選從本http://empire-defense.crystalin.fr/blog/2d_shock_wave_texture_with_shader在整個屏幕上使用opengl着色器和幀緩衝器在整個屏幕上的爆炸衝擊波效果座標

這是我的渲染方法

resultBuf.begin(); 
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 
    Gdx.gl20.glViewport(0, 0, resultBuf.getWidth(), resultBuf.getHeight()); 
    Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D); 

    batch.begin(); 
    renderbackground(); 
    batch.setProjectionMatrix(camera.combined); 



    if(imageObjDraw){ 
     for(Integer type:imageObjects.keySet()){ 
      if(type!=ImageObject.mountains&&type!=ImageObject.steelbridge1&&type!=ImageObject.steelbridge2&&type!=ImageObject.steelbridge3)for(ImageObject o:imageObjects.get(type))if(o.isInSquare(camRec))o.draw(batch); 
     } 
    } 
    batch.end(); 

    if (meshDraw) { 
     //DRAWING MESHES 
     shaderPassThrough.begin(); 
     Gdx.graphics.getGL20().glEnable(GL20.GL_BLEND); 
     shaderPassThrough.setUniformMatrix("u_projTrans", camera.combined); 
     shaderPassThrough.setUniformi("u_texture", 0); 
     for(Integer key:meshes.keySet()){ 
      if(key!=MeshInfo.bridge){ 
       LinkedList<myMesh> mlist=meshes.get(key); 
       Texture tex=meshTextures.get(key); 
       if(tex!=null)tex.bind(0); 
       for(myMesh m:mlist){ 
        m.render(); 
       } 
      } 
     } 
     shaderPassThrough.end(); 
    } 

    batch.begin(); 
    if(drawObjEnable){ 
     drawObjects(batch); 
     vehicle.drawState0(batch); 
     drawParticles(batch); 
    } 

    if(particleDraw)PushTheLimits.animMan.render(batch); 
    if(bulletEnable)BulletManager.render(batch); 

    if(imageObjDraw){ 
     for(Integer type:imageObjects.keySet()){ 
      if(type==ImageObject.steelbridge1||type==ImageObject.steelbridge2||type==ImageObject.steelbridge3)for(ImageObject o:imageObjects.get(type))if(o.isInSquare(camRec))o.draw(batch); 
     } 
    } 

    batch.end(); 

    if (meshDraw) { 
     //DRAWING MESHES 
     shaderPassThrough.begin(); 
     Gdx.graphics.getGL20().glEnable(GL20.GL_BLEND); 
     shaderPassThrough.setUniformMatrix("u_projTrans", camera.combined); 
     shaderPassThrough.setUniformi("u_texture", 0); 
     for(Integer key:meshes.keySet()){ 
      if(key==MeshInfo.bridge){ 
       LinkedList<myMesh> mlist=meshes.get(key); 
       Texture tex=meshTextures.get(key); 
       if(tex!=null)tex.bind(0); 
       for(myMesh m:mlist){ 
        m.render(); 
       } 
      } 
     } 
     shaderPassThrough.end(); 
    } 

    resultBuf.end(); 

    batch.begin(); 
    batch.setShader(shaderWave); 
    shaderWave.begin(); 
    shaderWave.setUniformMatrix("u_projTrans", camera.combined); 
    shaderWave.setUniformi("sceneTex", 0); 
    shaderWave.setUniformf("center", new Vector2((explCoorX-camera.position.x+camera.effectivewidth/2f)/camera.zoom/screenW,(explCoorY-camera.position.y+camera.effectiveheight/2f)/camera.zoom/screenH)); 
    shaderWave.setUniformf("time", waveElaps); 
    shaderWave.setUniformf("shockParams", new Vector3(10.0f, 0.8f, 0.1f)); 
    resultTexReg.setRegion(resultBuf.getColorBufferTexture()); 
    resultTexReg.flip(false, true); 
    resultTexReg.getTexture().bind(); 
    batch.draw(resultTexReg, camera.position.x-camera.effectivewidth/2f,camera.position.y-camera.effectiveheight/2f,camera.effectivewidth,camera.effectiveheight); 
    batch.end(); 
    batch.setShader(null); 

這裏的着色器 片段着色器

#ifdef GL_ES 
precision highp float; 
#endif 
uniform sampler2D sceneTex; // 0 
uniform vec2 center; // Mouse position 
uniform float time; // effect elapsed time 
uniform vec3 shockParams; // 10.0, 0.8, 0.1 
varying vec2 v_texCoords; 
varying vec2 proj; 
void main() 
{ 
    float distance = distance(v_texCoords, center); 
    if ((distance <= (time + shockParams.z)) && (distance >= (time - shockParams.z))) { 
    float diff = (distance - time); 
    float powDiff = 1.0 - pow(abs(diff*shockParams.x), shockParams.y); 
    float diffTime = diff * powDiff; 
    vec2 diffUV = normalize(v_texCoords-center); 
    v_texCoords = v_texCoords + (diffUV * diffTime); 
    } 
    gl_FragColor = texture2D(sceneTex, v_texCoords); 
} 

頂點着色器

attribute vec4 a_position; 
attribute vec2 a_texCoord0; 
uniform mat4 u_projTrans; 
varying vec2 v_texCoords; 
varying vec2 proj; 
void main() {  
//proj=u_projTrans.xy; 
v_texCoords = a_texCoord0; 
gl_Position = u_projTrans * a_position; 
} 

以始終施加關於屏幕座標我的意思是中心變量I傳遞到片段着色器 - 即定義問題 衝擊波作用0,0-必須是我box2d世界座標的原點,但即使將相機移動到地圖效果的最後,效果也始終應用於屏幕的左下角,效果在屏幕的左下角,但我希望它在在世界的起源是0,0非常離開屏幕我懷疑這個問題與我在相機的位置上繪製相應的紋理有關,並且我在着色器中使用相機作爲投影矩陣,但是我對這個着色器主題和圖形座標沒有很好的理解,實際上我對它進行了很好的研究似乎對我是正確的,但我不能看到錯誤,並在這一點上需要幫助 預先感謝請評論如果我沒有足夠清楚地告訴問題我會編輯和添加所需的信息,甚至可能你想看到一些屏幕截圖?

回答

0

您的片段着色器中被稱爲「中心」的統一制不是在世界座標中指定的。當您將渲染到紋理渲染到屏幕時,它在紋理座標中指定。

所以無論你的世界相機在哪裏,座標0,0總是在屏幕的左下角,1,1是右上角。

爲了傳遞vec2'中心'的適當值,必須將爆炸的座標(或任何引起衝擊波的座標)從您的世界空間座標系轉換爲紋理空間。

這樣做的一種方法是將世界座標乘以相機WVP矩陣(camera.combined)。如果它是透視攝像機,則可能需要將結果的xy除以w。這應該給你一個從-1,-1到1,1的剪輯空間座標。然後你需要通過加1和減半重新映射到紋理座標。你可以在頂點着色器中做這件事,並通過改變來傳遞結果,或者你可以在CPU上完成,並將結果作爲統一傳遞。

+0

感謝您的快速回復我做了你如何說,現在的作品,但不幸的是只有在桌面上現在座標不是問題,但當爆炸發生在爆炸期間,我看到只是一個黑色的屏幕,應用衝擊波效應,但是當沒有爆炸時,我只從緩衝區中繪製紋理,而不將着色器設置爲批處理,只需用相機組合默認着色器繪製它就會出現問題。我需要在Android清單中啓用某些內容嗎?並且logcat中沒有錯誤,只有警告gl狀態啓用無效枚舉。 –

+0

我在Windows和使用eclipse霓虹燈,我試圖在三星galax s5迷你和一般手機gm 5加在兩個我只看到一個黑色的屏幕 –

+0

一個重要的通知:我開始着色器,我結束它的不同我結束它在批量繪製紋理之前,它在桌面上也會變成黑屏,所以它可能與着色器和批處理的開始和結束順序有關,也許這會有所幫助。你認爲它與這些有什麼關係? –