zoukankan      html  css  js  c++  java
  • 简易的轮廓边生成(N和V dot点乘方式)(surface方式和vs ps 方式的分别实现)

    一、前面心情

    1.公司我的架构发生变动,从技术中心到项目组了,但不管怎么样,该看的还要看,总会用到

    二、实现

    三、参考:

    http://blog.csdn.net/cubesky/article/details/38588723

    四、代码和关键流程

    1.使用surface shader实现:

    首先:viewDir:世界坐标系下,vertex为起点,Camera为终点的向量,即Camera到vertex的反向量。

    Shader "Custom/outLineTest" {
    	Properties {
    		_MainTex ("Base (RGB)", 2D) = "white" {}
    		_OutLineColor("outLineColor",Color)=(1.0,0.0,0.0,1.0)
    		_threshold("outLine threshold ",Range(0.0,1.0))=0.21
    	}
    	SubShader {
    		Tags { "RenderType"="Opaque" }
    		LOD 200
    		
    		CGPROGRAM
    		#pragma surface surf Lambert
    
    		sampler2D _MainTex;
    		float4 _OutLineColor;
    		float _threshold;
    
    		struct Input {
    			float2 uv_MainTex;
    			float3 worldNormal;
    			float3 viewDir;
    		};
    
    		void surf (Input IN, inout SurfaceOutput o) {
    			half4 c = tex2D (_MainTex, IN.uv_MainTex);
    			float angleF=dot(normalize(IN.worldNormal),normalize(IN.viewDir));//求dot是否很小,如果很小,则说明normal和viewDir为90度,达到边缘。
    			o.Emission =_OutLineColor.rgb*step(angleF,_threshold);
    			o.Albedo = c.rgb;
    			o.Alpha = c.a;
    		}
    		ENDCG
    	} 
    	FallBack "Diffuse"
    }
    

      

    2.vs ps实现:

    当Camera位置变化时,cs文件传递pos到shader中去:

    cs绑定到球体上:

    using UnityEngine;
    using System.Collections;
    
    public class cameraCoordTest : MonoBehaviour {
    
    	// Use this for initialization
        public GameObject camer;
        const float cameraSpeed = 10.0f;
        Vector4 SetTempV()
        {
            Vector4  tempV = Vector4.zero;
            tempV.x = camer.transform.position.x;
            tempV.y = camer.transform.position.y;
            tempV.z = camer.transform.position.z;
            tempV.w = 1;
            return tempV;
        }
    
    	// Update is called once per frame
    	void Update () {
    
    	    if (Input.GetKey(KeyCode.W))
    	    {
                camer.transform.Translate(Vector3.forward * Time.deltaTime * cameraSpeed);
    
                transform.renderer.material.SetVector("_camPos", SetTempV());  
    	    }
            else if (Input.GetKey(KeyCode.S))
    	    {
                camer.transform.Translate(Vector3.forward * Time.deltaTime * -cameraSpeed);
                transform.renderer.material.SetVector("_camPos", SetTempV());  
    	    }
            else if (Input.GetKey(KeyCode.A))
            {
                camer.transform.Translate(Vector3.left * Time.deltaTime * cameraSpeed);
                transform.renderer.material.SetVector("_camPos", SetTempV());  
            }
            else if(Input.GetKey(KeyCode.D))
            {
                camer.transform.Translate(Vector3.left * Time.deltaTime * -cameraSpeed);
                transform.renderer.material.SetVector("_camPos", SetTempV());  
            }
    	}
    }
    

      

    shader中,把surface修改为vs ps实现方式:

    Shader "Custom/outLineTest" {
    	Properties {
    		_MainTex ("Base (RGB)", 2D) = "white" {}
    		_threshold("outLine threshold ",Range(0.0,1.0))=0.1
    		_camPos("cam pos",Vector)=(0,0,-10.0,1.0)
    	}
    	SubShader{
    		Pass{
    		 Fog{Mode Off}
    		 CGPROGRAM
    		 #pragma vertex vert
    		 #pragma fragment frag
    		 #include "UnityCG.cginc"
    
    		 uniform float _threshold;
    		 uniform float4 _camPos;
    
    		 struct v2f1{
    			float4 pos :SV_POSITION;
    			float3 norm : TEXCOORD1;
    			float3 verToViewDir : TEXCOORD2;
    		 };
    
    		 v2f1 vert(appdata_base inV)
    		 {
    			v2f1 o;
    			o.pos = mul(UNITY_MATRIX_MVP,inV.vertex);
    			o.norm = mul ((float3x3)_Object2World, inV.normal);//normal转化到世界坐标系下
    			o.verToViewDir = normalize(_camPos.xyz-mul(_Object2World,inV.vertex).xyz);
    			return o;
    		 }
    
    		 float4  frag(v2f1 inV):SV_Target
    		 {
    			float4 reColor;
    			reColor.a = 1.0f;
    			float angleF=dot(normalize(inV.norm),normalize(inV.verToViewDir));
    
    			reColor.rgb=float3(0,0,0)+float3(1,1,1)*step(angleF,0.3);
    
    			return reColor;			
    		 }
    		 ENDCG
    		}
    	}
    	Fallback off
    	}
    

      

    五、下一步

    这种方式对平滑曲面有效,当立方体或非渐变的法线物体,此法无效,比如说plane,由于背面没有normal,无法获取

    以前轮廓边检测生成阴影时,可以通过GS来判断邻边,判断line是否是轮廓边。作为以后学习内容吧

    六:注意点:

    1.appdata_base 类中全是本地坐标系下的数据,需要转化到worldSpace下,所以,normal需要进行object2World的转化;
    2.为了达到surface中viewDir数据,需要Camera的pos和vertex的pos进行处理,
    3.如果写好surface实现,vs ps写不好,参考surface编译后的代码,仔细看,总会写好vs ps实现

    改变自己
  • 相关阅读:
    22.112.leetcode_path_sum
    21.leetcode111_minimum_depth_of_binary_tree
    20.leetcode110_balanced_binary_tree
    19.leetcode108_convert_sorted_array_to_binary_search_tree
    论文阅读 | RoBERTa: A Robustly Optimized BERT Pretraining Approach
    CheckList:ACL 2020 Best Paper
    激活函数综述
    盘点深度学习中的损失函数
    逻辑回归
    机器学习之参数估计
  • 原文地址:https://www.cnblogs.com/sun-shadow/p/4973313.html
Copyright © 2011-2022 走看看