成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

著色器入門:符號距離函數!

開發 后端
在本文中,我將介紹我用來學習編寫簡單著色器的步驟,并努力讓你們相信著色器并不難入門!

[[441677]]

大家好!不久前我學會了如何使用著色器制作有趣的閃亮旋轉八面體:

我的著色器能力仍然非常基礎,但事實證明制作這個有趣的旋轉八面體比我想象中要容易得多(從其他人那里復制了很多代碼片段!)。

我在做這件事時, 從一個非常有趣的叫做 符號距離函數教程:盒子和氣球 的教程中學到了“符號距離函數”的重要思路。

在本文中,我將介紹我用來學習編寫簡單著色器的步驟,并努力讓你們相信著色器并不難入門!

更高級著色器的示例

如果你還沒有看過用著色器做的真正有趣的事情,這里有幾個例子:

  1. 這個非常復雜的著色器就像一條河流的真實視頻:https://www.shadertoy.com/view/Xl2XRW
  2. 一個更抽象(更短!)有趣的著色器,它有很多發光的圓圈:https://www.shadertoy.com/view/lstSzj

步驟一:我的第一個著色器

我知道你可以在 shadertoy 上制作著色器,所以我去了 https://www.shadertoy.com/new。它們提供了一個默認著色器,

代碼如下:

  1. void mainImage( out vec4 fragColor, in vec2 fragCoord )
  2. {
  3. // 規范像素坐標 (從 0 到 1)
  4. vec2 uv = fragCoord / iResolution.xy;
  5.  
  6. // 隨時間改變像素顏色
  7. vec3 col = 0.5 + 0.5 * cos(iTime + uv.xyx + vec3(0, 2, 4));
  8.  
  9. // 輸出到屏幕
  10. fragColor = vec4(col, 1.0);
  11. }

雖然還沒有做什么令人興奮的事情,但它已經教會了我著色器程序的基本結構!

思路:將一對坐標(和時間)映射到一個顏色

這里的思路是獲得一對坐標作為輸入(fragCoord),你需要輸出一個 RGBA 向量作為此坐標的顏色。該函數也可以使用當前時間(iTime),圖像從而可以隨時間變化。

這種編程模型(將一對坐標和時間映射到其中)的巧妙之處在于,它非常容易并行化。我對 GPU 了解不多,但我的理解是,這種任務(一次執行 10000 個微不足道的可并行計算)正是 GPU 擅長的事情。

步驟二:使用 shadertoy-render 加快開發迭代

玩了一段時間的 shadertoy 之后,我厭倦了每次保存我的著色器時都必須在 shadertoy 網站上單擊“重新編譯”。

我找到了一個名為 shadertoy-render 命令行工具,它會在每次保存時實時查看文件并更新動畫。現在我可以運行:

  1. shadertoy-render.py circle.glsl

并更快地開發迭代!

步驟三:畫一個圓圈

接下來我想 —— 我擅長數學!我可以用一些基本的三角學來畫一個會彈跳的彩虹圈!

我知道圓的方程為(x^2 + y^2 = 任意正數!),所以我寫了一些代碼來實現它:

代碼如下:(你也可以 在 shadertoy 上查看

  1. void mainImage( out vec4 fragColor, in vec2 fragCoord )
  2. {
  3. // 規范像素坐標 (從 0 到 1)
  4. vec2 uv = fragCoord / iResolution.xy;
  5. // 繪制一個中心位置依賴于時間的圓
  6. vec2 shifted = uv - vec2((sin(iGlobalTime) + 1) / 2, (1 + cos(iGlobalTime)) / 2);
  7. if (dot(shifted, shifted) < 0.03) {
  8. // 改變像素顏色
  9. vec3 col = 0.5 + 0.5 * cos(iGlobalTime + uv.xyx + vec3(0, 2, 4));
  10. fragColor = vec4(col, 1.0);
  11. } else {
  12. // 使圓之外的其他像素都是黑色
  13. fragColor = vec4(0,0, 0, 1.0);
  14. }
  15. }

代碼將坐標向量 fragCoord 與自身點積,這與計算 x^2 + y^2 相同。我還在這個圓圈的中心玩了一點花活 – 圓心為 vec2((sin(iGlobalTime) + 1)/ 2,(1 + cos(faster)) / 2,這意味著圓心也隨著時間沿另一個圓移動。

著色器是一種學習數學的有趣方式!

我覺得有意思的(即使我們沒有做任何超級高級的事情!)是這些著色器為我們提供了一種有趣的可視化方式學習數學 - 我用 sin 和 cos 來使某些東西沿著圓移動,如果你想更直觀地了解三角函數的工作方式, 也許編寫著色器會是一種有趣的方法!

我喜歡的是,可以獲得有關數學代碼的即時視覺反饋 - 如果你把一些東西乘以 2,圖像里的東西會變得更大!或更小!或更快!或更慢!或更紅!

但是我們如何做一些真正有趣的事情呢?

這個會彈跳的圓圈很好,但它與我見過的其他人使用著色器所做的非常奇特的事情相去甚遠。那么下一步要做什么呢?

思路:不要使用 if 語句,而是使用符號距離函數!

在我上面的圓圈代碼中,我基本上是這樣寫的:

  1. if (dot(uv, uv) < 0.03) {
  2. // 圓里的代碼
  3. } else {
  4. // 圓外的代碼
  5. }

但問題(也是我感到卡住的原因)是不清楚如何將它推廣到更復雜的形狀!編寫大量的 if 語句似乎不太好用。那人們要如何渲染這些 3d 形狀呢?

所以!符號距離函數Signed distance function 是定義形狀的另一種方式。不是使用硬編碼的 if 語句,而是定義一個 函數,該函數告訴你,對于世界上的任何一個點,該點與你的形狀有多遠。比如,下面是球體的符號距離函數。

  1. float sdSphere( vec3 p, float center )
  2. {
  3. return length(p) - center;
  4. }

符號距離函數非常棒,因為它們:

  • 易于定義!
  • 易于組合!如果你想要一個被切去一塊的球體, 你可以用一些簡單的數學來計算并集/交集/差集。
  • 易于旋轉/拉伸/彎曲!

制作旋轉陀螺的步驟

當我開始時,我不明白需要編寫什么代碼來制作一個閃亮的旋轉東西。結果表明如下是基本步驟:

  1. 為想要的形狀創建一個符號距離函數(在我的例子里是八面體)
  2. 光線追蹤符號距離函數,以便可以在 2D 圖片中顯示它(或沿光線行進?我使用的教程稱之為光線追蹤,我還不明白光線追蹤和光線行進之間的區別)
  3. 編寫代碼處理形狀的表面紋理并使其發光

我不打算在本文中詳細解釋符號距離函數或光線追蹤,因為我發現這個 關于符號距離函數的神奇教程 非常友好,老實說,它比我做的更好,它解釋了如何執行上述 3 個步驟,并且代碼有大量的注釋,非常棒。

步驟四:復制教程代碼并開始更改內容

我在這里使用了久負盛名的編程實踐,即“復制代碼并以混亂的方式更改內容,直到得到我想要的結果”。

最后一堆閃亮的旋轉八面體著色器在這里:https://www.shadertoy.com/view/wdlcR4

為了做到這一點,我基本上只是復制了關于符號距離函數的教程,該函數根據符號距離函數呈現形狀,并且:

  • 將 sdfBalloon 更改為 sdfOctahedron,并使八面體旋轉而不是在我的符號距離函數中靜止不動
  • 修改 doBalloonColor 著色功能,使其有光澤
  • 有很多八面體而不是一個

使八面體旋轉!

下面是我用來使八面體旋轉的代碼!事實證明這真的很簡單:首先從 這個頁面 復制一個八面體符號距離函數,然后添加一個 rotate 使其根據時間旋轉,然后它就可以旋轉了!

  1. vec2 sdfOctahedron( vec3 currentRayPosition, vec3 offset ){
  2. vec3 p = rotate((currentRayPosition), offset.xy, iTime * 3.0) - offset;
  3. float s = 0.1; // s 是啥?
  4. p = abs(p);
  5. float distance = (p.x + p.y + p.z - s) * 0.57735027;
  6. float id = 1.0;
  7. return vec2( distance, id );
  8. }

用一些噪音讓它發光

我想做的另一件事是讓我的形狀看起來閃閃發光/有光澤。我使用了在 這個 GitHub gist 中找到的噪聲函數使表面看起來有紋理。

以下是我如何使用噪聲函數的代碼。基本上,我只是隨機地將參數更改為噪聲函數(乘以 2?3?1800?隨你!),直到得到喜歡的效果。

  1. float x = noise(rotate(positionOfHit, vec2(0, 0), iGlobalTime * 3.0).xy * 1800.0);
  2. float x2 = noise(lightDirection.xy * 400.0);
  3. float y = min(max(x, 0.0), 1.0);
  4. float y2 = min(max(x2, 0.0), 1.0);
  5. vec3 balloonColor = vec3(y, y + y2, y + y2);

編寫著色器很有趣!

上面就是全部的步驟了!讓這個八面體旋轉并閃閃發光使我很開心。如果你也想用著色器制作有趣的動畫,希望本文能幫助你制作出很酷的東西!

通常對于不太了解的主題,我可能在文章中說了至少一件關于著色器的錯誤事情,請讓我知道錯誤是什么!

再說一遍,如下是我用到的兩個資源:

  1. “符號距離函數教程:盒子和氣球”:https://www.shadertoy.com/view/Xl2XWt(修改和玩起來真的很有趣)
  2. 可以將大量符號距離函數復制并粘貼到你的代碼中:http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm

   

 

責任編輯:龐桂玉 來源: Linux中國
相關推薦

2017-01-11 19:15:55

Android著色器Tint

2013-01-30 15:37:19

CSS著色器HTML5

2021-03-18 08:03:58

SteamMesa緩存

2023-04-12 07:46:24

JavaScriptWebGL

2023-10-16 15:58:54

開源Blender

2017-05-08 11:41:37

WebGLThree.js

2013-04-15 14:23:21

2022-09-26 12:28:16

OpenGLAPI使用移動應用

2023-11-15 14:15:03

開源Blender

2023-03-16 14:33:23

WebGL初始化繪制

2023-05-06 07:23:57

2022-10-10 09:01:21

JavaQuarkus

2025-01-08 10:17:11

2009-12-29 16:21:46

silverlight

2025-06-03 14:14:59

智能技術AI

2019-07-10 16:45:49

LinuxLinux游戲游戲性能

2024-02-26 00:00:00

前端工具Space.js

2023-09-04 06:52:28

AMD銳龍GPU

2012-05-22 01:20:14

SyntaxHighlJavaScriptJava

2023-04-13 07:45:15

WebGL片元著色器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产亚洲精品久久久久久豆腐 | 在线色网址| 久久99这里只有精品 | 欧美精品第一区 | 国产一区二区三区视频 | 91色在线| 精品国产久 | 国产精品99久久久久久宅男 | h视频免费看 | 成年女人免费v片 | 午夜视频在线观看一区二区 | 国产精品久久a | 亚洲国产片 | 久久的色 | 美女啪啪国产 | 免费av一区二区三区 | 男人的天堂久久 | 国产亚洲第一页 | 国产在线不卡视频 | 欧美电影一区 | 偷拍自拍第一页 | 国产精品区一区二 | 韩日在线观看视频 | 久久伊人一区二区 | 亚洲欧美国产精品久久 | 日韩一区二区三区四区五区 | 一级片成人| 好姑娘高清在线观看电影 | 91精品国产一区二区三区 | 国产乱码精品1区2区3区 | 成人免费黄视频 | 日韩精品视频中文字幕 | 一道本不卡视频 | 久久99精品久久久久久 | 亚洲福利一区二区 | 国产在线中文字幕 | 婷婷国产一区二区三区 | 国产免费一区二区 | 9191成人精品久久 | 中日av | h视频免费观看 |