Dav*_*och 5 shader android opengl-es unity-game-engine ios
我的表面着色器的主要纹理是Google Maps图像图块,类似于:
.
我想用一个单独的纹理替换接近指定颜色的像素.现在正在做的是以下内容:
Shader "MyShader"
{
Properties
{
_MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
_GrassTexture("Grass Texture", 2D) = "white" {}
_RoadTexture("Road Texture", 2D) = "white" {}
_WaterTexture("Water Texture", 2D) = "white" {}
}
SubShader
{
Tags{ "Queue" = "Transparent-1" "IgnoreProjector" = "True" "ForceNoShadowCasting" = "True" "RenderType" = "Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert alpha approxview halfasview noforwardadd nometa
uniform sampler2D _MainTex;
uniform sampler2D _GrassTexture;
uniform sampler2D _RoadTexture;
uniform sampler2D _WaterTexture;
struct Input
{
float2 uv_MainTex;
};
void surf(Input IN, inout SurfaceOutput o)
{
fixed4 ct = tex2D(_MainTex, IN.uv_MainTex);
// if the red (or blue) channel of the pixel is within a
// specific range, get either a 1 or a 0 (true/false).
int grassCond = int(ct.r >= 0.45) * int(0.46 >= ct.r);
int waterCond = int(ct.r >= 0.14) * int(0.15 >= ct.r);
int roadCond = int(ct.b >= 0.23) * int(0.24 >= ct.b);
// if none of the above conditions is a 1, then we want to keep our
// current pixel's color:
half defaultCond = 1 - grassCond - waterCond - roadCond;
// get the pixel from each texture, multiple by their check condition
// to get:
// fixed4(0,0,0,0) if this isn't the right texture for this pixel
// or fixed4(r,g,b,1) from the texture if it is the right pixel
fixed4 grass = grassCond * tex2D(_GrassTexture, IN.uv_MainTex);
fixed4 water = waterCond * tex2D(_WaterTexture, IN.uv_MainTex);
fixed4 road = roadCond * tex2D(_RoadTexture, IN.uv_MainTex);
fixed4 def = defaultCond * ct; // just used the MainTex pixel
// then use the found pixels as the Albedo
o.Albedo = (grass + road + water + def).rgb;
o.Alpha = 1;
}
ENDCG
}
Fallback "None"
}
Run Code Online (Sandbox Code Playgroud)
这是我写过的第一个着色器,它可能不是很高效.我觉得在每个像素的每个纹理上调用tex2D就可以直接抛出那些数据,但是如果没有if/else(我读到的那些对GPU不好),我想不出更好的方法.
这是Unity Surface Shader,而不是片段/顶点着色器.我知道幕后会有一个步骤会为我生成片段/顶点着色器(添加场景的光照,雾等).此着色器应用于100个256x256px地图图块(总共2560x2560像素).草/道路/水纹理也都是256x256像素.
我的问题是:是否有一种更好,更高效的方式来完成我在这里所做的事情?该游戏在Android和iOS上运行.
我不是着色器性能方面的专家,但假设您希望在同一帧中渲染的源图块数量相对较少,那么存储像素替换的结果并重用它可能更有意义。
当您声明生成的图像将与源图块大小相同时,只需使用表面着色器将源图块渲染(尽管没有任何照明,您可能需要考虑使用简单的平面像素着色器!)一次 RenderTexture,然后使用该 RenderTexture 作为世界渲染的源。这样,您只需为每个源图块执行一次昂贵的工作,因此着色器是否得到很好的优化就不再重要了。
如果所有纹理都是静态的,您甚至可以考虑不在运行时执行此操作,而只需在编辑器中将它们转换一次。