【问题标题】:How to apply cubemap to inverse of a sphere in Unity 3D如何在 Unity 3D 中将立方体贴图应用于球体的反转
【发布时间】:2016-11-27 21:44:27
【问题描述】:

我正在尝试将 .jpg 纹理应用到球体图元(倒置球体)的内部,以制作用于 VR 的简单 3D 光球,但我遇到了问题。我正在使用统一 5.4

我导入 360 度全景 .jpg 纹理,将其纹理类型设置为立方体贴图,并将其映射设置为经度/纬度(圆柱)。

我创建了一个新材质,我可以在材质的着色器下拉菜单中找到的唯一立方体贴图着色器是天空盒/立方体贴图。我选择了它,但它不会让我将材质分配给球体。我可以将它分配给背景,但我需要它在球体上,我做错了什么?如何将立方体贴图纹理应用到可以应用于倒置球体的材质上?

【问题讨论】:

    标签: unity3d unity5 virtual-reality


    【解决方案1】:

    这是一个可能有帮助的着色器

    Shader "Flipping Normals" {
        Properties {
            _MainTex ("Base (RGB)", 2D) = "white" {}
        }
        SubShader {
    
            Tags { "RenderType" = "Opaque" }
    
            Cull Off
    
            CGPROGRAM
    
            #pragma surface surf Lambert vertex:vert
            sampler2D _MainTex;
    
            struct Input {
                float2 uv_MainTex;
                float4 color : COLOR;
            };
    
            void vert(inout appdata_full v) {
                v.normal.xyz = v.normal * -1;
            }
    
            void surf (Input IN, inout SurfaceOutput o) {
                 fixed3 result = tex2D(_MainTex, IN.uv_MainTex);
                 o.Albedo = result.rgb;
                 o.Alpha = 1;
            }
    
            ENDCG
    
        }
    
          Fallback "Diffuse"
    }

    【讨论】:

      【解决方案2】:

      着色器代码归功于 Unity 论坛上的用户 Bgolushttps://forum.unity.com/threads/cube-mapped-sphere-aka-quad-sphere-asset.292860/#post-2708001

      该论坛帖子中的着色器代码将允许将立方体贴图渲染成球体和立方体。

      我对该代码所做的唯一补充是将Cull Front 添加到着色器中以使网格看起来正常反转,并且您可以使用 Unity 的内置球体作为网格。

      Shader "Unlit/InverseCullCubeMapShader"
      {
          Properties
          {
              _CubeMap( "Cube Map", Cube ) = "white" {}
          }
          SubShader
          {
              Pass 
              {
                  Tags { "DisableBatching" = "True" }
      
                  Cull Front
      
                  CGPROGRAM
                  #pragma vertex vert
                  #pragma fragment frag
                  #include "UnityCG.cginc"
              
                  samplerCUBE _CubeMap;
              
                  struct v2f 
                  {
                      float4 pos : SV_Position;
                      half3 uv : TEXCOORD0;
                  };
              
                  v2f vert( appdata_img v )
                  {
                      v2f o;
                      o.pos = UnityObjectToClipPos( v.vertex );
                      o.uv = v.vertex.xyz * half3(-1,1,1); // mirror so cubemap projects as expected
                      return o;
                  }
              
                  fixed4 frag( v2f i ) : SV_Target 
                  {
                      return texCUBE( _CubeMap, i.uv );
                  }
                  ENDCG
              }
          }
      }

      【讨论】:

        【解决方案3】:

        这是一个组件形式的非着色器解决方案,它将为您反转球体的法线,然后您可以简单地应用您提到的任何 equirectangular 纹理。我假设你需要一个球体的内部,这样你就可以与全景图中的实际几何体/区域进行交互(这也是我写这篇文章的原因)。

        using System.Collections;
        using System.Collections.Generic;
        using UnityEngine;
        
        [RequireComponent(typeof(MeshFilter))]
        public class InvertNormals : BaseView
        {
            void Start()
                {
                    // Firstly, we grab this object's mesh filter component
                    MeshFilter filter = gameObject.GetComponent<MeshFilter>();
        
                    if (filter != null)
                    {
                        // Now that we have the mesh filter component, we can grab the
                        topology itself...
                        Mesh skyboxSphereMesh = filter.mesh;
        
                        // ...and cache all of its normals into an array of Vector3 values
                        Vector3[] normals = skyboxSphereMesh.normals;
        
                        // We iterate over the array and negate (-x, -y, -z) each vector...
                        // https://docs.unity3d.com/ScriptReference/Vector3-operator_subtract.html
                        // ...then re-assign the value
                        for (int i = 0; i < normals.Length; i++)
                            normals[i] = -normals[i];
        
                        // Re-assign all of our inverted normal values to the mesh
                        skyboxSphereMesh.normals = normals;
        
                        // Now we need to iterate over all of the submeshes, each index
                        // referring to a list of triangles/trigons, which refer to a set
                        // of vertices in 3D space 
                        for (int i = 0; i < skyboxSphereMesh.subMeshCount; i++)
                        {
                            // Firstly, we cache the triangles...
                            int[] triangles = skyboxSphereMesh.GetTriangles(i);
                            // ...then iterate over the values, incrementing our count by 3 each time
                            for (int j = 0; j < triangles.Length; j += 3)
                            {
                                // We're offsetting the index array here and not the actual vertex array,
                                // this might cause problems with UVs down the line!
                                int temp = triangles[j + 0]; // Unity Forum magic per-vertex offset
                                triangles[j + 0] = triangles[j + 1];
                                triangles[j + 1] = temp;
                            }
                            // Re-assign the mesh with a new set of triangle indices at the current submesh
                            skyboxSphereMesh.SetTriangles(triangles, i);
                       }
                    }
                }
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-08-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多