- Added support for emissive color to OpenGL 2.0 render path

- Eliminated code for Lommel-Seeliger photometric model, since it's just a special case of the more general Lunar-Lambert model.
- Cleaned up GLSL_RenderContext so it uses the light and shadow functions in the shader manager
ver1_5_1
Chris Laurel 2006-09-03 23:22:07 +00:00
parent b5a18b1710
commit 54d5de0563
4 changed files with 36 additions and 148 deletions

View File

@ -402,125 +402,6 @@ GLSL_RenderContext::initLightingEnvironment()
}
}
// TODO: eliminate this and use CelestiaGLProgram::setLightingParameters instead
void
GLSL_RenderContext::setLightingParameters(CelestiaGLProgram& prog, Color materialDiffuse, Color materialSpecular)
{
unsigned int nLights = min(MaxShaderLights, lightingState.nLights);
Vec3f diffuseColor(materialDiffuse.red(),
materialDiffuse.green(),
materialDiffuse.blue());
Vec3f specularColor(materialSpecular.red(),
materialSpecular.green(),
materialSpecular.blue());
for (unsigned int i = 0; i < nLights; i++)
{
const DirectionalLight& light = lightingState.lights[i];
Vec3f lightColor = Vec3f(light.color.red(),
light.color.green(),
light.color.blue()) * light.irradiance;
prog.lights[i].direction = light.direction_obj;
if (shaderProps.usesShadows() ||
shaderProps.usesFragmentLighting() ||
shaderProps.lightModel == ShaderProperties::RingIllumModel)
{
prog.fragLightColor[i] = Vec3f(lightColor.x * diffuseColor.x,
lightColor.y * diffuseColor.y,
lightColor.z * diffuseColor.z);
if (shaderProps.hasSpecular())
{
prog.fragLightSpecColor[i] = Vec3f(lightColor.x * specularColor.x,
lightColor.y * specularColor.y,
lightColor.z * specularColor.z);
}
}
else
{
prog.lights[i].diffuse = Vec3f(lightColor.x * diffuseColor.x,
lightColor.y * diffuseColor.y,
lightColor.z * diffuseColor.z);
}
prog.lights[i].specular = Vec3f(lightColor.x * specularColor.x,
lightColor.y * specularColor.y,
lightColor.z * specularColor.z);
Vec3f halfAngle_obj = lightingState.eyeDir_obj + light.direction_obj;
if (halfAngle_obj.length() != 0.0f)
halfAngle_obj.normalize();
prog.lights[i].halfVector = halfAngle_obj;
}
prog.eyePosition = lightingState.eyePos_obj;
prog.ambientColor = Vec3f(lightingState.ambientColor.x * diffuseColor.x,
lightingState.ambientColor.y * diffuseColor.y,
lightingState.ambientColor.z * diffuseColor.z);
prog.opacity = materialDiffuse.alpha();
}
// TODO: eliminate this and use CelestiaGLProgram::setShadowParameters instead
void
GLSL_RenderContext::setShadowParameters(CelestiaGLProgram& prog)
{
// TODO: this code is largely a copy of some code in render.cpp; we should
// have just a single instance of the code.
for (unsigned int li = 0;
li < min(lightingState.nLights, MaxShaderLights);
li++)
{
vector<EclipseShadow>* shadows = lightingState.shadows[li];
if (shadows != NULL)
{
unsigned int nShadows = min((size_t) MaxShaderShadows,
shadows->size());
for (unsigned int i = 0; i < nShadows; i++)
{
EclipseShadow& shadow = shadows->at(i);
CelestiaGLProgramShadow& shadowParams = prog.shadows[li][i];
float R2 = 0.25f;
float umbra = shadow.umbraRadius / shadow.penumbraRadius;
umbra = umbra * umbra;
if (umbra < 0.0001f)
umbra = 0.0001f;
else if (umbra > 0.99f)
umbra = 0.99f;
float umbraRadius = R2 * umbra;
float penumbraRadius = R2;
float shadowBias = 1.0f / (1.0f - penumbraRadius / umbraRadius);
shadowParams.bias = shadowBias;
shadowParams.scale = -shadowBias / umbraRadius;
// Compute the transformation to use for generating texture
// coordinates from the object vertices.
Point3f origin = shadow.origin * xform;
Vec3f dir = shadow.direction * xform;
float scale = objRadius / shadow.penumbraRadius;
Vec3f axis = Vec3f(0, 1, 0) ^ dir;
float angle = (float) acos(Vec3f(0, 1, 0) * dir);
axis.normalize();
Mat4f mat = Mat4f::rotation(axis, -angle);
Vec3f sAxis = Vec3f(0.5f * scale, 0, 0) * mat;
Vec3f tAxis = Vec3f(0, 0, 0.5f * scale) * mat;
float sw = (Point3f(0, 0, 0) - origin) * sAxis / objRadius + 0.5f;
float tw = (Point3f(0, 0, 0) - origin) * tAxis / objRadius + 0.5f;
shadowParams.texGenS = Vec4f(sAxis.x, sAxis.y, sAxis.z, sw);
shadowParams.texGenT = Vec4f(tAxis.x, tAxis.y, tAxis.z, tw);
}
}
}
}
void
@ -609,9 +490,9 @@ GLSL_RenderContext::makeCurrent(const Mesh::Material& m)
textures[i]->bind();
}
setLightingParameters(*prog, m.diffuse, m.specular);
prog->setLightParameters(lightingState, m.diffuse, m.specular, m.emissive);
if (shaderProps.shadowCounts != 0)
setShadowParameters(*prog);
prog->setEclipseShadowParameters(lightingState, objRadius, xform);
// TODO: handle emissive color
prog->shininess = m.specularPower;

View File

@ -185,7 +185,7 @@ void renderSphere_GLSL(const RenderInfo& ri,
prog->use();
prog->setLightParameters(ls, ri.color, ri.specularColor);
prog->setLightParameters(ls, ri.color, ri.specularColor, Color::Black);
prog->eyePosition = ls.eyePos_obj;
prog->shininess = ri.specularPower;
@ -363,7 +363,7 @@ void renderClouds_GLSL(const RenderInfo& ri,
prog->use();
prog->setLightParameters(ls, ri.color, ri.specularColor);
prog->setLightParameters(ls, ri.color, ri.specularColor, Color::Black);
prog->eyePosition = ls.eyePos_obj;
prog->ambientColor = Vec3f(ri.ambientColor.red(), ri.ambientColor.green(),
ri.ambientColor.blue());
@ -427,7 +427,7 @@ renderAtmosphere_GLSL(const RenderInfo& ri,
prog->use();
prog->setLightParameters(ls, ri.color, ri.specularColor);
prog->setLightParameters(ls, ri.color, ri.specularColor, Color::Black);
prog->ambientColor = Vec3f(0.0f, 0.0f, 0.0f);
float atmosphereRadius = radius + -atmosphere->mieScaleHeight * (float) log(AtmosphereExtinctionThreshold);
@ -534,7 +534,7 @@ void renderRings_GLSL(RingSystem& rings,
prog->eyePosition = ls.eyePos_obj;
prog->ambientColor = Vec3f(ri.ambientColor.red(), ri.ambientColor.green(),
ri.ambientColor.blue());
prog->setLightParameters(ls, ri.color, ri.specularColor);
prog->setLightParameters(ls, ri.color, ri.specularColor, Color::Black);
for (unsigned int li = 0; li < ls.nLights; li++)
{

View File

@ -46,7 +46,8 @@ ShaderProperties::ShaderProperties() :
nLights(0),
texUsage(0),
lightModel(DiffuseModel),
shadowCounts(0)
shadowCounts(0),
effects(0)
{
}
@ -165,6 +166,11 @@ bool operator<(const ShaderProperties& p0, const ShaderProperties& p1)
return true;
else if (p1.shadowCounts < p0.shadowCounts)
return false;
if (p0.effects < p1.effects)
return true;
else if (p1.effects < p0.effects)
return false;
return (p0.lightModel < p1.lightModel);
}
@ -497,10 +503,6 @@ AddDirectionalLightContrib(unsigned int i, const ShaderProperties& props)
source += "diff.rgb += " + LightProperty(i, "diffuse") + " * d;\n";
}
}
else if (props.lightModel == ShaderProperties::LommelSeeligerModel)
{
source += AssignDiffuse(i, props) + " NL / (max(NV, 0.001) + NL);\n";
}
else if (props.lightModel == ShaderProperties::LunarLambertModel)
{
source += AssignDiffuse(i, props) + " mix(NL, NL / (max(NV, 0.001) + NL), lunarLambert);\n";
@ -922,7 +924,7 @@ ShaderManager::buildVertexShader(const ShaderProperties& props)
}
else
{
source += "uniform vec3 ambientColor;\n";
source += "uniform vec3 ambientColor;\n";
source += "uniform float opacity;\n";
source += "varying vec4 diff;\n";
if (props.lightModel == ShaderProperties::SpecularModel)
@ -1349,8 +1351,7 @@ ShaderManager::buildFragmentShader(const ShaderProperties& props)
source += "vec3 H;\n";
source += "float NH;\n";
}
else if (props.lightModel == ShaderProperties::LommelSeeligerModel ||
props.lightModel == ShaderProperties::LunarLambertModel)
else if (props.lightModel == ShaderProperties::LunarLambertModel)
{
source += "float NV = dot(n, V);\n";
}
@ -1365,12 +1366,7 @@ ShaderManager::buildFragmentShader(const ShaderProperties& props)
// geometry like planet spheres.)
// source += LightDir_tan(i) + " = normalize(" + LightDir(i)_tan + ");\n";
source += "NL = dot(" + LightDir_tan(i) + ", n);\n";
if (props.lightModel == ShaderProperties::LommelSeeligerModel)
{
source += "NL = max(0.0, NL);\n";
source += "l = (NL / (max(NV, 0.001) + NL)) * clamp(" + LightDir_tan(i) + ".z * 8.0, 0.0, 1.0);\n";
}
else if (props.lightModel == ShaderProperties::LunarLambertModel)
if (props.lightModel == ShaderProperties::LunarLambertModel)
{
source += "NL = max(0.0, NL);\n";
source += "l = mix(NL, (NL / (max(NV, 0.001) + NL)), lunarLambert) * clamp(" + LightDir_tan(i) + ".z * 8.0, 0.0, 1.0);\n";
@ -2010,7 +2006,8 @@ CelestiaGLProgram::initSamplers()
void
CelestiaGLProgram::setLightParameters(const LightingState& ls,
Color materialDiffuse,
Color materialSpecular)
Color materialSpecular,
Color materialEmissive)
{
unsigned int nLights = min(MaxShaderLights, ls.nLights);
@ -2062,9 +2059,9 @@ CelestiaGLProgram::setLightParameters(const LightingState& ls,
}
eyePosition = ls.eyePos_obj;
ambientColor = Vec3f(ls.ambientColor.x * diffuseColor.x,
ls.ambientColor.y * diffuseColor.y,
ls.ambientColor.z * diffuseColor.z);
ambientColor = Vec3f(ls.ambientColor.x * diffuseColor.x + materialEmissive.red(),
ls.ambientColor.y * diffuseColor.y + materialEmissive.green(),
ls.ambientColor.z * diffuseColor.z + materialEmissive.blue());
opacity = materialDiffuse.alpha();
}

View File

@ -53,18 +53,27 @@ class ShaderProperties
RingIllumModel = 2,
PerPixelSpecularModel = 3,
OrenNayarModel = 4,
LommelSeeligerModel = 5,
AtmosphereModel = 6,
LunarLambertModel = 7,
AtmosphereModel = 5,
LunarLambertModel = 6,
};
enum
{
VolumetricScatteringEffect = 0x0001,
VolumetricAbsorptionEffect = 0x0002,
VolumetricEmissionEffect = 0x0004,
};
public:
unsigned short nLights;
unsigned short texUsage;
unsigned short texUsage;
unsigned short lightModel;
// Two bits per light, up to eight lights + three shadows per light
unsigned short shadowCounts;
// Effects that may be applied with any light model
unsigned short effects;
};
@ -96,7 +105,8 @@ class CelestiaGLProgram
void setLightParameters(const LightingState& ls,
Color materialDiffuse,
Color materialSpecular);
Color materialSpecular,
Color materialEmissive);
void setEclipseShadowParameters(const LightingState& ls,
float planetRadius,
const Mat4f& planetMat);