转载自 冯乐乐的 《Unity Shader 入门精要》

消融效果

消融效果常见于游戏中的角色死亡、地图烧毁等效果。这这些效果中,消融往往从不同的区域开始,并向看似随机的方向扩张,最后整个物体都将消失不见。我们将学习如何在Unity中实现这种效果。效果如下图所示。

要实现上图中的效果,原理非常简单,概括来说就是噪声纹理+透明度测试。我们使用对噪声纹理采样的结果和某个控制消融程度的阈值比较,如果小于阈值,就使用clip函数把它对应的像素裁剪掉,这些部分就对应了图中被“烧毁”的区域。而镂空区域边缘的烧焦效果则是将两种颜色混合,再用pow函数处理后,与原纹理颜色混合后的效果。

我们进行如下准备工作。

1)新建一个场景,去掉天空盒子。

2)新建一个材质,新建一个Shader,赋给材质

3)构建一个包含3面墙的房间,并放置一个立方体,上步材质赋给立方体

我们修改Shader 代码。

  1. Shader "Unity Shaders Book/Chapter 15/Dissolve" {
  2. Properties {
  3. //控制消融程度
  4. _BurnAmount ("Burn Amount", Range(0.0, 1.0)) = 0.0
  5. //控制模拟烧焦效果时的线宽
  6. _LineWidth("Burn Line Width", Range(0.0, 0.2)) = 0.1
  7. _MainTex ("Base (RGB)", 2D) = "white" {}
  8. _BumpMap ("Normal Map", 2D) = "bump" {}
  9. //火焰边缘颜色
  10. _BurnFirstColor("Burn First Color", Color) = (1, 0, 0, 1)
  11. //火焰边缘颜色
  12. _BurnSecondColor("Burn Second Color", Color) = (1, 0, 0, 1)
  13. _BurnMap("Burn Map", 2D) = "white"{}
  14. }
  15. SubShader {
  16. Tags { "RenderType"="Opaque" "Queue"="Geometry"}
  17. Pass {
  18. Tags { "LightMode"="ForwardBase" }
  19. //关闭剔除,正面和背面都会被渲染
  20. Cull Off
  21. CGPROGRAM
  22. #include "Lighting.cginc"
  23. #include "AutoLight.cginc"
  24. #pragma multi_compile_fwdbase
  25. #pragma vertex vert
  26. #pragma fragment frag
  27. fixed _BurnAmount;
  28. fixed _LineWidth;
  29. sampler2D _MainTex;
  30. sampler2D _BumpMap;
  31. fixed4 _BurnFirstColor;
  32. fixed4 _BurnSecondColor;
  33. sampler2D _BurnMap;
  34. float4 _MainTex_ST;
  35. float4 _BumpMap_ST;
  36. float4 _BurnMap_ST;
  37. struct a2v {
  38. float4 vertex : POSITION;
  39. float3 normal : NORMAL;
  40. float4 tangent : TANGENT;
  41. float4 texcoord : TEXCOORD0;
  42. };
  43. struct v2f {
  44. float4 pos : SV_POSITION;
  45. float2 uvMainTex : TEXCOORD0;
  46. float2 uvBumpMap : TEXCOORD1;
  47. float2 uvBurnMap : TEXCOORD2;
  48. float3 lightDir : TEXCOORD3;
  49. float3 worldPos : TEXCOORD4;
  50. SHADOW_COORDS(5)
  51. };
  52. v2f vert(a2v v) {
  53. v2f o;
  54. o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
  55. o.uvMainTex = TRANSFORM_TEX(v.texcoord, _MainTex);
  56. o.uvBumpMap = TRANSFORM_TEX(v.texcoord, _BumpMap);
  57. o.uvBurnMap = TRANSFORM_TEX(v.texcoord, _BurnMap);
  58. TANGENT_SPACE_ROTATION;
  59. o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;
  60. o.worldPos = mul(_Object2World, v.vertex).xyz;
  61. TRANSFER_SHADOW(o);
  62. return o;
  63. }
  64. fixed4 frag(v2f i) : SV_Target {
  65. //对噪声纹理采样
  66. fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;
  67. //将采样结果与_BurnAmount相减后 传递给clip
  68. //小于0则会被剔除,不会显示到屏幕上
  69. clip(burn.r - _BurnAmount);
  70. float3 tangentLightDir = normalize(i.lightDir);
  71. fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap, i.uvBumpMap));
  72. fixed3 albedo = tex2D(_MainTex, i.uvMainTex).rgb;
  73. fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
  74. fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal, tangentLightDir));
  75. fixed t = 1 - smoothstep(0.0, _LineWidth, burn.r - _BurnAmount);
  76. fixed3 burnColor = lerp(_BurnFirstColor, _BurnSecondColor, t);
  77. burnColor = pow(burnColor, 5);
  78. UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
  79. fixed3 finalColor = lerp(ambient + diffuse * atten, burnColor, t * step(0.0001, _BurnAmount));
  80. return fixed4(finalColor, 1);
  81. }
  82. ENDCG
  83. }
  84. //用于投射阴影
  85. Pass {
  86. Tags { "LightMode" = "ShadowCaster" }
  87. CGPROGRAM
  88. #pragma vertex vert
  89. #pragma fragment frag
  90. #pragma multi_compile_shadowcaster
  91. #include "UnityCG.cginc"
  92. fixed _BurnAmount;
  93. sampler2D _BurnMap;
  94. float4 _BurnMap_ST;
  95. struct v2f {
  96. V2F_SHADOW_CASTER;
  97. float2 uvBurnMap : TEXCOORD1;
  98. };
  99. v2f vert(appdata_base v) {
  100. v2f o;
  101. TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
  102. o.uvBurnMap = TRANSFORM_TEX(v.texcoord, _BurnMap);
  103. return o;
  104. }
  105. fixed4 frag(v2f i) : SV_Target {
  106. fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;
  107. clip(burn.r - _BurnAmount);
  108. SHADOW_CASTER_FRAGMENT(i)
  109. }
  110. ENDCG
  111. }
  112. }
  113. FallBack "Diffuse"
  114. }

在本例中,我们使用的噪声纹理如下图所示。

水波效果

在模拟实时水面的过程中,我们往往也会使用噪声纹理。此时,噪声纹理通常会用作一个高度图,以不断修改水面的法线方向。为了模拟水不断流动的效果,我们会使用和时间相关的变量来对噪声纹理进行采样,当得到法线信息后,再进行正常的反射+折射计算,得到最后的水面波动效果。

我们将使用一个由噪声纹理得到的法线贴图,实现一个包含菲涅耳发射的水面效果,如下图所示。

我们在之前介绍过如何使用反射和折射来模拟一个透明玻璃的效果。我们要使用的Shader 和之前的类似。我们使用一张立方体纹理作为环境纹理,模拟反射。为了模拟折射效果,我们使用GrabPass来获取当前屏幕的渲染纹理,并使用切线空间下的法线方向对像素的屏幕坐标进行偏移,再使用该坐标对渲染为进行屏幕采样,从而模拟近似的折射效果。水波的法线纹理是由一张噪声纹理生成而得,而且会随着时间变化不断平移,模拟波光粼粼的效果。除此之外,我们没有使用一个定值来混合反射和折射颜色,而是使用之前提到的菲涅耳系数来动态决定混合系数。我们使用如下公式来计算菲涅耳系数:

其中,v 和 n 分别对应了视角方向和法线方向。它们之间的夹角越小,fresnel 值越小,反射越弱,折射越强。菲涅耳系数还经常会用于边缘光照的计算中。

我们做如下准备工作。

1)新建一个场景,去掉天空盒子

2)新建一个材质,新建一个Shader,赋给材质

3)我们构建一个由6面墙围成的封闭房间,房间里放置了一个平面来模拟水面。上步材质赋给平面。

4)为了得到本场景适用的环境纹理,我们使用了之前实现的创建立方体纹理的脚本 (通过GameObject -> Render into Cubemap 打开编辑器窗口)来创建它,如下图所示。

然后我们开始编写Shader

  1. Shader "Unity Shaders Book/Chapter 15/Water Wave" {
  2. Properties {
  3. //控制水面颜色
  4. _Color ("Main Color", Color) = (0, 0.15, 0.115, 1)
  5. //水面波纹材质纹理
  6. _MainTex ("Base (RGB)", 2D) = "white" {}
  7. //由噪声纹理生成的法线纹理
  8. _WaveMap ("Wave Map", 2D) = "bump" {}
  9. //模拟反射的立方体纹理
  10. _Cubemap ("Environment Cubemap", Cube) = "_Skybox" {}
  11. _WaveXSpeed ("Wave Horizontal Speed", Range(-0.1, 0.1)) = 0.01
  12. _WaveYSpeed ("Wave Vertical Speed", Range(-0.1, 0.1)) = 0.01
  13. //控制模拟折射时图像的扭曲程度
  14. _Distortion ("Distortion", Range(0, 100)) = 10
  15. }
  16. SubShader {
  17. // We must be transparent, so other objects are drawn before this one.
  18. Tags { "Queue"="Transparent" "RenderType"="Opaque" }
  19. //使用GrabPass 来获取屏幕图像
  20. GrabPass { "_RefractionTex" }
  21. Pass {
  22. Tags { "LightMode"="ForwardBase" }
  23. CGPROGRAM
  24. #include "UnityCG.cginc"
  25. #include "Lighting.cginc"
  26. #pragma multi_compile_fwdbase
  27. #pragma vertex vert
  28. #pragma fragment frag
  29. fixed4 _Color;
  30. sampler2D _MainTex;
  31. float4 _MainTex_ST;
  32. sampler2D _WaveMap;
  33. float4 _WaveMap_ST;
  34. samplerCUBE _Cubemap;
  35. fixed _WaveXSpeed;
  36. fixed _WaveYSpeed;
  37. float _Distortion;
  38. sampler2D _RefractionTex;
  39. float4 _RefractionTex_TexelSize;
  40. struct a2v {
  41. float4 vertex : POSITION;
  42. float3 normal : NORMAL;
  43. float4 tangent : TANGENT;
  44. float4 texcoord : TEXCOORD0;
  45. };
  46. struct v2f {
  47. float4 pos : SV_POSITION;
  48. float4 scrPos : TEXCOORD0;
  49. float4 uv : TEXCOORD1;
  50. float4 TtoW0 : TEXCOORD2;
  51. float4 TtoW1 : TEXCOORD3;
  52. float4 TtoW2 : TEXCOORD4;
  53. };
  54. v2f vert(a2v v) {
  55. v2f o;
  56. o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
  57. o.scrPos = ComputeGrabScreenPos(o.pos);
  58. o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
  59. o.uv.zw = TRANSFORM_TEX(v.texcoord, _WaveMap);
  60. float3 worldPos = mul(_Object2World, v.vertex).xyz;
  61. fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
  62. fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
  63. fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
  64. o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
  65. o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
  66. o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
  67. return o;
  68. }
  69. fixed4 frag(v2f i) : SV_Target {
  70. float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
  71. fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
  72. float2 speed = _Time.y * float2(_WaveXSpeed, _WaveYSpeed);
  73. // Get the normal in tangent space
  74. fixed3 bump1 = UnpackNormal(tex2D(_WaveMap, i.uv.zw + speed)).rgb;
  75. fixed3 bump2 = UnpackNormal(tex2D(_WaveMap, i.uv.zw - speed)).rgb;
  76. fixed3 bump = normalize(bump1 + bump2);
  77. // Compute the offset in tangent space
  78. float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;
  79. i.scrPos.xy = offset * i.scrPos.z + i.scrPos.xy;
  80. fixed3 refrCol = tex2D( _RefractionTex, i.scrPos.xy/i.scrPos.w).rgb;
  81. // Convert the normal to world space
  82. bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
  83. fixed4 texColor = tex2D(_MainTex, i.uv.xy + speed);
  84. fixed3 reflDir = reflect(-viewDir, bump);
  85. fixed3 reflCol = texCUBE(_Cubemap, reflDir).rgb * texColor.rgb * _Color.rgb;
  86. fixed fresnel = pow(1 - saturate(dot(viewDir, bump)), 4);
  87. fixed3 finalColor = reflCol * fresnel + refrCol * (1 - fresnel);
  88. return fixed4(finalColor, 1);
  89. }
  90. ENDCG
  91. }
  92. }
  93. // Do not cast shadow
  94. FallBack Off
  95. }

再谈全局雾效

我们之前讲到了如何使用深度纹理来实现一种基于屏幕后处理的全局雾效。我们由深度纹理重建每个像素在世界空间系下的位置,再使用一个基于高度的公式来计算雾效的混合系数,最后使用该系数来混合雾的颜色和原屏幕颜色。这种雾效是一个基于高度的均匀雾效,即在同一个高度上,雾的浓度是相同的,如下图左图所示。然而,一些时候我们希望可以模拟一种不均匀的雾效,同时让雾不断飘动,使雾看起来更加缥缈,如下图右图所示。而这就可通过使用一张噪声纹理来实现。

实现非常简单,绝大代码和之前的一样,我们只是添加了噪声相关的参数和属性,并在Shader 的片元着色器中对高度的计算添加了噪声影响。

准备工作如下:

1)新建一个场景,去掉天空盒子

2)构建一个包含3面墙的房间,并放置两个立方体和两个球体

3)摄像机上添加脚本FogWithNoise.cs

4)新建一个Shader。

首先,我们编写FogWithNoise.cs

  1. public class FogWithNoise : PostEffectsBase {
  2. public Shader fogShader;
  3. private Material fogMaterial = null;
  4. public Material material {
  5. get {
  6. fogMaterial = CheckShaderAndCreateMaterial(fogShader, fogMaterial);
  7. return fogMaterial;
  8. }
  9. }
  10. private Camera myCamera;
  11. public Camera camera {
  12. get {
  13. if (myCamera == null) {
  14. myCamera = GetComponent<Camera>();
  15. }
  16. return myCamera;
  17. }
  18. }
  19. private Transform myCameraTransform;
  20. public Transform cameraTransform {
  21. get {
  22. if (myCameraTransform == null) {
  23. myCameraTransform = camera.transform;
  24. }
  25. return myCameraTransform;
  26. }
  27. }
  28. [Range(0.1f, 3.0f)]
  29. public float fogDensity = 1.0f;
  30. public Color fogColor = Color.white;
  31. public float fogStart = 0.0f;
  32. public float fogEnd = 2.0f;
  33. public Texture noiseTexture;
  34. [Range(-0.5f, 0.5f)]
  35. public float fogXSpeed = 0.1f;
  36. [Range(-0.5f, 0.5f)]
  37. public float fogYSpeed = 0.1f;
  38. [Range(0.0f, 3.0f)]
  39. public float noiseAmount = 1.0f;
  40. void OnEnable() {
  41. GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;
  42. }
  43. void OnRenderImage (RenderTexture src, RenderTexture dest) {
  44. if (material != null) {
  45. Matrix4x4 frustumCorners = Matrix4x4.identity;
  46. float fov = camera.fieldOfView;
  47. float near = camera.nearClipPlane;
  48. float aspect = camera.aspect;
  49. float halfHeight = near * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);
  50. Vector3 toRight = cameraTransform.right * halfHeight * aspect;
  51. Vector3 toTop = cameraTransform.up * halfHeight;
  52. Vector3 topLeft = cameraTransform.forward * near + toTop - toRight;
  53. float scale = topLeft.magnitude / near;
  54. topLeft.Normalize();
  55. topLeft *= scale;
  56. Vector3 topRight = cameraTransform.forward * near + toRight + toTop;
  57. topRight.Normalize();
  58. topRight *= scale;
  59. Vector3 bottomLeft = cameraTransform.forward * near - toTop - toRight;
  60. bottomLeft.Normalize();
  61. bottomLeft *= scale;
  62. Vector3 bottomRight = cameraTransform.forward * near + toRight - toTop;
  63. bottomRight.Normalize();
  64. bottomRight *= scale;
  65. frustumCorners.SetRow(0, bottomLeft);
  66. frustumCorners.SetRow(1, bottomRight);
  67. frustumCorners.SetRow(2, topRight);
  68. frustumCorners.SetRow(3, topLeft);
  69. material.SetMatrix("_FrustumCornersRay", frustumCorners);
  70. material.SetFloat("_FogDensity", fogDensity);
  71. material.SetColor("_FogColor", fogColor);
  72. material.SetFloat("_FogStart", fogStart);
  73. material.SetFloat("_FogEnd", fogEnd);
  74. material.SetTexture("_NoiseTex", noiseTexture);
  75. material.SetFloat("_FogXSpeed", fogXSpeed);
  76. material.SetFloat("_FogYSpeed", fogYSpeed);
  77. material.SetFloat("_NoiseAmount", noiseAmount);
  78. Graphics.Blit (src, dest, material);
  79. } else {
  80. Graphics.Blit(src, dest);
  81. }
  82. }
  83. }

然后,再修改Shader

    1. Shader "Unity Shaders Book/Chapter 15/Fog With Noise" {
    2. Properties {
    3. _MainTex ("Base (RGB)", 2D) = "white" {}
    4. _FogDensity ("Fog Density", Float) = 1.0
    5. _FogColor ("Fog Color", Color) = (1, 1, 1, 1)
    6. _FogStart ("Fog Start", Float) = 0.0
    7. _FogEnd ("Fog End", Float) = 1.0
    8. _NoiseTex ("Noise Texture", 2D) = "white" {}
    9. _FogXSpeed ("Fog Horizontal Speed", Float) = 0.1
    10. _FogYSpeed ("Fog Vertical Speed", Float) = 0.1
    11. _NoiseAmount ("Noise Amount", Float) = 1
    12. }
    13. SubShader {
    14. CGINCLUDE
    15. #include "UnityCG.cginc"
    16. float4x4 _FrustumCornersRay;
    17. sampler2D _MainTex;
    18. half4 _MainTex_TexelSize;
    19. sampler2D _CameraDepthTexture;
    20. half _FogDensity;
    21. fixed4 _FogColor;
    22. float _FogStart;
    23. float _FogEnd;
    24. sampler2D _NoiseTex;
    25. half _FogXSpeed;
    26. half _FogYSpeed;
    27. half _NoiseAmount;
    28. struct v2f {
    29. float4 pos : SV_POSITION;
    30. float2 uv : TEXCOORD0;
    31. float2 uv_depth : TEXCOORD1;
    32. float4 interpolatedRay : TEXCOORD2;
    33. };
    34. v2f vert(appdata_img v) {
    35. v2f o;
    36. o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    37. o.uv = v.texcoord;
    38. o.uv_depth = v.texcoord;
    39. #if UNITY_UV_STARTS_AT_TOP
    40. if (_MainTex_TexelSize.y < 0)
    41. o.uv_depth.y = 1 - o.uv_depth.y;
    42. #endif
    43. int index = 0;
    44. if (v.texcoord.x < 0.5 && v.texcoord.y < 0.5) {
    45. index = 0;
    46. } else if (v.texcoord.x > 0.5 && v.texcoord.y < 0.5) {
    47. index = 1;
    48. } else if (v.texcoord.x > 0.5 && v.texcoord.y > 0.5) {
    49. index = 2;
    50. } else {
    51. index = 3;
    52. }
    53. #if UNITY_UV_STARTS_AT_TOP
    54. if (_MainTex_TexelSize.y < 0)
    55. index = 3 - index;
    56. #endif
    57. o.interpolatedRay = _FrustumCornersRay[index];
    58. return o;
    59. }
    60. fixed4 frag(v2f i) : SV_Target {
    61. float linearDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth));
    62. float3 worldPos = _WorldSpaceCameraPos + linearDepth * i.interpolatedRay.xyz;
    63. float2 speed = _Time.y * float2(_FogXSpeed, _FogYSpeed);
    64. float noise = (tex2D(_NoiseTex, i.uv + speed).r - 0.5) * _NoiseAmount;
    65. float fogDensity = (_FogEnd - worldPos.y) / (_FogEnd - _FogStart);
    66. fogDensity = saturate(fogDensity * _FogDensity * (1 + noise));
    67. fixed4 finalColor = tex2D(_MainTex, i.uv);
    68. finalColor.rgb = lerp(finalColor.rgb, _FogColor.rgb, fogDensity);
    69. return finalColor;
    70. }
    71. ENDCG
    72. Pass {
    73. CGPROGRAM
    74. #pragma vertex vert
    75. #pragma fragment frag
    76. ENDCG
    77. }
    78. }
    79. FallBack Off
    80. }

Unity Shader入门精要学习笔记 - 第15章 使用噪声的更多相关文章

  1. Unity Shader入门精要学习笔记 - 第4章 学习 Shader 所需的数学基础

    摘录自 冯乐乐的<Unity Shader入门精要> 笛卡尔坐标系 1)二维笛卡尔坐标系 在游戏制作中,我们使用的数学绝大部分都是计算位置.距离.角度等变量.而这些计算大部分都是在笛卡尔坐 ...

  2. Unity Shader入门精要学习笔记 - 第17章 Unity的表面着色器探秘

    转自 冯乐乐的<Unity Shader 入门精要> 2010年的Unity 3 中,Surface Shader 出现了. 表面着色器的一个例子. 我们先做如下准备工作. 1)新建一个场 ...

  3. Unity Shader入门精要学习笔记 - 第16章 Unity中的渲染优化技术

    转自冯乐乐的 <Unity Shader 入门精要> 移动平台的特点 为了尽可能一处那些隐藏的表面,减少overdraw(即一个像素被绘制多次),PowerVR芯片(通常用于ios设备和某 ...

  4. Unity Shader入门精要学习笔记 - 第14章非真实感渲染

    转载自 冯乐乐的 <Unity Shader 入门精要> 尽管游戏渲染一般都是以照相写实主义作为主要目标,但也有许多游戏使用了非真实感渲染(NPR)的方法来渲染游戏画面.非真实感渲染的一个 ...

  5. Unity Shader入门精要学习笔记 - 第11章 让画面动起来

    转自 冯乐乐的 <Unity Shader入门精要> Unity Shader 中的内置变量 动画效果往往都是把时间添加到一些变量的计算中,以便在时间变化时画面也可以随之变化.Unity ...

  6. Unity Shader入门精要学习笔记 - 第10章 高级纹理

    转载自 冯乐乐的 <Unity Shader入门精要> 立方体纹理 在图形学中,立方体纹理是环境映射的一种实现方法.环境映射可以模拟物体周围的环境,而使用了环境映射的物体可以看起来像镀了层 ...

  7. Unity Shader入门精要学习笔记 - 第9章 更复杂的光照

    转载自 冯乐乐的<Unity Shader入门精要> Unity 的渲染路径 在Unity里,渲染路径决定了光照是如何应该到Unity Shader 中的.因此,如果要和光源打交道,我们需 ...

  8. Unity Shader入门精要学习笔记 - 第8章 透明效果

    转载自 冯乐乐的 <Unity Shader入门精要> 透明是游戏中经常要使用的一种效果.在实时渲染中要实现透明效果,通常会在渲染模型时控制它的透明通道.当开启透明混合后,当一个物体被渲染 ...

  9. Unity Shader入门精要学习笔记 - 第7章 基础纹理

    转自 冯乐乐的 <Unity Shader 入门精要> 纹理最初的目的就是使用一张图片来控制模型的外观.使用纹理映射技术,我们可以把一张图“黏”在模型表面,逐纹素地控制模型的颜色. 在美术 ...

随机推荐

  1. 51Nod - 1304 :字符串的相似度 (裸的扩展KMP)

    我们定义2个字符串的相似度等于两个串的相同前缀的长度.例如 "abc" 同 "abd" 的相似度为2,"aaa" 同 "aaab& ...

  2. python装饰器精髓代码

    #!/usr/bin/env python #-*- coding:utf-8 -*- import time def foo(func): def inner(): print('fs...') f ...

  3. moco实例

    一.moco模拟接口响应json moco的下载地址见虫师博客园:https://www.cnblogs.com/fnng/p/7511539.html foo.json文件内容如下 [ { &quo ...

  4. silverlight RadGridView 动态添加数据列

    public void BindFaultGridInfo(IList<HealthStatusApp.Web.Models.FaultMajorModel> list) { rg_Fau ...

  5. 抓屏工具 faststone capture

    百度百科 http://baike.baidu.com/link?url=te51CfOKYIEmqT1jsyRwcB8Pnals5xQ8nUXk6trvBPGSJRBO5G7BEZL7cYQxmx8 ...

  6. B. Vanya and Food Processor【转】

    B. Vanya and Food Processor time limit per test 1 second memory limit per test 256 megabytes input s ...

  7. HrrpClient使用

    使用HttpClient获取网页内容的过程 1.创建一个CloseableHttpClient类的实例: 2.使用这个实例执行HTTP请求,得到一个HttpResponse的实例: 3.最后,通过Ht ...

  8. msq 表操作与其数据类型

    一:表介绍 表相当于文件, 表中的一条记录就相当于文件的一行内容, 不同的是,表中的一条记录有对应的标题,称为表的字段: id,name, age, sex,称为字段, 其余的一行内容称为一条记录. ...

  9. Mac Apache

    参考文章1 当前系统版本:Mac OS 10.11.6 一.使用 homebrew 安装 apache 停止系统自带的 apache 服务 $ sudo apachectl stop 卸载系统自带的 ...

  10. hdu5861【线段树】

    题意: 有n个点,每个两两之间有一条路,给出每条路开放的花费,每条路只能打开关闭一次,然后m天里给出一个区间代表这条路必须在该天开放,求每天需要的花费. 思路: 这是一题纯粹用线段树搞的题. 我们可以 ...