磚頭牆壁紋理片元着色器實現(Shader特效7)
最近在研究一個使用片元着色器完成牆壁紋理和排球紋理的例子,在這裏進行總結一些算法和開發過程。
作者:憨豆酒(YinDou),聯繫我[email protected],熟悉圖形學,圖像處理領域,本章的源代碼可在此倉庫中找到: https://github.com/douysu/person-summary 如果大家發現錯誤以及不合理之處,還希望多多指出。
參考內容:
- 《OpenGL ES 3.X 遊戲開發 下卷》
牆壁紋理運行效果
排球紋理運行效果
牆壁紋理基本原理
通過以上的圖片可以這樣計算
1、首先通過每一行的高度計算出每一個頂點的所屬行。奇數行與偶數行的磚塊不能夠重疊,否則看不出效果,所以奇數行相對偶數行有一個偏移量,這也就是需要計算行號的目的了。
2、將一行分解成圖中的1,2,3部分分別計算即可。
排球紋理基本原理
排球紋理原理就不再多講了,與牆壁紋理類似,將經度劃分成8個區域,給定不用顏色,將緯度劃分成3個區域,兩極爲白色。
牆壁紋理代碼部分
commonTexLight.frag
#version 400
#extension GL_ARB_separate_shader_objects : enable//開啓separate_shader_objects
#extension GL_ARB_shading_language_420pack : enable//開啓shading_language_420pack
layout (location = 0) in vec3 vposition;//頂點着色器傳入的頂點位置
layout (location = 1) in vec2 mcLongLat;//頂點着色器傳入的頂點位置(經度,緯度)(偏航角,俯仰角)
layout (location = 0) out vec4 outColor;//輸出到渲染管線的片元顏色值
void main(){//主方法
vec3 bColor=vec3(0.678,0.231,0.129);//磚塊的顏色
vec3 mColor=vec3(0.763,0.657,0.614);//水泥的顏色
vec3 color;//片元的最終顏色
//計算當前位於奇數還是偶數行(這裏的12是指每一行的高度)求得的結果爲0或者1
int row=int(mod((mcLongLat.y+90.0)/12.0,2.0));
//計算當前片元是否在此行區域1中的輔助變量,結果爲0~11將牆壁的每一行分段化
float ny=mod(mcLongLat.y+90.0,12.0);
//每行的磚塊偏移值,奇數行偏移半個磚塊
float oeoffset=0.0;
//當前片元是否在此行區域3中的輔助變量
float nx;
if(ny>10.0){//圖中的1部分
color=mColor;//採用水泥色着色
}else{//圖中的2,3部分
if(row==1){//若爲奇數行則偏移半個磚塊
oeoffset=11.0;
}
//計算當前片元是否在此行區域3中的輔助變量
nx=mod(mcLongLat.x+oeoffset,22.0);
if(nx>20.0){//圖中的2部分
color=mColor;
}else{//圖中的3部分
color=bColor;//採用磚塊色着色
}
} //將片元的最終顏色傳遞進渲染管線
outColor=vec4(color,0);
}
這裏需要注意,傳入的vary有mcLongLat,這是一個vec2類型的變量,第一個值爲緯度,第二個值爲經度(也可以理解爲第一個爲偏航角,第二個值爲俯仰角)
緯度和經度的知識可以看:http://blog.csdn.net/modestbean/article/details/79185457
偏航角和俯仰角的知識可以看:http://blog.csdn.net/modestbean/article/details/79135769
排球紋理代碼部分
#version 400
#extension GL_ARB_separate_shader_objects : enable//開啓separate_shader_objects
#extension GL_ARB_shading_language_420pack : enable//開啓shading_language_420pack
layout (location = 0) in vec3 vposition;//頂點着色器傳入的頂點位置
layout (location = 1) in vec2 mcLongLat;//頂點着色器傳入的頂點位置(偏航角,仰角)
layout (location = 0) out vec4 outColor;//輸出到渲染管線的片元顏色值
void main(){//主方法
vec3 color;
if(abs(mcLongLat.y)>75.0){
color = vec3(1.0,1.0,1.0);//兩邊是白色
}else{
int colorNum = int(mcLongLat.x/45.0);//顏色號
if(colorNum == 0){
color = vec3(1.0,0.0,0.0);//0號顏色
}else if(colorNum == 1){
color = vec3(0.0,1.0,0.0);//1號顏色
}else if(colorNum == 2){
color = vec3(0.0,0.0,1.0);//2號顏色
}else if(colorNum == 3){
color = vec3(1.0,1.0,0.0);//3號顏色
}else if(colorNum == 4){
color = vec3(1.0,0.0,1.0);//4號顏色
}else if(colorNum == 5){
color = vec3(0.0,1.0,1.0);//5號顏色
}else if(colorNum == 6){
color = vec3(0.3,0.4,0.7);//6號顏色
}else if(colorNum == 7){
color = vec3(0.3,0.7,0.2);//7號顏色
}
}
outColor = vec4(color,1.0);//將顏色擴充爲帶Alpha通道的vec4類型
}