博客
关于我
【Shader入门精要】第十章——高级纹理
阅读量:499 次
发布时间:2019-03-07

本文共 4989 字,大约阅读时间需要 16 分钟。

Shader入门精要项目链接

相关章节

一、立方体纹理

立方体纹理是环境映射的一种实现方法,它可以模拟物体周围的环境,让物体看起来像金属一样反射出周围环境。这是环境映射最基本且常用的实现方式之一。

1.1 立方体纹理制作流程(Unity2017)

在Unity中制作立方体纹理需要以下几个步骤:

  • 拖拽六张相关图片作为立方体纹理的六个面。这六张图片需要按照特定的角度拍摄,确保立方体在各个面都能正确显示环境。

  • 接下来,将这些图片拖拽到一个材质球的属性中,选择Cubemap_HDR选项。这样可以将立方体纹理应用到物体表面,实现环境映射效果。

  • 2.1 环境反射(金属效果)

    环境反射是通过立方体纹理实现的,效果类似于金属反射。通过反射向量从立方体纹理中采样,结合自定义反射颜色,可以实现出像是金属般反射周围环境的效果。

    以下是实现环境反射的Shader示例:

    Shader "M_Reflection"{	Properties	{		_Cubemap ("CubeMap", Cube) = "_Skybox" {}		_Color ("Color Tint", Color) = (1,1,1,1)		_ReflectColor ("Reflection Color", Color) = (1,1,1,1)		_ReflectAmount ("Reflect Amount", Range(0,1)) = 1	}	SubShader	{		Tags { "RenderType"="Opaque" }		LOD 100		Pass		{			Tags{ "LightMode" = "ForwardBase" }			CGPROGRAM			#pragma vertex vert			#pragma fragment frag			#pragma multi_compile_fwdbase						#include "UnityCG.cginc"			#include "Lighting.cginc"			#include "AutoLight.cginc"			struct appdata			{				float4 vertex : POSITION;							[float3 normal : NORMAL]	

    2.2 环境折射

    环境折射通过立方体纹理实现,效果类似于水面上的折射。通过折射向量从立方体纹理中采样,结合自定义折射颜色,可以模拟介质中光线折射的效果。

    以下是实现环境折射的Shader示例:

    2.3 菲涅尔反射

    菲涅尔反射是一种特殊的反射类型,常见于水面、玻璃等表面。通过菲涅尔反射公式,可以在近距离和远距离的物体表面产生不同的反射效果。

    菲涅尔反射公式:[ f + (1-f) \times \text{pow}((1-\text{dot}(\text{viewDir}, \text{normal})), \text{FresnelPower}) ]

    其中,( f ) 是菲涅尔反射的影响系数,( \text{dot}(\text{viewDir}, \text{normal}) ) 是视角向量与法线向量的点积。

    3.1 渲染纹理

    渲染纹理是一种将摄像机渲染结果输出到纹理上的技术。这种纹理可以被应用到镜子、玻璃等物体上,模拟真实的反射和折射效果。

    在Unity中创建渲染纹理的步骤如下:

  • 创建一个材质球,将其设置为透明渲染队列。

  • 在Scene窗口右下角的摄像机小窗口中,观察渲染结果。这张小窗口的图像是会被存储到指定的渲染纹理上。

  • 3.2 镜子效果

    镜子效果可以通过渲染纹理实现。创建一个正面朝向摄像机的Quad面板,将其材质球设置为镜面反射效果。通过Shader调整面板的大小和位置,可以实现镜子的效果。

    以下是镜子效果的Shader示例:

    3.3 玻璃效果

    玻璃效果通过渲染纹理和法线纹理实现。使用法线纹理模拟玻璃表面的粗糙度,并结合立方体纹理实现透明度的变化。

    以下是玻璃效果的Shader示例:

    4. 程序纹理

    程序纹理是一种动态生成纹理的技术。通过代码控制纹理的颜色和纹理元素,可以生成高度定制的纹理效果。

    以下是动态生成程序纹理的代码示例:

    using System.Collections; using System.Collections.Generic; using UnityEngine; [ExecuteInEditMode] public class M_ProceduralTextureGeneration : MonoBehaviour {    public Material material = null;    [SerializeField] private int m_textureWidth = 512;    public int textureWidth    {        get { return m_textureWidth; }        set        {            m_textureWidth = value;            _UpdateMaterial();        }    }    [SerializeField] public Color backgroundColor    {        get { return m_backgroundColor; }        set        {            m_backgroundColor = value;            _UpdateMaterial();        }    }    public Color circleColor    {        get { return m_circleColor; }        set        {            m_circleColor = value;            _UpdateMaterial();        }    }    [SerializeField] public float blurFactor    {        get { return m_blurFactor; }        set        {            m_blurFactor = value;            _UpdateMaterial();        }    }    private Texture2D m_generateTexture = null;    private void Start()    {        if (material == null)        {            Renderer renderer = gameObject.GetComponent
    (); if (renderer == null) { Debug.LogWarning("can not find a renderer."); return; } material = renderer.sharedMaterial; } _UpdateMaterial(); } private void _UpdateMaterial() { if (material != null) { m_generateTexture = _GenerateProceduralTexture(); material.SetTexture("_MainTex", m_generateTexture); } } private Texture2D _GenerateProceduralTexture() { Texture2D proceduralTexture = new Texture2D(textureWidth, textureWidth); float circleInterval = textureWidth / (float)4.0f; float radius = textureWidth / (float)10.0f; float edgeBlur = 1.0f / blurFactor; for (int w = 0; w < textureWidth; w++) { for (int h = 0; h < textureWidth; h++) { Color pixel = backgroundColor; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { Vector2 circleCenter = new Vector2(circleInterval * (i + 1), circleInterval * (j+1)); float dist = Vector2.Distance(new Vector2(w, h), circleCenter) - radius; Color color = _MixColor(circleColor, new Color(pixel.r, pixel.g, pixel.b, 0.0f), Mathf.SmoothStep(0f, 1.0f, dist * edgeBlur)); pixel = _MixColor(pixel, color, color.a); } } proceduralTexture.SetPixel(w, h, pixel); } } proceduralTexture.Apply(); return proceduralTexture; } private Color _MixColor(Color color0, Color color1, float mixFactor) { Color mixColor = Color.white; mixColor.r = Mathf.Lerp(color0.r, color1.r, mixFactor); mixColor.g = Mathf.Lerp(color0.g, color1.g, mixFactor); mixColor.b = Mathf.Lerp(color0.b, color1.b, mixFactor); mixColor.a = Mathf.Lerp(color0.a, color1.a, mixFactor); return mixColor; } }

    通过以上代码,可以动态生成一张带有圆形纹理的纹理图像。这种纹理可以用于材质球的颜色混合,为视觉效果增添更多层次感。

    转载地址:http://shucz.baihongyu.com/

    你可能感兴趣的文章
    opencv30-图像矩
    查看>>
    opencv32-基于距离变换和分水岭的图像分割
    查看>>
    opencv4-图像操作
    查看>>
    opencv5-图像混合
    查看>>
    opencv6-调整图像亮度和对比度
    查看>>
    opencv9-膨胀和腐蚀
    查看>>
    OpenCV_ cv2.imshow()
    查看>>
    opencv——图像缩放1(resize)
    查看>>
    Opencv——模块介绍
    查看>>
    OpenCV与AI深度学习 | 2024年AI初学者需要掌握的热门技能有哪些?
    查看>>
    OpenCV与AI深度学习 | CIB-SE-YOLOv8: 优化的YOLOv8, 用于施工现场的安全设备实时检测 !
    查看>>
    OpenCV与AI深度学习 | OpenCV图像拼接--Stitching detailed使用与参数介绍
    查看>>
    OpenCV与AI深度学习 | OpenCV快速傅里叶变换(FFT)用于图像和视频流的模糊检测(建议收藏!)
    查看>>
    OpenCV与AI深度学习 | SAM2(Segment Anything Model 2)新一代分割一切大模型介绍与使用(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | YOLO11介绍及五大任务推理演示(目标检测,图像分割,图像分类,姿态检测,带方向目标检测)
    查看>>
    OpenCV与AI深度学习 | YOLOv11来了:将重新定义AI的可能性
    查看>>
    OpenCV与AI深度学习 | YOLOv8自定义数据集训练实现火焰和烟雾检测(代码+数据集!)
    查看>>
    OpenCV与AI深度学习 | YOLOv8重磅升级,新增旋转目标检测,又该学习了!
    查看>>
    OpenCV与AI深度学习 | 使用OpenCV轮廓检测提取图像前景
    查看>>
    OpenCV与AI深度学习 | 使用Python和OpenCV实现火焰检测(附源码)
    查看>>