一、前面心情

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实现

简易的轮廓边生成(N和V dot点乘方式)(surface方式和vs ps 方式的分别实现)的更多相关文章

  1. ASP.NET 生成二维码(采用ThoughtWorks.QRCode和QrCode.Net两种方式)

    最近做项目遇到生成二维码的问题,发现网上用的最多的是ThoughtWorks.QRCode和QrCode.Net两种方式.访问官网看着例子写了两个Demo,使用过程中发现两个都挺好用的,Thought ...

  2. android的dmtracedump工具生成trace文件图片 'dot' 不是内部或外部命令,也不是可运行的程序 或批处理文件。

    http://jingyan.baidu.com/article/c910274bfa6c1fcd361d2df7.html http://www.cnblogs.com/albert1017/p/3 ...

  3. c# iText 生成PDF 有文字,图片,表格,文字样式,对齐方式,页眉页脚,等等等,

    #region 下载说明书PDF protected void lbtnDownPDF_Click(object sender, EventArgs e) { int pid = ConvertHel ...

  4. Ubuntu操作用户账户

    Git Gerrit $是普通管员,#是系统管理员,在Ubuntu下,root用户默认是没有密码的,因此也就无法使用(据说是为了安全).想用root的话,得给root用户设置一个密码: sudo pa ...

  5. miaov- 自动生成正V反V大于号V小于号V楼梯等图案

    1. 核心:控制 数量的长度-1-i的位置,是放在left上还是top上?是放在前面还是后面! <!DOCTYPE html> <html lang="en"&g ...

  6. opencv6.5-imgproc图像处理模块之轮廓

    接opencv6.4-imgproc图像处理模块之直方图与模板 这部分的<opencv_tutorial>上都是直接上代码,没有原理部分的解释的. 十一.轮廓 1.图像中找轮廓 /// 转 ...

  7. Why数学图像生成工具

    该软件能够以给定的数学公式及算法生成各种绚烂的数学图像.软件中有两种生成图像的方法: (1)通过一种我自定义的脚本语言生成: 软件中定义一套简单易学的脚本语言,用于描述数学表达式.使用时需要先要将数学 ...

  8. 由zImage生成uImage

    一.手动使用mkimage命令 mkimage -A arm -O linux -T kernel -C none -a 30007fc0 -e 30007fc0 -n uImage   -d /wo ...

  9. 对xlslib库与libxls库的简易封装

    一.简介 xlslib库是用来创建excel文件.libxls是用来读取excel文件的,在使用C++或者QT语言来设计对excel文件的读取.都需要事先下载这两个库编译成功后再进行程序设计的.之所以 ...

随机推荐

  1. 第一弹:Java 中创建对象的4种方式

    Java 是面向对象的语言,不可避免的,"对象"这个概念是 Java 语言的核心部分,这里来简单讨论一下在 Java 中创建一般对象的方法. 总结下来有以下4种创建对象的方法: 使 ...

  2. JSTL中的fmt标签小例子

    <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding= ...

  3. Spring声明事务管理

    首先我们先了解事务,什么是事务? 简单来说就是要么全部成功,要么什么都不做. 为什么要使用事务? 比如说常用银行系统的例子,如果没有用事务,有人在存入钱的时候出了问题,那么银行系统数据库的数据没有改变 ...

  4. 在 Visual Studio 等编辑器/IDE中自动切换输入法,不需要手动的有没有?

    使用Visual Studio写代码,经常遇到的一个问题就是切换中文输入法麻烦,输入完注释//,要切换到中文,输入完引号,要输入中文,然后还需要切换回来,有没有? 有时候中文输入法忽然失效有没有?明明 ...

  5. highCharts提示框不显示的问题

    使用HighCharts插件进行数据展示的时候,鼠标放在数据处没有提示框,或者只有头尾2个提示框,其他提示框不显示,为什么会这样? 1.查看是否使用了tooltip属性,该属性的enabled默认为t ...

  6. js实现右下角可关闭最小化div

    本实例使用Javascript实现右下角可关闭最小化div,可以用于展示推荐内容,效果预览网址:http://keleyi.com/keleyi/phtml/xuanfudiv/3.htm效果图片: ...

  7. Oracle常用SQL查询(2)

    三.查看数据库的SQL 1 .查看表空间的名称及大小 select  t.tablespace_name,  round ( sum (bytes / ( 1024 * 1024 )), 0 ) ts ...

  8. 使用mvc时,在视图view中使用强类型视图,在web.config文件中添加命名空间namespace的引用不起作用,解决方法

    这是view中的model代码: @model t_user_info 这是web.config配置文件只的代码: <namespaces> <add namespace=" ...

  9. iOS8 tableview separatorInset cell分割线左对齐,ios7的方法失效了

    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 -(void)viewDidLayoutSubviews {          if ([self.m ...

  10. ORA-01502: index ‘index_name' or partition of such index is in unusable state

    错误现象: 今天发布脚本时,一个表插入数据时报如下错误 ORA-01502: index ‘index_name' or partition of such index is in unusable ...