本文參考
Creator3D: shader10_解析【Creator3D shader】的正確姿勢(shì)(匯總1)
一五芝、Creator3D:基礎(chǔ)1_一起學(xué)shader_紅色小球
源碼見https://gitee.com/carlosyzy/Creator3D_Mesh_Basics項(xiàng)目中的Tes1示例
1.用法
新建一個(gè)material冤狡,選擇示例中的Effect
這里面Technique只有一個(gè),別的選項(xiàng)先不管志群。創(chuàng)建一個(gè)3D物體,把上面的material替換上去渡处,就能看到變成紅色施无。
2.test1.effect文件內(nèi)容
CCEffect %{
techniques:
- name: opaque
passes:
- vert: general-vs:vert # builtin header
frag: unlit-fs:frag
}%
CCProgram unlit-fs %{
precision highp float;
vec4 frag () {
vec4 color=vec4(1.0,0.0,0.0,1.0);
return color;
}
}%
這里如果在VS CODE中打開容劳,會(huì)自動(dòng)提示安裝一下插件
name對(duì)應(yīng)的就是每一個(gè)technique名字,這里只填了一個(gè)闸度,對(duì)應(yīng)在IDE中也只有一個(gè)竭贩。
每個(gè)technique只有一個(gè)pass。有一些效果莺禁,我們需要多次渲染同一個(gè)物體才能實(shí)現(xiàn)留量,這個(gè)時(shí)候就需要多pass,大部分情況下哟冬,只需要一個(gè)pass就能搞定了楼熄。
在effect格式中的代碼中我們能看見這樣三行代碼,文檔中是這樣寫的:每個(gè) Pass 只有兩個(gè)必填參數(shù):vert 和 frag 聲明了當(dāng)前 pass 使用的 shader, 格式為 片段名:入口函數(shù)名 這個(gè)名字可以是本文件中聲明的 shader 片段名, 也可以是引擎提供的標(biāo)準(zhǔn)頭文件浩峡。其中:
- vert 表示的是頂點(diǎn)著色器的入口函數(shù)
- frag 表示的片元著色器的入口
在示例一中可岂,只是讓物體顯示紅色,所以只要寫片元著色器
CCProgram unlit-fs %{
precision highp float;
vec4 frag () {
vec4 color=vec4(1.0,0.0,0.0,1.0);
return color;
}
}%
這里我改了一下effect內(nèi)容的方法名红符,如下:
frag: unlit-fs111:frag
}%
CCProgram unlit-fs11 %{
報(bào)錯(cuò)了青柄,方法名改成一樣的,就可以了预侯。
1.precision highp float;
float類型在 shaders 中非常重要致开,
所以精度非常重要。更低的精度會(huì)有更快的渲染速度萎馅,但是會(huì)以質(zhì)量為代價(jià)双戳。
你可以選擇每一個(gè)浮點(diǎn)值的精度。
在第一行(precision highp float;)我們就是設(shè)定了所有的浮點(diǎn)值都是高精度糜芳。
但我們也可以選擇把這個(gè)值設(shè)為“低”(precision lowp float;)或者“中”(precision mediump float;)飒货。
2.vec4 frag () 函數(shù)入口
大概寫一下shader中的數(shù)據(jù)類型:float, vec2, vec3, vec4, mat2, mat3, mat4, sampler2D and samplerCube,至于具體的區(qū)別峭竣,我都列出來塘辅,大家可以百度查一下。
3.vec4 color=vec4(1.0,0.0,0.0,1.0);
定義一個(gè)顏色皆撩,其中vec4中的x,y,z,w分別代表顏色的r,g,b,a;我用的是紅色扣墩,大家可以任意設(shè)置(0-1直接的浮點(diǎn)數(shù))
二、Creator3D:基礎(chǔ)2_一起學(xué)shader_變色小球
源碼見https://gitee.com/carlosyzy/Creator3D_Mesh_Basics項(xiàng)目中的Tes2示例
CCEffect %{
techniques:
- name: opaque
passes:
- vert: general-vs:vert # builtin header
frag: unlit-fs:frag
}%
CCProgram unlit-fs %{
precision highp float;
#include <cc-global>
#include <output>
vec4 frag () {
vec4 oldColor=vec4(abs(sin(cc_time.x)),0.2,0.2,1.0);
return CCFragOutput(oldColor);
}
}%
1.cc_time
2.Fragment Ouput
在之前的文章和今天這個(gè)文章的我對(duì)顏色的返回都是直接return:
return oldColor;
當(dāng)然這樣是不標(biāo)準(zhǔn)的扛吞,來看看官方的文檔Effect syntax
為對(duì)接引擎渲染管線呻惕,Creator 提供了 CCFragOutput 工具函數(shù),對(duì)所有無光照 shader滥比,都可以直接在 fs 返回時(shí)類似這樣寫:
#include <output>
vec4 frag () {
vec4 o = vec4(0.0);
// ... do the computation
return CCFragOutput(o);
}
這樣中間的顏色計(jì)算就不必區(qū)分當(dāng)前渲染管線是否為 HDR 流程等亚脆。
如需包含光照計(jì)算,可結(jié)合標(biāo)準(zhǔn)著色函數(shù) CCStandardShading 一起構(gòu)成 surface shader 流程:
#include <shading-standard>
#include <output-standard>
void surf (out StandardSurface s) {
// fill in your data here
}
vec4 frag () {
StandardSurface s; surf(s);
vec4 color = CCStandardShading(s);
return CCFragOutput(color);
}
在此框架下可方便地實(shí)現(xiàn)自己的 surface 輸入盲泛,或其他 shading 算法濒持。
注意:CCFragOutput 函數(shù)一般還是不需要自己實(shí)現(xiàn)键耕,它只起到與渲染管線對(duì)接的作用,且對(duì)于這種含有光照計(jì)算的輸出弥喉,因?yàn)橛?jì)算結(jié)果已經(jīng)在 HDR 范圍郁竟,所以應(yīng)該包含 output-standard 而非 output 頭文件。
3.內(nèi)置函數(shù)
上邊用到了sin函數(shù)由境,這里順帶給大家提供一下shader的內(nèi)置函數(shù)
- radians(degree) : 角度變弧度;
- degrees(radian) : 弧度變角度蓖议;
- sin(angle), cos(angle), tan(angle)
- asin(x): arc sine, 返回弧度 [-PI/2, PI/2];
- acos(x): arc cosine,返回弧度 [0, PI];
- atan(y, x): arc tangent, 返回弧度 [-PI, PI];
- atan(y/x): arc tangent, 返回弧度 [-PI/2, PI/2];
- pow(x, y): x的y次方虏杰;
- exp(x): 指數(shù), log(x):
- exp2(x): 2的x次方, log2(x):
- sqrt(x): x的根號(hào)勒虾;inversesqrt(x): x根號(hào)的倒數(shù)
- abs(x): 絕對(duì)值
- sign(x): 符號(hào), 1, 0 或 -1
- floor(x): 底部取整
- ceil(x): 頂部取整
- fract(x): 取小數(shù)部分
- mod(x, y): 取模纺阔, x - y*floor(x/y)
- min(x, y): 取最小值
- max(x, y): 取最大值
- clamp(x, min, max): min(max(x, min), max);
- mix(x, y, a): x, y的線性混疊, x(1-a) + y*a;
- step(edge, x): 如 x
- smoothstep(edge0, edge1, x): threshod smooth transition時(shí)使用修然。edge0<=edge0時(shí)為0.0笛钝, x>=edge1時(shí)為1.0
- length(x): 向量長度
- distance(p0, p1): 兩點(diǎn)距離, length(p0-p1);
- dot(x, y): 點(diǎn)積愕宋,各分量分別相乘 后 相加
- cross(x, y): 差積玻靡,x[1]y[2]-y[1]x[2], x[2]y[0] - y[2]x[0], x[0]y[1] - y[0]x[1]
- normalize(x): 歸一化, length(x)=1;
- faceforward(N, I, Nref): 如 dot(Nref, I)< 0則N, 否則 -N
- reflect(I, N): I的反射方向中贝, I -2dot(N, I)N, N必須先歸一化
- refract(I, N, eta): 折射囤捻,k=1.0-etaeta(1.0 - dot(N, I) * dot(N, I)); 如k<0.0 則0.0,否則 etaI - (etadot(N, I)+sqrt(k))*N
- matrixCompMult(matX, matY): 矩陣相乘, 每個(gè)分量 自行相乘邻寿, 即 r[i][j] = x[i][j]*y[i][j];矩陣線性相乘蝎土,直接用 *
- lessThan(vecX, vecY): 向量 每個(gè)分量比較 x < y
- lessThanEqual(vecX, vecY): 向量 每個(gè)分量比較 x<=y
- greaterThan(vecX, vecY): 向量 每個(gè)分量比較 x>y
- greaterThanEqual(vecX, vecY): 向量 每個(gè)分量比較 x>=y
- equal(vecX, vecY): 向量 每個(gè)分量比較 x==y
- notEqual(vecX, vexY): 向量 每個(gè)分量比較 x!=y
- any(bvecX): 只要有一個(gè)分量是true, 則true
- all(bvecX): 所有分量是true绣否, 則true
- not(bvecX): 所有分量取反
- texture2D(sampler2D, coord): texture lookup
- texture2D(sampler2D, coord, bias): LOD bias, mip-mapped texture
- texture2DProj(sampler2D, coord):
- texture2DProj(sampler2D, coord, bias):
- texture2DLod(sampler2D, coord, lod):
- texture2DProjLod(sampler2D, coord, lod):
- textureCube(samplerCube, coord):
- textureCube(samplerCube, coord, bias):
- textureCubeLod(samplerCube, coord, lod):
三誊涯、Creator3D:基礎(chǔ)3_一起學(xué)shader_波浪小球
源碼見https://gitee.com/carlosyzy/Creator3D_Mesh_Basics項(xiàng)目中的Tes3示例
CCEffect %{
techniques:
- name: opaque
passes:
- vert: general-vs:vert # builtin header
frag: unlit-fs:frag
}%
//第一個(gè)shader 正常渲染
CCProgram unlit-fs %{
precision highp float;
#include <cc-global>
#include <output>
#include <cc-local-batch>
in vec3 v_position;
vec4 frag () {
vec4 color = vec4(0.0,0.6,1.0,1.0);
//頂點(diǎn)坐標(biāo),法線坐標(biāo)都是基于世界坐標(biāo)系的
if(v_position.y+sin((v_position.x+cc_time.x)*7.0)/40.0> 0.0){
color = vec4(1.0,1.1,1.0,0.0);
}
return CCFragOutput(color);
}
}%
1.in vec3 v_position
首先大家可以先了解一下in和out的蒜撮,in表示傳入暴构,out表示傳出。
在這里是將模型頂點(diǎn)的世界坐標(biāo)傳了進(jìn)來淀弹,從哪里傳進(jìn)來的呢丹壕,答案是頂點(diǎn)著色器(vert: general-vs:vert),在這里咱們沒有自定義頂點(diǎn)著色器薇溃,用的是引擎自帶的默認(rèn)的菌赖。
給大家看一下默認(rèn)頂點(diǎn)著色器的代碼:
precision highp float;
#include <input-standard>
#include <cc-global>
#include <cc-local-batch>
in vec3 a_color;
in vec2 a_texCoord;
#if HAS_SECOND_UV
in vec2 a_texCoord1;
#endif
out vec3 v_position;
out vec3 v_normal;
out vec3 v_tangent;
out vec3 v_bitangent;
out vec2 v_uv;
out vec2 v_uv1;
out vec3 v_color;
vec4 vert () {
StandardVertInput In;
CCVertInput(In);
mat4 matWorld, matWorldIT;
CCGetWorldMatrixFull(matWorld, matWorldIT);
v_position = (matWorld * In.position).xyz;
v_normal = normalize((matWorldIT * vec4(In.normal, 0.0)).xyz);
v_tangent = normalize((matWorld * vec4(In.tangent.xyz, 0.0)).xyz);
v_bitangent = cross(v_normal, v_tangent) * In.tangent.w; // note the cross order
v_uv = a_texCoord;
#if HAS_SECOND_UV
v_uv1 = a_texCoord1;
#endif
v_color = a_color;
return cc_matProj * (cc_matView * matWorld) * In.position;
}
因?yàn)楝F(xiàn)在沒有說到頂點(diǎn)著色器,所以就不做詳細(xì)的說明沐序,大家只要知道片元著色器中的in和頂點(diǎn)著色器中的out是對(duì)應(yīng)的琉用。
//初始化顏色 藍(lán)色
vec4 color = vec4(0.0,0.6,1.0,1.0);
//頂點(diǎn)的y軸坐標(biāo)+正弦值(頂點(diǎn)的x坐標(biāo)+shader運(yùn)行時(shí)間)
//shader運(yùn)行時(shí)間保證同一坐標(biāo)正弦值是變化的堕绩,
//7.0是一個(gè)波浪波動(dòng)速度縮放值,可以手動(dòng)調(diào)整
//40 是波浪高度的縮放值邑时,因?yàn)榍虻拇笮関ec3(1.0,1.0,1.0,),sin介于-1到1直接奴紧,
if(v_position.y+sin((v_position.x+cc_time.x)*7.0)/40.0> 0.0){
color = vec4(1.0,1.1,1.0,0.0);
return CCFragOutput(color);
}
把上述代碼的color改成vec4(1.0,0.0,0.0,0.0),可以看到上半部分的白色變成紅色晶丘。
如果把+cc_time.x
去除黍氮,波浪就不變化了
四、Creator3D:基礎(chǔ)4_一起學(xué)shader_沒有盡頭的路
沒找到源碼浅浮,效果如下
實(shí)際效果就是利用shader實(shí)現(xiàn)一個(gè)透明度變化的效果沫浆,變化規(guī)則是根據(jù)攝像機(jī)的距離,透明度從1到0的一個(gè)變化過程
CCEffect %{
techniques:
- name: opaque
passes:
- vert: general-vs:vert # builtin header
frag: unlit-fs:frag
properties: &props
mainTexture: { value: white }
mainColor: { value: [1, 1, 1, 1], editor: { type: color } }
- name: transparent
passes:
- vert: general-vs:vert # builtin header
frag: unlit-fs:frag
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
blendSrcAlpha: src_alpha
blendDstAlpha: one_minus_src_alpha
properties: *props
}%
CCProgram unlit-fs %{
precision highp float;
#include <output>
#include <cc-global>
in vec2 v_uv;
in vec3 v_position;
uniform sampler2D mainTexture;
uniform Constant {
vec4 mainColor;
};
vec4 frag () {
float dis=distance(cc_cameraPos.xyz,v_position);
//隨著距離增大滚秩,透明度變小
float apha=1.0-(dis-5.0)/50.0;;
vec3 color=mainColor.xyz;
return CCFragOutput(vec4(color,apha) * texture(mainTexture, v_uv));
}
}%
核心代碼如下
//cc_cameraPos creator內(nèi)部提供的专执,相機(jī)的位置,注意需要導(dǎo)入#include <cc-global>
//逐個(gè)頂點(diǎn)判斷與攝像機(jī)的距離
float dis=distance(cc_cameraPos.xyz,v_position);
//隨著距離增大郁油,透明度變小
//5.0 表示從距離攝像機(jī)5.0后開始透明度變化
//50.0表示透明度從1-0的距離為50
//兩個(gè)參數(shù)大家都可以修改
float apha=1.0-(dis-5.0)/50.0;;
vec3 color=mainColor.xyz;
return CCFragOutput(vec4(color,apha) * texture(mainTexture, v_uv));
五本股、其它示例
Creator3D_shader5_代碼如何控制effect中的屬性
Creator3D:shader6_程序員也是會(huì)心動(dòng)的
Creator3D:shader7_盡然還有雙pass這波操作
Creator3D:shader8_這種shader怎樣配標(biāo)題
Creator3D:shader9_這樣的內(nèi)發(fā)光你喜歡不