mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-30 08:15:37 +00:00
experimental point light bindings
This commit is contained in:
parent
fee639a74f
commit
0cb63ca4e6
13 changed files with 168 additions and 12 deletions
|
@ -94,6 +94,8 @@ namespace MWRender
|
|||
, mNormals(false)
|
||||
, mPrevNormals(false)
|
||||
, mNormalsSupported(false)
|
||||
, mPassLights(false)
|
||||
, mPrevPassLights(false)
|
||||
, mMainTemplate(new osg::Texture2D)
|
||||
{
|
||||
mSoftParticles = Settings::Manager::getBool("soft particles", "Shaders") && !Stereo::getStereo() && !Stereo::getMultiview();
|
||||
|
@ -393,9 +395,10 @@ namespace MWRender
|
|||
mDirty = false;
|
||||
}
|
||||
|
||||
if (mNormalsSupported && mNormals != mPrevNormals)
|
||||
if ((mNormalsSupported && mNormals != mPrevNormals) || (mPassLights != mPrevPassLights))
|
||||
{
|
||||
mPrevNormals = mNormals;
|
||||
mPrevPassLights = mPassLights;
|
||||
|
||||
mViewer->stopThreading();
|
||||
|
||||
|
@ -404,10 +407,15 @@ namespace MWRender
|
|||
defines["disableNormals"] = mNormals ? "0" : "1";
|
||||
shaderManager.setGlobalDefines(defines);
|
||||
|
||||
mRendering.getLightRoot()->setCollectPPLights(mPassLights);
|
||||
mStateUpdater->bindPointLights(mPassLights ? mRendering.getLightRoot()->getPPLightsBuffer() : nullptr);
|
||||
mStateUpdater->reset();
|
||||
|
||||
mViewer->startThreading();
|
||||
|
||||
createTexturesAndCamera(frameId);
|
||||
createObjectsForFrame(frameId);
|
||||
|
||||
mDirty = true;
|
||||
mDirtyFrameId = !frameId;
|
||||
}
|
||||
|
@ -491,6 +499,7 @@ namespace MWRender
|
|||
bool sunglare = true;
|
||||
mHDR = false;
|
||||
mNormals = false;
|
||||
mPassLights = false;
|
||||
|
||||
for (const auto& technique : mTechniques)
|
||||
{
|
||||
|
@ -513,6 +522,9 @@ namespace MWRender
|
|||
if (technique->getNormals())
|
||||
mNormals = true;
|
||||
|
||||
if (technique->getLights())
|
||||
mPassLights = true;
|
||||
|
||||
if (node.mFlags & fx::Technique::Flag_Disable_SunGlare)
|
||||
sunglare = false;
|
||||
|
||||
|
|
|
@ -212,6 +212,8 @@ namespace MWRender
|
|||
bool mNormals;
|
||||
bool mPrevNormals;
|
||||
bool mNormalsSupported;
|
||||
bool mPassLights;
|
||||
bool mPrevPassLights;
|
||||
bool mUBO;
|
||||
int mGLSLVersion;
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include <components/sceneutil/writescene.hpp>
|
||||
#include <components/sceneutil/shadow.hpp>
|
||||
|
||||
#include <components/misc/constants.hpp>
|
||||
|
||||
#include <components/terrain/terraingrid.hpp>
|
||||
#include <components/terrain/quadtreeworld.hpp>
|
||||
|
||||
|
@ -558,10 +560,9 @@ namespace MWRender
|
|||
cullingMode |= osg::CullStack::SMALL_FEATURE_CULLING;
|
||||
}
|
||||
|
||||
mViewer->getCamera()->setCullingMode( cullingMode );
|
||||
|
||||
mViewer->getCamera()->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
mViewer->getCamera()->setCullingMode(cullingMode);
|
||||
mViewer->getCamera()->setName(Constants::SceneCamera);
|
||||
|
||||
auto mask = ~(Mask_UpdateVisitor | Mask_SimpleWater);
|
||||
MWBase::Environment::get().getWindowManager()->setCullMask(mask);
|
||||
|
@ -650,7 +651,7 @@ namespace MWRender
|
|||
return mViewer->getFrameStamp()->getReferenceTime();
|
||||
}
|
||||
|
||||
osg::Group* RenderingManager::getLightRoot()
|
||||
SceneUtil::LightManager* RenderingManager::getLightRoot()
|
||||
{
|
||||
return mSceneRoot.get();
|
||||
}
|
||||
|
@ -1360,7 +1361,7 @@ namespace MWRender
|
|||
it->second == "light fade start" ||
|
||||
it->second == "max lights"))
|
||||
{
|
||||
auto* lightManager = static_cast<SceneUtil::LightManager*>(getLightRoot());
|
||||
auto* lightManager = getLightRoot();
|
||||
lightManager->processChangedSettings(changed);
|
||||
|
||||
if (it->second == "max lights" && !lightManager->usingFFP())
|
||||
|
|
|
@ -59,6 +59,7 @@ namespace SceneUtil
|
|||
{
|
||||
class ShadowManager;
|
||||
class WorkQueue;
|
||||
class LightManager;
|
||||
}
|
||||
|
||||
namespace DetourNavigator
|
||||
|
@ -116,7 +117,7 @@ namespace MWRender
|
|||
|
||||
double getReferenceTime() const;
|
||||
|
||||
osg::Group* getLightRoot();
|
||||
SceneUtil::LightManager* getLightRoot();
|
||||
|
||||
void setNightEyeFactor(float factor);
|
||||
|
||||
|
@ -271,7 +272,7 @@ namespace MWRender
|
|||
|
||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||
osg::ref_ptr<osg::Group> mRootNode;
|
||||
osg::ref_ptr<osg::Group> mSceneRoot;
|
||||
osg::ref_ptr<SceneUtil::LightManager> mSceneRoot;
|
||||
Resource::ResourceSystem* mResourceSystem;
|
||||
|
||||
osg::ref_ptr<SceneUtil::WorkQueue> mWorkQueue;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <components/resource/resourcesystem.hpp>
|
||||
|
||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||
#include <components/sceneutil/lightmanager.hpp>
|
||||
|
||||
#include <components/detournavigator/navigator.hpp>
|
||||
#include <components/detournavigator/settings.hpp>
|
||||
|
@ -197,7 +198,7 @@ namespace MWWorld
|
|||
}
|
||||
|
||||
mRendering.reset(new MWRender::RenderingManager(viewer, rootNode, resourceSystem, workQueue, resourcePath, *mNavigator, mGroundcoverStore));
|
||||
mProjectileManager.reset(new ProjectileManager(mRendering->getLightRoot(), resourceSystem, mRendering.get(), mPhysics.get()));
|
||||
mProjectileManager.reset(new ProjectileManager(mRendering->getLightRoot()->asGroup(), resourceSystem, mRendering.get(), mPhysics.get()));
|
||||
mRendering->preloadCommonAssets();
|
||||
|
||||
mWeatherManager.reset(new MWWorld::WeatherManager(*mRendering, mStore));
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include <components/sceneutil/util.hpp>
|
||||
#include <components/sceneutil/lightmanager.hpp>
|
||||
#include <components/sceneutil/clearcolor.hpp>
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/stereo/multiview.hpp>
|
||||
|
@ -77,6 +78,34 @@ uniform @builtinSampler omw_SamplerLastPass;
|
|||
uniform @builtinSampler omw_SamplerDepth;
|
||||
uniform @builtinSampler omw_SamplerNormals;
|
||||
|
||||
uniform vec4 omw_PointLights[@pointLightCount];
|
||||
uniform int omw_PointLightsCount;
|
||||
|
||||
int omw_GetPointLightCount()
|
||||
{
|
||||
return omw_PointLightsCount;
|
||||
}
|
||||
|
||||
vec3 omw_GetPointLightViewPos(int index)
|
||||
{
|
||||
return omw_PointLights[(index * 3)].xyz;
|
||||
}
|
||||
|
||||
vec3 omw_GetPointLightDiffuse(int index)
|
||||
{
|
||||
return omw_PointLights[(index * 3) + 1].xyz;
|
||||
}
|
||||
|
||||
vec3 omw_GetPointLightAttenuation(int index)
|
||||
{
|
||||
return omw_PointLights[(index * 3) + 2].xyz;
|
||||
}
|
||||
|
||||
float omw_GetPointLightRadius(int index)
|
||||
{
|
||||
return omw_PointLights[(index * 3) + 2].w;
|
||||
}
|
||||
|
||||
#if @ubo
|
||||
layout(std140) uniform _data { _omw_data omw; };
|
||||
#else
|
||||
|
@ -143,6 +172,7 @@ uniform @builtinSampler omw_SamplerNormals;
|
|||
extBlock << "#ifdef " << extension << '\n' << "\t#extension " << extension << ": enable" << '\n' << "#endif" << '\n';
|
||||
|
||||
const std::vector<std::pair<std::string,std::string>> defines = {
|
||||
{"@pointLightCount", std::to_string(SceneUtil::PPLightBuffer::sMaxPPLightsArraySize)},
|
||||
{"@version", std::to_string(technique.getGLSLVersion())},
|
||||
{"@multiview", Stereo::getMultiview() ? "1" : "0"},
|
||||
{"@builtinSampler", Stereo::getMultiview() ? "sampler2DArray" : "sampler2D"},
|
||||
|
|
|
@ -56,5 +56,8 @@ namespace fx
|
|||
|
||||
std::apply([&] (const auto& ... v) { (setUniform(v) , ...); }, mData.getData());
|
||||
}
|
||||
|
||||
if (mPointLightBuffer)
|
||||
mPointLightBuffer->applyUniforms(nv->getTraversalNumber(), stateset);
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <osg/BufferTemplate>
|
||||
|
||||
#include <components/sceneutil/lightmanager.hpp>
|
||||
#include <components/sceneutil/statesetupdater.hpp>
|
||||
#include <components/std140/ubo.hpp>
|
||||
|
||||
|
@ -86,12 +87,21 @@ namespace fx
|
|||
|
||||
void setWeatherTransition(float transition) { mData.get<WeatherTransition>() = transition; }
|
||||
|
||||
void bindPointLights(std::shared_ptr<SceneUtil::PPLightBuffer> buffer)
|
||||
{
|
||||
mPointLightBuffer = buffer;
|
||||
}
|
||||
|
||||
static std::string getStructDefinition()
|
||||
{
|
||||
static std::string definition = UniformData::getDefinition("_omw_data");
|
||||
return definition;
|
||||
}
|
||||
|
||||
void setDefaults(osg::StateSet* stateset) override;
|
||||
|
||||
void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override;
|
||||
|
||||
private:
|
||||
struct ProjectionMatrix : std140::Mat4 { static constexpr std::string_view sName = "projectionMatrix"; };
|
||||
|
||||
|
@ -180,12 +190,10 @@ namespace fx
|
|||
IsInterior
|
||||
>;
|
||||
|
||||
private:
|
||||
void setDefaults(osg::StateSet* stateset) override;
|
||||
void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override;
|
||||
|
||||
UniformData mData;
|
||||
bool mUseUBO;
|
||||
|
||||
std::shared_ptr<SceneUtil::PPLightBuffer> mPointLightBuffer;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ namespace fx
|
|||
mValid = false;
|
||||
mHDR = false;
|
||||
mNormals = false;
|
||||
mLights = false;
|
||||
mEnabled = true;
|
||||
mPassMap.clear();
|
||||
mPasses.clear();
|
||||
|
@ -238,6 +239,8 @@ namespace fx
|
|||
mHDR = parseBool();
|
||||
else if (key == "pass_normals")
|
||||
mNormals = parseBool() && mSupportsNormals;
|
||||
else if (key == "pass_lights")
|
||||
mLights = parseBool();
|
||||
else if (key == "glsl_profile")
|
||||
{
|
||||
expect<Lexer::String>();
|
||||
|
|
|
@ -129,6 +129,8 @@ namespace fx
|
|||
|
||||
bool getNormals() const { return mNormals && mSupportsNormals; }
|
||||
|
||||
bool getLights() const { return mLights; }
|
||||
|
||||
const PassList& getPasses() { return mPasses; }
|
||||
|
||||
const TexList& getTextures() const { return mTextures; }
|
||||
|
@ -253,6 +255,7 @@ namespace fx
|
|||
bool mValid;
|
||||
bool mHDR;
|
||||
bool mNormals;
|
||||
bool mLights;
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@ const float TorsoHeight = 0.75f;
|
|||
static constexpr float sStepSizeUp = 34.0f;
|
||||
static constexpr float sMaxSlope = 46.0f;
|
||||
|
||||
// Identifier for main scene camera
|
||||
const std::string SceneCamera = "SceneCam";
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <components/misc/hash.hpp>
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include <components/misc/constants.hpp>
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
|
||||
|
@ -839,6 +840,7 @@ namespace SceneUtil
|
|||
, mPointLightFadeEnd(copy.mPointLightFadeEnd)
|
||||
, mPointLightFadeStart(copy.mPointLightFadeStart)
|
||||
, mMaxLights(copy.mMaxLights)
|
||||
, mPPLightBuffer(copy.mPPLightBuffer)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1001,6 +1003,9 @@ namespace SceneUtil
|
|||
|
||||
void LightManager::update(size_t frameNum)
|
||||
{
|
||||
if (mPPLightBuffer)
|
||||
mPPLightBuffer->clear(frameNum);
|
||||
|
||||
getLightIndexMap(frameNum).clear();
|
||||
mLights.clear();
|
||||
mLightsInViewSpace.clear();
|
||||
|
@ -1132,6 +1137,17 @@ namespace SceneUtil
|
|||
l.mLightSource = transform.mLightSource;
|
||||
l.mViewBound = viewBound;
|
||||
it->second.push_back(l);
|
||||
|
||||
if (mPPLightBuffer && it->first->getName() == Constants::SceneCamera)
|
||||
{
|
||||
const auto* light = l.mLightSource->getLight(frameNum);
|
||||
mPPLightBuffer->setLight(frameNum, light->getPosition() * (*viewMatrix),
|
||||
light->getDiffuse(),
|
||||
light->getConstantAttenuation(),
|
||||
light->getLinearAttenuation(),
|
||||
light->getQuadraticAttenuation(),
|
||||
l.mLightSource->getRadius());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1168,6 +1184,14 @@ namespace SceneUtil
|
|||
return uniform;
|
||||
}
|
||||
|
||||
void LightManager::setCollectPPLights(bool enabled)
|
||||
{
|
||||
if (enabled)
|
||||
mPPLightBuffer = std::make_shared<PPLightBuffer>();
|
||||
else
|
||||
mPPLightBuffer = nullptr;
|
||||
}
|
||||
|
||||
LightSource::LightSource()
|
||||
: mRadius(0.f)
|
||||
, mActorFade(1.f)
|
||||
|
|
|
@ -26,6 +26,64 @@ namespace SceneUtil
|
|||
class LightBuffer;
|
||||
struct StateSetGenerator;
|
||||
|
||||
class PPLightBuffer
|
||||
{
|
||||
public:
|
||||
inline static constexpr auto sMaxPPLights = 30;
|
||||
inline static constexpr auto sMaxPPLightsArraySize = sMaxPPLights * 3;
|
||||
|
||||
PPLightBuffer()
|
||||
{
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
{
|
||||
mIndex[i] = 0;
|
||||
mUniformBuffers[i] = new osg::Uniform(osg::Uniform::FLOAT_VEC4, "omw_PointLights", sMaxPPLightsArraySize);
|
||||
mUniformCount[i] = new osg::Uniform("omw_PointLightsCount", static_cast<int>(0));
|
||||
}
|
||||
}
|
||||
|
||||
void applyUniforms(size_t frame, osg::StateSet* stateset)
|
||||
{
|
||||
size_t frameId = frame % 2;
|
||||
|
||||
if (!stateset->getUniform("omw_PointLights"))
|
||||
stateset->addUniform(mUniformBuffers[frameId]);
|
||||
if (!stateset->getUniform("omw_PointLightsCount"))
|
||||
stateset->addUniform(mUniformCount[frameId]);
|
||||
|
||||
mUniformBuffers[frameId]->dirty();
|
||||
mUniformCount[frameId]->dirty();
|
||||
}
|
||||
|
||||
void clear(size_t frame)
|
||||
{
|
||||
mIndex[frame % 2] = 0;
|
||||
}
|
||||
|
||||
void setLight(size_t frame, const osg::Vec4f& position, osg::Vec4f diffuse, float ac, float al, float aq, float radius)
|
||||
{
|
||||
size_t frameId = frame % 2;
|
||||
size_t i = mIndex[frameId];
|
||||
|
||||
if (i >= (sMaxPPLights - 1))
|
||||
return;
|
||||
|
||||
i *= 3;
|
||||
|
||||
mUniformBuffers[frameId]->setElement(i + 0, position);
|
||||
mUniformBuffers[frameId]->setElement(i + 1, diffuse);
|
||||
mUniformBuffers[frameId]->setElement(i + 2, osg::Vec4f(ac, al, aq, radius));
|
||||
|
||||
mIndex[frameId]++;
|
||||
mUniformCount[frameId]->set(static_cast<int>(mIndex[frameId]));
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<size_t, 2> mIndex;
|
||||
std::array<osg::ref_ptr<osg::Uniform>, 2> mUniformBuffers;
|
||||
std::array<osg::ref_ptr<osg::Uniform>, 2> mUniformCount;
|
||||
};
|
||||
|
||||
enum class LightingMethod
|
||||
{
|
||||
FFP,
|
||||
|
@ -227,6 +285,11 @@ namespace SceneUtil
|
|||
|
||||
osg::ref_ptr<osg::Uniform> generateLightBufferUniform(const osg::Matrixf& sun);
|
||||
|
||||
// Whether to collect main scene camera points lights into a buffer to be later sent to postprocessing shaders
|
||||
void setCollectPPLights(bool enabled);
|
||||
|
||||
std::shared_ptr<PPLightBuffer> getPPLightsBuffer() { return mPPLightBuffer; }
|
||||
|
||||
private:
|
||||
void initFFP(int targetLights);
|
||||
void initPerObjectUniform(int targetLights);
|
||||
|
@ -285,6 +348,8 @@ namespace SceneUtil
|
|||
static constexpr auto mFFPMaxLights = 8;
|
||||
|
||||
static const std::unordered_map<std::string, LightingMethod> mLightingMethodSettingMap;
|
||||
|
||||
std::shared_ptr<PPLightBuffer> mPPLightBuffer;
|
||||
};
|
||||
|
||||
/// To receive lighting, objects must be decorated by a LightListCallback. Light list callbacks must be added via
|
||||
|
|
Loading…
Reference in a new issue