一、前面心情

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. overflow

    1. 隐藏x轴滚动条,垂直有滚动条: <body> <div style="width:100px;height:150px;overflow:scroll;overflo ...

  2. [转]看部电影,透透彻彻理解IoC(你没有理由再迷惑!)

    之前对依赖注入的概念一直感到模糊,直到看了这篇文章:http://www.iteye.com/topic/1122835 引述: IoC(控制反转:Inverse of Control)是Spring ...

  3. [翻译]Java日志终极指南

    本文由 ImportNew - Wing 翻译自 loggly.欢迎加入翻译小组.转载请见文末要求. Java日志基础 Java使用了一种自定义的.可扩展的方法来输出日志.虽然Java通过java.u ...

  4. 商业智能SAAS走向中小企业

    20多年前,Gartner提出了商业智能的概念,并将其定义为“一类由数据仓库.查询报表.数据分析.数据挖掘等部分组成的,以帮助企业决策的技术及应用”.从技术上讲,商业智能是数据仓库.OLAP和数据挖掘 ...

  5. SharePoint 2013 Search REST API 使用示例

    前言:在SharePoint2013中,提供Search REST service搜索服务,你可以在自己的客户端搜索方法或者移动应用程序中使用,该服务支持REST web request.你可以使用K ...

  6. View and Data API 现在支持IE11了

    By Daniel Du After a long time waiting, IE11 finally supports WebGL, which enables us viewing our 3D ...

  7. entity Framework codefirst Migrations

    一次数据迁移的记录 首先在vs工具里面使用打开程序包管理器控制台 在控制台上面选择程序集为数据访问层 注意配置生成app里面的连接字符串 在控制台输入 Enable-Migrations 会自动生成一 ...

  8. OS的沙盒机制 --基础知识

    /* iOS的沙盒机制,应用只能访问自己应用目录下的文件. iOS不像android,没有SD卡概念,不能直接访问图像.视频等内容. iOS应用产生的内容,如图像.文件.缓存内容等都必须存储在自己的沙 ...

  9. 【代码笔记】iOS-通过颜色来生成一个纯色图片

    一,效果图. 二,代码. RootViewController.m - (void)viewDidLoad { [super viewDidLoad]; // Do any additional se ...

  10. ThinkPHP3快速入门教程二:数据CURD

    CURD(创建[Create].更新[Updata].读取[Read].删除[Delete]),定义了用于处理数据的基本原子操作. CURD在具体的应用中并非一定使用create.updata.rea ...