public static Vector4 GetShadowBias(/*ref VisibleLight shadowLight,*/ ref LightData_Shadow lightShadowData, int shadowLightIndex, ref ShadowData shadowData, out Matrix4x4 lightProjectionMatrix, out Matrix4x4 lightViewMatrix, float shadowResolution) { lightProjectionMatrix = lightShadowData.projMatrix; lightViewMatrix = lightShadowData.viewMatrix; if (shadowLightIndex < 0 || shadowLightIndex >= shadowData.bias.Count) { Debug.LogWarning(string.Format("{0} is not a valid light index.", shadowLightIndex)); return(Vector4.zero); } // TODO ? float frustumSize = 2.0f / lightProjectionMatrix.m00; //if (shadowLight.lightType == LightType.Directional) //{ // // Frustum size is guaranteed to be a cube as we wrap shadow frustum around a sphere // frustumSize = 2.0f / lightProjectionMatrix.m00; //} //else if (shadowLight.lightType == LightType.Spot) //{ // // For perspective projections, shadow texel size varies with depth // // It will only work well if done in receiver side in the pixel shader. Currently LWRP // // do bias on caster side in vertex shader. When we add shader quality tiers we can properly // // handle this. For now, as a poor approximation we do a constant bias and compute the size of // // the frustum as if it was orthogonal considering the size at mid point between near and far planes. // // Depending on how big the light range is, it will be good enough with some tweaks in bias // frustumSize = Mathf.Tan(shadowLight.spotAngle * 0.5f * Mathf.Deg2Rad) * shadowLight.range; //} //else //{ // Debug.LogWarning("Only spot and directional shadow casters are supported in lightweight pipeline"); // frustumSize = 0.0f; //} // depth and normal bias scale is in shadowmap texel size in world space float texelSize = frustumSize / shadowResolution; float depthBias = -shadowData.bias[shadowLightIndex].x * texelSize; float normalBias = -shadowData.bias[shadowLightIndex].y * texelSize; if (shadowData.supportsSoftShadows) { // TODO: depth and normal bias assume sample is no more than 1 texel away from shadowmap // This is not true with PCF. Ideally we need to do either // cone base bias (based on distance to center sample) // or receiver place bias based on derivatives. // For now we scale it by the PCF kernel size (5x5) const float kernelRadius = 2.5f; depthBias *= kernelRadius; normalBias *= kernelRadius; } return(new Vector4(depthBias, normalBias, 0.0f, 0.0f)); }
public static bool ExtractProjectorLightMatrix(ref ProjectorLight projectorLight, ref LightData_Shadow shadowData, out Matrix4x4 shadowMatrix) { ShadowSplitData splitData = new ShadowSplitData(); splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity); splitData.cullingPlaneCount = 0; //for (int i = 0; i < 6; ++i) //{ // var splane = shadowData.planes[i]; // Plane plane = new Plane(splane.normal, splane.distance); // splitData.SetCullingPlane(i, plane); //} shadowMatrix = GetShadowTransform(shadowData.projMatrix, shadowData.viewMatrix); return(true); }
public LightDataInAll GetLightData(Matrix4x4 c2w, int currentShadowIndex) { LightDataInAll lightDataInAll = new LightDataInAll(); var ps = iFPipelineProjector.GetProjectorSettings; { //bound.planes = Projector.GetCullingPlanes(ps.frustumMatrix, c2w);//world to view Projector.GetCullingPlanesAndSphere( out lightDataInAll.sFiniteLightBound.planes, out lightDataInAll.sFiniteLightBound.aabb, ps.frustumMatrix, c2w); } LightData lightData = new LightData(); lightData.pos = cacheTransform.position; //lightData.lightParms = (uint)LightParams; lightData.posShadow = new Vector4(); lightData.falloffR = ps.falloffR; lightData.projS = ps.projectMatrixX; lightData.projT = ps.projectMatrixY; lightData.projQ = ps.projectMatrixW; lightData.colorPacked = ColorTools.packRGBE(ColorTools.Color2Vec3(FinalColor)); var unpack = ColorTools.unpackRGBE(2256963201); //Debug.Log(unpack.ToString()); //Debug.Log(FinalColor.ToString()); lightData.specMultiplier = specMultiplier; lightData.shadowBleedReduce = shadowBleedReduce; int sizex = spritesAtlas.width; int sizey = spritesAtlas.height; { SpriteData spriteData = projSpriteData; float x = spriteData.x; float y = sizey - spriteData.y - spriteData.height;//GPU得纹理坐标y轴反的,原点左上角 float width = spriteData.width; float height = spriteData.height; float scalex = width / sizex;//todo:optimize float scaley = height / sizey; float offsetx = x / sizex; float offsety = y / sizey; ColorTools.packR15G15B15A15( out lightData.scaleBias.x, out lightData.scaleBias.y, new Vector4(scalex, scaley, offsetx, offsety)); } { SpriteData spriteData = falloffSpriteData; float x = spriteData.x; float y = sizey - spriteData.y - spriteData.height;//GPU得纹理坐标y轴反的,原点左上角 float width = spriteData.width; float height = spriteData.height; float scalex = width / sizex;//todo:optimize float scaley = height / sizey; float offsetx = x / sizex; float offsety = y / sizey; ColorTools.packR15G15B15A15( out lightData.scaleBias.z, out lightData.scaleBias.w, new Vector4(scalex, scaley, offsetx, offsety)); } //public Vector4 boxMin; //public Vector4 boxMax; //public Vector4 areaPlane; { Plane plane = lightDataInAll.sFiniteLightBound.planes.Near; Vector3 normalws = plane.normal.normalized; plane.distance = Vector3.Dot(lightData.pos, normalws); plane.normal = normalws * area_falloff; lightData.areaPlane = new Vector4( plane.normal.x, plane.normal.y, plane.normal.z, plane.distance); //问题:已知plane,求面上偏移width,height的点 Vector3 topright = new Vector3(area_width, area_height, 0); Vector3 bottomleft = new Vector3(-area_width, -area_height, 0); Matrix4x4 local2world = cacheTransform.localToWorldMatrix; topright = local2world.MultiplyPoint3x4(topright); bottomleft = local2world.MultiplyPoint3x4(bottomleft); #if UNITY_EDITOR posa = bottomleft; posc = topright; posb = new Vector3(-area_width, area_height, 0); posb = local2world.MultiplyPoint3x4(posb); posd = new Vector3(area_width, -area_height, 0); posd = local2world.MultiplyPoint3x4(posd); #endif Vector3 boxMin = new Vector3( Mathf.Min(bottomleft.x, topright.x), Mathf.Min(bottomleft.y, topright.y), Mathf.Min(bottomleft.z, topright.z) ); Vector3 boxMax = new Vector3( Mathf.Max(bottomleft.x, topright.x), Mathf.Max(bottomleft.y, topright.y), Mathf.Max(bottomleft.z, topright.z) ); lightData.boxMin = boxMin; lightData.boxMax = boxMax; } #if UNITY_EDITOR cacheLightData = lightDataInAll; #endif // shadow { LightData_Shadow shadowData = new LightData_Shadow(); if (lightParms_Shadow && currentShadowIndex != -1) { needDrawShadow = true; lightParams_ShadowIndex = currentShadowIndex; shadowData.projMatrix = iFPipelineProjector.GetProjectorSettings.projMatrix; shadowData.viewMatrix = iFPipelineProjector.GetProjectorSettings.viewMatrix; #if UNITY_EDITOR shadowData.planes = cacheLightData.sFiniteLightBound.planes; #endif } else { needDrawShadow = false; } lightDataInAll.shadowData = shadowData; } lightData.lightParms = (uint)LightParams; lightDataInAll.lightData = lightData; return(lightDataInAll); }