protected override bool ProcessNode(CommandBuffer cmd) { if (!base.ProcessNode(cmd) || input == null) { return(false); } HistogramUtility.ComputeLuminanceMinMax(cmd, minMaxBuffer, input); TextureUtils.UpdateTextureFromCurve(interpolationCurve, ref curveTexture); var mat = tempRenderTexture.material = GetTempMaterial("Hidden/Mixture/Levels"); mat.SetFloat("_Mode", (int)mode); mat.SetFloat("_ManualMin", min); mat.SetFloat("_ManualMax", max); mat.SetVector("_RcpTextureSize", new Vector4(1.0f / input.width, 1.0f / input.height, 1.0f / TextureUtils.GetSliceCount(input), 0)); MixtureUtils.SetupDimensionKeyword(mat, tempRenderTexture.dimension); MixtureUtils.SetTextureWithDimension(mat, "_Input", input); mat.SetBuffer("_Luminance", minMaxBuffer); mat.SetTexture("_InterpolationCurve", curveTexture); tempRenderTexture.Update(); CustomTextureManager.UpdateCustomRenderTexture(cmd, tempRenderTexture); output = tempRenderTexture; return(true); }
protected override bool ProcessNode(CommandBuffer cmd) { if (!base.ProcessNode(cmd) || input == null) { return(false); } SyncSettings(); UpdateTempRenderTexture(ref outputR); UpdateTempRenderTexture(ref outputG); UpdateTempRenderTexture(ref outputB); UpdateTempRenderTexture(ref outputA); SetMaterialParams(outputRMat, 0); SetMaterialParams(outputGMat, 1); SetMaterialParams(outputBMat, 2); SetMaterialParams(outputAMat, 3); void SetMaterialParams(Material m, int component) { MixtureUtils.SetTextureWithDimension(m, "_Source", input); m.SetColor("_NeutralColor", neutralColor); m.SetFloat("_Mode", (int)mode); m.SetInt("_Component", component); } return(true); }
protected override bool ProcessNode() { UpdateTempRenderTexture(ref output); if (material == null || material.shader == null) { Debug.LogError($"Can't process {name}, missing material/shader."); return(false); } var outputDimension = rtSettings.GetTextureDimension(graph); MixtureUtils.SetupDimensionKeyword(material, outputDimension); #if UNITY_EDITOR // IsShaderCompiled is editor only if (!IsShaderCompiled(material.shader)) { output.material = null; Debug.LogError($"Can't process {name}, shader has errors."); LogShaderErrors(material.shader); } else #endif { output.material = material; } return(true); }
public IEnumerable <PortData> InputPortType(List <SerializableEdge> edges) { var data = MixtureUtils.UpdateInputPortType(ref inputType, "Input", edges); data.acceptMultipleEdges = true; yield return(data); }
public override void OnInteractivePreviewGUI(Rect previewRect, GUIStyle background) { HandleZoomAndPan(previewRect); if (firstLockedPreviewTarget?.previewTexture != null && e.type == EventType.Repaint) { MixtureUtils.SetupDimensionKeyword(previewMaterial, firstLockedPreviewTarget.previewTexture.dimension); // Set texture property based on the dimension MixtureUtils.SetTextureWithDimension(previewMaterial, "_MainTex0", firstLockedPreviewTarget.previewTexture); MixtureUtils.SetTextureWithDimension(previewMaterial, "_MainTex1", secondLockedPreviewTarget.previewTexture); previewMaterial.SetFloat("_ComparisonSlider", compareSlider); previewMaterial.SetFloat("_ComparisonEnabled", compareEnabled ? 1 : 0); previewMaterial.SetFloat("_CompareMode", (int)compareMode); previewMaterial.SetFloat("_PreviewMip", mipLevel); previewMaterial.SetFloat("_YRatio", previewRect.height / previewRect.width); previewMaterial.SetFloat("_Zoom", zoom); previewMaterial.SetVector("_Pan", shaderPos / previewRect.size); previewMaterial.SetFloat("_FilterMode", (int)filterMode); previewMaterial.SetFloat("_Exp", exposure); previewMaterial.SetVector("_TextureSize", new Vector4(firstLockedPreviewTarget.previewTexture.width, firstLockedPreviewTarget.previewTexture.height, 1.0f / firstLockedPreviewTarget.previewTexture.width, 1.0f / firstLockedPreviewTarget.previewTexture.height)); previewMaterial.SetVector("_Channels", MixtureEditorUtils.GetChannelsMask(channels)); previewMaterial.SetFloat("_IsSRGB0", firstLockedPreviewTarget is OutputNode o0 && o0.mainOutput.sRGB ? 1 : 0); previewMaterial.SetFloat("_IsSRGB1", secondLockedPreviewTarget is OutputNode o1 && o1.mainOutput.sRGB ? 1 : 0); EditorGUI.DrawPreviewTexture(previewRect, Texture2D.whiteTexture, previewMaterial); } else { EditorGUI.DrawRect(previewRect, new Color(1, 0, 1, 1)); } }
protected override bool ProcessNode(CommandBuffer cmd) { rtSettings.doubleBuffered = true; if (!base.ProcessNode(cmd) || inputMesh?.mesh == null) { return(false); } UpdateTempRenderTexture(ref outputVolume); UpdateTempRenderTexture(ref rayMapBuffer, overrideGraphicsFormat: GraphicsFormat.R32_UInt); MixtureUtils.SetupComputeTextureDimension(cmd, computeShader, TextureDimension.Tex3D); // Clear 3D render texture int clearKernel = mode == Mode.Signed ? clearSignedKernel : clearUnsignedKernel; cmd.SetComputeTextureParam(computeShader, clearKernel, "_Output", outputVolume); cmd.SetComputeTextureParam(computeShader, clearKernel, "_RayMapsOutput", rayMapBuffer); DispatchCompute(cmd, clearKernel, outputVolume.width, outputVolume.height, outputVolume.volumeDepth); // Rasterize the mesh in the volume MixtureUtils.RasterizeMeshToTexture3D(cmd, inputMesh, outputVolume, conservativeRaster); // Generate a distance field with JFA JumpFlooding(cmd); return(true); }
public static void ComputeLuminanceMinMax(CommandBuffer cmd, ComputeBuffer targetBuffer, Texture input) { MixtureUtils.SetupComputeTextureDimension(cmd, histogramCompute, input.dimension); // Clear buffers cmd.SetComputeBufferParam(histogramCompute, clearLuminanceKernel, "_ImageLuminance", luminanceBuffer); int dispatchCount = input.width * input.height * TextureUtils.GetSliceCount(input) / 64; // Limit computing to 8K textures int yCount = Mathf.Clamp(dispatchCount / dispatchGroupSizeX / 64, 1, dispatchGroupSizeX); int xCount = Mathf.Clamp(dispatchCount / yCount / 8, 1, dispatchGroupSizeX); cmd.SetComputeIntParam(histogramCompute, "_DispatchSizeX", dispatchGroupSizeX); cmd.DispatchCompute(histogramCompute, clearLuminanceKernel, xCount, yCount, TextureUtils.GetSliceCount(input)); // Find luminance min / max in the texture cmd.SetComputeTextureParam(histogramCompute, computeLuminanceBufferKernel, "_Input", input); cmd.SetComputeBufferParam(histogramCompute, computeLuminanceBufferKernel, "_ImageLuminance", luminanceBuffer); cmd.SetComputeVectorParam(histogramCompute, "_InputTextureSize", new Vector4(input.width, input.height, TextureUtils.GetSliceCount(input), 0)); MixtureUtils.SetTextureWithDimension(cmd, histogramCompute, computeLuminanceBufferKernel, "_Input", input); cmd.SetComputeVectorParam(histogramCompute, "_RcpTextureSize", new Vector4(1.0f / input.width, 1.0f / input.height, 1.0f / TextureUtils.GetSliceCount(input), 0)); cmd.DispatchCompute(histogramCompute, computeLuminanceBufferKernel, Mathf.Max(1, input.width / 8), Mathf.Max(1, input.height / 8), TextureUtils.GetSliceCount(input)); ReduceLuminanceBuffer(cmd, dispatchCount); cmd.SetComputeBufferParam(histogramCompute, copyMinMaxToBuffer, "_ImageLuminance", luminanceBuffer); cmd.SetComputeBufferParam(histogramCompute, copyMinMaxToBuffer, "_Target", targetBuffer); cmd.DispatchCompute(histogramCompute, copyMinMaxToBuffer, 1, 1, 1); }
protected void BlitMixtureIcon(Texture preview, RenderTexture target, bool realtime = false) { var blitMaterial = (realtime) ? MixtureUtils.blitRealtimeIconMaterial : MixtureUtils.blitIconMaterial; MixtureUtils.SetupDimensionKeyword(blitMaterial, preview.dimension); switch (preview.dimension) { case TextureDimension.Tex2D: blitMaterial.SetTexture("_Texture2D", preview); Graphics.Blit(preview, target, blitMaterial, 0); break; case TextureDimension.Tex2DArray: blitMaterial.SetTexture("_Texture2DArray", preview); Graphics.Blit(preview, target, blitMaterial, 0); break; case TextureDimension.Tex3D: blitMaterial.SetTexture("_Texture3D", preview); Graphics.Blit(preview, target, blitMaterial, 0); break; case TextureDimension.Cube: blitMaterial.SetTexture("_Cubemap", preview); Graphics.Blit(preview, target, blitMaterial, 0); break; default: Debug.LogError($"{preview.dimension} is not supported for icon preview"); break; } }
protected override bool ProcessNode(CommandBuffer cmd) { // Force the double buffering for multi-pass flooding rtSettings.doubleBuffered = true; if (!base.ProcessNode(cmd) || input == null) { return(false); } UpdateTempRenderTexture(ref output); cmd.SetComputeFloatParam(computeShader, "_Threshold", threshold); cmd.SetComputeVectorParam(computeShader, "_Size", new Vector4(output.width, 1.0f / output.width)); cmd.SetComputeFloatParam(computeShader, "_Distance", distance / 100.0f); cmd.SetComputeIntParam(computeShader, "_ThresholdMode", (int)thresholdMode); cmd.SetComputeIntParam(computeShader, "_DistanceMode", (int)distanceMode); cmd.SetComputeIntParam(computeShader, "_Mode", (int)mode); output.doubleBuffered = true; output.EnsureDoubleBufferConsistency(); var rt = output.GetDoubleBufferRenderTexture(); rt.Release(); rt.enableRandomWrite = true; rt.Create(); MixtureUtils.SetupComputeDimensionKeyword(computeShader, input.dimension); cmd.SetComputeTextureParam(computeShader, fillUvKernel, "_Input", input); cmd.SetComputeTextureParam(computeShader, fillUvKernel, "_Output", output); cmd.SetComputeTextureParam(computeShader, fillUvKernel, "_FinalOutput", rt); cmd.SetComputeIntParam(computeShader, "_DistanceMode", (int)distanceMode); cmd.SetComputeFloatParam(computeShader, "_InputScaleFactor", (float)input.width / (float)output.width); DispatchCompute(cmd, fillUvKernel, output.width, output.height, output.volumeDepth); int maxLevels = (int)Mathf.Log(input.width, 2); for (int i = 0; i <= maxLevels; i++) { float offset = 1 << (maxLevels - i); cmd.SetComputeFloatParam(computeShader, "_InputScaleFactor", 1); cmd.SetComputeFloatParam(computeShader, "_Offset", offset); cmd.SetComputeTextureParam(computeShader, jumpFloodingKernel, "_Input", output); cmd.SetComputeTextureParam(computeShader, jumpFloodingKernel, "_Output", rt); cmd.SetComputeIntParam(computeShader, "_DistanceMode", (int)distanceMode); DispatchCompute(cmd, jumpFloodingKernel, output.width, output.height, output.volumeDepth); cmd.CopyTexture(rt, output); } cmd.SetComputeFloatParam(computeShader, "_InputScaleFactor", (float)input.width / (float)output.width); cmd.SetComputeTextureParam(computeShader, finalPassKernel, "_Input", input); cmd.SetComputeTextureParam(computeShader, finalPassKernel, "_Output", rt); cmd.SetComputeIntParam(computeShader, "_DistanceMode", (int)distanceMode); cmd.SetComputeTextureParam(computeShader, finalPassKernel, "_FinalOutput", output); DispatchCompute(cmd, finalPassKernel, output.width, output.height, output.volumeDepth); return(true); }
protected override void Enable() { if (createNewPrefab) { // Create and save the new prefab var defaultPrefab = CreateDefaultPrefab(); prefab = SavePrefab(defaultPrefab); MixtureUtils.DestroyGameObject(defaultPrefab); ProjectWindowUtil.ShowCreatedAsset(prefab); } UpdateRenderTextures(); }
protected override bool ProcessNode(CommandBuffer cmd) { if (output == null) { return(false); } var outputDimension = rtSettings.GetTextureDimension(graph); MixtureUtils.SetupDimensionKeyword(material, outputDimension); var s = material.shader; for (int i = 0; i < s.GetPropertyCount(); i++) { if (s.GetPropertyType(i) != ShaderPropertyType.Texture) { continue; } int id = s.GetPropertyNameId(i); if (material.GetTexture(id) != null) { continue; // Avoid overriding existing textures } var dim = s.GetPropertyTextureDimension(i); if (dim == TextureDimension.Tex2D) { continue; // Texture2D don't need this feature } // default texture names doesn't work with cubemap and 3D textures so we do it ourselves... switch (s.GetPropertyTextureDefaultName(i)) { case "black": material.SetTexture(id, TextureUtils.GetBlackTexture(dim)); break; case "white": material.SetTexture(id, TextureUtils.GetWhiteTexture(dim)); break; // TODO: grey and bump } } output.material = material; bool useCustomUV = material.HasTextureBound("_UV", rtSettings.GetTextureDimension(graph)); material.SetKeywordEnabled("USE_CUSTOM_UV", useCustomUV); return(true); }
public static void ComputeHistogram(CommandBuffer cmd, Texture input, HistogramData data) { using (new ProfilingScope(cmd, new ProfilingSampler("Generate Histogram"))) { MixtureUtils.SetupComputeTextureDimension(cmd, histogramCompute, input.dimension); // Clear buffers cmd.SetComputeBufferParam(histogramCompute, clearKernel, "_ImageLuminance", luminanceBuffer); cmd.SetComputeBufferParam(histogramCompute, clearKernel, "_Histogram", data.histogram); int dispatchCount = input.width * input.height * TextureUtils.GetSliceCount(input) / 64; // Limit computing to 8K textures int yCount = Mathf.Clamp(dispatchCount / dispatchGroupSizeX / 64, 1, dispatchGroupSizeX); int xCount = Mathf.Clamp(dispatchCount / yCount / 8, 1, dispatchGroupSizeX); cmd.SetComputeIntParam(histogramCompute, "_DispatchSizeX", dispatchGroupSizeX); cmd.DispatchCompute(histogramCompute, clearKernel, xCount, yCount, 1); // Find luminance min / max in the texture // TODO: handle texture 3D and Cube cmd.SetComputeTextureParam(histogramCompute, computeLuminanceBufferKernel, "_Input", input); cmd.SetComputeBufferParam(histogramCompute, computeLuminanceBufferKernel, "_ImageLuminance", luminanceBuffer); cmd.SetComputeVectorParam(histogramCompute, "_InputTextureSize", new Vector4(input.width, input.height, TextureUtils.GetSliceCount(input), 0)); cmd.SetComputeVectorParam(histogramCompute, "_RcpTextureSize", new Vector4(1.0f / input.width, 1.0f / input.height, 1.0f / TextureUtils.GetSliceCount(input), 0)); MixtureUtils.SetTextureWithDimension(cmd, histogramCompute, computeLuminanceBufferKernel, "_Input", input); cmd.DispatchCompute(histogramCompute, computeLuminanceBufferKernel, Mathf.Max(1, input.width / 8), Mathf.Max(1, input.height / 8), TextureUtils.GetSliceCount(input)); ReduceLuminanceBuffer(cmd, dispatchCount); // Generate histogram data in compute buffer cmd.SetComputeBufferParam(histogramCompute, generateHistogramKernel, "_ImageLuminance", luminanceBuffer); cmd.SetComputeBufferParam(histogramCompute, generateHistogramKernel, "_Histogram", data.histogram); cmd.SetComputeTextureParam(histogramCompute, generateHistogramKernel, "_Input", input); cmd.SetComputeIntParam(histogramCompute, "_HistogramBucketCount", data.bucketCount); cmd.SetComputeVectorParam(histogramCompute, "_RcpTextureSize", new Vector4(1.0f / input.width, 1.0f / input.height, 1.0f / TextureUtils.GetSliceCount(input), 0)); MixtureUtils.SetTextureWithDimension(cmd, histogramCompute, generateHistogramKernel, "_Input", input); cmd.DispatchCompute(histogramCompute, generateHistogramKernel, Mathf.Max(1, input.width / 8), Mathf.Max(1, input.height / 8), TextureUtils.GetSliceCount(input)); cmd.SetComputeBufferParam(histogramCompute, computeHistogramDataKernel, "_HistogramData", data.histogramData); cmd.SetComputeBufferParam(histogramCompute, computeHistogramDataKernel, "_Histogram", data.histogram); cmd.DispatchCompute(histogramCompute, computeHistogramDataKernel, Mathf.Max(1, data.bucketCount / 64), 1, 1); // Request histogram data back for inspector cmd.RequestAsyncReadback(luminanceBuffer, 8, 0, (c) => { var d = c.GetData <float>(); if (d.Length > 0) { data.minLuminance = d[0]; data.maxLuminance = d[1]; } }); } }
bool UpdateFinalCopyMaterial(OutputTextureSettings targetOutput) { if (targetOutput.finalCopyMaterial == null) { targetOutput.finalCopyMaterial = CreateFinalCopyMaterial(); if (!graph.IsObjectInGraph(targetOutput.finalCopyMaterial)) { graph.AddObjectToGraph(targetOutput.finalCopyMaterial); } } // Manually reset all texture inputs ResetMaterialPropertyToDefault(targetOutput.finalCopyMaterial, "_Source_2D"); ResetMaterialPropertyToDefault(targetOutput.finalCopyMaterial, "_Source_3D"); ResetMaterialPropertyToDefault(targetOutput.finalCopyMaterial, "_Source_Cube"); var input = targetOutput.inputTexture; if (input != null) { if (input.dimension != (TextureDimension)rtSettings.dimension) { Debug.LogError("Error: Expected texture type input for the OutputNode is " + graph.mainOutputTexture.dimension + " but " + input?.dimension + " was provided"); return(false); } MixtureUtils.SetupDimensionKeyword(targetOutput.finalCopyMaterial, input.dimension); if (input.dimension == TextureDimension.Tex2D) { targetOutput.finalCopyMaterial.SetTexture("_Source_2D", input); } else if (input.dimension == TextureDimension.Tex3D) { targetOutput.finalCopyMaterial.SetTexture("_Source_3D", input); } else { targetOutput.finalCopyMaterial.SetTexture("_Source_Cube", input); } targetOutput.finalCopyMaterial.SetInt("_IsSRGB", targetOutput.sRGB ? 1 : 0); } if (targetOutput.finalCopyRT != null) { targetOutput.finalCopyRT.material = targetOutput.finalCopyMaterial; } return(true); }
protected override void Enable() { #if UNITY_EDITOR if (createNewPrefab) { // Create and save the new prefab var defaultPrefab = GameObject.Instantiate(LoadDefaultPrefab()); prefab = SavePrefab(defaultPrefab); MixtureUtils.DestroyGameObject(defaultPrefab); ProjectWindowUtil.ShowCreatedAsset(prefab); EditorGUIUtility.PingObject(prefab); } #endif }
void GenerateCustomMipMaps() { #if UNITY_EDITOR mipchainCmd.Clear(); mipchainCmd.name = "Generate Custom MipMaps"; if (mipMapPropertyBlock == null) { mipMapPropertyBlock = new MaterialPropertyBlock(); } int slice = 0; // TODO: support 3D textures and Cubemaps // for (int slice = 0; slice < tempRenderTexture.volumeDepth; slice++) { for (int i = 0; i < tempRenderTexture.mipmapCount - 1; i++) { int mipLevel = i + 1; mipmapRenderTexture.name = "Tmp mipmap"; mipchainCmd.SetRenderTarget(mipmapRenderTexture, mipLevel, CubemapFace.Unknown, 0); Vector4 textureSize = new Vector4(tempRenderTexture.width, tempRenderTexture.height, tempRenderTexture.volumeDepth, 0); textureSize /= 1 << (mipLevel); Vector4 textureSizeRcp = new Vector4(1.0f / textureSize.x, 1.0f / textureSize.y, 1.0f / textureSize.z, 0); mipMapPropertyBlock.SetTexture("_InputTexture_2D", tempRenderTexture); mipMapPropertyBlock.SetTexture("_InputTexture_3D", tempRenderTexture); mipMapPropertyBlock.SetFloat("_CurrentMipLevel", mipLevel - 1); mipMapPropertyBlock.SetFloat("_MaxMipLevel", tempRenderTexture.mipmapCount); mipMapPropertyBlock.SetVector("_InputTextureSize", textureSize); mipMapPropertyBlock.SetVector("_InputTextureSizeRcp", textureSizeRcp); mipMapPropertyBlock.SetFloat("_CurrentSlice", slice / (float)tempRenderTexture.width); MixtureUtils.SetupDimensionKeyword(customMipMapMaterial, tempRenderTexture.dimension); mipchainCmd.DrawProcedural(Matrix4x4.identity, customMipMapMaterial, 0, MeshTopology.Triangles, 3, 1, mipMapPropertyBlock); mipchainCmd.CopyTexture(mipmapRenderTexture, slice, mipLevel, tempRenderTexture, slice, mipLevel); } } // Dirty hack to enqueue the command buffer but it's okay because it's the builtin renderer. if (GraphicsSettings.renderPipelineAsset == null) { Camera.main.RemoveCommandBuffer(CameraEvent.BeforeDepthTexture, mipchainCmd); Camera.main.AddCommandBuffer(CameraEvent.BeforeDepthTexture, mipchainCmd); } #endif }
void GenerateCustomMipMaps(CommandBuffer cmd, OutputTextureSettings targetOutput) { #if UNITY_EDITOR if (targetOutput.mipmapTempRT == null || targetOutput.finalCopyRT == null) { return; } cmd.BeginSample(generateMipMapSampler); if (targetOutput.mipMapPropertyBlock == null) { targetOutput.mipMapPropertyBlock = new MaterialPropertyBlock(); } int slice = 0; // TODO: support 3D textures and Cubemaps // for (int slice = 0; slice < targetOutput.finalCopyRT.volumeDepth; slice++) { for (int i = 0; i < targetOutput.finalCopyRT.mipmapCount - 1; i++) { int mipLevel = i + 1; targetOutput.mipmapTempRT.name = "Tmp mipmap"; cmd.SetRenderTarget(targetOutput.mipmapTempRT, mipLevel, CubemapFace.Unknown, 0); Vector4 textureSize = new Vector4(targetOutput.finalCopyRT.width, targetOutput.finalCopyRT.height, targetOutput.finalCopyRT.volumeDepth, 0); textureSize /= 1 << (mipLevel); Vector4 textureSizeRcp = new Vector4(1.0f / textureSize.x, 1.0f / textureSize.y, 1.0f / textureSize.z, 0); targetOutput.mipMapPropertyBlock.SetTexture("_InputTexture_2D", targetOutput.finalCopyRT); targetOutput.mipMapPropertyBlock.SetTexture("_InputTexture_3D", targetOutput.finalCopyRT); targetOutput.mipMapPropertyBlock.SetFloat("_CurrentMipLevel", mipLevel - 1); targetOutput.mipMapPropertyBlock.SetFloat("_MaxMipLevel", targetOutput.finalCopyRT.mipmapCount); targetOutput.mipMapPropertyBlock.SetVector("_InputTextureSize", textureSize); targetOutput.mipMapPropertyBlock.SetVector("_InputTextureSizeRcp", textureSizeRcp); targetOutput.mipMapPropertyBlock.SetFloat("_CurrentSlice", slice / (float)targetOutput.finalCopyRT.width); MixtureUtils.SetupDimensionKeyword(targetOutput.customMipMapMaterial, targetOutput.finalCopyRT.dimension); cmd.DrawProcedural(Matrix4x4.identity, targetOutput.customMipMapMaterial, 0, MeshTopology.Triangles, 3, 1, targetOutput.mipMapPropertyBlock); cmd.CopyTexture(targetOutput.mipmapTempRT, slice, mipLevel, targetOutput.finalCopyRT, slice, mipLevel); } } cmd.EndSample(generateMipMapSampler); #endif }
public override void OnInteractivePreviewGUI(Rect previewRect, GUIStyle background) { HandleZoomAndPan(previewRect); if (mixtureInspector.firstLockedPreviewTarget?.previewTexture != null && e.type == EventType.Repaint) { mixtureInspector.volumeCameraMatrix = Matrix4x4.Rotate(Quaternion.Euler(mixtureInspector.cameraYAxis, mixtureInspector.cameraXAxis, 0)); MixtureUtils.SetupDimensionKeyword(previewMaterial, mixtureInspector.firstLockedPreviewTarget.previewTexture.dimension); // Set texture property based on the dimension MixtureUtils.SetTextureWithDimension(previewMaterial, "_MainTex0", mixtureInspector.firstLockedPreviewTarget.previewTexture); MixtureUtils.SetTextureWithDimension(previewMaterial, "_MainTex1", mixtureInspector.secondLockedPreviewTarget.previewTexture); previewMaterial.SetFloat("_ComparisonSlider", mixtureInspector.compareSlider); previewMaterial.SetFloat("_ComparisonSlider3D", mixtureInspector.compareSlider3D); previewMaterial.SetVector("_MouseUV", mixtureInspector.mouseUV); previewMaterial.SetMatrix("_CameraMatrix", mixtureInspector.volumeCameraMatrix); previewMaterial.SetFloat("_CameraZoom", mixtureInspector.cameraZoom); previewMaterial.SetFloat("_ComparisonEnabled", mixtureInspector.compareEnabled ? 1 : 0); previewMaterial.SetFloat("_CompareMode", (int)mixtureInspector.compareMode); previewMaterial.SetFloat("_PreviewMip", mixtureInspector.mipLevel); previewMaterial.SetFloat("_YRatio", previewRect.height / previewRect.width); previewMaterial.SetFloat("_Zoom", mixtureInspector.zoom); previewMaterial.SetVector("_Pan", mixtureInspector.shaderPos / previewRect.size); previewMaterial.SetFloat("_FilterMode", (int)mixtureInspector.filterMode); previewMaterial.SetFloat("_Exp", mixtureInspector.exposure); previewMaterial.SetVector("_TextureSize", new Vector4(mixtureInspector.firstLockedPreviewTarget.previewTexture.width, mixtureInspector.firstLockedPreviewTarget.previewTexture.height, 1.0f / mixtureInspector.firstLockedPreviewTarget.previewTexture.width, 1.0f / mixtureInspector.firstLockedPreviewTarget.previewTexture.height)); previewMaterial.SetVector("_Channels", MixtureEditorUtils.GetChannelsMask(mixtureInspector.channels)); previewMaterial.SetFloat("_IsSRGB0", mixtureInspector.firstLockedPreviewTarget is OutputNode o0 && o0.mainOutput.sRGB ? 1 : 0); previewMaterial.SetFloat("_IsSRGB1", mixtureInspector.secondLockedPreviewTarget is OutputNode o1 && o1.mainOutput.sRGB ? 1 : 0); previewMaterial.SetFloat("_PreserveAspect", mixtureInspector.preserveAspect ? 1 : 0); previewMaterial.SetFloat("_Texture3DMode", (int)mixtureInspector.texture3DPreviewMode); previewMaterial.SetFloat("_Density", mixtureInspector.texture3DDensity); previewMaterial.SetFloat("_SDFOffset", mixtureInspector.texture3DDistanceFieldOffset); previewMaterial.SetFloat("_SDFChannel", (int)mixtureInspector.sdfChannel); previewMaterial.SetFloat("_ShowCubeBackface", mixtureInspector.showCubeBackface ? 1 : 0); previewMaterial.SetFloat("_InvertSurface", mixtureInspector.invertSurface ? 1 : 0); previewMaterial.SetFloat("_VolumetricDensityChannel", mixtureInspector.volumetricDensityChannel); EditorGUI.DrawPreviewTexture(previewRect, Texture2D.whiteTexture, previewMaterial); } else { EditorGUI.DrawRect(previewRect, new Color(1, 0, 1, 1)); } }
protected override bool ProcessNode(CommandBuffer cmd) { if (!base.ProcessNode(cmd) || inputMesh?.mesh == null) { return(false); } UpdateTempRenderTexture(ref outputVolume); // Clear 3D render texture cmd.SetComputeTextureParam(computeShader, 0, "_Output", outputVolume); DispatchCompute(cmd, 0, outputVolume.width, outputVolume.height, outputVolume.volumeDepth); MixtureUtils.RasterizeMeshToTexture3D(cmd, inputMesh, outputVolume, conservativeRaster); return(true); }
protected override bool ProcessNode(CommandBuffer cmd) { if (!base.ProcessNode(cmd) || textureAsset == null) { return(false); } #if UNITY_EDITOR var importer = UnityEditor.AssetImporter.GetAtPath(UnityEditor.AssetDatabase.GetAssetPath(textureAsset)); if (importer is UnityEditor.TextureImporter textureImporter) { normalMap = textureImporter.textureType == UnityEditor.TextureImporterType.NormalMap; } #endif // Compressed normal maps need to be converted from AG to RG format if (normalMap) { if (postProcessedTexture == null) { postProcessedTexture = new RenderTexture(1, 1, 0, GraphicsFormat.R16G16B16A16_SFloat); } if (postProcessedTexture.width != textureAsset.width || postProcessedTexture.height != textureAsset.height) { postProcessedTexture.Release(); postProcessedTexture.width = textureAsset.width; postProcessedTexture.height = textureAsset.height; postProcessedTexture.Create(); } var blitMaterial = GetTempMaterial("Hidden/Mixture/TextureNode"); MixtureUtils.SetTextureWithDimension(blitMaterial, "_Source", textureAsset); MixtureUtils.Blit(cmd, blitMaterial, textureAsset, postProcessedTexture); outputTexture = postProcessedTexture; } else { postProcessedTexture?.Release(); outputTexture = textureAsset; } return(true); }
public sealed override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor) { // In case the material is shown in the inspector, the editor will not be linked to a node if (!mixtureDrawerInfos.ContainsKey(editor)) { DrawerGUI(position, prop, label, editor, null, null); return; } var nodeView = GetNodeView(editor); var graph = GetGraph(editor); var node = nodeView.nodeTarget as MixtureNode; allowedDimensions = MixtureUtils.GetAllowedDimentions(prop.name); if (IsVisible(editor)) { DrawerGUI(position, prop, label, editor, graph, nodeView); } }
protected override bool ProcessNode(CommandBuffer cmd) { if (!base.ProcessNode(cmd) || input == null) { return(false); } UpdateTempRenderTexture(ref outputR); UpdateTempRenderTexture(ref outputG); UpdateTempRenderTexture(ref outputB); UpdateTempRenderTexture(ref outputA); MixtureUtils.SetTextureWithDimension(outputRMat, "_Source", input); MixtureUtils.SetTextureWithDimension(outputGMat, "_Source", input); MixtureUtils.SetTextureWithDimension(outputBMat, "_Source", input); MixtureUtils.SetTextureWithDimension(outputAMat, "_Source", input); outputRMat.SetInt("_Component", 0); outputGMat.SetInt("_Component", 1); outputBMat.SetInt("_Component", 2); outputAMat.SetInt("_Component", 3); return(true); }
bool PropertySupportsDimension(MaterialProperty prop, TextureDimension dim) { return(MixtureUtils.GetAllowedDimentions(prop.name).Contains(dim)); }
protected override bool ProcessNode() { if (graph.outputTexture == null) { Debug.LogError("Output Node can't write to target texture, Graph references a null output texture"); return(false); } // Update the renderTexture reference for realtime graph if (graph.isRealtime) { if (tempRenderTexture != graph.outputTexture) { onTempRenderTextureUpdated?.Invoke(); } tempRenderTexture = graph.outputTexture as CustomRenderTexture; } var inputPort = GetPort(nameof(input), nameof(input)); if (inputPort.GetEdges().Count == 0) { if (uniqueMessages.Add("OutputNotConnected")) { AddMessage("Output node input is not connected", NodeMessageType.Warning); } input = TextureUtils.GetBlackTexture(rtSettings); // TODO: set a black texture of texture dimension as default value return(false); } else { uniqueMessages.Clear(); ClearMessages(); } // Update the renderTexture size and format: if (UpdateTempRenderTexture(ref tempRenderTexture)) { onTempRenderTextureUpdated?.Invoke(); } if (input.dimension != graph.outputTexture.dimension) { Debug.LogError("Error: Expected texture type input for the OutputNode is " + graph.outputTexture.dimension + " but " + input?.dimension + " was provided"); return(false); } MixtureUtils.SetupDimensionKeyword(finalCopyMaterial, input.dimension); // Manually reset all texture inputs ResetMaterialPropertyToDefault(finalCopyMaterial, "_Source_2D"); ResetMaterialPropertyToDefault(finalCopyMaterial, "_Source_3D"); ResetMaterialPropertyToDefault(finalCopyMaterial, "_Source_Cube"); if (input.dimension == TextureDimension.Tex2D) { finalCopyMaterial.SetTexture("_Source_2D", input); } else if (input.dimension == TextureDimension.Tex3D) { finalCopyMaterial.SetTexture("_Source_3D", input); } else { finalCopyMaterial.SetTexture("_Source_Cube", input); } tempRenderTexture.material = finalCopyMaterial; return(true); }
static bool IsCompatibleWithRealtimeGraph(BaseGraph graph) => MixtureUtils.IsRealtimeGraph(graph);
public IEnumerable <PortData> InputPortTypeFalse(List <SerializableEdge> edges) { yield return(MixtureUtils.UpdateInputPortType(ref inputType, "False", edges)); }
protected override bool ProcessNode(CommandBuffer cmd) { if (!base.ProcessNode(cmd) || textureAsset == null) { return(false); } #if UNITY_EDITOR var importer = UnityEditor.AssetImporter.GetAtPath(UnityEditor.AssetDatabase.GetAssetPath(textureAsset)); if (importer is UnityEditor.TextureImporter textureImporter) { normalMap = textureImporter.textureType == UnityEditor.TextureImporterType.NormalMap; } #endif int targetWidth = textureAsset.width; int targetHeight = textureAsset.height; int targetDepth = TextureUtils.GetSliceCount(textureAsset); bool needsTempTarget = false; if (!IsPowerOf2(textureAsset) && POTMode != PowerOf2Mode.None) { int maxSize = Mathf.Max(Mathf.Max(targetWidth, targetHeight), targetDepth); int potSize = 0; switch (POTMode) { case PowerOf2Mode.ScaleToNextPowerOf2: potSize = Mathf.NextPowerOfTwo(maxSize); break; default: potSize = Mathf.ClosestPowerOfTwo(maxSize); break; } targetWidth = targetHeight = targetDepth = potSize; needsTempTarget = true; } if (normalMap) { needsTempTarget = true; } if (needsTempTarget && postProcessedTexture == null) { postProcessedTexture = new RenderTexture(1, 1, 0, GraphicsFormat.R16G16B16A16_SFloat, mipCount: textureAsset.mipmapCount) { dimension = textureAsset.dimension, enableRandomWrite = true, volumeDepth = 1 } } ; else if (!needsTempTarget) { postProcessedTexture?.Release(); postProcessedTexture = null; } if (postProcessedTexture != null && (postProcessedTexture.width != targetWidth || postProcessedTexture.height != targetHeight || postProcessedTexture.volumeDepth != targetDepth)) { postProcessedTexture.Release(); postProcessedTexture.width = targetWidth; postProcessedTexture.height = targetHeight; postProcessedTexture.volumeDepth = targetDepth; postProcessedTexture.Create(); } // TODO: same alloc as normal map + scale and crop options // Compressed normal maps need to be converted from AG to RG format if (normalMap) { // Transform normal map texture into POT var blitMaterial = GetTempMaterial("Hidden/Mixture/TextureNode"); MixtureUtils.SetTextureWithDimension(blitMaterial, "_Source", textureAsset); blitMaterial.SetInt("_POTMode", (int)POTMode); MixtureUtils.Blit(cmd, blitMaterial, textureAsset, postProcessedTexture, 0); outputTexture = postProcessedTexture; } else if (needsTempTarget) { // Transform standard texture into POT var blitMaterial = GetTempMaterial("Hidden/Mixture/TextureNode"); MixtureUtils.SetTextureWithDimension(blitMaterial, "_Source", textureAsset); blitMaterial.SetInt("_POTMode", (int)POTMode); MixtureUtils.Blit(cmd, blitMaterial, textureAsset, postProcessedTexture, 1); outputTexture = postProcessedTexture; } else { outputTexture = textureAsset; } if (outputTexture != null) { settings.sizeMode = OutputSizeMode.Absolute; settings.width = outputTexture.width; settings.height = outputTexture.height; settings.depth = TextureUtils.GetSliceCount(outputTexture); } return(true); }
protected override bool ProcessNode() { if (graph.outputTexture == null) { Debug.LogError("Output Node can't write to target texture, Graph references a null output texture"); return(false); } // Update the renderTexture reference for realtime graph if (graph.isRealtime) { if (tempRenderTexture != graph.outputTexture) { onTempRenderTextureUpdated?.Invoke(); } tempRenderTexture = graph.outputTexture as CustomRenderTexture; } var inputPort = GetPort(nameof(input), nameof(input)); if (inputPort.GetEdges().Count == 0) { if (uniqueMessages.Add("OutputNotConnected")) { AddMessage("Output node input is not connected", NodeMessageType.Warning); } } else { uniqueMessages.Clear(); ClearMessages(); } // Update the renderTexture size and format: if (UpdateTempRenderTexture(ref tempRenderTexture, hasMips, customMipMapShader == null)) { onTempRenderTextureUpdated?.Invoke(); } // Manually reset all texture inputs ResetMaterialPropertyToDefault(finalCopyMaterial, "_Source_2D"); ResetMaterialPropertyToDefault(finalCopyMaterial, "_Source_3D"); ResetMaterialPropertyToDefault(finalCopyMaterial, "_Source_Cube"); if (input != null && inputPort.GetEdges().Count != 0) { if (input.dimension != graph.outputTexture.dimension) { Debug.LogError("Error: Expected texture type input for the OutputNode is " + graph.outputTexture.dimension + " but " + input?.dimension + " was provided"); return(false); } MixtureUtils.SetupDimensionKeyword(finalCopyMaterial, input.dimension); if (input.dimension == TextureDimension.Tex2D) { finalCopyMaterial.SetTexture("_Source_2D", input); } else if (input.dimension == TextureDimension.Tex3D) { finalCopyMaterial.SetTexture("_Source_3D", input); } else { finalCopyMaterial.SetTexture("_Source_Cube", input); } } tempRenderTexture.material = finalCopyMaterial; // The CustomRenderTexture update will be triggered at the begining of the next frame so we wait one frame to generate the mipmaps // We need to do this because we can't generate custom mipMaps with CustomRenderTextures if (customMipMapShader != null && hasMips) { UpdateTempRenderTexture(ref mipmapRenderTexture, true, false); GenerateCustomMipMaps(); } else { Camera.main.RemoveCommandBuffers(CameraEvent.BeforeDepthTexture); } return(true); }
protected void ClearBuffer(CommandBuffer cmd, ComputeBuffer buffer, int sizeInByte = -1, int offset = 0) => MixtureUtils.ClearBuffer(cmd, buffer, sizeInByte, offset);
protected override bool ProcessNode(CommandBuffer cmd) { rtSettings.doubleBuffered = true; if (!base.ProcessNode(cmd) || input == null) { return(false); } TextureUtils.CopyTexture(cmd, input, output, false); var mipmapGenMat = GetTempMaterial("Hidden/Mixture/GenerateMipMaps"); if (mode == Mode.Custom) { mipmapGenMat = material; } else { output.material = null; } if (mode == Mode.Auto) { cmd.GenerateMips(output); } else { var props = new MaterialPropertyBlock(); MixtureUtils.SetupDimensionKeyword(mipmapGenMat, rtSettings.GetTextureDimension(graph)); mipmapGenMat.SetFloat("_Mode", (int)mode); MixtureUtils.SetTextureWithDimension(props, "_PreviousMip", input); // Manually generate mips: for (int i = 0; i < output.mipmapCount - 1; i++) { props.SetFloat("_SourceMip", i); float width = Mathf.Max(1, input.width >> i); float height = Mathf.Max(1, input.width >> i); float depth = Mathf.Max(1, TextureUtils.GetSliceCount(input) >> i); props.SetVector("_RcpTextureSize", new Vector4(1.0f / width, 1.0f / height, 1.0f / depth, 0.0f)); output.material = mipmapGenMat; if (mode == Mode.Gaussian) { // 2 passes of gaussian blur for 2D and Cubemaps props.SetVector("_GaussianBlurDirection", Vector3.right); CustomTextureManager.UpdateCustomRenderTexture(cmd, output, 1, i + 1, props); TextureUtils.CopyTexture(cmd, output.GetDoubleBufferRenderTexture(), output, i + 1); props.SetFloat("_SourceMip", i + 1); MixtureUtils.SetTextureWithDimension(props, "_PreviousMip", output); props.SetVector("_GaussianBlurDirection", Vector3.up); CustomTextureManager.UpdateCustomRenderTexture(cmd, output, 1, i + 1, props); // And a third pass if we're in 3D if (input.dimension == TextureDimension.Tex3D) { props.SetVector("_GaussianBlurDirection", Vector3.forward); TextureUtils.CopyTexture(cmd, output.GetDoubleBufferRenderTexture(), output, i + 1); CustomTextureManager.UpdateCustomRenderTexture(cmd, output, 1, i + 1, props); } } else { CustomTextureManager.UpdateCustomRenderTexture(cmd, output, 1, i + 1, props); } TextureUtils.CopyTexture(cmd, output.GetDoubleBufferRenderTexture(), output, i + 1); MixtureUtils.SetTextureWithDimension(props, "_PreviousMip", output); } } output.material = null; return(true); }
bool PropertySupportsDimension(string name, TextureDimension dim) { return(MixtureUtils.GetAllowedDimentions(name).Contains(dim)); }