Unity Shaders 基础篇(二) 基本操作
来源:互联网 发布:idea中导入hadoop源码 编辑:程序博客网 时间:2024/05/16 08:33
本文主要参照CG_WikiBook.
最简vf shader模板
先上一个最简单的vfshader模板.
Shader "Cg basic shader" { // defines the name of the shader SubShader { // Unity chooses the subshader that fits the GPU best Pass { // some shaders require multiple passes CGPROGRAM // here begins the part in Unity's Cg #pragma vertex vert // this specifies the vert function as the vertex shader #pragma fragment frag // this specifies the frag function as the fragment shader float4 vert(float4 vertexPos : POSITION) : SV_POSITION // vertex shader { return mul(UNITY_MATRIX_MVP, vertexPos); //把顶点坐标从模型空间转换成投影空间 } float4 frag(void) : COLOR // fragment shader { return float4(1.0, 0.0, 0.0, 1.0); //修改此行去更改颜色 RGBA } ENDCG // here ends the part in Cg } }}
这是一个红色的cube.
修改颜色
fragment指的就是屏幕像素.
现在修改fragment shader中的颜色使其变绿.
float4 frag(void) : COLOR // fragment shader { return float4(0.0, 1.0, 0.0, 1.0); //修改此行去更改颜色 RGBA }
修改形状
因为到frag函数时,已经到了屏幕空间了. 无法更改物体的几何特征.所以更改物体形状只能放在vertex函数中.
float4 vert(float4 vertexPos : POSITION) : SV_POSITION // vertex shader { return mul(UNITY_MATRIX_MVP, float4(1,0.5,1,1)*vertexPos); //把顶点坐标从模型空间转换成投影空间 }
由图可看出,模型沿y轴压缩了一半.
让颜色更多变一点
Shader "Cg shader for RGB cube" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // 在上文中,我们vert返回的是屏幕的坐标. // 但是我们也可以返回多个参数. // 方法就是定义一个struct. struct vertexOutput { float4 pos : SV_POSITION; float4 col : TEXCOORD0; //这里有一点需要注意一下,这个参数代表的是颜色.而不是纹理的坐标. //TEXCOORD0(semantics)只是代表了数据的类型,实际用途由我们来定义 }; vertexOutput vert(float4 vertexPos : POSITION) // vertex shader { vertexOutput output; // we don't need to type 'struct' here output.pos = mul(UNITY_MATRIX_MVP, vertexPos); output.col = vertexPos + float4(0.5, 0.5, 0.5, 0.0); //这里都加0.5的含义是因为我这里取得是单位立方体(边长为1). //比如顶点(-0.5,-0.5,0.5,1)+(0.5,0.5,0.5,0)=(0,0,1,1) //所以左下角呈现的就是蓝色了 return output; } float4 frag(vertexOutput input) : COLOR // fragment shader { return input.col; // Here the fragment shader returns the "col" input // parameter with semantic TEXCOORD0 as nameless // output parameter with semantic COLOR. } ENDCG } }}
这里的代码演示了vert函数返回多个参数的方法.
效果图如下:
大家如果仔细考虑下的话,会发现不仅仅是顶点有颜色,而且这些平面也都获取了颜色.这是由于非顶点的像素颜色会被三角形的顶点进行插值.
这里再次注意下: cube的顶点个数并不为8.而是24.
原因是默认的cube为了让边缘看起来颜色完全不同,所以每个顶点的法向量都是按照面来计算的.即每个顶点的法向量要算三次. 所以每个顶点就会额外计算两次. 所以顶点数为24.
切割立方体
按自己数值
Shader "Cg shader for RGB cube" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // 在上文中,我们vert返回的是屏幕的坐标. // 但是我们也可以返回多个参数. // 方法就是定义一个struct. struct vertexOutput { float4 pos : SV_POSITION; float4 col : TEXCOORD0; float4 posInObjectSpace : TEXCOORD1; //这里有一点需要注意一下,这个参数代表的是颜色.而不是纹理的坐标. //TEXCOORD0(semantics)只是代表了数据的类型,实际用途由我们来定义 }; vertexOutput vert(float4 vertexPos : POSITION) // vertex shader { vertexOutput output; // we don't need to type 'struct' here output.pos = mul(UNITY_MATRIX_MVP, vertexPos); output.col = vertexPos + float4(0.5, 0.5, 0.5, 0.0); //这里都加0.5的含义是因为我这里取得是单位立方体(边长为1). //比如顶点(-0.5,-0.5,0.5,1)+(0.5,0.5,0.5,0)=(0,0,1,1) //所以左下角呈现的就是蓝色了 output.posInObjectSpace=vertexPos; return output; } float4 frag(vertexOutput input) : COLOR // fragment shader { if(input.posInObjectSpace.y>0.0) { discard; //不对像素进行处理 } return input.col; // Here the fragment shader returns the "col" input // parameter with semantic TEXCOORD0 as nameless // output parameter with semantic COLOR. } ENDCG } }}
更改的代码主要在于我们加入了一个额外的参数posInObjectSpace
. 即我们也传递了模型空间的坐标. 这个参数也会和颜色值一样像上述例子进行插值. 换句话来讲,即我们可以在屏幕空间中获得其对应的模型空间的坐标.
按照参照体进行切割
除此之外 我们还可以通过别的GameObject来进行切割. 比如我们拿球体来切割材质.
从Sphere取矩阵信息:
using UnityEngine;using System.Collections;public class CutOff : MonoBehaviour { public GameObject sphere; // Use this for initialization void Start () { } // Update is called once per frame void Update () { Matrix4x4 matrix = sphere.GetComponent<Renderer>().worldToLocalMatrix; GetComponent<Renderer>().material.SetMatrix("sphereM", matrix); }}
Shader代码:
Shader "Cg shader for RGB cube" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag float4x4 sphereM; // 在上文中,我们vert返回的是屏幕的坐标. // 但是我们也可以返回多个参数. // 方法就是定义一个struct. struct vertexOutput { float4 pos : SV_POSITION; float4 col : TEXCOORD0; float4 posWorldSpace : TEXCOORD1; //这里有一点需要注意一下,这个参数代表的是颜色.而不是纹理的坐标. //TEXCOORD0(semantics)只是代表了数据的类型,实际用途由我们来定义 }; vertexOutput vert(float4 vertexPos : POSITION) // vertex shader { vertexOutput output; // we don't need to type 'struct' here output.pos = mul(UNITY_MATRIX_MVP, vertexPos); output.col = vertexPos + float4(0.5, 0.5, 0.5, 0.0); //这里都加0.5的含义是因为我这里取得是单位立方体(边长为1). //比如顶点(-0.5,-0.5,0.5,1)+(0.5,0.5,0.5,0)=(0,0,1,1) //所以左下角呈现的就是蓝色了 output.posWorldSpace=mul(UNITY_MATRIX_M,vertexPos); return output; } float4 frag(vertexOutput input) : COLOR // fragment shader { float4 localPos= mul(sphereM,input.posWorldSpace); if(localPos.y>0.3||localPos.y<-0.3|| localPos.x>0.3||localPos.x<-0.3) { discard; //不对像素进行处理 } return input.col; // Here the fragment shader returns the "col" input // parameter with semantic TEXCOORD0 as nameless // output parameter with semantic COLOR. } ENDCG } }}
试了大半天, 由于即使用sphere来切割立方体,切口也是个矩形,所以没办法展示特效. 后面想到了再进行补充.
正反面赋色
Shader "Cg shader with two passes using discard" { SubShader { // first pass (is executed before the second pass) Pass { Cull Front // cull only front faces CGPROGRAM #pragma vertex vert #pragma fragment frag struct vertexInput { float4 vertex : POSITION; }; struct vertexOutput { float4 pos : SV_POSITION; float4 posInObjectCoords : TEXCOORD0; }; vertexOutput vert(vertexInput input) { vertexOutput output; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); output.posInObjectCoords = input.vertex; return output; } float4 frag(vertexOutput input) : COLOR { if (input.posInObjectCoords.y > 0.0) { discard; // drop the fragment if y coordinate > 0 } return float4(1.0, 0.0, 0.0, 1.0); // red } ENDCG } // second pass (is executed after the first pass) Pass { Cull Back // cull only back faces CGPROGRAM #pragma vertex vert #pragma fragment frag struct vertexInput { float4 vertex : POSITION; }; struct vertexOutput { float4 pos : SV_POSITION; float4 posInObjectCoords : TEXCOORD0; }; vertexOutput vert(vertexInput input) { vertexOutput output; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); output.posInObjectCoords = input.vertex; return output; } float4 frag(vertexOutput input) : COLOR { if (input.posInObjectCoords.y > 0.0) { discard; // drop the fragment if y coordinate > 0 } return float4(0.0, 1.0, 0.0, 1.0); // green } ENDCG } }}
这个Shader展示了两个render pass. 正面赋绿,背面赋红. 其余和上面一样.
0 0
- Unity Shaders 基础篇(二) 基本操作
- Unity Shaders 基础篇(一) 基本概念
- Unity Shaders 基础篇(四) 光照
- Unity Shaders 基础篇(三) 纹理与透明度
- Unity学习笔记——Unity基础二:基本操作以及坐标系
- 【Unity Shaders】《Unity Shaders and Effects Cookbook》总结篇
- 【unity shaders】一 Unity中的Shader及其基本框架
- 【Unity Shaders】学习笔记之固定着色器命令(二)
- 【Unity Shaders】学习笔记之固定着色器命令(二)
- Python基础--基本文件操作二
- Unity Shaders简介
- 【Unity Shaders】法线贴图
- Unity各类数据库的基本操作(二)-- CSV
- unity学习笔记01--基础视图以及基本操作
- Unity各类基础数据库的基本操作(一)
- Unity之Unity基本操作
- unity 基本操作 总结
- Unity基本操作认识
- 自定义控件-下拉刷新
- TOJ 3203.Pay Back
- 南阳理工OJ 题目115 城市平乱
- 流体力学及其工程应用
- 直方图中最大矩形面积
- Unity Shaders 基础篇(二) 基本操作
- 多重json字符串解析
- http问题
- 启动Mac mysql服务器步骤
- Unity UI(七):交互式控件之Scroll Rect和ScrollView
- 接口与抽象类
- 一天一个设计模式---代理模式
- 51nod 逆序数[NYOJ 逆序数](离散化+树状数组)
- 网络(4):socket中用户自定义缓冲区的原因及方式