我想使用胶水(函数如下)来绘制球体,它只支持单个纹理。 我必须在iphone4上使用大纹理(8096X4096)。我将大纹理分成几个小纹理(512X512)。我如何使用多纹理结合这些小的一个大的传递给gluSphere使用????
提前谢谢!
//glues draw sphere function
GLAPI void APIENTRY gluSphere(GLUquadric* qobj, GLfloat radius, GLint slices, GLint stacks)
{
GLint i, j;
GLfloat sinCache1a[CACHE_SIZE];
GLfloat cosCache1a[CACHE_SIZE];
GLfloat sinCache2a[CACHE_SIZE];
GLfloat cosCache2a[CACHE_SIZE];
GLfloat sinCache3a[CACHE_SIZE];
GLfloat cosCache3a[CACHE_SIZE];
GLfloat sinCache1b[CACHE_SIZE];
GLfloat cosCache1b[CACHE_SIZE];
GLfloat sinCache2b[CACHE_SIZE];
GLfloat cosCache2b[CACHE_SIZE];
GLfloat sinCache3b[CACHE_SIZE];
GLfloat cosCache3b[CACHE_SIZE];
GLfloat angle;
GLfloat zLow, zHigh;
GLfloat sintemp1 = 0.0, sintemp2 = 0.0, sintemp3 = 0.0, sintemp4 = 0.0;
GLfloat costemp1 = 0.0, costemp2 = 0.0, costemp3 = 0.0, costemp4 = 0.0;
GLfloat vertices[(CACHE_SIZE+1)*2][3];
GLfloat texcoords[(CACHE_SIZE+1)*2][2];
GLfloat normals[(CACHE_SIZE+1)*2][3];
GLboolean needCache2, needCache3;
GLint start, finish;
GLboolean texcoord_enabled;
GLboolean normal_enabled;
GLboolean vertex_enabled;
GLboolean color_enabled;
if (slices>=CACHE_SIZE)
{
slices=CACHE_SIZE-1;
}
if (stacks>=CACHE_SIZE)
{
stacks=CACHE_SIZE-1;
}
if (slices<2 || stacks<1 || radius<0.0)
{
gluQuadricError(qobj, GLU_INVALID_VALUE);
return;
}
/* Cache is the vertex locations cache */
/* Cache2 is the various normals at the vertices themselves */
/* Cache3 is the various normals for the faces */
needCache2=needCache3=GL_FALSE;
if (qobj->normals==GLU_SMOOTH)
{
needCache2=GL_TRUE;
}
if (qobj->normals==GLU_FLAT)
{
if (qobj->drawStyle!=GLU_POINT)
{
needCache3=GL_TRUE;
}
if (qobj->drawStyle==GLU_LINE)
{
needCache2=GL_TRUE;
}
}
for (i=0; i<slices; i++)
{
angle=2.0f*PI*i/slices;
sinCache1a[i]=(GLfloat)sin(angle);
cosCache1a[i]=(GLfloat)cos(angle);
if (needCache2)
{
sinCache2a[i] = sinCache1a[i];
cosCache2a[i] = cosCache1a[i];
}
}
for (j=0; j<=stacks; j++)
{
angle=PI*j/stacks;
if (needCache2)
{
if (qobj->orientation==GLU_OUTSIDE)
{
sinCache2b[j]=(GLfloat)sin(angle);
cosCache2b[j]=(GLfloat)cos(angle);
}
else
{
sinCache2b[j]=(GLfloat)-sin(angle);
cosCache2b[j]=(GLfloat)-cos(angle);
}
}
sinCache1b[j]=(GLfloat)(radius*sin(angle));
cosCache1b[j]=(GLfloat)(radius*cos(angle));
}
/* Make sure it comes to a point */
sinCache1b[0]=0;
sinCache1b[stacks]=0;
if (needCache3)
{
for (i=0; i<slices; i++)
{
angle=2.0f*PI*(i-0.5f)/slices;
sinCache3a[i]=(GLfloat)sin(angle);
cosCache3a[i]=(GLfloat)cos(angle);
}
for (j=0; j<=stacks; j++)
{
angle=PI*(j-0.5f)/stacks;
if (qobj->orientation==GLU_OUTSIDE)
{
sinCache3b[j]=(GLfloat)sin(angle);
cosCache3b[j]=(GLfloat)cos(angle);
}
else
{
sinCache3b[j]=(GLfloat)-sin(angle);
cosCache3b[j]=(GLfloat)-cos(angle);
}
}
}
sinCache1a[slices]=sinCache1a[0];
cosCache1a[slices]=cosCache1a[0];
if (needCache2)
{
sinCache2a[slices]=sinCache2a[0];
cosCache2a[slices]=cosCache2a[0];
}
if (needCache3)
{
sinCache3a[slices]=sinCache3a[0];
cosCache3a[slices]=cosCache3a[0];
}
/* Store status of enabled arrays */
texcoord_enabled=GL_FALSE; //glIsEnabled(GL_TEXTURE_COORD_ARRAY);
normal_enabled=GL_FALSE; //glIsEnabled(GL_NORMAL_ARRAY);
vertex_enabled=GL_FALSE; //glIsEnabled(GL_VERTEX_ARRAY);
color_enabled=GL_FALSE; //glIsEnabled(GL_COLOR_ARRAY);
/* Enable arrays */
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
if (qobj->textureCoords)
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
}
else
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (qobj->normals!=GLU_NONE)
{
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, normals);
}
else
{
glDisableClientState(GL_NORMAL_ARRAY);
}
glDisableClientState(GL_COLOR_ARRAY);
switch (qobj->drawStyle)
{
case GLU_FILL:
if (!(qobj->textureCoords))
{
start=1;
finish=stacks-1;
/* Low end first (j == 0 iteration) */
sintemp2=sinCache1b[1];
zHigh=cosCache1b[1];
switch(qobj->normals)
{
case GLU_FLAT:
sintemp3=sinCache3b[1];
costemp3=cosCache3b[1];
normals[0][0]=sinCache3a[0]*sinCache3b[0];
normals[0][1]=cosCache3a[0]*sinCache3b[0];
normals[0][2]=cosCache3b[0];
break;
case GLU_SMOOTH:
sintemp3=sinCache2b[1];
costemp3=cosCache2b[1];
normals[0][0]=sinCache2a[0]*sinCache2b[0];
normals[0][1]=cosCache2a[0]*sinCache2b[0];
normals[0][2]=cosCache2b[0];
break;
default:
break;
}
vertices[0][0]=0.0f;
vertices[0][1]=0.0f;
vertices[0][2]=radius;
if (qobj->orientation==GLU_OUTSIDE)
{
for (i=slices; i>=0; i--)
{
switch(qobj->normals)
{
case GLU_SMOOTH:
normals[slices-i+1][0]=sinCache2a[i]*sintemp3;
normals[slices-i+1][1]=cosCache2a[i]*sintemp3;
normals[slices-i+1][2]=costemp3;
break;
case GLU_FLAT:
if (i!=slices)
{
normals[slices-i+1][0]=sinCache3a[i+1]*sintemp3;
normals[slices-i+1][1]=cosCache3a[i+1]*sintemp3;
normals[slices-i+1][2]=costemp3;
}
else
{
/* We must add any normal here */
normals[slices-i+1][0]=sinCache3a[i]*sintemp3;
normals[slices-i+1][1]=cosCache3a[i]*sintemp3;
normals[slices-i+1][2]=costemp3;
}
break;
case GLU_NONE:
default:
break;
}
vertices[slices-i+1][0]=sintemp2*sinCache1a[i];
vertices[slices-i+1][1]=sintemp2*cosCache1a[i];
vertices[slices-i+1][2]=zHigh;
}
}
else
{
for (i=0; i<=slices; i++)
{
switch(qobj->normals)
{
case GLU_SMOOTH:
normals[i+1][0]=sinCache2a[i]*sintemp3;
normals[i+1][1]=cosCache2a[i]*sintemp3;
normals[i+1][2]=costemp3;
break;
case GLU_FLAT:
normals[i+1][0]=sinCache3a[i]*sintemp3;
normals[i+1][1]=cosCache3a[i]*sintemp3;
normals[i+1][2]=costemp3;
break;
case GLU_NONE:
default:
break;
}
vertices[i+1][0]=sintemp2*sinCache1a[i];
vertices[i+1][1]=sintemp2*cosCache1a[i];
vertices[i+1][2]=zHigh;
}
}
glDrawArrays(GL_TRIANGLE_FAN, 0, (slices+2));
/* High end next (j==stacks-1 iteration) */
sintemp2=sinCache1b[stacks-1];
zHigh=cosCache1b[stacks-1];
switch(qobj->normals)
{
case GLU_FLAT:
sintemp3=sinCache3b[stacks];
costemp3=cosCache3b[stacks];
normals[0][0]=sinCache3a[stacks]*sinCache3b[stacks];
normals[0][1]=cosCache3a[stacks]*sinCache3b[stacks];
normals[0][2]=cosCache3b[stacks];
break;
case GLU_SMOOTH:
sintemp3=sinCache2b[stacks-1];
costemp3=cosCache2b[stacks-1];
normals[0][0]=sinCache2a[stacks]*sinCache2b[stacks];
normals[0][1]=cosCache2a[stacks]*sinCache2b[stacks];
normals[0][2]=cosCache2b[stacks];
break;
default:
break;
}
vertices[0][0]=0.0f;
vertices[0][1]=0.0f;
vertices[0][2]=-radius;
if (qobj->orientation==GLU_OUTSIDE)
{
for (i=0; i<=slices; i++)
{
switch(qobj->normals)
{
case GLU_SMOOTH:
normals[i+1][0]=sinCache2a[i]*sintemp3;
normals[i+1][1]=cosCache2a[i]*sintemp3;
normals[i+1][2]=costemp3;
break;
case GLU_FLAT:
normals[i+1][0]=sinCache3a[i]*sintemp3;
normals[i+1][1]=cosCache3a[i]*sintemp3;
normals[i+1][2]=costemp3;
break;
case GLU_NONE:
default:
break;
}
vertices[i+1][0]=sintemp2*sinCache1a[i];
vertices[i+1][1]=sintemp2*cosCache1a[i];
vertices[i+1][2]=zHigh;
}
}
else
{
for (i=slices; i>=0; i--)
{
switch(qobj->normals)
{
case GLU_SMOOTH:
normals[slices-i+1][0]=sinCache2a[i]*sintemp3;
normals[slices-i+1][1]=cosCache2a[i]*sintemp3;
normals[slices-i+1][2]=costemp3;
break;
case GLU_FLAT:
if (i!=slices)
{
normals[slices-i+1][0]=sinCache3a[i+1]*sintemp3;
normals[slices-i+1][1]=cosCache3a[i+1]*sintemp3;
normals[slices-i+1][2]=costemp3;
}
else
{
normals[slices-i+1][0]=sinCache3a[i]*sintemp3;
normals[slices-i+1][1]=cosCache3a[i]*sintemp3;
normals[slices-i+1][2]=costemp3;
}
break;
case GLU_NONE:
default:
break;
}
vertices[slices-i+1][0]=sintemp2*sinCache1a[i];
vertices[slices-i+1][1]=sintemp2*cosCache1a[i];
vertices[slices-i+1][2]=zHigh;
}
}
glDrawArrays(GL_TRIANGLE_FAN, 0, (slices+2));
}
else
{
start=0;
finish=stacks;
}
for (j=start; j<finish; j++)
{
zLow=cosCache1b[j];
zHigh=cosCache1b[j+1];
sintemp1=sinCache1b[j];
sintemp2=sinCache1b[j+1];
switch(qobj->normals)
{
case GLU_FLAT:
sintemp4=sinCache3b[j+1];
costemp4=cosCache3b[j+1];
break;
case GLU_SMOOTH:
if (qobj->orientation==GLU_OUTSIDE)
{
sintemp3=sinCache2b[j+1];
costemp3=cosCache2b[j+1];
sintemp4=sinCache2b[j];
costemp4=cosCache2b[j];
}
else
{
sintemp3=sinCache2b[j];
costemp3=cosCache2b[j];
sintemp4=sinCache2b[j+1];
costemp4=cosCache2b[j+1];
}
break;
default:
break;
}
for (i=0; i<=slices; i++)
{
switch(qobj->normals)
{
case GLU_SMOOTH:
normals[i*2][0]=sinCache2a[i]*sintemp3;
normals[i*2][1]=cosCache2a[i]*sintemp3;
normals[i*2][2]=costemp3;
break;
case GLU_FLAT:
normals[i*2][0]=sinCache3a[i]*sintemp4;
normals[i*2][1]=cosCache3a[i]*sintemp4;
normals[i*2][2]=costemp4;
break;
case GLU_NONE:
default:
break;
}
if (qobj->orientation==GLU_OUTSIDE)
{
if (qobj->textureCoords)
{
texcoords[i*2][0]=1-(GLfloat)i/slices;
texcoords[i*2][1]=1-(GLfloat)(j+1)/stacks;
}
vertices[i*2][0]=sintemp2*sinCache1a[i];
vertices[i*2][1]=sintemp2*cosCache1a[i];
vertices[i*2][2]=zHigh;
}
else
{
if (qobj->textureCoords)
{
texcoords[i*2][0]=1-(GLfloat)i/slices;
texcoords[i*2][1]=1-(GLfloat)j/stacks;
}
vertices[i*2][0]=sintemp1*sinCache1a[i];
vertices[i*2][1]=sintemp1*cosCache1a[i];
vertices[i*2][2]=zLow;
}
switch(qobj->normals)
{
case GLU_SMOOTH:
normals[i*2+1][0]=sinCache2a[i]*sintemp4;
normals[i*2+1][1]=cosCache2a[i]*sintemp4;
normals[i*2+1][2]=costemp4;
break;
case GLU_FLAT:
normals[i*2+1][0]=sinCache3a[i]*sintemp4;
normals[i*2+1][1]=cosCache3a[i]*sintemp4;
normals[i*2+1][2]=costemp4;
break;
case GLU_NONE:
default:
break;
}
if (qobj->orientation==GLU_OUTSIDE)
{
if (qobj->textureCoords)
{
texcoords[i*2+1][0]=1-(GLfloat)i/slices;
texcoords[i*2+1][1]=1-(GLfloat)j/stacks;
}
vertices[i*2+1][0]=sintemp1*sinCache1a[i];
vertices[i*2+1][1]=sintemp1*cosCache1a[i];
vertices[i*2+1][2]=zLow;
}
else
{
if (qobj->textureCoords)
{
texcoords[i*2+1][0]=1-(GLfloat)i/slices;
texcoords[i*2+1][1]=1-(GLfloat)(j+1)/stacks;
}
vertices[i*2+1][0]=sintemp2*sinCache1a[i];
vertices[i*2+1][1]=sintemp2*cosCache1a[i];
vertices[i*2+1][2]=zHigh;
}
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, (slices+1)*2);
}
break;
case GLU_POINT:
for (j=0; j<=stacks; j++)
{
sintemp1=sinCache1b[j];
costemp1=cosCache1b[j];
switch(qobj->normals)
{
case GLU_FLAT:
case GLU_SMOOTH:
sintemp2=sinCache2b[j];
costemp2=cosCache2b[j];
break;
default:
break;
}
for (i=0; i<slices; i++)
{
switch(qobj->normals)
{
case GLU_FLAT:
case GLU_SMOOTH:
normals[i][0]=sinCache2a[i]*sintemp2;
normals[i][1]=cosCache2a[i]*sintemp2;
normals[i][2]=costemp2;
break;
case GLU_NONE:
default:
break;
}
zLow=j*radius/stacks;
if (qobj->textureCoords)
{
texcoords[i][0]=1-(GLfloat)i/slices;
texcoords[i][1]=1-(GLfloat)j/stacks;
}
vertices[i][0]=sintemp1*sinCache1a[i];
vertices[i][1]=sintemp1*cosCache1a[i];
vertices[i][2]=costemp1;
}
glDrawArrays(GL_POINTS, 0, slices);
}
break;
case GLU_LINE:
case GLU_SILHOUETTE:
for (j=1; j<stacks; j++)
{
sintemp1=sinCache1b[j];
costemp1=cosCache1b[j];
switch(qobj->normals)
{
case GLU_FLAT:
case GLU_SMOOTH:
sintemp2=sinCache2b[j];
costemp2=cosCache2b[j];
break;
default:
break;
}
for (i=0; i<=slices; i++)
{
switch(qobj->normals)
{
case GLU_FLAT:
normals[i][0]=sinCache3a[i]*sintemp2;
normals[i][1]=cosCache3a[i]*sintemp2;
normals[i][2]=costemp2;
break;
case GLU_SMOOTH:
normals[i][0]=sinCache2a[i]*sintemp2;
normals[i][1]=cosCache2a[i]*sintemp2;
normals[i][2]=costemp2;
break;
case GLU_NONE:
default:
break;
}
if (qobj->textureCoords)
{
texcoords[i][0]=1-(GLfloat)i/slices;
texcoords[i][1]=1-(GLfloat)j/stacks;
}
vertices[i][0]=sintemp1*sinCache1a[i];
vertices[i][1]=sintemp1*cosCache1a[i];
vertices[i][2]=costemp1;
}
glDrawArrays(GL_LINE_STRIP, 0, slices+1);
}
for (i=0; i<slices; i++)
{
sintemp1=sinCache1a[i];
costemp1=cosCache1a[i];
switch(qobj->normals)
{
case GLU_FLAT:
case GLU_SMOOTH:
sintemp2=sinCache2a[i];
costemp2=cosCache2a[i];
break;
default:
break;
}
for (j=0; j<=stacks; j++)
{
switch(qobj->normals)
{
case GLU_FLAT:
normals[j][0]=sintemp2*sinCache3b[j];
normals[j][1]=costemp2*sinCache3b[j];
normals[j][2]=cosCache3b[j];
break;
case GLU_SMOOTH:
normals[j][0]=sintemp2*sinCache2b[j];
normals[j][1]=costemp2*sinCache2b[j];
normals[j][2]=cosCache2b[j];
break;
case GLU_NONE:
default:
break;
}
if (qobj->textureCoords)
{
texcoords[j][0]=1-(GLfloat)i/slices;
texcoords[j][1]=1-(GLfloat)j/stacks;
}
vertices[j][0]=sintemp1*sinCache1b[j];
vertices[j][1]=costemp1*sinCache1b[j];
vertices[j][2]=cosCache1b[j];
}
glDrawArrays(GL_LINE_STRIP, 0, stacks+1);
}
break;
default:
break;
}
/* Disable or re-enable arrays */
if (vertex_enabled)
{
/* Re-enable vertex array */
glEnableClientState(GL_VERTEX_ARRAY);
}
else
{
glDisableClientState(GL_VERTEX_ARRAY);
}
if (texcoord_enabled)
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
else
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (normal_enabled)
{
glEnableClientState(GL_NORMAL_ARRAY);
}
else
{
glDisableClientState(GL_NORMAL_ARRAY);
}
if (color_enabled)
{
glEnableClientState(GL_COLOR_ARRAY);
}
else
{
glDisableClientState(GL_COLOR_ARRAY);
}
}
/ 端 /
答案 0 :(得分:1)
首先回答这个问题,如果您使用的是ES2,您可以尝试加载所有16x8纹理,但我会说其中32个目前在iOS上最大(从活动纹理的枚举判断)。如果成功拥有所有纹理,则需要从片段着色器中的纹理坐标计算要使用的纹理:
int verticalTextureCount, horizontalTextureCount; //input tile count
float texCoordX, texCoordY; //input texture coordinates
int textureX = (int)(texCoordX*horizontalTextureCount); //texture to use
int textureY = (int)(texCoordY*verticalTextureCount); //texture to use
texCoordX -= (1.0/horizontalTextureCount)*textureX; //decreas offset
texCoordY -= (1.0/verticalTextureCount)*textureY; //decreas offset
texCoordX *= horizontalTextureCount; //rescale
texCoordY *= verticalTextureCount; //rescale
此时,您可以使用textureX和textureY编写verticalTextureCount * horizontalTextureCount“if语句”,以确定要使用的纹理和texCoors来获取纹理元素。这或多或少都是。
第二,关于讨论,不,不要那样做。如果纹理太大,那就太大了。如果我敢于猜测我会说你正在尝试制作一个具有某种行星的应用程序,你希望它具有一些极端的缩放功能,并且你需要一些细节纹理。如果是这种情况或类似情况,请创建多个将用作纹理的图像,例如:有1个图像放置整个球体,4个图像,每个图像有四个球体,16个图像......以及所有这些图像大小相同,如2048 * 2048。
现在是最好的部分,你需要一个动态系统,根据你的需要加载和卸载图像。如果球体缩小,您只需要1张整个图像并像之前一样绘制。如果你放大很多,你需要检查最适合的纹理级别,并检查球体的哪些部分是可见的,这样你只能加载你需要的纹理,只绘制可见球体的部分。这不是一项容易的任务,但它与大多数可以在3D中看到地球的应用程序的原理大致相同。它会在运行时检查您正在查看的行星的哪个部分以及详细信息,通常会向服务器发送请求,以便在需要时接收详细图像并创建要显示的详细纹理。