博客
关于我
【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/

    你可能感兴趣的文章
    python基础内容_Python基础入门必须了解的
    查看>>
    Python基础之面向对象2(封装)
    查看>>
    Python基础之给函数增加元信息
    查看>>
    python基础之字符编码
    查看>>
    python基础之多线程与多进程(二)
    查看>>
    Python基础之基本数据类型一《数字与字符串》
    查看>>
    python基础之变量---总纲
    查看>>
    Python基础之列表
    查看>>
    Python基础之Python环境搭建
    查看>>
    python基础之--面相对象--OOP基本特性
    查看>>
    python基础之--迭代器和生成器及异常处理
    查看>>
    python基础之--包和模块
    查看>>
    python基础之---面向对象--属性和方法
    查看>>
    python基础之---运算符
    查看>>
    python基础之---语句
    查看>>
    python基础之---正则表达式
    查看>>
    python基础之---函数式编程
    查看>>
    python基础之---函数
    查看>>
    Python基础之(一)基本数据类型
    查看>>
    Python基础【os】
    查看>>