void ConfigureLights(CullingResults cull) { Vector4[] visibleLightColors = new Vector4[_maximumLightCount]; Vector4[] visibleLightDirections = new Vector4[_maximumLightCount]; for (int i = 0; i < cull.visibleLights.Length; i++) { if (i > _maximumLightCount) { break; } VisibleLight light = cull.visibleLights[i]; visibleLightColors[i] = light.finalColor; // visibleLightColors[i].y = light.finalColor.g; // visibleLightColors[i].z = light.finalColor.b; Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightDirections[i] = v; } if (cull.visibleLights.Length > _maximumLightCount) { var lightIndices = cull.GetLightIndexMap(new Unity.Collections.Allocator());//.GetLightIndexMap(); for (int i = _maximumLightCount; i < cull.visibleLights.Length; i++) { lightIndices[i] = -1; } cull.SetLightIndexMap(lightIndices); } _buffer.SetGlobalVectorArray(Shader.PropertyToID("_VisibleLightColors"), visibleLightColors); _buffer.SetGlobalVectorArray(Shader.PropertyToID("_VisibleLightDirections"), visibleLightDirections); }
void ConfigureLights() { for (int i = 0; i < _cullingResults.visibleLights.Length; i++) { if (i == maxVisibleLights) { break; } VisibleLight light = _cullingResults.visibleLights[i]; visibleLightColors[i] = light.finalColor; Vector4 attenuation = Vector4.zero; attenuation.w = 1f; if (light.lightType == LightType.Directional) { Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightDirectionsOrPositions[i] = v; } else { visibleLightDirectionsOrPositions[i] = light.localToWorldMatrix.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightSpotDirections[i] = v; float outerRad = Mathf.Deg2Rad * 0.5f * light.spotAngle; float outerCos = Mathf.Cos(outerRad); float outerTan = Mathf.Tan(outerRad); float innerCos = Mathf.Cos(Mathf.Atan((46f / 64f) * outerTan)); float angleRange = Mathf.Max(innerCos - outerCos, 0.001f); attenuation.z = 1f / angleRange; attenuation.w = -outerCos * attenuation.z; } } visibleLightAttenuations[i] = attenuation; } if (_cullingResults.visibleLights.Length > maxVisibleLights) { var lightIndices = _cullingResults.GetLightIndexMap(Allocator.Temp); for (int i = maxVisibleLights; i < _cullingResults.visibleLights.Length; i++) { lightIndices[i] = -1; } _cullingResults.SetLightIndexMap(lightIndices); } }
void SetupPerObjectLightIndices(CullingResults cullResults, ref LightData lightData) { if (lightData.additionalLightsCount == 0) { return; } var visibleLights = lightData.visibleLights; var perObjectLightIndexMap = cullResults.GetLightIndexMap(Allocator.Temp); int directionalLightsCount = 0; int additionalLightsCount = 0; // Disable all directional lights from the perobject light indices // Pipeline handles them globally. for (int i = 0; i < visibleLights.Length; ++i) { if (additionalLightsCount >= LightweightRenderPipeline.maxVisibleAdditionalLights) { break; } VisibleLight light = visibleLights[i]; if (light.lightType == LightType.Directional) { perObjectLightIndexMap[i] = -1; ++directionalLightsCount; } else { perObjectLightIndexMap[i] -= directionalLightsCount; ++additionalLightsCount; } } // Disable all remaining lights we cannot fit into the global light buffer. for (int i = directionalLightsCount + additionalLightsCount; i < visibleLights.Length; ++i) { perObjectLightIndexMap[i] = -1; } cullResults.SetLightIndexMap(perObjectLightIndexMap); perObjectLightIndexMap.Dispose(); }
int SetupPerObjectLightIndices(ref CullingResults cullingResults, int dynamicLightsMaxCount) { Debug.Assert(dynamicLightsMaxCount > 0); var visibleLights = cullingResults.visibleLights; var perObjectLightIndexMap = cullingResults.GetLightIndexMap(Allocator.Temp); int globalDirectionalLightsCount = 0; int additionalLightsCount = 0; // Disable all directional lights from the perobject light indices // Pipeline handles main light globally and there's no support for additional directional lights atm. for (int i = 0; i < visibleLights.Length; ++i) { if (additionalLightsCount >= dynamicLightsMaxCount) { break; } VisibleLight light = visibleLights[i]; // if (i == lightData.mainLightIndex) // { // perObjectLightIndexMap[i] = -1; // ++globalDirectionalLightsCount; // } // else // { perObjectLightIndexMap[i] -= globalDirectionalLightsCount; ++additionalLightsCount; // } } // Disable all remaining lights we cannot fit into the global light buffer. for (int i = globalDirectionalLightsCount + additionalLightsCount; i < perObjectLightIndexMap.Length; ++i) { perObjectLightIndexMap[i] = -1; } cullingResults.SetLightIndexMap(perObjectLightIndexMap); perObjectLightIndexMap.Dispose(); return(additionalLightsCount); }
void ConfigureLights() { mainLightExists = false; shadowMapTileCount = 0; for (int i = 0; i < cullingResults.visibleLights.Length; i++) { if (i == maxVisibleLights) { break; } VisibleLight light = cullingResults.visibleLights[i]; visibleLightColors[i] = light.finalColor; Vector4 attenuation = Vector4.zero; attenuation.w = 1f; Vector4 shadow = Vector4.zero; if (light.lightType == LightType.Directional) { Vector4 v = CalculateLightDir(light); visibleLightDirectionsOrPositions[i] = v; shadow = ConfigureShadows(i, light.light); shadow.z = 1f; if (i == 0 && shadow.x > 0f && shadowCascades > 0) { mainLightExists = true; shadowMapTileCount -= 1; } } else { visibleLightDirectionsOrPositions[i] = light.localToWorldMatrix.GetColumn(3); attenuation = CalcualteAtten(light); if (light.lightType == LightType.Spot) { Vector4 v = CalculateLightDir(light); visibleLightSpotDirections[i] = v; attenuation = CalcualteAtten(light); shadow = ConfigureShadows(i, light.light); shadow.z = 0; } } visibleLightAttenuations[i] = attenuation; shadowData[i] = shadow; } if (mainLightExists || cullingResults.visibleLights.Length > maxVisibleLights) { Unity.Collections.NativeArray <int> lightIndices = cullingResults.GetLightIndexMap(Unity.Collections.Allocator.Temp); if (mainLightExists) { lightIndices[0] = -1; } for (int i = maxVisibleLights; i < cullingResults.visibleLights.Length; i++) { lightIndices[i] = -1; } cullingResults.SetLightIndexMap(lightIndices); } }
void SetupLights(bool useLightPerObject, int camRenderingLayerMask) { //get a temp light indice array NativeArray <int> indexMap = useLightPerObject ? cullingResults.GetLightIndexMap(Allocator.Temp) : default; //Switch to get lights via Culling result NativeArray <VisibleLight> visibleLights = cullingResults.visibleLights; int dirLightCount = 0, otherLightCount = 0; int i; for (i = 0; i < visibleLights.Length; i++) { // set the index for directional lights to -1 unity will not include this into per object lighting int newIndex = -1; VisibleLight visibleLight = visibleLights[i]; Light light = visibleLight.light; if ((light.renderingLayerMask & camRenderingLayerMask) != 0) { switch (visibleLight.lightType) { case LightType.Directional: if (dirLightCount < maxDirLightCount) { SetupDirectionalLight(dirLightCount++, i, ref visibleLight, light); } break; case LightType.Point: if (otherLightCount < maxOtherLightCount) { newIndex = otherLightCount; SetupPointLight(otherLightCount++, i, ref visibleLight, light); } break; case LightType.Spot: if (otherLightCount < maxOtherLightCount) { newIndex = otherLightCount; SetupSpotLight(otherLightCount++, i, ref visibleLight, light); } break; } } if (useLightPerObject)//set index for visible lights { indexMap[i] = newIndex; } } if (useLightPerObject)//set index of invisible lights to -1 { for (; i < indexMap.Length; i++) { indexMap[i] = -1; } cullingResults.SetLightIndexMap(indexMap); indexMap.Dispose(); Shader.EnableKeyword(lightsPerObjectKeyword); } else { Shader.DisableKeyword(lightsPerObjectKeyword); } //Set to global so all shader for dirctional lights buffer.SetGlobalInt(dirLightCountId, dirLightCount); if (dirLightCount > 0) { buffer.SetGlobalVectorArray(dirLightColorId, dirLightColors); buffer.SetGlobalVectorArray(dirLightDirectionsAndMasksId, dirLightDirectionsAndMasks); buffer.SetGlobalVectorArray(dirLightShadowDataId, dirLightShadowData); } //set params for other lights buffer.SetGlobalInt(otherLightCountID, otherLightCount); if (otherLightCount > 0) { buffer.SetGlobalVectorArray(otherLightColorsID, otherLightColors); buffer.SetGlobalVectorArray(otherLightPositionsID, otherLightPositions); buffer.SetGlobalVectorArray(otherLightDirectionsAndMasksID, otherLightDirectionsAndMasks); buffer.SetGlobalVectorArray(otherLightSpotAnhglesID, otherLightSpotAngles); buffer.SetGlobalVectorArray(otherLightShadowDataId, otherLightShadowData); } }
void SetupLights(bool useLightsPerObject) { NativeArray <int> indexMap = useLightsPerObject ? cullingResults.GetLightIndexMap(Allocator.Temp) : default; NativeArray <VisibleLight> visibleLights = cullingResults.visibleLights; int dirLightCount = 0; int otherLightCount = 0; int i; for (i = 0; i < visibleLights.Length; i++) { int newIndex = -1; VisibleLight visibleLight = visibleLights[i]; switch (visibleLight.lightType) { case LightType.Directional: if (dirLightCount < maxDirLightCount) { SetupDirectionalLight(dirLightCount++, ref visibleLight); } break; case LightType.Point: if (otherLightCount < maxOtherLightCount) { newIndex = otherLightCount; SetupPointLight(otherLightCount++, ref visibleLight); } break; case LightType.Spot: if (otherLightCount < maxOtherLightCount) { newIndex = otherLightCount; SetupSpotLight(otherLightCount++, ref visibleLight); } break; } if (useLightsPerObject) { indexMap[i] = newIndex; } } //We have to sanitize these lists so only the indices of visible non-directional lights remain. //保留可见的非方向光 if (useLightsPerObject) { for (; i < indexMap.Length; i++) { indexMap[i] = -1; } cullingResults.SetLightIndexMap(indexMap); indexMap.Dispose(); Shader.EnableKeyword(lightsPerObjectKeyword); } else { Shader.DisableKeyword(lightsPerObjectKeyword); } buffer.SetGlobalInt(dirLightCountId, dirLightCount); if (dirLightCount > 0) { buffer.SetGlobalVectorArray(dirLightColorsId, dirLightColors); buffer.SetGlobalVectorArray(dirLightDirectionsId, dirLightDirections); buffer.SetGlobalVectorArray(dirLightShadowDataId, dirLightShadowData); } buffer.SetGlobalInt(otherLightCountId, otherLightCount); if (otherLightCount > 0) { buffer.SetGlobalVectorArray(otherLightColorsId, otherLightColors); buffer.SetGlobalVectorArray( otherLightPositionsId, otherLightPositions ); buffer.SetGlobalVectorArray( otherLightDirectionsId, otherLightDirections ); buffer.SetGlobalVectorArray( otherLightShadowDataId, otherLightShadowData ); } }
/// <summary> /// 构建灯光信息 /// </summary> private void configureLights() { m_mainLightExits = false; m_shadowTileCount = 0; for (int i = 0; i < m_cullingResults.visibleLights.Length; i++) { //相机控制中存在的灯光大于最大灯光配置时停止 if (i == m_maxVisibleLights) { break; } VisibleLight light = m_cullingResults.visibleLights[i]; //设置灯光颜色 m_visibleLightColors[i] = light.finalColor; //灯光衰减信息 Vector4 attenuation = Vector4.zero; attenuation.w = 1.0f; Vector4 shadow = Vector4.zero; if (light.lightType == LightType.Directional) { //通过取灯光变换矩阵的Z取反获得灯光方向 Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; //设置灯光的方向 m_visibleLightDirectionsOrPositions[i] = v; shadow = configureShadows(i, light.light); shadow.z = 1.0f; //判断是否使用CSM if (i == 0 && shadow.x > 0.0f && m_rpp.shadowCascades > 0) { m_mainLightExits = true; m_shadowTileCount -= 1; } } else { //提取第4列的位置变换保存灯光位置 m_visibleLightDirectionsOrPositions[i] = light.localToWorldMatrix.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; //聚光灯方向 m_visibleLightSpotDirections[i] = v; //计算聚光灯的半角余弦值 float outerRad = Mathf.Deg2Rad * 0.5f * light.spotAngle; float outerCos = Mathf.Cos(outerRad); float outerTan = Mathf.Tan(outerRad); //定义聚光灯内外角关系,计算内角余弦值 float innerCos = Mathf.Cos(Mathf.Atan((46f / 64f) * outerTan)); //计算内外角余弦差值,避免为0 //cos(ri) - cos(r0) float angleRange = Mathf.Max(innerCos - outerCos, 0.001f); attenuation.z = 1.0f / angleRange; // - cos(r0) / cos(ri) - cos(r0) attenuation.w = -outerCos * attenuation.z; shadow = configureShadows(i, light.light); } } //方向光没有衰减信息 m_visibleLightAttenuations[i] = attenuation; //构建阴影信息 x: 阴影强度 y: 阴影类型 m_shadowData[i] = shadow; } //当场景灯光数量改变后清除没用的灯光信息 if (m_cullingResults.visibleLights.Length > m_maxVisibleLights) { var indexs = m_cullingResults.GetLightIndexMap(new Unity.Collections.Allocator()); if (m_mainLightExits) { indexs[0] = -1; } for (int i = m_maxVisibleLights; i < m_cullingResults.visibleLights.Length; i++) { indexs[i] = -1; } m_cullingResults.SetLightIndexMap(indexs); } }
//存入可见的方向光信息 void ConfigureLights() { mainLightExists = false; shadowTileCount = 0; for (int i = 0; i < culling.visibleLights.Length; ++i) { if (i == maxVisibleLights) { break; } Vector4 attenuation = Vector4.zero; VisibleLight light = culling.visibleLights[i]; visibleLightColors[i] = light.finalColor; attenuation.w = 1; Vector4 shadow = Vector4.zero; if (light.lightType == LightType.Directional) { Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightDirectionsOrPositions[i] = v; shadow = ConfigureShadows(i, light.light); //用z通道为1来表示存储的是方向光的数据 shadow.z = 1; //判断是否是满足条件的主光源 if (i == 0 && shadow.x > 0f && shadowCascades > 0) { mainLightExists = true; //级联阴影贴图不会使用其他阴影一样的贴图 shadowTileCount -= 1; } } else { visibleLightDirectionsOrPositions[i] = light.localToWorldMatrix.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightSpotDirections[i] = v; //计算lwpl里面的聚光灯的innerCos和outerCos float outerRad = Mathf.Deg2Rad * 0.5f * light.spotAngle; float outerCos = Mathf.Cos(outerRad); float outerTan = Mathf.Tan(outerRad); float innerCos = Mathf.Cos(Mathf.Atan((46 / 64f) * outerTan)); //lwpl的衰减定义是 /* * (Ds * Dl)a + b * a = 1/(cos(ri) - cos(ro) * b = -cos(ro)a * * cos(ri)是innerCos, cos(ro)是outerCos * Ds * Dl是聚光灯朝向和灯光方向的点乘 */ float anleRange = Mathf.Max(innerCos - outerCos, 0.001f); attenuation.z = 1f / anleRange; attenuation.w = -outerCos * attenuation.z; shadow = ConfigureShadows(i, light.light); } } visibleLightAttenuations[i] = attenuation; shadowData[i] = shadow; } //排除多余的light if (mainLightExists || culling.visibleLights.Length > maxVisibleLights) { NativeArray <int> lightIndices = culling.GetLightIndexMap(Allocator.Temp); if (mainLightExists) { lightIndices[0] = -1; } for (int i = maxVisibleLights; i < culling.visibleLights.Length; ++i) { lightIndices[i] = -1; } culling.SetLightIndexMap(lightIndices); } }
void ConfigureLights() { mainLightExists = false; shadowTileCount = 0; bool shadowmaskExists = false; for (int i = 0; i < cull.visibleLights.Length; i++) { if (i == maxVisibleLights) { break; } VisibleLight light = cull.visibleLights[i]; visibleLightColors[i] = light.finalColor; Vector4 attenuation = Vector4.zero; attenuation.w = 1f; Vector4 shadow = Vector4.zero; // shadowmask ? LightBakingOutput baking = light.light.bakingOutput; visibleLightOcclusionMasks[i] = occlusionMasks[baking.occlusionMaskChannel + 1]; if (baking.lightmapBakeType == LightmapBakeType.Mixed) { shadowmaskExists |= baking.mixedLightingMode == MixedLightingMode.Shadowmask; } if (light.lightType == LightType.Directional) { Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightDirectionsOrPositions[i] = v; shadow = ConfigureShadows(i, light.light); shadow.z = 1f;// flag if (i == 0 && shadow.x > 0f && shadowCascades > 0) { mainLightExists = true; shadowTileCount -= 1; } } else { visibleLightDirectionsOrPositions[i] = light.localToWorldMatrix.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightSpotDirections[i] = v; float outerRad = Mathf.Deg2Rad * 0.5f * light.spotAngle; float outerCos = Mathf.Cos(outerRad); float outerTan = Mathf.Tan(outerRad); float innerCos = Mathf.Cos(Mathf.Atan((46f / 64f) * outerTan)); float angleRange = Mathf.Max(innerCos - outerCos, 0.001f); attenuation.z = 1f / angleRange; attenuation.w = -outerCos * attenuation.z; shadow = ConfigureShadows(i, light.light); } else { visibleLightSpotDirections[i] = Vector4.one; } } visibleLightAttenuations[i] = attenuation; shadowData[i] = shadow; } // shadowmask bool useDistanceShadowmask = QualitySettings.shadowmaskMode == ShadowmaskMode.DistanceShadowmask; CoreUtils.SetKeyword(cameraBuffer, shadowmaskKeyword, shadowmaskExists && !useDistanceShadowmask); CoreUtils.SetKeyword(cameraBuffer, distanceShadowmaskKeyword, shadowmaskExists && useDistanceShadowmask); if (mainLightExists || cull.visibleLights.Length > maxVisibleLights) { NativeArray <int> lightIndices = cull.GetLightIndexMap(Allocator.Temp); if (mainLightExists) { lightIndices[0] = -1; } for (int i = maxVisibleLights; i < cull.visibleLights.Length; i++) { lightIndices[i] = -1; } cull.SetLightIndexMap(lightIndices); } }
void ConfigureLights() { shadowTileCount = 0; for (int i = 0; i < cull.visibleLights.Length; i++) { if (i == maxVisibleLights) { break; } VisibleLight light = cull.visibleLights[i]; visibleLightColors[i] = light.finalColor; Vector4 attenuation = Vector4.zero; attenuation.w = 1f; Vector4 shadow = Vector4.zero; if (light.lightType == LightType.Directional) { Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightDirectionsOrPositions[i] = v; shadow = ConfigureShadows(i, light.light); shadow.z = 1f; //marks the shadow as being a directional light shadow } else { visibleLightDirectionsOrPositions[i] = light.localToWorldMatrix.GetColumn(3); //this is the position for point lights attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightSpotDirections[i] = v; float outerRad = Mathf.Deg2Rad * 0.5f * light.spotAngle; float outerCos = Mathf.Cos(outerRad); float outerTan = Mathf.Tan(outerRad); float innerCos = Mathf.Cos(Mathf.Atan(((46f / 64f) * outerTan))); float angleRange = Mathf.Max(innerCos - outerCos, 0.001f); attenuation.z = 1f / angleRange; attenuation.w = -outerCos * attenuation.z; //shadows shadow = ConfigureShadows(i, light.light); } } visibleLightAttenuations[i] = attenuation; shadowData[i] = shadow; } //TODO: READ UP ON NATIVE LISTS AND JUNK if (cull.visibleLights.Length > maxVisibleLights) { var lightIndicies = cull.GetLightIndexMap(Unity.Collections.Allocator.Temp); for (int i = maxVisibleLights; i < cull.visibleLights.Length; i++) { lightIndicies[i] = -1; } cull.SetLightIndexMap(lightIndicies); } }
private void Render(ScriptableRenderContext context, Camera camera) { BeginCameraRendering(camera); ScriptableCullingParameters parameters; if (!camera.TryGetCullingParameters(out parameters)) { return; } CullingResults cullingResults = context.Cull(ref parameters); context.SetupCameraProperties(camera); cameraBuffer.Clear(); cameraBuffer.ClearRenderTarget((camera.clearFlags & CameraClearFlags.Depth) != 0, (camera.clearFlags & CameraClearFlags.Color) != 0, camera.backgroundColor); context.ExecuteCommandBuffer(cameraBuffer); //init FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.all); SortingSettings sortingSettings = new SortingSettings(); DrawingSettings drawingSettings = new DrawingSettings(m_ShaderTagId, sortingSettings); RenderShawder(context); // cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(); //drawSkybox context.DrawSkybox(camera); #region light var lightcount = Mathf.Min(cullingResults.visibleLights.Length, MAX_VISABLE_COUNT); LightColors = new Vector4[MAX_VISABLE_COUNT]; LightDirections = new Vector4[MAX_VISABLE_COUNT]; LightAttenuations = new Vector4[MAX_VISABLE_COUNT]; LightSpotDirections = new Vector4[MAX_VISABLE_COUNT]; for (int i = 0; i < cullingResults.visibleLights.Length; i++) { if (i == MAX_VISABLE_COUNT) { break; } LightSpotDirections[i] = Vector4.zero; LightDirections[i] = Vector4.zero; LightAttenuations[i] = Vector4.zero; LightColors[i] = Vector4.zero; var light = cullingResults.visibleLights[i]; LightSpotDirections[i] = Vector4.zero; LightAttenuations[i].w = 1f; if (light.lightType == LightType.Directional) { var v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; v.w = 0;// LightDirections[i] = v; } else { LightDirections[i] = cullingResults.visibleLights[i].localToWorldMatrix.GetColumn(3); LightDirections[i].w = 1; //衰减 (1-(dir^2/range^2)^2)^2 LightAttenuations[i].x = 1f / Mathf.Max(Mathf.Sqrt(light.range), 0.000001f); //spot fade (lightPos*lightDir)-cos(r_out)/cos(r_in)-cos(r_out) if (light.lightType == LightType.Spot) { var dir = light.localToWorldMatrix.GetColumn(2); dir.x = -dir.x; dir.y = -dir.y; dir.z = -dir.z; LightSpotDirections[i] = dir; var outerRad = Mathf.Deg2Rad * 0.5f * light.spotAngle; var outerCos = Mathf.Cos(outerRad); //tan(r_in) = 46/64*tan(r_out) var outerTan = Mathf.Tan(outerRad); var innerCos = Mathf.Cos(Mathf.Atan(23 / 32 * outerTan)); LightAttenuations[i].z = 1 / Mathf.Max(innerCos - outerCos, 0.0001f); LightAttenuations[i].w = -outerCos * LightAttenuations[i].z; } } LightColors[i] = light.finalColor; } if (cullingResults.visibleLights.Length > MAX_VISABLE_COUNT) { NativeArray <int> lightMap = cullingResults.GetLightIndexMap(Allocator.Invalid); for (int i = MAX_VISABLE_COUNT; i < cullingResults.visibleLights.Length; i++) { lightMap[i] = -1; } cullingResults.SetLightIndexMap(lightMap); lightMap.Dispose(); } cameraBuffer.Clear(); cameraBuffer.SetGlobalVectorArray(_LightDirectionsID, LightDirections); cameraBuffer.SetGlobalVectorArray(_LightColorId, LightColors); cameraBuffer.SetGlobalVectorArray(_LightAttenuationID, LightAttenuations); cameraBuffer.SetGlobalVectorArray(_LightSpotDirectionID, LightSpotDirections); context.ExecuteCommandBuffer(cameraBuffer); #endregion //qaueue filteringSettings.renderQueueRange = RenderQueueRange.opaque; sortingSettings.criteria = SortingCriteria.CommonOpaque; context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings); context.Submit(); if (shadowMap) { RenderTexture.ReleaseTemporary(shadowMap); shadowMap = null; } }
static void SetupAdditionalLightConstants(CommandBuffer buffer, NativeArray <VisibleLight> visibleLights, int mainLightIndex, CullingResults cullingResults) { NativeArray <int> indexMap = cullingResults.GetLightIndexMap(Allocator.Temp); int globalDirectionalLightsCount = 0; int additionalLightsCount = 0; for (int i = 0; i < visibleLights.Length; i++) { if (additionalLightsCount >= maxVisibleAdditionalLights) { break; } VisibleLight light = visibleLights[i]; if (i == mainLightIndex) { indexMap[i] = -1; globalDirectionalLightsCount += 1; } else { indexMap[i] -= globalDirectionalLightsCount; additionalLightsCount += 1; } } for (int i = globalDirectionalLightsCount + additionalLightsCount; i < indexMap.Length; i++) { indexMap[i] = -1; } cullingResults.SetLightIndexMap(indexMap); indexMap.Dispose(); Vector4[] additionalLightPositions = new Vector4[maxVisibleAdditionalLights]; Vector4[] additionalLightColors = new Vector4[maxVisibleAdditionalLights]; Vector4[] additionalLightAttenuations = new Vector4[maxVisibleAdditionalLights]; Vector4[] additionalLightSpotDirections = new Vector4[maxVisibleAdditionalLights]; Vector4[] additionalLightOcclusionProbeChannels = new Vector4[maxVisibleAdditionalLights]; if (additionalLightsCount > 0) { for (int i = 0, lightIndex = 0; i < visibleLights.Length && lightIndex < maxVisibleAdditionalLights; i++) { VisibleLight light = visibleLights[i]; if (mainLightIndex != i) { InitializeLightConstants(visibleLights, i, out additionalLightPositions[lightIndex], out additionalLightColors[lightIndex], out additionalLightAttenuations[lightIndex], out additionalLightSpotDirections[lightIndex], out additionalLightOcclusionProbeChannels[lightIndex]); lightIndex += 1; } } buffer.SetGlobalVectorArray(additionalLightsPositionId, additionalLightPositions); buffer.SetGlobalVectorArray(additionalLightsColorId, additionalLightColors); buffer.SetGlobalVectorArray(additionalLightsAttenuationId, additionalLightAttenuations); buffer.SetGlobalVectorArray(additionalLightsSpotDirId, additionalLightSpotDirections); buffer.SetGlobalVectorArray(additionalLightOcclusionProbeChannelId, additionalLightOcclusionProbeChannels); buffer.SetGlobalVector(additionalLightsCountId, new Vector4(maxPerObjectAdditionalLights, 0.0f, 0.0f, 0.0f)); } else { buffer.SetGlobalVector(additionalLightsCountId, Vector4.zero); } }
void ConfigureLights() { shadowTileCount = 0; for (int i = 0; i < _cullingResults.visibleLights.Length; i++) { if (i == maxVisibleLights) { break; } VisibleLight light = _cullingResults.visibleLights[i]; visibleLightColors[i] = light.finalColor; Vector4 attenuation = Vector4.zero; attenuation.w = 1f; Vector4 shadow = Vector4.zero; if (light.lightType == LightType.Directional) { Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightDirectionsOrPositions[i] = v; } else { visibleLightDirectionsOrPositions[i] = light.localToWorldMatrix.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightSpotDirections[i] = v; float outerRad = Mathf.Deg2Rad * 0.5f * light.spotAngle; float outerCos = Mathf.Cos(outerRad); float outerTan = Mathf.Tan(outerRad); float innerCos = Mathf.Cos(Mathf.Atan((46f / 64f) * outerTan)); float angleRange = Mathf.Max(innerCos - outerCos, 0.001f); attenuation.z = 1f / angleRange; attenuation.w = -outerCos * attenuation.z; Light shadowLight = light.light; Bounds shadowBounds; if (shadowLight.shadows != LightShadows.None && _cullingResults.GetShadowCasterBounds(i, out shadowBounds)) { shadowTileCount += 1; shadow.x = shadowLight.shadowStrength; shadow.y = shadowLight.shadows == LightShadows.Soft ? 1f : 0f; } } } visibleLightAttenuations[i] = attenuation; shadowData[i] = shadow; } if (_cullingResults.visibleLights.Length > maxVisibleLights) { var lightIndices = _cullingResults.GetLightIndexMap(Allocator.Temp); for (int i = maxVisibleLights; i < _cullingResults.visibleLights.Length; i++) { lightIndices[i] = -1; } _cullingResults.SetLightIndexMap(lightIndices); } }
private void ConfigureLights() { mainLightExists = false; bool shadowmaskExists = false; bool subtractiveLighting = false; shadowTileCount = 0; for (int i = 0; i < cullingResults.visibleLights.Length; i++) { if (i == maxVisibleLights) { break; } VisibleLight light = cullingResults.visibleLights[i]; // finalColor字段存储了光源的颜色,该颜色数据是由光源的color属性和intensity属性相乘后的结果,并经过了颜色空间的校正。 visibleLightColors[i] = light.finalColor; Vector4 attenuation = Vector4.zero; attenuation.w = 1f; // 为了保证不同类型的光照计算的一致性(用同样的shader代码),将w分量设置为1。 Vector4 shadow = Vector4.zero; LightBakingOutput baking = light.light.bakingOutput; // 有四种可能的掩码,我们可以在静态数组(occlusionMasks)中预定义。 // 但也有可能有些灯光不使用阴影遮罩。我们将通过将第一个遮罩组件设置为-1来指示这一点。 // 如果灯光不使用阴影遮罩,则通道为-1,因此在检索预定义的 occlusionMasks 时+1。 visibleLightOcclusionMasks[i] = occlusionMasks[baking.occlusionMaskChannel + 1]; if (baking.lightmapBakeType == LightmapBakeType.Mixed) { shadowmaskExists |= baking.mixedLightingMode == MixedLightingMode.Shadowmask; // 判读是否存在烘培阴影。 if (baking.mixedLightingMode == MixedLightingMode.Subtractive) { subtractiveLighting = true; cameraBuffer.SetGlobalColor(subtractiveShadowColorId, UnityEngine.RenderSettings.subtractiveShadowColor.linear); } } if (light.lightType == LightType.Directional) { // 方向光的光源方向信息可以通过光源的旋转信息获得,光源的方向是它的z轴方向。 // 我们可以通过VisibleLight.localToWorldMatrix矩阵获取在世界坐标系中的该信息。这个矩阵的第三列定义了光源的本地Z轴方向。 Vector4 v = light.localToWorldMatrix.GetColumn(2); // 在shader中我们使用从物体朝向光源的向量方向进行计算,所以将获得的光源方向进行取反操作。 v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightDirectionsOrPositions[i] = v; // 设置阴影。 shadow = ConfigureShadows(i, light.light); shadow.z = 1f; // 用阴影数据的z分量来区分是方向光还是聚光灯。 if (i == 0 && shadow.x > 0f && ShadowCascades > 0) { mainLightExists = true; // 我们会为主光源提供单独的渲染贴图,所以当我们拥有主光源时,让图块计数减1, // 并且在RenderShadows函数中将其从常规阴影贴图渲染中排除。 shadowTileCount -= 1; } } else if (light.lightType == LightType.Point || light.lightType == LightType.Spot) { // 点光源不关心光的方向而关心光源的位置。这个矩阵的第四列定义了光源的世界位置。 visibleLightDirectionsOrPositions[i] = light.localToWorldMatrix.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { // 聚光灯的光源方向。 Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightSpotDirections[i] = v; // 聚光灯的衰减。 float outerRad = Mathf.Deg2Rad * 0.5f * light.spotAngle; float outerCos = Mathf.Cos(outerRad); float outerTan = Mathf.Tan(outerRad); float innerCos = Mathf.Cos(Mathf.Atan(((46f / 64f) * outerTan))); float angleRange = Mathf.Max(innerCos - outerCos, 0.001f); attenuation.z = 1f / angleRange; attenuation.w = -outerCos * attenuation.z; // 设置阴影。 shadow = ConfigureShadows(i, light.light); } else { visibleLightSpotDirections[i] = Vector4.one; } } // 填充点光源或聚光灯的光照范围。 visibleLightAttenuations[i] = attenuation; shadowData[i] = shadow; } cameraBuffer.SetGlobalVectorArray(visibleLightColorsId, visibleLightColors); cameraBuffer.SetGlobalVectorArray(visibleLightDirectionsOrPositionsId, visibleLightDirectionsOrPositions); cameraBuffer.SetGlobalVectorArray(visibleLightAttenuationsId, visibleLightAttenuations); // 点光源。 cameraBuffer.SetGlobalVectorArray(visibleLightSpotDirectionsId, visibleLightSpotDirections); // 聚光灯。 cameraBuffer.SetGlobalVectorArray(visibleLightOcclusionMasksId, visibleLightOcclusionMasks); // 尽管目前我们已经支持到场景中最多16个光源,但是依然无法避免有可能会存在更多光源的情况。 // 当超出时,我们需要告诉Unity需要将一些光源舍弃以避免数组的越界。 // 如果主光源存在,在渲染前将主光源移出可见光列表,以防止在shader中计算多次(会导致像素光数量上限变成5个)。 if (mainLightExists || cullingResults.visibleLights.Length > maxVisibleLights) { var lightIndexs = cullingResults.GetLightIndexMap(Unity.Collections.Allocator.TempJob); if (mainLightExists) { lightIndexs[0] = -1; } for (int i = maxVisibleLights; i < cullingResults.visibleLights.Length; i++) { lightIndexs[i] = -1; } cullingResults.SetLightIndexMap(lightIndexs); lightIndexs.Dispose(); } bool useDistanceShadowmask = QualitySettings.shadowmaskMode == ShadowmaskMode.DistanceShadowmask; CoreUtils.SetKeyword(cameraBuffer, shadowmaskKeyword, shadowmaskExists && !useDistanceShadowmask); CoreUtils.SetKeyword(cameraBuffer, distanceShadowmaskKeyword, shadowmaskExists && useDistanceShadowmask); CoreUtils.SetKeyword(cameraBuffer, subtractiveLightingKeyword, subtractiveLighting); }
void SetupLights(bool useLightsPerObject, int renderingLayerMask) { NativeArray <int> indexMap = useLightsPerObject ? cullingResults.GetLightIndexMap(Allocator.Temp) : default; NativeArray <VisibleLight> visibleLights = cullingResults.visibleLights; int dirLightCount = 0, otherLightCount = 0; int i; for (i = 0; i < visibleLights.Length; i++) { int newIndex = -1; VisibleLight visibleLight = visibleLights[i]; Light light = visibleLight.light; if ((light.renderingLayerMask & renderingLayerMask) != 0) { switch (visibleLight.lightType) { case LightType.Directional: if (dirLightCount < maxDirLightCount) { SetupDirectionalLight(dirLightCount++, i, ref visibleLight, light); } break; case LightType.Point: if (otherLightCount < maxOtherLightCount) { newIndex = otherLightCount; SetupPointLight(otherLightCount++, i, ref visibleLight, light); } break; case LightType.Spot: if (otherLightCount < maxOtherLightCount) { newIndex = otherLightCount; SetupSpotLight(otherLightCount++, i, ref visibleLight, light); } break; } } if (useLightsPerObject) { indexMap[i] = newIndex; } } if (useLightsPerObject) { for (; i < indexMap.Length; i++) { indexMap[i] = -1; } cullingResults.SetLightIndexMap(indexMap); indexMap.Dispose(); Shader.EnableKeyword(lightsPerObjectKeyword); } else { Shader.DisableKeyword(lightsPerObjectKeyword); } buffer.SetGlobalInt(dirLightCountId, dirLightCount); if (dirLightCount > 0) { buffer.SetGlobalVectorArray(dirLightColorsId, dirLightColors); buffer.SetGlobalVectorArray(dirLightDirectionsId, dirLightDirectionsAndMasks); buffer.SetGlobalVectorArray(dirLightShadowDataId, dirLightShadowData); } buffer.SetGlobalInt(otherLightCountId, otherLightCount); if (otherLightCount > 0) { buffer.SetGlobalVectorArray(otherLightColorsId, otherLightColors); buffer.SetGlobalVectorArray(otherLightPositionsId, otherLightPositions); buffer.SetGlobalVectorArray(otherLightDirectionsId, otherLightDirectionsAndMasks); buffer.SetGlobalVectorArray(otherLightSpotAnglesId, otherLightSpotAngles); buffer.SetGlobalVectorArray(otherLightShadowDataId, otherLightShadowData); } }
public void SetupPerObjectLightIndices(ref CullingResults cullResults, ref LightData lightData) { if (lightData.additionalLightsCount == 0) { return; } var visibleLights = lightData.visibleLights; var perObjectLightIndexMap = cullResults.GetLightIndexMap(Allocator.Temp); int directionalLightsCount = 0; int additionalLightsCount = 0; // Disable all directional lights from the perobject light indices // Pipeline handles them globally. for (int i = 0; i < visibleLights.Length; ++i) { if (additionalLightsCount >= maxVisibleAdditionalLights) { break; } VisibleLight light = visibleLights[i]; if (light.lightType == LightType.Directional) { perObjectLightIndexMap[i] = -1; ++directionalLightsCount; } else { perObjectLightIndexMap[i] -= directionalLightsCount; ++additionalLightsCount; } } // Disable all remaining lights we cannot fit into the global light buffer. for (int i = directionalLightsCount + additionalLightsCount; i < visibleLights.Length; ++i) { perObjectLightIndexMap[i] = -1; } cullResults.SetLightIndexMap(perObjectLightIndexMap); perObjectLightIndexMap.Dispose(); // if not using a compute buffer, engine will set indices in 2 vec4 constants // unity_4LightIndices0 and unity_4LightIndices1 if (useStructuredBufferForLights) { int lightIndicesCount = cullResults.lightAndReflectionProbeIndexCount; if (lightIndicesCount > 0) { if (perObjectLightIndices == null) { perObjectLightIndices = new ComputeBuffer(lightIndicesCount, sizeof(int)); } else if (perObjectLightIndices.count < lightIndicesCount) { perObjectLightIndices.Release(); perObjectLightIndices = new ComputeBuffer(lightIndicesCount, sizeof(int)); } cullResults.FillLightAndReflectionProbeIndices(perObjectLightIndices); } } }
private void SetupLights(bool useLightsPerObject) { // lightIndexMap contains light indices, matching the visible light indices plus all other active lights in the scene (from catlike) // we only use lightIndexMap for point and spot light NativeArray <int> lightIndexMap = useLightsPerObject ? cullingResults.GetLightIndexMap(Allocator.Temp) : default; NativeArray <VisibleLight> visibleLights = cullingResults.visibleLights; int directionalLightCount = 0; int otherLightCount = 0; int i = 0; for (; i < visibleLights.Length; ++i) { int newIndex = -1; VisibleLight visibleLight = visibleLights[i]; switch (visibleLight.lightType) { case LightType.Directional: { if (directionalLightCount < maxDirectionalLightCount) { SetupDirectionalLight(directionalLightCount++, i, ref visibleLight); } break; } case LightType.Point: { if (otherLightCount < maxOtherLightCount) { newIndex = otherLightCount; SetupPointLight(otherLightCount++, i, ref visibleLight); } break; } case LightType.Spot: { if (otherLightCount < maxOtherLightCount) { newIndex = otherLightCount; SetupSpotLight(otherLightCount++, i, ref visibleLight); } break; } } if (useLightsPerObject) { lightIndexMap[i] = newIndex; } } if (useLightsPerObject) { for (; i < lightIndexMap.Length; ++i) { lightIndexMap[i] = -1; } // cullingResults.SetLightIndexMap(lightIndexMap); Shader.EnableKeyword(lightsPerObjectKeyword); lightIndexMap.Dispose(); } else { Shader.DisableKeyword(lightsPerObjectKeyword); } // Light light = RenderSettings.sun; // commandBuffer.SetGlobalVector(directionalLightColorPropertyID, light.color.linear * light.intensity); // commandBuffer.SetGlobalVector(directionalLightDirectionPropertyID, -light.transform.forward); commandBuffer.SetGlobalInt(directionalLightCountPropertyID, directionalLightCount); if (directionalLightCount > 0) { commandBuffer.SetGlobalVectorArray(directionalLightColorsPropertyID, directionalLightColors); commandBuffer.SetGlobalVectorArray(directionalLightDirectionsPropertyID, directionalLightDirections); commandBuffer.SetGlobalVectorArray(directionalShadowInfosPropertyID, _DirectionalShadowInfos); } commandBuffer.SetGlobalInt(otherLightCountPropertyID, otherLightCount); if (otherLightCount > 0) { commandBuffer.SetGlobalVectorArray(otherLightColorsPropertyID, otherLightColors); commandBuffer.SetGlobalVectorArray(otherLightPositionsProoertyID, otherLightPositions); commandBuffer.SetGlobalVectorArray(otherLightDirectionsPropertyID, otherLightDirections); commandBuffer.SetGlobalVectorArray(otherLightSpotAnglesPropertyID, otherLightSpotAngles); commandBuffer.SetGlobalVectorArray(otherLightShadowDatasPropertyID, otherLightShadowDatas); } }