Unity中的ShaderToy

文章目录

  • 前言
  • 一、ShaderToy网站
  • 二、ShaderToy基本框架
    • 1、我们可以在ShaderToy网站中,这样看用到的GLSL文档
    • 2、void mainImage 是我们的程序入口,类似于片断着色器
    • 3、fragColor作为输出变量,为屏幕每一像素的颜色,alpha一般赋值为 1
    • 4、fragCoord作为输入变量
  • 三、怎么把ShaderToy的Shader转化为Unity中的Shader
    • 1、使用到的代码基础模板
    • 2、逐条把ShaderToy代码转化到Unity中Shader
  • 三、最终效果


前言

我们在之前的文章中,学习了很多的Shadar知识。但是,我们没有自己实现一些奇特的效果。而ShaderToy是一个国外的网站,上面刚好有很多Shader大神实现的效果,提供给我们借鉴。我们在这篇文章中了解一下ShaderToy。


一、ShaderToy网站

  • ShaderToy

我们可以借鉴这个网站中的 视觉灵感 和 算法 来提升自我

  • 我们来看看iq大神的作品:

ShaderToy本质使用的是GLSL,我们可以查看OpenGL的官方文档来学习


二、ShaderToy基本框架

1、我们可以在ShaderToy网站中,这样看用到的GLSL文档

Unity中的ShaderToy_第1张图片

2、void mainImage 是我们的程序入口,类似于片断着色器

Unity中的ShaderToy_第2张图片

3、fragColor作为输出变量,为屏幕每一像素的颜色,alpha一般赋值为 1

Unity中的ShaderToy_第3张图片

Unity中的ShaderToy_第4张图片

4、fragCoord作为输入变量


三、怎么把ShaderToy的Shader转化为Unity中的Shader

因为ShaderToy的操作是类似于,直接对屏幕上的图像做处理并且覆盖。
处理起来和Unity中的后处理很像,所以我们可以直接使用后处理脚本框架来实现

  • Unity中后处理简介

  • Unity中后处理 脚本 和 Shader

1、使用到的代码基础模板

因为ShaderToy是直接对屏幕像素进行覆盖修改。
所以,我们的功能主要在Shader的片元着色器中完成,并且不需要外部传入属性

  • C#:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//后处理脚本
[ExecuteInEditMode]
public class P2_8 : MonoBehaviour
{
    public Shader PostProcessingShader;
    private Material mat;
    public Material Mat
    {
        get
        {
            if (PostProcessingShader == null)
            {
                Debug.LogError("没有赋予Shader");
                return null;
            }
            if (!PostProcessingShader.isSupported)
            {
                Debug.LogError("当前Shader不支持");
                return null;
            }
            //如果材质没有创建,则根据Shader创建材质,并给成员变量赋值存储
            if (mat == null)
            {
                Material _newMaterial = new Material(PostProcessingShader);
                _newMaterial.hideFlags = HideFlags.HideAndDontSave;
                mat = _newMaterial;
                return _newMaterial;
            }
            return mat;
        }
    }

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        Graphics.Blit(source,destination,Mat);
    }
}

  • Shader:
Shader "MyShader/P2_8"
{
    SubShader
    {
        // No culling or depth
        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;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return 1;
            }
            ENDCG
        }
    }
}

2、逐条把ShaderToy代码转化到Unity中Shader

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;

    // Time varying pixel color
    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));

    // Output to screen
    fragColor = vec4(col,1.0);
}
  • i 开头的变量都是着色器的内部输入变量

  • fragCoord:输入图像的像素 所在屏幕中的位置 x(宽)、y(高)

  • iResolution.xy : x代表屏幕宽度,y代表屏幕高度

  • fragCoord/iResolution.xy :得到一个归一化后(0,1)的值
    等效: i.uv

  • iTime:是一个一维变量,单位为秒
    等效:_Time.y

  • fragColor:输出变量
    等效:return col

转化后的片元着色器:

fixed4 frag (v2f i) : SV_Target
{
	//vec2 uv = fragCoord/iResolution.xy;
	//i.uv
	//vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
	float3 col = 0.5 + 0.5*cos(_Time.y + i.uv.xyx + fixed3(0,2,4));
	//fragColor = vec4(col,1.0);
	return fixed4(col,1);
}

三、最终效果

你可能感兴趣的:(Unity,unity,游戏引擎)