11
8

More than 5 years have passed since last update.

【GLSL】UnityのInspector上でレイマーチングはできる

Last updated at Posted at 2016-02-17

※この記事で使っているUnityのバージョンは Unity5.2.1p3 です。

image

C#コード

以下のスクリプトを作成して適当なオブジェクトにアタッチ

NewBehaviourScript.cs
using UnityEngine;
using System.Collections;

public class NewBehaviourScript : MonoBehaviour
{

}

以下のスクリプトを作成してEditorフォルダ内へ入れる

NewBehaviourScriptEditor.cs
using UnityEngine;
using UnityEditor;
using System.Collections;

[CustomEditor(typeof(NewBehaviourScript))]
public class NewBehaviourScriptEditor : Editor
{
  private Material material = null;
  public override bool HasPreviewGUI()
  {
    return true;
  }

  public override GUIContent GetPreviewTitle()
  {
    return new GUIContent("ほげ");
  }

  public override void OnPreviewGUI(Rect r, GUIStyle background)
  {
    if (material == null)
    {
      Shader shader = Resources.Load<Shader>("Shader/RayMarch");
      this.material = new Material(shader);
    }

    base.OnPreviewGUI(r, background);
    Graphics.DrawTexture(r, Texture2D.whiteTexture, this.material);
    Repaint();

  }

}

シェーダーコード

レイマーチングは 全能感UP! GLSLで進めレイマーチング を参考にしました.
光と法線の内積をとって影をつけています.

ファイルパスがAssets/Resources/Shader/RayMarch.shaderとなるように
配置します.

RayMarch.shader
Shader "Unlit/RayMarch"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
    }

        SubShader
    {
        Tags{ "RenderType" = "Opaque" }

        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;
        float4 screenPos : TEXCOORD1;
    };

    sampler2D _MainTex;
    float4 _MainTex_ST;

    v2f vert(appdata v)
    {
        v2f o;
        o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
        o.uv = TRANSFORM_TEX(v.uv, _MainTex);
        return o;
    }

    float distanceFunc(float3 p) {
        float sphereSize = 0.1;
        float3 spherePos = float3(0.0, 0.0, -4.0);
        return length(p - spherePos) - sphereSize;
    }

    float3 getNormal(float3 p)
    {
        const float d = 0.0001;
        return
            normalize
            (
                float3
                (
                    distanceFunc(p + float3(d, 0.0, 0.0)) - distanceFunc(p + float3(-d, 0.0, 0.0)),
                    distanceFunc(p + float3(0.0, d, 0.0)) - distanceFunc(p + float3(0.0, -d, 0.0)),
                    distanceFunc(p + float3(0.0, 0.0, d)) - distanceFunc(p + float3(0.0, 0.0, -d))
                    )
                );
    }

    fixed4 frag(v2f i) : SV_Target
    {
        // fragment position
        float2 p = i.uv - 0.5;
        p *= 0.3;

        // camera
        float3 cPos = float3(0.0, 0.0, 2.0);
        float3 cDir = float3(0.0, 0.0, -1.0);
        float3 cUp = float3(0.0, 1.0, 0.0);
        float3 cSide = cross(cDir, cUp);
        float targetDepth = 1.0;

        // ray
        float3 ray = normalize(cSide * p.x + cUp * p.y + cDir * targetDepth);

        // marching loop
        float distance = 0.0; // レイとオブジェクト間の最短距離
        float rLen = 0.0;     // レイに継ぎ足す長さ
        float3  rPos = cPos;  // レイの先端位置
        for (int i = 0; i < 4; i++) {
            distance = distanceFunc(rPos);
            rLen += distance;
            rPos = cPos + ray * rLen;

        }

        // hit check
        if (abs(distance) < 0.1) {
            float t = _Time.z;
            float3 normal = getNormal(rPos); 
            float3 light = float3(0.3 * cos(t), 0.3 * sin(t), 0.0);
            float env = 0.3; // 環境光
            float diffuse = dot(normal, light);
            float color = env + diffuse;
            return float4(color, color, color, 1.0);
        }else
        {
            return float4(0.0, 0.0, 0.0, 1.0);
        }
    }

ENDCG
    }
    }
}

結果

image

参考

全能感UP! GLSLで進めレイマーチング
http://www.demoscene.jp/?p=811

11
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8