From 698712ad306c467eaecfca5670fa4f8d9bb568b4 Mon Sep 17 00:00:00 2001 From: Chris Laurel Date: Tue, 20 Aug 2002 09:09:35 +0000 Subject: [PATCH] Handle different sized base, bump, and specular mask textures correctly. --- shaders/bumpdiffuse.vp | 4 +- shaders/bumphaze.vp | 5 +- shaders/simple.vp | 1 + shaders/specular.vp | 2 + src/celengine/lodspheremesh.cpp | 187 +++++++++++++++++++++++--------- src/celengine/lodspheremesh.h | 17 ++- src/celengine/regcombine.cpp | 4 +- src/celengine/render.cpp | 27 +++-- src/celengine/texture.cpp | 2 +- 9 files changed, 178 insertions(+), 71 deletions(-) diff --git a/shaders/bumpdiffuse.vp b/shaders/bumpdiffuse.vp index 634316c5..6d11d567 100644 --- a/shaders/bumpdiffuse.vp +++ b/shaders/bumpdiffuse.vp @@ -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 diff --git a/shaders/bumphaze.vp b/shaders/bumphaze.vp index 02daeef0..64cb157f 100644 --- a/shaders/bumphaze.vp +++ b/shaders/bumphaze.vp @@ -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 diff --git a/shaders/simple.vp b/shaders/simple.vp index ae6f18ad..89861565 100644 --- a/shaders/simple.vp +++ b/shaders/simple.vp @@ -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 diff --git a/shaders/specular.vp b/shaders/specular.vp index 39cb0b96..8b7707d8 100644 --- a/shaders/specular.vp +++ b/shaders/specular.vp @@ -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; diff --git a/src/celengine/lodspheremesh.cpp b/src/celengine/lodspheremesh.cpp index dbbe505f..7bb4da83 100644 --- a/src/celengine/lodspheremesh.cpp +++ b/src/celengine/lodspheremesh.cpp @@ -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; diff --git a/src/celengine/lodspheremesh.h b/src/celengine/lodspheremesh.h index 6466ece0..c544161e 100644 --- a/src/celengine/lodspheremesh.h +++ b/src/celengine/lodspheremesh.h @@ -15,6 +15,9 @@ #include +#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_ diff --git a/src/celengine/regcombine.cpp b/src/celengine/regcombine.cpp index 26255828..75a35157 100644 --- a/src/celengine/regcombine.cpp +++ b/src/celengine/regcombine.cpp @@ -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); diff --git a/src/celengine/render.cpp b/src/celengine/render.cpp index d020734b..044c8826 100644 --- a/src/celengine/render.cpp +++ b/src/celengine/render.cpp @@ -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 diff --git a/src/celengine/texture.cpp b/src/celengine/texture.cpp index fd4cc7d2..6ac26a44 100644 --- a/src/celengine/texture.cpp +++ b/src/celengine/texture.cpp @@ -162,7 +162,7 @@ static void initTextureLoader() autoMipMapSupported = ExtensionSupported("GL_SGIS_generate_mipmap"); maxLevelSupported = testMaxLevel(); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); - + initialized = true; }