Merge branch 'PBR_ProbeArrayWIP' of https://github.com/Areloch/Torque3D into PBR_ProbeArrayWIP

# Conflicts:
#	Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl
This commit is contained in:
Azaezel 2019-03-03 11:54:24 -06:00
commit 6a7d046a19
11 changed files with 226 additions and 54 deletions

View file

@ -91,6 +91,8 @@ void BoxEnvironmentProbe::initPersistFields()
{
// SceneObject already handles exposing the transform
Parent::initPersistFields();
removeField("radius");
}
void BoxEnvironmentProbe::inspectPostApply()
@ -154,7 +156,7 @@ void BoxEnvironmentProbe::updateProbeParams()
mProbeInfo->mProbeShapeType = ProbeRenderInst::Box;
}
void BoxEnvironmentProbe::prepRenderImage(SceneRenderState *state)
/*void BoxEnvironmentProbe::prepRenderImage(SceneRenderState *state)
{
if (!mEnabled || !ReflectionProbe::smRenderPreviewProbes)
return;
@ -223,7 +225,7 @@ void BoxEnvironmentProbe::prepRenderImage(SceneRenderState *state)
ri->type = RenderPassManager::RIT_Editor;
state->getRenderPass()->addInst(ri);
}
}
}*/
void BoxEnvironmentProbe::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)
{

View file

@ -108,7 +108,7 @@ public:
virtual void updateProbeParams();
// This is the function that allows this object to submit itself for rendering
void prepRenderImage(SceneRenderState *state);
//void prepRenderImage(SceneRenderState *state);
void setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat);
};

View file

@ -106,6 +106,7 @@ ReflectionProbe::ReflectionProbe()
mDirty = false;
mRadius = 10;
mObjScale = Point3F::One * 10;
mProbeRefScale = Point3F::One*10;
mUseCubemap = false;
@ -159,17 +160,19 @@ void ReflectionProbe::initPersistFields()
addGroup("Rendering");
addProtectedField("enabled", TypeBool, Offset(mEnabled, ReflectionProbe),
&_setEnabled, &defaultProtectedGetFn, "Regenerate Voxel Grid");
addField("radius", TypeF32, Offset(mRadius, ReflectionProbe), "The name of the material used to render the mesh.");
//addProtectedField("EditPosOffset", TypeBool, Offset(mEditPosOffset, ReflectionProbe),
// &_toggleEditPosOffset, &defaultProtectedGetFn, "Toggle Edit Pos Offset Mode", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
endGroup("Rendering");
addGroup("Reflection");
addProtectedField("radius", TypeF32, Offset(mRadius, ReflectionProbe), &_setRadius, &defaultProtectedGetFn,
"The name of the material used to render the mesh.");
addProtectedField("EditPosOffset", TypeBool, Offset(mEditPosOffset, ReflectionProbe),
&_toggleEditPosOffset, &defaultProtectedGetFn, "Toggle Edit Pos Offset Mode", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
addField("refOffset", TypePoint3F, Offset(mProbeRefOffset, ReflectionProbe), "");
addField("refScale", TypePoint3F, Offset(mProbeRefScale, ReflectionProbe), "");
addField("ReflectionMode", TypeReflectionModeEnum, Offset(mReflectionModeType, ReflectionProbe),
addProtectedField("ReflectionMode", TypeReflectionModeEnum, Offset(mReflectionModeType, ReflectionProbe), &_setReflectionMode, &defaultProtectedGetFn,
"The type of mesh data to use for collision queries.");
addField("StaticCubemap", TypeCubemapName, Offset(mCubemapName, ReflectionProbe), "Cubemap used instead of reflection texture if fullReflect is off.");
@ -217,15 +220,7 @@ bool ReflectionProbe::_doBake(void *object, const char *index, const char *data)
{
ReflectionProbe* probe = reinterpret_cast< ReflectionProbe* >(object);
//if (probe->mDirty)
// probe->bake(probe->mReflectionPath, 256);
ReflectionProbe *clientProbe = (ReflectionProbe*)probe->getClientObject();
if (clientProbe)
{
clientProbe->bake();
}
probe->bake();
return false;
}
@ -236,12 +231,39 @@ bool ReflectionProbe::_toggleEditPosOffset(void *object, const char *index, cons
probe->mEditPosOffset = !probe->mEditPosOffset;
//if (probe->mDirty)
// probe->bake(probe->mReflectionPath, 256);
return false;
}
bool ReflectionProbe::_setRadius(void *object, const char *index, const char *data)
{
ReflectionProbe* probe = reinterpret_cast<ReflectionProbe*>(object);
if (probe->mProbeShapeType != ProbeRenderInst::Sphere)
return false;
probe->mObjScale = Point3F(probe->mRadius, probe->mRadius, probe->mRadius);
return true;
}
bool ReflectionProbe::_setReflectionMode(void *object, const char *index, const char *data)
{
ReflectionProbe* probe = reinterpret_cast<ReflectionProbe*>(object);
if (data == "Static Cubemap")
{
probe->mReflectionModeType = StaticCubemap;
}
else if (data == "Baked Cubemap")
{
//Clear our cubemap if we changed it to be baked, just for cleanliness
probe->mReflectionModeType = BakedCubemap;
probe->mCubemapName = "";
}
return true;
}
bool ReflectionProbe::onAdd()
{
if (!Parent::onAdd())
@ -249,9 +271,8 @@ bool ReflectionProbe::onAdd()
mEditPosOffset = false;
mObjBox.minExtents.set(-1, -1, -1);
mObjBox.maxExtents.set(1, 1, 1);
//mObjScale.set(mRadius/2, mRadius/2, mRadius/2);
mObjBox.minExtents.set(-0.5, -0.5, -0.5);
mObjBox.maxExtents.set(0.5, 0.5, 0.5);
// Skip our transform... it just dirties mask bits.
Parent::setTransform(mObjToWorld);
@ -266,7 +287,7 @@ bool ReflectionProbe::onAdd()
if (!mPersistentId)
mPersistentId = getOrCreatePersistentId();
mProbeUniqueID = std::to_string(mPersistentId->getUUID().getHash()).c_str();
mProbeUniqueID = String::ToString(mPersistentId->getUUID().getHash());
}
// Refresh this object's material (if any)
@ -330,6 +351,49 @@ void ReflectionProbe::setTransform(const MatrixF & mat)
setMaskBits(TransformMask);
}
const MatrixF& ReflectionProbe::getTransform() const
{
if (!mEditPosOffset)
return mObjToWorld;
else
{
MatrixF transformMat = MatrixF::Identity;
transformMat.setPosition(mProbeRefOffset);
return transformMat;
}
}
void ReflectionProbe::setScale(const VectorF &scale)
{
if (!mEditPosOffset)
Parent::setScale(scale);
else
mProbeRefScale = scale;
mDirty = true;
// Dirty our network mask so that the new transform gets
// transmitted to the client object
setMaskBits(TransformMask);
}
const VectorF& ReflectionProbe::getScale() const
{
if (!mEditPosOffset)
return mObjScale;
else
return mProbeRefScale;
}
bool ReflectionProbe::writeField(StringTableEntry fieldname, const char *value)
{
if (fieldname == StringTable->insert("Bake") || fieldname == StringTable->insert("EditPosOffset"))
return false;
return Parent::writeField(fieldname, value);
}
U32 ReflectionProbe::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
{
// Allow the Parent to get a crack at writing its info
@ -338,8 +402,9 @@ U32 ReflectionProbe::packUpdate(NetConnection *conn, U32 mask, BitStream *stream
// Write our transform information
if (stream->writeFlag(mask & TransformMask))
{
mathWrite(*stream, getTransform());
mathWrite(*stream, getScale());
stream->writeFlag(mEditPosOffset);
mathWrite(*stream, mObjToWorld);
mathWrite(*stream, mObjScale);
mathWrite(*stream, mProbeRefOffset);
mathWrite(*stream, mProbeRefScale);
}
@ -385,10 +450,13 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
if (stream->readFlag()) // TransformMask
{
mEditPosOffset = stream->readFlag();
mathRead(*stream, &mObjToWorld);
mathRead(*stream, &mObjScale);
setTransform(mObjToWorld);
Parent::setTransform(mObjToWorld);
resetWorldBox();
mathRead(*stream, &mProbeRefOffset);
mathRead(*stream, &mProbeRefScale);
@ -491,7 +559,9 @@ void ReflectionProbe::updateProbeParams()
mProbeInfo->mTransform = getWorldTransform();
mProbeInfo->mPosition = getPosition();
mObjScale.set(mRadius, mRadius, mRadius);
if(mProbeShapeType == ProbeRenderInst::Sphere)
mObjScale.set(mRadius, mRadius, mRadius);
// Skip our transform... it just dirties mask bits.
Parent::setTransform(mObjToWorld);
@ -783,19 +853,24 @@ void ReflectionProbe::_onRenderViz(ObjectRenderInst *ri,
// Base the sphere color on the light color.
ColorI color = ColorI(255, 0, 255, 63);
const MatrixF worldToObjectXfm = getTransform();
const MatrixF worldToObjectXfm = mObjToWorld;
if (mProbeShapeType == ProbeRenderInst::Sphere)
{
draw->drawSphere(desc, mRadius, getPosition(), color);
}
else
{
Box3F projCube(-Point3F(mRadius, mRadius, mRadius),Point3F(mRadius, mRadius, mRadius));
Point3F tscl = worldToObjectXfm.getScale();
Box3F projCube(-mObjScale/2, mObjScale / 2);
projCube.setCenter(getPosition());
draw->drawCube(desc, projCube, color, &worldToObjectXfm);
}
Box3F refCube = Box3F(-mProbeRefScale/2, mProbeRefScale/2);
refCube.setCenter(getPosition()+mProbeRefOffset);
Point3F renderPos = getRenderTransform().getPosition();
Box3F refCube = Box3F(-mProbeRefScale / 2, mProbeRefScale / 2);
refCube.setCenter(renderPos + mProbeRefOffset);
color = ColorI(0, 255, 255, 63);
draw->drawCube(desc, refCube, color, &worldToObjectXfm);
}

View file

@ -186,6 +186,8 @@ public:
static bool _setEnabled(void *object, const char *index, const char *data);
static bool _doBake(void *object, const char *index, const char *data);
static bool _toggleEditPosOffset(void *object, const char *index, const char *data);
static bool _setRadius(void *object, const char *index, const char *data);
static bool _setReflectionMode(void *object, const char *index, const char *data);
// Handle when we are added to the scene and removed from the scene
bool onAdd();
@ -194,7 +196,12 @@ public:
virtual void handleDeleteAction();
// Override this so that we can dirty the network flag when it is called
void setTransform(const MatrixF &mat);
virtual void setTransform(const MatrixF &mat);
virtual const MatrixF& getTransform() const;
virtual void setScale(const VectorF &scale);
virtual const VectorF& getScale() const;
virtual bool writeField(StringTableEntry fieldname, const char *value);
// This function handles sending the relevant data from the server
// object to the client object

View file

@ -91,6 +91,12 @@ void Skylight::initPersistFields()
{
// SceneObject already handles exposing the transform
Parent::initPersistFields();
removeField("radius");
removeField("scale");
removeField("EditPosOffset");
removeField("refOffset");
removeField("refScale");
}
void Skylight::inspectPostApply()
@ -151,7 +157,7 @@ void Skylight::updateProbeParams()
{
Parent::updateProbeParams();
mProbeInfo->mProbeShapeType = ProbeRenderInst::Sphere;
mProbeInfo->mProbeShapeType = ProbeRenderInst::Skylight;
mProbeInfo->setPosition(getPosition());

View file

@ -43,7 +43,6 @@
class BaseMatInstance;
//-----------------------------------------------------------------------------
// This class implements a basic SceneObject that can exist in the world at a
// 3D position and render itself. There are several valid ways to render an

View file

@ -91,6 +91,8 @@ void SphereEnvironmentProbe::initPersistFields()
{
// SceneObject already handles exposing the transform
Parent::initPersistFields();
removeField("scale");
}
void SphereEnvironmentProbe::inspectPostApply()

View file

@ -333,8 +333,8 @@ void RenderProbeMgr::_setupStaticParameters()
if (!curEntry.mIrradianceCubemap->isInitialised())
continue;
if (curEntry.mIsSkylight)
continue;
//if (curEntry.mIsSkylight)
// continue;
mMipCount = curEntry.mCubemap.getPointer()->getMipMapLevels();
@ -350,7 +350,7 @@ void RenderProbeMgr::_setupStaticParameters()
probeBBMinData[mEffectiveProbeCount] = Point4F(bbMin.x, bbMin.y, bbMin.z, 0);
probeBBMaxData[mEffectiveProbeCount] = Point4F(bbMax.x, bbMax.y, bbMax.z, 0);
probeConfigData[mEffectiveProbeCount] = Point4F(curEntry.mProbeShapeType == ProbeRenderInst::Sphere ? 1 : 0,
probeConfigData[mEffectiveProbeCount] = Point4F(curEntry.mProbeShapeType,
curEntry.mRadius,
attenuation,
1);
@ -690,6 +690,8 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe *probe)
{
GFXDEBUGEVENT_SCOPE(RenderProbeMgr_Bake, ColorI::WHITE);
bool serverObj = probe->isServerObject();
Con::warnf("RenderProbeMgr::bakeProbe() - Beginning bake!");
U32 startMSTime = Platform::getRealMilliseconds();
@ -700,6 +702,9 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe *probe)
ReflectionProbe *clientProbe = static_cast<ReflectionProbe*>(probe->getClientObject());
if (clientProbe == nullptr)
return;
String probePrefilterPath = clientProbe->getPrefilterMapPath();
String probeIrradPath = clientProbe->getIrradianceMapPath();

View file

@ -88,8 +88,9 @@ struct ProbeRenderInst : public SystemInterface<ProbeRenderInst>
enum ProbeShapeType
{
Sphere = 0, ///< Sphere shaped
Box = 1, ///< Box-based shape
Box = 0, ///< Sphere shaped
Sphere = 1, ///< Box-based shape
Skylight = 2
};
ProbeShapeType mProbeShapeType;

View file

@ -484,7 +484,7 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
const MatrixF& getWorldTransform() const { return mWorldToObj; }
/// Returns the scale of the object
const VectorF& getScale() const { return mObjScale; }
virtual const VectorF& getScale() const { return mObjScale; }
/// Returns the bounding box for this object in local coordinates.
const Box3F& getObjBox() const { return mObjBox; }

View file

@ -32,8 +32,55 @@ uniform float4 probeConfigData[MAX_PROBES]; //r,g,b/mode,radius,atten
uniform float4 probeContribColors[MAX_PROBES];
#endif
//Probe IBL stuff
struct ProbeData
// Box Projected IBL Lighting
// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
/*float3 boxProject(float3 wsPosition, float3 wsEyeRay, float3 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax)
{
float3 positionLS = mul(worldToObjArray[id], float4(wsEyeRay, 1.0)).xyz;
//float3 rayLS = mul(worldToObjArray[id], float4(wsEyeRay, 1.0)).xyz;
//float3 reflCameraLS = mul(worldToObjArray[id], float4(reflectDir), 1.0)).xyz;
float3 nrdir = reflectDir;
float3 offset = wsPosition;
float3 plane1vec = (boxMax - offset) / nrdir;
float3 plane2vec = (boxMin - offset) / nrdir;
float3 furthestPlane = max(plane1vec, plane2vec);
float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
float3 posonbox = offset + nrdir * dist;
return posonbox - boxWSPos;
}*/
float3 iblSkylightDiffuse(Surface surface, ProbeData probe)
{
float lod = surface.roughness*cubeMips;
float3 color = TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, surface.N, probe.probeIdx, lod).xyz;
return color;
}
float3 iblSkylightSpecular(Surface surface, ProbeData probe)
{
// BRDF
float2 brdf = TORQUE_TEX2DLOD(BRDFTexture, float4(surface.roughness, surface.NdotV, 0.0, 0.0)).xy;
// Radiance (Specular)
#if DEBUGVIZ_SPECCUBEMAP == 0
float lod = surface.roughness*cubeMips;
#elif DEBUGVIZ_SPECCUBEMAP == 1
float lod = 0;
#endif
float3 color = TORQUE_TEXCUBEARRAYLOD(cubeMapAR, surface.N, probe.probeIdx, 0).xyz * (brdf.x + brdf.y);
//float3 color = float3(1, 1, 1);
return color;
}
float3 iblBoxDiffuse( Surface surface, ProbeData probe)
{
float3 wsPosition;
float radius;
@ -169,14 +216,19 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
{
probes[i].defineBoxSpaceInfluence(surface, IN.wsEyeRay);
}
else
else if (probes[i].type == 1) //sphere
{
probes[i].defineSphereSpaceInfluence(surface,IN.wsEyeRay);
}
if (probes[i].contribution>1||probes[i].contribution<0)
probes[i].contribution = 0;
blendSum += probes[i].contribution;
invBlendSum += (1.0f - probes[i].contribution);
else //skylight
{
//
blendVal[i] = 1;
}
blendVal[i] = saturate(blendVal[i]);
blendSum += blendVal[i];
invBlendSum += (1.0f - blendVal[i]);
}
// Weight0 = normalized NDF, inverted to have 1 at center, 0 at boundary.
@ -248,9 +300,18 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
if (probes[i].contribution == 0)
continue;
irradiance += probes[i].iblBoxDiffuse(surface);
specular += F*probes[i].iblBoxSpecular(surface);
if (probes[i].type == 2) //skylight
{
irradiance += blendFactor[i] * iblSkylightDiffuse(surface, probes[i]);
specular += blendFactor[i] * F * iblSkylightSpecular(surface, probes[i]);
}
else
{
irradiance += blendFactor[i] * iblBoxDiffuse(surface, probes[i]);
specular += blendFactor[i] * F*iblBoxSpecular(surface, probes[i]);
}
}
//final diffuse color
@ -263,7 +324,14 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
float3 cubeColor = float3(0, 0, 0);
for (i = 0; i < numProbes; ++i)
{
cubeColor += probes[i].iblBoxSpecular(surface);
//if (probes[i].type == 2) //skylight
//{
cubeColor += blendFactor[i] * iblSkylightSpecular(surface, probes[i]);
/*}
else
{
cubeColor += blendFactor[i] * iblBoxSpecular(surface, probes[i]);
}*/
}
return float4(cubeColor, 1);
@ -271,7 +339,14 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
float3 cubeColor = float3(0, 0, 0);
for (i = 0; i < numProbes; ++i)
{
cubeColor += probes[i].iblBoxDiffuse(surface);
//if (probes[i].type == 2) //skylight
//{
cubeColor += blendFactor[i] * iblSkylightDiffuse(surface, probes[i]);
/*}
else
{
cubeColor += blendFactor[i] * iblBoxDiffuse(surface, probes[i]);
}*/
}
return float4(cubeColor, 1);