概述
在我的应用程序(这是一个游戏)中,我使用项目的批处理来减少绘制调用的次数。因此,我将创建一个名为平台的Java对象,该对象用于所有游戏中的平台。所有的敌人都被收集在一起,就像所有收藏物品一样....
这非常有效。目前,我可以相互独立地批量和定位各个项目,但是,我已经到了我真正需要改变个人项目的不透明度的地步。目前,我只能更改整批产品的不透明度。
配料
我正在上传批次中要显示的所有项目的顶点(如果我不希望它们被绘制,我可以关闭单个项目),然后一旦完成,我只需绘制它们在一个电话中。
以下是我正在做的事情的想法 - 我意识到这可能无法编译,只是为了提出问题的目的。
public void draw(){
//Upload vertices
for (count = 0;count<numOfSpritesInBatch;count+=1){
vertices[x] = xLeft;
vertices[(x+1)] = yPTop;
vertices[(x+2)] = 0;
vertices[(x+3)] = textureLeft;
vertices[(x+4)] = 0;
vertices[(x+5)] = xPRight;
vertices[(x+6)] = yTop;
vertices[(x+7)] = 0;
vertices[(x+8)] = textureRight;
vertices[x+9] = 0;
vertices[x+10] = xLeft;
vertices[x+11] = yBottom;
vertices[x+12] = 0;
vertices[x+13] = textureLeft;
vertices[x+14] = 1;
vertices[x+15] = xRight;
vertices[x+16] = yTop;
vertices[x+17] = 0;
vertices[x+18] = textureRight;
vertices[x+19] = 0;
vertices[x+20] = xLeft;
vertices[x+21] = yBottom;
vertices[x+22] = 0;
vertices[x+23] = textureLeft;
vertices[x+24] = 1;
vertices[x+25] = xRight;
vertices[x+26] = yBottom;
vertices[x+27] = 0;
vertices[x+28] = textureRight;
vertices[x+29] = 1;
x+=30;
}
vertexBuf.rewind();
vertexBuf.put(vertices).position(0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texID);
GLES20.glUseProgram(iProgId);
Matrix.multiplyMM(mvpMatrix2, 0, mvpMatrix, 0, mRotationMatrix, 0);
mMVPMatrixHandle = GLES20.glGetUniformLocation(iProgId, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix2, 0);
vertexBuf.position(0);
GLES20.glVertexAttribPointer(iPosition, 3, GLES20.GL_FLOAT, false, 5 * 4, vertexBuf);
GLES20.glEnableVertexAttribArray(iPosition);
vertexBuf.position(3);
GLES20.glVertexAttribPointer(iTexCoords, 2, GLES20.GL_FLOAT, false, 5 * 4, vertexBuf);
GLES20.glEnableVertexAttribArray(iTexCoords);
//Enable Alpha blending and set blending function
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
//Draw it
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6 * numOfSpritesInBatch);
//Disable Alpha blending
GLES20.glDisable(GLES20.GL_BLEND);
}
着色
String strVShader =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 a_position;\n"+
"attribute vec2 a_texCoords;" +
"varying vec2 v_texCoords;" +
"void main()\n" +
"{\n" +
"gl_Position = uMVPMatrix * a_position;\n"+
"v_texCoords = a_texCoords;" +
"}";
String strFShader =
"precision mediump float;" +
"uniform float opValue;"+
"varying vec2 v_texCoords;" +
"uniform sampler2D u_baseMap;" +
"void main()" +
"{" +
"gl_FragColor = texture2D(u_baseMap, v_texCoords);" +
"gl_FragColor *= opValue;"+
"}";
目前,我的Sprite类中有一个方法允许我更改opacty。例如,像这样:
spriteBatch.setOpacity(0.5f); //Half opacity
这有效,但改变了整个批次 - 而不是我所追求的。
应用
我需要这个,因为我想在玩家摧毁敌人时绘制小指标 - 显示从该动作获得的分数。 (许多游戏中发生的事情类型) - 我希望这些小的“得分指标”一旦出现就会淡出。当然,所有指标都是一批创建的,因此可以通过一次平局调用绘制所有指标。
唯一的其他选择是:
我需要在粒子系统等中看看它的未来用途......所以我真的想弄清楚如何做到这一点(能够分别调整每个项目的不透明度)。如果我需要在着色器中执行此操作,如果您能够展示其工作原理,我将不胜感激。或者,是否可以在着色器外执行此操作?
当然,这可以通过某种方式完成吗?欢迎所有建议......
答案 0 :(得分:2)
实现此目的的最直接方法是使用顶点属性作为不透明度值,而不是均匀值。这将允许您设置每个顶点的不透明度,而不会增加绘制调用的数量。
要实现此功能,您可以按照已用于纹理坐标的模式。它们作为属性传递到顶点着色器中,然后作为变量变量传递给片段着色器。
所以在顶点着色器中,你添加:
...
attribute float a_opValue;
varying float v_opValue;
...
v_opValue = a_opValue;
...
在片段着色器中,删除opValue
的统一声明,并将其替换为:
varying float v_opValue;
...
gl_FragColor *= v_opValue;
...
在Java代码中,您使用不透明度的附加值扩展顶点数据,每个顶点使用6个值(3个位置,2个纹理坐标,1个不透明度),并相应地更新状态设置:
vertexBuf.position(0);
GLES20.glVertexAttribPointer(iPosition, 3, GLES20.GL_FLOAT, false, 6 * 4, vertexBuf);
GLES20.glEnableVertexAttribArray(iPosition);
vertexBuf.position(3);
GLES20.glVertexAttribPointer(iTexCoords, 2, GLES20.GL_FLOAT, false, 6 * 4, vertexBuf);
GLES20.glEnableVertexAttribArray(iTexCoords);
vertexBuf.position(5);
GLES20.glVertexAttribPointer(iOpValue, 1, GLES20.GL_FLOAT, false, 6 * 4, vertexBuf);
GLES20.glEnableVertexAttribArray(iOpValue);