[体渲染]渲染一个球体 圆由大到小,最后渲染成方形

思路

· 这个体渲染并不是投射射线的体渲染。以后会写常规体渲染给大家。

· 判断射线位置

[体渲染]渲染一个球体 圆由大到小,最后渲染成方形_第1张图片 

我们知道视线的角度normalize(u),和 视线和球心的距离u`(_SpherePos - _CameraPos)

 

通过投影的逆运算,我们能求出视角U未来在球心垂面上的点位置。

 

 

: p = normalize(U) · normalize(U`) * |U|

未来的位置为:视角法向量 点乘 视角和球心的法向量 乘以 视角和球心的模长,推导公式学了投影向量自然就会了,这里不累述。

 

然后通过对比 p和球心的长度是否小于半径,就可以实现简单的画圆。

 

· 求出球面法线向量

[体渲染]渲染一个球体 圆由大到小,最后渲染成方形_第2张图片 

 

如果要在球体上使用光照模型,必然需要知道法线向量。

 

我们知道了坐标和半径的比值,通过反sin或者反cos值得到弧度,然后求弧度在π/2的比例就可以得出法向量的差值,进行视角向量和位置向量的插值运算即可。

 

 

 

源代码

 

Shader "QQ/Volume/Sphere" 

{ 

    Properties 

    { 

        _Color("Color",Color) = (0.5,0.5,0.5,1) 

        _Radius("radius",Range(0,1)) = 0.4 

        _Smoothness("smoothness",Range(0.1,1)) = 0.5 

   

    } 

        SubShader 

    { 

        Tags { "RenderType" = "Opaque"} 

        LOD 100 

   

        Pass 

        { 

        Tags{ 

        "LightMode" = "ForwardBase" 

            } 

            CGPROGRAM 

            #pragma vertex vert 

            #pragma fragment frag 

            #include "UnityCG.cginc" 

            uniform fixed4 _Color; 

            uniform float _Radius; 

            uniform float _Smoothness; 

            uniform fixed4 _LightColor0

            struct a2

            { 

                float4 vertex : POSITION; 

                float3 normal : NORMAL; 

            }

   

            struct v2

            { 

                float4 pos : SV_POSITION; 

                float3 wPos:TEXCOORD0

                float3 normal : TEXCOORD1

            }

   

            v2f vert(a2v v) 

            { 

                v2f o; 

                o.pos = mul(UNITY_MATRIX_MVP, v.vertex)

                o.wPos = mul(unity_ObjectToWorld,v.vertex)

                o.normal = v.normal; 

                return o; 

            } 

   

            inline float3 ToLocal(float3 pos) 

            { 

                return mul(unity_WorldToObject, float4(pos, 1.0)).xyz; 

            } 

   

            fixed4 frag(v2f i) : SV_Target 

            { 

                fixed4 col; 

                float3 pos = ToLocal(i.wPos)

                float3 nor = UnityObjectToWorldNormal(i.normal)

                float _i = length(pos) / _Radius; 

                if (_i > 1) 

                { 

                    float3 camera = ToLocal(_WorldSpaceCameraPos.xyz)

                    float3 dir = normalize(pos - camera)

                    float len0 = distance(pos, camera)

                    float len1 = length(camera) * dot(dir, normalize(-camera))

                    if (len1 > len0) 

                    { 

                        pos = dir * len1 + camera; 

                        _i = length(pos) / _Radius; 

                        float3 dir0 = normalize(pos)

                        float3 dir1 = normalize(camera)

                        nor = UnityObjectToWorldNormal(normalize(lerp(dir1, dir0, asin(_i) / UNITY_PI * 2)))

                    } 

                } 

                if (_i <= 1) 

                { 

                    float3 wPos = mul(unity_ObjectToWorld, pos)

                    float LdotN = max(dot(_WorldSpaceLightPos0.xyz, nor), 0)

                    float3 Half = normalize(normalize(_WorldSpaceLightPos0.xyz) + normalize(_WorldSpaceCameraPos.xyz - wPos))

                    float spec = pow(max(dot(nor, Half),0), _Smoothness * _Smoothness * 1000)

                    col = _Color * fixed4(UNITY_LIGHTMODEL_AMBIENT.rgb, 1.0) + (LdotN + spec) * fixed4(_LightColor0.rgb,1.0)

                } 

                else 

                { 

                    discard; 

                } 

            return col; 

            } 

    ENDCG 

    } 

    } 

}

 

你可能感兴趣的:(C#,Unity,渲染)