Shader從入門到跑路:自定義紋理輸入
上文:Shader從入門到跑路:樸實無華的圖形學基礎
上節課後作業答案
只需要將返回顏色的藍色通道更改為1,就可以得到課後作業的渲染結果
- float4 frag(v2f i) : SV_Target
- {
- float4 color = float4(i.uv.r, i.uv.g, 1, 1);
- return color;
- }
課後作業渲染結果
前言
實在是手殘,不小心把這篇文章刪掉了,問了客服好像並沒有解決辦法,希望知乎以後可以提供恢復誤刪文章的功能...只能再手打一遍了,欲哭無淚。
正文
上一章我們都是指揮unity來獲取渲染資訊,那麼接下來就介紹如何將圖片輸出到物體上。
背景為透明的我老婆
為了展示接下來的內容,我在PS內製作了一張帶有透明通道的PNG圖片,正確的渲染效果應該是顯示人像,而背景部分則顯示圖片後面的場景物體(即應該為透明的)。
現於SubShader區塊上面新增一個Properties區塊,並在其中定義一個MainTexture的二維屬性。
- Properties{
- _MainTex("Main Texture", 2D) = "white" {}
- }
注意,在屬性區塊內被定義的資料在CGPROGRAM內被使用之前都要預定義一遍,不然會報錯。在CGPROGRAM內加入紋理的定義:
sampler2D _MainTex;
在這裡的sampler2D是一個GLSL的型別,表示用來儲存一個2D紋理
https://www.khronos.org/opengl/wiki/Sampler_(GLSL)
接下來,在frag函式中利用tex2D這個方法來獲取紋理中的顏色,並直接使用顏色進行著色。這個方法其實就是在一張紋理中對一個點進行取樣,我們要得到整個紋理的顏色,就需要所有畫素對應的uv點,程式碼如下:
- float4 frag(v2f i) : SV_Target
- {
- return tex2D(_MainTex, i.uv);
- }
然而我們卻得到了一些奇怪的渲染結果,來看一看為什麼。
與預期不符的渲染結果,背景應該是透明的
可見得出的渲染結果並不符合我們的預期,本來在PNG裡背景被設定為透明的圖片,背景變成了白色。這是因為tex2D在處理紋理的時候會計算每一個對應uv點的畫素顏色,但是本應是透明的內容是不會有”顏色“這一屬性的,然而tex2D還是將它們視為待計算的顏色,這才出現了錯誤。
為了解決這個問題,我們需要一種叫Transparent Blend的技術。其實就是定義一下在shader裡面,目前處理的畫素如何與它後面畫素混合。混合模式有很多種:
https://docs.unity3d.com/Manual/SL-Blend.html
我們這次用的是一種叫做Alpha Blend的東西,定義CGPROGRAM外面,它長這樣:
Blend SrcAlpha OneMinusSrcAlpha
它的意思是將源顏色乘上源顏色的透明度,與目標顏色乘(1 - 原顏色的透明度)的結果相加,公式如下:
OutColor = SrcColor * ScrAlpha + DstColor * (1 - SrcAlpha)
或許這有些難以理解,但只要稍微思考一下就好了,將兩個顏色的減淡後疊加在一起,便產生了一種中間色,看起來就好像透過目前的物體看到了後面的物體一樣。
下一步則是要在SubShader的tag區塊內設定shader的渲染通道,以確保在非透明的物體渲染結束後才渲染我們的透明物體。
- Tags
- {
- "Queue" = "Transparent"
- }
如果你跳過了這一步,那麼就會出現一些奇怪的渲染效果。對於好奇心重的同學,歡迎跳過設定渲染通道來看看錯誤效果。
正確的渲染結果,可以透過透明部分看到後面的物體
完整的shader程式碼:
- Shader "Custom/ShaderLearning"
- {
- Properties{
- _MainTex("Main Texture", 2D) = "white"
- }
- SubShader
- {
- Tags
- {
- "Queue" = "Transparent"
- }
- Pass
- {
- Blend SrcAlpha OneMinusSrcAlpha
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- sampler2D _MainTex;
- #include "UnityCG.cginc"
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv: TEXCOORD0;
- };
- struct v2f
- {
- float4 vertex : SV_POSITION;
- float2 uv: TEXCOORD1;
- };
- v2f vert(appdata v)
- {
- v2f o;
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.uv = v.uv;
- return o;
- }
- float4 frag(v2f i) : SV_Target
- {
- return tex2D(_MainTex, i.uv);
- }
- ENDCG
- }
- }
- }
作者:俊銘
專欄地址:https://zhuanlan.zhihu.com/p/86096949
相關文章
- Shader從入門到跑路:顏色自定義輸出、紋理取樣
- Shader從入門到跑路:螢幕後處理效果
- Shader從入門到跑路:實作螢幕扭曲效果
- babel從入門到跑路Babel
- Kotlin從入門到跑路(一)Kotlin
- Shader從入門到跑路:樸實無華的圖形學基礎
- Docker實戰-從入門到跑路Docker
- Django 自定義管理命令:從入門到高階Django
- Vue入門到跑路---VuexVue
- Linux Shell 從入門到刪除根目錄跑路指南Linux
- 《Golang 從入門到跑路》之開發環境搭建Golang開發環境
- Re:《Unity Shader入門精要》13.3全域性霧效--如何從深度紋理重構世界座標Unity
- MySQL 效能壓測工具,從入門到自定義測試項MySql
- VSCode自定義快捷輸入VSCode
- MySQL 效能壓測工具-sysbench,從入門到自定義測試項MySql
- scala 從入門到入門+
- makefile從入門到入門
- VS code 自定義快捷輸入
- Linux 從入門到跑路第二十一講 -- 字串擷取Linux字串
- SDL3 入門(5):紋理渲染
- 給谷歌輸入法增添自定義片語,提高輸入效率谷歌
- 要點3:輸入函式對比與自定義輸入方式函式
- 資料庫運維初入門-SQL Server入門到跑路002-初使用資料庫運維SQLServer
- MyBatis從入門到精通(一):MyBatis入門MyBatis
- 從輸入 URL 到頁面載入完成(前端優化理論篇)前端優化
- kafka從入門到關門Kafka
- Android 自定義 View 之入門篇AndroidView
- hive從入門到放棄(二)——DDL資料定義Hive
- Promise從入門到精通Promise
- LESS從入門到精通
- Git 從入門到精通Git
- SAP從入門到精通
- Python從入門到精通Python
- Thymeleaf從入門到精通
- Eclipse從入門到精通Eclipse
- SA:從入門到入土
- Jdbc從入門到入土JDBC
- vim從入門到精通