Specular map support. This is the vast majority of the material parameters implemented at this point for opaque geometry.

meow-7.2.2
Geenz 2013-01-30 12:17:04 -05:00
parent 66a01ba4c5
commit aa1befd689
12 changed files with 78 additions and 48 deletions

View File

@ -1126,6 +1126,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("texture_gamma");
mReservedUniforms.push_back("specular_color");
mReservedUniforms.push_back("env_intensity");
llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);

View File

@ -169,6 +169,7 @@ public:
TEXTURE_GAMMA,
SPECULAR_COLOR,
ENVIRONMENT_INTENSITY,
END_RESERVED_UNIFORMS
} eGLSLReservedUniforms;

View File

@ -31,6 +31,9 @@ out vec4 frag_data[3];
uniform sampler2D diffuseMap;
uniform sampler2D bumpMap;
uniform sampler2D specularMap;
uniform float env_intensity;
uniform vec4 specular_color;
VARYING vec3 vary_mat0;
VARYING vec3 vary_mat1;
@ -42,15 +45,17 @@ VARYING vec2 vary_texcoord0;
void main()
{
vec3 col = vertex_color.rgb * texture2D(diffuseMap, vary_texcoord0.xy).rgb;
vec3 norm = texture2D(bumpMap, vary_texcoord0.xy).rgb * 2.0 - 1.0;
vec4 spec = texture2D(specularMap, vary_texcoord0.xy);
vec4 norm = texture2D(bumpMap, vary_texcoord0.xy);
norm.xyz = norm.xyz * 2 - 1;
vec3 tnorm = vec3(dot(norm,vary_mat0),
dot(norm,vary_mat1),
dot(norm,vary_mat2));
frag_data[0] = vec4(col, 0.0);
frag_data[1] = vertex_color.aaaa; // spec
vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
dot(norm.xyz,vary_mat1),
dot(norm.xyz,vary_mat2));
frag_data[0] = vec4(col * (1 - spec.a * env_intensity), 0);
frag_data[1] = vec4(spec.xyz * specular_color.xyz, specular_color.a * norm.a); // spec
//frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested
vec3 nvn = normalize(tnorm);
frag_data[2] = vec4(nvn.xyz * 0.5 + 0.5, 0.0);
frag_data[2] = vec4(nvn.xyz * 0.5 + 0.5, spec.a * env_intensity);
}

View File

@ -280,8 +280,8 @@ void main()
vec2 tc = vary_fragcoord.xy;
float depth = texture2DRect(depthMap, tc.xy).r;
vec3 pos = getPosition_d(tc, depth).xyz;
vec3 norm = texture2DRect(normalMap, tc).xyz;
norm = (norm.xyz-0.5)*2.0; // unpack norm
vec4 norm = texture2DRect(normalMap, tc);
norm.xyz = (norm.xyz-0.5)*2.0; // unpack norm
float da = max(dot(norm.xyz, sun_dir.xyz), 0.0);
@ -315,7 +315,7 @@ void main()
//add environmentmap
vec3 env_vec = env_mat * refnormpersp;
col = mix(col.rgb, samplesRGB(textureCube(environmentMap, env_vec).rgb) * 2.2,
max(spec.a-diffuse.a*2.0, 0.0));
max(norm.a-diffuse.a*2.0, 0.0));
}
col = atmosLighting(col);

View File

@ -283,8 +283,8 @@ void main()
vec2 tc = vary_fragcoord.xy;
float depth = texture2DRect(depthMap, tc.xy).r;
vec3 pos = getPosition_d(tc, depth).xyz;
vec3 norm = texture2DRect(normalMap, tc).xyz;
norm = (norm.xyz-0.5)*2.0; // unpack norm
vec4 norm = texture2DRect(normalMap, tc);
norm.xyz = (norm.xyz-0.5)*2.0; // unpack norm
float da = max(dot(norm.xyz, sun_dir.xyz), 0.0);
@ -324,7 +324,7 @@ void main()
//add environmentmap
vec3 env_vec = env_mat * refnormpersp;
col = mix(col.rgb, samplesRGB(textureCube(environmentMap, env_vec).rgb) * 2.2,
max(spec.a-diffuse.a*2.0, 0.0));
max(norm.a-diffuse.a*2.0, 0.0));
}
col = atmosLighting(col);

View File

@ -72,7 +72,7 @@ static LLGLSLShader* shader = NULL;
static S32 cube_channel = -1;
static S32 diffuse_channel = -1;
static S32 bump_channel = -1;
static S32 spec_channel = -1;
// static
void LLStandardBumpmap::init()
{
@ -634,7 +634,7 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel)
U8 bump_code = params.mBump;
if (params.mNormalMap.notNull())
{
bump_code = BE_CUSTOM;
bump_code = 99;
return bindBumpMap(bump_code, params.mNormalMap, params.mVSize, channel);
}
@ -675,7 +675,7 @@ BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsi
case BE_DARKNESS:
bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code );
break;
case BE_CUSTOM:
case 99:
bump = tex;
bump->addTextureStats(vsize);
break;
@ -828,6 +828,7 @@ void LLDrawPoolBump::beginDeferredPass(S32 pass)
gDeferredBumpProgram.bind();
diffuse_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
bump_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::BUMP_MAP);
spec_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::SPECULAR_MAP);
gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(bump_channel)->unbind(LLTexUnit::TT_TEXTURE);
}
@ -842,6 +843,7 @@ void LLDrawPoolBump::endDeferredPass(S32 pass)
mShiny = FALSE;
gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::BUMP_MAP);
gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::SPECULAR_MAP);
gDeferredBumpProgram.unbind();
gGL.getTexUnit(0)->activate();
}
@ -864,7 +866,16 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
{
LLDrawInfo& params = **i;
gDeferredBumpProgram.uniform4fv(LLShaderMgr::SPECULAR_COLOR, 4, (GLfloat*)params.mSpecColor.mV);
gDeferredBumpProgram.uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]);
gDeferredBumpProgram.uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity);
if (params.mSpecularMap)
{
params.mSpecularMap->addTextureStats(params.mVSize);
gGL.getTexUnit(spec_channel)->bind(params.mSpecularMap);
} else {
gGL.getTexUnit(spec_channel)->bind(LLViewerFetchedTexture::sWhiteImagep);
}
LLDrawPoolBump::bindBumpMap(params, bump_channel);
pushBatch(params, mask, TRUE);

View File

@ -100,9 +100,8 @@ enum EBumpEffect
BE_NO_BUMP = 0,
BE_BRIGHTNESS = 1,
BE_DARKNESS = 2,
BE_CUSTOM = 3,
BE_STANDARD_0 = 4, // Standard must always be the last one
BE_COUNT = 5
BE_STANDARD_0 = 3, // Standard must always be the last one
BE_COUNT = 4
};
////////////////////////////////////////////////////////////////

View File

@ -2077,9 +2077,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
LLFastTimer t(FTM_FACE_GEOM_BINORMAL);
mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range);
F32* binormals = (F32*) binorm.get();
mVObjp->getVolume()->genBinormals(f);
for (S32 i = 0; i < num_vertices; i++)
{
{
LLVector4a binormal;
mat_normal.rotate(vf.mBinormals[i], binormal);
binormal.normalize3fast();

View File

@ -4672,7 +4672,12 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
mGroup(NULL),
mFace(NULL),
mDistance(0.f),
mDrawMode(LLRender::TRIANGLES)
mDrawMode(LLRender::TRIANGLES),
mSpecColor(1.0f, 1.0f, 1.0f, 0.5f),
mEnvIntensity(0.0f),
mAlphaMaskCutoff(0.5f),
mDiffuseAlphaMode(0),
mMaterialID(NULL)
{
mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset);

View File

@ -4108,12 +4108,10 @@ S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost hos
S32 LLViewerObject::setTENormalMapCore(const U8 te, const LLUUID& uuid, LLHost host)
{
LL_INFOS("Materials") << "Maybe normal maps! " << uuid << LL_ENDL;
S32 retval = 0;
//if (uuid != getTE(te)->getMaterialParams()->getNormalID() ||
//uuid == LLUUID::null)
// uuid == LLUUID::null)
{
LL_INFOS("Materials") << "Normal maps! " << uuid << LL_ENDL;
retval = TEM_CHANGE_TEXTURE;
getTE(te)->getMaterialParams()->setNormalID(uuid);
mTENormalMaps[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, LLViewerTexture::BOOST_BUMP, LLViewerTexture::LOD_TEXTURE, 0, 0, host);
@ -4128,12 +4126,10 @@ S32 LLViewerObject::setTENormalMapCore(const U8 te, const LLUUID& uuid, LLHost h
S32 LLViewerObject::setTESpecularMapCore(const U8 te, const LLUUID& uuid, LLHost host)
{
LL_INFOS("Materials") << "Maybe specular maps! " << uuid << LL_ENDL;
S32 retval = 0;
if (uuid != getTE(te)->getMaterialParams()->getSpecularID() ||
uuid == LLUUID::null)
//if (uuid != getTE(te)->getMaterialParams()->getSpecularID() ||
// uuid == LLUUID::null)
{
LL_INFOS("Materials") << "Specular maps! " << uuid << LL_ENDL;
retval = TEM_CHANGE_TEXTURE;
getTE(te)->getMaterialParams()->setSpecularID(uuid);
mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host);
@ -4381,6 +4377,7 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri
{
retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams);
setTENormalMap(te, tep->getMaterialParams()->getNormalID());
setTESpecularMap(te, tep->getMaterialParams()->getSpecularID());
setChanged(TEXTURE);
if (mDrawable.notNull() && retval)
{

View File

@ -4172,12 +4172,26 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
specColor.mV[2] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightColor().mV[2] * (1.0 / 255);
specColor.mV[3] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightExponent() * (1.0 / 255);
draw_info->mSpecColor = specColor;
LL_INFOS("Materials") << "Specular Color: " << specColor << LL_ENDL;
draw_info->mEnvIntensity = facep->getTextureEntry()->getMaterialParams()->getEnvironmentIntensity() * (1.0 / 255);
draw_info->mAlphaMaskCutoff = facep->getTextureEntry()->getMaterialParams()->getAlphaMaskCutoff() * (1.0 / 255);
draw_info->mDiffuseAlphaMode = facep->getTextureEntry()->getMaterialParams()->getDiffuseAlphaMode();
draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTextureIndex());
draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTextureIndex());
}
} else {
U8 shiny = facep->getTextureEntry()->getShiny();
float alpha[4] =
{
0.00f,
0.25f,
0.5f,
0.75f
};
float spec = alpha[shiny];
LLVector4 specColor(spec, spec, spec, spec);
draw_info->mSpecColor = specColor;
draw_info->mEnvIntensity = spec;
}
if (type == LLRenderPass::PASS_ALPHA)
@ -4631,7 +4645,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
if (gPipeline.canUseWindLightShadersOnObjects()
&& LLPipeline::sRenderBump)
{
if (te->getBumpmap())
if (te->getBumpmap() || te->getMaterialParams() != NULL)
{ //needs normal + binormal
bump_faces.push_back(facep);
}
@ -5237,7 +5251,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
}
else
{
if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && (te->getBumpmap() || te->getMaterialParams() != NULL))
if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && (te->getBumpmap() || te->getMaterialParams()))
{ //non-shiny or fullbright deferred bump
registerFace(group, facep, LLRenderPass::PASS_BUMP);
}

View File

@ -1262,31 +1262,26 @@ void LLPipeline::createLUTBuffers()
U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
F32* ls = new F32[lightResX*lightResY];
//F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); // Note: only use this when creating new specular lighting functions.
// Calculate the (normalized) Gaussian specular lookup texture. (with a few tweaks)
// Calculate the (normalized) blinn-phong specular lookup texture. (with a few tweaks)
for (U32 y = 0; y < lightResY; ++y)
{
for (U32 x = 0; x < lightResX; ++x)
{
ls[y*lightResX+x] = 0;
F32 sa = (F32) x/(lightResX-1);
F32 spec = (F32) y/(lightResY);
F32 n = spec;
F32 spec = (F32) y/(lightResY-1);
F32 n = spec * spec * 368;
float angleNormalHalf = acosf(sa);
float exponent = angleNormalHalf / ((1 - n));
exponent = -(exponent * exponent);
spec = expf(exponent);
// Nothing special here. Just your typical blinn-phong term.
spec = powf(sa, n);
// Apply our normalization function.
// This is based around the phong normalization function, trading n+2 for n+1 instead.
// Since we're using a gaussian model here, we actually don't really need as large of an exponent as blinn-phong shading.
// Instead, we assume that the correct exponent is 8 here.
// This was achieved through much tweaking to find a decent "middleground" with our specular highlights with the gaussian term.
// Bigger highlights don't look too soft, smaller highlights don't look too bright, and everything in the middle seems to have a well maintained highlight curvature.
// There isn't really much theory behind this one. This was done purely to produce a nice and mostly customizable BRDF.
spec = lerpf(spec, spec * (n * 8 + 1) / 4.5, n);
// Note: This is the full equation that applies the full normalization curve, not an approximation.
// This is fine, given we only need to create our LUT once per buffer initialization.
spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n)));
// Since we use R16F, we no longer have a dynamic range issue we need to work around here.
// Though some older drivers may not like this, newer drivers shouldn't have this problem.
ls[y*lightResX+x] = spec;
}
}