//Unpacks a sort key for a light public static void UnpackLightSortKey(uint sortKey, out LightCategory lightCategory, out GPULightType gpuLightType, out LightVolumeType lightVolumeType, out int lightIndex) { lightCategory = (LightCategory)((sortKey >> 27) & 0xF); gpuLightType = (GPULightType)((sortKey >> 22) & 0x1F); lightVolumeType = (LightVolumeType)((sortKey >> 17) & 0x1F); lightIndex = (int)(sortKey & 0xFFFF); }
//Packs a sort key for a light public static uint PackLightSortKey(LightCategory lightCategory, GPULightType gpuLightType, LightVolumeType lightVolumeType, int lightIndex) { //We sort directional lights to be in the beginning of the list. //This ensures that we can access directional lights very easily after we sort them. uint isDirectionalMSB = gpuLightType == GPULightType.Directional ? 0u : 1u; uint sortKey = (uint)isDirectionalMSB << 31 | (uint)lightCategory << 27 | (uint)gpuLightType << 22 | (uint)lightVolumeType << 17 | (uint)lightIndex; return(sortKey); }
private BaseItem createTestItem() { BaseItem lightItem = new BaseItem("Sample Light"); lightItem.FlavorText = "This is a test light"; lightItem.InventorySprite = "light.png"; lightItem.WorldModel = "lightModel.png"; lightItem.Types = new List <string>(); lightItem.Types.Add(ItemTypes.Fuel); LightCategory light = new LightCategory(); light.Brightness = 2f; light.BurnRate = 0.75f; light.CurrentFuelLevel = 3f; light.MaxFuel = 5f; lightItem.AddItemCategory(light); return(lightItem); }
public void AddFuelTest() { // Arrange BaseItem lightItem = createTestItem(); LightCategory lightCategory = (LightCategory)lightItem.GetItemCategoryByClass(typeof(LightCategory)); float fuel = 1.5f; float expectedNewFuel = lightCategory.CurrentFuelLevel + fuel; float expectedNewFuel2 = lightCategory.MaxFuel; // Act lightCategory.AddFuel(fuel); // Assert Assert.AreEqual(expectedNewFuel, lightCategory.CurrentFuelLevel); lightCategory.AddFuel(fuel); Assert.AreEqual(expectedNewFuel2, lightCategory.CurrentFuelLevel); }
void BuildLightData(CommandBuffer cmd, HDCamera hdCamera, HDRayTracingLights rayTracingLights, DebugDisplaySettings debugDisplaySettings) { // If no lights, exit if (rayTracingLights.lightCount == 0) { ResizeLightDataBuffer(1); return; } // Also we need to build the light list data if (m_LightDataGPUArray == null || m_LightDataGPUArray.count != rayTracingLights.lightCount) { ResizeLightDataBuffer(rayTracingLights.lightCount); } m_LightDataCPUArray.Clear(); // Grab the shadow settings var hdShadowSettings = hdCamera.volumeStack.GetComponent <HDShadowSettings>(); BoolScalableSetting contactShadowScalableSetting = HDAdditionalLightData.ScalableSettings.UseContactShadow(m_RenderPipeline.asset); // Build the data for every light for (int lightIdx = 0; lightIdx < rayTracingLights.hdLightArray.Count; ++lightIdx) { // Grab the additinal light data to process HDAdditionalLightData additionalLightData = rayTracingLights.hdLightArray[lightIdx]; LightData lightData = new LightData(); // When the user deletes a light source in the editor, there is a single frame where the light is null before the collection of light in the scene is triggered // the workaround for this is simply to add an invalid light for that frame if (additionalLightData == null) { m_LightDataCPUArray.Add(lightData); continue; } // Evaluate all the light type data that we need LightCategory lightCategory = LightCategory.Count; GPULightType gpuLightType = GPULightType.Point; LightVolumeType lightVolumeType = LightVolumeType.Count; HDLightType lightType = additionalLightData.type; HDRenderPipeline.EvaluateGPULightType(lightType, additionalLightData.spotLightShape, additionalLightData.areaLightShape, ref lightCategory, ref gpuLightType, ref lightVolumeType); // Fetch the light component for this light additionalLightData.gameObject.TryGetComponent(out lightComponent); // Build the processed light data that we need ProcessedLightData processedData = new ProcessedLightData(); processedData.additionalLightData = additionalLightData; processedData.lightType = additionalLightData.type; processedData.lightCategory = lightCategory; processedData.gpuLightType = gpuLightType; processedData.lightVolumeType = lightVolumeType; // Both of these positions are non-camera-relative. processedData.distanceToCamera = (additionalLightData.gameObject.transform.position - hdCamera.camera.transform.position).magnitude; processedData.lightDistanceFade = HDUtils.ComputeLinearDistanceFade(processedData.distanceToCamera, additionalLightData.fadeDistance); processedData.volumetricDistanceFade = HDUtils.ComputeLinearDistanceFade(processedData.distanceToCamera, additionalLightData.volumetricFadeDistance); processedData.isBakedShadowMask = HDRenderPipeline.IsBakedShadowMaskLight(lightComponent); // Build a visible light Color finalColor = lightComponent.color.linear * lightComponent.intensity; if (additionalLightData.useColorTemperature) { finalColor *= Mathf.CorrelatedColorTemperatureToRGB(lightComponent.colorTemperature); } visibleLight.finalColor = finalColor; visibleLight.range = lightComponent.range; // This should be done explicitely, localtoworld matrix doesn't work here localToWorldMatrix.SetColumn(3, lightComponent.gameObject.transform.position); localToWorldMatrix.SetColumn(2, lightComponent.transform.forward); localToWorldMatrix.SetColumn(1, lightComponent.transform.up); localToWorldMatrix.SetColumn(0, lightComponent.transform.right); visibleLight.localToWorldMatrix = localToWorldMatrix; visibleLight.spotAngle = lightComponent.spotAngle; int shadowIndex = additionalLightData.shadowIndex; int screenSpaceShadowIndex = -1; int screenSpaceChannelSlot = -1; Vector3 lightDimensions = new Vector3(0.0f, 0.0f, 0.0f); // Use the shared code to build the light data m_RenderPipeline.GetLightData(cmd, hdCamera, hdShadowSettings, visibleLight, lightComponent, in processedData, shadowIndex, contactShadowScalableSetting, isRasterization: false, ref lightDimensions, ref screenSpaceShadowIndex, ref screenSpaceChannelSlot, ref lightData); // We make the light position camera-relative as late as possible in order // to allow the preceding code to work with the absolute world space coordinates. Vector3 camPosWS = hdCamera.mainViewConstants.worldSpaceCameraPos; HDRenderPipeline.UpdateLightCameraRelativetData(ref lightData, camPosWS); // Set the data for this light m_LightDataCPUArray.Add(lightData); } // Push the data to the GPU m_LightDataGPUArray.SetData(m_LightDataCPUArray); }
void BuildLightData(CommandBuffer cmd, HDCamera hdCamera, List <HDAdditionalLightData> lightArray) { // Also we need to build the light list data if (m_LightDataGPUArray == null || m_LightDataGPUArray.count != lightArray.Count) { ResizeLightDataBuffer(lightArray.Count); } // Build the data for every light for (int lightIdx = 0; lightIdx < lightArray.Count; ++lightIdx) { var lightData = new LightData(); HDAdditionalLightData additionalLightData = lightArray[lightIdx]; // When the user deletes a light source in the editor, there is a single frame where the light is null before the collection of light in the scene is triggered // the workaround for this is simply to add an invalid light for that frame if (additionalLightData == null) { m_LightDataCPUArray[lightIdx] = lightData; continue; } Light light = additionalLightData.gameObject.GetComponent <Light>(); // Both of these positions are non-camera-relative. float distanceToCamera = (light.gameObject.transform.position - hdCamera.camera.transform.position).magnitude; float lightDistanceFade = HDUtils.ComputeLinearDistanceFade(distanceToCamera, additionalLightData.fadeDistance); bool contributesToLighting = ((additionalLightData.lightDimmer > 0) && (additionalLightData.affectDiffuse || additionalLightData.affectSpecular)) || (additionalLightData.volumetricDimmer > 0); contributesToLighting = contributesToLighting && (lightDistanceFade > 0); if (!contributesToLighting) { continue; } lightData.lightLayers = additionalLightData.GetLightLayers(); LightCategory lightCategory = LightCategory.Count; GPULightType gpuLightType = GPULightType.Point; GetLightGPUType(additionalLightData, light, ref gpuLightType, ref lightCategory); lightData.lightType = gpuLightType; lightData.positionRWS = light.gameObject.transform.position - hdCamera.camera.transform.position; bool applyRangeAttenuation = additionalLightData.applyRangeAttenuation && (gpuLightType != GPULightType.ProjectorBox); lightData.range = light.range; if (applyRangeAttenuation) { lightData.rangeAttenuationScale = 1.0f / (light.range * light.range); lightData.rangeAttenuationBias = 1.0f; if (lightData.lightType == GPULightType.Rectangle) { // Rect lights are currently a special case because they use the normalized // [0, 1] attenuation range rather than the regular [0, r] one. lightData.rangeAttenuationScale = 1.0f; } } else // Don't apply any attenuation but do a 'step' at range { // Solve f(x) = b - (a * x)^2 where x = (d/r)^2. // f(0) = huge -> b = huge. // f(1) = 0 -> huge - a^2 = 0 -> a = sqrt(huge). const float hugeValue = 16777216.0f; const float sqrtHuge = 4096.0f; lightData.rangeAttenuationScale = sqrtHuge / (light.range * light.range); lightData.rangeAttenuationBias = hugeValue; if (lightData.lightType == GPULightType.Rectangle) { // Rect lights are currently a special case because they use the normalized // [0, 1] attenuation range rather than the regular [0, r] one. lightData.rangeAttenuationScale = sqrtHuge; } } Color value = light.color.linear * light.intensity; if (additionalLightData.useColorTemperature) { value *= Mathf.CorrelatedColorTemperatureToRGB(light.colorTemperature); } lightData.color = new Vector3(value.r, value.g, value.b); lightData.forward = light.transform.forward; lightData.up = light.transform.up; lightData.right = light.transform.right; if (lightData.lightType == GPULightType.ProjectorBox) { // Rescale for cookies and windowing. lightData.right *= 2.0f / Mathf.Max(additionalLightData.shapeWidth, 0.001f); lightData.up *= 2.0f / Mathf.Max(additionalLightData.shapeHeight, 0.001f); } else if (lightData.lightType == GPULightType.ProjectorPyramid) { // Get width and height for the current frustum var spotAngle = light.spotAngle; float frustumWidth, frustumHeight; if (additionalLightData.aspectRatio >= 1.0f) { frustumHeight = 2.0f * Mathf.Tan(spotAngle * 0.5f * Mathf.Deg2Rad); frustumWidth = frustumHeight * additionalLightData.aspectRatio; } else { frustumWidth = 2.0f * Mathf.Tan(spotAngle * 0.5f * Mathf.Deg2Rad); frustumHeight = frustumWidth / additionalLightData.aspectRatio; } // Rescale for cookies and windowing. lightData.right *= 2.0f / frustumWidth; lightData.up *= 2.0f / frustumHeight; } if (lightData.lightType == GPULightType.Spot) { var spotAngle = light.spotAngle; var innerConePercent = additionalLightData.GetInnerSpotPercent01(); var cosSpotOuterHalfAngle = Mathf.Clamp(Mathf.Cos(spotAngle * 0.5f * Mathf.Deg2Rad), 0.0f, 1.0f); var sinSpotOuterHalfAngle = Mathf.Sqrt(1.0f - cosSpotOuterHalfAngle * cosSpotOuterHalfAngle); var cosSpotInnerHalfAngle = Mathf.Clamp(Mathf.Cos(spotAngle * 0.5f * innerConePercent * Mathf.Deg2Rad), 0.0f, 1.0f); // inner cone var val = Mathf.Max(0.0001f, (cosSpotInnerHalfAngle - cosSpotOuterHalfAngle)); lightData.angleScale = 1.0f / val; lightData.angleOffset = -cosSpotOuterHalfAngle * lightData.angleScale; // Rescale for cookies and windowing. float cotOuterHalfAngle = cosSpotOuterHalfAngle / sinSpotOuterHalfAngle; lightData.up *= cotOuterHalfAngle; lightData.right *= cotOuterHalfAngle; } else { // These are the neutral values allowing GetAngleAnttenuation in shader code to return 1.0 lightData.angleScale = 0.0f; lightData.angleOffset = 1.0f; } if (lightData.lightType != GPULightType.Directional && lightData.lightType != GPULightType.ProjectorBox) { // Store the squared radius of the light to simulate a fill light. lightData.size = new Vector2(additionalLightData.shapeRadius * additionalLightData.shapeRadius, 0); } if (lightData.lightType == GPULightType.Rectangle || lightData.lightType == GPULightType.Tube) { lightData.size = new Vector2(additionalLightData.shapeWidth, additionalLightData.shapeHeight); } lightData.lightDimmer = lightDistanceFade * (additionalLightData.lightDimmer); lightData.diffuseDimmer = lightDistanceFade * (additionalLightData.affectDiffuse ? additionalLightData.lightDimmer : 0); lightData.specularDimmer = lightDistanceFade * (additionalLightData.affectSpecular ? additionalLightData.lightDimmer * hdCamera.frameSettings.specularGlobalDimmer : 0); lightData.volumetricLightDimmer = lightDistanceFade * (additionalLightData.volumetricDimmer); lightData.contactShadowIndex = -1; lightData.cookieIndex = -1; lightData.shadowIndex = -1; lightData.rayTracedAreaShadowIndex = -1; if (light != null && light.cookie != null) { // TODO: add texture atlas support for cookie textures. switch (light.type) { case LightType.Spot: lightData.cookieIndex = m_LightLoop.cookieTexArray.FetchSlice(cmd, light.cookie); break; case LightType.Point: lightData.cookieIndex = m_LightLoop.cubeCookieTexArray.FetchSlice(cmd, light.cookie); break; } } else if (light.type == LightType.Spot && additionalLightData.spotLightShape != SpotLightShape.Cone) { // Projectors lights must always have a cookie texture. // As long as the cache is a texture array and not an atlas, the 4x4 white texture will be rescaled to 128 lightData.cookieIndex = m_LightLoop.cookieTexArray.FetchSlice(cmd, Texture2D.whiteTexture); } else if (lightData.lightType == GPULightType.Rectangle && additionalLightData.areaLightCookie != null) { lightData.cookieIndex = m_LightLoop.areaLightCookieManager.FetchSlice(cmd, additionalLightData.areaLightCookie); } { lightData.shadowDimmer = 1.0f; lightData.volumetricShadowDimmer = 1.0f; } { // fix up shadow information lightData.shadowIndex = additionalLightData.shadowIndex; } // Value of max smoothness is from artists point of view, need to convert from perceptual smoothness to roughness lightData.minRoughness = (1.0f - additionalLightData.maxSmoothness) * (1.0f - additionalLightData.maxSmoothness); // No usage for the shadow masks lightData.shadowMaskSelector = Vector4.zero; { // use -1 to say that we don't use shadow mask lightData.shadowMaskSelector.x = -1.0f; lightData.nonLightMappedOnly = 0; } // Set the data for this light m_LightDataCPUArray[lightIdx] = lightData; } //Push the data to the GPU m_LightDataGPUArray.SetData(m_LightDataCPUArray); }
void GetLightGPUType(HDAdditionalLightData additionalData, Light light, ref GPULightType gpuLightType, ref LightCategory lightCategory) { lightCategory = LightCategory.Count; gpuLightType = GPULightType.Point; if (additionalData.lightTypeExtent == LightTypeExtent.Punctual) { lightCategory = LightCategory.Punctual; switch (light.type) { case LightType.Spot: switch (additionalData.spotLightShape) { case SpotLightShape.Cone: gpuLightType = GPULightType.Spot; break; case SpotLightShape.Pyramid: gpuLightType = GPULightType.ProjectorPyramid; break; case SpotLightShape.Box: gpuLightType = GPULightType.ProjectorBox; break; default: Debug.Assert(false, "Encountered an unknown SpotLightShape."); break; } break; case LightType.Directional: gpuLightType = GPULightType.Directional; break; case LightType.Point: gpuLightType = GPULightType.Point; break; default: Debug.Assert(false, "Encountered an unknown LightType."); break; } } else { lightCategory = LightCategory.Area; switch (additionalData.lightTypeExtent) { case LightTypeExtent.Rectangle: gpuLightType = GPULightType.Rectangle; break; case LightTypeExtent.Tube: gpuLightType = GPULightType.Tube; break; default: Debug.Assert(false, "Encountered an unknown LightType."); break; } } }
private BaseItem createTestItem() { PlayerInventory mockPlayerInventory = new PlayerInventory("player", 20); PlayerController controller = new GameObject().AddComponent <PlayerController>(); Game.Instance.PlayerInstance = new Player(mockPlayerInventory); Game.Instance.PlayerInstance.Controller = controller; BaseItem item = new BaseItem("Sample Item"); item.FlavorText = "This is a test item"; item.InventorySprite = "item.png"; item.WorldModel = "itemWorld.png"; item.Types = new List <string>(); item.Types.Add(ItemTypes.BaseSolid); item.Types.Add(ItemTypes.Rod); SolidCategory solid = new SolidCategory(); solid.Durability = 0.1f; solid.Elasticity = 0.2f; solid.Flexibility = 0.3f; solid.Sharpness = 0.4f; solid.Stickiness = 0.5f; solid.Thickness = 0.6f; PlantCategory plant = new PlantCategory(); plant.PneumoniaEffect = 0.1f; plant.StomachEffect = 0.2f; plant.Toughness = 0.3f; plant.WaterContent = 0.4f; FleshCategory flesh = new FleshCategory(); flesh.HealthEffect = 0.1f; flesh.HungerGain = 0.2f; ContainerCategory container = new ContainerCategory(); container.Size = 1; MedicineCategory medicine = new MedicineCategory(); medicine.HealthGain = 5f; medicine.Sickness = "all"; ClothCategory cloth = new ClothCategory(); cloth.FabricThickness = 0.5f; cloth.Impermiability = 1f; cloth.ThreadDensity = 0.3f; cloth.OnPlayer = 0f; FuelCategory fuel = new FuelCategory(); fuel.BurnTime = 5f; FireBaseCategory fire = new FireBaseCategory(); fire.BurnRateMultiplier = 1f; fire.FuelRemaining = 10f; fire.StartingFuel = 10f; ShelterCategory shelter = new ShelterCategory(); shelter.WarmthRate = 2; RaftCategory raft = new RaftCategory(); raft.Speed = 1f; raft.InventorySize = 5; WarmthIdolCategory warmthIdol = new WarmthIdolCategory(); warmthIdol.Equiped = 0f; warmthIdol.WarmthBenefit = 1; LightCategory light = new LightCategory(); light.Brightness = 2f; light.BurnRate = 0.75f; light.CurrentFuelLevel = 3f; light.MaxFuel = 5f; EquipableCategory equipable = new EquipableCategory(); equipable.Equiped = 0f; item.AddItemCategory(solid); item.AddItemCategory(plant); item.AddItemCategory(flesh); item.AddItemCategory(container); item.AddItemCategory(medicine); item.AddItemCategory(cloth); item.AddItemCategory(fuel); item.AddItemCategory(fire); item.AddItemCategory(shelter); item.AddItemCategory(raft); item.AddItemCategory(warmthIdol); item.AddItemCategory(light); item.AddItemCategory(equipable); return(item); }
void BuildLightData(CommandBuffer cmd, HDCamera hdCamera, HDRayTracingLights rayTracingLights, DebugDisplaySettings debugDisplaySettings) { // If no lights, exit if (rayTracingLights.lightCount == 0) { ResizeLightDataBuffer(1); return; } // Also we need to build the light list data if (m_LightDataGPUArray == null || m_LightDataGPUArray.count != rayTracingLights.lightCount) { ResizeLightDataBuffer(rayTracingLights.lightCount); } m_LightDataCPUArray.Clear(); // Grab the shadow settings var hdShadowSettings = hdCamera.volumeStack.GetComponent <HDShadowSettings>(); BoolScalableSetting contactShadowScalableSetting = HDAdditionalLightData.ScalableSettings.UseContactShadow(m_RenderPipeline.asset); // Build the data for every light HDLightRenderDatabase lightEntities = HDLightRenderDatabase.instance; var processedLightEntity = new HDProcessedVisibleLight() { shadowMapFlags = HDProcessedVisibleLightsBuilder.ShadowMapFlags.None }; var globalConfig = HDGpuLightsBuilder.CreateGpuLightDataJobGlobalConfig.Create(hdCamera, hdShadowSettings); var shadowInitParams = m_RenderPipeline.currentPlatformRenderPipelineSettings.hdShadowInitParams; for (int lightIdx = 0; lightIdx < rayTracingLights.hdLightEntityArray.Count; ++lightIdx) { // Grab the additinal light data to process int dataIndex = lightEntities.GetEntityDataIndex(rayTracingLights.hdLightEntityArray[lightIdx]); HDAdditionalLightData additionalLightData = lightEntities.hdAdditionalLightData[dataIndex]; LightData lightData = new LightData(); // When the user deletes a light source in the editor, there is a single frame where the light is null before the collection of light in the scene is triggered // the workaround for this is simply to add an invalid light for that frame if (additionalLightData == null) { m_LightDataCPUArray.Add(lightData); continue; } // Evaluate all the light type data that we need LightCategory lightCategory = LightCategory.Count; GPULightType gpuLightType = GPULightType.Point; LightVolumeType lightVolumeType = LightVolumeType.Count; HDLightType lightType = additionalLightData.type; HDRenderPipeline.EvaluateGPULightType(lightType, additionalLightData.spotLightShape, additionalLightData.areaLightShape, ref lightCategory, ref gpuLightType, ref lightVolumeType); // Fetch the light component for this light additionalLightData.gameObject.TryGetComponent(out lightComponent); ref HDLightRenderData lightRenderData = ref lightEntities.GetLightDataAsRef(dataIndex); // Build the processed light data that we need processedLightEntity.dataIndex = dataIndex; processedLightEntity.gpuLightType = gpuLightType; processedLightEntity.lightType = additionalLightData.type; processedLightEntity.distanceToCamera = (additionalLightData.transform.position - hdCamera.camera.transform.position).magnitude; processedLightEntity.lightDistanceFade = HDUtils.ComputeLinearDistanceFade(processedLightEntity.distanceToCamera, lightRenderData.fadeDistance); processedLightEntity.lightVolumetricDistanceFade = HDUtils.ComputeLinearDistanceFade(processedLightEntity.distanceToCamera, lightRenderData.volumetricFadeDistance); processedLightEntity.isBakedShadowMask = HDRenderPipeline.IsBakedShadowMaskLight(lightComponent); // Build a visible light visibleLight.finalColor = LightUtils.EvaluateLightColor(lightComponent, additionalLightData); visibleLight.range = lightComponent.range; // This should be done explicitly, localToWorld matrix doesn't work here localToWorldMatrix.SetColumn(3, lightComponent.gameObject.transform.position); localToWorldMatrix.SetColumn(2, lightComponent.transform.forward); localToWorldMatrix.SetColumn(1, lightComponent.transform.up); localToWorldMatrix.SetColumn(0, lightComponent.transform.right); visibleLight.localToWorldMatrix = localToWorldMatrix; visibleLight.spotAngle = lightComponent.spotAngle; int shadowIndex = additionalLightData.shadowIndex; Vector3 lightDimensions = new Vector3(0.0f, 0.0f, 0.0f); // Use the shared code to build the light data HDGpuLightsBuilder.CreateGpuLightDataJob.ConvertLightToGPUFormat( lightCategory, gpuLightType, globalConfig, lightComponent.lightShadowCasterMode, lightComponent.bakingOutput, visibleLight, processedLightEntity, lightRenderData, out var _, ref lightData); m_RenderPipeline.gpuLightList.ProcessLightDataShadowIndex(cmd, shadowInitParams, lightType, lightComponent, additionalLightData, shadowIndex, ref lightData); // We make the light position camera-relative as late as possible in order // to allow the preceding code to work with the absolute world space coordinates. Vector3 camPosWS = hdCamera.mainViewConstants.worldSpaceCameraPos; HDRenderPipeline.UpdateLightCameraRelativetData(ref lightData, camPosWS); // Set the data for this light m_LightDataCPUArray.Add(lightData); }