MasterGH Опубликовано 17 февраля, 2015 Поделиться Опубликовано 17 февраля, 2015 Задали на работе написать пост эффект. Кому интересно, могут помочь. Берем каждый пиксель за кадр рендренига и анализируем его яркость - 30% темных по яркости делаем черными- 30% - сиреневым цветом- след. 40% - белыми Если это делать CPU, то это очень медленно. Поэтому надо через шейдер писельный. Вот пример, когда цвета подбираются по функции distance(), а не по яркости Shader "AlpacaSound/RetroPixel3"{ Properties { _Br0 ("Brightness Range 0", Range (0, 0.3)) = 0.3 _Br1 ("Brightness Range 1", Range (0.3, 0.6)) = 0.3 _Br2 ("Brightness Range 2", Range (0.6, 1.0)) = 0.6 _Color0 ("Color 0", Color) = (0.00, 0.00, 0.00, 1.0) _Color1 ("Color 1", Color) = (0.14, 0.14, 0.14, 1.0) _Color2 ("Color 2", Color) = (0.29, 0.29, 0.29, 1.0) _MainTex ("", 2D) = "white" {} } SubShader { Lighting Off ZTest Always Cull Off ZWrite Off Fog { Mode Off } Pass { CGPROGRAM #pragma exclude_renderers flash #pragma vertex vert_img #pragma fragment frag #pragma fragmentoption ARB_precision_hint_fastest #include "UnityCG.cginc" uniform fixed4 _Color0; uniform fixed4 _Color1; uniform fixed4 _Color2; uniform sampler2D _MainTex; fixed4 frag (v2f_img i) : COLOR { fixed3 original = tex2D (_MainTex, i.uv).rgb; fixed dist0 = distance (original, _Color0.rgb); fixed dist1 = distance (original, _Color1.rgb); fixed dist2 = distance (original, _Color2.rgb); fixed4 col = fixed4 (0,0,0,0); fixed dist = 10.0; if (dist0 < dist) { dist = dist0; col = _Color0; } if (dist1 < dist) { dist = dist1; col = _Color1; } if (dist2 < dist) { dist = dist2; col = _Color2; } return col; } ENDCG } } FallBack "Diffuse"}using UnityEngine;using System.Collections;namespace Retro //Pixel{ [ExecuteInEditMode] [RequireComponent (typeof(Camera))] [AddComponentMenu("Image Effects/Custom/Retro Pixel")] public class RetroPixel : MonoBehaviour { public bool isUseOriginalResolution = true; public static readonly int MAX_NUM_COLORS = 8; public int horizontalResolution = 160; public int verticalResolution = 200; public int numColors = MAX_NUM_COLORS; int oldNumColors = 0; public Color color0 = Color.black; public Color color1 = Color.white; public Color color2 = new Color32(255, 75, 75, 255); public Color color3 = new Color32(255, 186, 19, 255); public Color color4 = new Color32(234, 233, 0, 255); public Color color5 = new Color32(132, 207, 69, 255); public Color color6 = new Color32(0, 165, 202, 255); public Color color7 = new Color32(192, 106, 194, 255); Shader[] shaders = new Shader[MAX_NUM_COLORS]; Material m_material; Material material { get { if (m_material == null) { for (int i = 1; i < MAX_NUM_COLORS; ++i) { string shaderName = "AlpacaSound/RetroPixel" + (i+1); Shader shader = Shader.Find (shaderName); if (shader == null) { Debug.LogError ("Shader \'" + shaderName + "\' not found. Was it deleted?"); enabled = false; return null; } shaders[i] = shader; } m_material = new Material (shaders[1]); m_material.hideFlags = HideFlags.DontSave; } return m_material; } } void Start () { if(isUseOriginalResolution){ horizontalResolution = Screen.width; verticalResolution = Screen.height; } if (!SystemInfo.supportsImageEffects) { enabled = false; return; } } public void OnRenderImage (RenderTexture src, RenderTexture dest) { horizontalResolution = Mathf.Clamp(horizontalResolution, 1, 2048); verticalResolution = Mathf.Clamp(verticalResolution, 1, 2048); numColors = Mathf.Clamp(numColors, 2, 8); if (material) { if (oldNumColors != numColors) { material.shader = shaders[numColors-1]; } material.SetColor ("_Color0", color0); material.SetColor ("_Color1", color1); if (numColors > 2) material.SetColor ("_Color2", color2); if (numColors > 3) material.SetColor ("_Color3", color3); if (numColors > 4) material.SetColor ("_Color4", color4); if (numColors > 5) material.SetColor ("_Color5", color5); if (numColors > 6) material.SetColor ("_Color6", color6); if (numColors > 7) material.SetColor ("_Color7", color7); RenderTexture scaled = RenderTexture.GetTemporary (horizontalResolution, verticalResolution); scaled.filterMode = FilterMode.Point; Graphics.Blit (src, scaled, material); Graphics.Blit (scaled, dest); RenderTexture.ReleaseTemporary (scaled); } else { Graphics.Blit (src, dest); } } void OnDisable () { if (m_material) { Material.DestroyImmediate (m_material); } } }} Я сегодня колупался с шейдерами, пока не решил. Вот такой интересной штукой я занимаюсь на работе. Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 17 февраля, 2015 Автор Поделиться Опубликовано 17 февраля, 2015 Вроде так Вот увлечешься этими документациями на официальном сайте и подразделами, и уйдешь в такие дебри, что потом и не заметишь как уже второй час ночи и пора бы подкрепиться. Интересно, что завтра начальство скажет по результату. Еще надо бы пару ползунков в гуи с тысячными долями прилепить, ладно днем прикручу.Shader "AlpacaSound/RetroPixel3"{ Properties { _Br0 ("Brightness Range 0", Range (0, 1.0)) = 0.3 _Br1 ("Brightness Range 1", Range (0.0, 1.0)) = 0.6 _Color0 ("Color 0", Color) = (0.00, 0.00, 0.00, 1.0) _Color1 ("Color 1", Color) = (0.14, 0.14, 0.14, 1.0) _Color2 ("Color 2", Color) = (0.29, 0.29, 0.29, 1.0) _MainTex ("", 2D) = "white" {} } SubShader { Lighting Off ZTest Always Cull Off ZWrite Off Fog { Mode Off } Pass { CGPROGRAM #pragma exclude_renderers flash #pragma vertex vert_img #pragma fragment frag #pragma fragmentoption ARB_precision_hint_fastest #include "UnityCG.cginc" uniform fixed4 _Color0; uniform fixed4 _Color1; uniform fixed4 _Color2; uniform fixed _Br0; uniform fixed _Br1; uniform sampler2D _MainTex; fixed4 frag (v2f_img i) : COLOR { fixed3 original = tex2D (_MainTex, i.uv).rgb; fixed brightest = (original.r + original.g + original.b)/3.0; fixed4 col = fixed4 (0,0,0,0); if (brightest < _Br0) col = _Color0; else if (brightest > _Br0 && brightest < _Br1) col = _Color1; else if (brightest > _Br1) col = _Color2; return col; } ENDCG } } FallBack "Diffuse"} Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 18 февраля, 2015 Поделиться Опубликовано 18 февраля, 2015 А зачем, ZTest Always? Разве шейдер выполняется не на прирендернный в 2д кадр, готовый к выводу на экран? Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 18 февраля, 2015 Автор Поделиться Опубликовано 18 февраля, 2015 Я не знаю деталей, но во всех официальных шейдрерах постэффектов есть установки//...Subshader {Pass { ZTest Always Cull Off ZWrite Off Fog { Mode off }//...}//...Официального объяснения я не нашел. На форумах пишут, что это нужно для работы Graphics.Blit, которая работает для пост эффекта в следующей функции public void OnRenderImage (RenderTexture src, RenderTexture dest){//... RenderTexture scaled = RenderTexture.GetTemporary (horizontalResolution, verticalResolution); scaled.filterMode = FilterMode.Point; Graphics.Blit (src, scaled, material); Graphics.Blit (scaled, dest); RenderTexture.ReleaseTemporary (scaled);}ZTest может быть установлен вLess | Greater | LEqual | GEqual | Equal | NotEqual | AlwaysZTest позволяет рисовать такие примеры:Для интересующихся шейдеры примеров можно найти здесь Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 18 февраля, 2015 Поделиться Опубликовано 18 февраля, 2015 Именно. Потому я и спросил, зачем включать глубину для шейдера, который применяется к прирендеренному в 2д кадру, готовому к выводу на экран. Я так понял, что постэффект в твоем посте должен накладываться именно на готовый кадр, именно готовый к выводу на экран, то есть, не 3д кадр, а уже готовую 2д картинку. Если так, то работа с глубиной шейдеру нафиг не сдалась, ведь ее попросту нет, так как готовый к выводу на экран кадр - это прогсто растровая картинка, не имеющая третьего измерения. Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 18 февраля, 2015 Автор Поделиться Опубликовано 18 февраля, 2015 Я понял. Те, кто писали на форумах, если не использовать проверку глубины буфера, то возникает черный эркан. Возможно это имеет значения на разных девайсах на множестве камер или еще что-нибудь... В официальных шейдерах потсэффектов пишут по дефолту. ZTest Always Cull Off ZWrite Off Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 18 февраля, 2015 Поделиться Опубликовано 18 февраля, 2015 если не использовать проверку глубины буфера, то возникает черный эркан Интересно. Надо будет затестить. Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 18 февраля, 2015 Автор Поделиться Опубликовано 18 февраля, 2015 Я кажись понял. Если не писать буфер глубины, то он задается по умолчанию для всех типов шейдеров с параметром LEqual Поэтому надо прописывать по умолчанию совсем другое значение или вообще его не прописывать.------------- Тема с проблемой, не знаю зачем я её тут привожу, я не поленился и нашел её снова Thanks very much, guys. The hint with the Greyscale Effect helped me fix my problem, which was very similar to 0xDEADCODE's. My blit with my custom material/shader returned black. My shader was already a fragment shader, but I forgot one more thing:Code (csharp):ZTest Always Cull Off ZWrite OffFog { Mode off }Adding these lines (within Pass{}) made mine work (mostly because of the ZTest Always; I guess the ZTest just failed for every pixel earlier). Hope I can help some other people with the same issue.Пост эффекты для рендерер текстуры, а они все через эту специальную текстуру идут скорее всего со своей спецификой для кода движка Unity3d.Кто-то писал даже, что это чуть ли не баг и надеялись, что этот баг поскорее бы исправили, чтобы в шейдерах не писать ZTest. Я бы не стал советовать это тестировать, т.к. мне это не нужно. Задача выполнена. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения