diff --git a/src/celengine/rendcontext.cpp b/src/celengine/rendcontext.cpp index 616a146bc..e805252ce 100644 --- a/src/celengine/rendcontext.cpp +++ b/src/celengine/rendcontext.cpp @@ -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* 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; diff --git a/src/celengine/renderglsl.cpp b/src/celengine/renderglsl.cpp index fcc0a32bf..62fae8b85 100644 --- a/src/celengine/renderglsl.cpp +++ b/src/celengine/renderglsl.cpp @@ -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++) { diff --git a/src/celengine/shadermanager.cpp b/src/celengine/shadermanager.cpp index 73d491900..d1f97d8d5 100644 --- a/src/celengine/shadermanager.cpp +++ b/src/celengine/shadermanager.cpp @@ -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(); } diff --git a/src/celengine/shadermanager.h b/src/celengine/shadermanager.h index 93331b1c0..ad2233120 100644 --- a/src/celengine/shadermanager.h +++ b/src/celengine/shadermanager.h @@ -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);