Handle different sized base, bump, and specular mask textures correctly.
parent
1a728e3f94
commit
698712ad30
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -162,7 +162,7 @@ static void initTextureLoader()
|
|||
autoMipMapSupported = ExtensionSupported("GL_SGIS_generate_mipmap");
|
||||
maxLevelSupported = testMaxLevel();
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
|
||||
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue