layout: post
title: “中级Shader教程09 3D Raymarch框架”
date: 2018-04-22 16:09:03
author: Jiepeng Tan
categories:
- shader tutorial
tags: shader_tutorial 3D_Raymarch shader
img_path: /assets/img/blog/ShaderTutorial2D/Snow
mathjax: true
Shader 视频教程
终于,我们暂时结束了2D,进入了令人兴奋的3D!!
在2D的屏幕中,绘制3D场景----升维进化!相信我,当你搞定了3D,再回头看2Dshader,你会想起一句广告词,so easy!妈妈再也不用担心我们的shader了.
1.3D Raymarch框架
- 获得相机位置ro
- 根据相机位置和朝向,计算当前像素所发出的射线ray的方向rd(ray dir)
- 求交ray和场景的碰撞点p(两种方式)
3.1 直接算式求解(比如射线到一个简单的圆的交点)
3.2 使用raymarching方式即一步步的递进ray,直到ray碰到场景,或达到ray的最大距离。
- 求得p处的法线和材质信息
- 根据4得到的信息求的p处的颜色
举个Raymarching方式例子:
// create by JiepengTan
// date:2018-04-12
// email: jiepengtan@gmail.com
Shader "FishManShaderTutorial/RayMarchSimpleScene"{
Properties {
_MainTex ("Texture", 2D) = "white" {
}
}
SubShader{
Tags {
"RenderType"="Opaque" }
LOD 100
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
//#include "ShaderLibs/Noise.cginc"
struct appdata{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v){
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
#define SPHERE_ID (1.0)
#define FLOOR_ID (2.0)
#define lightDir (normalize(float3(5.,3.0,-1.0)))
float MapSphere(float3 pos){
// center at float3(0.,0.,0.);
float radius = 0.5;
float3 centerPos = float3(0.,1.0+ sin(_Time.y*1.)*0.5,0.);
return length(pos-centerPos) - radius;
}
float MapFloor(float3 pos ){
float3 n= float3(0.,1.,0.);
float3 d = 0;
return dot(n,pos)-d;
}
float2 Map(float3 pos){
float dist2Sphere = MapSphere(pos);// ID 1
float dist2Plane = MapFloor(pos); // ID 2
if(dist2Plane < dist2Sphere) {
return float2(dist2Plane,FLOOR_ID);
}else{
return float2(dist2Sphere,SPHERE_ID);
}
}
#define MARCH_NUM 256 //最多光线检测次数
float2 RayCast(float3 ro,float3 rd){
float tmin = 0.1;
float tmax = 20.0;
float t = tmin;
float2 res = float2(