Handle different sized base, bump, and specular mask textures correctly.

pull/3/head
Chris Laurel 2002-08-20 09:09:35 +00:00
parent 1a728e3f94
commit 698712ad30
9 changed files with 178 additions and 71 deletions

View File

@ -40,9 +40,9 @@ DP3 R0.z, R1, c[16];
MOV R5, c[40];
MAD o[COL0], R0, R5.z, R5.z;
# Output the texture coordinates. Use the same coordinates for
# Output the texture coordinates. Use different coordinates for
# the decal (texture 0) and the bump map (texture 1)
MOV o[TEX0], v[TEX0];
MOV o[TEX1], v[TEX0];
MOV o[TEX1], v[TEX1];
END

View File

@ -58,9 +58,8 @@ DP3 R0.z, R1, c[16];
MOV R5, c[40];
MAD o[COL0], R0, R5.z, R5.z;
# Output the texture coordinates. Use the same coordinates for
# the decal (texture 0) and the bump map (texture 1)
# Output the texture coordinates.
MOV o[TEX0], v[TEX0];
MOV o[TEX1], v[TEX0];
MOV o[TEX1], v[TEX1];
END

View File

@ -7,6 +7,7 @@ DP4 o[HPOS].x, c[0], v[OPOS];
DP4 o[HPOS].y, c[1], v[OPOS];
DP4 o[HPOS].z, c[2], v[OPOS];
DP4 o[HPOS].w, c[3], v[OPOS];
MOV o[TEX0], v[TEX0];
END

View File

@ -59,6 +59,8 @@ MOV R6.w, c[40].w;
# Output the texture
MOV o[TEX0], v[TEX0];
MOV o[TEX1], v[TEX1];
# Output the primary color
MOV R0, c[32];
MAD o[COL0], c[20], R2.xxxx, R0;

View File

@ -61,7 +61,6 @@ static void InitTrigArrays()
LODSphereMesh::LODSphereMesh() :
vertices(NULL),
normals(NULL),
texCoords(NULL),
tangents(NULL)
{
if (!trigArraysInitialized)
@ -73,7 +72,8 @@ LODSphereMesh::LODSphereMesh() :
vertices = new float[maxVertices * 3];
normals = new float[maxVertices * 3];
texCoords = new float[maxVertices * 2];
for (int i = 0; i < MAX_SPHERE_MESH_TEXTURES; i++)
texCoords[i] = new float[maxVertices * 2];
tangents = new float[maxVertices * 3];
indices = new unsigned short[maxPhiSteps * 2 * (maxThetaSteps + 1)];
@ -83,12 +83,15 @@ LODSphereMesh::~LODSphereMesh()
{
if (vertices != NULL)
delete[] vertices;
if (texCoords != NULL)
delete[] texCoords;
if (normals != NULL)
delete[] normals;
if (tangents != NULL)
delete[] tangents;
for (int i = 0; i < MAX_SPHERE_MESH_TEXTURES; i++)
{
if (texCoords != NULL)
delete[] texCoords[i];
}
}
@ -102,16 +105,42 @@ static Point3f spherePoint(int theta, int phi)
void LODSphereMesh::render(const Frustum& frustum,
float lodBias,
Texture* tex)
Texture** tex,
int nTextures)
{
render(Mesh::Normals | Mesh::TexCoords0, frustum, lodBias, tex);
render(Mesh::Normals | Mesh::TexCoords0, frustum, lodBias, tex,
nTextures);
}
void LODSphereMesh::render(unsigned int attributes,
const Frustum& frustum,
float lodBias,
Texture* tex)
Texture* tex0,
Texture* tex1,
Texture* tex2,
Texture* tex3)
{
Texture* textures[MAX_SPHERE_MESH_TEXTURES];
int nTextures = 0;
if (tex0 != NULL)
textures[nTextures++] = tex0;
if (tex1 != NULL)
textures[nTextures++] = tex1;
if (tex2 != NULL)
textures[nTextures++] = tex2;
if (tex3 != NULL)
textures[nTextures++] = tex3;
render(attributes, frustum, lodBias, textures, nTextures);
}
void LODSphereMesh::render(unsigned int attributes,
const Frustum& frustum,
float lodBias,
Texture** tex,
int nTextures)
{
Point3f fp[8];
@ -145,15 +174,19 @@ void LODSphereMesh::render(unsigned int attributes,
phiExtent /= split;
}
// If the texture is split into subtextures, we may have to extra
// patches, since there can be at most one subtexture per per patch.
if (tex == NULL)
nTextures = 0;
// 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 minSplit = 1;
if (tex != NULL)
int i;
for (i = 0; i < nTextures; i++)
{
if (tex->getUSubtextures() > minSplit)
minSplit = tex->getUSubtextures();
if (tex->getVSubtextures() > minSplit)
minSplit = tex->getVSubtextures();
if (tex[i]->getUSubtextures() > minSplit)
minSplit = tex[i]->getUSubtextures();
if (tex[i]->getVSubtextures() > minSplit)
minSplit = tex[i]->getVSubtextures();
}
if (split < minSplit)
@ -163,16 +196,22 @@ void LODSphereMesh::render(unsigned int attributes,
split = minSplit;
}
// Set the current texture
texture0 = tex;
subtexture0 = 0;
// Set the current textures
nTexturesUsed = nTextures;
for (i = 0; i < nTextures; i++)
{
textures[i] = tex[i];
subtextures[i] = 0;
EXTglActiveTextureARB(GL_TEXTURE0_ARB + i);
glEnable(GL_TEXTURE_2D);
}
// Set up the mesh vertices
int nRings = phiExtent / step;
int nSlices = thetaExtent / step;
int n2 = 0;
for (int i = 0; i < nRings; i++)
for (i = 0; i < nRings; i++)
{
for (int j = 0; j <= nSlices; j++)
{
@ -195,6 +234,7 @@ void LODSphereMesh::render(unsigned int attributes,
glDisableClientState(GL_NORMAL_ARRAY);
}
#if 0
if (texCoords != NULL && ((attributes & Mesh::TexCoords0) != 0))
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@ -204,6 +244,15 @@ void LODSphereMesh::render(unsigned int attributes,
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
#endif
for (i = 0; i < nTextures; i++)
{
EXTglClientActiveTextureARB(GL_TEXTURE0_ARB + i);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords[i]);
}
glDisableClientState(GL_COLOR_ARRAY);
// Use nVidia's vertex program extension . . . right now, we
@ -280,6 +329,15 @@ void LODSphereMesh::render(unsigned int attributes,
glDisableClientState(GL_VERTEX_ATTRIB_ARRAY6_NV);
}
for (i = 0; i < nTextures; i++)
{
EXTglClientActiveTextureARB(GL_TEXTURE0_ARB + i);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
EXTglClientActiveTextureARB(GL_TEXTURE0_ARB);
EXTglActiveTextureARB(GL_TEXTURE0_ARB);
#if SHOW_FRUSTUM
// Debugging code for visualizing the frustum.
glMatrixMode(GL_PROJECTION);
@ -411,45 +469,57 @@ void LODSphereMesh::renderSection(int phi0, int theta0,
int phiExtent = extent / 2;
int theta1 = theta0 + thetaExtent;
int phi1 = phi0 + phiExtent;
float du = (float) 1.0f / thetaDivisions;
float dv = (float) 1.0f / phiDivisions;
float u0 = 1.0f;
float v0 = 1.0f;
int n3 = 0;
int n2 = 0;
float du[MAX_SPHERE_MESH_TEXTURES];
float dv[MAX_SPHERE_MESH_TEXTURES];
float u0[MAX_SPHERE_MESH_TEXTURES];
float v0[MAX_SPHERE_MESH_TEXTURES];
// Set the current texture. This is necessary because the texture
// may be split into subtextures.
if (texture0 != NULL)
for (int tex = 0; tex < nTexturesUsed; tex++)
{
int uTexSplit = texture0->getUSubtextures();
int vTexSplit = texture0->getVSubtextures();
int patchSplit = maxDivisions / extent;
assert(patchSplit >= uTexSplit && patchSplit >= vTexSplit);
du[tex] = (float) 1.0f / thetaDivisions;;
dv[tex] = (float) 1.0f / phiDivisions;;
u0[tex] = 1.0f;
v0[tex] = 1.0f;
int u = theta0 / thetaExtent;
int v = phi0 / phiExtent;
int patchesPerUSubtex = patchSplit / uTexSplit;
int patchesPerVSubtex = patchSplit / vTexSplit;
du *= uTexSplit;
dv *= vTexSplit;
u0 = 1.0f - (float) (u % patchesPerUSubtex) / (float)patchesPerUSubtex;
v0 = 1.0f - (float) (v % patchesPerVSubtex) / (float)patchesPerVSubtex;
u0 += theta0 * du;
v0 += phi0 * dv;
u /= patchesPerUSubtex;
v /= patchesPerVSubtex;
unsigned int tn = texture0->getName(uTexSplit - u - 1,
vTexSplit - v - 1);
if (tn != subtexture0)
if (textures[tex] != NULL)
{
int uTexSplit = textures[tex]->getUSubtextures();
int vTexSplit = textures[tex]->getVSubtextures();
int patchSplit = maxDivisions / extent;
assert(patchSplit >= uTexSplit && patchSplit >= vTexSplit);
int u = theta0 / thetaExtent;
int v = phi0 / phiExtent;
int patchesPerUSubtex = patchSplit / uTexSplit;
int patchesPerVSubtex = patchSplit / vTexSplit;
du[tex] *= uTexSplit;
dv[tex] *= vTexSplit;
u0[tex] = 1.0f - ((float) (u % patchesPerUSubtex) /
(float) patchesPerUSubtex);
v0[tex] = 1.0f - ((float) (v % patchesPerVSubtex) /
(float) patchesPerVSubtex);
u0[tex] += theta0 * du[tex];
v0[tex] += phi0 * dv[tex];
u /= patchesPerUSubtex;
v /= patchesPerVSubtex;
unsigned int tn = textures[tex]->getName(uTexSplit - u - 1,
vTexSplit - v - 1);
// We track the current texture to avoid unnecessary and costly
// texture state changes.
glBindTexture(GL_TEXTURE_2D, tn);
subtexture0 = tn;
if (tn != subtextures[tex])
{
EXTglActiveTextureARB(GL_TEXTURE0_ARB + tex);
glBindTexture(GL_TEXTURE_2D, tn);
subtextures[tex] = tn;
}
}
}
@ -468,8 +538,6 @@ void LODSphereMesh::renderSection(int phi0, int theta0,
vertices[n3] = cphi * ctheta;
vertices[n3 + 1] = sphi;
vertices[n3 + 2] = cphi * stheta;
texCoords[n2] = u0 - theta * du;
texCoords[n2 + 1] = v0 - phi * dv;
// Compute the tangent--required for bump mapping
float tx = sphi * stheta;
@ -493,12 +561,29 @@ void LODSphereMesh::renderSection(int phi0, int theta0,
vertices[n3] = cphi * ctheta;
vertices[n3 + 1] = sphi;
vertices[n3 + 2] = cphi * stheta;
texCoords[n2] = u0 - theta * du;
texCoords[n2 + 1] = v0 - phi * dv;
n2 += 2;
n3 += 3;
}
}
// Texture coordinates
for (int tex = 0; tex < nTexturesUsed; tex++)
{
float u = u0[tex];
float v = v0[tex];
float du_ = du[tex];
float dv_ = dv[tex];
n2 -= (theta1 - theta0) / step * 2 + 2;
for (int theta = theta0; theta <= theta1; theta += step)
{
float ctheta = cosTheta[theta];
float stheta = sinTheta[theta];
texCoords[tex][n2] = u - theta * du_;
texCoords[tex][n2 + 1] = v - phi * dv_;
n2 += 2;
}
}
}
int nRings = phiExtent / step;

View File

@ -15,6 +15,9 @@
#include <celengine/texture.h>
#define MAX_SPHERE_MESH_TEXTURES 4
class LODSphereMesh
{
public:
@ -22,9 +25,12 @@ public:
~LODSphereMesh();
void render(unsigned int attributes, const Frustum&, float lod,
Texture* tex);
Texture** tex, int nTextures);
void render(unsigned int attributes, const Frustum&, float lod,
Texture* tex0 = NULL, Texture* tex1 = NULL,
Texture* tex2 = NULL, Texture* tex3 = NULL);
void render(const Frustum&, float lod,
Texture* tex);
Texture** tex, int nTextures);
private:
int renderPatches(int phi0, int theta0,
@ -41,13 +47,14 @@ public:
float* vertices;
float* normals;
float* texCoords;
float* texCoords[MAX_SPHERE_MESH_TEXTURES];
float* tangents;
int nIndices;
unsigned short* indices;
Texture* texture0;
unsigned int subtexture0;
int nTexturesUsed;
Texture* textures[MAX_SPHERE_MESH_TEXTURES];
unsigned int subtextures[MAX_SPHERE_MESH_TEXTURES];
};
#endif // _LODSPHEREMESH_H_

View File

@ -226,12 +226,12 @@ void SetupCombinersDecalAndBumpMap(Texture& bumpTexture,
Color diffuseColor)
{
glEnable(GL_REGISTER_COMBINERS_NV);
#if 0
EXTglActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
bumpTexture.bind();
EXTglActiveTextureARB(GL_TEXTURE0_ARB);
#endif
EXTglCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 2);
rc::parameter(GL_CONSTANT_COLOR0_NV, ambientColor);

View File

@ -1460,6 +1460,8 @@ static void renderBumpMappedMesh(Texture& bumpTexture,
const Frustum& frustum,
float lod)
{
Texture* textures[4];
// We're doing our own per-pixel lighting, so disable GL's lighting
glDisable(GL_LIGHTING);
@ -1467,7 +1469,7 @@ static void renderBumpMappedMesh(Texture& bumpTexture,
// texture and color should have been set up already by the
// caller.
lodSphere->render(Mesh::Normals | Mesh::TexCoords0, frustum, lod,
NULL);
NULL, 0);
// The 'default' light vector for the bump map is (0, 0, 1). Determine
// a rotation transformation that will move the sun direction to
@ -1530,8 +1532,9 @@ static void renderBumpMappedMesh(Texture& bumpTexture,
glMatrixMode(GL_MODELVIEW);
EXTglActiveTextureARB(GL_TEXTURE0_ARB);
textures[0] = &bumpTexture;
lodSphere->render(Mesh::Normals | Mesh::TexCoords0, frustum, lod,
&bumpTexture);
textures, 1);
// Reset the second texture unit
EXTglActiveTextureARB(GL_TEXTURE1_ARB);
@ -1555,6 +1558,8 @@ static void renderSmoothMesh(Texture& baseTexture,
const Frustum& frustum,
bool invert = false)
{
Texture* textures[4];
// We're doing our own per-pixel lighting, so disable GL's lighting
glDisable(GL_LIGHTING);
@ -1615,8 +1620,9 @@ static void renderSmoothMesh(Texture& baseTexture,
glMatrixMode(GL_MODELVIEW);
EXTglActiveTextureARB(GL_TEXTURE0_ARB);
textures[0] = &baseTexture;
lodSphere->render(Mesh::Normals | Mesh::TexCoords0, frustum, lod,
&baseTexture);
textures, 1);
// Reset the second texture unit
EXTglActiveTextureARB(GL_TEXTURE1_ARB);
@ -1891,7 +1897,7 @@ static void renderSphereFragmentShader(const RenderInfo& ri,
else
{
glEnable(GL_LIGHTING);
lodSphere->render(frustum, ri.lod, NULL);
lodSphere->render(frustum, ri.lod, NULL, 0);
}
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
@ -1901,6 +1907,8 @@ static void renderSphereFragmentShader(const RenderInfo& ri,
static void renderSphereVertexAndFragmentShader(const RenderInfo& ri,
const Frustum& frustum)
{
Texture* textures[4];
if (ri.baseTex == NULL)
{
glDisable(GL_TEXTURE_2D);
@ -1960,7 +1968,7 @@ static void renderSphereVertexAndFragmentShader(const RenderInfo& ri,
ri.sunColor * ri.color);
lodSphere->render(Mesh::Normals | Mesh::Tangents | Mesh::TexCoords0 |
Mesh::VertexProgParams, frustum, ri.lod,
ri.baseTex);
ri.baseTex, ri.bumpTex);
DisableCombiners();
// Render a specular pass
@ -1974,9 +1982,11 @@ static void renderSphereVertexAndFragmentShader(const RenderInfo& ri,
vp::parameter(20, Color::Black);
vp::parameter(32, Color::Black);
SetupCombinersGlossMap(ri.glossTex != NULL ? GL_TEXTURE0_ARB : 0);
textures[0] = ri.glossTex != NULL ? ri.glossTex : ri.baseTex;
lodSphere->render(Mesh::Normals | Mesh::TexCoords0,
frustum, ri.lod,
ri.glossTex != NULL ? ri.glossTex : ri.baseTex);
textures, 1);
DisableCombiners();
glDisable(GL_BLEND);
}
@ -1988,9 +1998,12 @@ static void renderSphereVertexAndFragmentShader(const RenderInfo& ri,
SetupCombinersGlossMapWithFog(ri.glossTex != NULL ? GL_TEXTURE1_ARB : 0);
unsigned int attributes = Mesh::Normals | Mesh::TexCoords0 |
Mesh::VertexProgParams;
#if 0
if (ri.glossTex != NULL)
attributes |= Mesh::TexCoords1;
lodSphere->render(attributes, frustum, ri.lod, ri.baseTex);
#endif
lodSphere->render(attributes, frustum, ri.lod,
ri.baseTex, ri.glossTex);
DisableCombiners();
}
else

View File

@ -162,7 +162,7 @@ static void initTextureLoader()
autoMipMapSupported = ExtensionSupported("GL_SGIS_generate_mipmap");
maxLevelSupported = testMaxLevel();
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
initialized = true;
}