水墨Shader解析

2023-11-14

Chinese Ink-wash Painting II Shader

简介

本文尝试对Chinese Ink-wash Painting II来源:https://www.shadertoy.com/view/DdSyDW)
的代码部分进行解析,以学习其中实现思路和方法。

在这里插入图片描述

代码实现

下面代码首先定义了一些函数来生成噪声、计算光线追踪、获取法线等。然后在mainImage函数中,它计算了每个像素的颜色值,这个颜色值基于光线追踪的结果和噪声纹理。最后,它将计算出的颜色值赋给了fragColor,这就是最终渲染到屏幕上的颜色。

1.常量

头文件中的常量,用于。

// 定义一些常量
#define MAX_STEPS 200
#define MAX_DIST 100.
#define SURF_DIST .001
#define TAU 6.283185
#define PI 3.141592
#define S smoothstep
#define T iTime

2.哈希值生成

生成2D哈希值:哈希函数可以将输入映射到一个固定大小的数值域,这里的哈希函数将2D坐标映射到一个随机的2D向量。这个函数在生成噪声函数中被用来创建一个伪随机的、看起来平滑的噪声纹理。

// 生成哈希值
vec2 hash22(vec2 p){
    p = vec2( dot(p,vec2(127.1,311.7)),
			  dot(p,vec2(269.5,183.3)));
    return -1.0 + 2.0 * fract(sin(p)*43758.5453123);
}

3.生成噪声和纹理

生成噪声:噪声函数是用来生成一种随机但连续的纹理,这种纹理常常被用来模拟自然界的各种现象,如云彩、火焰、水波等。

// 生成噪声
float noise(vec2 p)
{
    const float K1 = 0.366025404; // (sqrt(3)-1)/2;
    const float K2 = 0.211324865; // (3-sqrt(3))/6;
    
    vec2 i = floor(p + (p.x + p.y) * K1);
    
    vec2 a = p - (i - (i.x + i.y) * K2);
    vec2 o = (a.x < a.y) ? vec2(0.0, 1.0) : vec2(1.0, 0.0);
    vec2 b = a - (o - K2);
    vec2 c = a - (1.0 - 2.0 * K2);
    
    vec3 h = max(0.5 - vec3(dot(a, a), dot(b, b), dot(c, c)), 0.0);
    vec3 n = h * h * h * h * vec3(dot(a, hash22(i)), dot(b, hash22(i + o)), dot(c, hash22(i + 1.0)));
     
    return dot(vec3(70.0, 70.0, 70.0), n);
}

// 生成噪声纹理
float noise_itself(vec2 p)
{
    float f = 0.;
    p *= 8.;
    f += 1.0000 * noise(p); p = 6.0 * p;
    f += 0.1000 * noise(p); p = 4.0 * p;
    f += 0.0100 * noise(p); p = 3.0 * p;
    return f;
}

4.旋转矩阵

旋转矩阵:用来进行坐标旋转的,它可以将一个坐标旋转到一个新的位置。在场景中,旋转矩阵被用来旋转相机的方向,使得用户可以从不同的角度观察地形。

// 旋转矩阵
mat2 Rot(float a) {
    float s=sin(a), c=cos(a);
    return mat2(c, -s, s, c);
}

5.获取距离

下面展示一些 内联代码片

// 获取距离
float GetDist(vec3 p) {
    float d = p.y+4.;
    p.z -= iTime;
    float h = max(0., noise_itself(p.xz*0.01+13.7)); 
    h = pow(h, 1.6)*8.;
    d -= h;
    
    return d*0.3;
}

6.光线追踪

光线追踪是一种用于生成图像的技术,通过追踪光线从视点出发并穿过像素投射到场景中的路径,来计算每个像素的颜色

// 光线追踪
float RayMarch(vec3 ro, vec3 rd) {
	float dO=0.;
    
    for(int i=0; i<MAX_STEPS; i++) {
    	vec3 p = ro + rd*dO;
        float dS = GetDist(p);
        dO += dS;
        if(dO>MAX_DIST || abs(dS)<SURF_DIST) break;
    }
    
    return dO;
}

7.获取法线

法线向量在计算机图形学中有很多重要的应用,主要包括以下几个方面:

  1. 光照计算:在计算物体表面的光照效果时,法线向量是非常关键的一个因素。根据光源方向和法线向量的夹角,可以决定物体表面的亮度。

  2. 碰撞检测:在物理模拟和游戏开发中,法线向量常常用于碰撞检测和碰撞响应。当两个物体发生碰撞时,可以通过法线向量来计算反弹的方向。

  3. 纹理映射:在进行纹理映射时,法线向量可以用于计算纹理的方向,使得纹理能够正确地贴在物体表面上。

  4. 几何处理:在进行几何处理,如模型剪裁、隐藏面消除等操作时,法线向量也会被用到。

vec3 GetNormal(vec3 p) {
    vec2 e = vec2(.001, 0);
    vec3 n = GetDist(p) - 
        vec3(GetDist(p-e.xyy), GetDist(p-e.yxy),GetDist(p-e.yyx));
    
    return normalize(n);
}

8.获取光线方向

在光线追踪或者光线投射的算法中,根据光线的起点、目标点和焦距,以及2D的纹理坐标,来计算光线的方向

// 获取光线方向
vec3 GetRayDir(vec2 uv, vec3 p, vec3 l, float z) {
    vec3 
        f = normalize(l-p),
        r = normalize(cross(vec3(0,1,0), f)),
        u = cross(f,r),
        c = f*z,
        i = c + uv.x*r + uv.y*u;
    return normalize(i);
}

9.主函数

主函数:GLSL(OpenGL Shading Language)中的主函数(通常命名为main)在片元着色器中负责计算每个像素的颜色。是程序的入口点,它是程序执行的开始。在这个上下文中,mainImage函数是一个特殊的主函数,它是在渲染管线中被调用的,用于计算每个像素的颜色值。

当你的图形程序运行时,GPU会为屏幕上的每个像素调用一次片元着色器。在每次调用中,主函数都会计算出当前像素的颜色,并将其存储在gl_FragColor变量中。这样,当所有的像素都经过片元着色器处理后,你就得到了最终的图像。

需要注意的是,虽然主函数会被调用多次(每个像素一次),但每次调用都是独立的,也就是说,每次调用只会影响当前的像素,不会影响其他像素的颜色

本Shader首先根据输入的屏幕坐标和分辨率,计算出每个像素对应的UV坐标。然后,根据鼠标的位置,计算出相机的位置和方向。接着,根据UV坐标和相机的位置和方向,计算出光线的方向。然后,使用光线追踪算法,计算出光线与地形的交点,以及交点处的颜色。最后,根据太阳的亮度,调整颜色,并将计算出的颜色赋给输出的颜色,计算出每个像素的颜色后,从而生成一个3D地形的渲染图像。

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // 将屏幕坐标转换为[-1, 1]范围内的UV坐标
    vec2 uv = (fragCoord-.5*iResolution.xy)/iResolution.y;
    
    // 设置默认的鼠标位置
	vec2 m = vec2(-.05, -0.5);
    
    // 如果鼠标在屏幕上移动,则更新鼠标位置
    if(iMouse.z > 0.) m = iMouse.xy/iResolution.xy;

    // 设置相机的初始位置
    vec3 ro = vec3(0, 3, -3);
    
    // 根据鼠标的位置旋转相机的方向
    ro.yz *= Rot(-m.y*PI+1.);
    ro.y = max(ro.y, -1.);
    ro.xz *= Rot(-m.x*TAU);
    
    // 计算光线的方向
    vec3 rd = GetRayDir(uv, ro, vec3(0,0.,0), 1.);
    
    // 初始化颜色为黑色
    vec3 col = vec3(0);
   
    // 进行光线追踪,获取光线行进的距离
    float d = RayMarch(ro, rd);
    
    // 计算太阳的亮度
    float sun = S(0.998,1.,dot(normalize(rd), normalize(vec3(0.,0.5,-1.))));
    
    // 如果光线没有超出最大距离,说明光线击中了物体
    if(d<MAX_DIST) {
        // 计算光线击中的位置
        vec3 p = ro + rd * d;
        
        // 计算该位置的法线
        vec3 n = GetNormal(p);
        
        // 设置光源的方向
        vec3 lightDir = normalize(vec3(0.0, .5,-.5));

        // 计算菲涅尔项,用于模拟光线在表面的反射和折射,描述光线在接触物体表面时,反射和折射
        float fre = max(0.,dot(n, normalize(ro-p)));
        fre = pow(fre,.125);
        fre = S(0.8,0.85,fre);
        fre = mix(fre, 1., S(-0.0, -4., p.y));
        
        // 根据高度计算颜色
        float heigh = S(-4., 0., p.y);
        col = mix(vec3(0.6588,0.5176,0.2824), vec3(0.3059, 0.4627, 0.633), heigh)*fre;
        
        // 如果高度在一定范围内,修改颜色
        heigh = S(-4.1, -3.9, p.y);
        col = mix(vec3(0.6,0.55,0.2)*S(0.,15., d), col, heigh);
        
        // 将太阳亮度设置为0
        sun = .0;
    }
    
    // 如果光线没有击中物体,设置背景颜色
    col = mix(col, vec3(0.6588,0.5176,0.2824)*1.5, S(0.,100., d));
    
    // 根据太阳的亮度调整颜色
    col = mix(col, vec3(1.,0.4,0.), sun);

    // 设置最终的颜色
    fragColor = vec4(col, 1.);
}

这个函数的主要目的是计算每个像素的颜色。
流程:首先计算出光线的方向,然后进行光线追踪,如果光线击中了物体,就根据物体的属性(如法线、高度等)来计算颜色,否则就设置为背景色。最后,根据太阳的亮度来调整颜色,并将计算出的颜色赋给fragColor。

10.总结

这几部分代码的主要目的都是为了生成一个看起来真实的3D地形。通过使用噪声函数和噪声纹理,可以生成一个既随机又自然的地形。通过使用旋转矩阵,可以让用户从不同的角度观察这个地形。

其他

噪声在计算机图形学中是一种非常重要的工具,因为它可以生成一种随机但连续的纹理,这种纹理在视觉上看起来非常类似于自然界的许多现象。如山脉、河流、云彩、火焰、水波等,都具有一种随机但又有规律的特性。这种特性很难通过简单的数学函数来模拟,但是噪声函数可以很好地模拟出这种特性。

噪声函数生成的纹理既有随机性,又有连续性,这使得它可以用来模拟自然界的各种现象。例如,我们可以通过噪声函数生成地形的高度值,使得地形看起来既随机又自然。我们也可以通过噪声函数生成云彩的形状,使得云彩看起来既随机又连续。

因此,噪声函数可以用来模拟自然界的各种现象,从而生成更加真实和生动的图像。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

水墨Shader解析 的相关文章

  • Vulkan下多线程渲染设计

    1 Vulkan 视角下的多线程渲染 首先我们需要从vulkan api的顶层框架上来看一下 它在哪些地方可以让我们并行 Vulkan API的基本框架 Vulkan不同于Gles只有一个 不被API暴露出来的 单一链条的cmdbuffer
  • 球谐函数原理

    参考 球谐函数极其应用 球谐函数是什么 球谐函数是傅里叶级数的高维类比 由一组表示球体表面的基函数构成 同时 球谐函数是Laplace算子角动量在三个维度上的特征函数 文章目录 球谐函数是什么 球坐标下的Laplace方程 Laplace方
  • 虚拟数字人定制公司 国内做虚拟数字人定制开发的公司有吗?

    得益于图形渲染技术 AI技术 传感器硬件等技术的发展 使得虚拟数字人逐步进入大众视野 虚拟数字人分为真人驱动 AI驱动 AI合成 不同形式的虚拟数字人制作难度与成本相差较大 许多大众认为 制作虚拟数字人就是做一个美术就可以了 如果这样的话
  • Vulkan入门精要

    Vulkan入门精要 fuxiii github io https fuxiii github io Essentials of Vulkan
  • OpenGL之Shader编程入门

    1 shader 编程基础 1 1 Vertex shader与Fragment shader Vertex shader即顶点着色器 用来改变顶点的属性 Fragment shader即片元着色器 用来改变片元的颜色 在Direct3D中
  • 2020年 IEEE VIS 科学可视化与体渲染论文整理与分析

    因为最近工作的关系 需要研究一下IEEE VIS中2017年以后的与我之前主要方向 体渲染 医学可视化 有关的论文 我把这些年全部的论文进行了筛选和梳理 总共筛选出57篇论文 打算写一个文章来记录这些内容 这个栏目是2020年的5篇论文的介
  • [游戏开发][Shader]GLSLSandBox转Unity-CG语言

    官网 GLSL Sandbox Galleryhttps glslsandbox com 屏幕坐标计算 fragCoord与 ScreenParams mat2矩阵转换 vec2向量 在GLSL里mat2 a b c d 函数返回vec2
  • 内推几何建模与图形渲染职位

    最近 可能也会是长期的 公司在大力招兵买马 急缺几何 图形方面的人才 初级 高级 专家或有致力于图形领域方面开发都欢迎 当然其他方面的也有 包括BIM相关的开发 可直接内推 具体职位列表如下 薪资open可谈 坐标 上海 深圳 武汉三地均可
  • 在vscode上搭建Shadertoy的环境

    目录 一 前期准备 1 1 vscode下载安装 1 2 Shadertoy网站 二 使用Shadertoy的效果 2 1 在vscode中查找如下插件 三 调用本地的glsl脚本 一 前期准备 1 1 vscode下载安装 Visual
  • 图形基础-叉乘

    using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviour public Vecto
  • Dx11--用dx11绘制棱台,并用键盘和鼠标进行旋转缩放操作

    目录 一 索引缓冲区 前言 创建缓冲区 缓冲区的描述 二 常量缓冲区 前言 准备工作 正式初始化 画面更新及其效果 画面更新 效果 三 键盘和鼠标的创建 1 鼠标的创建 2 键盘的创建 3 更新画面 4 消息回调函数 处理键盘鼠标信息 效果
  • GAMES101回顾 -- Geometry

    Geometry Examples of geometry 隐式几何 Inplict 定义 用函数进行表示 如 f x y z 0 显式几何 Explict 定义 所有点都是直接或通过参数映射给出 所有的 u v 映射到对应的 x y z
  • 新手LearnOpenGL纹理不显示的部分解决方法

    项目场景 在LearnOpenGL学习中遇到的一些问题 照着写但是纹理加载不出来或者两张纹理只加载一张 问题描述 lt 纹理加载不出来 gt 1 文件路径是否正确 是否输出texture load fail等提示 设置了成功检查才会有提示
  • GAMES101笔记_Lec07~09_着色 Shading

    0 我们已经学了什么 What We ve Covered So Far 空间中定义了一个摄像机 通过某些变换使模型摆好姿势 Model 通过观测变换让摄像机放在原点 得到标准的 1 1
  • GAMES101: 现代计算机图形学入门(2)几何、光线追踪

    GAMES101 现代计算机图形学入门 链接 GAMES101 1 几何 1 1 几何的表示 隐式几何 通过一个函数表达式来表示的几何体 即 f x y z 0 优点 很容易判断一个点在不在几何体上 缺点 很难通过表达式看出几何体的形状 显
  • DirectX12 3D游戏开发实践(龙书)第四章 Direct3D的初始化

    目录 Direct3D的初始化 预备知识 Direct3D概述 组件对象模型 纹理格式 Textures Formats 交换链和页面翻转 深度缓冲 资源与描述符 多重采样技术的原理 利用Direct3D进行多重采样 功能级别 Direct
  • 如何渲染精美3D PCB图

    简介 现在网上大部分PCB渲染方法都比较麻烦 并且会有丝印不清晰 或者走线与铜皮不显现问题 现在分享一种简单有效的PCB渲染方法 图为渲染效果图 工具或材料 AD keyshot 一个带3D封装图的PCB文件 具体步骤 1 AD端操作 在P
  • GAMES101 Lec 07~09:Shading 定义、着色模型、着色频率、图形渲染管线、纹理

    3dMax 导出一个模型文件包含内容 顶点坐标 法线 边的关系 model 模型 空间中有了一个摄像机 Model 通过变换可以让摄像机放在原点 View 三维空间的模型变换到屏幕上 Projection 通过采样进行光栅化 Rasteri
  • 次表面散射

    专题介绍 在实时渲染和离线渲染领域 对场景模型表面以及空间介质的精细化建模是增加场景真实感的重要手段 计算机图形学领域的许多科研工作者设计出一系列复杂精巧的技术理论 模拟出光线从宏观世界到微观粒子的变化规律 本期专题精选了近年来关于微表面模
  • Unity震撼首发,最新一代高清数字人短片《Enemies》

    我们屡获殊荣的 Demo 团队又一次在 异教徒 The Heretic 累积了超 400 万观众 的基础上取得了进展 推出了 Enemies 一支全新的电影式预告片 以 4K 分辨率的实时渲染来展示眼睛 头发和皮肤渲染等方面的重大突破 创建

随机推荐

  • ES分布式搜索引擎

    初始化RestClient 引入依赖 因为SpringBoot默认的ES版本是7 6 2 所以我们需要覆盖默认的ES版本
  • Linux用nohup后台运行python程序及停止

    在Ubuntu上用python flask写了一个后端代码 每次运行要CMD先远程连上服务器 然后python xxx py启动 这样操作会让cmd窗口被占用 没办法进行其他操作 ls cd这种 如果把窗口关了 程序就停止了 看了网上的例子
  • CTFSHOW【萌新计划】Writeup

    CTFSHOW 萌新计划 web1 萌新计划 web2 萌新计划 web3 萌新计划 web4 萌新计划 web5 萌新计划 web6 萌新计划 web7 萌新计划 web8 萌新计划 web9 萌新计划 web10 萌新计划 web11
  • 《我的眼睛--图灵识别》第五章:基础:形状识别

    我的眼睛 图灵识别 第五章 基础 形状识别 1 图形认识 三角形 三角形是由同一平面内不在同一直线上的三条线段 首尾 顺次连接所组成的封闭图形 三角形按边分有不等边三角形 等腰三角和等边三角形 按角分有直角三角形 锐角三角形 钝角三角形等
  • antd的Form表单控制实例的使用

    Form表单的控制实例 一 业务常景 二 使用Form表单的实例来解决 一 业务常景 遇到一种业务场景 即一个简单的Modal框 Form的一个组合 仔细思考了一下 和我们平时直接使用Form表单还是有一定的区别 我们通常是通过给Form表
  • springcloudAlibaba 链路追踪SkyWalking

    一 链路追踪SkyWalking简介 在大型系统的微服务化构建中 一个系统被拆分成了许多模块 这些模块负责不同的功能 组合成系统 最终可以提供丰富的功能 在这种架构中 一次请求往往要涉及到多个服务 互联网应用构建在不同的软件模块集上 这些软
  • 关调度与关中断

    关调度与关中断 关中断与关调度是两种进入临界区的方式 它们有各自的使用环境 最近在研究 ucos III 的源代码时发现 ucos III 中有对临界区的优化 以关调度来代替关中断的方式工作 系统可以在特定的情况下用关调度的方式来替代关中断
  • 数据可视化之Seaborn(1)

    文章目录 什么是Seaborn seaborn提供的一些特点 Seaborn的基本使用 1 安装seaborn 2 导入seaborn库并导入Seaborn内置数据集 3 设置画图空间风格 4 设置子图风格 5 去除图脊 边框 6 设置内容
  • 设计一个表示分数的类Fraction。这个类用两个int类型的变量分别表示分子和分母。

    分数 题目内容 设计一个表示分数的类Fraction 这个类用两个int类型的变量分别表示分子和分母 这个类的构造函数是 Fraction int a int b 构造一个a b的分数 这个类要提供以下的功能 double toDouble
  • 第五章:数据库完整性

    数据库完整性 文章目录 5 1参照完整性 5 1 1实体完整性定义 5 1 2实体完整性的违约处理和检查 5 2参照完整性 5 2 1参照完整性定义 5 2 2参照完整性的违约处理和检查 5 3用户自定义的完整性 5 3 1属性上的约束条件
  • Python - OpenCV实现摄像头人脸识别(亲测版)

    要使用Python 3和OpenCV进行摄像头人脸识别 您可以按照以下步骤进行操作 0 安装OpenCV软件 去官网直接下载安装即可 如果是C 使用OpenCV 需要使用编译源码并配置环境变量 1 安装OpenCV库 在命令行中输入以下命令
  • 【bug记录】This attempt to set a cookie via a Set-Cookie header was blocked because it had the “Secure“

    问题出现场景 最近在使用浏览器访问一个登录页面时会一直发生302重定向请求 然后f12看到浏览器的访问页面上有如下警告 错误原因 错误原因为 尝试通过Set Cookie头设置具有 secure 属性的cookie 但未通过安全连接接收 因
  • gurobi安装

    gurobi安装 先去官网下载 Gurobi Optimizer 同时申请一个免费的license 学术用途的 土豪随意买 以最新的6 5版本为例进行解说 解压下载的gurobi6 0 5 linux64 tar gz 命令 tar zxv
  • web端引入高德地图

    1 安装 amap amap jsapi loader 依赖 高德地图加载器 npm i amap amap jsapi loader S 2 在对应的文件引入依赖或者全局引入 注意 由于高德api文档提示 您在2021年12月02日申请以
  • centos7设置账号密码复杂度、密码有效期、账号锁定、会话超时等策略

    目录 一 设置密码复杂度 二 设置密码有效期 三 设置登陆会话超时 四 设置登陆失败锁定 一 设置密码复杂度 CentOS7 RHEL7 开始使用pam pwquality模块进行密码复杂度策略的控制管理 pam pwquality替换了原
  • html制作动态八卦图源码

    动态八卦图 自动旋转的八卦图 一个html文件就行 如下动态图所示 taijitu html div div
  • 看甲骨文如何在云端一路高歌猛进!

    甲骨文喜欢并购这事儿不假 但更根植于创新 过去的十几年中 甲骨文始终坚持将完整并颇具创新性的云服务提供给用户 所谓完整 也就是需要覆盖端到端的全流程 提及创新 如今的大环境下怎能不将区块链 IoT 甚至是机器学习统统收入囊中 一起植入软件
  • 《大白AI周报》精华内容整理汇总

    在人工智能学习中 大家或多或少都会关注一些公众号 但随着每天信息量的暴增 碎片化的内容让大家应接不暇 如何挖掘有价值的内容 如何快速查阅自己需要的内容 是一个头疼的问题 因此大白每周都会将人工智能领域 几十个公众号每周发布的精华内容汇总起来
  • 带你认识 MySQL 之 MySQL 体系结构

    序 最近一直在忙项目 各种加班加点 项目上线 渐渐的没有了学习的时间 这不 刚这几天才能抽出点时间 忙里偷闲 正在看一本数据库的书籍 相信很多小伙伴们也都看过 MySQL 技术内幕 InnoDB 存储引擎 这本书很详细的讲述了 MySQL
  • 水墨Shader解析

    Chinese Ink wash Painting II Shader 简介 本文尝试对Chinese Ink wash Painting II 来源 https www shadertoy com view DdSyDW 的代码部分进行解