public void SetupPerObjectLightIndices(ref CullResults cullResults, ref LightData lightData) { if (lightData.additionalLightsCount == 0) { return; } List <VisibleLight> visibleLights = lightData.visibleLights; int[] perObjectLightIndexMap = cullResults.GetLightIndexMap(); 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.Count; ++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.Count; ++i) { perObjectLightIndexMap[i] = -1; } cullResults.SetLightIndexMap(perObjectLightIndexMap); // if not using a compute buffer, engine will set indices in 2 vec4 constants // unity_4LightIndices0 and unity_4LightIndices1 if (useStructuredBufferForLights) { int lightIndicesCount = cullResults.GetLightIndicesCount(); 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.FillLightIndices(perObjectLightIndices); } } }
private void SetupShaderLightListConstants(VisibleLight[] lights, ref LightData lightData, ref ScriptableRenderContext context) { int maxLights = Math.Min(kMaxVisibleLights, lights.Length); for (int i = 0; i < maxLights; ++i) { VisibleLight currLight = lights [i]; if (currLight.lightType == LightType.Directional) { Vector4 dir = -currLight.localToWorld.GetColumn(2); m_LightPositions [i] = new Vector4(dir.x, dir.y, dir.z, 0.0f); } else { Vector4 pos = currLight.localToWorld.GetColumn(3); m_LightPositions [i] = new Vector4(pos.x, pos.y, pos.z, 1.0f); } m_LightColors[i] = currLight.finalColor; float rangeSq = currLight.range * currLight.range; float quadAtten = (currLight.lightType == LightType.Directional) ? 0.0f : 25.0f / rangeSq; if (currLight.lightType == LightType.Spot) { Vector4 dir = currLight.localToWorld.GetColumn(2); m_LightSpotDirections [i] = new Vector4(-dir.x, -dir.y, -dir.z, 0.0f); float spotAngle = Mathf.Deg2Rad * currLight.spotAngle; float cosOuterAngle = Mathf.Cos(spotAngle * 0.5f); float cosInneAngle = Mathf.Cos(spotAngle * 0.25f); float angleRange = cosInneAngle - cosOuterAngle; m_LightAttenuations [i] = new Vector4(cosOuterAngle, Mathf.Approximately(angleRange, 0.0f) ? 1.0f : angleRange, quadAtten, rangeSq); } else { m_LightSpotDirections [i] = new Vector4(0.0f, 0.0f, 1.0f, 0.0f); m_LightAttenuations [i] = new Vector4(-1.0f, 1.0f, quadAtten, rangeSq); } } // Lightweight pipeline only upload kMaxVisibleLights to shader cbuffer. // We tell the pipe to disable remaining lights by setting it to -1. int[] lightIndexMap = m_CullResults.GetLightIndexMap(); for (int i = kMaxVisibleLights; i < lightIndexMap.Length; ++i) { lightIndexMap[i] = -1; } m_CullResults.SetLightIndexMap(lightIndexMap); CommandBuffer cmd = CommandBufferPool.Get("SetupShadowShaderConstants"); cmd.SetGlobalVector("globalLightCount", new Vector4(lightData.pixelLightsCount, lightData.vertexLightsCount, 0.0f, 0.0f)); cmd.SetGlobalVectorArray("globalLightPos", m_LightPositions); cmd.SetGlobalVectorArray("globalLightColor", m_LightColors); cmd.SetGlobalVectorArray("globalLightAtten", m_LightAttenuations); cmd.SetGlobalVectorArray("globalLightSpotDir", m_LightSpotDirections); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
void ConfigureLights() { mainLightExists = false; shadowTileCount = 0; for (int i = 0; i < cull.visibleLights.Count; 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.localToWorld.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; if (i == 0 && shadow.x > 0f && shadowCascades > 0) { mainLightExists = true; shadowTileCount -= 1; } } else { visibleLightDirectionsOrPositions[i] = light.localToWorld.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorld.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); } } visibleLightAttenuations[i] = attenuation; shadowData[i] = shadow; } if (mainLightExists || cull.visibleLights.Count > maxVisibleLights) { int[] lightIndices = cull.GetLightIndexMap(); if (mainLightExists) { lightIndices[0] = -1; } for (int i = maxVisibleLights; i < cull.visibleLights.Count; i++) { lightIndices[i] = -1; } cull.SetLightIndexMap(lightIndices); } }
void ConfigureLights() { mainLightExists = false; bool shadowmaskExists = false; bool subtractiveLighting = false; shadowTileCount = 0; for (int i = 0; i < cull.visibleLights.Count; 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; LightBakingOutput baking = light.light.bakingOutput; visibleLightOcclusionMasks[i] = occlusionMasks[baking.occlusionMaskChannel + 1]; if (baking.lightmapBakeType == LightmapBakeType.Mixed) { shadowmaskExists |= baking.mixedLightingMode == MixedLightingMode.Shadowmask; //subtractiveLighting |= // baking.mixedLightingMode == MixedLightingMode.Subtractive; if (baking.mixedLightingMode == MixedLightingMode.Subtractive) { subtractiveLighting = true; cameraBuffer.SetGlobalColor( subtractiveShadowColorId, RenderSettings.subtractiveShadowColor.linear ); } } if (light.lightType == LightType.Directional) { //因为要求出光源的朝向,相当于要知道光源transform.forward,矩阵第三列是光源z轴在世界坐标系下表示,也就是forward Vector4 v = light.localToWorld.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; if (i == 0 && shadow.x > 0f && shadowCascades > 0) { mainLightExists = true; shadowTileCount -= 1; } } else { //第四列是光源原点在世界坐标系中的位置 visibleLightDirectionsOrPositions[i] = light.localToWorld.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorld.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; //存储spot光源方向 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); //Light shadowLight = light.light; //Bounds shadowBounds; //if (shadowLight.shadows != LightShadows.None && cull.GetShadowCasterBounds(i, out shadowBounds)) //{ // shadowTileCount += 1; // shadow.x = shadowLight.shadowStrength; // shadow.y = shadowLight.shadows == LightShadows.Soft ? 1f : 0f; //} } else { visibleLightSpotDirections[i] = Vector4.one; } } visibleLightAttenuations[i] = attenuation; shadowData[i] = shadow; } bool useDistanceShadowmask = QualitySettings.shadowmaskMode == ShadowmaskMode.DistanceShadowmask; CoreUtils.SetKeyword(cameraBuffer, shadowmaskKeyword, shadowmaskExists && !useDistanceShadowmask); CoreUtils.SetKeyword( cameraBuffer, distanceShadowmaskKeyword, shadowmaskExists && useDistanceShadowmask ); CoreUtils.SetKeyword(cameraBuffer, subtractiveLightingKeyword, subtractiveLighting); //如果超过maxVisibleLights数量的灯光,该脚本不会传输给Shader //但是Unity自身可能会对超出maxVisibleLights的灯光,进行unity_4LightIndices0赋值,下标会找不到,_VisibleLightColors越界 if (mainLightExists || cull.visibleLights.Count > maxVisibleLights) { int[] lightIndices = cull.GetLightIndexMap(); if (mainLightExists) { lightIndices[0] = -1; } for (int i = maxVisibleLights; i < cull.visibleLights.Count; i++) { lightIndices[i] = -1; } cull.SetLightIndexMap(lightIndices); } }
void ConfigureLights() { mainLightExists = false; bool shadowmaskExists = false; bool subtractiveLighting = false; shadowTileCount = 0; for (int i = 0; i < cull.visibleLights.Count; i++) { if (i == maxVisibleLights) { break; } VisibleLight light = cull.visibleLights[i]; visibleLightColors[i] = light.finalColor; Vector4 attenuation = Vector4.zero; attenuation.w = 1f; //if no spot light, factor =1 Vector4 shadow = Vector4.zero; //shadowmask settings LightBakingOutput baking = light.light.bakingOutput; 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, RenderSettings.subtractiveShadowColor.linear ); } } //light settings if (light.lightType == LightType.Directional) { Vector4 v = light.localToWorld.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; //change to vector surfaceToLight visibleLightDirectionsOrPositions[i] = v; shadow = ConfigureShadows(i, light.light); shadow.z = 1f; //directional light index =0, cast shadow, use cascades if (i == 0 && shadow.x > 0f && shadowCascades > 0) { mainLightExists = true; shadowTileCount -= 1; //cascaded shadow map is not included in tiled shadow map } } else { visibleLightDirectionsOrPositions[i] = light.localToWorld.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorld.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; //buffer shadowData shadow = ConfigureShadows(i, light.light); } else { //indicator of pointlight visibleLightSpotDirections[i] = Vector4.one; } } visibleLightAttenuations[i] = attenuation; shadowData[i] = shadow; } //number of lights exceeds upper limit if (mainLightExists || cull.visibleLights.Count > maxVisibleLights) { int[] lightIndices = cull.GetLightIndexMap(); if (mainLightExists) { //remove main light from diffuseLight render, avoid a second render lightIndices[0] = -1; } for (int i = maxVisibleLights; i < cull.visibleLights.Count; i++) { lightIndices[i] = -1; } cull.SetLightIndexMap(lightIndices); } bool useDistanceShadowmask = QualitySettings.shadowmaskMode == ShadowmaskMode.DistanceShadowmask; //enable shadowmask keyword CoreUtils.SetKeyword(cameraBuffer, shadowmaskKeyword, shadowmaskExists && !useDistanceShadowmask); //if use shadowmask mode CoreUtils.SetKeyword(cameraBuffer, distanceShadowmaskKeyword, shadowmaskExists && useDistanceShadowmask); //if use distance shadowmask CoreUtils.SetKeyword(cameraBuffer, subtractiveLightingKeyword, subtractiveLighting); }
// 计算光数据 void ConfigureLights() { mainLightExists = false; shadowTileCount = 0; for (int i = 0; i < cull.visibleLights.Count; i++) { // 其他光被抛弃 if (i == maxVisibleLights) { break; } VisibleLight light = cull.visibleLights[i]; // finalColor是光的颜色和亮度的乘积,并且已经被转换到正确的颜色空间 visibleLightColors[i] = light.finalColor; // 点光和聚光的边界衰减 Vector4 attenuation = Vector4.zero; // 保证计算聚光灯的边界衰减不会影响其他类型的灯 attenuation.w = 1f; Vector4 shadow = Vector4.zero; if (light.lightType == LightType.Directional) { // 获取光线方向 Vector4 v = light.localToWorld.GetColumn(2); // shader中使用视点到光的方向,因此需要取反,w为0,不需要取反 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; // 层级阴影使用另一张阴影纹理 shadowTileCount -= 1; } } else { // 获取光的位置 visibleLightDirectionsOrPositions[i] = light.localToWorld.GetColumn(3); // 计算点光的边界衰减数据,放在attenuation的x分量中 attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); // 如果是聚光灯 if (light.lightType == LightType.Spot) { // 设定方向 Vector4 v = light.localToWorld.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightSpotDirections[i] = v; // 计算聚光的边界衰减数据,并放在attenuation的z和w分量中 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); } } visibleLightAttenuations[i] = attenuation; shadowData[i] = shadow; } // 如果光的数量超过maxVisibleLights,将超过的灯光的索引剔除掉 if (mainLightExists || cull.visibleLights.Count > maxVisibleLights) { // 获取光索引数组 int[] lightIndices = cull.GetLightIndexMap(); if (mainLightExists) { // 将主光剔除掉,否则主光会被渲染两次 // 这也意味着每个物体支持的像素光的数量变为5 lightIndices[0] = -1; } for (int i = maxVisibleLights; i < cull.visibleLights.Count; i++) { // 索引为-1的光会被剔除掉 lightIndices[i] = -1; } // 设置光索引数组 cull.SetLightIndexMap(lightIndices); } }
void ConfigureLights() { shadowTileCount = 0; for (int i = 0; i < cull.visibleLights.Count; i++) { if (i == maxVisibleLights) { break; } VisibleLight light = cull.visibleLights[i]; visibleLightColors[i] = light.finalColor; Vector4 attenuation = Vector4.zero; attenuation.w = 1f; //if no spot light, factor =1 Vector4 shadow = Vector4.zero; if (light.lightType == LightType.Directional) { Vector4 v = light.localToWorld.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; //change to vector surfaceToLight visibleLightDirectionsOrPositions[i] = v; } else { visibleLightDirectionsOrPositions[i] = light.localToWorld.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorld.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; //buffer shadowData Light shadowLight = light.light; Bounds shadowBounds; if (shadowLight.shadows != LightShadows.None && cull.GetShadowCasterBounds(i, out shadowBounds)) { shadowTileCount += 1; shadow.x = shadowLight.shadowStrength; shadow.y = shadowLight.shadows == LightShadows.Soft ? 1f : 0f; } } } visibleLightAttenuations[i] = attenuation; shadowData[i] = shadow; } //number of lights exceeds upper limit if (cull.visibleLights.Count > maxVisibleLights) { int[] lightIndices = cull.GetLightIndexMap(); for (int i = maxVisibleLights; i < cull.visibleLights.Count; i++) { lightIndices[i] = -1; } cull.SetLightIndexMap(lightIndices); } }
void ConfigureLights() { mainLightExists = false; bool shadowmaskExists = false; bool subtractiveLighting = false; shadowTileCount = 0; for (int i = 0; i < cull.visibleLights.Count; 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; LightBakingOutput baking = light.light.bakingOutput; 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, RenderSettings.subtractiveShadowColor.linear ); } } if (light.lightType == LightType.Directional) { Vector4 v = light.localToWorld.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; if (i == 0 && shadow.x > 0f && shadowCascades > 0) { mainLightExists = true; shadowTileCount -= 1; } } else { visibleLightDirectionsOrPositions[i] = light.localToWorld.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorld.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; } bool useDistanceShadowmask = QualitySettings.shadowmaskMode == ShadowmaskMode.DistanceShadowmask; CoreUtils.SetKeyword( cameraBuffer, shadowmaskKeyword, shadowmaskExists && !useDistanceShadowmask ); CoreUtils.SetKeyword( cameraBuffer, distanceShadowmaskKeyword, shadowmaskExists && useDistanceShadowmask ); CoreUtils.SetKeyword( cameraBuffer, subtractiveLightingKeyword, subtractiveLighting ); if (mainLightExists || cull.visibleLights.Count > maxVisibleLights) { int[] lightIndices = cull.GetLightIndexMap(); if (mainLightExists) { lightIndices[0] = -1; } for (int i = maxVisibleLights; i < cull.visibleLights.Count; i++) { lightIndices[i] = -1; } cull.SetLightIndexMap(lightIndices); } }
void ConfigureLights() { mainLightExists = false; shadowTileCount = 0; for (int i = 0; i < cull.visibleLights.Count; i++) { if (i == maxVisibleLights) { break; } VisibleLight light = cull.visibleLights[i]; visibleLightColors[i] = light.finalColor; Vector4 attenuation = Vector4.zero; attenuation.w = 1f; //if no spot light, factor =1 Vector4 shadow = Vector4.zero; if (light.lightType == LightType.Directional) { Vector4 v = light.localToWorld.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; //change to vector surfaceToLight visibleLightDirectionsOrPositions[i] = v; shadow = ConfigureShadows(i, light.light); shadow.z = 1f; //directional light index =0, cast shadow, use cascades if (i == 0 && shadow.x > 0f && shadowCascades > 0) { mainLightExists = true; shadowTileCount -= 1; //cascaded shadow map is not included in tiled shadow map } } else { visibleLightDirectionsOrPositions[i] = light.localToWorld.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorld.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; //buffer shadowData shadow = ConfigureShadows(i, light.light); } } visibleLightAttenuations[i] = attenuation; shadowData[i] = shadow; } //number of lights exceeds upper limit if (mainLightExists || cull.visibleLights.Count > maxVisibleLights) { int[] lightIndices = cull.GetLightIndexMap(); if (mainLightExists) { //remove main light from diffuseLight render, avoid a second render lightIndices[0] = -1; } for (int i = maxVisibleLights; i < cull.visibleLights.Count; i++) { lightIndices[i] = -1; } cull.SetLightIndexMap(lightIndices); } }
//------------------------------------------------------------------------------ private void ConfigureLights() { for (int i = 0; i < cullResults.visibleLights.Count; i++) { // might try to put more lights in the scene than supported in pipeline if (i == maxVisibleLights) { Debug.LogError("Attempting to use more lights in the scene than the renderer supports. Max supported lights: " + maxVisibleLights); break; } // set light color VisibleLight light = cullResults.visibleLights[i]; visibleLightColors[i] = light.finalColor; // set light vector, attentuation, & spotdirection // based on light type Vector4 a = Vector4.zero; a.w = 1.0f; if (light.lightType == LightType.Directional) { // 3rd column is z-axis of light, which is the direction it shines in Vector4 v = light.localToWorld.GetColumn(2); // negate so vector is pointing towards the light v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightVectors[i] = v; } else { // 3rd column is position visibleLightVectors[i] = light.localToWorld.GetColumn(3); a.x = 1.0f / Mathf.Max(light.range * light.range, 0.00001f); // set direction & extra attentuation info if it's a spot light if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorld.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((46.0f / 64.0f) * outerTan)); float angleRange = Mathf.Max(innerCos - outerCos, 0.001f); a.z = 1.0f / angleRange; a.w = -outerCos * a.z; } } visibleLightAttenuations[i] = a; } // let unity know about unused lights so it doesn't write // to out of bounds locations in light data if (cullResults.visibleLights.Count > maxVisibleLights) { // allocates new memory every frame, booo int[] lightIndices = cullResults.GetLightIndexMap(); for (int i = maxVisibleLights; i < cullResults.visibleLights.Count; i++) { lightIndices[i] = -1; } cullResults.SetLightIndexMap(lightIndices); } }
void ConfigureLights() { for (int i = 0; i < cull.visibleLights.Count; i++) { if (i == maxVisibleLights) { break; } VisibleLight light = cull.visibleLights[i]; visibleLightColors[i] = light.finalColor; Vector4 attenuation = Vector4.zero; attenuation.w = 1f; //if no spot light, factor =1 if (light.lightType == LightType.Directional) { Vector4 v = light.localToWorld.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; //change to vector surfaceToLight visibleLightDirectionsOrPositions[i] = v; } else { visibleLightDirectionsOrPositions[i] = light.localToWorld.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorld.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; } //number of lights exceeds upper limit if (cull.visibleLights.Count > maxVisibleLights) { int[] lightIndices = cull.GetLightIndexMap(); for (int i = maxVisibleLights; i < cull.visibleLights.Count; i++) { lightIndices[i] = -1; } cull.SetLightIndexMap(lightIndices); } }