【Shader】实验06——后处理实现色散效果

上次写完那坨固态水之后,就想试着写一个比较节省性能比较省的一片水试试,然鹅,天有不测风云,人有旦夕祸福,我不幸地沉迷于空洞骑士,每天都沉迷于打boss与跑尸乐此不疲……

我自己都觉得好悔恨,好罪恶,怎么能天天打游戏呢,所以今天先把这个简单的后处理色散效果写了,简单水那个也快写好了,真的快写好了……

色散是太阳光沿着一定角度射入空气中的水滴所引起的比较复杂的由折射和反射造成的一种现象,像这样:

色散现象

本质是因为不同波长的光折射率不同,就从原本混合的单色光被分成了多种颜色。

但今天要做的不是这个……是这个:

色散效果

这是一种风格化效果,貌似属于故障艺术的一种,也就是以前电视、电脑出了问题,就变成了这幅模样,逐渐也演变成了一种艺术性风格。

用后处理实现可以说是十分简单了,shader里片元着色器的输出颜色的rgb值是分别对rgb通道的_MainTex进行采样,并对采样坐标做不同的偏移。还可以加上时间参数做出动画。

这真的是个非常的简单的效果惹:

色散动画效果

C#脚本

using UnityEngine;

[ExecuteInEditMode]
public class ColorDispersion : PostEffectsBase
{
    public Shader shader;
    private Material _material;
    private Material Material
    {
        get
        {
            if (_material == null)
                _material = CheckShaderAndMaterial(shader, _material);
            return _material;
        }
    }

    [Range(0,0.01f)]
    public float scale = 0;

    public float speed = 5;

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (Material != null)
        {
            Material.SetFloat("_Scale", scale);
            Material.SetFloat("_Speed", speed);

            Graphics.Blit(source, destination,Material);
        }
        else
        {
            Graphics.Blit(source, destination);
            Debug.Log("Material == null !");
        }
    }

}

Shader

Shader "MyShaderTest/8_ColorDispersion"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}
	}
		SubShader
	{
		Cull Off ZWrite Off ZTest Always

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			v2f vert(appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = v.uv;
				return o;
			}

			sampler2D _MainTex;
			float _Scale;
			float _Speed;

			fixed4 frag(v2f i) : SV_Target
			{
				fixed3 col = fixed3(0,0,0);

				fixed scale = _Scale * sin(_Time.y * _Speed); 

				scale = saturate(scale);

				half2 uv_0 = half2(i.uv.x - scale,i.uv.y);
				half2 uv_1 = half2(i.uv.x + scale, i.uv.y);

				col.r = tex2D(_MainTex, uv_0).r;
				col.g = tex2D(_MainTex, i.uv).g;
				col.b = tex2D(_MainTex, uv_1).b;

				return fixed4(col,1);
			}
			ENDCG
		}
	}
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
A:要使用Shader实现通信效果,可以在osg::ShaderComposer中构建Shader代码,通过使用Uniform和varying变量进行数据传递,具体代码实现如下所示: ``` osg::ShaderComposer shaderComposer; // 创建顶点Shader osg::Shader* vertShader = new osg::Shader(osg::Shader::VERTEX, R"( #version 430 layout(location = 0) in vec3 vertex; layout(location = 1) in vec3 normal; out vec3 normal_fs; uniform mat4 mvpc; uniform mat4 mv; uniform vec3 light_pos; void main() { vec3 light_dir = normalize(light_pos - vec3(mv * vec4(vertex, 1.0))); float diffuse = dot(light_dir, normalize(normal)); gl_Position = mvpc * vec4(vertex, 1.0); normal_fs = normal; } )"); shaderComposer.setDefaultVertexShader(vertShader); // 创建片段Shader osg::Shader* fragShader = new osg::Shader(osg::Shader::FRAGMENT, R"( #version 430 in vec3 normal_fs; out vec4 frag_color; uniform vec4 diffuse_color; void main() { frag_color = diffuse_color; } )"); shaderComposer.setDefaultFragmentShader(fragShader); // 设置Uniform变量 shaderComposer.addUniform("mvpc", osg::Uniform::FLOAT_MAT4); shaderComposer.addUniform("mv", osg::Uniform::FLOAT_MAT4); osg::Vec3 lightPos(0.0f, 0.0f, 10.0f); shaderComposer.addUniform("light_pos", lightPos); osg::Vec4 diffuseColor(1.0f, 0.0f, 0.0f, 1.0f); shaderComposer.addUniform("diffuse_color", diffuseColor); // 设置varying变量 shaderComposer.addVarying("normal_fs"); // 创建程序管线 osg::Program* program = shaderComposer.createShaderProgram(); program->setName("ShaderProgram"); ``` 在上述代码中,顶点Shader代码中使用了uniform变量mvpc、mv、light_pos,分别表示MVP矩阵、MV矩阵、光源位置;使用varying变量normal_fs将normal向片段Shader中传递。 片段Shader代码中使用了uniform变量diffuse_color表示物体颜色。 最后,使用osg::Program和osg::StateSet将Shader设置到osg::Geode中即可在场景中看到通信效果

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值