延迟渲染里为什么i.ray = lerp(UnityObjectToViewPos(v.vertex)) * float(-1, -1, 1)里要乘 float3(-1, -1, 1)

下面是built-in着色器的源码:

为什么i.ray = lerp(UnityObjectToViewPos(v.vertex)) * float(-1, -1, 1)里要乘 float3(-1, -1, 1)?请看代码下面的注释

 

#pragma vertex vert_deferred
#pragma fragment frag

struct unity_v2f_deferred {
    float4 pos : SV_POSITION;
    float4 uv : TEXCOORD0;
    float3 ray : TEXCOORD1;
};

float _LightAsQuad;

// 顶点着色器
unity_v2f_deferred vert_deferred (float4 vertex : POSITION, float3 normal : NORMAL)
{
    unity_v2f_deferred o;
    o.pos = UnityObjectToClipPos(vertex);
    o.uv = ComputeScreenPos(o.pos);
    // 乘以float3(-1, -1, 1)是为了配合片元着色器里面(UnityDeferredCalculateLightParams函数第一行)计算rayToFarPlane的操作,
    //因为视口空间是右手坐标系,摄像机前的坐标z值都是负数,而_ProjectionParams.z(far)是正数。
    // 例如所以当视口坐标(-1,-1,-1)代入i.ray * _ProjectionParam.z / i.ray.z之后x和y会变成正数(相反数),
    //所以在这里提前反转一下x和y,以免后续计算错误。而这里乘float3(1, 1, -1)同样可以避免错误。
    o.ray = UnityObjectToViewPos(vertex) * float3(-1,-1,1); 

    // normal contains a ray pointing from the camera to one of near plane's
    // corners in camera space when we are drawing a full screen quad.
    // Otherwise, when rendering 3D shapes, use the ray calculated here.
    o.ray = lerp(o.ray, normal, _LightAsQuad);

    return o;
}

#ifdef UNITY_HDR_ON
half4
#else
fixed4
#endif
// 片元着色器
frag (unity_v2f_deferred i) : SV_Target
{
    half4 c = CalculateLight(i);
    #ifdef UNITY_HDR_ON
    return c;
    #else
    return exp2(-c);
    #endif
}

half4 CalculateLight (unity_v2f_deferred i)
{
    float3 wpos;
    float2 uv;
    float atten, fadeDist;
    UnityLight light;
    UNITY_INITIALIZE_OUTPUT(UnityLight, light);
    UnityDeferredCalculateLightParams (i, wpos, uv, light.dir, atten, fadeDist);

    light.color = _LightColor.rgb * atten;

    // unpack Gbuffer
    half4 gbuffer0 = tex2D (_CameraGBufferTexture0, uv);
    half4 gbuffer1 = tex2D (_CameraGBufferTexture1, uv);
    half4 gbuffer2 = tex2D (_CameraGBufferTexture2, uv);
    UnityStandardData data = UnityStandardDataFromGbuffer(gbuffer0, gbuffer1, gbuffer2);

    float3 eyeVec = normalize(wpos-_WorldSpaceCameraPos);
    half oneMinusReflectivity = 1 - SpecularStrength(data.specularColor.rgb);

    UnityIndirect ind;
    UNITY_INITIALIZE_OUTPUT(UnityIndirect, ind);
    ind.diffuse = 0;
    ind.specular = 0;

    half4 res = UNITY_BRDF_PBS (data.diffuseColor, data.specularColor, oneMinusReflectivity, data.smoothness, data.normalWorld, -eyeVec, light, ind);

    return res;
}

void UnityDeferredCalculateLightParams (
    unity_v2f_deferred i,
    out float3 outWorldPos,
    out float2 outUV,
    out half3 outLightDir,
    out float outAtten,
    out float outFadeDist)
{
    i.ray = i.ray * (_ProjectionParams.z / i.ray.z); // 得到摄像机到远裁切面方向向量
    float2 uv = i.uv.xy / i.uv.w;

    // read depth and reconstruct world position
    float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);
    depth = Linear01Depth (depth);
    float4 vpos = float4(i.ray * depth,1);
    float3 wpos = mul (unity_CameraToWorld, vpos).xyz; // 这里的vpos不是视口空间坐标,而是z值反转的视口空间坐标。详细解析:https://blog.csdn.net/zengjunjie59/article/details/113033567

    float fadeDist = UnityComputeShadowFadeDistance(wpos, vpos.z);

    // spot light case
    #if defined (SPOT)
        float3 tolight = _LightPos.xyz - wpos;
        half3 lightDir = normalize (tolight);

        float4 uvCookie = mul (unity_WorldToLight, float4(wpos,1));
        // negative bias because http://aras-p.info/blog/2010/01/07/screenspace-vs-mip-mapping/
        float atten = tex2Dbias (_LightTexture0, float4(uvCookie.xy / uvCookie.w, 0, -8)).w;
        atten *= uvCookie.w < 0;
        float att = dot(tolight, tolight) * _LightPos.w;
        atten *= tex2D (_LightTextureB0, att.rr).r;

        atten *= UnityDeferredComputeShadow (wpos, fadeDist, uv);

    // directional light case
    #elif defined (DIRECTIONAL) || defined (DIRECTIONAL_COOKIE)
        half3 lightDir = -_LightDir.xyz;
        float atten = 1.0;

        atten *= UnityDeferredComputeShadow (wpos, fadeDist, uv);

        #if defined (DIRECTIONAL_COOKIE)
        atten *= tex2Dbias (_LightTexture0, float4(mul(unity_WorldToLight, half4(wpos,1)).xy, 0, -8)).w;
        #endif //DIRECTIONAL_COOKIE

    // point light case
    #elif defined (POINT) || defined (POINT_COOKIE)
        float3 tolight = wpos - _LightPos.xyz;
        half3 lightDir = -normalize (tolight);

        float att = dot(tolight, tolight) * _LightPos.w;
        float atten = tex2D (_LightTextureB0, att.rr).r;

        atten *= UnityDeferredComputeShadow (tolight, fadeDist, uv);

        #if defined (POINT_COOKIE)
        atten *= texCUBEbias(_LightTexture0, float4(mul(unity_WorldToLight, half4(wpos,1)).xyz, -8)).w;
        #endif //POINT_COOKIE
    #else
        half3 lightDir = 0;
        float atten = 0;
    #endif

    outWorldPos = wpos;
    outUV = uv;
    outLightDir = lightDir;
    outAtten = atten;
    outFadeDist = fadeDist;
}

 

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
判断右键是否按下 if (Input.GetMouseButton(1)) { 获取鼠标在水平和垂直方向上的移动距离 float mouseX = Input.GetAxis(“Mouse X”); float mouseY = Input.GetAxis(“Mouse Y”); currentRotationY += mouseX * rotationSpeed; currentRotationX -= mouseY * rotationSpeed; float targetRotationY = currentRotationY + mouseX * rotationSpeed; float targetRotationX = currentRotationX - mouseY * rotationSpeed; // 限制上下旋转的角度 currentRotationX = Mathf.Clamp(currentRotationX, minYAngle, maxYAngle); // 使用平滑插值逐渐改变当前旋转角度到目标旋转角度 currentRotationY = Mathf.Lerp(currentRotationY, targetRotationY, rotationSmoothness * Time.deltaTime); currentRotationX = Mathf.Lerp(currentRotationX, targetRotationX, rotationSmoothness * Time.deltaTime); float targetDistance = Mathf.Lerp(0.5f, distance, (currentRotationX - minYAngle) / (maxYAngle - minYAngle)); float newDistance = Mathf.Lerp(distance, targetDistance, rotationSmoothness * Time.deltaTime); transform.position = target.position - transform.forward * newDistance; // 设置摄像机的旋转 Quaternion yRotation = Quaternion.Euler(0, currentRotationY, 0); Quaternion xRotation = Quaternion.Euler(currentRotationX, 0, 0); Quaternion rotation = initialRotation * yRotation * xRotation; transform.rotation = rotation; }Vector3 direction =this.transform.position- target.position; Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance); Vector3 position = transform.rotation * negDistance + target.position; //Vector3 vertexPosition = target.position + target.up * distance; // // 从玩家的位置沿着朝向摄像机发出射线 Ray ray = new Ray(target.position, direction.normalized); if (Physics.Raycast(ray, out hit,distance)) { //Debug.DrawRay(target.position, vertexPosition, Color.red); if (hit.collider.gameObject != target.gameObject) { transform.position = transform.rotation* new Vector3(0.0f, 0.0f, -Vector3.Distance(hit.point, target.position)) + target.position; //transform.position=hit.point; } else { //transform.position = position; } } else { transform.position = position; }这段代码摄像机会一会正常位置,一会到玩家身上,怎么修改
07-13

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值