UnityShader源码2017---学习笔记与自我拓展001

源自FrameDebuggerRenderTargetDisplay

发现一个很好玩的function---ProcessColor。

fixed4 ProcessColor (half4 tex)
{
	half4 col = tex;
	col -= _Levels.rrrr;
	col /= _Levels.gggg-_Levels.rrrr;
	
	col *= _Channels;
	
	if (dot(_Channels,fixed4(1,1,1,1)) == 1.0)
	{
		half c = dot(col,half4(1,1,1,1));
		col = c;
	}
	return col;
}

接下来就开始吹捧之路-----精源码分子

half4 col = tex;这行代码真是精美,增一分过美,减一分欠美。如此吹捧甚是美好,脑仁不疼,膝盖不酸。

首先要注意的是_Levels是个float2.也就是说只有rg有用。

我们先精简function

fixed4 ProcessColor(half4 tex)
{
    half4 col = tex;
    col -= _Levels.rrrr;
    return col;
}

很明显,如果_Levels.x是1,那么col是黑色,如果是-1,则为白色。

接下来再把_Levels部分不全看一下

fixed4 ProcessColor(half4 tex)
{
    half4 col = tex;
    col -= _Levels.rrrr;
    col /= _Levels.gggg-_Levels.rrrr;
    return col;
}

貌似在哪里见过相同的或者说是相似的画面。。。。


_Levels..........难道就是色阶,毕竟色阶的英文就是Level.....

查了一圈也没有找到level的算法。。。哎没有找到。。。看来是我google的方式不对,或者看到了也看不懂。。。

就权当上述就是level算法的一个简易版吧,毕竟是太像了。


接下来继续吹捧源码之路。

_Channels。。。。通道,看到这个就不在迷糊了,rgba通道嘛,

把码再添点。

fixed4 ProcessColor(half4 tex)
{
    half4 col = tex;
    col -= _Levels.rrrr;
    col /= _Levels.gggg-_Levels.rrrr;

    // leave only channels we want to show
    col *= _Channels;
    return col;
}

源码真好,看人家还给留着注释。。。。牛逼牛逼。。。

翻译过来就是“留下我们想显示的那些通道”

是的,如果_Channels.r是1,那么结果就是

UnityShader源码2017---学习笔记与自我拓展001_第1张图片

如果_Channels.rg是1,那么结果就是

UnityShader源码2017---学习笔记与自我拓展001_第2张图片

哇,源码真是牛逼,一下子就分离的通道。呵呵。

似乎有些不妥,如果只显示R通道不应该是灰色的么。。。。这好像是美术的日常

fixed4 ProcessColor(half4 tex)
{
    half4 col = tex;
    col -= _Levels.rrrr;
    col /= _Levels.gggg-_Levels.rrrr;

    // leave only channels we want to show
    col *= _Channels;
    // if we're showing only a single channel, display that as grayscale
    if (dot(_Channels,fixed4(1,1,1,1)) == 1.0)
    {
      half c = dot(col,half4(1,1,1,1));
      col = c;
    }
    

    return col;
}

源码注释:如果只想显示一个通道,我们就让它以灰度图显示

dot(_Channels,fixed4(1,1,1,1)) 这个的意思就是判断是否只显示一个通道,并且显示的比重是1,这个一目了然。

如果_Channels是(0.5,0,0,0),那么,不好意思,还是红红地显示一个R通道的一半值

half c = dot(col,half4(1,1,1,1));这个也挺有意思的。如果_Channels的四个分量有且只有一个分量为1,其余为0的话,col在上一步col*=_Channles里已经摒弃了gba通道信息。那么这次dot的值就只是个r通道的值。


什么?什么?什么?你要问shader里if和step的问题?我眼睛近视,听不到。


写这么一篇不是为了什么,只是觉得山不在高,在于灵;水不在深,在于龙,码不在长,在于短。


接下来再把其余部分的知识点说一下,希望一起学习的人或者将要学习的人,有个方便之路。总之PBR我要放到最后,这个实在是我的小短腿。

_MainTex ( "" , any ) = "white" {}

和这一点

struct appdata {
float4 vertex : POSITION ;
float3 uv : TEXCOORD0 ;
};

struct v2f {
float4 pos : SV_POSITION ;
float3 uv : TEXCOORD0 ;
};

把_MainTex设置为any,然后uv是float3,这几点还是挺微秒的。微妙之处就不说了,说一下目的吧

就是为了通用。如此操作,可以是2D texture 可以是3Dtexture,可以是cubemap,所以uv可能是float2,也可能是float3.

再说一个Tags

Tags { "ForceSupported" = "True" }

这个Tag的意思就是只要你的显卡支持这个subshader,那么不管你怎么设置的,都会强制支持。

static ShaderLab::IntShader* ShaderFromParseShader (const ShaderLab::ParserShader* parsed, ShaderPtrVector& dependenciesTable, bool useDependenciesTable, ShaderErrors& outErrors)
{
	AssertIf( !parsed );


	#if UNITY_EDITOR
	// In the editor, we want to mark up some shaders as "always will be supported",
	// no matter what the graphics emulation options say. For those shaders,
	// bump up the graphics caps here, and restore them after loading the shader.
	bool forceSupported = false;
	if (parsed && !parsed->m_SubShaders.empty() && parsed->m_SubShaders[0]->m_Tags.find (GetShaderTagID("ForceSupported")) != parsed->m_SubShaders[0]->m_Tags.end())
		forceSupported = true;
	GraphicsCaps oldGraphicsCaps;
	if (forceSupported)
	{
		oldGraphicsCaps = gGraphicsCaps;
		gGraphicsCaps.InitializeOriginalEmulationCapsIfNeeded(); // force initialization of gOriginalCaps
		gGraphicsCaps = gOriginalCaps;
	}
	#endif


	// create ShaderLab shader from the parser representation
	IntShader* shader = IntShader::CreateFromParsedShader (*parsed, dependenciesTable, useDependenciesTable, outErrors);

	#if UNITY_EDITOR
	if (forceSupported)
	{
		gGraphicsCaps = oldGraphicsCaps;
	}
	#endif

	if (!shader)
		return NULL;

	if (shader->GetSubShaders().empty())
	{
		if (!parsed->m_DisableNoSubshadersMessage)
		{
			outErrors.AddShaderError ("No subshaders can run on this graphics card", -1, true);
		}
		UNITY_DELETE( shader, kMemShader);
		return NULL;
	}

	return shader;
}

这个shader最后一个知识点

UNITY_DECLARE_TEX2DARRAY (_MainTex);
half4 tex = UNITY_SAMPLE_TEX2DARRAY (_MainTex, i.uv.xyz);

这个是HLSLSupport里的。

额。。。好像从来没有用的2DTex Array。。。嗯。。要不就跳过吧。。。知识短板。

不知道该说什么,就是sample 2Dtexarray的方法,跟tex2D应该是一个层级的function吧


你可能感兴趣的:(UnityShader源码2017---学习笔记与自我拓展001)