有许多3D对象(1000+)由三角形构成,我需要使用Android NDK和OpenGL ES 2.0绘制它。每个三角形都有顶点坐标,颜色,纹理和纹理坐标。我有两个问题:
texture2D(u_Texture,v_TexCoord)
会为每个三角形返回vec4(0.0, 0.0, 0.0, 1.0)
。 这是我的代码:
加载bmp文件并创建纹理:
void CreateTexture(unsigned &texture, const char * fileName)
{
char *pFolderName = NULL;
int width = 0;
int height = 0;
unsigned char *data = NULL;
char *pExtension = NULL;
glGenTextures(1, &texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//check extension
pExtension = new char[5];
pExtension[4] = '\0';
int j = strlen(fileName) - 1;
do {
j--;
} while (j > 0 && fileName[j] != '.');
for (int k = 0; k < 5; k++) {
j++;
pExtension[k] = fileName[j];
}
if ( 0 == strcmp(pExtension, BMP_EXT)
|| 0 == strcmp(pExtension, BMP_EXT1))
{
FILE *f = fopen(fileName, "r");
if(f == NULL) LOGE("Couldn't open texture file %s", fileName);
fseek(f, 18, SEEK_SET);
fread(&width, 4, 1, f);
fread(&height, 4, 1, f);
data = new unsigned char[width*height*3];
fseek(f, 54, SEEK_SET);
fread(data, width*height*3, 1, f);
char tmp;
//convert BGR->RGB
for(int i=0;i<width*height*3-2;i+=3)
{
tmp = data[i];
data[i] = data[i+2];
data[i+2] = tmp;
}
unsigned char *reverseData = new unsigned char[width*height*3];
for(int j1 = 0; j1 < height; ++j1)
for(int i1 = 0; i1 < width*3; ++i1)
reverseData[j1*(width*3)+i1] = data[(height-j1-1)*width*3+i1];
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, reverseData);
delete []data;
delete []pExtension;
delete []reverseData;
}
}
绘制功能:
void Display(VisObject *obj)
{
GLint pos = shader.GetAttribLocation("a_Position");
GLint texpos = shader.GetAttribLocation("a_TexCoord");
GLint a_color = shader.GetAttribLocation("a_Color");
GLint texture = shader.GetUniformLocation("u_Texture");
GLint textureFlag = shader.GetUniformLocation("u_TextureFlag");
for(int i=0; i < obj->CountTr ; i++)
{
if (!obj->m_visible) return;
float color[12];
if(obj->triangles[i].color[0] < 0)
{
color[0] = 1.0f; color[1] = 1.0f; color[2] = 1.0f;color[3] = obj->m_vis_koef;
color[4] = 1.0f; color[5] = 1.0f; color[6] = 1.0f;color[7] = obj->m_vis_koef;
color[8] = 1.0f; color[9] = 1.0f; color[10] = 1.0f;color[11] = obj->m_vis_koef;
}
else
{
color[0] = obj->triangles[i].color[0]; color[1] = obj->triangles[i].color[1];
color[2] = obj->triangles[i].color[2]; color[3] = obj->triangles[i].color[3];
color[4] = obj->triangles[i].color[0]; color[5] = obj->triangles[i].color[1];
color[6] = obj->triangles[i].color[2]; color[7] = obj->triangles[i].color[3];
color[8] = obj->triangles[i].color[0]; color[9] = obj->triangles[i].color[1];
color[10] = obj->triangles[i].color[2]; color[11] = obj->triangles[i].color[3];
}
glActiveTexture(GL_TEXTURE0);
if(obj->m_num_texture > 0)
glBindTexture(GL_TEXTURE_2D,g_Texture[obj->m_num_texture] );
else
glBindTexture(GL_TEXTURE_2D, obj->triangles[i].numtex );
shader.Uniform1i(texture, 0);
float vertices[] = {
obj->triangles[i].verts[0].x, obj->triangles[i].verts[0].y, obj->triangles[i].verts[0].z,
obj->triangles[i].verts[1].x, obj->triangles[i].verts[1].y, obj->triangles[i].verts[1].z,
obj->triangles[i].verts[2].x, obj->triangles[i].verts[2].y, obj->triangles[i].verts[2].z
};
float texcoords[] = {
obj->triangles[i].tex[0].U, obj->triangles[i].tex[0].V,
obj->triangles[i].tex[1].U, obj->triangles[i].tex[1].V,
obj->triangles[i].tex[2].U, obj->triangles[i].tex[2].V
};
glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 0, vertices);
checkGlError("glVertexAttribPointer");
glEnableVertexAttribArray(pos);
checkGlError("glEnableVertexAttribArray");
glVertexAttribPointer(texpos, 2, GL_FLOAT, GL_FALSE, 0, texcoords);
checkGlError("glVertexAttribPointer");
glEnableVertexAttribArray(texpos);
checkGlError("glEnableVertexAttribArray");
shader.Uniform1f(textureFlag, 1.0f);
glVertexAttribPointer(a_color, 4, GL_FLOAT, GL_FALSE, 0, color);
checkGlError("glVertexAttribPointer");
glEnableVertexAttribArray(a_color);
checkGlError("glEnableVertexAttribArray");
glDrawArrays(GL_TRIANGLES, 0, 3);
checkGlError("glDrawArrays");
}
顶点着色器:
attribute vec3 a_Position;
attribute vec2 a_TexCoord;
attribute vec4 a_Color;
varying vec2 v_TexCoord;
varying vec4 v_Color;
uniform mat4 u_projectionMatrix;
uniform mat4 u_modelviewMatrix;
void main(void)
{
mat4 mvpMatrix = u_projectionMatrix*u_modelviewMatrix;
gl_Position = mvpMatrix*vec4(a_Position, 1.0);
v_TexCoord = a_TexCoord;
v_Color = a_Color;
}
片段着色器:
precision mediump float;
varying vec2 v_TexCoord;
varying vec4 v_Color;
uniform sampler2D u_Texture;
uniform float u_TextureFlag;
void main(void)
{
gl_FragColor = u_TextureFlag*texture2D(u_Texture,v_TexCoord)*v_Color + (1.0 - u_TextureFlag)*v_Color;
}
我试图将顶点数组和其他数据声明为float vertices[3*3*obj->CountTr];
,并在循环中设置数组的值。循环后我绘制三角形:
glDrawArrays(GL_TRIANGLES, 0, 3*obj->CountTr);
它工作得更快,但我不明白如何在必要时为三角形设置不同的纹理。