Made virtual textures actually work, modulo LOD calculation and eviction.Delegated the task of computing sphere LODs to LODSphereMesh.

ver1_5_1
Chris Laurel 2003-07-30 17:07:46 +00:00
parent f9dbddb8b0
commit b9da43799b
5 changed files with 205 additions and 191 deletions

View File

@ -65,6 +65,27 @@ static void InitTrigArrays()
}
static float getSphereLOD(float discSizeInPixels)
{
if (discSizeInPixels < 10)
return -3.0f;
else if (discSizeInPixels < 20)
return -2.0f;
else if (discSizeInPixels < 50)
return -1.0f;
else if (discSizeInPixels < 200)
return 0.0f;
else if (discSizeInPixels < 1200)
return 1.0f;
else if (discSizeInPixels < 7200)
return 2.0f;
else if (discSizeInPixels < 53200)
return 3.0f;
else
return 4.0f;
}
LODSphereMesh::LODSphereMesh() :
vertices(NULL),
normals(NULL),
@ -112,12 +133,12 @@ static Point3f spherePoint(int theta, int phi)
void LODSphereMesh::render(const GLContext& context,
const Frustum& frustum,
float lodBias,
float pixWidth,
Texture** tex,
int nTextures)
{
render(context,
Mesh::Normals | Mesh::TexCoords0, frustum, lodBias, tex,
Mesh::Normals | Mesh::TexCoords0, frustum, pixWidth, tex,
nTextures);
}
@ -125,7 +146,7 @@ void LODSphereMesh::render(const GLContext& context,
void LODSphereMesh::render(const GLContext& context,
unsigned int attributes,
const Frustum& frustum,
float lodBias,
float pixWidth,
Texture* tex0,
Texture* tex1,
Texture* tex2,
@ -142,20 +163,20 @@ void LODSphereMesh::render(const GLContext& context,
textures[nTextures++] = tex2;
if (tex3 != NULL)
textures[nTextures++] = tex3;
render(context, attributes, frustum, lodBias, textures, nTextures);
render(context, attributes, frustum, pixWidth, textures, nTextures);
}
void LODSphereMesh::render(const GLContext& context,
unsigned int attributes,
const Frustum& frustum,
float lodBias,
float pixWidth,
Texture** tex,
int nTextures)
{
Point3f fp[8];
int lod = 64;
float lodBias = getSphereLOD(pixWidth);
if (lodBias < 0.0f)
{
if (lodBias < -30)
@ -188,16 +209,19 @@ void LODSphereMesh::render(const GLContext& context,
if (tex == NULL)
nTextures = 0;
RenderInfo ri(step, attributes, frustum);
// If one of the textures is split into subtextures, we may have to
// use extra patches, since there can be at most one subtexture per patch.
int i;
int minSplit = 1;
for (i = 0; i < nTextures; i++)
{
ri.texLOD[i] = tex[i]->getLODCount() - 1;
if (tex[i]->getUTileCount(0) > minSplit)
minSplit = tex[i]->getUTileCount(0);
minSplit = tex[i]->getUTileCount(ri.texLOD[i]);
if (tex[i]->getVTileCount(0) > minSplit)
minSplit = tex[i]->getVTileCount(0);
minSplit = tex[i]->getVTileCount(ri.texLOD[i]);
}
if (split < minSplit)
@ -269,17 +293,10 @@ void LODSphereMesh::render(const GLContext& context,
glDisableClientState(GL_COLOR_ARRAY);
// Use nVidia's vertex program extension . . . right now, we
// just assume that we only send down tangents if we're using this
// extension. Need to come up with a better solution . . .
if (tangents != NULL && ((attributes & Mesh::Tangents) != 0))
{
#if 0
glEnableClientState(GL_VERTEX_ATTRIB_ARRAY6_NV);
glx::glVertexAttribPointerNV(6, 3, GL_FLOAT, 0, tangents);
glx::glEnableVertexAttribArrayARB(6);
glx::glVertexAttribPointerARB(6, 3, GL_FLOAT, GL_FALSE, 0, tangents);
#endif
// Need to have vertex programs enabled in order to make
// use of surface tangents.
VertexProcessor* vproc = context.getVertexProcessor();
if (vproc != NULL)
{
@ -290,7 +307,7 @@ void LODSphereMesh::render(const GLContext& context,
if (split == 1)
{
renderSection(0, 0, thetaExtent, step, attributes);
renderSection(0, 0, thetaExtent, ri);
}
else
{
@ -299,30 +316,30 @@ void LODSphereMesh::render(const GLContext& context,
// Compute the vertices of the view frustum. These will be used for
// culling patches.
fp[0] = Planef::intersection(frustum.getPlane(Frustum::Near),
frustum.getPlane(Frustum::Top),
frustum.getPlane(Frustum::Left));
fp[1] = Planef::intersection(frustum.getPlane(Frustum::Near),
frustum.getPlane(Frustum::Top),
frustum.getPlane(Frustum::Right));
fp[2] = Planef::intersection(frustum.getPlane(Frustum::Near),
frustum.getPlane(Frustum::Bottom),
frustum.getPlane(Frustum::Left));
fp[3] = Planef::intersection(frustum.getPlane(Frustum::Near),
frustum.getPlane(Frustum::Bottom),
frustum.getPlane(Frustum::Right));
fp[4] = Planef::intersection(frustum.getPlane(Frustum::Far),
frustum.getPlane(Frustum::Top),
frustum.getPlane(Frustum::Left));
fp[5] = Planef::intersection(frustum.getPlane(Frustum::Far),
frustum.getPlane(Frustum::Top),
frustum.getPlane(Frustum::Right));
fp[6] = Planef::intersection(frustum.getPlane(Frustum::Far),
frustum.getPlane(Frustum::Bottom),
frustum.getPlane(Frustum::Left));
fp[7] = Planef::intersection(frustum.getPlane(Frustum::Far),
frustum.getPlane(Frustum::Bottom),
frustum.getPlane(Frustum::Right));
ri.fp[0] = Planef::intersection(frustum.getPlane(Frustum::Near),
frustum.getPlane(Frustum::Top),
frustum.getPlane(Frustum::Left));
ri.fp[1] = Planef::intersection(frustum.getPlane(Frustum::Near),
frustum.getPlane(Frustum::Top),
frustum.getPlane(Frustum::Right));
ri.fp[2] = Planef::intersection(frustum.getPlane(Frustum::Near),
frustum.getPlane(Frustum::Bottom),
frustum.getPlane(Frustum::Left));
ri.fp[3] = Planef::intersection(frustum.getPlane(Frustum::Near),
frustum.getPlane(Frustum::Bottom),
frustum.getPlane(Frustum::Right));
ri.fp[4] = Planef::intersection(frustum.getPlane(Frustum::Far),
frustum.getPlane(Frustum::Top),
frustum.getPlane(Frustum::Left));
ri.fp[5] = Planef::intersection(frustum.getPlane(Frustum::Far),
frustum.getPlane(Frustum::Top),
frustum.getPlane(Frustum::Right));
ri.fp[6] = Planef::intersection(frustum.getPlane(Frustum::Far),
frustum.getPlane(Frustum::Bottom),
frustum.getPlane(Frustum::Left));
ri.fp[7] = Planef::intersection(frustum.getPlane(Frustum::Far),
frustum.getPlane(Frustum::Bottom),
frustum.getPlane(Frustum::Right));
@ -342,12 +359,7 @@ void LODSphereMesh::render(const GLContext& context,
for (int j = 0; j < 2; j++)
{
nPatches += renderPatches(i * extent / 2, j * extent,
extent,
split / 2,
step,
attributes,
frustum,
fp);
extent, split / 2, ri);
}
}
}
@ -356,10 +368,6 @@ void LODSphereMesh::render(const GLContext& context,
if (tangents != NULL && ((attributes & Mesh::Tangents) != 0))
{
#if 0
glDisableClientState(GL_VERTEX_ATTRIB_ARRAY6_NV);
glDisableVertexAttribArrayARB(6);
#endif
VertexProcessor* vproc = context.getVertexProcessor();
if (vproc != NULL)
vproc->disableAttribArray(6);
@ -399,18 +407,18 @@ void LODSphereMesh::render(const GLContext& context,
glColor4f(1, 0, 0, 1);
glTranslatef(0, 0, -20);
glBegin(GL_LINES);
glVertex(fp[0]); glVertex(fp[1]);
glVertex(fp[0]); glVertex(fp[2]);
glVertex(fp[3]); glVertex(fp[1]);
glVertex(fp[3]); glVertex(fp[2]);
glVertex(fp[4]); glVertex(fp[5]);
glVertex(fp[4]); glVertex(fp[6]);
glVertex(fp[7]); glVertex(fp[5]);
glVertex(fp[7]); glVertex(fp[6]);
glVertex(fp[0]); glVertex(fp[4]);
glVertex(fp[1]); glVertex(fp[5]);
glVertex(fp[2]); glVertex(fp[6]);
glVertex(fp[3]); glVertex(fp[7]);
glVertex(ri.fp[0]); glVertex(ri.fp[1]);
glVertex(ri.fp[0]); glVertex(ri.fp[2]);
glVertex(ri.fp[3]); glVertex(ri.fp[1]);
glVertex(ri.fp[3]); glVertex(ri.fp[2]);
glVertex(ri.fp[4]); glVertex(ri.fp[5]);
glVertex(ri.fp[4]); glVertex(ri.fp[6]);
glVertex(ri.fp[7]); glVertex(ri.fp[5]);
glVertex(ri.fp[7]); glVertex(ri.fp[6]);
glVertex(ri.fp[0]); glVertex(ri.fp[4]);
glVertex(ri.fp[1]); glVertex(ri.fp[5]);
glVertex(ri.fp[2]); glVertex(ri.fp[6]);
glVertex(ri.fp[3]); glVertex(ri.fp[7]);
glEnd();
// Render axes representing the unit sphere.
@ -479,10 +487,7 @@ void LODSphereMesh::render(const GLContext& context,
int LODSphereMesh::renderPatches(int phi0, int theta0,
int extent,
int level,
int step,
unsigned int attributes,
const Frustum& frustum,
Point3f* fp)
const RenderInfo& ri)
{
int thetaExtent = extent;
int phiExtent = extent / 2;
@ -513,7 +518,7 @@ int LODSphereMesh::renderPatches(int phi0, int theta0,
#if 1
for (int k = 0; k < 8; k++)
{
if (separatingPlane.distanceTo(fp[k]) > 0.0f)
if (separatingPlane.distanceTo(ri.fp[k]) > 0.0f)
{
outside = false;
break;
@ -543,7 +548,7 @@ int LODSphereMesh::renderPatches(int phi0, int theta0,
boundingRadius = max(boundingRadius, patchCenter.distanceTo(p1));
boundingRadius = max(boundingRadius, patchCenter.distanceTo(p2));
boundingRadius = max(boundingRadius, patchCenter.distanceTo(p3));
if (frustum.testSphere(patchCenter, boundingRadius) == Frustum::Outside)
if (ri.frustum.testSphere(patchCenter, boundingRadius) == Frustum::Outside)
outside = true;
if (outside)
@ -552,9 +557,7 @@ int LODSphereMesh::renderPatches(int phi0, int theta0,
}
else if (level == 1)
{
renderSection(phi0, theta0,
thetaExtent,
step, attributes);
renderSection(phi0, theta0, thetaExtent, ri);
return 1;
}
else
@ -568,10 +571,7 @@ int LODSphereMesh::renderPatches(int phi0, int theta0,
theta0 + thetaExtent / 2 * j,
extent / 2,
level / 2,
step,
attributes,
frustum,
fp);
ri);
}
}
return nRendered;
@ -579,10 +579,9 @@ int LODSphereMesh::renderPatches(int phi0, int theta0,
}
void LODSphereMesh::renderSection(int phi0, int theta0,
int extent,
int step,
unsigned int attributes)
void LODSphereMesh::renderSection(int phi0, int theta0, int extent,
const RenderInfo& ri)
{
#ifdef SHOW_PATCH_VISIBILITY
{
@ -594,7 +593,7 @@ void LODSphereMesh::renderSection(int phi0, int theta0,
visiblePatches[y * width + x] = 1;
}
#endif // SHOW_PATCH_VISIBILITY
// assert(step >= minStep);
// assert(ri.step >= minStep);
// assert(phi0 + extent <= maxDivisions);
// assert(theta0 + extent / 2 < maxDivisions);
// assert(isPow2(extent));
@ -621,8 +620,8 @@ void LODSphereMesh::renderSection(int phi0, int theta0,
if (textures[tex] != NULL)
{
int uTexSplit = textures[tex]->getUTileCount(0);
int vTexSplit = textures[tex]->getVTileCount(0);
int uTexSplit = textures[tex]->getUTileCount(ri.texLOD[tex]);
int vTexSplit = textures[tex]->getVTileCount(ri.texLOD[tex]);
int patchSplit = maxDivisions / extent;
assert(patchSplit >= uTexSplit && patchSplit >= vTexSplit);
@ -643,13 +642,14 @@ void LODSphereMesh::renderSection(int phi0, int theta0,
u /= patchesPerUSubtex;
v /= patchesPerVSubtex;
TextureTile tile = textures[tex]->getTile(0,
TextureTile tile = textures[tex]->getTile(ri.texLOD[tex],
uTexSplit - u - 1,
vTexSplit - v - 1);
#if 0
unsigned int tn = textures[tex]->getName(uTexSplit - u - 1,
vTexSplit - v - 1);
#endif
du[tex] *= tile.du;
dv[tex] *= tile.dv;
u0[tex] = u0[tex] * tile.du + tile.u;
v0[tex] = v0[tex] * tile.dv + tile.v;
unsigned int tn = tile.texID;
// We track the current texture to avoid unnecessary and costly
// texture state changes.
@ -663,14 +663,14 @@ void LODSphereMesh::renderSection(int phi0, int theta0,
}
}
for (int phi = phi0; phi <= phi1; phi += step)
for (int phi = phi0; phi <= phi1; phi += ri.step)
{
float cphi = cosPhi[phi];
float sphi = sinPhi[phi];
if ((attributes & Mesh::Tangents) != 0)
if ((ri.attributes & Mesh::Tangents) != 0)
{
for (int theta = theta0; theta <= theta1; theta += step)
for (int theta = theta0; theta <= theta1; theta += ri.step)
{
float ctheta = cosTheta[theta];
float stheta = sinTheta[theta];
@ -690,7 +690,7 @@ void LODSphereMesh::renderSection(int phi0, int theta0,
}
else
{
for (int theta = theta0; theta <= theta1; theta += step)
for (int theta = theta0; theta <= theta1; theta += ri.step)
{
float ctheta = cosTheta[theta];
float stheta = sinTheta[theta];
@ -711,8 +711,8 @@ void LODSphereMesh::renderSection(int phi0, int theta0,
float du_ = du[tex];
float dv_ = dv[tex];
n2 -= (theta1 - theta0) / step * 2 + 2;
for (int theta = theta0; theta <= theta1; theta += step)
n2 -= (theta1 - theta0) / ri.step * 2 + 2;
for (int theta = theta0; theta <= theta1; theta += ri.step)
{
float ctheta = cosTheta[theta];
float stheta = sinTheta[theta];
@ -724,9 +724,9 @@ void LODSphereMesh::renderSection(int phi0, int theta0,
}
// TODO: Fix this--number of rings can reach zero and cause dropout
// int nRings = max(phiExtent / step, 1); // buggy
int nRings = phiExtent / step;
int nSlices = thetaExtent / step;
// int nRings = max(phiExtent / ri.step, 1); // buggy
int nRings = phiExtent / ri.step;
int nSlices = thetaExtent / ri.step;
for (int i = 0; i < nRings; i++)
{
glDrawElements(GL_QUAD_STRIP,

View File

@ -26,29 +26,36 @@ public:
~LODSphereMesh();
void render(const GLContext&,
unsigned int attributes, const Frustum&, float lod,
unsigned int attributes, const Frustum&, float pixWidth,
Texture** tex, int nTextures);
void render(const GLContext&,
unsigned int attributes, const Frustum&, float lod,
unsigned int attributes, const Frustum&, float pixWidth,
Texture* tex0 = NULL, Texture* tex1 = NULL,
Texture* tex2 = NULL, Texture* tex3 = NULL);
void render(const GLContext&,
const Frustum&, float lod,
const Frustum&, float pixWidth,
Texture** tex, int nTextures);
private:
struct RenderInfo
{
RenderInfo(int _step, unsigned int _attr, const Frustum& _frustum) :
step(_step), attributes(_attr), frustum(_frustum)
{};
int step;
unsigned int attributes; // vertex attributes
const Frustum& frustum; // frustum, for culling
Point3f fp[8]; // frustum points, for culling
int texLOD[MAX_SPHERE_MESH_TEXTURES];
};
int renderPatches(int phi0, int theta0,
int extent,
int level,
int step,
unsigned int attributes,
const Frustum&,
Point3f* fp);
const RenderInfo&);
void renderSection(int phi0, int theta0,
int extent,
int step,
unsigned int attributes);
void renderSection(int phi0, int theta0, int extent, const RenderInfo&);
float* vertices;
float* normals;

View File

@ -1818,7 +1818,7 @@ struct RenderInfo
Color sunColor;
Color ambientColor;
Quatf orientation;
float lod;
float pixWidth;
bool useTexEnvCombine;
RenderInfo() : color(1.0f, 1.0f, 1.0f),
@ -1837,7 +1837,7 @@ struct RenderInfo
sunColor(1.0f, 1.0f, 1.0f),
ambientColor(0.0f, 0.0f, 0.0f),
orientation(1.0f, 0.0f, 0.0f, 0.0f),
lod(0.0f),
pixWidth(1.0f),
useTexEnvCombine(false)
{};
};
@ -2345,7 +2345,7 @@ static void renderMeshDefault(Mesh* mesh,
glColor(ri.color);
mesh->render(Mesh::Normals | Mesh::TexCoords0, ri.lod);
mesh->render(Mesh::Normals | Mesh::TexCoords0, ri.pixWidth);
}
@ -2372,7 +2372,7 @@ static void renderSphereDefault(const RenderInfo& ri,
glColor(ri.color);
lodSphere->render(context,
Mesh::Normals | Mesh::TexCoords0, frustum, ri.lod,
Mesh::Normals | Mesh::TexCoords0, frustum, ri.pixWidth,
ri.baseTex);
if (ri.nightTex != NULL && ri.useTexEnvCombine)
{
@ -2382,7 +2382,8 @@ static void renderSphereDefault(const RenderInfo& ri,
glBlendFunc(GL_ONE, GL_ONE);
glAmbientLightColor(Color::Black); // Disable ambient light
lodSphere->render(context,
Mesh::Normals | Mesh::TexCoords0, frustum, ri.lod,
Mesh::Normals | Mesh::TexCoords0,
frustum, ri.pixWidth,
ri.nightTex);
glAmbientLightColor(ri.ambientColor);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
@ -2394,7 +2395,8 @@ static void renderSphereDefault(const RenderInfo& ri,
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
lodSphere->render(context,
Mesh::Normals | Mesh::TexCoords0, frustum, ri.lod,
Mesh::Normals | Mesh::TexCoords0,
frustum, ri.pixWidth,
ri.overlayTex);
glBlendFunc(GL_ONE, GL_ONE);
}
@ -2428,7 +2430,7 @@ static void renderSphere_Combiners(const RenderInfo& ri,
ri.orientation,
ri.ambientColor,
frustum,
ri.lod);
ri.pixWidth);
}
else if (ri.baseTex != NULL)
{
@ -2437,13 +2439,13 @@ static void renderSphere_Combiners(const RenderInfo& ri,
ri.sunDir_eye,
ri.orientation,
ri.ambientColor,
ri.lod,
ri.pixWidth,
frustum);
}
else
{
glEnable(GL_LIGHTING);
lodSphere->render(context, frustum, ri.lod, NULL, 0);
lodSphere->render(context, frustum, ri.pixWidth, NULL, 0);
}
if (ri.nightTex != NULL)
@ -2456,7 +2458,7 @@ static void renderSphere_Combiners(const RenderInfo& ri,
ri.sunDir_eye,
ri.orientation,
Color::Black,
ri.lod,
ri.pixWidth,
frustum,
true);
}
@ -2468,7 +2470,8 @@ static void renderSphere_Combiners(const RenderInfo& ri,
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
lodSphere->render(context,
Mesh::Normals | Mesh::TexCoords0, frustum, ri.lod,
Mesh::Normals | Mesh::TexCoords0,
frustum, ri.pixWidth,
ri.overlayTex);
#if 0
renderSmoothMesh(context,
@ -2476,7 +2479,7 @@ static void renderSphere_Combiners(const RenderInfo& ri,
ri.sunDir_eye,
ri.orientation,
ri.ambientColor,
ri.lod,
ri.pixWidth,
frustum);
#endif
glBlendFunc(GL_ONE, GL_ONE);
@ -2523,7 +2526,7 @@ static void renderSphere_DOT3_VP(const RenderInfo& ri,
setupBumpTexenv();
lodSphere->render(context,
Mesh::Normals | Mesh::Tangents | Mesh::TexCoords0 |
Mesh::VertexProgParams, frustum, ri.lod,
Mesh::VertexProgParams, frustum, ri.pixWidth,
ri.bumpTex, ri.baseTex);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
@ -2533,7 +2536,7 @@ static void renderSphere_DOT3_VP(const RenderInfo& ri,
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
lodSphere->render(context,
Mesh::Normals | Mesh::TexCoords0 |
Mesh::VertexProgParams, frustum, ri.lod,
Mesh::VertexProgParams, frustum, ri.pixWidth,
ri.baseTex);
}
@ -2552,7 +2555,7 @@ static void renderSphere_DOT3_VP(const RenderInfo& ri,
lodSphere->render(context,
Mesh::Normals | Mesh::TexCoords0,
frustum, ri.lod,
frustum, ri.pixWidth,
ri.glossTex != NULL ? ri.glossTex : ri.baseTex);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
@ -2567,7 +2570,8 @@ static void renderSphere_DOT3_VP(const RenderInfo& ri,
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
lodSphere->render(context,
Mesh::Normals | Mesh::TexCoords0, frustum, ri.lod,
Mesh::Normals | Mesh::TexCoords0,
frustum, ri.pixWidth,
ri.nightTex);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
@ -2579,7 +2583,8 @@ static void renderSphere_DOT3_VP(const RenderInfo& ri,
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
lodSphere->render(context,
Mesh::Normals | Mesh::TexCoords0, frustum, ri.lod,
Mesh::Normals | Mesh::TexCoords0,
frustum, ri.pixWidth,
ri.overlayTex);
glBlendFunc(GL_ONE, GL_ONE);
}
@ -2648,7 +2653,7 @@ static void renderSphere_Combiners_VP(const RenderInfo& ri,
ri.sunColor * ri.color);
lodSphere->render(context,
Mesh::Normals | Mesh::Tangents | Mesh::TexCoords0 |
Mesh::VertexProgParams, frustum, ri.lod,
Mesh::VertexProgParams, frustum, ri.pixWidth,
ri.baseTex, ri.bumpTex);
DisableCombiners();
@ -2668,7 +2673,7 @@ static void renderSphere_Combiners_VP(const RenderInfo& ri,
textures[0] = ri.glossTex != NULL ? ri.glossTex : ri.baseTex;
lodSphere->render(context,
Mesh::Normals | Mesh::TexCoords0,
frustum, ri.lod,
frustum, ri.pixWidth,
textures, 1);
// re-enable diffuse
@ -2687,7 +2692,7 @@ static void renderSphere_Combiners_VP(const RenderInfo& ri,
unsigned int attributes = Mesh::Normals | Mesh::TexCoords0 |
Mesh::VertexProgParams;
lodSphere->render(context,
attributes, frustum, ri.lod,
attributes, frustum, ri.pixWidth,
ri.baseTex, ri.glossTex);
DisableCombiners();
glDisable(GL_COLOR_SUM_EXT);
@ -2700,7 +2705,7 @@ static void renderSphere_Combiners_VP(const RenderInfo& ri,
vproc->use(vp::diffuse);
lodSphere->render(context,
Mesh::Normals | Mesh::TexCoords0 |
Mesh::VertexProgParams, frustum, ri.lod,
Mesh::VertexProgParams, frustum, ri.pixWidth,
ri.baseTex);
}
@ -2715,7 +2720,8 @@ static void renderSphere_Combiners_VP(const RenderInfo& ri,
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
lodSphere->render(context,
Mesh::Normals | Mesh::TexCoords0, frustum, ri.lod,
Mesh::Normals | Mesh::TexCoords0,
frustum, ri.pixWidth,
ri.nightTex);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
@ -2727,7 +2733,8 @@ static void renderSphere_Combiners_VP(const RenderInfo& ri,
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
lodSphere->render(context,
Mesh::Normals | Mesh::TexCoords0, frustum, ri.lod,
Mesh::Normals | Mesh::TexCoords0,
frustum, ri.pixWidth,
ri.overlayTex);
glBlendFunc(GL_ONE, GL_ONE);
}
@ -2777,11 +2784,11 @@ static void renderShadowedMeshDefault(Mesh* mesh,
{
lodSphere->render(context,
Mesh::Normals | Mesh::Multipass,
frustum, ri.lod, NULL);
frustum, ri.pixWidth, NULL);
}
else
{
mesh->render(Mesh::Normals | Mesh::Multipass, ri.lod);
mesh->render(Mesh::Normals | Mesh::Multipass, ri.pixWidth);
}
glEnable(GL_LIGHTING);
@ -2812,7 +2819,8 @@ static void renderShadowedMeshVertexShader(const RenderInfo& ri,
vproc->use(vp::shadowTexture);
lodSphere->render(context,
Mesh::Normals | Mesh::Multipass, frustum, ri.lod, NULL);
Mesh::Normals | Mesh::Multipass, frustum,
ri.pixWidth, NULL);
vproc->disable();
}
@ -3264,7 +3272,8 @@ renderRingShadowsVS(Mesh* mesh,
1.0f / (ringWidth / planetRadius),
0.0f, 0.5f);
vproc->parameter(vp::TexGen_T, scale, 0, 0, 0);
lodSphere->render(context, Mesh::Multipass, viewFrustum, ri.lod, NULL);
lodSphere->render(context, Mesh::Multipass,
viewFrustum, ri.pixWidth, NULL);
vproc->disable();
// Restore the texture combiners
@ -3373,27 +3382,6 @@ void Renderer::renderLocations(const vector<Location*>& locations,
}
static float getSphereLOD(float discSizeInPixels)
{
if (discSizeInPixels < 10)
return -3.0f;
else if (discSizeInPixels < 20)
return -2.0f;
else if (discSizeInPixels < 50)
return -1.0f;
else if (discSizeInPixels < 200)
return 0.0f;
else if (discSizeInPixels < 1200)
return 1.0f;
else if (discSizeInPixels < 7200)
return 2.0f;
else if (discSizeInPixels < 53200)
return 3.0f;
else
return 4.0f;
}
void Renderer::renderObject(Point3f pos,
float distance,
double now,
@ -3458,7 +3446,7 @@ void Renderer::renderObject(Point3f pos,
ri.orientation = cameraOrientation;
ri.lod = getSphereLOD(discSizeInPixels);
ri.pixWidth = discSizeInPixels;
// Set up the colors
if (ri.baseTex == NULL ||
@ -3530,8 +3518,8 @@ void Renderer::renderObject(Point3f pos,
// Temporary hack until we fix culling for ringed planets
if (obj.rings != NULL)
{
if (ri.lod > 2.0f)
ri.lod = 2.0f;
if (ri.pixWidth > 5000)
ri.pixWidth = 5000;
}
Mesh* mesh = NULL;
@ -3688,7 +3676,7 @@ void Renderer::renderObject(Point3f pos,
lodSphere->render(*context,
Mesh::Normals | Mesh::TexCoords0,
viewFrustum,
ri.lod,
ri.pixWidth,
cloudTex);
if (vproc != NULL)
@ -3700,7 +3688,7 @@ void Renderer::renderObject(Point3f pos,
lodSphere->render(*context,
Mesh::Normals | Mesh::TexCoords0,
viewFrustum,
ri.lod,
ri.pixWidth,
cloudTex);
glEnable(GL_LIGHTING);
}

View File

@ -92,25 +92,24 @@ const TextureTile VirtualTexture::getTile(int lod, int u, int v)
{
TileQuadtreeNode* node = tileTree[u >> lod];
Tile* tile = node->tile;
int tileLOD = 0;
int n = 0;
uint tileLOD = 0;
while (n < lod)
for (int n = 0; n < lod; n++)
{
int child = (((v << 1) | u) >> (lod - n - 1)) & 3;
uint mask = 1 << (lod - n - 1);
uint child = (((v & mask) << 1) | (u & mask)) >> (lod - n - 1);
//int child = (((v << 1) | u) >> (lod - n - 1)) & 3;
if (node->children[child] == NULL)
{
break;
}
else
{
node = node->children[child];
if (node->tile != NULL)
tile = node->tile;
tileLOD = n;
tileLOD = n + 1;
}
node = node->children[child];
n++;
}
// No tile was found at all--not even the base texture was found
@ -118,13 +117,15 @@ const TextureTile VirtualTexture::getTile(int lod, int u, int v)
return TextureTile(0);
// Make the tile resident.
makeResident(tile, lod, u, v);
uint tileU = u >> (lod - tileLOD);
uint tileV = v >> (lod - tileLOD);
makeResident(tile, tileLOD, tileU, tileV);
// It's possible that we failed to make the tile resident, either
// because the texture file was bad, or there was an unresolvable
// out of memory situation. In that case there is nothing else to
// do but return a texture tile with a null texture name.
if (node->tile->tex == NULL)
if (tile->tex == NULL)
{
return TextureTile(0);
}
@ -143,7 +144,9 @@ const TextureTile VirtualTexture::getTile(int lod, int u, int v)
texU = (u & ((1 << lodDiff) - 1)) * texDU;
texV = (v & ((1 << lodDiff) - 1)) * texDV;
return TextureTile(node->tile->tex->getName(),
cout << "Tile: " << tile->tex->getName() << ", " <<
texU << ", " << texV << ", " << texDU << ", " << texDV << '\n';
return TextureTile(tile->tex->getName(),
texU, texV, texDU, texDV);
}
}
@ -157,6 +160,12 @@ void VirtualTexture::bind()
}
int VirtualTexture::getLODCount() const
{
return nResolutionLevels - baseSplit;
}
int VirtualTexture::getUTileCount(int lod) const
{
return 2 << (lod + baseSplit);
@ -218,6 +227,7 @@ ImageTexture* VirtualTexture::loadTileTexture(uint lod, uint u, uint v)
void VirtualTexture::makeResident(Tile* tile, uint lod, uint u, uint v)
{
cout << "makeResident: " << lod << ", " << u << ", " << v << '\n';
if (tile->tex == NULL && !tile->loadFailed)
{
// Potentially evict other tiles in order to make this one fit
@ -231,35 +241,41 @@ void VirtualTexture::makeResident(Tile* tile, uint lod, uint u, uint v)
void VirtualTexture::populateTileTree()
{
// Count the number of resolution levels present
uint maxLevel = 0;
for (int i = 0; i < MaxResolutionLevels; i++)
{
char filename[32];
sprintf(filename, "level%d", i);
Directory* dir = OpenDirectory(tilePath + filename);
if (dir)
if (IsDirectory(tilePath + filename))
{
nResolutionLevels = i + baseSplit;
int uLimit = 2 << nResolutionLevels;
int vLimit = 1 << nResolutionLevels;
string filename;
while (dir->nextFile(filename))
Directory* dir = OpenDirectory(tilePath + filename);
if (dir != NULL)
{
int u = -1, v = -1;
cout << "Scanning file " << filename << '\n';
if (sscanf(filename.c_str(), "tx_%d_%d.", &u, &v) == 2)
maxLevel = i + baseSplit;
cout << filename << ", levels = " << maxLevel + 1 << '\n';
int uLimit = 2 << maxLevel;
int vLimit = 1 << maxLevel;
string filename;
while (dir->nextFile(filename))
{
if (u >= 0 && v >= 0 && u < uLimit && v < vLimit)
int u = -1, v = -1;
cout << "Scanning file " << filename << '\n';
if (sscanf(filename.c_str(), "tx_%d_%d.", &u, &v) == 2)
{
// Found a tile, so add it to the quadtree
Tile* tile = new Tile();
addTileToTree(tile, nResolutionLevels,
(uint) u, (uint) v);
if (u >= 0 && v >= 0 && u < uLimit && v < vLimit)
{
// Found a tile, so add it to the quadtree
Tile* tile = new Tile();
addTileToTree(tile, maxLevel, (uint) u, (uint) v);
}
}
}
}
}
}
nResolutionLevels = maxLevel + 1;
}
@ -269,11 +285,13 @@ void VirtualTexture::addTileToTree(Tile* tile, uint lod, uint u, uint v)
for (uint i = 0; i < lod; i++)
{
int child = (((v << 1) | u) >> (lod - i - 1)) & 3;
uint mask = 1 << (lod - i - 1);
uint child = (((v & mask) << 1) | (u & mask)) >> (lod - i - 1);
if (node->children[child] == NULL)
node->children[child] = new TileQuadtreeNode();
node = node->children[child];
}
cout << "addTileToTree: " << node << ", " << lod << ", " << u << ", " << v << '\n';
// Verify that the tile doesn't already exist
if (node->tile == NULL)

View File

@ -27,6 +27,7 @@ class VirtualTexture : public Texture
virtual const TextureTile getTile(int lod, int u, int v);
virtual void bind();
virtual int getLODCount() const;
virtual int getUTileCount(int lod) const;
virtual int getVTileCount(int lod) const;
virtual void beginUsage();