精华内容
下载资源
问答
  • HDRI转换为Cubemap 从全景图像生成6个立方体贴图纹理 依存关系 枕头 麻木 意象 HDR处理的FreeImage扩展 Python版本 在3.7、3.6上测试 这个怎么运作 使用来自立方体贴图的UV,将其转换为球形矢量以采样球形全景图。 ...
  • HDRI到立方体贴图 它将球形贴图转换为立方体贴图 实时版本 只需上传球形地图(.hdr,.png,.jpg)=>查看预览(您可以同时旋转它们)=>保存 您可以在获得一些球形贴图 在本地运行 它在localhost上的工作方式更好,我...
  • 实现将2:1全景图(矩形球面投影equirectangular)划分成即将要进行的cubemap所需要的6个纹理面,附件代码只是一个简单的划分例子,仅供入门参考,集成开发环境是vs2010,可以直接打开运行看效果。如果想实现更为复杂...
  • import { panorama2Cubemap } from '@littlecabbage/panorama-to-cubemap' import panorama from './panorama.png' const options = { output : 'jpeg' , interpolation : 'lanczos' , } ; panorama2Cubemap ( ...
  • 起因:我们将一张外部的jpg导入UE4后,会在资源管理器中生成Texture纹理贴图资源,然后需要将Texture纹理贴图导出成HDR,之后再将HDR导入UE4中,才会生成Texture Cube格式。如果原始jpg分辨率高,图片多的话,整个...

    VS:2019

    虚幻引擎:4.25

    Python:官方2.7版本

    目的:通过加载外部的jpg全景图,直接在UE4中生成Texture Cube格式

    起因:我们将一张外部的jpg导入UE4后,会在资源管理器中生成Texture纹理贴图资源,然后需要将Texture纹理贴图导出成HDR,之后再将HDR导入UE4中,才会生成Texture Cube格式。如果原始jpg分辨率高,图片多的话,整个流程会特别慢。

    思路:分成两部分,第一部分通过读取jpg图片数据,直接在内存中生成Texture2D。第二部分我们可以通过SceneCaptureCube这个组件,去渲染球体场景,来填充RenderTargetCube,进而生成Texture Cube格式。而球体场景可以通过第一部分的Texture2D,作为球体材质实例的图片。

    一、场景:
    在这里插入图片描述
    在这里插入图片描述
    Content/RenderTargetCube目录说明:

    • M_Sphere是母材质
    • MI_Sphere是材质实例
    • T_Init是初始的材质贴图
    • RTC_Sphere是场景中SceneCaptureCube需要用到的RenderTargetCube

    场景说明:

    • 场景里有个Sphere的静态模型,我们给它赋上自己创建的材质实例,注意Sphere模型的Scale值,z是-5和镜像有关。
    • 场景在球心的位置有一个SceneCaptureCube这个Actor,设置它的TextureTarget,以及一些设置,记得勾选CaptureRotation让旋转生效。然后注意它的Rotation,也是和镜像相关。

    二、代码:

    • 加载jpg,创建Texture2D,并修改MI_Sphere材质实例的贴图

    .h

    UFUNCTION(BlueprintCallable)
    	static UTexture2D* LoadTexture(UMaterialInstanceConstant* _MaterialInstanceConstant,const FString _Path, bool& _IsValid, int32& _OutWidth, int32& _OutHeight);
    

    .cpp

    static TSharedPtr<IImageWrapper> GetImageWrapperByExtention(const FString InImagePath)
    {
    	IImageWrapperModule& mImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
    	if (InImagePath.EndsWith(".png"))
    	{
    		return mImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);
    	}
    	else if (InImagePath.EndsWith(".jpg") || InImagePath.EndsWith(".jpeg"))
    	{
    		return mImageWrapperModule.CreateImageWrapper(EImageFormat::JPEG);
    	}
    	else if (InImagePath.EndsWith(".bmp"))
    	{
    		return mImageWrapperModule.CreateImageWrapper(EImageFormat::BMP);
    	}
    	else if (InImagePath.EndsWith(".ico"))
    	{
    		return mImageWrapperModule.CreateImageWrapper(EImageFormat::ICO);
    
    	}
    	else if (InImagePath.EndsWith("exr"))
    	{
    		return mImageWrapperModule.CreateImageWrapper(EImageFormat::EXR);
    	}
    	else if (InImagePath.EndsWith(".icns"))
    	{
    		return mImageWrapperModule.CreateImageWrapper(EImageFormat::ICNS);
    	}
    	return nullptr;
    }
    
    UTexture2D* UExportTextureFunctionLibrary::LoadTexture(UMaterialInstanceConstant* _MaterialInstanceConstant, const FString _Path, bool& _IsValid, int32& _OutWidth, int32& _OutHeight)
    {
    	UTexture2D* mTexture2D = nullptr;
    
    	_IsValid = false;
    
    	// 判断路径下是否存在图片.
    	if (!FPlatformFileManager::Get().GetPlatformFile().FileExists(*_Path))
    	{
    		return nullptr;
    	}
    
    	// 从文件中加载压缩的字节数据.
    	TArray<uint8> mRawFileData;
    	if (!FFileHelper::LoadFileToArray(mRawFileData, *_Path))
    	{
    		return nullptr;
    	}
    
    	// 使用ImageWrapper模块检测图像类型.
    	TSharedPtr<IImageWrapper> ImageWrapper = GetImageWrapperByExtention(_Path);
    
    	// 解压图像数据.
    	if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(mRawFileData.GetData(), mRawFileData.Num()))
    	{
    		TArray<uint8> mUnCompressedRGBA;
    
    		if (ImageWrapper->GetRaw(ERGBFormat::BGRA, 8, mUnCompressedRGBA))
    		{
    			// 创建Texture2D.
    			mTexture2D = UTexture2D::CreateTransient(ImageWrapper->GetWidth(), ImageWrapper->GetHeight(), PF_B8G8R8A8);
    			
    			if (mTexture2D != nullptr)
    			{
    				_IsValid = true;
    
    				_OutWidth = ImageWrapper->GetWidth();
    
    				_OutHeight = ImageWrapper->GetHeight();
    
    				void* TextureData = mTexture2D->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
    
    				FMemory::Memcpy(TextureData, mUnCompressedRGBA.GetData(), mUnCompressedRGBA.Num());
    
    				mTexture2D->PlatformData->Mips[0].BulkData.Unlock();
    
    				mTexture2D->UpdateResource();
    			}
    		}
    	}
    	// 修改MI_Sphere材质实例的贴图.
    	if(mTexture2D)
    		UMaterialEditingLibrary::SetMaterialInstanceTextureParameterValue(_MaterialInstanceConstant, FName(TEXT("Texture")), mTexture2D);
    
    	return mTexture2D;
    }
    
    • 刷新SceneCaptureCube,将最新的RTC_Sphere创建TextureCube

    .h

    UFUNCTION(BlueprintCallable)
    	static void CreateCubemap(class UTextureRenderTargetCube* _TextureRenderTargetCube, FString _PackagePath, FString _AssetName);
    

    .cpp

    void UExportTextureFunctionLibrary::CreateCubemap(class UTextureRenderTargetCube* _TextureRenderTargetCube, FString _PackagePath, FString _AssetName)
    {
    	UPackage* mPackage = CreatePackage(NULL, *_PackagePath);
    
    	UTextureCube* mTextureCube = _TextureRenderTargetCube->ConstructTextureCube(mPackage, _AssetName, EObjectFlags::RF_Public | EObjectFlags::RF_Standalone);
    
    	if (mTextureCube)
    	{
    		mTextureCube->MarkPackageDirty();
    
    		mTextureCube->GetOuter()->MarkPackageDirty();
    
    		FAssetRegistryModule::AssetCreated(mTextureCube);
    
    		UE_LOG(LogTemp, Log, TEXT("cube full path:%s"), *(mTextureCube->GetFullName()));
    	}
    }
    
    • 我们通过python脚本,将这两部分连接起来,能够让加载进来的jpg,生成Texture2D,并修改MI_Sphere材质实例。然后场景中的SceneCaptureCube刷新,将最新的RTC_Sphere场景生成jpg对应的TextureCube。

    jpg_to_cubemap.py

    import unreal
    import os
    
    # part1 这部分是从外部导入jpg,需要的Setting.
    def build_auto_import_data(filenames, destination_path):
        auto_import_data = unreal.AutomatedAssetImportData()
    
        # set filenames that need be imported
        auto_import_data.set_editor_property("filenames", filenames)    
    
        # set destination_path
        auto_import_data.set_editor_property("destination_path", destination_path)
    
        # set replace
        auto_import_data.set_editor_property("replace_existing", True)
    
        return auto_import_data
    
    # part2 这部分是通过外部的路径,将jpg导入到UE4中.
    def import_jpg():
        file_dir=r'C:\Users\Administrator\Desktop\Camera\202000000000009\images'
    
        file_list = os.listdir(file_dir)
    
        jpg_list = [item for item in file_list if item.endswith('.jpg')]
    
        jpg_os_list=[]
    
        jpg_ue_list=[]
        for jpg in jpg_list:
            jpg_os = os.path.join(file_dir, jpg)
            jpg_os_list.append(jpg_os)
    
            asset_name = str(jpg).split('.')[1]
            jpg_ue = '/Game/Texture/' + asset_name
            jpg_ue_list.append(jpg_ue)
    
        import_data=build_auto_import_data(jpg_os_list, '/Game/Texture')
    
        unreal.AssetToolsHelpers.get_asset_tools().import_assets_automated(import_data)
    
        unreal.EditorAssetLibrary.save_directory('/Game/Texture')
    
    # part3 这部分是单张图片生成Cubemap.
    def create_cubemap():
        mi_asset_path = '/Game/RenderTargetCube/MI_Sphere.MI_Sphere'
        mi_asset_data = unreal.AssetRegistryHelpers.get_asset_registry().get_asset_by_object_path(mi_asset_path)
        mi_asset_object = mi_asset_data.get_asset()
    
        tex_asset_path = '/Game/Texture/camera_1vB44rwa.camera_1vB44rwa'
        tex_asset_data = unreal.AssetRegistryHelpers.get_asset_registry().get_asset_by_object_path(tex_asset_path)
        tex_asset_object = tex_asset_data.get_asset()
        tex_asset_name = tex_asset_data.get_editor_property('asset_name')
    
        unreal.MaterialEditingLibrary.set_material_instance_texture_parameter_value(mi_asset_object, 'Texture', tex_asset_object)
    
        rtc_asset_path = '/Game/RenderTargetCube/RTC_Sphere.RTC_Sphere'
        rtc_asset_data = unreal.AssetRegistryHelpers.get_asset_registry().get_asset_by_object_path(rtc_asset_path)
        rtc_asset_object = rtc_asset_data.get_asset()
    
        scene_capture_cube_array = unreal.GameplayStatics.get_all_actors_of_class(unreal.EditorLevelLibrary.get_editor_world(), unreal.SceneCaptureCube)
        scene_capture_cube = scene_capture_cube_array[0]
        capture_component_cube = scene_capture_cube.get_editor_property('capture_component_cube')
        capture_component_cube.update_content()
    
        cubemap_package_path = '/Game/HDR/' + str(tex_asset_name)
        unreal.ExportTextureFunctionLibrary.create_cubemap(rtc_asset_object, cubemap_package_path, str(tex_asset_name))
    
    # part4 这部分是通过加载图片,然后生成Cubemap.
    def create_cubemap_by_texture2d():
        mi_asset_path = '/Game/RenderTargetCube/MI_Sphere.MI_Sphere'
        mi_asset_data = unreal.AssetRegistryHelpers.get_asset_registry().get_asset_by_object_path(mi_asset_path)
        mi_asset_object = mi_asset_data.get_asset()
    
        rtc_asset_path = '/Game/RenderTargetCube/RTC_Sphere.RTC_Sphere'
        rtc_asset_data = unreal.AssetRegistryHelpers.get_asset_registry().get_asset_by_object_path(rtc_asset_path)
        rtc_asset_object = rtc_asset_data.get_asset()
    
        scene_capture_cube_array = unreal.GameplayStatics.get_all_actors_of_class(unreal.EditorLevelLibrary.get_editor_world(), unreal.SceneCaptureCube)
        scene_capture_cube = scene_capture_cube_array[0]
        capture_component_cube = scene_capture_cube.get_editor_property('capture_component_cube')
    
        file_dir = r'C:\Users\Administrator\Desktop\Camera\202000000000009\images'
    
        file_list = os.listdir(file_dir)
    
        jpg_list = [item for item in file_list if item.endswith('.jpg')]
    
        for jpg_name in jpg_list:
            jpg_path = os.path.join(file_dir, jpg_name)
    
            tex_asset_name = str(jpg_name).split('.')[0]
    
            unreal.ExportTextureFunctionLibrary.load_texture(mi_asset_object, jpg_path)
        
            capture_component_cube.update_content()
    
            cubemap_package_path = '/Game/HDR/' + str(tex_asset_name)
    
            unreal.ExportTextureFunctionLibrary.create_cubemap(rtc_asset_object, cubemap_package_path, str(tex_asset_name))
    
    # part5 这部分是part3的多张图的自动化操作.
    def create_cubemap_auto():
        mi_asset_path = '/Game/RenderTargetCube/MI_Sphere.MI_Sphere'
        mi_asset_data = unreal.AssetRegistryHelpers.get_asset_registry().get_asset_by_object_path(mi_asset_path)
        mi_asset_object = mi_asset_data.get_asset()
    
        tex_asset_path = '/Game/Texture'
        tex_asset_data_array = unreal.AssetRegistryHelpers.get_asset_registry().get_assets_by_path(tex_asset_path)
    
        rtc_asset_path = '/Game/RenderTargetCube/RTC_Sphere.RTC_Sphere'
        rtc_asset_data = unreal.AssetRegistryHelpers.get_asset_registry().get_asset_by_object_path(rtc_asset_path)
        rtc_asset_object = rtc_asset_data.get_asset()
    
        scene_capture_cube_array = unreal.GameplayStatics.get_all_actors_of_class(unreal.EditorLevelLibrary.get_editor_world(), unreal.SceneCaptureCube)
        scene_capture_cube = scene_capture_cube_array[0]
        capture_component_cube = scene_capture_cube.get_editor_property('capture_component_cube')
    
        for tex_asset_data in tex_asset_data_array:
            tex_asset_object = tex_asset_data.get_asset()
            tex_asset_name = tex_asset_data.get_editor_property('asset_name')
    
            unreal.MaterialEditingLibrary.set_material_instance_texture_parameter_value(mi_asset_object, 'Texture', tex_asset_object)
    
            capture_component_cube.update_content()
    
            cubemap_package_path = '/Game/HDR/' + str(tex_asset_name)
    
            unreal.ExportTextureFunctionLibrary.create_cubemap(rtc_asset_object, cubemap_package_path, str(tex_asset_name))
    
    
    if __name__ == "__main__":
        # import_jpg()
    
        # create_cubemap_auto()
    
    	# all 只用这个就行.
        create_cubemap_by_texture2d()
    

    这样,整个流程大幅提升。本人测试结果:16张全景图(6720x3360),导入UE4生成TextureCube,大约10s

    展开全文
  • Unity3d_cubemap

    热门讨论 2013-12-25 23:05:43
    13 个 U3D cubemap 及地面时时反射,一直自己用。
  • CubeMap实现图片背景替换
  • 2、Ctrl + R (刷新),菜单项会多出一个"Custom/Render Cubemap"菜单项 3、点击Render Cubemap会打开会话框,拖动对象到“Renderer From Position” 4、点击“Render”,Ctrl + R (刷新) 会在项目视图里生成文件夹:...
  • Threejs-cubemap-painter 在立方体贴图上绘制亮度/HDR 值 用法 执照 麻省理工学院,有关详细信息,请参阅 。
  • 在Photoshop中已打开一系列VR Cubemap JPEG文件。 当我们使用立体立方体贴图时,我们有两个六个正方形的集合,分别用于左眼和右眼。 当我们使用单眼立方体贴图时,我们只有六个正方形的集合,仅用于左眼。 我们...
  • threejs-cubemap-exporter 将THREE.CubeCamera的立方体贴图环境导出到6个.PNG中 用法 执照 麻省理工学院,有关详细信息,请参阅 。
  • CubeMap 天空盒源码

    2017-03-13 16:04:20
    VB.net源码
  • 命运Oracle 一个进行中的归档站点,用于存储有关Destiny 2的数据。 模型来自Destiny 2的游戏文件,使用图像,骨骼,定位数据等的高度复杂的重构来生成展示的.fbx和.glb版本。 提供了以测试格式直接下载资产的信息。...
  • 立方体贴图 处理中的立方体贴图反射/折射环境着色器
  • D3D11_CubeMap.rar

    2017-02-23 23:19:22
    D3D11_CubeMap.rar
  • OpenGL3.3_CubeMap_ReflectionMapOpenGL3.3_CubeMap_ReflectionMapOpenGL3.3_CubeMap_ReflectionMapOpenGL3.3_CubeMap_ReflectionMapOpenGL3.3_CubeMap_ReflectionMap
  • 【Unity Shader】 CubeMap(立方体贴图)

    万次阅读 多人点赞 2018-03-07 17:22:35
    一、介绍CubeMap Shader中对CubeMap采样 Unity中如何制作CubeMap 二、Reflect CubeMap(反射立方体纹理用于环境映射) 环境映射原理 反射方向的计算 Unity Shader实现Reflection CubeMap(基于CubeMap的反射效果)...

    Unity Shader 立方体贴图

    一、介绍CubeMap

    Cubemap是一个由六个独立的正方形纹理组成的集合,它将多个纹理组合起来映射到一个单一纹理。

    基本上说CubeMap包含6个2D纹理,这每个2D纹理是一个立方体(cube)的一个面,也就是说它是一个有贴图的立方体。

    CubeMap通常被用来作为具有反射属性物体的反射源。

    这里写图片描述
    你可能会奇怪这样的立方体有什么用?为什么费事地把6个独立纹理结合为一个单独的纹理,只使用6个各自独立的不行吗?这是因为cubemap有自己特有的属性,可以使用方向向量对它们索引和采样

    想象一下,我们有一个1×1×1的单位立方体,有个以原点为起点的方向向量在它的中心。方向向量的大小无关紧要,当方向向量向外延伸时,就会和立方体表面上的相应纹理发生相交,我们可以根据该交点进行采样。
    这里写图片描述

    Shader中对CubeMap采样

    Shader提供了CubeMap的内置类型samplerCube,samplerCube和sampler2D一样,都是贴图,不同的是,需要使用textureCube进行采样,采样的时候需要传递规范化的方向向量而不是uv坐标。

    texCUBE(_CubeMap, directionVec);

    texCUBE会采样方向向量directionVec在CubeMap上的交点。

    如果texCube采样时,传入模型中心到定点的向量,就可以将CubeMap纹理贴到模型上了。

    Shader "Hidden/CubemapSampler"
    {
        Properties
        {
            _CubeMap("CubeMap", CUBE) = ""{}
        }
        SubShader
        {
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;   
                    float3 normal : NORMAL;
                };
    
                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    float4 vertexLocal : TEXCOORD1;
                };
    
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertexLocal = v.vertex;
                    o.vertex = UnityObjectToClipPos(v.vertex);
    
                    return o;
                }
    
                samplerCUBE _CubeMap;
                fixed4 frag (v2f i) : SV_Target
                {
                    fixed4 col = texCUBE(_CubeMap, normalize(i.vertexLocal.xyz));
                    return col;
                }
                ENDCG
            }
        }
    }

    这里写图片描述

    Unity中如何制作CubeMap

    1. 已经有6张2D纹理,直接创建CubeMap
      Project-Create-Legacy-CubeMap
      这里写图片描述

    二、Reflect CubeMap(反射立方体纹理用于环境映射)

    在图形学中,立方体纹理(CubeMap)是环境映射(Environment Mapping)的一种实现方法。环境映射可以模拟物体周围IDE环境,而使用了环境映射的物体可以看起来像镀了层金属一样反射出周围的环境。

    通常我们使用高光来模拟光滑物体对于点光源的反射效果,更进一步,高反光的物体通常可以在表面反射出周围的物体,这样的效果通过高光贴图就无法实现了,需要通过环境贴图CubeMap来实现。。

    环境反射的原理很简单,一个光滑的物体表面可以根据我们观察的不同角度反射出不同位置的环境。即物体表面一点反射的颜色和该点的法线,观察视线和反射视线有关系。

    环境映射原理

    这里写图片描述

    如果我们使用texCube函数对立方体纹理进行采样时,使用视线关于物体顶点法线的反射向量作为采样的方向向量就可以得到反射的效果。

    反射方向的计算

    这里写图片描述
    L为入射光(顶点到光源)的单位法向量,N为顶点的单位法向量,R为反射光的单位法向量,V是观察方向。

    R=2(N•L)N-L

    推导过程:
    L在N方向上的投影是|Lcosθ|=cosθ,那么投影矢量N’=Ncosθ
    L+S = N’ = Ncosθ
    R = L+2S = L+2(Ncosθ-L) = 2Ncosθ-L

    简单计算,或者使用Cg的内置函数reflect(),该函数接受参数向量I和法线N,返回I关于N的反射向量。
    float3 R = reflect(I,N);

    Unity Shader实现Reflection CubeMap(基于CubeMap的反射效果)

    步骤:
    - 创建用于环境映射的立方体纹理(反射源)
    - 用该立方体纹理作为天空盒子
    - 使用worldRef(视线关于物体顶点法线的反射向量)作为采样的方向向量,对CubeMap采样作为物体的表面纹理

    如果物体的纹理采集自与天空盒子同一个CubeMap,就会有一种环境映射的感觉。

    反射CubeMap的Shader代码

    Shader "Hidden/CM       Reflect"
    {
        Properties
        {
            _CubeMap("CubeMap", CUBE) = ""{}
        }
        SubShader
        {
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;           
                    float3 normal : NORMAL;
                };
    
                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    float3 worldNormal : TEXCOORD0;
                    float3 worldRef : TEXCOORD1;
                    float3 worldPos : TEXCOORD2;
                    float3 worldViewDir : TEXCOORD3;
                };
    
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                    o.worldNormal = mul(unity_ObjectToWorld, v.normal);
                    o.worldViewDir =  normalize(_WorldSpaceCameraPos.xyz - o.worldPos.xyz);
                    o.worldRef = reflect(-o.worldViewDir,normalize(o.worldNormal));
                    return o;
                }
    
                samplerCUBE _CubeMap;
                fixed4 frag (v2f i) : SV_Target
                {
                    fixed4 col = texCUBE(_CubeMap, i.worldRef);
                    return col;
                }
                ENDCG
            }
        }
    }

    反射效果展示

    这里写图片描述

    ps:“假”反射?

    这种基于CubeMap反射效果的环境映射,并不是“真”反射,只是“模拟”环境反射,是“假”反射。如果我们改变了环境的天空盒子,物体的纹理并不会跟着改变,且不会反射出环境中的其他物体,只能反射天空盒子。
    这里写图片描述

    一个非常消耗效率的真反射实现方法

    创建一个相机、RenderTexture将RenderTexture赋给相机的Render Target,再将RenderTexture赋给物体material的贴图。
    这里写图片描述

    三、Refract CubeMap(折射立方体纹理用于环境透视)

    透明材质,如水,玻璃,水晶,应该可以透视。这种环境的透视我们可以在对CubeMap采样时,使用视线关于物体法线的反射向量作为方向向量,就得到了环境透射的效果。

    texCube(_CubeMap, refract(viewDir,normal,_RefractRatio));

    _RefractRatio是折射相对系数,与物体的介质有关。

    斯涅尔定律:入射角的正弦值与折射角的正弦值的比值为一定值,而此一定值跟入射与折射介质有关.
    这里写图片描述
    sinθ比值等于介质折射率n的比值

    材质折射指数
    空气1.00
    1.33
    1.309
    玻璃1.52
    宝石2.42

    环境透视的实现原理

    这里写图片描述

    Unity Shader实现Refract CubeMap(基于CubeMap的折射效果)

    折射CubeMap的Shader代码

    Shader "Hidden/CMRefract"
    {
        Properties
        {
            _CubeMap("CubeMap", CUBE) = ""{}
            _RefractRatio("Refract Ratio", Float) = 0.5
        }
        SubShader
        {
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;               
                    float3 normal : NORMAL;
                };
    
                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    float3 worldNormal : TEXCOORD0;
                    float3 worldRef : TEXCOORD1;
                    float3 worldPos : TEXCOORD2;
                    float3 worldViewDir : TEXCOORD3;
                    float4 vertexLocal : TEXCOORD4;
                };
    
                float _RefractRatio;
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertexLocal = v.vertex;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                    o.worldNormal = mul(unity_ObjectToWorld, v.normal);
                    o.worldViewDir =  normalize(_WorldSpaceCameraPos.xyz - o.worldPos.xyz);
                    o.worldRef = refract(-o.worldViewDir,normalize(o.worldNormal),_RefractRatio);
                    return o;
                }
    
                samplerCUBE _CubeMap;
                fixed4 frag (v2f i) : SV_Target
                {
                    fixed4 col = texCUBE(_CubeMap, normalize(i.worldRef));
                    return col;
                }
                ENDCG
            }
        }
    }

    折射效果展示

    这里写图片描述

    四、菲涅尔反射(同时考虑折射与反射)

    菲尼尔现象是指光到达材质交界处时,一部分被反射,一部分被折射,即视线垂直于表面时,夹角越小,反射越明显。所有物体都有菲尼尔反射,只是强大大小不同。因此,菲尼尔反射是为了模拟真实世界中的这种光学现象。多少光发生反射,多少光发生折射,可以用菲涅尔公式进行计算。

    实际世界的菲涅尔公式非常复杂,我们同样用一些近似公式来计算,如下面提到的Schlick菲涅尔近似公式和Empricial菲涅尔近似公式:

    • Schlick菲涅尔近似等式
    //resnelBias 菲尼尔偏移系数  
    //fresnelScale 菲尼尔缩放系数  
    //fresnelPower 菲尼尔指数  
    reflectFact = fresnelBias + fresnelScale*pow(1-dot(viewDir,N)),fresnelPower);  //系数:多少光发生折射多少光发生反射
    • Empricial菲涅尔近似等式:
    //F0是反射系数用于控制菲涅尔的强度
    reflectFact = F0 + (1-F0)*pow(1-dot(viewDir,N),5);

    这里写图片描述

    有了反射系数,我们就可以根据能量守恒计算反射光线和折射光线的强度了。

    c(reflect) = reflect(viewDir,N)
    c(refract) = reflect(viewDir,N,eatRadio)
    C(fresnelFinal) = reflectFact * C(reflect) + (1-reflectFact)*C(refract);  //能量守恒

    以Schlick菲涅尔公式为例实现Fresnel反射

    CubeMap的菲涅尔反射Shader代码

    Shader "Hidden/Fresnel_Schlick"
    {
        Properties
        {
            _CubeMap("CubeMap", CUBE) = ""{}
            _RefractRatio("Refract Ratio", Float) = 0.5
            _FresnelScale("Fresnel Scale", Float) = 0.5
        }
        SubShader
        {
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;               
                    float3 normal : NORMAL;
                };
    
                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    float3 worldNormal : TEXCOORD0;
                    float3 worldReflect : TEXCOORD1;
                    float3 worldPos : TEXCOORD2;
                    float3 worldViewDir : TEXCOORD3;
                    float4 vertexLocal : TEXCOORD4;
                    float3 worldRefract : TEXCOORD5;
                };
    
                float _RefractRatio;
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertexLocal = v.vertex;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                    o.worldNormal = mul(unity_ObjectToWorld, v.normal);
                    o.worldViewDir =  normalize(_WorldSpaceCameraPos.xyz - o.worldPos.xyz);
                    o.worldReflect = reflect(-o.worldViewDir,normalize(o.worldNormal));
                    o.worldRefract = refract(-o.worldViewDir,normalize(o.worldNormal),_RefractRatio);
                    return o;
                }
    
                float _FresnelScale;
                samplerCUBE _CubeMap;
                fixed4 frag (v2f i) : SV_Target
                {
                    float4 fresnelReflectFactor = _FresnelScale + (1 - _FresnelScale)*pow(1-dot(i.worldViewDir,i.worldNormal), 5);
                    fixed4 colReflect = texCUBE(_CubeMap, normalize(i.worldReflect));
                    fixed4 colRefract = texCUBE(_CubeMap, normalize(i.worldRefract));
                    fixed4 col = fresnelReflectFactor * colReflect + (1-fresnelReflectFactor) * colRefract;
                    return col;
                }
                ENDCG
            }
        }
    }

    菲涅尔反射效果展示

    这里写图片描述

    参考

    UnityShader入门精要学习笔记(十四):立方体纹理
    openGL CG 系列教程5 – Environment Mapping ( 环境贴图 )
    立方体贴图
    学习OpenGL ES之基于CubeMap的反射效果

    展开全文
  • art-cubemap贴图制作

    千次阅读 2019-04-02 17:31:13
    title: art-cubemap贴图制作 categories: Art tags: [art, cubemap, 贴图, 制作, ta] date: 2019-04-02 10:37:47 comments: false art-cubemap贴图制作 前篇 cubemap 素材下载的站点 - ...

    title: art-cubemap贴图制作
    categories: Art
    tags: [art, cubemap, 贴图, 制作, ta]
    date: 2019-04-02 10:37:47
    comments: false

    art-cubemap贴图制作


    前篇


    unity 将 六张图 合成为 cubemap

    素材来源是六张图

    • 原素材展开图

      原素材命名

    • unity中制作cubemap. 创建 cubemap : assets -> create -> legacy -> cubemap

      因为坐标系的不同, 所以要将原素材命名为 negx 放在unity中的 +x 位置, posx 放在 -x 位置


    unity 将 cubemap 分割成 六张图

    参考: Cube Map Seperator Here! - https://forum.unity.com/threads/cube-map-seperator-here.239101/

    1. 编辑器扩展代码

      using System.Collections;
      using System.Collections.Generic;
      using System.IO;
      using UnityEditor;
      using UnityEngine;
      
      public class CubeSplitter : EditorWindow {
      	Cubemap splitCube;
      	Color[] CubeMapColors;
      	int splitSize;
      
      	[MenuItem ("Tools/CubeSplitter", false, 20001)]
      	public static void OpenCubeSplitter () {
      		var win = GetWindow<CubeSplitter> ("CubeSplitter");
      		win.Show ();
      	}
      
      	void OnGUI () {
      		GUILayout.Label ("Choose the Cube Map you want to save as 6 images and click EXPORT!", EditorStyles.boldLabel);
      		splitCube = EditorGUILayout.ObjectField ("My Cubemap:", splitCube, typeof (Cubemap), false) as Cubemap;
      		GUILayout.Label ("Make sure to set the Size to the same as the Cubemap you are using", EditorStyles.boldLabel);
      		splitSize = EditorGUILayout.IntField ("CubeMap Size: ", splitSize);
      
      		if (GUILayout.Button ("EXPORT!")) {
      			if (splitCube) {
      				Export ();
      			} else {
      				Debug.Log ("Forget Something?");
      			}
      		}
      	}
      
      	void Export () {
      		var filePath = AssetDatabase.GetAssetPath (splitCube);
      		Texture2D tex = new Texture2D (splitSize, splitSize, TextureFormat.RGB24, false);
      
      		CubeMapColors = splitCube.GetPixels (CubemapFace.PositiveY);
      		tex.SetPixels (CubeMapColors, 0);
      		tex.Apply ();
      		byte[] bytes = tex.EncodeToPNG ();
      		File.WriteAllBytes (filePath + "_Bot.png", bytes);
      
      		CubeMapColors = splitCube.GetPixels (CubemapFace.NegativeY);
      		tex.SetPixels (CubeMapColors, 0);
      		tex.Apply ();
      		bytes = tex.EncodeToPNG ();
      		File.WriteAllBytes (filePath + "_Top.png", bytes);
      
      		CubeMapColors = splitCube.GetPixels (CubemapFace.PositiveX);
      		tex.SetPixels (CubeMapColors, 0);
      		tex.Apply ();
      		bytes = tex.EncodeToPNG ();
      		File.WriteAllBytes (filePath + "_Left.png", bytes);
      
      		CubeMapColors = splitCube.GetPixels (CubemapFace.NegativeX);
      		tex.SetPixels (CubeMapColors, 0);
      		tex.Apply ();
      		bytes = tex.EncodeToPNG ();
      		File.WriteAllBytes (filePath + "_Right.png", bytes);
      
      		CubeMapColors = splitCube.GetPixels (CubemapFace.PositiveZ);
      		tex.SetPixels (CubeMapColors, 0);
      		tex.Apply ();
      		bytes = tex.EncodeToPNG ();
      		File.WriteAllBytes (filePath + "_Front.png", bytes);
      
      		CubeMapColors = splitCube.GetPixels (CubemapFace.NegativeZ);
      		tex.SetPixels (CubeMapColors, 0);
      		tex.Apply ();
      		bytes = tex.EncodeToPNG ();
      		File.WriteAllBytes (filePath + "_Back.png", bytes);
      
      		this.Close ();
      	}
      }
      
    2. 拖入要分割的 cubemap, 设置分辨率为 cubemap 的分辨率. 点击 EXPORT. done!


    unity 渲染场景 cubemap

    把当前场景渲染成一个 cubemap

    参考: How To Generate The Environment Cubemap In Unity - https://lmhpoly.com/how-to-generate-the-environment-cubemap-in-unity/

    1. 编辑器扩展代码. 这是官方提供的脚本

      using System.Collections;
      using UnityEditor;
      using UnityEngine;
      
      public class RenderCubemapWizard : ScriptableWizard {
          public Transform renderFromPosition;
          public Cubemap cubemap;
      
          void OnWizardUpdate () {
              string helpString = "Select transform to render from and cubemap to render into";
              bool isValid = (renderFromPosition != null) && (cubemap != null);
          }
      
          void OnWizardCreate () {
              GameObject go = new GameObject ("CubemapCamera");
              go.AddComponent<Camera> ();
              go.transform.position = renderFromPosition.position;
              go.transform.rotation = Quaternion.identity;
              go.GetComponent<Camera> ().RenderToCubemap (cubemap);
              DestroyImmediate (go);
          }
      
          [MenuItem ("Tools/Render into Cubemap")]
          static void RenderCubemap () {
              ScriptableWizard.DisplayWizard<RenderCubemapWizard> (
                  "Render cubemap", "Render!");
          }
      }
      
    2. 新建一个空的 cubemap, asset -> create -> legacy -> cubemap, 并设置参数. ( 若修改 cubemap 参数崩溃, 可能是版本问题, 参考: [使用 unity2018.2.8f1 版本, 修改 cubemap 的参数总是崩溃.](#使用 unity2018.2.8f1 版本, 修改 cubemap 的参数总是崩溃.) )

    3. 打开脚本工具, 设置 位置 和 新创建的 cubemap. 点解 render. done!

      • 在使用到场景中


    踩坑

    使用 unity2018.2.8f1 版本, 修改 cubemap 的参数总是崩溃.

    解决办法: 我升级到 unity2018.3.11f1 就ok了.

    展开全文
  • OpenGL3.3_CubeMap_ReractionMap.rar OpenGL3.3_CubeMap_ReractionMap.rar OpenGL3.3_CubeMap_ReractionMap.rar OpenGL3.3_CubeMap_ReractionMap.rar
  • cubemap制作的反射

    2016-12-03 15:00:38
    cubemap制作的反射
  • 工程GIT地址:https://gitee.com/yaksue/yaksue-graphics 目标 参考了 Vulkan Adventures: Cube map tutorial! – satellitnorden

    工程GIT地址:https://gitee.com/yaksue/yaksue-graphics

    目标

    本篇的目标很明确:

    • 实现加载并采样CubeMap纹理。

    然而当前有个问题是:

    D3D11和D3D12的官方范例,以及“龙书”中的范例,都是以DDS作为纹理格式,而这个格式仅DirectX支持。作为兼顾OpenGL和Vulkan的工程,我不应该用这种格式的纹理。

    这个问题我在《图形API学习工程(11):使用纹理》也做了讨论,说明了如何在D3D11和D3D12中使用PNG格式的纹理。然而,当时只是面对普通的2D纹理,现在面对CubeMap纹理,情况变得复杂很多,我没法简单地搞明白如何使用非DDS格式的图片来创建CubeMap纹理。

    因此,最后我决定:

    • 当前对于OpenGL和Vulkan,使用6张非DDS格式图片。对于D3D11和D3D12,使用DDS格式。

    这样导致接口不统一,自然是不能接受的。但当前只是个临时的做法,目的是可以更快看到D3D11和D3D12上CubeMap的效果。另外,使用的函数来自于microsoft/DirectXTex/DDSTextureLoader的源文件而非库文件,所以只要未来有时间和耐心,肯定是能搞明白其中的原理。在搞明白原理之后,便可以将读取数据的方式从“读取DDS纹理”改为“使用stb库读取非DDS格式纹理”。

    OpenGL

    OpenGL中,创建一个CubeMap纹理对比普通的2D纹理来说,流程上很相似:
    在这里插入图片描述
    不同点在于:

    1.绑定资源
    使用glBindTexture时要用GL_TEXTURE_CUBE_MAP而非GL_TEXTURE_2D

    2.设置环绕、过滤方式
    使用glTexParameteri时要用GL_TEXTURE_CUBE_MAP而非GL_TEXTURE_2D,另外要主要环绕模式是三个维度。

    3.设定数据
    使用glTexImage2D时要使用六次。且不是GL_TEXTURE_2D而是立方体的六个面:

    #define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
    #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
    #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
    #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
    #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
    #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
    

    Vulkan

    此处参考的资料是:

    对于Vulkan,创建一个CubeMap纹理对比普通的2D纹理来说,流程上也很相似:
    在这里插入图片描述
    但区别有很多需要注意:

    1.加载数据
    加载数据时将数据存到一个数组中(std::vector<stbi_uc*> FaceTexturePixels),并且创建Buffer的尺寸将是图片长宽乘积的6倍(因为有6个面)

    2.创建Image
    我为我的createImage函数增添了参数来指出当前要创建的纹理是否是CubeMap。
    在这里插入图片描述

    3.转换Image的Layout
    我为我的transitionImageLayout函数增添了参数来指出当前要创建的纹理是否是CubeMap。
    在这里插入图片描述
    4.将读取的数据拷贝到中间Buffer
    需要对读取到的数据(std::vector<stbi_uc*> FaceTexturePixels)拷贝六次,且注意:需要对map到的地址进行对应的偏移。
    在这里插入图片描述
    5.将Buffer中的数据拷贝到Image中
    我为我的copyBufferToImage函数增添了参数来指出当前要创建的纹理是否是CubeMap。
    在这里插入图片描述
    6.创建ImageView
    我为我的createImageView函数增添了参数来指出当前要创建的纹理是否是CubeMap。
    在这里插入图片描述

    D3D11

    对于普通的2D纹理,我是使用D3DX11CreateShaderResourceViewFromFile的,这是个方便而直接的函数——给它文件名,得到资源(ID3D11ShaderResourceView)。

    而且它还可以读取DDS中的CubeMap。DDS可以直接将CubeMap的6个面存储到一个文件中,也就是说,DDS本身含有自己是否是CubeMap的信息(可见之前博客中的学习

    所以,读取CubeMap的时候我可以简单地使用普通的2D纹理的版本就能实现效果:

    AbstractTextureData* D3D11Interface::CreateCubeMapTextureFromDDS(std::string DDSFile)
    {
        return CreateTexture(DDSFile);
    }
    

    但是,D3DX11CreateShaderResourceViewFromFile的实现在d3dx11.lib中,源代码看不到,不利于之后的学习,因此我还是想使用microsoft/DirectXTex/DDSTextureLoader/DDSTextureLoader11.cpp

    最后,我使用了CreateDDSTextureFromFile函数,也挺简单的:
    在这里插入图片描述

    DX12

    与D3D11一样,使用了microsoft/DirectXTex/DDSTextureLoader/DDSTextureLoader12.cpp来读取DDS文件。

    在使用LoadDDSTextureFromFile并用得到的数据创建Shader可读的纹理资源(ID3D12Resource)方面,我参考了《DirectX12(D3D12)基础教程(五)——理解和使用捆绑包,加载并使用DDS Cube Map_Gamebaby Rock Sun的博客-CSDN博客_directx12教程》中的代码。而这方面的流程和我之前的普通的2D纹理有较大的区别,而且所用的API有些我没用过,所以暂时先不讨论。

    在创建完之后,就和普通的2D纹理流程相似了,唯一需要注意的是在创建ShaderResourceView时:
    在这里插入图片描述

    Shader文件

    Shader中,是用反射的方向作为立方体纹理的采样方向:

    GLSL

    //测试CubeMap的像素着色器
    
    #version 450
    #extension GL_ARB_separate_shader_objects : enable
    
    //输入-从顶点着色器
    layout(location = 0) in vec3 vs_fs_normal;
    layout(location = 1) in vec2 vs_fs_TexCoord;
    layout(location = 2) in vec3 vs_fs_worldPosition;
    
    //输出
    layout(location = 0) out vec4 fColor;
    
    //纹理
    layout(binding = 9) uniform samplerCube ourCubeMap;
    
    //UniformBuffer
    layout(binding = 7) uniform SceneData {
    	mat4 view;
    	mat4 proj;
    	vec4 lightDir;
    	vec4 eyePosition;
    } ub_SceneData;
    
    void main()
    {
    	//视线方向
    	vec3 EyeDir = ub_SceneData.eyePosition.xyz - vs_fs_worldPosition;
    	
    	//镜面反射光的方向
    	vec3 LightDir = reflect(normalize(EyeDir),normalize(vs_fs_normal));
    	
    	//采样的方向,这里做一个小调整
    	vec3 SampleDir = vec3(LightDir.x,-LightDir.z,LightDir.y);
    	
    	//采样立方体贴图获得颜色
    	fColor = texture(ourCubeMap, SampleDir);
    }
    

    HLSL

    //测试CubeMap的像素着色器
    
    //顶点着色器输出
    struct VS_OUTPUT
    {
        float4 Pos : SV_POSITION;
        float3 Normal : NORMAL;
    	float2 TexCoord : TEXCOORD0;
    	float3 WorldPosition : TEXCOORD1;
    };
    
    TextureCube ourCubeMap : register( t9 );
    SamplerState ourSampler : register( s5 );
    
    cbuffer SceneData : register( b7 )
    {
    	matrix View;
    	matrix Projection;
    	float4 lightDir;
    	float4 eyePosition;
    }
    
    float4 Main( VS_OUTPUT input ) : SV_Target
    {
    	//视线方向
    	float3 EyeDir = eyePosition.xyz - input.WorldPosition;
    	
    	
    	//镜面反射光的方向
    	float3 LightDir = reflect(normalize(EyeDir),normalize(input.Normal));
    	
    	//采样的方向,这里做一个小调整
    	float3 SampleDir = float3(LightDir.x,-LightDir.z,LightDir.y);
    	
    	//采样立方体贴图获得颜色
    	return ourCubeMap.Sample( ourSampler, SampleDir );
    }
    

    效果

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • Ambient Cubemap 环境立方体贴图 用处 在标准光照模型(Blinn-Phong模型)中,进入摄像机的光线分为4种,自发光、高光反射、漫反射、环境光。其中环境光适用于描述物体所收到的间接光照的。而Ambient Cubemap用于...
  • OpenGL ES2.0 Cubemap texture

    2013-04-01 17:16:03
    在Xcode4.5上调试通过,利用OpenGL ES2.0实现cubemap texture.
  • void main(void) { vFragColor = texture(cubeMap, vVaryingTexCoord); } 注意:天空盒两个面之间的缝隙问题 解决方法 glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); 即可 在GLSL代码里,需注意的是天空盒顶点着色器...
  • cubemap,立方体映射

    热门讨论 2011-09-01 08:53:28
    基于vc6.0下的opengl源代码,实现环境映射,原理是立方体映射,自己建立了button,top,left,right,back,front六幅图像,将其 贴在茶壶上,效果和光线跟踪的效果差不多
  • DirectX11.2 CubeMap

    2015-01-26 19:02:09
    DirectX 11.2 CubeMap
  • Unity 将全景球转成CubeMap

    千次阅读 2021-10-21 20:01:09
    官网插件:PanoramaToCubemap
  • 十字图 cubeMap,失真部分较小 对cubeMap的采样的原理: 从立方体的中心点出发: 1.先确定相交面 2.确定相交点, 3.转化为2D的坐标求解,如上图中右下部分所示 在lighting设置全局反射探针,unity中一个Shader...
  • Cubemap是一个由六个独立的正方形纹理组成的集合,它将多个纹理组合起来映射到一个单一纹理。 基本上说CubeMap包含6个2D纹理,这每个2D纹理是一个立方体(cube)的一个面,也就是说它是一个有贴图的立方体。 Cube...
  • OpenGL3.3_CubeMap_Reflection.rar

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,154
精华内容 6,061
关键字:

Cubemap