u3d27-shader-镜面反射

u3d27-shader-镜面反射

说实话镜面反射很简单,难就难在实现镜面反射的代码困难,但是现在我们的代码都是集成好的所以直接使用就可以了!

我们创建一个组件作为我们要变成镜面的工具(一般我们选择plane),之后创建一个材质,在其属性界面

选择我们shader创建的方法

把我们创建的材质赋给我们要做成镜面的组件(plane),把我们的代码与我们的组件绑定!

Ok我们的镜面就做好了!

共享一段JS代码。。。。可以让我们创建的组件自行旋转欧! function Update () {

transform.Rotate( 0, Time.deltaTime * 10, 0 );

}

把代码共享如下:

Shader文件:

Shader "FX/Mirror Reflection"

{Properties

{_MainTex("Base(RGB)",2D)="white"{}

_ReflectionTex("Reflection",2D)="white"{TexGen ObjectLinear}

}

// two texture cards: full thing

Subshader

{Pass

{SetTexture[_MainTex]{combine texture}

SetTexture[_ReflectionTex]{matrix [_ProjMatrix] combine texture*previous} }

}

// fallback: just main texture

Subshader

{Pass

{SetTexture [_MainTex]{combine texture}

}

}

}

Cs文件:

using UnityEngine;

using System.Collections;

//实际上 This is in fact just the Water script from Pro Standard Assets,

// just with refraction stuff removed.

[ExecuteInEditMode]// Make mirror live-update even when not in play mode

public class MirrorReflection:MonoBehaviour

{public bool m_DisablePixelLights=true;

public int m_TextureSize=256;

public float m_ClipPlaneOffset=0.07f;

public LayerMask m_ReflectLayers=-1;

private Hashtable m_ReflectionCameras=new Hashtable(); // Camera ->Camera table private RenderTexture m_ReflectionTexture=null;

private int m_OldReflectionTextureSize=0;

private static bool s_InsideRendering=false;

// This is called when it's known that the object will be rendered by some

// camera. We render reflections and do other updates here.

// Because the script executes in edit mode,reflections for the scene view

// camera will just work!

public void OnWillRenderObject()

{if(!enabled || !renderer || !renderer.sharedMaterial || !renderer.enabled )return;

Camera cam=Camera.current;

if(!cam )return;

// Safeguard from recursive reflections.

if(s_InsideRendering )return;

s_InsideRendering=true;

Camera reflectionCamera;

CreateMirrorObjects(cam,out reflectionCamera );

// find out the reflection plane:position and normal in world space

Vector3 pos=transform.position;

Vector3 normal=transform.up;

// Optionally disable pixel lights for reflection

int oldPixelLightCount=QualitySettings.pixelLightCount;

if(m_DisablePixelLights )QualitySettings.pixelLightCount=0;

UpdateCameraModes(cam,reflectionCamera );

// Render reflection

// Reflect camera around reflection plane

float d=-Vector3.Dot(normal,pos)-m_ClipPlaneOffset;

Vector4 reflectionPlane=new Vector4(normal.x,normal.y,normal.z,d);

Matrix4x4 reflection=Matrix4x4.zero;

CalculateReflectionMatrix(ref reflection,reflectionPlane);

Vector3 oldpos=cam.transform.position;

Vector3 newpos=reflection.MultiplyPoint(oldpos );

reflectionCamera.worldToCameraMatrix=cam.worldToCameraMatrix * reflection;

// Setup oblique projection matrix so that near plane is our reflection

// plane. This way we clip everything below/above it for free.

Vector4 clipPlane=CameraSpacePlane(reflectionCamera,pos,normal,1.0f );

Matrix4x4 projection=cam.projectionMatrix;

CalculateObliqueMatrix(ref projection,clipPlane);

reflectionCamera.projectionMatrix=projection;

reflectionCamera.cullingMask=~(1

reflectionCamera.targetTexture=m_ReflectionTexture;

GL.SetRevertBackfacing(true);

reflectionCamera.transform.position=newpos;

Vector3 euler=cam.transform.eulerAngles;

reflectionCamera.transform.eulerAngles=new Vector3(0,euler.y,euler.z);

reflectionCamera.Render();

reflectionCamera.transform.position=oldpos;

GL.SetRevertBackfacing(false);

Material[]materials=renderer.sharedMaterials;

foreach(Material mat in materials ){

if(mat.HasProperty("_ReflectionTex"))

mat.SetTexture("_ReflectionTex",m_ReflectionTexture );

}

// Set matrix on the shader that transforms UVs from object space into screen

// space. We want to just project reflection texture on screen.

Matrix4x4 scaleOffset=Matrix4x4.TRS(

new Vector3(0.5f,0.5f,0.5f),Quaternion.identity,new Vector3(0.5f,0.5f,0.5f));

Vector3 scale=transform.lossyScale;

Matrix4x4 mtx=transform.localToWorldMatrix * Matrix4x4.Scale(new Vector3(1.0f/scale.x,1.0f/scale.y,1.0f/scale.z));

mtx=scaleOffset * cam.projectionMatrix * cam.worldToCameraMatrix * mtx;

foreach(Material mat in materials ){

mat.SetMatrix("_ProjMatrix",mtx );

}

// Restore pixel light count

if(m_DisablePixelLights )

QualitySettings.pixelLightCount=oldPixelLightCount;

s_InsideRendering=false;

}

// Cleanup all the objects we possibly have created

void OnDisable()

{

if(m_ReflectionTexture ){

DestroyImmediate(m_ReflectionTexture );

m_ReflectionTexture=null;

}

foreach(DictionaryEntry kvp in m_ReflectionCameras )

DestroyImmediate(((Camera)kvp.Value).gameObject );

m_ReflectionCameras.Clear();

}

private void UpdateCameraModes(Camera src,Camera dest )

{

if(dest==null )

return;

// set camera to clear the same way as current camera

dest.clearFlags=src.clearFlags;

dest.backgroundColor=src.backgroundColor;

if(src.clearFlags==CameraClearFlags.Skybox )

{

Skybox sky=src.GetComponent(typeof(Skybox))as Skybox;

Skybox mysky=dest.GetComponent(typeof(Skybox))as Skybox;

if(!sky || !sky.material ){

mysky.enabled=false;

}

else

{

mysky.enabled=true;

mysky.material=sky.material;

}

}

// update other values to match current camera.

// even if we are supplying custom camera&projection matrices,

// some of values are used elsewhere(e.g. skybox uses far plane)

dest.farClipPlane=src.farClipPlane;

dest.nearClipPlane=src.nearClipPlane;

dest.orthographic=src.orthographic;

dest.fieldOfView=src.fieldOfView;

dest.aspect=src.aspect;

dest.orthographicSize=src.orthographicSize;

}

// On-demand create any objects we need

private void CreateMirrorObjects(Camera currentCamera,out Camera reflectionCamera ) {

reflectionCamera=null;

// Reflection render texture

if(!m_ReflectionTexture || m_OldReflectionTextureSize !=m_TextureSize )

{

if(m_ReflectionTexture )

DestroyImmediate(m_ReflectionTexture );

m_ReflectionTexture=new RenderTexture(m_TextureSize,m_TextureSize,16 );

m_ReflectionTexture.name="__MirrorReflection" + GetInstanceID();

m_ReflectionTexture.isPowerOfTwo=true;

m_ReflectionTexture.hideFlags=HideFlags.DontSave;

m_OldReflectionTextureSize=m_TextureSize;

}

// Camera for reflection

reflectionCamera=m_ReflectionCameras[currentCamera]as Camera;

if(!reflectionCamera )// catch both not-in-dictionary and in-dictionary-but-deleted-GO

{

GameObject go=new GameObject("Mirror Refl Camera id" + GetInstanceID()+ " for " + currentCamera.GetInstanceID(),typeof(Camera),typeof(Skybox));

reflectionCamera=go.camera;

reflectionCamera.enabled=false;

reflectionCamera.transform.position=transform.position;

reflectionCamera.transform.rotation=transform.rotation;

reflectionCamera.gameObject.AddComponent("FlareLayer");

go.hideFlags=HideFlags.HideAndDontSave;

m_ReflectionCameras[currentCamera]=reflectionCamera;

}

}

// Extended sign:returns -1,0 or 1 based on sign of a

private static float sgn(float a)

{if(a>0.0f)return 1.0f;

if(a

return 0.0f;

}

// Given position/normal of the plane,calculates plane in camera space.

private Vector4 CameraSpacePlane(Camera cam,Vector3 pos,Vector3 normal,float sideSign)

{

Vector3 offsetPos=pos + normal * m_ClipPlaneOffset;

Matrix4x4 m=cam.worldToCameraMatrix;

Vector3 cpos=m.MultiplyPoint(offsetPos );

Vector3 cnormal=m.MultiplyVector(normal ).normalized * sideSign;

return new Vector4(cnormal.x,cnormal.y,cnormal.z,-Vector3.Dot(cpos,cnormal));

}

//调整给定的射影矩阵以便最近的平面Adjusts the given projection matrix so that near plane is the given clipPlane

// clipPlane is given in camera space. See article in Game Programming Gems 5.

private static void CalculateObliqueMatrix(ref Matrix4x4 projection,Vector4 clipPlane) {Vector4 q=projection.inverse * new Vector4(sgn(clipPlane.x),sgn(clipPlane.y),1.0f,1.0f); Vector4 c=clipPlane *(2.0F /(Vector4.Dot(clipPlane,q)));

// third row=clip plane -fourth row

projection[2]=c.x -projection[3];

projection[6]=c.y -projection[7];

projection[10]=c.z -projection[11];

projection[14]=c.w -projection[15];

}

//围绕给定的平面计算折射矩阵

private static void CalculateReflectionMatrix(ref Matrix4x4 reflectionMat,Vector4 plane) {reflectionMat.m00=(1F -2F*plane[0]*plane[0]);

reflectionMat.m01=(-2F*plane[0]*plane[1]);

reflectionMat.m02=(-2F*plane[0]*plane[2]);

reflectionMat.m03=(-2F*plane[3]*plane[0]);

reflectionMat.m10=(-2F*plane[1]*plane[0]);

reflectionMat.m11=(1F -2F*plane[1]*plane[1]);

reflectionMat.m12=(-2F*plane[1]*plane[2]);

reflectionMat.m13=(-2F*plane[3]*plane[1]);

} reflectionMat.m21=(-2F*plane[2]*plane[1]); reflectionMat.m22=(1F -2F*plane[2]*plane[2]); reflectionMat.m23=(-2F*plane[3]*plane[2]); reflectionMat.m30=0F; reflectionMat.m31=0F; reflectionMat.m32=0F; reflectionMat.m33=1F; }

u3d27-shader-镜面反射

说实话镜面反射很简单,难就难在实现镜面反射的代码困难,但是现在我们的代码都是集成好的所以直接使用就可以了!

我们创建一个组件作为我们要变成镜面的工具(一般我们选择plane),之后创建一个材质,在其属性界面

选择我们shader创建的方法

把我们创建的材质赋给我们要做成镜面的组件(plane),把我们的代码与我们的组件绑定!

Ok我们的镜面就做好了!

共享一段JS代码。。。。可以让我们创建的组件自行旋转欧! function Update () {

transform.Rotate( 0, Time.deltaTime * 10, 0 );

}

把代码共享如下:

Shader文件:

Shader "FX/Mirror Reflection"

{Properties

{_MainTex("Base(RGB)",2D)="white"{}

_ReflectionTex("Reflection",2D)="white"{TexGen ObjectLinear}

}

// two texture cards: full thing

Subshader

{Pass

{SetTexture[_MainTex]{combine texture}

SetTexture[_ReflectionTex]{matrix [_ProjMatrix] combine texture*previous} }

}

// fallback: just main texture

Subshader

{Pass

{SetTexture [_MainTex]{combine texture}

}

}

}

Cs文件:

using UnityEngine;

using System.Collections;

//实际上 This is in fact just the Water script from Pro Standard Assets,

// just with refraction stuff removed.

[ExecuteInEditMode]// Make mirror live-update even when not in play mode

public class MirrorReflection:MonoBehaviour

{public bool m_DisablePixelLights=true;

public int m_TextureSize=256;

public float m_ClipPlaneOffset=0.07f;

public LayerMask m_ReflectLayers=-1;

private Hashtable m_ReflectionCameras=new Hashtable(); // Camera ->Camera table private RenderTexture m_ReflectionTexture=null;

private int m_OldReflectionTextureSize=0;

private static bool s_InsideRendering=false;

// This is called when it's known that the object will be rendered by some

// camera. We render reflections and do other updates here.

// Because the script executes in edit mode,reflections for the scene view

// camera will just work!

public void OnWillRenderObject()

{if(!enabled || !renderer || !renderer.sharedMaterial || !renderer.enabled )return;

Camera cam=Camera.current;

if(!cam )return;

// Safeguard from recursive reflections.

if(s_InsideRendering )return;

s_InsideRendering=true;

Camera reflectionCamera;

CreateMirrorObjects(cam,out reflectionCamera );

// find out the reflection plane:position and normal in world space

Vector3 pos=transform.position;

Vector3 normal=transform.up;

// Optionally disable pixel lights for reflection

int oldPixelLightCount=QualitySettings.pixelLightCount;

if(m_DisablePixelLights )QualitySettings.pixelLightCount=0;

UpdateCameraModes(cam,reflectionCamera );

// Render reflection

// Reflect camera around reflection plane

float d=-Vector3.Dot(normal,pos)-m_ClipPlaneOffset;

Vector4 reflectionPlane=new Vector4(normal.x,normal.y,normal.z,d);

Matrix4x4 reflection=Matrix4x4.zero;

CalculateReflectionMatrix(ref reflection,reflectionPlane);

Vector3 oldpos=cam.transform.position;

Vector3 newpos=reflection.MultiplyPoint(oldpos );

reflectionCamera.worldToCameraMatrix=cam.worldToCameraMatrix * reflection;

// Setup oblique projection matrix so that near plane is our reflection

// plane. This way we clip everything below/above it for free.

Vector4 clipPlane=CameraSpacePlane(reflectionCamera,pos,normal,1.0f );

Matrix4x4 projection=cam.projectionMatrix;

CalculateObliqueMatrix(ref projection,clipPlane);

reflectionCamera.projectionMatrix=projection;

reflectionCamera.cullingMask=~(1

reflectionCamera.targetTexture=m_ReflectionTexture;

GL.SetRevertBackfacing(true);

reflectionCamera.transform.position=newpos;

Vector3 euler=cam.transform.eulerAngles;

reflectionCamera.transform.eulerAngles=new Vector3(0,euler.y,euler.z);

reflectionCamera.Render();

reflectionCamera.transform.position=oldpos;

GL.SetRevertBackfacing(false);

Material[]materials=renderer.sharedMaterials;

foreach(Material mat in materials ){

if(mat.HasProperty("_ReflectionTex"))

mat.SetTexture("_ReflectionTex",m_ReflectionTexture );

}

// Set matrix on the shader that transforms UVs from object space into screen

// space. We want to just project reflection texture on screen.

Matrix4x4 scaleOffset=Matrix4x4.TRS(

new Vector3(0.5f,0.5f,0.5f),Quaternion.identity,new Vector3(0.5f,0.5f,0.5f));

Vector3 scale=transform.lossyScale;

Matrix4x4 mtx=transform.localToWorldMatrix * Matrix4x4.Scale(new Vector3(1.0f/scale.x,1.0f/scale.y,1.0f/scale.z));

mtx=scaleOffset * cam.projectionMatrix * cam.worldToCameraMatrix * mtx;

foreach(Material mat in materials ){

mat.SetMatrix("_ProjMatrix",mtx );

}

// Restore pixel light count

if(m_DisablePixelLights )

QualitySettings.pixelLightCount=oldPixelLightCount;

s_InsideRendering=false;

}

// Cleanup all the objects we possibly have created

void OnDisable()

{

if(m_ReflectionTexture ){

DestroyImmediate(m_ReflectionTexture );

m_ReflectionTexture=null;

}

foreach(DictionaryEntry kvp in m_ReflectionCameras )

DestroyImmediate(((Camera)kvp.Value).gameObject );

m_ReflectionCameras.Clear();

}

private void UpdateCameraModes(Camera src,Camera dest )

{

if(dest==null )

return;

// set camera to clear the same way as current camera

dest.clearFlags=src.clearFlags;

dest.backgroundColor=src.backgroundColor;

if(src.clearFlags==CameraClearFlags.Skybox )

{

Skybox sky=src.GetComponent(typeof(Skybox))as Skybox;

Skybox mysky=dest.GetComponent(typeof(Skybox))as Skybox;

if(!sky || !sky.material ){

mysky.enabled=false;

}

else

{

mysky.enabled=true;

mysky.material=sky.material;

}

}

// update other values to match current camera.

// even if we are supplying custom camera&projection matrices,

// some of values are used elsewhere(e.g. skybox uses far plane)

dest.farClipPlane=src.farClipPlane;

dest.nearClipPlane=src.nearClipPlane;

dest.orthographic=src.orthographic;

dest.fieldOfView=src.fieldOfView;

dest.aspect=src.aspect;

dest.orthographicSize=src.orthographicSize;

}

// On-demand create any objects we need

private void CreateMirrorObjects(Camera currentCamera,out Camera reflectionCamera ) {

reflectionCamera=null;

// Reflection render texture

if(!m_ReflectionTexture || m_OldReflectionTextureSize !=m_TextureSize )

{

if(m_ReflectionTexture )

DestroyImmediate(m_ReflectionTexture );

m_ReflectionTexture=new RenderTexture(m_TextureSize,m_TextureSize,16 );

m_ReflectionTexture.name="__MirrorReflection" + GetInstanceID();

m_ReflectionTexture.isPowerOfTwo=true;

m_ReflectionTexture.hideFlags=HideFlags.DontSave;

m_OldReflectionTextureSize=m_TextureSize;

}

// Camera for reflection

reflectionCamera=m_ReflectionCameras[currentCamera]as Camera;

if(!reflectionCamera )// catch both not-in-dictionary and in-dictionary-but-deleted-GO

{

GameObject go=new GameObject("Mirror Refl Camera id" + GetInstanceID()+ " for " + currentCamera.GetInstanceID(),typeof(Camera),typeof(Skybox));

reflectionCamera=go.camera;

reflectionCamera.enabled=false;

reflectionCamera.transform.position=transform.position;

reflectionCamera.transform.rotation=transform.rotation;

reflectionCamera.gameObject.AddComponent("FlareLayer");

go.hideFlags=HideFlags.HideAndDontSave;

m_ReflectionCameras[currentCamera]=reflectionCamera;

}

}

// Extended sign:returns -1,0 or 1 based on sign of a

private static float sgn(float a)

{if(a>0.0f)return 1.0f;

if(a

return 0.0f;

}

// Given position/normal of the plane,calculates plane in camera space.

private Vector4 CameraSpacePlane(Camera cam,Vector3 pos,Vector3 normal,float sideSign)

{

Vector3 offsetPos=pos + normal * m_ClipPlaneOffset;

Matrix4x4 m=cam.worldToCameraMatrix;

Vector3 cpos=m.MultiplyPoint(offsetPos );

Vector3 cnormal=m.MultiplyVector(normal ).normalized * sideSign;

return new Vector4(cnormal.x,cnormal.y,cnormal.z,-Vector3.Dot(cpos,cnormal));

}

//调整给定的射影矩阵以便最近的平面Adjusts the given projection matrix so that near plane is the given clipPlane

// clipPlane is given in camera space. See article in Game Programming Gems 5.

private static void CalculateObliqueMatrix(ref Matrix4x4 projection,Vector4 clipPlane) {Vector4 q=projection.inverse * new Vector4(sgn(clipPlane.x),sgn(clipPlane.y),1.0f,1.0f); Vector4 c=clipPlane *(2.0F /(Vector4.Dot(clipPlane,q)));

// third row=clip plane -fourth row

projection[2]=c.x -projection[3];

projection[6]=c.y -projection[7];

projection[10]=c.z -projection[11];

projection[14]=c.w -projection[15];

}

//围绕给定的平面计算折射矩阵

private static void CalculateReflectionMatrix(ref Matrix4x4 reflectionMat,Vector4 plane) {reflectionMat.m00=(1F -2F*plane[0]*plane[0]);

reflectionMat.m01=(-2F*plane[0]*plane[1]);

reflectionMat.m02=(-2F*plane[0]*plane[2]);

reflectionMat.m03=(-2F*plane[3]*plane[0]);

reflectionMat.m10=(-2F*plane[1]*plane[0]);

reflectionMat.m11=(1F -2F*plane[1]*plane[1]);

reflectionMat.m12=(-2F*plane[1]*plane[2]);

reflectionMat.m13=(-2F*plane[3]*plane[1]);

} reflectionMat.m21=(-2F*plane[2]*plane[1]); reflectionMat.m22=(1F -2F*plane[2]*plane[2]); reflectionMat.m23=(-2F*plane[3]*plane[2]); reflectionMat.m30=0F; reflectionMat.m31=0F; reflectionMat.m32=0F; reflectionMat.m33=1F; }


相关文章

  • 光的反射练习题
  • 一.选择题 1.阳光灿烂的日子,在茂密的树林下,常能在地上见到许多圆形的光斑,这些光斑是( ) A.太阳的虚像 B.太阳的实像 C.树叶的影子 D.树叶的实像 2.光从空气中进入水中,光的传播速度( ) A.会减小 B.不变 C.会增大 D ...查看


  • 5.2光的反射
  • 5.2 光的反射 课程目标 1. 认识光反射的规律,了解法线.入射光线.反射光线.入射角.反射角的含义. 2. 理解光的反射定律,理解反射现象中光路的可逆性. 3. 知道镜面反射和漫反射的区别及其应用. 4. 会根据光的反射定律绘图. 知识 ...查看


  • 初二物理第四章课上习题答案
  • 初二物理第四章课上练习 1. 小明同学在课外用易拉罐做成如图1所示的装置做小孔成像实验,如果易拉罐 底部有一个很小的三角形小孔,则他在半透明纸上看到的像是:( B ) A .蜡烛的正立像 B .蜡烛的倒立像 C .三角形光斑 D .圆形光斑 ...查看


  • 8年级上物理课课练3
  • §4.1 光的色彩 颜色 一. 填空题 1.太阳.月亮.镜子,其中属于光源的是; 光源可以分为 和 两种. 2.光的三原色是.., 颜料的三原色是3.我国唐朝的张志和在<玄贞子>中记载了著名的"人工虹"实验, ...查看


  • 试卷命题与分析
  • 八年级物理第二章<光现象>测验题 命题计划与试卷分析 一.考试目的: 1.考查学生在第二章里的学习成就.教师完成教学目标的程度: 2.检查学生在一段时间内(第二章光现象的学习期间)对所学知识的掌握程度: 3.激发学生的学习行为. ...查看


  • 4.2光的反射
  • 教学设计 第2节 光的反射 整体设计 光的反射是本教材中第一个比较完整的探究实验,对学生的物理学习是一个很重要的开端,既要引导学生学习如何开展探究实验,又要让学生体验物理探究的乐趣,与九年义务教育物理教材相比,课程标准降低了教学要求,由原来 ...查看


  • [光现象]测试题
  • 光现象单元测试题 班级_________ 姓名_________ 学号_________ 成绩__________ 一 .填空题(每空1分,共27分) 1.影子和平面镜成像的原理不同,影子是光的 形成的,平面镜成像是光的 形成的. 2.光的 ...查看


  • 旋转抛物面误差对聚光性能的影响
  • 第30卷第4期 2009年4月 太阳能学报 ACI.A口Ⅲ£RCL^E V01.30,No.4Apr.,2009 sIm^RIs鲫ICA 旋转抛物面误差对聚光性能的影响 成 珂1,韩 迪2 (1.西北工业大学空调制冷与太阳能应用研究所,西安 ...查看


  • 八年级物理光的反射练习题
  • 光的反射 一.选择题 (1)关于光的反射,下列说法错误的是( ) A .反射光线跟入射光线和法线在同一平面内B .反射光线和入射光线分居在法线的两侧C .入射角增大,反射角也同样增大D .入射角大于反射角 (2)入射光线与反射光线间的夹角为 ...查看


热门内容