Страница 1 из 1

Поправить MotionBlur

СообщениеДобавлено: 15 июн 2010, 13:34
RefractoR
Нашел на оф форуме неплохой шейдер размытия движения, но как сказал сам создатель шейдера: там проблемы с вычислениями матриц. Я переписал скрипт управления данным шейдером на сишарп, переписал вычисления матриц, но все же шейдер работает не так, как хочется - размытие происходит только при движении объекта вверх / вниз и при поворотах (при поворотах особенно сильное размытие).

Переписанный скрипт управления:
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;

[AddComponentMenu("Image Effects/CameraMotionBlur")]
[RequireComponent (typeof (Camera))]

public class MotionBlurComponent : MonoBehaviour {
       
        public Shader blurShader;
        public float strength = 12.0f;
        public Transform target;
       
        Material m_CompositeMaterial;
       
        Material GetCompositeMaterial() {
               
                if (!m_CompositeMaterial) {
                        m_CompositeMaterial = new Material(blurShader);
                        m_CompositeMaterial.hideFlags = HideFlags.HideAndDontSave;
                }
                return m_CompositeMaterial;
               
        }
       
        void OnDisable () {
               
                DestroyImmediate(m_CompositeMaterial);
               
        }
       
        void OnPreCull () {
               
                Matrix4x4 Iview = target.localToWorldMatrix * transform.worldToLocalMatrix * camera.projectionMatrix;
                Shader.SetGlobalMatrix("_Myview", Iview.inverse);
               
        }
       
        void OnRenderImage (RenderTexture source, RenderTexture destination) {
               
                Material compositeMat = GetCompositeMaterial();
                compositeMat.SetFloat("_Strength", strength);
                ImageEffects.BlitWithMaterial(compositeMat, source, destination);
               
        }
       
        void OnPostRender () {
               
                StartCoroutine("RenderLate");
               
        }
       
        IEnumerator RenderLate () {
               
                yield return new WaitForEndOfFrame();
                Matrix4x4 Iviewprev = target.localToWorldMatrix * transform.worldToLocalMatrix * camera.projectionMatrix;
                Shader.SetGlobalMatrix("_Myviewprev", Iviewprev);
               
        }

}
 


Оригинальный скрипт управления:
Синтаксис:
Используется javascript
#pragma strict

@script ExecuteInEditMode
@script AddComponentMenu("Image Effects/CameraMBlur")
@script RequireComponent(Camera)

var compositeShader : Shader;
var Strength = 13.0;
private var m_CompositeMaterial : Material;
 
private function GetCompositeMaterial() : Material {
        if (m_CompositeMaterial == null) {
                m_CompositeMaterial = new Material( compositeShader );
                m_CompositeMaterial.hideFlags = HideFlags.HideAndDontSave;
        }
        return m_CompositeMaterial;
}
function OnDisable() { 
        DestroyImmediate (m_CompositeMaterial);
}
function OnPreCull()
{
        var Iview=(camera.worldToCameraMatrix.inverse * camera.projectionMatrix);
        Shader.SetGlobalMatrix("_Myview", Iview.inverse);
}

// Called by the camera to apply the image effect
function OnRenderImage (source : RenderTexture, destination : RenderTexture) : void
{
        var compositeMat = GetCompositeMaterial();
        compositeMat.SetFloat("_Strength", Strength);

        ImageEffects.BlitWithMaterial(compositeMat, source, destination);

}

function OnPostRender()
{
renderlate();
}


function renderlate ()
{

yield WaitForEndOfFrame();
var Iviewprev=(camera.worldToCameraMatrix.inverse * camera.projectionMatrix);
Shader.SetGlobalMatrix("_Myviewprev", Iviewprev);
}
 


Сам шейдер:
Синтаксис:
Используется glsl
Shader "CameraMBlur" {
Properties {
        _MainTex ("", RECT) = "white" {}
        _Strength ("Strength", Range (1, 30)) = 15.0
}

SubShader {
        Pass {
                ZTest Always Cull off ZWrite Off Fog { Mode off }

CGPROGRAM
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"

uniform samplerRECT _MainTex;

struct v2f {
        float4 pos      : POSITION;
        float2 uv       : TEXCOORD0;

};

v2f vert (appdata_base v)
{

        v2f o;
        o.pos = mul (glstate.matrix.mvp, v.vertex);
        o.uv.xy=v.texcoord;
        return o;
}

uniform float4x4 _Myview;
uniform float4x4 _Myviewprev;
uniform float _Strength;

half4 frag (v2f i) : COLOR
{
float2 Texcoord =i.uv;
  // Get the depth buffer value at this pixel.  
  float zOverW = 1;  
// H is the viewport position at this pixel in the range -1 to 1.  
float4 H = float4(Texcoord.x * 2 - 1, (1 - Texcoord.y) * 2 - 1,zOverW, 1);  
// Transform by the view-projection inverse.  
   float4 D = mul(H, _Myview);  
// Divide by w to get the world position.  
   float4 worldPos = D / D.w;  
     // Current viewport position  
   float4 currentPos = H;  
// Use the world position, and transform by the previous view-  
   // projection matrix.  
   float4 previousPos = mul(worldPos, _Myviewprev);  
// Convert to nonhomogeneous points [-1,1] by dividing by w.  
previousPos /= previousPos.w;  
// Use this frame's position and last frame's to compute the pixel  
   // velocity.  
   float2 velocity = (currentPos - previousPos)/_Strength;  
   
    // Get the initial color at this pixel.  
   float4 color = texRECT(_MainTex, Texcoord);  
Texcoord += velocity;  
for(int i = 1; i < 12; ++i, Texcoord += velocity)  
{  
  // Sample the color buffer along the velocity vector.  
   float4 currentColor = texRECT(_MainTex, Texcoord);  
  // Add the current color to our color sum.  
  color += currentColor;  

}  
// Average all of the samples to get the final blur color.  
   float4 finalColor = color / 12;  
       
        return finalColor;
}
ENDCG
        }
}

Fallback off

}
 


Еще раз напомню, что внимание, судя по всему, надо обратить на вычисления матриц.
Статья, по которой был написан шейдер

Re: Поправить MotionBlur

СообщениеДобавлено: 15 июн 2010, 13:40
Neodrop
А чем он лучше родного мошнблюра? :-?

Re: Поправить MotionBlur

СообщениеДобавлено: 15 июн 2010, 13:43
RefractoR
Родной примитивен. Данный шейдер дает более натуральный результат

Re: Поправить MotionBlur

СообщениеДобавлено: 15 июн 2010, 13:46
Neodrop
Что то я сильно сомневаюсь..
Нет ли картинок для сравнения "примитивного" и "продвинутого" вариантов? :-?

Re: Поправить MotionBlur

СообщениеДобавлено: 15 июн 2010, 13:49
RefractoR
Я говорю примерно о таком размытии

Re: Поправить MotionBlur

СообщениеДобавлено: 15 июн 2010, 15:21
Kann
по моему это PixelMotionBlur сомнительная выгода.....
http://http.developer.nvidia.com/GPUGem ... _ch27.html

Re: Поправить MotionBlur

СообщениеДобавлено: 15 июн 2010, 15:35
RefractoR
Возможно, но я не умею писать шейдеры, а других готовых не находил (конечно, можно использовать RadialBlur, который прилично выглядит, но он только в одном направлении работает)...

Re: Поправить MotionBlur

СообщениеДобавлено: 15 июн 2010, 22:38
Neodrop
На мой взгляд это вообще излишества. И тратить на них время и силы уместно только тогда, когда вся программа уже написана. Да и то, блюр почти всегда излишество.
Но, дело ваше, конечно.

Re: Поправить MotionBlur

СообщениеДобавлено: 18 янв 2013, 05:34
LightWorld
Проблема решается увлечением значение Strength до 200.