private void PersistLookupTexture() { SkinShadingLookupTexture l = target as SkinShadingLookupTexture; if (!l) { return; } string assetName = (l.gameObject.name) + kLookupTexturePropertyName; // Dr Paranoia, featuring his sidekick, Punk Patch. assetName = assetName.Replace(":", "_"); Texture2D persistentTexture = PersistLookupTexture(assetName, l.lookupTexture); //TODO: fix this name. foreach (Material m in l.GetComponent <Renderer>().sharedMaterials) { if (HasLookupTextureSlot(m)) { m.SetTexture(kLookupTexturePropertyName, persistentTexture); } } }
public void OnEnable() { SkinShadingLookupTexture l = target as SkinShadingLookupTexture; if (!l) { return; } string path = AssetDatabase.GetAssetPath(l.lookupTexture); if (path == "") { baked = false; } }
public override void OnInspectorGUI() { SkinShadingLookupTexture l = target as SkinShadingLookupTexture; GUILayout.Label("SCATTERING", EditorStyles.miniBoldLabel); EditorGUI.indentLevel++; l.topLayerStrength = EditorGUILayout.Slider("Top Layer", l.topLayerStrength, 0f, 1.0f); l.epiLayerStrength = EditorGUILayout.Slider("Epi Layer", l.epiLayerStrength, 0f, 1.0f); l.subLayerStrength = EditorGUILayout.Slider("Sub Layer", l.subLayerStrength, 0f, 1.0f); EditorGUI.indentLevel++; l.isEyes = EditorGUILayout.Toggle(" Eyes?", l.isEyes); if (!l.isEyes) { l.sssssBlurDistance = EditorGUILayout.Slider("SSSSS Distance", l.sssssBlurDistance, 0.1f, 4.0f); l.epiRelative = EditorGUILayout.Slider(" Epi Softness", l.epiRelative, 0.1f, 0.9f); l.fadeWithDistance = EditorGUILayout.Toggle(" Distance Fade", l.fadeWithDistance); } else { GUILayout.Label(" NOTE: Eyes are reusing SSS buffer from the face", EditorStyles.miniBoldLabel); } EditorGUI.indentLevel--; EditorGUILayout.Space(); //l.diffuseIntensity = EditorGUILayout.Slider ("Diffuse", l.diffuseIntensity, 0f, 2f); { l.keyColor = EditorGUILayout.ColorField("Top Layer Color", l.keyColor); l.epiColor = EditorGUILayout.ColorField("Epi Layer Scatter", l.epiColor); l.scatterColor = EditorGUILayout.ColorField("Sub Layer Scatter", l.scatterColor); l.saturation = EditorGUILayout.Slider(" Saturation", l.saturation, 0.0f, 10.0f); //l.backColor = EditorGUILayout.ColorField ("Back Color", l.backColor); //l.scatter = EditorGUILayout.Slider (" Scatter", l.scatter, -1f, 1f); //l.wrapAround = EditorGUILayout.Slider ("Wrap Around", l.wrapAround, -1f, 1f); EditorGUILayout.Space(); GUILayout.Label("FRESNEL", EditorStyles.miniBoldLabel); l.reflectivityAt0 = EditorGUILayout.Slider(" Reflectivity (0 degrees)", l.reflectivityAt0, 0f, 1f); l.reflectivityAt90 = EditorGUILayout.Slider(" Reflectivity (90 degrees)", l.reflectivityAt90, 0f, 1f); l.reflectivityFalloff = EditorGUILayout.Slider(" Falloff", l.reflectivityFalloff, 0f, 20.0f); } EditorGUI.indentLevel--; EditorGUILayout.Space(); GUILayout.Label("SPECULAR", EditorStyles.miniBoldLabel); EditorGUI.indentLevel++; l.specularIntensity = EditorGUILayout.Slider("Specular 1", l.specularIntensity, 0f, 10f); if (l.specularIntensity > 1e-6) { EditorGUI.indentLevel++; l.specularShininess = EditorGUILayout.Slider(" Roughness", l.specularShininess, 0f, 1f); EditorGUI.indentLevel--; } l.specularIntensity2 = EditorGUILayout.Slider("Specular 2", l.specularIntensity2, 0f, 10f); if (l.specularIntensity2 > 1e-6) { EditorGUI.indentLevel++; l.specularShininess2 = EditorGUILayout.Slider(" Roughness", l.specularShininess2, 0f, 1f); EditorGUI.indentLevel--; } EditorGUI.indentLevel--; EditorGUILayout.Space(); GUILayout.Label("MISC", EditorStyles.miniBoldLabel); GUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Lookup Texture", "MiniPopup"); l.lookupTextureWidth = EditorGUILayout.IntPopup(l.lookupTextureWidth, kTextureSizes, kTextureSizesValues, GUILayout.MinWidth(40)); GUILayout.Label("x"); l.lookupTextureHeight = EditorGUILayout.IntPopup(l.lookupTextureHeight, kTextureSizes, kTextureSizesValues, GUILayout.MinWidth(40)); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); if (GUI.changed) { EditorUtility.SetDirty(l); Undo.RegisterUndo(l, "SSSSkin Params Change"); baked = false; } // preview GUILayout.BeginHorizontal(); lowResPreview = EditorGUILayout.Toggle("Low Res Preview", lowResPreview); GUILayout.FlexibleSpace(); if (GUILayout.Button(previewRGB? "RGB": "Alpha", "MiniButton", GUILayout.MinWidth(38))) { previewRGB = !previewRGB; } GUILayout.EndHorizontal(); if (lowResPreview && !baked) { GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Bake", GUILayout.MinWidth(64))) { l.Bake(); baked = true; } GUILayout.EndHorizontal(); } if (GUI.changed || !l.lookupTexture) { if (lowResPreview) { if (!baked) { l.Preview(); } } else { l.Bake(); } PersistLookupTexture(); } if (!HasSupportedMaterial(l.GetComponent <Renderer>())) { if (GUILayout.Button("Setup shaders (will modify materials)!!!")) { SetupMaterials(l.GetComponent <Renderer>()); } } Rect r = GUILayoutUtility.GetAspectRect(1.0f); r.x += kTexturePreviewBorder; r.y += kTexturePreviewBorder; r.width -= kTexturePreviewBorder * 2; r.height -= kTexturePreviewBorder * 2; if (previewRGB) { EditorGUI.DrawPreviewTexture(r, l.lookupTexture); } else { EditorGUI.DrawTextureAlpha(r, l.lookupTexture); } // persist lookup-texture on Undo if (Event.current.type == EventType.ValidateCommand) { switch (Event.current.commandName) { case "UndoRedoPerformed": { l.Bake(); PersistLookupTexture(); baked = false; } break; } } }
void RenderSSS(Camera targetCamera) { if (scattering < ScatteringModel.TwoLayersCheap) { foreach (Renderer r in skinnedMeshRenderers) { if (r) { SetupPass(r, 0); // fallback } } return; } if (frameCount == Time.frameCount) { frameCount = Time.frameCount; return; } frameCount = Time.frameCount; if (insideSSSPass) { return; } insideSSSPass = true; // create throwaway camera to render skin into Camera cam = GetSSSCamera(targetCamera); RenderTexture tmpTargetRt = cam.targetTexture; Vector3 eye = targetCamera.transform.position; if (cam && skinLayers.value != 0) { // assign 1st pass shader and render: foreach (Renderer r in skinnedMeshRenderers) { if (r && !UseFallback(r, eye)) { SetupPass(r, 1, tmpTargetRt); } else { r.enabled = false; } } RenderTexture lastActiveRT = RenderTexture.active; if (lastActiveRT && Application.isPlaying) { lastActiveRT.DiscardContents(); } tmpTargetRt.DiscardContents(); RenderTexture tmp = RenderTexture.GetTemporary(tmpTargetRt.width, tmpTargetRt.height, 0, rtFormat); RenderTexture tmp2 = null; // all skinned objects are rendered for the first time here cam.cullingMask = skinLayers; cam.Render(); if (skinPostPassMaterial) { // do skin posting // TODO: investigate more optimizations such as stenciling etc skinPostPassMaterial.SetFloat("_BlurWidthScale", blurOffset); // cache viewspace quads Rect[] rects = new Rect[skinnedMeshRenderers.Length]; SkinShadingLookupTexture[] skins = new SkinShadingLookupTexture[skinnedMeshRenderers.Length]; int skinCount = 0; foreach (Renderer r in skinnedMeshRenderers) { if (r) { rects[skinCount] = ViewspaceQuad(r, cam); if (!UseFallback(r, eye)) { skins[skinCount] = r.GetComponent <SkinShadingLookupTexture>(); } else { skins[skinCount] = null; } skinCount++; } } float fadeWithDistance = 1.0f; { RenderTexture.active = tmp; for (int i = 0; i < skinCount; ++i) { var c = skins[i]; if (c && !c.isEyes) { c.SetParameters(skinPostPassMaterial); fadeWithDistance = c.GetDistanceFade(targetCamera); skinPostPassMaterial.SetFloat("_BlurWidthScale", c.sssssBlurDistance * blurOffset * fadeWithDistance); DrawRect(tmpTargetRt, skinPostPassMaterial, 0, rects[i]); } } tmpTargetRt.DiscardContents(); RenderTexture.active = tmpTargetRt; for (int i = 0; i < skinCount; ++i) { var c = skins[i]; if (c && !c.isEyes) { c.SetParameters(skinPostPassMaterial); fadeWithDistance = c.GetDistanceFade(targetCamera); skinPostPassMaterial.SetFloat("_BlurWidthScale", c.sssssBlurDistance * blurOffset * fadeWithDistance); DrawRect(tmp, skinPostPassMaterial, 1, rects[i]); } } } } RenderTexture.active = lastActiveRT; if (tmp) { RenderTexture.ReleaseTemporary(tmp); } if (tmp2) { RenderTexture.ReleaseTemporary(tmp2); } // reset stuff and continue, now we can easily sample from skin 1st pass // after this, the rendering of the std camera will happen and all skinned objects will be rendered a 2nd time foreach (Renderer r in skinnedMeshRenderers) { if (r) { if (UseFallback(r, eye)) { r.enabled = true; SetupPass(r, 2, null); } else { SetupPass(r, 2, tmpTargetRt); } } } } insideSSSPass = false; }
public void SetupPassFullButSlow(Renderer r, int pass, RenderTexture sssRT = null, bool forceMaterial = false) { SkinShadingLookupTexture c = r.GetComponent <SkinShadingLookupTexture>(); foreach (Material m in r.sharedMaterials) { if (SupportedMaterial(m) || forceMaterial) { if (useKeywordShader) { m.shader = skinKeywordShader; m.shaderKeywords = defaultShaderKeywords; // SKIN_PASS_1 SKIN_PASS_1_EYES SKIN_PASS_2 SKIN_PASS_2_EYES SKIN_FALLBACK switch (pass) { case 0: m.shaderKeywords = new string[] { "SKIN_FALLBACK" }; if (c) { c.SetParameters(m); } break; case 1: if (c && c.isEyes) { m.shaderKeywords = new string[] { "SKIN_PASS_1_EYES" } } ; else { m.shaderKeywords = new string[] { "SKIN_PASS_1" } }; break; case 2: if (c && c.isEyes) { m.shaderKeywords = new string[] { "SKIN_PASS_2_EYES" } } ; else { m.shaderKeywords = new string[] { "SKIN_PASS_2" } }; m.SetTexture("_SkinScreenspaceLookup", sssRT); if (c) { c.SetParameters(m); } break; } } else { m.shaderKeywords = defaultShaderKeywords; if (pass == 0) { m.shader = skinFBShader; if (c) { c.SetParameters(m); } } else if (pass == 1) { if (c && c.isEyes) { m.shader = skin1stPassEyesShader; } else { m.shader = skin1stPassShader; } } else if (pass == 2) { m.shader = skin2ndPassLQShader; if (c && c.isEyes) { m.shader = skin2ndPassLQEyesShader; } // set diffusion texture m.SetTexture("_SkinScreenspaceLookup", sssRT); if (c) { c.SetParameters(m); } } } } } }
public void SetupPass(Renderer r, int pass, RenderTexture sssRT = null, bool forceMaterial = false) { SkinShadingLookupTexture c = r.GetComponent <SkinShadingLookupTexture>(); if (!Application.isPlaying || !c) { SetupPassFullButSlow(r, pass, sssRT, forceMaterial); return; } c.SetupMaterials(this); Material[] mats = null; if (useKeywordShader) { mats = c.skinKeywordMaterials; foreach (var m in mats) { // SKIN_PASS_1 SKIN_PASS_1_EYES SKIN_PASS_2 SKIN_PASS_2_EYES SKIN_FALLBACK m.shaderKeywords = defaultShaderKeywords; switch (pass) { case 0: m.shaderKeywords = new string[] { "SKIN_FALLBACK" }; break; case 1: if (c.isEyes) { m.shaderKeywords = new string[] { "SKIN_PASS_1_EYES" } } ; else { m.shaderKeywords = new string[] { "SKIN_PASS_1" } }; break; case 2: if (c.isEyes) { m.shaderKeywords = new string[] { "SKIN_PASS_2_EYES" } } ; else { m.shaderKeywords = new string[] { "SKIN_PASS_2" } }; m.SetTexture("_SkinScreenspaceLookup", sssRT); break; } } } else { if (pass == 0) { mats = c.skinFallbackMaterials; } else if (pass == 1) { mats = c.skin1stPassMaterials; } else if (pass == 2) { mats = c.skin2ndPassMaterials; foreach (var m in mats) { m.SetTexture("_SkinScreenspaceLookup", sssRT); } } } r.materials = mats; }