Libgdx中如何繪製帶透明度的3D模型相關實現程式碼 2種方案
阿新 • • 發佈:2019-01-22
問題?如何解決在繪製帶透明度的3D模型時候,深度和透明度混合之間的矛盾問題。
第一種方法:
採取透明度測試,在glsl裡面,先開啟透明度測試只通過不透明的部分,然後再繪製繪製透明的部分即可。
public void draw (Batch batch, float parentAlpha) { batch.flush(); batch.end(); Gdx.gl.glDisable(GL20.GL_BLEND); Gdx.gl.glDepthMask(true); Gdx.gl.glEnable(GL20.GL_DEPTH_TEST); matrix4.idt().set(getStage().getCamera().combined); if (isEnableRatate) { rotateAxisAngle(matrix4, xToAngle(deltaX), xToAngle(deltaY), 0); } else { deltaX = 0; deltaY = 0; } shader.begin(); shader.setUniformMatrix("u_projTrans", matrix4); shader.setUniformi("alphatest", 1);//glsl實現開啟透明度測試 this.texture.bind(); glCircle.mesh.render(this.shader, GL20.GL_TRIANGLE_STRIP,0,glCircle.getIndexCount()); Gdx.gl.glEnable(GL20.GL_BLEND); Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); Gdx.gl.glDepthMask(false); shader.setUniformMatrix("u_projTrans", matrix4); shader.setUniformi("alphatest", -1); this.texture.bind(); glCircle.mesh.render(this.shader, GL20.GL_TRIANGLE_STRIP,0,glCircle.getIndexCount()); batch.begin(); }
第二種方式(我採用的第二種實現):
採取繪製2次做法,需要繪製2次因為如果圖片不帶透明度就比較吃虧了。
第一次繪製:開啟前面裁剪模式,繪製後面。
第二次繪製:開啟背面裁剪模式,繪製前面即可。
程式碼如下:
Gdx.gl.glEnable(GL20.GL_DEPTH_TEST); shader.begin(); Gdx.gl.glEnable(GL20.GL_BLEND); Gdx.gl.glBlendFunc(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA); Gdx.gl.glDepthMask(false);//禁用深度緩衝 Gdx.gl.glEnable(GL20.GL_CULL_FACE); Gdx.gl.glCullFace(GL20.GL_FRONT); shader.setUniformMatrix("u_projTrans", matrix4); shader.setUniformi("alphatest", 0); shader.setUniformf("t_colorAlpha", parentAlpha);//實現透明度漸變 shader.setUniformi("preAlpha", -1);//不需要預乘alpha if(texturebg==null) { shader.setUniformi("hasbg", -1); textureRegion.getTexture().bind(); }else{ shader.setUniformi("hasbg", 1); shader.setUniformf("bgAlpha", radio); //注意該紋理的繫結順序,有點奇葩,必須前後對調,感覺很不爽 //繫結圖示層 Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE0); textureRegion.getTexture().bind(1); shader.setUniformi("u_texture", 1); //passing first texture!!! //繫結背景 Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE1); texturebg.getRegion().getTexture().bind(0); shader.setUniformi("u_texture2", 0); //passing first texture!!! } this.mesh.render(this.shader, GL20.GL_TRIANGLE_STRIP, 0, spriteVertices.length / 6); Gdx.gl.glCullFace(GL20.GL_BACK); shader.setUniformMatrix("u_projTrans", matrix4); shader.setUniformf("t_colorAlpha", parentAlpha);//實現透明度漸變 shader.setUniformi("preAlpha", -1);//不需要預乘alpha if(texturebg==null) { shader.setUniformi("hasbg", -1); textureRegion.getTexture().bind(); }else{ shader.setUniformi("hasbg", 1); shader.setUniformf("bgAlpha", radio); //注意該紋理的繫結順序,有點奇葩,必須前後對調,感覺很不爽 //繫結圖示層 Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE0); textureRegion.getTexture().bind(1); shader.setUniformi("u_texture", 1); //passing first texture!!! //繫結背景 Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE1); texturebg.getRegion().getTexture().bind(0); shader.setUniformi("u_texture2", 0); //passing first texture!!! } this.mesh.render(this.shader, GL20.GL_TRIANGLE_STRIP, 0, spriteVertices.length / 6); shader.end(); Gdx.gl.glDisable(GL20.GL_CULL_FACE); Gdx.gl.glEnable(GL20.GL_BLEND); Gdx.gl20.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); Gdx.gl.glDisable(GL20.GL_DEPTH_TEST); Gdx.gl.glDepthMask(false);