2015-07-30 6 views
5

तो मेरे पास एक आयताकार छवि पर पानी का प्रभाव लागू होता है जो मेरा पानी है जिसमें एक पाप लहर समारोह लागू होता है। यह केवल इस TextureRegion के लिए लागू किया जाता है:LibGdx क्या पानी के प्रभाव के लिए स्प्राइट बैच के एक वर्ग में शेडर लगाने का कोई तरीका है?

Water.java

public void updateshaders(){ 

    float dt = Gdx.graphics.getDeltaTime(); 

    if(waterShader != null){ 

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

     Gdx.gl20.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); 
     Gdx.gl20.glEnable(GL20.GL_BLEND); 
     waterShader.setUniformMatrix("u_projTrans", gs.cam.combined); 

     waterShader.begin(); 
     waterShader.setUniformf("timedelta", -angle); 
     waterShader.end(); 
    } 
} 
@Override 
public void draw(SpriteBatch g) { 
    g.end(); 
    updateshaders(); 
    g.setProjectionMatrix(gs.cam.combined); 
    g.setShader(waterShader); 
    g.begin(); 
    g.draw(gs.gsm.rm.water_top, x, y + height - gs.gsm.rm.water_top.getRegionHeight(), width, gs.gsm.rm.water_top.getRegionHeight()); 
    g.draw(gs.gsm.rm.water, x, y, width, height - gs.gsm.rm.water_top.getRegionHeight()); 
    g.end(); 
    g.setShader(null); 
    g.begin(); 
} 

Imgur

मैं लाल आयत में सब कुछ करने के लिए इस आशय जोड़ना चाहते हैं। मैं SpriteBatch को फ्लश करने और क्षेत्र की एक छवि काटने का विचार कर रहा था, विकृति को लागू करने के बाद इसे मूल पर फिर से चला रहा था, फिर मेरे बाकी रेंडर थ्रेड को समाप्त कर दिया।

अद्यतन: तो मेरा समाधान काम किया ... sorta। यह अविश्वसनीय रूप से धीमा है। यह सही दिखता है लेकिन गेम को नामुमकिन और धीमा बनाता है। (gif में सूचना के लिए एक छोटे से कठिन हो सकता है, लेकिन यह खेल में अच्छा लगता है।) gif

नए कोड:

Water.java

public void draw(SpriteBatch g) { 
    g.end(); 
    updateshaders(); 
    //Distortion 
    coords = gs.cam.project(new Vector3(x,y,0)); 
    if(scr != null){scr.getTexture().dispose();} 
    scr = ScreenUtils.getFrameBufferTexture(
      (int)coords.x,(int)coords.y, 
      (int)(width * scaleX),(int)((height - gs.gsm.rm.water_top.getRegionHeight()/4) * scaleY)); 

    if(scr != null){ 
     g.setShader(waterShader2); 
     g.begin(); 
     g.draw(scr, 
      x,y, 
      width,height- gs.gsm.rm.water_top.getRegionHeight()/4); 
     g.end(); 
    } 
    //SURFACE WAVES 
    g.setShader(waterShader); 
    g.begin(); 
    g.draw(gs.gsm.rm.water_top, x, y + height - gs.gsm.rm.water_top.getRegionHeight(), width, gs.gsm.rm.water_top.getRegionHeight()); 
    g.end(); 
    //BACK TO NORMAL 
    g.setShader(null); 
    g.begin(); 
    g.draw(gs.gsm.rm.water, x, y, width, height - gs.gsm.rm.water_top.getRegionHeight()); 
} 

अद्यतन: मैंने कोशिश की Tenfour04 के समाधान और यह काम किया ... sorta। जबकि विकृति प्रभाव होता है, और गेम पूर्ण एफपीएस पर चलता है, विरूपण पृष्ठभूमि को दिखाता है।

scr = new TextureRegion(((PlayGameState) gs).frameBuffer.getColorBufferTexture(), 
      (int)coords.x, (int)coords.y, 
      (int)(width * scaleX),(int)((height - gs.gsm.rm.water_top.getRegionHeight()/4) * scaleY)); 

werid

उत्तर

3

हर फ्रेम पर, आप को त्यागकर रहे हैं और एक पिक्समैप पुनः बनाने और: इसका कारण यह है शेडर न सिर्फ क्षेत्र की सीमा है कि मैं का उपयोग कर पकड़ लेना भीतर बनावट के लिए लागू किया जा रहा है, है एक बनावट, और उसके बाद स्क्रीन को उस बनावट पर कैप्चर करना। यह दोहराया जाने वाला एक बेहद धीमा ऑपरेशन है।

इसके बजाए, आप सीधे अपने गेम को लगातार ऑफ-स्क्रीन फ्रेम बफर में प्रस्तुत कर सकते हैं।

private FrameBuffer frameBuffer; 
private final Matrix4 idt = new Matrix4(); 

public void render() { 
    if (frameBuffer == null){ 
     //Normally this would go in the resize method, but that causes issues on iOS 
     //because resize isn't always called on the GL thread in iOS. So lazy load here. 
     try { 
      frameBuffer = new FrameBuffer(Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false); 
     } catch (GdxRuntimeException e){ 
      frameBuffer = new FrameBuffer(Format.RGB565, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false); 
      //RGBA8888 not supported on all devices. You might instead want to turn off 
      //the water effect if it's not supported, because 565 is kinda ugly. 
     } 
    } 

    frameBuffer.begin(); 
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 
    //draw everything that is behind the water layer here 
    frameBuffer.end(); 

    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 
    //Draw the frame buffer texture to the screen: 
    spriteBatch.setProjectionMatrix(idt); 
    spriteBatch.begin(); 
    spriteBatch.draw(frameBuffer.getColorBufferTexture(), -1, 1, 2, -2); //IIRC, you need to vertically flip it. If I remembered wrong, then do -1, -1, 2, 2 
    spriteBatch.end(); 

    water.draw(spriteBatch, frameBuffer.getColorBufferTexture()); 

    //draw stuff that is in front of the water here 
} 

और फिर नीचे अपनी जल श्रेणी को संशोधित करें। अगर मुझे सही याद है, तो स्क्रीन बनावट उल्टा है, इसलिए आपको अपने कुछ गणित को फ़्लिप करना पड़ सकता है। मैंने यह जानने के लिए नीचे अपना गणित नहीं देखा है कि क्या आप इसके लिए पहले ही खाते हैं।

public void draw(SpriteBatch g, Texture scr) { 
    updateshaders(); 
    //Distortion 
    coords = gs.cam.project(new Vector3(x,y,0)); 

    if(scr != null){ 
     g.setShader(waterShader2); 
     g.begin(); 
     g.draw(scr, 
      x,y, 
      width,height- gs.gsm.rm.water_top.getRegionHeight()/4); 
     g.end(); 
    } 
    //SURFACE WAVES 
    g.setShader(waterShader); 
    g.begin(); 
    g.draw(gs.gsm.rm.water_top, x, y + height - gs.gsm.rm.water_top.getRegionHeight(), width, gs.gsm.rm.water_top.getRegionHeight()); 
    g.end(); 
    //BACK TO NORMAL 
    g.setShader(null); 
    g.begin(); 
    g.draw(gs.gsm.rm.water, x, y, width, height - gs.gsm.rm.water_top.getRegionHeight()); 
} 

एक बात यह है कि इस प्रक्रिया में unoptimized है कि आप कम से कम दो बार पानी परत के पीछे सभी पिक्सल ड्राइंग में पहुंचते हैं। इसे फ्रेम बफर पर खींचने के बाद, और फिर दूसरी बार जब फ्रेम बफर स्क्रीन पर खींचा जाता है। इसे बाद में अनुकूलित किया जा सकता है (यदि आप दर से भरने वाले हैं) पानी के नीचे आने वाले दृश्य के क्षेत्र में पीछे-पानी की चीज़ें खींचकर, और फिर फ्रेम बफर बनावट को चित्रित करने के चरण को चित्रित करने के चरण को बदलकर सामान्य रूप से पृष्ठभूमि सामान। यह केवल तभी अच्छा लगेगा जब आपने सफलतापूर्वक एक RGBA8888 फ्रेम बफर बनाया, जो सभी Androids पर समर्थित नहीं है।

+0

केवल एक चीज यह है कि मुझे पानी निकालने से पहले प्रक्षेपण मैट्रिक्स को कैमरे में वापस बदलना पड़ा, मुझे अपने लक्ष्य को प्राप्त करने के लिए फ्रेम बफर बनावट का एक क्षेत्र लेना पड़ा –

+0

आपका समाधान प्रदर्शन भाग के लिए बहुत अच्छा था , लेकिन मैं कैसे सुनिश्चित कर सकता हूं कि शेडर लाल बॉक्स में केवल 'TextureRegion' पर लागू होता है? –

+0

पूरे बनावट को स्क्रीन पर खींचा जाता है और फिर आपकी जल श्रेणी उन क्षेत्रों को दोबारा हटा देती है जिन्हें प्रभाव की आवश्यकता होती है। मुझे लगता है कि आप पहले से ही उस भाग के स्क्रीन आकार के बनावट के साथ काम कर रहे थे जिसे आप ScreenUtils से प्राप्त कर रहे थे। सुनिश्चित नहीं है कि आपकी जल वर्ग सभी चरों के कारण कैसे काम करती है। – Tenfour04

संबंधित मुद्दे