请参阅最后的编辑以了解进度。
我正在尝试学习 OpenGL ES 2.0(我将在 Android 设备上进行开发)
我对顶点和片段着色器有点困惑。我理解他们的目的,但是如果我从自定义构建的类(比如“点”)构建形状并设置它的大小和颜色或应用纹理并假设两个着色器最初是在对象类的构造函数中声明和定义的,这是否意味着该类的每个实例都有自己的一对着色器?
这是我的第一个问题。我的第二个问题是,如果是这种情况(每个对象的着色器对)............这是要走的路吗?我听说拥有一对着色器并切换它的参数并不是一个好主意,因为性能原因,但如果我有 100 个大小和颜色(或纹理)相同的精灵,那么让它们都有一个具有完全相同参数的不同着色器对?
我希望我问的是正确的问题,我研究 ES 2.0 的时间不长,所以觉得它有点混乱。我目前对OpenGL的了解有限!
编辑
根据要求添加代码。
public class Dot {
int iProgId;
int iPosition;
float size = 10;
FloatBuffer vertexBuf;
float r = 1f;
float g = 1f;
float b = 1f;
float a = 1f;
int iBaseMap;
int texID;
Bitmap imgTexture;
//Constructor
public Dot() {
float[] vertices = {
0,0,0f
};
//Create vertex shader
String strVShader =
"attribute vec4 a_position;\n"+
"void main()\n" +
"{\n" +
"gl_PointSize = " +size+ ";\n" +
"gl_Position = a_position;\n"+
"}";
//Create fragment shader
String strFShader =
"precision mediump float;" +
"void main() " +
"{" +
"gl_FragColor = vec4(0,0,0,1);" +
"}";
iProgId = Utils.LoadProgram(strVShader, strFShader);
iPosition = GLES20.glGetAttribLocation(iProgId, "a_position");
vertexBuf = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuf.put(vertices).position(0);
}
我的 setTexture 方法
public void setTexture(GLSurfaceView view, Bitmap imgTexture){
this.imgTexture=imgTexture;
//Create vertex shader
String strVShader =
"attribute vec4 a_position;\n"+
"void main()\n" +
"{\n" +
"gl_PointSize = " +size+ ";\n" +
"gl_Position = a_position;\n"+
"}";
//Fragment shader
String strFShader =
"precision mediump float;" +
"uniform sampler2D u_baseMap;" +
"void main()" +
"{" +
"vec4 color;" +
"color = texture2D(u_baseMap, gl_PointCoord);" +
"gl_FragColor = color;" +
"}";
iProgId = Utils.LoadProgram(strVShader, strFShader);
iBaseMap = GLES20.glGetUniformLocation(iProgId, "u_baseMap");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glUniform1i(iBaseMap, 0);
texID = Utils.LoadTexture(view, imgTexture); //See code below
}
Utils
我班级的 LoadTexture() 方法:
public static int LoadTexture(GLSurfaceView view, Bitmap imgTex) {
int textures[] = new int[1];
try {
GLES20.glGenTextures(1, textures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, imgTex, 0);
} catch
}
return textures[0];
}
最后是我的绘图方法:
public void drawDot(float x, float y){
float[] vertices = {
x,y,0f
};
vertexBuf = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuf.put(vertices).position(0);
GLES20.glUseProgram(iProgId);
GLES20.glVertexAttribPointer(iPosition, 3, GLES20.GL_FLOAT, false, 0, vertexBuf);
GLES20.glEnableVertexAttribArray(iPosition);
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
}
所以我可以创造这样的东西:
Dot dot1 = new Dot();
dot1.setSize(40);
setTexture(myBitmap); //(created earlier with BitmapFactory)
drawDot(0,0);
谢谢!
编辑1:感谢您到目前为止的回答。在进一步的研究中,似乎其他一些人也遇到了同样的问题。问题似乎是我没有在我的渲染例程中调用 glBindTexture,因此 OpenGL 只是使用它加载的最后一个纹理,我想这是有道理的。
如果我将以下内容放入我的渲染例程中:
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 1);
它将应用第一个位图并显示它
如果我说:
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 2);
它将应用第二个位图并显示它
所以,找个地方!但是我现在的问题是如何让我的渲染方法根据调用它的对象(渲染例程)自动知道要使用哪个位图?
再次感谢