Added support for bump mapped planets.

pull/3/head
Chris Laurel 2001-03-03 02:01:01 +00:00
parent 3638a4347a
commit 967e2233c1
8 changed files with 164 additions and 8 deletions

View File

@ -17,7 +17,7 @@
void SetupCombinersBumpMap(CTexture& bumpTexture,
CTexture& normalizationTexture,
float* ambientColor)
Color ambientColor)
{
glEnable(GL_REGISTER_COMBINERS_NV);
@ -33,7 +33,11 @@ void SetupCombinersBumpMap(CTexture& bumpTexture,
// Just a single combiner stage required . . .
glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, ambientColor);
float ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
ambient[0] = ambientColor.red();
ambient[1] = ambientColor.green();
ambient[2] = ambientColor.blue();
glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, ambient);
// Compute N dot L in the RGB portion of combiner 0
// Load register A with a normal N from the normal map

View File

@ -14,10 +14,11 @@
#define _REGCOMBINE_H_
#include "texture.h"
#include "color.h"
extern void SetupCombinersBumpMap(CTexture& bumpTexture,
CTexture& normalizationTexture,
float* ambientColor);
Color ambientColor);
extern void DisableCombiners();
#endif // _REGCOMBINE_H_

View File

@ -17,6 +17,7 @@
#include "texfont.h"
#include "console.h"
#include "gui.h"
#include "regcombine.h"
#include "render.h"
using namespace std;
@ -55,6 +56,7 @@ Renderer::Renderer() :
renderMode(GL_FILL),
labelMode(NoLabels),
ambientLightLevel(0.1f),
perPixelLightingEnabled(false),
console(NULL),
nSimultaneousTextures(1),
useRegisterCombiners(false),
@ -227,6 +229,9 @@ bool Renderer::init(int winWidth, int winHeight)
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
// LEQUAL rather than LESS required for multipass rendering
glDepthFunc(GL_LEQUAL);
// We need this enabled because we use glScale, but only
// with uniform scale factors
// TODO: Do a proper check for this extension before enabling
@ -323,6 +328,22 @@ void Renderer::setAmbientLightLevel(float level)
}
bool Renderer::getPerPixelLighting() const
{
return perPixelLightingEnabled;
}
void Renderer::setPerPixelLighting(bool enable)
{
perPixelLightingEnabled = enable && perPixelLightingSupported();
}
bool Renderer::perPixelLightingSupported() const
{
return useCubeMaps && useRegisterCombiners;
}
void Renderer::addLabel(string text, Color color, Point3f pos)
{
double winX, winY, winZ;
@ -714,6 +735,97 @@ void Renderer::renderBodyAsParticle(Point3f position,
}
static void renderBumpMappedMesh(Mesh& mesh,
CTexture& bumpTexture,
Vec3f lightDirection,
Quatf orientation,
Color ambientColor)
{
// We're doing our own per-pixel lighting, so disable GL's lighting
glDisable(GL_LIGHTING);
// Render the base texture on the first pass . . . The base
// texture and color should have been set up already by the
// caller.
mesh.render();
// The 'default' light vector for the bump map is (0, 0, 1). Determine
// a rotation transformation that will move the sun direction to
// this vector.
Quatf lightOrientation;
{
Vec3f zeroLightDirection(0, 0, 1);
Vec3f axis = lightDirection ^ zeroLightDirection;
float cosAngle = zeroLightDirection * lightDirection;
float angle = 0.0f;
float epsilon = 1e-5f;
if (cosAngle + 1 < epsilon)
{
axis = Vec3f(0, 1, 0);
angle = (float) PI;
}
else if (cosAngle - 1 > -epsilon)
{
axis = Vec3f(0, 1, 0);
angle = 0.0f;
}
else
{
axis.normalize();
angle = (float) acos(cosAngle);
}
lightOrientation.setAxisAngle(axis, angle);
}
// Set up the bump map with one directional light source
glEnable(GL_BLEND);
glBlendFunc(GL_DST_COLOR, GL_ZERO);
SetupCombinersBumpMap(bumpTexture, *normalizationTex, ambientColor);
// The second set texture coordinates will contain the light
// direction in tangent space. We'll generate the texture coordinates
// from the surface normals using GL_NORMAL_MAP_EXT and then
// use the texture matrix to rotate them into tangent space.
// This method of generating tangent space light direction vectors
// isn't as general as transforming the light direction by an
// orthonormal basis for each mesh vertex, but it works well enough
// for spheres illuminated by directional light sources.
glActiveTextureARB(GL_TEXTURE1_ARB);
// Set up GL_NORMAL_MAP_EXT texture coordinate generation. This
// mode is part of the cube map extension.
glEnable(GL_TEXTURE_GEN_R);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_EXT);
glEnable(GL_TEXTURE_GEN_S);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_EXT);
glEnable(GL_TEXTURE_GEN_T);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_EXT);
// Set up the texture transformation--the light direction and the
// viewer orientation both need to be considered.
glMatrixMode(GL_TEXTURE);
glRotate(lightOrientation * orientation);
glMatrixMode(GL_MODELVIEW);
glActiveTextureARB(GL_TEXTURE0_ARB);
mesh.render();
// Reset the second texture unit
glActiveTextureARB(GL_TEXTURE1_ARB);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
DisableCombiners();
glDisable(GL_BLEND);
}
void Renderer::renderPlanet(const Body& body,
Point3f pos,
Vec3f sunDirection,
@ -740,12 +852,22 @@ void Renderer::renderPlanet(const Body& body,
const Surface& surface = body.getSurface();
// Get the texture . . .
CTexture* tex = NULL;
CTexture* bumpTex = NULL;
if (surface.baseTexture != "")
{
if (!textureManager->find(surface.baseTexture, &tex))
tex = textureManager->load(surface.baseTexture);
}
// If this renderer can support bump mapping then get the bump texture
if ((surface.appearanceFlags & Surface::ApplyBumpMap) != 0 &&
(perPixelLightingEnabled && useRegisterCombiners && useCubeMaps) &&
surface.bumpTexture != "")
{
if (!textureManager->find(surface.bumpTexture, &bumpTex))
bumpTex = textureManager->loadBumpMap(surface.bumpTexture);
}
if (tex == NULL)
{
glDisable(GL_TEXTURE_2D);
@ -814,7 +936,13 @@ void Renderer::renderPlanet(const Body& body,
}
if (mesh != NULL)
mesh->render();
{
if (bumpTex != NULL)
renderBumpMappedMesh(*mesh, *bumpTex, sunDirection, orientation,
Color(ambientLightLevel, ambientLightLevel, ambientLightLevel));
else
mesh->render();
}
// If the planet has a ring system, render it.
if (body.getRings() != NULL)

View File

@ -61,6 +61,9 @@ class Renderer
void clearLabelledStars();
float getAmbientLightLevel() const;
void setAmbientLightLevel(float);
bool getPerPixelLighting() const;
void setPerPixelLighting(bool);
bool perPixelLightingSupported() const;
typedef struct {
string text;
@ -148,6 +151,7 @@ class Renderer
int renderMode;
int labelMode;
float ambientLightLevel;
bool perPixelLightingEnabled;
vector<RenderListEntry> renderList;
vector<Particle> starParticles;

View File

@ -170,12 +170,16 @@ static Body* CreatePlanet(PlanetarySystem* system,
Surface surface;
surface.color = Color(1.0f, 1.0f, 1.0f);
planetData->getColor("Color", surface.color);
planetData->getString("Texture", surface.baseTexture);
planetData->getString("BumpMap", surface.bumpTexture);
bool applyBaseTexture = planetData->getString("Texture", surface.baseTexture);
bool applyBumpMap = planetData->getString("BumpMap", surface.bumpTexture);
bool blendTexture = false;
planetData->getBoolean("BlendTexture", blendTexture);
if (blendTexture)
surface.appearanceFlags |= Surface::BlendTexture;
if (applyBaseTexture)
surface.appearanceFlags |= Surface::ApplyBaseTexture;
if (applyBumpMap)
surface.appearanceFlags |= Surface::ApplyBumpMap;
body->setSurface(surface);
string mesh("");

View File

@ -24,7 +24,7 @@ class Surface
// Appearance flags
enum {
BlendTexture = 0x1,
ApplyDecalTexture = 0x2,
ApplyBaseTexture = 0x2,
ApplyBumpMap = 0x4,
};

View File

@ -34,3 +34,17 @@ CTexture* TextureManager::load(string name)
return tex;
}
CTexture* TextureManager::loadBumpMap(string name)
{
DPRINTF("Loading bump map: %s\n", name.c_str());
CTexture* tex = LoadTextureFromFile(baseDir + "\\" + name);
if (tex != NULL)
{
tex->normalMap(5.0f, true);
tex->bindName();
}
addResource(name, static_cast<void*>(tex));
return tex;
}

View File

@ -25,7 +25,8 @@ class TextureManager : public ResourceManager
~TextureManager();
bool find(string name, CTexture**);
CTexture* load(string name);
CTexture* load(std::string name);
CTexture* loadBumpMap(std::string name);
};
#endif // _TEXMANAGER_H_