Made virtual textures actually work, modulo LOD calculation and eviction.Delegated the task of computing sphere LODs to LODSphereMesh.
parent
f9dbddb8b0
commit
b9da43799b
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue