diff --git a/Engine/source/lighting/probeManager.cpp b/Engine/source/lighting/probeManager.cpp index fea0cc474..f9c3c6b6a 100644 --- a/Engine/source/lighting/probeManager.cpp +++ b/Engine/source/lighting/probeManager.cpp @@ -129,7 +129,8 @@ ProbeShaderConstants::ProbeShaderConstants() mProbeBoxMaxSC(NULL), mProbeIsSphereSC(NULL), mProbeLocalPosSC(NULL), - mProbeCubemapSC(NULL) + mProbeCubemapSC(NULL), + mProbeCountSC(NULL) { } @@ -163,6 +164,7 @@ void ProbeShaderConstants::init(GFXShader* shader) mProbeIsSphereSC = shader->getShaderConstHandle(ShaderGenVars::probeIsSphere); mProbeLocalPosSC = shader->getShaderConstHandle(ShaderGenVars::probeLocalPos); mProbeCubemapSC = shader->getShaderConstHandle(ShaderGenVars::probeCubemap); + mProbeCountSC = shader->getShaderConstHandle(ShaderGenVars::probeCount); mInit = true; } @@ -182,6 +184,7 @@ ProbeManager::ProbeManager() mSkylightMaterial = nullptr; mReflectProbeMaterial = nullptr; + mReflectProbeArrayMaterial = nullptr; } ProbeManager::~ProbeManager() @@ -624,6 +627,22 @@ ProbeManager::ReflectProbeMaterialInfo* ProbeManager::getReflectProbeMaterial() return mReflectProbeMaterial; } +ProbeManager::ReflectionProbeArrayMaterialInfo* ProbeManager::getReflectProbeArrayMaterial() +{ + PROFILE_SCOPE(AdvancedLightBinManager_getReflectProbeArrayMaterial); + + //ReflectProbeMaterialInfo *info = NULL; + + if (!mReflectProbeArrayMaterial) + { + // Now create the material info object. + mReflectProbeArrayMaterial = new ReflectionProbeArrayMaterialInfo("ReflectionProbeArrayMaterial", + getGFXVertexFormat()); + } + + return mReflectProbeArrayMaterial; +} + void ProbeManager::setupSkylightProbe(ProbeRenderInst *probeInfo) { probeInfo->vertBuffer = getSphereMesh(probeInfo->numPrims, probeInfo->primBuffer); @@ -756,11 +775,19 @@ GFXVertexBufferHandle ProbeManager::getSphereMesh(U32 &outNumPrimit // bool ReflectProbeMatInstance::init(const FeatureSet &features, const GFXVertexFormat *vertexFormat) { + mShaderMat = nullptr; + bool success = Parent::init(features, vertexFormat); // If the initialization failed don't continue. if (!success || !mProcessedMaterial || mProcessedMaterial->getNumPasses() == 0) return false; + + mShaderMat = static_cast(getShaderMaterial()); + mShaderMat->init(features, vertexFormat, mFeaturesDelegate); + + //mShaderMat->setMaterialParameters(mDefaultParameters, 0); + return true; } @@ -814,6 +841,41 @@ bool SkylightMatInstance::setupPass(SceneRenderState *state, const SceneData &sg return true; } + +bool ReflectProbeArrayMatInstance::init(const FeatureSet &features, const GFXVertexFormat *vertexFormat) +{ + bool success = Parent::init(features, vertexFormat); + + // If the initialization failed don't continue. + if (!success || !mProcessedMaterial || mProcessedMaterial->getNumPasses() == 0) + return false; + return true; +} + +bool ReflectProbeArrayMatInstance::setupPass(SceneRenderState *state, const SceneData &sgData) +{ + if (!Parent::setupPass(state, sgData)) + return false; + + AssertFatal(mProcessedMaterial->getNumPasses() > 0, "No passes created! Ohnoes"); + const RenderPassData *rpd = mProcessedMaterial->getPass(0); + AssertFatal(rpd, "No render pass data!"); + AssertFatal(rpd->mRenderStates[0], "No render state 0!"); + + if (!mProjectionState) + { + GFXStateBlockDesc desc; + desc.setZReadWrite(false); + desc.zWriteEnable = false; + desc.setCullMode(GFXCullNone); + desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvDestAlpha, GFXBlendOpAdd); + mProjectionState = GFX->createStateBlock(desc); + } + // Now override stateblock with our own + GFX->setStateBlock(mProjectionState); + + return true; +} // // ProbeManager::ReflectProbeMaterialInfo::ReflectProbeMaterialInfo(const String &matName, @@ -861,6 +923,8 @@ ProbeManager::ReflectProbeMaterialInfo::ReflectProbeMaterialInfo(const String &m useSphereMode = matInstance->getMaterialParameterHandle("$useSphereMode"); + probeCount = matInstance->getMaterialParameterHandle("$numProbes"); + for (U32 i = 0; i < 9; i++) shTerms[i] = matInstance->getMaterialParameterHandle(String::ToString("$SHTerms%d", i)); @@ -1010,6 +1074,41 @@ ProbeManager::SkylightMaterialInfo::~SkylightMaterialInfo() SAFE_DELETE(matInstance); } +// +// +ProbeManager::ReflectionProbeArrayMaterialInfo::ReflectionProbeArrayMaterialInfo(const String &matName, + const GFXVertexFormat *vertexFormat) + : ReflectProbeMaterialInfo(matName, vertexFormat) +{ + Material *mat = MATMGR->getMaterialDefinitionByName(matName); + if (!mat) + return; + + matInstance = new ReflectProbeArrayMatInstance(*mat); + + const Vector ¯os = Vector(); + + for (U32 i = 0; i < macros.size(); i++) + matInstance->addShaderMacro(macros[i].name, macros[i].value); + + matInstance->init(MATMGR->getDefaultFeatures(), vertexFormat); + + farPlane = matInstance->getMaterialParameterHandle("$farPlane"); + vsFarPlane = matInstance->getMaterialParameterHandle("$vsFarPlane"); + negFarPlaneDotEye = matInstance->getMaterialParameterHandle("$negFarPlaneDotEye"); + zNearFarInvNearFar = matInstance->getMaterialParameterHandle("$zNearFarInvNearFar"); + + useCubemap = matInstance->getMaterialParameterHandle("$useCubemap"); + cubemap = matInstance->getMaterialParameterHandle("$cubeMap"); + + eyePosWorld = matInstance->getMaterialParameterHandle("$eyePosWorld"); +} + +ProbeManager::ReflectionProbeArrayMaterialInfo::~ReflectionProbeArrayMaterialInfo() +{ + SAFE_DELETE(matInstance); +} + /*bool ProbeManager::lightScene( const char* callback, const char* param ) { BitSet32 flags = 0; diff --git a/Engine/source/lighting/probeManager.h b/Engine/source/lighting/probeManager.h index b2e8ad82e..4996a379c 100644 --- a/Engine/source/lighting/probeManager.h +++ b/Engine/source/lighting/probeManager.h @@ -56,6 +56,8 @@ #include "core/util/SystemInterfaceList.h" +#include "materials/processedShaderMaterial.h" + class SimObject; class ProbeManager; class Material; @@ -177,6 +179,7 @@ struct ProbeShaderConstants GFXShaderConstHandle *mProbeIsSphereSC; GFXShaderConstHandle *mProbeLocalPosSC; GFXShaderConstHandle *mProbeCubemapSC; + GFXShaderConstHandle *mProbeCountSC; ProbeShaderConstants(); ~ProbeShaderConstants(); @@ -197,11 +200,15 @@ protected: GFXStateBlockRef mProjectionState; + ProcessedShaderMaterial* mShaderMat; + public: ReflectProbeMatInstance(Material &mat) : Parent(mat), mProbeParamsSC(NULL), mInternalPass(false), mProjectionState(NULL) {} virtual bool init(const FeatureSet &features, const GFXVertexFormat *vertexFormat); virtual bool setupPass(SceneRenderState *state, const SceneData &sgData); + + ProcessedShaderMaterial* getProcessedShaderMaterial() { return mShaderMat; } }; class SkylightMatInstance : public ReflectProbeMatInstance @@ -216,6 +223,22 @@ public: virtual bool setupPass(SceneRenderState *state, const SceneData &sgData); }; +class ReflectProbeArrayMatInstance : public MatInstance +{ + typedef MatInstance Parent; +protected: + MaterialParameterHandle * mProbeParamsSC; + bool mInternalPass; + + GFXStateBlockRef mProjectionState; + +public: + ReflectProbeArrayMatInstance(Material &mat) : Parent(mat), mProbeParamsSC(NULL), mInternalPass(false), mProjectionState(NULL) {} + + virtual bool init(const FeatureSet &features, const GFXVertexFormat *vertexFormat); + virtual bool setupPass(SceneRenderState *state, const SceneData &sgData); +}; + class ProbeManager { public: @@ -254,6 +277,8 @@ public: MaterialParameterHandle *shTerms[9]; MaterialParameterHandle *shConsts[5]; + MaterialParameterHandle *probeCount; + ReflectProbeMaterialInfo(const String &matName, const GFXVertexFormat *vertexFormat); virtual ~ReflectProbeMaterialInfo(); @@ -275,6 +300,15 @@ public: virtual ~SkylightMaterialInfo(); }; + struct ReflectionProbeArrayMaterialInfo : public ReflectProbeMaterialInfo + { + ReflectionProbeArrayMaterialInfo(const String &matName, const GFXVertexFormat *vertexFormat); + + ReflectProbeArrayMatInstance *matInstance; + + virtual ~ReflectionProbeArrayMaterialInfo(); + }; + enum SpecialProbeTypesEnum { SkylightProbeType, @@ -353,6 +387,7 @@ public: ReflectProbeMaterialInfo* getReflectProbeMaterial(); SkylightMaterialInfo* getSkylightMaterial(); + ReflectionProbeArrayMaterialInfo* getReflectProbeArrayMaterial(); protected: @@ -415,6 +450,8 @@ protected: SkylightMaterialInfo* mSkylightMaterial; + ReflectionProbeArrayMaterialInfo* mReflectProbeArrayMaterial; + GFXVertexBufferHandle getSphereMesh(U32 &outNumPrimitives, GFXPrimitiveBufferHandle &outPrimitives);; }; diff --git a/Engine/source/materials/processedShaderMaterial.h b/Engine/source/materials/processedShaderMaterial.h index 464f7e20f..e95819087 100644 --- a/Engine/source/materials/processedShaderMaterial.h +++ b/Engine/source/materials/processedShaderMaterial.h @@ -266,9 +266,11 @@ protected: void _setPrimaryLightConst(const LightInfo* light, const MatrixF& objTrans, const U32 stageNum); /// This is here to deal with the differences between ProcessedCustomMaterials and ProcessedShaderMaterials. +public: virtual GFXShaderConstBuffer* _getShaderConstBuffer(const U32 pass); virtual ShaderConstHandles* _getShaderConstHandles(const U32 pass); +protected: /// virtual void _initMaterialParameters(); diff --git a/Engine/source/renderInstance/renderProbeMgr.cpp b/Engine/source/renderInstance/renderProbeMgr.cpp index 39426c3f1..d1f308634 100644 --- a/Engine/source/renderInstance/renderProbeMgr.cpp +++ b/Engine/source/renderInstance/renderProbeMgr.cpp @@ -33,6 +33,8 @@ #include "gfx/gfxDebugEvent.h" +#include "materials/shaderData.h" + IMPLEMENT_CONOBJECT(RenderProbeMgr); ConsoleDocClass( RenderProbeMgr, @@ -116,34 +118,43 @@ void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state) // Now build the quad for drawing full-screen vector light // passes.... this is a volatile VB and updates every frame. - FarFrustumQuadVert verts[4]; + GFXVertexPC verts[4]; { verts[0].point.set(wsFrustumPoints[Frustum::FarTopLeft] - cameraPos); - invCam.mulP(wsFrustumPoints[Frustum::FarTopLeft], &verts[0].normal); - verts[0].texCoord.set(-1.0, 1.0); - verts[0].tangent.set(wsFrustumPoints[Frustum::FarTopLeft] - cameraOffsetPos); + //invCam.mulP(wsFrustumPoints[Frustum::FarTopLeft], &verts[0].normal); + //verts[0].texCoord.set(-1.0, 1.0); + //verts[0].tangent.set(wsFrustumPoints[Frustum::FarTopLeft] - cameraOffsetPos); verts[1].point.set(wsFrustumPoints[Frustum::FarTopRight] - cameraPos); - invCam.mulP(wsFrustumPoints[Frustum::FarTopRight], &verts[1].normal); - verts[1].texCoord.set(1.0, 1.0); - verts[1].tangent.set(wsFrustumPoints[Frustum::FarTopRight] - cameraOffsetPos); + // invCam.mulP(wsFrustumPoints[Frustum::FarTopRight], &verts[1].normal); + //verts[1].texCoord.set(1.0, 1.0); + //verts[1].tangent.set(wsFrustumPoints[Frustum::FarTopRight] - cameraOffsetPos); verts[2].point.set(wsFrustumPoints[Frustum::FarBottomLeft] - cameraPos); - invCam.mulP(wsFrustumPoints[Frustum::FarBottomLeft], &verts[2].normal); - verts[2].texCoord.set(-1.0, -1.0); - verts[2].tangent.set(wsFrustumPoints[Frustum::FarBottomLeft] - cameraOffsetPos); + //invCam.mulP(wsFrustumPoints[Frustum::FarBottomLeft], &verts[2].normal); + // verts[2].texCoord.set(-1.0, -1.0); + // verts[2].tangent.set(wsFrustumPoints[Frustum::FarBottomLeft] - cameraOffsetPos); verts[3].point.set(wsFrustumPoints[Frustum::FarBottomRight] - cameraPos); - invCam.mulP(wsFrustumPoints[Frustum::FarBottomRight], &verts[3].normal); - verts[3].texCoord.set(1.0, -1.0); - verts[3].tangent.set(wsFrustumPoints[Frustum::FarBottomRight] - cameraOffsetPos); + // invCam.mulP(wsFrustumPoints[Frustum::FarBottomRight], &verts[3].normal); + // verts[3].texCoord.set(1.0, -1.0); + // verts[3].tangent.set(wsFrustumPoints[Frustum::FarBottomRight] - cameraOffsetPos); } + + Point3F norms[4]; + { + invCam.mulP(wsFrustumPoints[Frustum::FarTopLeft], &norms[0]); + invCam.mulP(wsFrustumPoints[Frustum::FarTopRight], &norms[1]); + invCam.mulP(wsFrustumPoints[Frustum::FarBottomLeft], &norms[2]); + invCam.mulP(wsFrustumPoints[Frustum::FarBottomRight], &norms[3]); + } + mFarFrustumQuadVerts.set(GFX, 4); dMemcpy(mFarFrustumQuadVerts.lock(), verts, sizeof(verts)); mFarFrustumQuadVerts.unlock(); PlaneF farPlane(wsFrustumPoints[Frustum::FarBottomLeft], wsFrustumPoints[Frustum::FarTopLeft], wsFrustumPoints[Frustum::FarTopRight]); - PlaneF vsFarPlane(verts[0].normal, verts[1].normal, verts[2].normal); + PlaneF vsFarPlane(norms[0], norms[1], norms[2]); // Parameters calculated, assign them to the materials @@ -168,6 +179,17 @@ void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state) farPlane, vsFarPlane); } + + ProbeManager::ReflectionProbeArrayMaterialInfo* reflProbeArrayMat = PROBEMGR->getReflectProbeArrayMaterial(); + + if (reflProbeArrayMat != nullptr && reflProbeArrayMat->matInstance != nullptr) + { + reflProbeArrayMat->setViewParameters(frustum.getNearDist(), + frustum.getFarDist(), + frustum.getPosition(), + farPlane, + vsFarPlane); + } } //----------------------------------------------------------------------------- @@ -230,7 +252,7 @@ void RenderProbeMgr::render( SceneRenderState *state ) ProbeManager::SkylightMaterialInfo* skylightMat = PROBEMGR->getSkylightMaterial(); ProbeManager::ReflectProbeMaterialInfo* reflProbeMat = PROBEMGR->getReflectProbeMaterial(); - for (U32 i = 0; i < ProbeRenderInst::all.size(); i++) + /*for (U32 i = 0; i < ProbeRenderInst::all.size(); i++) { ProbeRenderInst* curEntry = ProbeRenderInst::all[i]; @@ -268,54 +290,155 @@ void RenderProbeMgr::render( SceneRenderState *state ) GFX->drawPrimitive(GFXTriangleList, 0, curEntry->numPrims); } } + }*/ + + //Array rendering + static U32 MAXPROBECOUNT = 50; + + U32 probeCount = PROBEMGR->mRegisteredProbes.size(); + + if (probeCount != 0) + { + AlignedArray probePositions(MAXPROBECOUNT, sizeof(Point3F)); + dMemset(probePositions.getBuffer(), 0, probePositions.getBufferSize()); + + if (reflProbeMat && reflProbeMat->matInstance) + { + MaterialParameters *matParams = reflProbeMat->matInstance->getMaterialParameters(); + + MaterialParameterHandle *numProbesSC = reflProbeMat->matInstance->getMaterialParameterHandle("$numProbes"); + matParams->setSafe(numProbesSC, (float)probeCount); + + //ProcessedShaderMaterial* processedMat = reflProbeMat->matInstance->getProcessedShaderMaterial(); + //GFXShaderConstBuffer* shaderConsts = processedMat->_getShaderConstBuffer(0); + + //ProbeShaderConstants *psc = PROBEMGR->getProbeShaderConstants(shaderConsts); + + MaterialParameterHandle *probePositionSC = reflProbeMat->matInstance->getMaterialParameterHandle("$inProbePosArray"); + + U32 effectiveProbeCount = 0; + + for (U32 i = 0; i < probeCount; i++) + { + if (effectiveProbeCount >= MAXPROBECOUNT) + break; + + ProbeRenderInst* curEntry = ProbeRenderInst::all[PROBEMGR->mRegisteredProbes[i]]; + + /*if (!curEntry->mIsEnabled) + continue; + + if (curEntry->numPrims == 0) + continue; + + if (curEntry->mIsSkylight && (!skylightMat || !skylightMat->matInstance)) + continue; + + if (!curEntry->mIsSkylight && (!reflProbeMat || !reflProbeMat->matInstance)) + break;*/ + + //Setup + const Point3F &probePos = curEntry->getPosition(); + probePositions[i].x = probePos.x; + probePositions[i].y = probePos.y; + probePositions[i].z = probePos.z; + + Point3F test = probePositions[i]; + + MatrixF probeTrans = curEntry->getTransform(); + + if (!curEntry->mIsSkylight) + { + //if (curEntry->mProbeShapeType == ProbeRenderInst::Sphere) + // probeTrans.scale(curEntry->mRadius * 1.01f); + + sgData.objTrans = &probeTrans; + + reflProbeMat->setProbeParameters(curEntry, state, worldToCameraXfm); + } + + effectiveProbeCount++; + } + + if (effectiveProbeCount != 0) + { + Con::printf("Probe aligned position count: %i", probeCount); + + for (U32 p = 0; p < probeCount; p++) + { + Point3F prb = probePositions[p]; + + Con::printf("Probe %i aligned position is: %g %g %g", p, prb.x, prb.y, prb.z); + + bool tasadfh = true; + } + + matParams->set(probePositionSC, probePositions); + + // Set geometry + GFX->setVertexBuffer(mFarFrustumQuadVerts); + GFX->setPrimitiveBuffer(NULL); + + while (reflProbeMat->matInstance->setupPass(state, sgData)) + { + // Set transforms + matrixSet.setWorld(*sgData.objTrans); + reflProbeMat->matInstance->setTransforms(matrixSet, state); + reflProbeMat->matInstance->setSceneInfo(state, sgData); + + GFX->drawPrimitive(GFXTriangleStrip, 0, 2); + } + } + } } + // + // + /*ProbeManager::ReflectionProbeArrayMaterialInfo* reflProbeArrayMat = PROBEMGR->getReflectProbeArrayMaterial(); for (U32 i = 0; i < ProbeRenderInst::all.size(); i++) { - ProbeRenderInst* curEntry = ProbeRenderInst::all[i]; + if (i > 0) + return; - if (!curEntry->mIsEnabled) - continue; + ProbeRenderInst* curEntry = ProbeRenderInst::all[i]; - if (curEntry->numPrims == 0) - continue; + if (!reflProbeArrayMat || !reflProbeArrayMat->matInstance) + break; - if (curEntry->mIsSkylight && (!skylightMat || !skylightMat->matInstance)) - continue; + //Setup + //MatrixF probeTrans = curEntry->getTransform(); - if (!curEntry->mIsSkylight && (!reflProbeMat || !reflProbeMat->matInstance)) - break; + //if (!curEntry->mIsSkylight) + { + //if (curEntry->mProbeShapeType == ProbeRenderInst::Sphere) + // probeTrans.scale(curEntry->mRadius * 1.01f); - //Setup - MatrixF probeTrans = curEntry->getTransform(); - - if (!curEntry->mIsSkylight) - { - if (curEntry->mProbeShapeType == ProbeRenderInst::Sphere) - probeTrans.scale(curEntry->mRadius * 1.01f); + //sgData.objTrans = &state-; - sgData.objTrans = &probeTrans; + reflProbeArrayMat->setProbeParameters(curEntry, state, worldToCameraXfm); - reflProbeMat->setProbeParameters(curEntry, state, worldToCameraXfm); + // Set geometry + GFX->setVertexBuffer(mFarFrustumQuadVerts); + GFX->setPrimitiveBuffer(NULL); + while (reflProbeArrayMat->matInstance->setupPass(state, sgData)) + { + // Set transforms + //matrixSet.setWorld(*sgData.objTrans); + reflProbeArrayMat->matInstance->setTransforms(matrixSet, state); + reflProbeArrayMat->matInstance->setSceneInfo(state, sgData); - // Set geometry - GFX->setVertexBuffer(curEntry->vertBuffer); - GFX->setPrimitiveBuffer(curEntry->primBuffer); - while (reflProbeMat->matInstance->setupPass(state, sgData)) - { - // Set transforms - matrixSet.setWorld(*sgData.objTrans); - reflProbeMat->matInstance->setTransforms(matrixSet, state); - reflProbeMat->matInstance->setSceneInfo(state, sgData); - - GFX->drawPrimitive(GFXTriangleList, 0, curEntry->numPrims); - } - } - } + GFX->drawPrimitive(GFXTriangleStrip, 0, 2); + } + } + }*/ + // + // GFX->popActiveRenderTarget(); //PROBEMGR->unregisterAllProbes(); + PROBEMGR->mRegisteredProbes.clear(); + PROFILE_END(); GFX->setVertexBuffer(NULL); diff --git a/Engine/source/renderInstance/renderProbeMgr.h b/Engine/source/renderInstance/renderProbeMgr.h index 205678ed5..e53447d48 100644 --- a/Engine/source/renderInstance/renderProbeMgr.h +++ b/Engine/source/renderInstance/renderProbeMgr.h @@ -38,18 +38,18 @@ #include "gfx/gfxVertexBuffer.h" #endif +#include "postFx/postEffectCommon.h" + //************************************************************************** // RenderObjectMgr //************************************************************************** class RenderProbeMgr : public RenderBinManager { typedef RenderBinManager Parent; -public: - typedef GFXVertexPNTT FarFrustumQuadVert; protected: - GFXVertexBufferHandle mFarFrustumQuadVerts; + GFXVertexBufferHandle mFarFrustumQuadVerts; public: RenderProbeMgr(); diff --git a/Engine/source/shaderGen/shaderGenVars.cpp b/Engine/source/shaderGen/shaderGenVars.cpp index 60de56410..90e08739f 100644 --- a/Engine/source/shaderGen/shaderGenVars.cpp +++ b/Engine/source/shaderGen/shaderGenVars.cpp @@ -77,6 +77,7 @@ const String ShaderGenVars::probeBoxMax("$inProbeBoxMax"); const String ShaderGenVars::probeLocalPos("$inProbeLocalPos"); const String ShaderGenVars::probeIsSphere("$inProbeIsSphere"); const String ShaderGenVars::probeCubemap("$inProbeCubemap"); +const String ShaderGenVars::probeCount("$numProbes"); // These are ignored by the D3D layers. const String ShaderGenVars::fogMap("$fogMap"); diff --git a/Engine/source/shaderGen/shaderGenVars.h b/Engine/source/shaderGen/shaderGenVars.h index a0ed88860..f35e81aab 100644 --- a/Engine/source/shaderGen/shaderGenVars.h +++ b/Engine/source/shaderGen/shaderGenVars.h @@ -90,6 +90,7 @@ struct ShaderGenVars const static String probeLocalPos; const static String probeIsSphere; const static String probeCubemap; + const static String probeCount; // Textures const static String fogMap; diff --git a/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs b/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs index 54c0f5dbd..fdb96ef9d 100644 --- a/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs +++ b/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs @@ -405,5 +405,34 @@ new CustomMaterial( SkyLightMaterial ) sampler["matInfoBuffer"] = "#matinfo"; sampler["colorBuffer"] = "#color"; + pixVersion = 3.0; +}; + +new ShaderData( ReflectionProbeArrayShader ) +{ + DXVertexShaderFile = "shaders/common/lighting/advanced/convexGeometryV.hlsl"; + DXPixelShaderFile = "shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl"; + + OGLVertexShaderFile = "shaders/common/lighting/advanced/gl/convexGeometryV.glsl"; + OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/reflectionProbeArrayP.glsl"; + + samplerNames[0] = "$deferredBuffer"; + samplerNames[1] = "$colorBuffer"; + samplerNames[2] = "$matInfoBuffer"; + samplerNames[3] = "$cubeMap"; + samplerNames[4] = "$irradianceCubemap"; + samplerNames[5] = "$BRDFTexture"; + + pixVersion = 3.0; +}; + +new CustomMaterial( ReflectionProbeArrayMaterial ) +{ + shader = ReflectionProbeArrayShader; + stateBlock = AL_ProbeState; + + sampler["deferredBuffer"] = "#deferred"; + sampler["matInfoBuffer"] = "#matinfo"; + pixVersion = 3.0; }; \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/reflectionProbeArrayP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/reflectionProbeArrayP.glsl new file mode 100644 index 000000000..8edf5c3e6 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/reflectionProbeArrayP.glsl @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../../torque.hlsl" + +struct ConnectData +{ + float4 hpos : TORQUE_POSITION; + float2 uv : TEXCOORD; +}; + +uniform int face; + +TORQUE_UNIFORM_SAMPLERCUBE(environmentMap, 0); + +float4 main(ConnectData IN) : TORQUE_TARGET0 +{ + float3 N = getCubeDir(face,IN.uv); + float3 irradiance = 0; + + // tangent space calculation from origin point + float3 up = float3(0.0, 0.0, 1.0); + float3 right = cross(up, N); + up = cross(N, right); + + float sampleDelta = 0.025; + int nrSamples = 0; + for(float phi = 0.0; phi < M_2PI_F; phi += sampleDelta) + { + for(float theta = 0.0; theta < M_HALFPI_F; theta += sampleDelta) + { + // spherical to cartesian (in tangent space) + float3 tangentSample = float3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); + // tangent space to world + float3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; + + irradiance += TORQUE_TEXCUBE(environmentMap, sampleVec).rgb * cos(theta) * sin(theta); + nrSamples++; + } + } + irradiance = M_PI_F * irradiance * (1.0 / float(nrSamples)); + + return float4(irradiance, 1.0); +} \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl new file mode 100644 index 000000000..af6a61ca0 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl @@ -0,0 +1,152 @@ +#include "../../shaderModelAutoGen.hlsl" + +#include "farFrustumQuad.hlsl" +#include "../../lighting.hlsl" +#include "../../torque.hlsl" + +struct ConvexConnectP +{ + float4 pos : TORQUE_POSITION; + float4 wsEyeDir : TEXCOORD0; + float4 ssPos : TEXCOORD1; + float4 vsEyeDir : TEXCOORD2; +}; + +TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0); +TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 1); +TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 2); +TORQUE_UNIFORM_SAMPLERCUBE(cubeMap, 3); +TORQUE_UNIFORM_SAMPLERCUBE(irradianceCubemap, 4); +TORQUE_UNIFORM_SAMPLER2D(BRDFTexture, 5); +uniform float cubeMips; + +uniform float4 rtParams0; + +uniform float3 probeWSPos; +uniform float3 probeLSPos; +uniform float4 vsFarPlane; + +uniform float radius; +uniform float2 attenuation; + +uniform float4x4 worldToObj; +uniform float4x4 cameraToWorld; + +uniform float3 eyePosWorld; +uniform float3 bbMin; +uniform float3 bbMax; + +uniform float useSphereMode; + +float3 boxProject(float3 wsPosition, float3 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax) +{ + 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 iblBoxSpecular(float3 normal, float3 wsPos, float roughness, float3 surfToEye, + TORQUE_SAMPLER2D(brdfTexture), + //TORQUE_SAMPLERCUBE(radianceCube), + float3 boxPos, + float3 boxMin, + float3 boxMax) +{ + float ndotv = clamp(dot(normal, surfToEye), 0.0, 1.0); + + // BRDF + float2 brdf = TORQUE_TEX2DLOD(brdfTexture, float4(roughness, ndotv,0.0,0.0)).xy; + + // Radiance (Specular) + float maxmip = pow(cubeMips+1,2); + float lod = roughness*maxmip; + float3 r = reflect(surfToEye, normal); + float3 cubeR = normalize(r); + cubeR = boxProject(wsPos, cubeR, boxPos, boxMin, boxMax); + + float3 radiance = float3(1,1,1);//TORQUE_TEXCUBELOD(radianceCube, float4(cubeR, lod)).xyz * (brdf.x + brdf.y); + + return radiance; +} + +float4 main(ConvexConnectP IN) : SV_TARGET +{ + // Compute scene UV + float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; + float2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); + + //eye ray WS/LS + float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane ); + float3 wsEyeRay = mul(cameraToWorld, float4(vsEyeRay, 0)).xyz; + + //unpack normal and linear depth + float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene); + + //create surface + Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer), + uvScene, eyePosWorld, wsEyeRay, cameraToWorld); + float blendVal = 1.0; + + [unroll] + for(float i=0; i < 10; i++) + { + float3 probeWSPos = float3(i * 1.1, 0, 2); + float3 L = probeWSPos - surface.P; + blendVal = 1.0-length(L)/radius; + clip(blendVal); + } + + //render into the bound space defined above + float3 surfToEye = normalize(surface.P - eyePosWorld); + float3 irradiance = float3(1,0,0);//TORQUE_TEXCUBELOD(irradianceCubemap, float4(surface.N,0)).xyz; + float3 specular = iblBoxSpecular(surface.N, surface.P, surface.roughness, surfToEye, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture)/*, TORQUE_SAMPLERCUBE_MAKEARG(cubeMap)*/, probeWSPos, bbMin, bbMax); + float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness); + specular *= F; + //energy conservation + float3 kD = 1.0.xxx - F; + kD *= 1.0 - surface.metalness; + //final diffuse color + float3 diffuse = kD * irradiance * surface.baseColor.rgb; + + return float4(diffuse + specular * surface.ao, blendVal); + + /*float3 N = getCubeDir(face,IN.uv); + float3 irradiance = 0; + + // tangent space calculation from origin point + float3 up = float3(0.0, 0.0, 1.0); + float3 right = cross(up, N); + up = cross(N, right); + + float sampleDelta = 0.025; + int nrSamples = 0; + for(float phi = 0.0; phi < M_2PI_F; phi += sampleDelta) + { + for(float theta = 0.0; theta < M_HALFPI_F; theta += sampleDelta) + { + // spherical to cartesian (in tangent space) + float3 tangentSample = float3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); + // tangent space to world + float3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; + + irradiance += TORQUE_TEXCUBE(environmentMap, sampleVec).rgb * cos(theta) * sin(theta); + nrSamples++; + } + } + irradiance = M_PI_F * irradiance * (1.0 / float(nrSamples)); + + return float4(irradiance, 1.0);*/ + + //return float4(1,0,0,1); + + //float4 texCoord = float4( 1,0,0, 1 ); + + //return texCoord; +} \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl index 9af29fa91..89125a7b6 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl @@ -38,6 +38,11 @@ uniform float3 bbMax; uniform float useSphereMode; +#define MAX_PROBES 50 + +uniform float numProbes; +uniform float3 inProbePosArray[MAX_PROBES]; + // 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/ @@ -112,7 +117,7 @@ float4 main( ConvexConnectP IN ) : SV_TARGET Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer), uvScene, eyePosWorld, wsEyeRay, cameraToWorld); float blendVal = 1.0; - if(useSphereMode) + /*if(useSphereMode) { float3 L = probeWSPos - surface.P; blendVal = 1.0-length(L)/radius; @@ -125,11 +130,29 @@ float4 main( ConvexConnectP IN ) : SV_TARGET clip(blendVal); float compression = 0.05; blendVal=(1.0-compression)+blendVal*compression; - } - //render into the bound space defined above - float3 surfToEye = normalize(surface.P - eyePosWorld); - float3 irradiance = TORQUE_TEXCUBELOD(irradianceCubemap, float4(surface.N,0)).xyz; + }*/ + + float3 surfToEye = normalize(surface.P - eyePosWorld); + float3 irradiance = TORQUE_TEXCUBELOD(irradianceCubemap, float4(surface.N,0)).xyz; float3 specular = iblBoxSpecular(surface.N, surface.P, surface.roughness, surfToEye, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture), TORQUE_SAMPLERCUBE_MAKEARG(cubeMap), probeWSPos, bbMin, bbMax); + + int i; + for(i=0; i < numProbes; i++) + { + float3 probeWS = inProbePosArray[i]; + + float3 L = probeWS - surface.P; + blendVal = 1.0-length(L)/radius; + //clip(blendVal); + + irradiance = float3(blendVal,blendVal,blendVal); + specular = irradiance; + } + + //render into the bound space defined above + // + //float3 irradiance = TORQUE_TEXCUBELOD(irradianceCubemap, float4(surface.N,0)).xyz; + //float3 specular = iblBoxSpecular(surface.N, surface.P, surface.roughness, surfToEye, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture), TORQUE_SAMPLERCUBE_MAKEARG(cubeMap), probeWSPos, bbMin, bbMax); float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness); specular *= F; //energy conservation