SL-17283 LLReflectionMapManager prototype. Remove snapshot code related overhead from reflection map renders. Add parallax correction and support for multiple reflection maps.
parent
82311e4b44
commit
93260cfeff
|
|
@ -166,6 +166,19 @@ void LLCubeMap::init(const std::vector<LLPointer<LLImageRaw> >& rawimages)
|
|||
}
|
||||
}
|
||||
|
||||
void LLCubeMap::initReflectionMap(U32 resolution, U32 components)
|
||||
{
|
||||
U32 texname = 0;
|
||||
|
||||
LLImageGL::generateTextures(1, &texname);
|
||||
|
||||
mImages[0] = new LLImageGL(resolution, resolution, components, TRUE);
|
||||
mImages[0]->setTexName(texname);
|
||||
mImages[0]->setTarget(mTargets[0], LLTexUnit::TT_CUBE_MAP);
|
||||
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
|
||||
mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
|
||||
}
|
||||
|
||||
void LLCubeMap::initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& rawimages)
|
||||
{
|
||||
llassert(rawimages.size() == 6);
|
||||
|
|
@ -203,6 +216,19 @@ void LLCubeMap::initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& ra
|
|||
disable();
|
||||
}
|
||||
|
||||
void LLCubeMap::generateMipMaps()
|
||||
{
|
||||
mImages[0]->setUseMipMaps(TRUE);
|
||||
mImages[0]->setHasMipMaps(TRUE);
|
||||
enableTexture(0);
|
||||
bind();
|
||||
mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
|
||||
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
||||
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||
gGL.getTexUnit(0)->disable();
|
||||
disable();
|
||||
}
|
||||
|
||||
GLuint LLCubeMap::getGLName()
|
||||
{
|
||||
return mImages[0]->getTexName();
|
||||
|
|
|
|||
|
|
@ -41,11 +41,15 @@ public:
|
|||
LLCubeMap(bool init_as_srgb);
|
||||
void init(const std::vector<LLPointer<LLImageRaw> >& rawimages);
|
||||
|
||||
// initialize as an undefined cubemap at the given resolution
|
||||
// used for render-to-cubemap operations
|
||||
// avoids usage of LLImageRaw
|
||||
void initReflectionMap(U32 resolution, U32 components = 3);
|
||||
|
||||
// init from environment map images
|
||||
// Similar to init, but takes ownership of rawimages and makes this cubemap
|
||||
// respect the resolution of rawimages
|
||||
// Raw images must point to array of six square images that are all the same resolution
|
||||
// For example usage, see LLEnvironmentMap
|
||||
void initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& rawimages);
|
||||
void initGL();
|
||||
void initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages);
|
||||
|
|
@ -62,6 +66,12 @@ public:
|
|||
void setMatrix(S32 stage);
|
||||
void restoreMatrix();
|
||||
|
||||
U32 getResolution() { return mImages[0].notNull() ? mImages[0]->getWidth(0) : 0; }
|
||||
|
||||
// generate mip maps for this Cube Map using GL
|
||||
// NOTE: Cube Map MUST already be resident in VRAM
|
||||
void generateMipMaps();
|
||||
|
||||
GLuint getGLName();
|
||||
|
||||
void destroyGL();
|
||||
|
|
|
|||
|
|
@ -738,7 +738,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
|
|||
{
|
||||
//found it
|
||||
mUniform[i] = location;
|
||||
mTexture[i] = mapUniformTextureChannel(location, type);
|
||||
mTexture[i] = mapUniformTextureChannel(location, type, size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -752,7 +752,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
|
|||
{
|
||||
//found it
|
||||
mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location;
|
||||
mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type);
|
||||
mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type, size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -775,16 +775,37 @@ void LLGLSLShader::removePermutation(std::string name)
|
|||
mDefines[name].erase();
|
||||
}
|
||||
|
||||
GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
|
||||
GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint size)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
|
||||
if ((type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) ||
|
||||
type == GL_SAMPLER_2D_MULTISAMPLE)
|
||||
{ //this here is a texture
|
||||
glUniform1iARB(location, mActiveTextureChannels);
|
||||
LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
|
||||
return mActiveTextureChannels++;
|
||||
GLint ret = mActiveTextureChannels;
|
||||
if (size == 1)
|
||||
{
|
||||
glUniform1iARB(location, mActiveTextureChannels);
|
||||
LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
|
||||
mActiveTextureChannels++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//is array of textures, make sequential after this texture
|
||||
GLint channel[32]; // <=== only support up to 32 texture channels
|
||||
llassert(size <= 32);
|
||||
size = llmin(size, 32);
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
channel[i] = mActiveTextureChannels++;
|
||||
}
|
||||
glUniform1ivARB(location, size, channel);
|
||||
LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " <<
|
||||
(mActiveTextureChannels-size) << " through " << (mActiveTextureChannels-1) << LL_ENDL;
|
||||
}
|
||||
|
||||
llassert(mActiveTextureChannels <= 32); // too many textures (probably)
|
||||
return ret;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ public:
|
|||
GLint getUniformLocation(U32 index);
|
||||
|
||||
GLint getAttribLocation(U32 attrib);
|
||||
GLint mapUniformTextureChannel(GLint location, GLenum type);
|
||||
GLint mapUniformTextureChannel(GLint location, GLenum type, GLint size);
|
||||
|
||||
void clearPermutations();
|
||||
void addPermutation(std::string name, std::string value);
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ public:
|
|||
|
||||
BOOL getUseMipMaps() const { return mUseMipMaps; }
|
||||
void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; }
|
||||
|
||||
void setHasMipMaps(BOOL hasmips) { mHasMipMaps = hasmips; }
|
||||
void updatePickMask(S32 width, S32 height, const U8* data_in);
|
||||
BOOL getMask(const LLVector2 &tc);
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ void LLRenderTarget::resize(U32 resx, U32 resy)
|
|||
|
||||
bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize);
|
||||
resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize);
|
||||
|
||||
|
|
@ -219,6 +220,7 @@ void LLRenderTarget::releaseColorAttachment()
|
|||
|
||||
bool LLRenderTarget::addColorAttachment(U32 color_fmt)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
if (color_fmt == 0)
|
||||
{
|
||||
return true;
|
||||
|
|
@ -315,6 +317,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
|
|||
|
||||
bool LLRenderTarget::allocateDepth()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
if (mStencil)
|
||||
{
|
||||
//use render buffers where stencil buffers are in play
|
||||
|
|
@ -395,6 +398,7 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
|
|||
|
||||
void LLRenderTarget::release()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
if (mDepth)
|
||||
{
|
||||
if (mStencil)
|
||||
|
|
|
|||
|
|
@ -196,7 +196,6 @@ set(viewer_SOURCE_FILES
|
|||
lldynamictexture.cpp
|
||||
llemote.cpp
|
||||
llenvironment.cpp
|
||||
llenvironmentmap.cpp
|
||||
llestateinfomodel.cpp
|
||||
lleventnotifier.cpp
|
||||
lleventpoll.cpp
|
||||
|
|
@ -546,6 +545,8 @@ set(viewer_SOURCE_FILES
|
|||
llproductinforequest.cpp
|
||||
llprogressview.cpp
|
||||
llrecentpeople.cpp
|
||||
llreflectionmap.cpp
|
||||
llreflectionmapmanager.cpp
|
||||
llregioninfomodel.cpp
|
||||
llregionposition.cpp
|
||||
llremoteparcelrequest.cpp
|
||||
|
|
@ -833,7 +834,6 @@ set(viewer_HEADER_FILES
|
|||
lldynamictexture.h
|
||||
llemote.h
|
||||
llenvironment.h
|
||||
llenvironmentmap.h
|
||||
llestateinfomodel.h
|
||||
lleventnotifier.h
|
||||
lleventpoll.h
|
||||
|
|
@ -1171,6 +1171,8 @@ set(viewer_HEADER_FILES
|
|||
llproductinforequest.h
|
||||
llprogressview.h
|
||||
llrecentpeople.h
|
||||
llreflectionmap.h
|
||||
llreflectionmapmanager.h
|
||||
llregioninfomodel.h
|
||||
llregionposition.h
|
||||
llremoteparcelrequest.h
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
/*[EXTRA_CODE_HERE]*/
|
||||
|
||||
#define REFMAP_COUNT 8
|
||||
|
||||
#ifdef DEFINE_GL_FRAGCOLOR
|
||||
out vec4 frag_color;
|
||||
#else
|
||||
|
|
@ -40,9 +42,13 @@ uniform sampler2DRect normalMap;
|
|||
uniform sampler2DRect lightMap;
|
||||
uniform sampler2DRect depthMap;
|
||||
uniform samplerCube environmentMap;
|
||||
uniform samplerCube reflectionMap;
|
||||
uniform samplerCube reflectionMap[REFMAP_COUNT];
|
||||
uniform sampler2D lightFunc;
|
||||
|
||||
uniform int refmapCount;
|
||||
|
||||
uniform vec3 refOrigin[REFMAP_COUNT];
|
||||
|
||||
uniform float blur_size;
|
||||
uniform float blur_fidelity;
|
||||
|
||||
|
|
@ -74,8 +80,136 @@ vec3 srgb_to_linear(vec3 c);
|
|||
vec4 applyWaterFogView(vec3 pos, vec4 color);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// from https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection
|
||||
|
||||
// original reference implementation:
|
||||
/*
|
||||
bool intersect(const Ray &ray) const
|
||||
{
|
||||
float t0, t1; // solutions for t if the ray intersects
|
||||
#if 0
|
||||
// geometric solution
|
||||
Vec3f L = center - orig;
|
||||
float tca = L.dotProduct(dir);
|
||||
// if (tca < 0) return false;
|
||||
float d2 = L.dotProduct(L) - tca * tca;
|
||||
if (d2 > radius2) return false;
|
||||
float thc = sqrt(radius2 - d2);
|
||||
t0 = tca - thc;
|
||||
t1 = tca + thc;
|
||||
#else
|
||||
// analytic solution
|
||||
Vec3f L = orig - center;
|
||||
float a = dir.dotProduct(dir);
|
||||
float b = 2 * dir.dotProduct(L);
|
||||
float c = L.dotProduct(L) - radius2;
|
||||
if (!solveQuadratic(a, b, c, t0, t1)) return false;
|
||||
#endif
|
||||
if (t0 > t1) std::swap(t0, t1);
|
||||
|
||||
if (t0 < 0) {
|
||||
t0 = t1; // if t0 is negative, let's use t1 instead
|
||||
if (t0 < 0) return false; // both t0 and t1 are negative
|
||||
}
|
||||
|
||||
t = t0;
|
||||
|
||||
return true;
|
||||
} */
|
||||
|
||||
// adapted -- assume that origin is inside sphere, return distance from origin to edge of sphere
|
||||
float sphereIntersect(vec3 origin, vec3 dir, vec4 sph )
|
||||
{
|
||||
float t0, t1; // solutions for t if the ray intersects
|
||||
|
||||
vec3 center = sph.xyz;
|
||||
float radius2 = sph.w * sph.w;
|
||||
|
||||
vec3 L = center - origin;
|
||||
float tca = dot(L,dir);
|
||||
|
||||
float d2 = dot(L,L) - tca * tca;
|
||||
|
||||
float thc = sqrt(radius2 - d2);
|
||||
t0 = tca - thc;
|
||||
t1 = tca + thc;
|
||||
|
||||
return t1;
|
||||
}
|
||||
|
||||
vec3 sampleRefMap(vec3 pos, vec3 dir, float lod)
|
||||
{
|
||||
float wsum = 0.0;
|
||||
|
||||
vec3 col = vec3(0,0,0);
|
||||
|
||||
for (int i = 0; i < refmapCount; ++i)
|
||||
//int i = 0;
|
||||
{
|
||||
float r = 16.0;
|
||||
vec3 delta = pos.xyz-refOrigin[i].xyz;
|
||||
if (length(delta) < r)
|
||||
{
|
||||
float w = 1.0/max(dot(delta, delta), r);
|
||||
w *= w;
|
||||
w *= w;
|
||||
|
||||
// parallax adjustment
|
||||
float d = sphereIntersect(pos, dir, vec4(refOrigin[i].xyz, r));
|
||||
|
||||
{
|
||||
vec3 v = pos + dir * d;
|
||||
v -= refOrigin[i].xyz;
|
||||
v = env_mat * v;
|
||||
|
||||
float min_lod = textureQueryLod(reflectionMap[i],v).y; // lower is higher res
|
||||
col += textureLod(reflectionMap[i], v, max(min_lod, lod)).rgb*w;
|
||||
wsum += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wsum > 0.0)
|
||||
{
|
||||
col *= 1.0/wsum;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this pixel not covered by a probe, fallback to "full scene" environment map
|
||||
vec3 v = env_mat * dir;
|
||||
float min_lod = textureQueryLod(environmentMap, v).y; // lower is higher res
|
||||
col = textureLod(environmentMap, v, max(min_lod, lod)).rgb;
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 sampleAmbient(vec3 pos, vec3 dir, float lod)
|
||||
{
|
||||
vec3 col = sampleRefMap(pos, dir, lod);
|
||||
|
||||
//desaturate
|
||||
vec3 hcol = col *0.5;
|
||||
|
||||
col *= 2.0;
|
||||
col = vec3(
|
||||
col.r + hcol.g + hcol.b,
|
||||
col.g + hcol.r + hcol.b,
|
||||
col.b + hcol.r + hcol.g
|
||||
);
|
||||
|
||||
col *= 0.333333;
|
||||
|
||||
return col*0.6; // fudge darker
|
||||
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float reflection_lods = 11; // TODO -- base this on resolution of reflection map instead of hard coding
|
||||
|
||||
vec2 tc = vary_fragcoord.xy;
|
||||
float depth = texture2DRect(depthMap, tc.xy).r;
|
||||
vec4 pos = getPositionWithDepth(tc, depth);
|
||||
|
|
@ -106,25 +240,29 @@ void main()
|
|||
vec3 atten;
|
||||
calcAtmosphericVars(pos.xyz, light_dir, ambocc, sunlit, amblit, additive, atten, true);
|
||||
|
||||
color.rgb = amblit;
|
||||
//vec3 amb_vec = env_mat * norm.xyz;
|
||||
|
||||
float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
|
||||
ambient *= 0.5;
|
||||
ambient *= ambient;
|
||||
ambient = (1.0 - ambient);
|
||||
color.rgb *= ambient;
|
||||
vec3 ambenv = sampleAmbient(pos.xyz, norm.xyz, reflection_lods-1);
|
||||
amblit = mix(ambenv, amblit, amblit);
|
||||
color.rgb = amblit;
|
||||
|
||||
|
||||
//float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
|
||||
//ambient *= 0.5;
|
||||
//ambient *= ambient;
|
||||
//ambient = (1.0 - ambient);
|
||||
//color.rgb *= ambient;
|
||||
|
||||
vec3 sun_contrib = min(da, scol) * sunlit;
|
||||
color.rgb += sun_contrib;
|
||||
color.rgb *= diffuse.rgb;
|
||||
|
||||
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
|
||||
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
|
||||
|
||||
vec3 env_vec = env_mat * refnormpersp;
|
||||
|
||||
if (spec.a > 0.0) // specular reflection
|
||||
{
|
||||
float sa = dot(refnormpersp, light_dir.xyz);
|
||||
float sa = dot(normalize(refnormpersp), light_dir.xyz);
|
||||
vec3 dumbshiny = sunlit * scol * (texture2D(lightFunc, vec2(sa, spec.a)).r);
|
||||
|
||||
// add the two types of shiny together
|
||||
|
|
@ -133,28 +271,30 @@ void main()
|
|||
color.rgb += spec_contrib;
|
||||
|
||||
// add reflection map - EXPERIMENTAL WORK IN PROGRESS
|
||||
float reflection_lods = 11; // TODO -- base this on resolution of reflection map instead of hard coding
|
||||
float min_lod = textureQueryLod(reflectionMap,env_vec).y; // lower is higher res
|
||||
|
||||
//vec3 reflected_color = texture(reflectionMap, env_vec, (1.0-spec.a)*reflection_lod).rgb;
|
||||
vec3 reflected_color = textureLod(reflectionMap, env_vec, max(min_lod, (1.0-spec.a)*reflection_lods)).rgb;
|
||||
//vec3 reflected_color = texture(reflectionMap, env_vec).rgb;
|
||||
//vec3 reflected_color = normalize(env_vec)*0.5+0.5;
|
||||
reflected_color *= spec.rgb;
|
||||
|
||||
float lod = (1.0-spec.a)*reflection_lods;
|
||||
vec3 reflected_color = sampleRefMap(pos.xyz, normalize(refnormpersp), lod);
|
||||
reflected_color *= 0.5; // fudge darker, not sure where there's a multiply by two and it's late
|
||||
float fresnel = 1.0+dot(normalize(pos.xyz), norm.xyz);
|
||||
fresnel += spec.a;
|
||||
fresnel *= fresnel;
|
||||
//fresnel *= spec.a;
|
||||
reflected_color *= spec.rgb*min(fresnel, 1.0);
|
||||
//reflected_color = srgb_to_linear(reflected_color);
|
||||
vec3 mixer = clamp(color.rgb + vec3(1,1,1) - spec.rgb, vec3(0,0,0), vec3(1,1,1));
|
||||
|
||||
color.rgb = mix(reflected_color*sqrt(spec.a*0.8), color, mixer);
|
||||
|
||||
//color.rgb = mix(reflected_color * spec.rgb * sqrt(spec.a*0.8), color.rgb, color.rgb);
|
||||
//color.rgb += reflected_color * spec.rgb; // * sqrt(spec.a*0.8), color.rgb, color.rgb);
|
||||
color.rgb = mix(reflected_color, color, mixer);
|
||||
}
|
||||
|
||||
color.rgb = mix(color.rgb, diffuse.rgb, diffuse.a);
|
||||
|
||||
if (envIntensity > 0.0)
|
||||
{ // add environmentmap
|
||||
vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
|
||||
color = mix(color.rgb, reflected_color, envIntensity);
|
||||
vec3 reflected_color = sampleRefMap(pos.xyz, normalize(refnormpersp), 0.0);
|
||||
float fresnel = 1.0+dot(normalize(pos.xyz), norm.xyz);
|
||||
fresnel *= fresnel;
|
||||
fresnel = fresnel * 0.95 + 0.05;
|
||||
reflected_color *= fresnel;
|
||||
color = mix(color.rgb, reflected_color, envIntensity);
|
||||
}
|
||||
|
||||
if (norm.w < 0.5)
|
||||
|
|
@ -172,6 +312,4 @@ void main()
|
|||
// convert to linear as fullscreen lights need to sum in linear colorspace
|
||||
// and will be gamma (re)corrected downstream...
|
||||
frag_color.rgb = srgb_to_linear(color.rgb);
|
||||
//frag_color.r = 1.0;
|
||||
frag_color.a = bloom;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1512,22 +1512,23 @@ bool LLAppViewer::doFrame()
|
|||
|
||||
// Render scene.
|
||||
// *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
|
||||
if (!LLApp::isExiting() && !gHeadlessClient && gViewerWindow)
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df Display" )
|
||||
pingMainloopTimeout("Main:Display");
|
||||
gGLActive = TRUE;
|
||||
if (!LLApp::isExiting() && !gHeadlessClient && gViewerWindow)
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Display");
|
||||
pingMainloopTimeout("Main:Display");
|
||||
gGLActive = TRUE;
|
||||
|
||||
display();
|
||||
display();
|
||||
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df Snapshot" )
|
||||
pingMainloopTimeout("Main:Snapshot");
|
||||
LLFloaterSnapshot::update(); // take snapshots
|
||||
LLFloaterOutfitSnapshot::update();
|
||||
gGLActive = FALSE;
|
||||
}
|
||||
}
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Snapshot");
|
||||
pingMainloopTimeout("Main:Snapshot");
|
||||
gPipeline.mReflectionMapManager.update();
|
||||
LLFloaterSnapshot::update(); // take snapshots
|
||||
LLFloaterOutfitSnapshot::update();
|
||||
gGLActive = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,116 +0,0 @@
|
|||
/**
|
||||
* @file llenvironmentmap.cpp
|
||||
* @brief LLEnvironmentMap class implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2022, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llenvironmentmap.h"
|
||||
#include "pipeline.h"
|
||||
#include "llviewerwindow.h"
|
||||
|
||||
LLEnvironmentMap::LLEnvironmentMap()
|
||||
{
|
||||
mOrigin.setVec(0, 0, 0);
|
||||
}
|
||||
|
||||
void LLEnvironmentMap::update(const LLVector3& origin, U32 resolution)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
|
||||
mOrigin = origin;
|
||||
|
||||
// allocate images
|
||||
std::vector<LLPointer<LLImageRaw> > rawimages;
|
||||
rawimages.reserve(6);
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
rawimages.push_back(new LLImageRaw(resolution, resolution, 3));
|
||||
}
|
||||
|
||||
// ============== modified copy/paste of LLFloater360Capture::capture360Images() follows ==============
|
||||
|
||||
// these are the 6 directions we will point the camera, see LLCubeMap::mTargets
|
||||
LLVector3 look_dirs[6] = {
|
||||
LLVector3(-1, 0, 0),
|
||||
LLVector3(1, 0, 0),
|
||||
LLVector3(0, -1, 0),
|
||||
LLVector3(0, 1, 0),
|
||||
LLVector3(0, 0, -1),
|
||||
LLVector3(0, 0, 1)
|
||||
};
|
||||
|
||||
LLVector3 look_upvecs[6] = {
|
||||
LLVector3(0, -1, 0),
|
||||
LLVector3(0, -1, 0),
|
||||
LLVector3(0, 0, -1),
|
||||
LLVector3(0, 0, 1),
|
||||
LLVector3(0, -1, 0),
|
||||
LLVector3(0, -1, 0)
|
||||
};
|
||||
|
||||
// save current view/camera settings so we can restore them afterwards
|
||||
S32 old_occlusion = LLPipeline::sUseOcclusion;
|
||||
|
||||
// set new parameters specific to the 360 requirements
|
||||
LLPipeline::sUseOcclusion = 0;
|
||||
LLViewerCamera* camera = LLViewerCamera::getInstance();
|
||||
LLVector3 old_origin = camera->getOrigin();
|
||||
F32 old_fov = camera->getView();
|
||||
F32 old_aspect = camera->getAspect();
|
||||
F32 old_yaw = camera->getYaw();
|
||||
|
||||
// camera constants for the square, cube map capture image
|
||||
camera->setAspect(1.0); // must set aspect ratio first to avoid undesirable clamping of vertical FoV
|
||||
camera->setView(F_PI_BY_TWO);
|
||||
camera->yaw(0.0);
|
||||
camera->setOrigin(mOrigin);
|
||||
|
||||
// for each of the 6 directions we shoot...
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
// set up camera to look in each direction
|
||||
camera->lookDir(look_dirs[i], look_upvecs[i]);
|
||||
|
||||
// call the (very) simplified snapshot code that simply deals
|
||||
// with a single image, no sub-images etc. but is very fast
|
||||
gViewerWindow->simpleSnapshot(rawimages[i],
|
||||
resolution, resolution, 1);
|
||||
}
|
||||
|
||||
// restore original view/camera/avatar settings settings
|
||||
camera->setAspect(old_aspect);
|
||||
camera->setView(old_fov);
|
||||
camera->yaw(old_yaw);
|
||||
camera->setOrigin(old_origin);
|
||||
|
||||
LLPipeline::sUseOcclusion = old_occlusion;
|
||||
|
||||
// ====================================================
|
||||
|
||||
mCubeMap = new LLCubeMap(false);
|
||||
mCubeMap->initEnvironmentMap(rawimages);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* @file llreflectionmap.cpp
|
||||
* @brief LLReflectionMap class implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2022, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llreflectionmap.h"
|
||||
#include "pipeline.h"
|
||||
#include "llviewerwindow.h"
|
||||
|
||||
LLReflectionMap::LLReflectionMap()
|
||||
{
|
||||
}
|
||||
|
||||
void LLReflectionMap::update(const LLVector3& origin, U32 resolution)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
llassert(LLPipeline::sRenderDeferred);
|
||||
|
||||
// make sure resolution is < gPipeline.mDeferredScreen.getWidth()
|
||||
|
||||
while (resolution > gPipeline.mDeferredScreen.getWidth() ||
|
||||
resolution > gPipeline.mDeferredScreen.getHeight())
|
||||
{
|
||||
resolution /= 2;
|
||||
}
|
||||
|
||||
if (resolution == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mOrigin.load3(origin.mV);
|
||||
|
||||
mCubeMap = new LLCubeMap(false);
|
||||
mCubeMap->initReflectionMap(resolution);
|
||||
|
||||
gViewerWindow->cubeSnapshot(origin, mCubeMap);
|
||||
|
||||
mCubeMap->generateMipMaps();
|
||||
}
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* @file llenvironmentmap.h
|
||||
* @brief LLEnvironmentMap class declaration
|
||||
* @file llreflectionmap.h
|
||||
* @brief LLReflectionMap class declaration
|
||||
*
|
||||
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
|
|
@ -28,21 +28,24 @@
|
|||
|
||||
#include "llcubemap.h"
|
||||
|
||||
class LLEnvironmentMap
|
||||
class LLReflectionMap : public LLRefCount
|
||||
{
|
||||
public:
|
||||
// allocate an environment map of the given resolution
|
||||
LLEnvironmentMap();
|
||||
LLReflectionMap();
|
||||
|
||||
// update this environment map
|
||||
// origin - position in agent space to generate environment map from in agent space
|
||||
// resolution - size of cube map to generate
|
||||
void update(const LLVector3& origin, U32 resolution);
|
||||
|
||||
// point at which environment map was generated from (in agent space)
|
||||
LLVector4a mOrigin;
|
||||
|
||||
// distance from viewer camera
|
||||
F32 mDistance;
|
||||
|
||||
// cube map used to sample this environment map
|
||||
LLPointer<LLCubeMap> mCubeMap;
|
||||
|
||||
// point at which environment map was generated from (in agent space)
|
||||
LLVector3 mOrigin;
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
* @file llreflectionmapmanager.cpp
|
||||
* @brief LLReflectionMapManager class implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2022, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llreflectionmapmanager.h"
|
||||
#include "llviewercamera.h"
|
||||
|
||||
LLReflectionMapManager::LLReflectionMapManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
struct CompareReflectionMapDistance
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct CompareProbeDistance
|
||||
{
|
||||
bool operator()(const LLReflectionMap& lhs, const LLReflectionMap& rhs)
|
||||
{
|
||||
return lhs.mDistance < rhs.mDistance;
|
||||
}
|
||||
};
|
||||
|
||||
// helper class to seed octree with probes
|
||||
void LLReflectionMapManager::update()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
|
||||
// naively drop probes every 16m as we move the camera around for now
|
||||
// later, use LLSpatialPartition to manage probes
|
||||
const F32 PROBE_SPACING = 16.f;
|
||||
const U32 MAX_PROBES = 8;
|
||||
|
||||
LLVector4a camera_pos;
|
||||
camera_pos.load3(LLViewerCamera::instance().getOrigin().mV);
|
||||
|
||||
for (auto& probe : mProbes)
|
||||
{
|
||||
LLVector4a d;
|
||||
d.setSub(camera_pos, probe.mOrigin);
|
||||
probe.mDistance = d.getLength3().getF32();
|
||||
}
|
||||
|
||||
if (mProbes.empty() || mProbes[0].mDistance > PROBE_SPACING)
|
||||
{
|
||||
addProbe(LLViewerCamera::instance().getOrigin());
|
||||
}
|
||||
|
||||
// update distance to camera for all probes
|
||||
std::sort(mProbes.begin(), mProbes.end(), CompareProbeDistance());
|
||||
|
||||
if (mProbes.size() > MAX_PROBES)
|
||||
{
|
||||
mProbes.resize(MAX_PROBES);
|
||||
}
|
||||
}
|
||||
|
||||
void LLReflectionMapManager::addProbe(const LLVector3& pos)
|
||||
{
|
||||
LLReflectionMap probe;
|
||||
probe.update(pos, 1024);
|
||||
mProbes.push_back(probe);
|
||||
}
|
||||
|
||||
void LLReflectionMapManager::getReflectionMaps(std::vector<LLReflectionMap*>& maps)
|
||||
{
|
||||
// just null out for now
|
||||
U32 i = 0;
|
||||
for (i = 0; i < maps.size() && i < mProbes.size(); ++i)
|
||||
{
|
||||
maps[i] = &(mProbes[i]);
|
||||
}
|
||||
|
||||
for (++i; i < maps.size(); ++i)
|
||||
{
|
||||
maps[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* @file llreflectionmapmanager.h
|
||||
* @brief LLReflectionMapManager class declaration
|
||||
*
|
||||
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2022, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "llreflectionmap.h"
|
||||
|
||||
class LLReflectionMapManager
|
||||
{
|
||||
public:
|
||||
// allocate an environment map of the given resolution
|
||||
LLReflectionMapManager();
|
||||
|
||||
// maintain reflection probes
|
||||
void update();
|
||||
|
||||
// drop a reflection probe at the specified position in agent space
|
||||
void addProbe(const LLVector3& pos);
|
||||
|
||||
// Populate "maps" with the N most relevant Reflection Maps where N is no more than maps.size()
|
||||
// If less than maps.size() ReflectionMaps are available, will assign trailing elements to nullptr.
|
||||
// maps -- presized array of Reflection Map pointers
|
||||
void getReflectionMaps(std::vector<LLReflectionMap*>& maps);
|
||||
|
||||
// list of active reflection maps
|
||||
std::vector<LLReflectionMap> mProbes;
|
||||
};
|
||||
|
||||
|
|
@ -5170,6 +5170,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
|
|||
|
||||
BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, const int num_render_passes)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
|
||||
gDisplaySwapBuffers = FALSE;
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
|
@ -5266,6 +5267,152 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_
|
|||
return true;
|
||||
}
|
||||
|
||||
BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMap* cubemap)
|
||||
{
|
||||
// NOTE: implementation derived from LLFloater360Capture::capture360Images() and simpleSnapshot
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
|
||||
llassert(LLPipeline::sRenderDeferred);
|
||||
|
||||
U32 res = cubemap->getResolution();
|
||||
|
||||
llassert(res <= gPipeline.mDeferredScreen.getWidth());
|
||||
llassert(res <= gPipeline.mDeferredScreen.getHeight());
|
||||
|
||||
|
||||
|
||||
// save current view/camera settings so we can restore them afterwards
|
||||
S32 old_occlusion = LLPipeline::sUseOcclusion;
|
||||
|
||||
// set new parameters specific to the 360 requirements
|
||||
LLPipeline::sUseOcclusion = 0;
|
||||
LLViewerCamera* camera = LLViewerCamera::getInstance();
|
||||
LLVector3 old_origin = camera->getOrigin();
|
||||
F32 old_fov = camera->getView();
|
||||
F32 old_aspect = camera->getAspect();
|
||||
F32 old_yaw = camera->getYaw();
|
||||
|
||||
// camera constants for the square, cube map capture image
|
||||
camera->setAspect(1.0); // must set aspect ratio first to avoid undesirable clamping of vertical FoV
|
||||
camera->setView(F_PI_BY_TWO);
|
||||
camera->yaw(0.0);
|
||||
camera->setOrigin(origin);
|
||||
|
||||
gDisplaySwapBuffers = FALSE;
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE;
|
||||
if (prev_draw_ui != false)
|
||||
{
|
||||
LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI);
|
||||
}
|
||||
|
||||
LLPipeline::sShowHUDAttachments = FALSE;
|
||||
LLRect window_rect = getWorldViewRectRaw();
|
||||
|
||||
LLRenderTarget scratch_space; // TODO: hold onto "scratch space" render target and allocate oncer per session (allocate takes > 1ms)
|
||||
U32 color_fmt = GL_RGBA;
|
||||
const bool use_depth_buffer = true;
|
||||
const bool use_stencil_buffer = true;
|
||||
if (scratch_space.allocate(res, res, color_fmt, use_depth_buffer, use_stencil_buffer))
|
||||
{
|
||||
mWorldViewRectRaw.set(0, res, res, 0);
|
||||
scratch_space.bindTarget();
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// "target" parameter of glCopyTexImage2D for each side of cubemap
|
||||
U32 targets[6] = {
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
|
||||
GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
|
||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
|
||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
|
||||
};
|
||||
|
||||
// these are the 6 directions we will point the camera, see LLCubeMap::mTargets
|
||||
LLVector3 look_dirs[6] = {
|
||||
LLVector3(-1, 0, 0),
|
||||
LLVector3(1, 0, 0),
|
||||
LLVector3(0, -1, 0),
|
||||
LLVector3(0, 1, 0),
|
||||
LLVector3(0, 0, -1),
|
||||
LLVector3(0, 0, 1)
|
||||
};
|
||||
|
||||
LLVector3 look_upvecs[6] = {
|
||||
LLVector3(0, -1, 0),
|
||||
LLVector3(0, -1, 0),
|
||||
LLVector3(0, 0, -1),
|
||||
LLVector3(0, 0, 1),
|
||||
LLVector3(0, -1, 0),
|
||||
LLVector3(0, -1, 0)
|
||||
};
|
||||
|
||||
// for each of six sides of cubemap
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
// set up camera to look in each direction
|
||||
camera->lookDir(look_dirs[i], look_upvecs[i]);
|
||||
|
||||
// turning this flag off here prohibits the screen swap
|
||||
// to present the new page to the viewer - this stops
|
||||
// the black flash in between captures when the number
|
||||
// of render passes is more than 1. We need to also
|
||||
// set it here because code in LLViewerDisplay resets
|
||||
// it to TRUE each time.
|
||||
gDisplaySwapBuffers = FALSE;
|
||||
|
||||
// actually render the scene
|
||||
const U32 subfield = 0;
|
||||
const bool do_rebuild = true;
|
||||
const F32 zoom = 1.0;
|
||||
const bool for_snapshot = TRUE;
|
||||
display(do_rebuild, zoom, subfield, for_snapshot);
|
||||
|
||||
// copy results to cube map face
|
||||
cubemap->enable(0);
|
||||
cubemap->bind();
|
||||
glCopyTexImage2D(targets[i], 0, GL_RGB, 0, 0, res, res, 0);
|
||||
gGL.getTexUnit(0)->disable();
|
||||
cubemap->disable();
|
||||
}
|
||||
|
||||
gDisplaySwapBuffers = FALSE;
|
||||
gDepthDirty = TRUE;
|
||||
|
||||
if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
|
||||
{
|
||||
if (prev_draw_ui != false)
|
||||
{
|
||||
LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI);
|
||||
}
|
||||
}
|
||||
|
||||
LLPipeline::sShowHUDAttachments = TRUE;
|
||||
|
||||
gPipeline.resetDrawOrders();
|
||||
mWorldViewRectRaw = window_rect;
|
||||
scratch_space.flush();
|
||||
scratch_space.release();
|
||||
|
||||
// restore original view/camera/avatar settings settings
|
||||
camera->setAspect(old_aspect);
|
||||
camera->setView(old_fov);
|
||||
camera->yaw(old_yaw);
|
||||
camera->setOrigin(old_origin);
|
||||
|
||||
LLPipeline::sUseOcclusion = old_occlusion;
|
||||
|
||||
// ====================================================
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLViewerWindow::destroyWindow()
|
||||
{
|
||||
if (mWindow)
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ class LLWindowListener;
|
|||
class LLViewerWindowListener;
|
||||
class LLVOPartGroup;
|
||||
class LLPopupView;
|
||||
class LLCubeMap;
|
||||
|
||||
#define PICK_HALF_WIDTH 5
|
||||
#define PICK_DIAMETER (2 * PICK_HALF_WIDTH + 1)
|
||||
|
|
@ -360,6 +361,17 @@ public:
|
|||
|
||||
BOOL simpleSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, const int num_render_passes);
|
||||
|
||||
|
||||
|
||||
// take a cubemap snapshot
|
||||
// origin - vantage point to take the snapshot from
|
||||
// cubemap - cubemap to store the results
|
||||
BOOL cubeSnapshot(const LLVector3& origin, LLCubeMap* cubemap);
|
||||
|
||||
|
||||
// special implementation of simpleSnapshot for reflection maps
|
||||
BOOL reflectionSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, const int num_render_passes);
|
||||
|
||||
BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type);
|
||||
BOOL isSnapshotLocSet() const;
|
||||
void resetSnapshotLoc() const;
|
||||
|
|
|
|||
|
|
@ -767,42 +767,16 @@ void LLPipeline::allocatePhysicsBuffer()
|
|||
|
||||
bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
|
||||
{
|
||||
refreshCachedSettings();
|
||||
|
||||
bool save_settings = sRenderDeferred;
|
||||
if (save_settings)
|
||||
{
|
||||
// Set this flag in case we crash while resizing window or allocating space for deferred rendering targets
|
||||
gSavedSettings.setBOOL("RenderInitError", TRUE);
|
||||
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
|
||||
}
|
||||
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
eFBOStatus ret = doAllocateScreenBuffer(resX, resY);
|
||||
|
||||
if (save_settings)
|
||||
{
|
||||
// don't disable shaders on next session
|
||||
gSavedSettings.setBOOL("RenderInitError", FALSE);
|
||||
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
|
||||
}
|
||||
|
||||
if (ret == FBO_FAILURE)
|
||||
{ //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled
|
||||
//NOTE: if the session closes successfully after this call, deferred rendering will be
|
||||
// disabled on future sessions
|
||||
if (LLPipeline::sRenderDeferred)
|
||||
{
|
||||
gSavedSettings.setBOOL("RenderDeferred", FALSE);
|
||||
LLPipeline::refreshCachedSettings();
|
||||
}
|
||||
}
|
||||
|
||||
return ret == FBO_SUCCESS_FULLRES;
|
||||
}
|
||||
|
||||
|
||||
LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
// try to allocate screen buffers at requested resolution and samples
|
||||
// - on failure, shrink number of samples and try again
|
||||
// - if not multisampled, shrink resolution and try again (favor X resolution over Y)
|
||||
|
|
@ -856,8 +830,7 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY)
|
|||
|
||||
bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
|
||||
{
|
||||
refreshCachedSettings();
|
||||
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
// remember these dimensions
|
||||
mScreenWidth = resX;
|
||||
mScreenHeight = resY;
|
||||
|
|
@ -961,8 +934,7 @@ inline U32 BlurHappySize(U32 x, F32 scale) { return U32( x * scale + 16.0f) & ~0
|
|||
|
||||
bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY)
|
||||
{
|
||||
refreshCachedSettings();
|
||||
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
if (LLPipeline::sRenderDeferred)
|
||||
{
|
||||
S32 shadow_detail = RenderShadowDetail;
|
||||
|
|
@ -1053,6 +1025,7 @@ void LLPipeline::updateRenderDeferred()
|
|||
// static
|
||||
void LLPipeline::refreshCachedSettings()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred");
|
||||
LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred");
|
||||
LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip");
|
||||
|
|
@ -8204,12 +8177,41 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
|
|||
channel = shader.enableTexture(LLShaderMgr::REFLECTION_MAP, LLTexUnit::TT_CUBE_MAP);
|
||||
if (channel > -1)
|
||||
{
|
||||
LLCubeMap* cube_map = mEnvironmentMap.mCubeMap;
|
||||
if (cube_map)
|
||||
mReflectionMaps.resize(8); //TODO -- declare the number of reflection maps the shader knows about somewhere sane
|
||||
mReflectionMapManager.getReflectionMaps(mReflectionMaps);
|
||||
LLVector3 origin[8]; //origin of refmaps in clip space
|
||||
|
||||
// load modelview matrix into matrix 4a
|
||||
LLMatrix4a modelview;
|
||||
modelview.loadu(gGLModelView);
|
||||
LLVector4a oa; // scratch space for transformed origin
|
||||
|
||||
S32 count = 0;
|
||||
for (auto* refmap : mReflectionMaps)
|
||||
{
|
||||
if (refmap)
|
||||
{
|
||||
LLCubeMap* cubemap = refmap->mCubeMap;
|
||||
if (cubemap)
|
||||
{
|
||||
cubemap->enable(channel + count);
|
||||
cubemap->bind();
|
||||
|
||||
modelview.affineTransform(refmap->mOrigin, oa);
|
||||
origin[count].set(oa.getF32ptr());
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
LLStaticHashedString refmapCount("refmapCount");
|
||||
LLStaticHashedString refOrigin("refOrigin");
|
||||
shader.uniform1i(refmapCount, count);
|
||||
shader.uniform3fv(refOrigin, count, (F32*)origin);
|
||||
setup_env_mat = true;
|
||||
cube_map->enable(channel);
|
||||
cube_map->bind();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -9125,10 +9127,14 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
|
|||
channel = shader.disableTexture(LLShaderMgr::REFLECTION_MAP, LLTexUnit::TT_CUBE_MAP);
|
||||
if (channel > -1)
|
||||
{
|
||||
LLCubeMap* cube_map = mEnvironmentMap.mCubeMap;
|
||||
if (cube_map)
|
||||
for (int i = 0; i < mReflectionMaps.size(); ++i)
|
||||
{
|
||||
cube_map->disable();
|
||||
gGL.getTexUnit(channel + i)->disable();
|
||||
}
|
||||
|
||||
if (channel == 0)
|
||||
{
|
||||
gGL.getTexUnit(channel)->enable(LLTexUnit::TT_TEXTURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -11498,6 +11504,7 @@ void LLPipeline::restoreHiddenObject( const LLUUID& id )
|
|||
|
||||
void LLPipeline::overrideEnvironmentMap()
|
||||
{
|
||||
mEnvironmentMap.update(LLViewerCamera::instance().getOrigin(), 1024);
|
||||
mReflectionMapManager.mProbes.clear();
|
||||
mReflectionMapManager.addProbe(LLViewerCamera::instance().getOrigin());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
#include "llgl.h"
|
||||
#include "lldrawable.h"
|
||||
#include "llrendertarget.h"
|
||||
#include "llenvironmentmap.h"
|
||||
#include "llreflectionmapmanager.h"
|
||||
|
||||
#include <stack>
|
||||
|
||||
|
|
@ -427,7 +427,7 @@ public:
|
|||
void hideObject( const LLUUID& id );
|
||||
void restoreHiddenObject( const LLUUID& id );
|
||||
|
||||
LLEnvironmentMap mEnvironmentMap;
|
||||
LLReflectionMapManager mReflectionMapManager;
|
||||
void overrideEnvironmentMap();
|
||||
|
||||
private:
|
||||
|
|
@ -661,6 +661,9 @@ public:
|
|||
//utility buffer for rendering cubes, 8 vertices are corners of a cube [-1, 1]
|
||||
LLPointer<LLVertexBuffer> mCubeVB;
|
||||
|
||||
//list of currently bound reflection maps
|
||||
std::vector<LLReflectionMap*> mReflectionMaps;
|
||||
|
||||
//sun shadow map
|
||||
LLRenderTarget mShadow[6];
|
||||
LLRenderTarget mShadowOcclusion[6];
|
||||
|
|
|
|||
Loading…
Reference in New Issue