浏览代码

HDRenderPipeline: Add refraction cubemap support

- Just a draft, don't work correctly
/Add-support-for-light-specular-color-tint
Sebastien Lagarde 7 年前
当前提交
aab7798a
共有 4 个文件被更改,包括 86 次插入10 次删除
  1. 8
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs
  2. 6
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs.hlsl
  3. 41
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl
  4. 41
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl

8
ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs


// Disk,
};
// This is use to distinguish between reflection and refraction probe in LightLoop
[GenerateHLSL]
public enum GPUImageBasedLightingType
{
Reflection,
Refraction
};
// These structures share between C# and hlsl need to be align on float4, so we pad them.
[GenerateHLSL]
public struct DirectionalLightData

6
ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs.hlsl


#define GPULIGHTTYPE_RECTANGLE (6)
//
// UnityEngine.Experimental.Rendering.HDPipeline.GPUImageBasedLightingType: static fields
//
#define GPUIMAGEBASEDLIGHTINGTYPE_REFLECTION (0)
#define GPUIMAGEBASEDLIGHTINGTYPE_REFRACTION (1)
//
// UnityEngine.Experimental.Rendering.HDPipeline.EnvShapeType: static fields
//
#define ENVSHAPETYPE_NONE (0)

41
ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl


uint envLightIndex = i;
#endif
EvaluateBSDF_Env( context, V, posInput, preLightData, _EnvLightDatas[envLightIndex], bsdfData, _EnvLightDatas[envLightIndex].envShapeType,
lighting, reflectionHierarchyWeight);
GPUIMAGEBASEDLIGHTINGTYPE_REFLECTION, lighting, reflectionHierarchyWeight);
}
// Refraction probe and reflection probe will process exactly the same weight. It will be good for performance to be able to share this computation
// However it is hard to deal with the fact that reflectionHierarchyWeight and refractionHierarchyWeight have not the same values, they are independent
// The refraction probe is rarely used and happen only with sphere shape and high IOR. So we accept the slow path that use more simple code and
// doesn't affect the performance of the reflection which is more important.
// We reuse LIGHTFEATUREFLAGS_SSREFRACTION flag as refraction is mainly base on the screen. Would be aa waste to not use screen and only cubemap.
if (featureFlags & LIGHTFEATUREFLAGS_SSREFRACTION)
{
for (i = 0; i < envLightCount && refractionHierarchyWeight < 1.0; ++i)
{
#ifdef LIGHTLOOP_TILE_PASS
uint envLightIndex = FetchIndex(envLightStart, i);
#else
uint envLightIndex = i;
#endif
EvaluateBSDF_Env( context, V, posInput, preLightData, _EnvLightDatas[envLightIndex], bsdfData, _EnvLightDatas[envLightIndex].envShapeType,
GPUIMAGEBASEDLIGHTINGTYPE_REFRACTION, lighting, refractionHierarchyWeight);
}
if (featureFlags & LIGHTFEATUREFLAGS_SKY)
// Only apply the sky IBL if the sky texture is available
if (featureFlags & LIGHTFEATUREFLAGS_SKY && _EnvLightSkyEnabled)
// Only apply the sky IBL if the sky texture is available, and if we haven't yet accumulated enough IBL lighting.
if (_EnvLightSkyEnabled && reflectionHierarchyWeight < 1.0)
// Only apply the sky if we haven't yet accumulated enough IBL lighting.
if (reflectionHierarchyWeight < 1.0)
EvaluateBSDF_Env(context, V, posInput, preLightData, envLightSky, bsdfData, ENVSHAPETYPE_SKY, lighting, reflectionHierarchyWeight);
EvaluateBSDF_Env(context, V, posInput, preLightData, envLightSky, bsdfData, ENVSHAPETYPE_SKY, GPUIMAGEBASEDLIGHTINGTYPE_REFLECTION, lighting, reflectionHierarchyWeight);
}
if (featureFlags & LIGHTFEATUREFLAGS_SSREFRACTION)
{
if (refractionHierarchyWeight < 1.0)
{
// The sky is a single cubemap texture separate from the reflection probe texture array (different resolution and compression)
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_SKY;
EnvLightData envLightSky = InitSkyEnvLightData(0); // The sky data are generated on the fly so the compiler can optimize the code
EvaluateBSDF_Env(context, V, posInput, preLightData, envLightSky, bsdfData, ENVSHAPETYPE_SKY, GPUIMAGEBASEDLIGHTINGTYPE_REFRACTION, lighting, refractionHierarchyWeight);
}
}
}
}

41
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


|| any(refractedBackPointSS < 0.0)
|| any(refractedBackPointSS > 1.0))
{
diffuseLighting = SAMPLE_TEXTURE2D_LOD(_GaussianPyramidColorTexture, s_trilinear_clamp_sampler, posInput.positionSS, 0.0).rgb;
// TODO: check with fred. If a pixel is in front of the object we should not sample at all and put hierarchyWeight to 1.0 so we discard the effect as it is occlusion
// Otherwise fallback on cubemap
// Do nothing and don't update the hierarchy weight so we can fall back on refraction probe
return;
}

// _preIntegratedFGD and _CubemapLD are unique for each BRDF
void EvaluateBSDF_Env( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData, int envShapeType,
PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData, int envShapeType, int GPUImageBasedLightingType,
#if !HAS_REFRACTION
if (GPUImageBasedLightingType == GPUIMAGEBASEDLIGHTINGTYPE_REFRACTION)
return ;
#endif
float3 positionWS = posInput.positionWS;
float3 specularLighting = float3(0.0, 0.0, 0.0);
float weight = 1.0;

float3 R = preLightData.iblDirWS;
float3 coatR = preLightData.coatIblDirWS;
if (GPUImageBasedLightingType == GPUIMAGEBASEDLIGHTINGTYPE_REFRACTION)
{
// This is the same code than what is use in screen space refraction
// TODO: put this code into a function
#if defined(_REFRACTION_PLANE)
R = refract(-V, bsdfData.normalWS, 1.0 / bsdfData.ior);
#elif defined(_REFRACTION_SPHERE)
float3 R1 = refract(-V, bsdfData.normalWS, 1.0 / bsdfData.ior);
// Center of the tangent sphere
float3 C = posInput.positionWS - bsdfData.normalWS * bsdfData.thickness * 0.5;
// Second refraction (tangent sphere out)
float NoR1 = dot(bsdfData.normalWS, R1);
// Optical depth within the sphere
float opticalDepth = -NoR1 * bsdfData.thickness;
// Out hit point in the tangent sphere
float3 P1 = posInput.positionWS + R1 * opticalDepth;
// Out normal
float3 N1 = normalize(C - P1);
// Out refracted ray
R = refract(R1, N1, bsdfData.ior);
#endif
}
// In Unity the cubemaps are capture with the localToWorld transform of the component.
// This mean that location and orientation matter. So after intersection of proxy volume we need to convert back to world.

#endif
UpdateLightingHierarchyWeights(hierarchyWeight, weight);
lighting.envSpecular += specularLighting * weight;
if (GPUImageBasedLightingType == GPUIMAGEBASEDLIGHTINGTYPE_REFLECTION)
lighting.envSpecular += specularLighting * weight;
else
lighting.refraction += specularLighting * weight;
}
//-----------------------------------------------------------------------------

正在加载...
取消
保存