问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何学习shader

发布网友 发布时间:2022-04-12 15:56

我来回答

3个回答

懂视网 时间:2022-04-12 20:17

这篇文章将收集unity中使用shader的相关技巧和特效,会不断地更新内容。关于在Unity中使用shader的介绍,请参考《【OpenGL】使用Unity来学习OpenGL》 常用的内置uniform iResolution =》_ScreenParams iGlobalTime = _Time.y glFragCoord = f loat4 sp:WPOS

这篇文章将收集unity中使用shader的相关技巧和特效,会不断地更新内容。关于在Unity中使用shader的介绍,请参考《【OpenGL】使用Unity来学习OpenGL》

常用的内置uniform

iResolution =》_ScreenParams

iGlobalTime => _Time.y

glFragCoord => float4 sp:WPOS // 需要 #pragma target 3.0, 另外的方式请见下面

vec2 => float2

mix => lerp

mod => fmod

texture2D => tex2D

textureCube => texCUBE

mat2=>float2x2

fract=>frac

========

关于glFragCoord, 可以使用另外一种方式计算(支持3.0之前的)参考官方例子

o.scrPos = ComputeScreenPos(o.pos);

float2 wcoord = (i.scrPos.xy/i.scrPos.w);

-------

float2 wcoord = sp.xy/_ScreenParams.xy;


关于数学的Shader:https://www.shadertoy.com/view/ldlSD2 https://www.shadertoy.com/view/ldlSWj


很好的一个教程:http://ogldev.atspace.co.uk/index.html


Deferred Shading 原理: http://ogldev.atspace.co.uk/www/tutorial35/tutorial35.html


关于Stencil Buffer 的理解:http://www.cnblogs.com/mikewolf2002/archive/2012/05/15/2500867.html

更多文章:1)http://docs.unity3d.com/Manual/SL-Stencil.html

2) http://answers.unity3d.com/questions/590800/how-to-cullrender-to-through-a-window.html


Stencil Shadow Volume : http://ogldev.atspace.co.uk/www/tutorial40/tutorial40.html

http://en.wikipedia.org/wiki/Shadow_volume


镜面反射的实现原理:

ftp://ftp.sgi.com/sgi/opengl/contrib/blythe/advanced99/notes/node158.html

其它镜面反射:

http://en.wikibooks.org/wiki/Cg_Programming/Unity/Mirrors


在unity cg中可以使用[HideInInspector]来隐藏uniform属性,这样就可以用作自定义常量。

Physically Based Rendering: Tutorial: Physically Based Rendering, And you can too!

边缘检测:1) http://www.codeproject.com/Articles/94817/Pixel-Shader-for-Edge-Detection-and-Cartoon-Effect

2) http://coding-experiments.blogspot.hk/2010/06/edge-detection.html

3) http://en.wikipedia.org/wiki/Edge_detection

Cg函数表:http://http.developer.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html

heat effect : http://forum.unity3d.com/threads/50132-Heat-Distortion, http://www.cnblogs.com/geoffyange/archive/2013/06/06/3122570.html

skin shading in unity: http://www.altdevblogaday.com/2011/12/31/skin-shading-in-unity3d/

http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html

http://gamedev.stackexchange.com/questions/31308/algorithm-for-creating-spheres

RenderMan University: http://renderman.pixar.com/view/renderman-university

一些shader的例子:











Shader "stalendp/shaderTest02" { //see https://www.shadertoy.com/view/4sj3zy
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
	}
	SubShader {
		Pass {
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma target 3.0
			
			#include "UnityCG.cginc"

			sampler2D _MainTex;
		
			//Variable declarations
			
			struct myvars {
				float3 bgColor;
				float sphereScale;
				float sphereShine;
				float3 sphereDiff;
				float3 sphereSpec;
				float2 specPoint;
			};

			float4 vert(appdata_base v) : POSITION {
				return mul(UNITY_MATRIX_MVP, v.vertex);
			}
			
			float4 frag(float4 sp:WPOS): COLOR {
				myvars mv;
				mv.bgColor = float3(0.6, 0.5, 0.6);
				mv.sphereScale = 0.7;
				mv.sphereShine = 0.5;
				mv.sphereDiff = float3(0.5, 0.0, 0.5);
				mv.sphereSpec = float3(1.0, 1.0, 1.0);
				mv.specPoint = float2(0.2, -0.1);
			
				// creates shader pixel coordinates
				float2 uv = sp.xy/_ScreenParams.xy;
				// sets the position of the camera
				float2 p = uv * 2.5 - float2(1.0, 1.0);
				p.x *= _ScreenParams.x / _ScreenParams.y;
				
				// Rotates the sphere in a circle
				p.x += cos(-_Time.y) *0.35;
				p.y += sin(-_Time.y) * 0.35;
				
				// Rotates the specular point with the sphere
				mv.specPoint.x += cos(-_Time.y) * 0.35;
				mv.specPoint.y += sin(-_Time.y) * 0.35;
				
				//Sets the radius of the sphere to the middle of the screen
				float radius = length(p);//sqrt(dot(p, p));
	
				float3 col = mv.bgColor;
	
				//Sets the initial dark shadow around the edge of the sphere
				float f = smoothstep(mv.sphereScale * 0.7, mv.sphereScale, length(p + mv.specPoint));
				col -= lerp(col, float3(0.0,0.0,0.0), f) * 0.2;
				
				//Only carries out the logic if the radius of the sphere is less than the scale
				if(radius < mv.sphereScale) {
					float3 bg = col;
					
					//Sets the diffuse colour of the sphere (solid colour)
					col = mv.sphereDiff;
					
					//Adds smooth dark borders to help achieve 3D look
					f = smoothstep(mv.sphereScale * 0.7, mv.sphereScale, radius);
					col = lerp(col, mv.sphereDiff * 0.45, f);
					
					//Adds specular glow to help achive 3D look
					f = 1.0 - smoothstep(-0.2, 0.6, length(p - mv.specPoint));
					col += f * mv.sphereShine * mv.sphereSpec;
				
					//Smoothes the edge of the sphere
					f = smoothstep(mv.sphereScale - 0.01, mv.sphereScale, radius);
					col = lerp(col, bg, f);
				}
				
				
				//The final output of the shader logic above
				//gl_FragColor is a vector with 4 paramaters(red, green, blue, alpha)
				//Only 2 need to be used here, as "col" is a vector that already carries r, g, and b values
				return float4(col, 1);
			}
			
			ENDCG
		}
	} 
	FallBack "Diffuse"
}


Shader "Custom/shaderTest03" { // https://www.shadertoy.com/view/Xdf3DS
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
	}
	SubShader {
	
		Pass {
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma target 3.0
			
			#include "UnityCG.cginc"

			sampler2D _MainTex;

			
			struct myvars {
				float k;
				float f;
				float threshold;

				float3 colour;
				float3 normal;

				float3 lightPos;
				float3 lightColour;
				float3 ambient;
				float shinyness;
				float diffuseFactor;
				float4 fragCoord;
			};
			

			float2 center ( float2 border , float2 _offset , float2 vel, myvars mv) {
				float2 c = _offset + vel * _Time * 0.5;
				c = fmod ( c , 2. - 4. * border );
				if ( c.x > 1. - border.x ) c.x = 2. - c.x - 2. * border.x;
				if ( c.x < border.x ) c.x = 2. * border.x - c.x;
				if ( c.y > 1. - border.y ) c.y = 2. - c.y - 2. * border.y;
				if ( c.y < border.y ) c.y = 2. * border.y - c.y;
				return c;
			}
			
			float field ( float b, float r , myvars mv) {
				if ( r > b )
					return 0.0;
				if ( r >= b/3.0 ) {
					float rb = 1.0 - r/b;
					return (3.0*mv.k)/2.0 * rb * rb;
				}
				if ( r >= 0.0 && r <= b/3.0 ) {
					return mv.k * ( 1.0 - ( (3.0*r*r)/(b*b) ) );	
				}
				return 0.0;
			}
			
			void circle ( float r , float2 col , float2 _offset , float2 vel, myvars mv ) {
				float2 pos = mv.fragCoord.xy / _ScreenParams.y;
				float aspect = _ScreenParams.x / _ScreenParams.y;
				float2 c = center ( float2 ( r / aspect , r ) , _offset , vel, mv);
				c.x *= aspect;
				float d = distance ( pos , c );
				float thisField = field (r, d, mv);
				mv.f += thisField;
				mv.colour += float3(col, 0) * thisField;
				mv.normal += normalize(float3(pos.x-c.x, pos.y-c.y,r))*thisField;
			}
						

			float4 vert(appdata_base v) : POSITION {
				return mul(UNITY_MATRIX_MVP, v.vertex);
			}
			
			float4 frag(float4 sp:WPOS): COLOR {
				myvars mv;
				mv.fragCoord = sp;
				mv.k = 100.0;
				mv.f = 0.0;
				mv.threshold = 10.0;

				mv.colour = float3(0.0,0.0,0.0);
				mv.normal = float3(0.0,0.0,0.0);

				mv.lightPos = float3(_ScreenParams.xy,2000.0);
				mv.lightColour = float3(0.9,0.9,1.0);
				mv.ambient = float3(0.1,0.0,0.0);
				mv.shinyness = 20.0;
				mv.diffuseFactor = 0.0006;
			
				circle ( .10 , float3 ( 0.7 , 0.2 , 0.8 ) , float2 ( .6 ) , float2 ( .30 , .70 ), mv );
				circle ( .09 , float3 ( 0.7 , 0.9 , 0.6 ) , float2 ( .1 ) , float2 ( .02 , .20 ), mv );
				circle ( .12 , float3 ( 0.3 , 0.4 , 0.1 ) , float2 ( .1 ) , float2 ( .10 , .04 ), mv );
				circle ( .15 , float3 ( 0.2 , 0.5 , 0.1 ) , float2 ( .3 ) , float2 ( .10 , .20 ), mv );
				circle ( .20 , float3 ( 0.1 , 0.3 , 0.7 ) , float2 ( .2 ) , float2 ( .40 , .25 ), mv );
				circle ( .30 , float3 ( 0.9 , 0.4 , 0.2 ) , float2 ( .0 ) , float2 ( .15 , .20 ), mv );
				
				float3 c;
				
				if (mv.f < mv.threshold)
					c = float3(0.0,0.0,0.0);
				else {
					mv.colour /= mv.f;
					mv.normal = mv.normal/mv.f;
					
					c = mv.ambient;
					float3 lightDir = mv.lightPos - float3(sp.xy,0.0);
					c += mv.colour * mv.diffuseFactor * max(dot(mv.normal,lightDir), 0.0);
					float3 r = normalize ( reflect ( lightDir, mv.normal ) );
					c += mv.lightColour * pow(max(dot(r,float3(0.0,0.0,-1.0)), 0.0), mv.shinyness);	
				}
				return float4(c, 1);
			}
			
			ENDCG
		}
	} 
}

Shader "stalendp/shaderTest04" { //see https://www.shadertoy.com/view/Xsf3R8
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
	}
	SubShader {
		Pass {
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma target 3.0
			
			#include "UnityCG.cginc"

			sampler2D _MainTex;
			
			struct Ray {
				float3 org;
				float3 dir;
			};
			
			float rayPlaneIntersect( Ray ray, float4 plane ) {
				float f = dot( ray.dir, plane.xyz );
				
				float t = -( dot( ray.org, plane.xyz ) + plane.w );
				t /= f;
				
				return t;
			}
			
			float3 shade( float3 pos, float3 nrm, float4 light ) {
				float3 toLight = light.xyz - pos;
				float toLightLen = length( toLight );
				toLight = normalize( toLight );
					
				float diff = dot( nrm, toLight );
				float attn = 1.0 - pow( min( 1.0, toLightLen / light.w ), 2.0 );
				float comb = 2.0 * diff * attn;
				
				return float3( comb, comb, comb );
			}


			float4 vert(appdata_base v) : POSITION {
				return mul(UNITY_MATRIX_MVP, v.vertex);
			}
			
			float4 frag(float4 sp:WPOS): COLOR {
			
				// gl_FragCoord: location (0.5, 0.5) is returned 
				// for the lower-left-most pixel in a window
				
				// XY of the normalized device coordinate
				// ranged from [-1, 1]
				float2 ndcXY = -1.0 + 2.0 * sp.xy / _ScreenParams.xy;
				
				// aspect ratio
				float aspectRatio = _ScreenParams.x / _ScreenParams.y;
				
				// scaled XY which fits the aspect ratio
				float2 scaledXY = ndcXY * float2( aspectRatio, 1.0 );
				
				// camera XYZ in world space
				float3 camWsXYZ = float3( 0.0, 1.0, 0.0 );
				camWsXYZ.z += 10.0 * cos( _Time.y );
				
				// construct the ray in world space
				Ray ray;
				ray.org = camWsXYZ;
				ray.dir = float3( scaledXY, -2.0 ); // OpenGL is right handed
				
				// define the plane in world space
				float4 plane = float4( 0.0, 1.0, 0.0, 0.0 );
				
				float t = rayPlaneIntersect( ray, plane );
				
				// define the point light in world space (XYZ, range)
				float4 lightWs = float4( 0.0, 5.0, -5.0, 10.0 );
				
				if ( t >= 0.0 )
				{
					float3 sceneWsPos = ray.org + t * ray.dir;
					float3 sceneWsNrm = plane.xyz;
					float2 sceneUV = sceneWsPos.xz / 4.0;
					
					float4 sceneBase = tex2D( _MainTex, sceneUV );		
					float3 sceneShade = shade( sceneWsPos, sceneWsNrm, lightWs );
					
					return float4( sceneShade * sceneBase.xyz, 1.0 );
				}
			
				return float4( 0.0, 0.0, 0.0, 1.0 );
			}
			
			ENDCG
		}
	} 
	FallBack "Diffuse"
}


Shader "stalendp/shaderTest04" { //see https://www.shadertoy.com/view/MdB3Dw
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
	}
	SubShader {
		Pass {
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma target 3.0
			
			#include "UnityCG.cginc"
			
			#define USE_ANALYTICAL_MBLUR

			sampler2D _MainTex;
	
			// intersect a MOVING sphere
			float2 iSphere( in float3 ro, in float3 rd, in float4 sp, in float3 ve, out float3 nor )
			{
			 float t = -1.0;
				float s = 0.0;
				nor = float3(0.0);
				
				float3 rc = ro - sp.xyz;
				float A = dot(rc,rd);
				float B = dot(rc,rc) - sp.w*sp.w;
				float C = dot(ve,ve);
				float D = dot(rc,ve);
				float E = dot(rd,ve);
				float aab = A*A - B;
				float eec = E*E - C;
				float aed = A*E - D;
				float k = aed*aed - eec*aab;
					
				if( k>0.0 )
				{
					k = sqrt(k);
					float hb = (aed - k)/eec;
					float ha = (aed + k)/eec;
					
					float ta = max( 0.0, ha );
					float tb = min( 1.0, hb );
					
					if( ta < tb )
					{
			  ta = 0.5*(ta+tb);			
			  t = -(A-E*ta) - sqrt( (A-E*ta)*(A-E*ta) - (B+C*ta*ta-2.0*D*ta) );
			  nor = normalize( (ro+rd*t) - (sp.xyz+ta*ve ) );
			  s = 2.0*(tb - ta);
					}
				}

				return float2(t,s);
			}

			// intersect a STATIC sphere
			float iSphere( in float3 ro, in float3 rd, in float4 sp, out float3 nor )
			{
			 float t = -1.0;
				nor = float3(0.0);
				
				float3 rc = ro - sp.xyz;
				float b = dot(rc,rd);
				float c = dot(rc,rc) - sp.w*sp.w;
				float k = b*b - c;
				if( k>0.0 )
				{
					t = -b - sqrt(k);
					nor = normalize( (ro+rd*t) - sp.xyz );
				}

				return t;
			}

			float3 getPosition( float time ) { return float3( 2.5*sin(8.0*time), 0.0, 1.0*cos(8.0*time) ); }
			float3 getVelocity( float time ) { return float3( 8.0*2.5*cos(8.0*time), 0.0, -8.0*1.0*sin(8.0*time) ); }


			float4 vert(appdata_base v) : POSITION {
				return mul(UNITY_MATRIX_MVP, v.vertex);
			}
			
			float4 frag(float4 sp:WPOS): COLOR {
				float2 q = sp.xy / _ScreenParams.xy;
				float2 p = -1.0 + 2.0*q;
				p.x *= _ScreenParams.x/_ScreenParams.y;	

				// camera
				float3 ro = float3(0.0,0.0,4.0);
			 float3 rd = normalize( float3(p.xy,-2.0) );
				
			 // sphere	
				
				// render
				float3 col = float3(0.0);
				
				#ifdef USE_ANALYTICAL_MBLUR
							
			 //---------------------------------------------------	
			 // render with analytical motion blur
			 //---------------------------------------------------	
				float3 ce = getPosition( _Time.y );
				float3 ve = getVelocity( _Time.y );
			 	
				col = float3(0.25) + 0.3*rd.y;
				float3 nor = float3(0.0);
				float3 tot = float3(0.25) + 0.3*rd.y;
			 float2 res = iSphere( ro, rd, float4(ce,1.0), ve/24.0, nor );
				float t = res.x;
				if( t>0.0 )
				{
					float dif = clamp( dot(nor,float3(0.5703)), 0.0, 1.0 );
					float amb = 0.5 + 0.5*nor.y;
					float3 lcol = dif*float3(1.0,0.9,0.3) + amb*float3(0.1,0.2,0.3);
					col = lerp( tot, lcol, res.y );
				}
				
				#else
				
			 //---------------------------------------------------	
			 // render with brute force sampled motion blur
			 //---------------------------------------------------	
				
			 #define NUMSAMPLES 32
				float3 tot = float3(0.0);
				for( int i=0; i0.0 )
			 {
			  float dif = clamp( dot(nor,float3(0.5703)), 0.0, 1.0 );
			  float amb = 0.5 + 0.5*nor.y;
			  tmp = dif*float3(1.0,0.9,0.3) + amb*float3(0.1,0.2,0.3);
			 }
			 col += tmp;
				}		
				col /= float(NUMSAMPLES);
					
			 #endif
				
				col = pow( clamp(col,0.0,1.0), float3(0.45) );

				return float4( col, 1.0 );
			}
			
			ENDCG
		}
	} 
	FallBack "Diffuse"
}

Shader "stalendp/shaderTest05" { //see https://www.shadertoy.com/view/XsB3DW
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_CubeDiffuse ("Cubemap Diffuse Map", CUBE) = "" {}
		vv1("vv1", float) = -1.0
		vv2("vv2", float) = 2.0
	}
	SubShader {
		Pass {
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma target 3.0
			//下面防止编译错误:instruction limit of 1024 exceed;
			#pragma glsl 
			
			#include "UnityCG.cginc" 
			
			#define MAX_STEPS 64
			#define MAX_REFLECTIONS 4
			#define PI 3.1415926536

			sampler2D _MainTex;
			samplerCUBE _CubeDiffuse;
			float vv1, vv2;
	
			struct Ray {
				float3 o;
				float3 d;
			};
			struct Sphere {
				float3 o;
				float r;
			};
			struct Box {
				float3 o;
				float3 s;
			};
			struct Torus {
				float3 o;
				float2 s;
			};
						
			float2 rotate2d(in float2 v, in float a) {
				float sinA = sin(a);
				float cosA = cos(a);
				return float2(v.x * cosA - v.y * sinA, v.y * cosA + v.x * sinA);	
			}

			float sdSphere(in float3 p, in Sphere s) {
				return length(p-s.o)-s.r;
			}
			float sdBox(in float3 p, in Box b) {
				float3 d = abs(p-b.o) - b.s;
				return min(max(d.x,max(d.y,d.z)),0.0) +
					length(max(d,0.0));
			}
			float sdTorus(in float3 p, in Torus t) {
				p -= t.o;
				float2 q = float2(length(p.xz)-t.s.x,p.y);
				return length(q)-t.s.y;
			}
			float world(in float3 p) {
				float ti = fmod(_Time.y,10.);
				if(ti > 2.) {
					Sphere s0 = Sphere(float3(0),1.);
					Box b0 = Box(float3(0),float3(.8));
					if(ti < 4.) {
						return max(-sdSphere(p,s0),sdBox(p,b0));
					} else if(ti < 6.) {
						return min(sdSphere(p,s0),sdBox(p,b0));
					} else if(ti < 8.) {
						return max(sdSphere(p,s0),sdBox(p,b0));
					} else {
						return max(sdSphere(p,s0),-sdBox(p,b0));
					}
				} else {
					float3 pr = p.xzy;
					return sdTorus(pr, Torus(float3(0),float2(1.,.5)));
				}
			}
			
			float3 getNormal(in float3 p) {
				float3 d = float3(.005,0,0);
				float3 n;
				n.x = world(p+d.xyy);
				n.y = world(p+d.yxy);
				n.z = world(p+d.yyx);
				return normalize(n);
			}

			bool march(in Ray r, out float3 p) {
				p = r.o;
				float d;
				for(int i = 0; i < MAX_STEPS; i++) {
					d = world(p);
					p += r.d*d;
				}
				return d<=0.01;
			}

			float3 colorMarch(in Ray r) {
				float3 p;
				float3 col = float3(0);
				for(int i = 0; i < MAX_REFLECTIONS; i++) {
					if(march(r,p)) {
						float3 ldir = normalize(float3(1,-1,.5));
						float3 n = getNormal(p);
						col += float3(dot(n,-ldir))*.25;
						r = Ray(p,reflect(r.d,n));
						r.o += r.d*0.2;
					} else {
						break;
					}
				}
				col += texCUBE(_CubeDiffuse, r.d).rgb;
				return col;
			}

			float4 vert(appdata_base v) : POSITION {
				return mul(UNITY_MATRIX_MVP, v.vertex);
			}
			
			float4 frag(float4 sp:WPOS): COLOR {
				float2 uv = 2.*sp.xy/_ScreenParams.xy-1.;
				uv.x *= _ScreenParams.x/_ScreenParams.y;
				
				Ray r = Ray(float3(0,0,-2),normalize(float3(uv,1)));
				r.o.xz = rotate2d(r.o.xz,_Time.y*.5);
				r.d.xz = rotate2d(r.d.xz,_Time.y*.5);
				float3 cc =colorMarch(r);

				return float4( cc, 1.0 );
			}
			
			ENDCG
		}
	} 
	FallBack "Diffuse"
}


CGINCLUDE的使用

 




                                        

热心网友 时间:2022-04-12 17:25

学习方法

(1)由简入繁:自己写Shader,从最简单写起,简单的测试通过了,再一点点往里加。
(2)多调试:例如,有一个float变量x。假如x范围是[0,1],则在frag片段函数里输出 float4(x,0,0,1)的颜色,以红色的深浅来观察x的值;如果x范围是[0,1000],则可在frag片段函数里输出 float4(x/1000,0,0,1)的颜色。方法就这么简单,具体根据需要去调整。
(3)结合查看UnityCG.cginc等文件,以及unity的自带Shader,即Build-in Shader。
Build-in Shader下载地址
(4)看看书:建议看本教程的同时,多看看书。推荐英文的The CG Tutorial,也就是中文版的Cg教程_可编程实时图形权威指南
相关教材链接

学习小技巧
(1)查看UnityCG.cginc等文件
使用Vertex and Fragment的CG时,会#include "UnityCG.cginc",用到里面的很多函数,如TRANSFORM_TEX,UNITY_TRANSFER_DEPTH等函数的定义。那么怎么查看这些定义呢?

windows路径:Unity\Editor\Data\CGIncludes
mac路径:右键点击unity图标->show contents->Data->CGIncludes
该文件夹下有Unity关于Shader的库,如UnityCG.cginc,UnityCG.glslinc,Lighting.cginc等。打开
UnityCG.cginc(写字板MONODev等均可),后即可查看相关函数的定义。

(2)电子书的学习技巧
中文电子书,学起来快,好理解,但大多数是影印版。
英文电子书,可以很好的用关键词搜索知识点。

(3)使用#prama only_renderers d3d9 , 限定编译平台。(3)(4)配合使用效果更好

(4)打开编译后的Shader,查看对应的汇编代码或者OpenGL ES代码。
方法:左键单机shader文件,然后在Inspector面板里点击Open Compiled Shader.

热心网友 时间:2022-04-12 18:43

学什么都得用心学
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
倩碧黄油适合哪种肤质的人使用? 倩碧有哪些护肤品比较受女性青睐? 倩碧紧致面霜适合哪些肤质的人使用? 倩碧护肤品适合什么肤质使用? 哪些肤质的人适合使用倩碧卓越润肤乳? 学校发的移动卡,套餐38的送一年宽带 现在卡不想用了,貌似宽带合约没到期... ...我居住浙江,有一个广西的移动卡,移动卡上还捆绑有宽带 我现在在外地我想注销移动卡或者联通卡怎么注销,回不到办卡的地方。 上海最建议去三个景点 为什么叫北京鸭篮球 冬瓜怎么做比较好吃呢?好想吃冬瓜,但又不知道怎么做? 冬瓜可以做成哪些菜? 冬瓜开洋水饺馅做法 开洋冬瓜汤的做法,开洋冬瓜汤怎么做好吃,开洋 开洋冬瓜的做法,开洋冬瓜怎么做好吃,开洋冬瓜 开洋冬瓜怎么做好吃又简单,做法图解分享,乐乐妈 开洋冬瓜的做法步骤图,开洋冬瓜怎么做好吃 酒类销售激励方案奖励名称征集? 女生做羊毛卷合适还是简单 公司管理层激励方案 保险公司活动奖励方案 保险公司年底奖励方案 怎样才能知道,微信好友有没有删掉你,但又不让他知道 公司激励方案奖励名称命名? 微信检测好友是否删除而不被对方知道 opengl 使用多个shader为不同物体着色 保险金额一次性给付 电脑打不开,系统怎么安装 重疾险被保险人已满18岁还18岁生日身故给付金额基本保险金额是什么意思? 笔记本打不开怎么重装系统啊? 苹果手机为什么不能直接打开网页上的ppt文件 皮肤毛孔粗大暗沉怎么办呀 肤色暗沉毛孔粗大怎么调理 怎样解决皮肤暗沉和毛孔粗大怎么办 皮肤暗沉、毛孔粗大改如何改善? 皮肤暗黄,没有光泽,还有黑色素,毛孔粗大,怎么办啊 男士皮肤暗沉毛孔粗大怎么办 毛孔粗大暗沉怎么办 如何解决皮肤暗沉,毛孔粗大,有黑头.具体怎么调养 皮肤暗沉毛孔粗大如何改善 皮肤粗糙暗沉毛孔粗大 皮肤粗糙,毛孔粗大,肤色暗沉怎么办 我想要比较长的名字。 (假如给我三天光明)第一章 假如给我三天光明的文章(海伦.凯勒) 《假如给我三天光明》的文章 &lt;假如给我三天光明&gt;的主要内容 《假如给我三天光明》,主要讲了什么? 假如给我三天的光明小学作文 《假如给我三天光明》这篇文章的大概内容,不要读后感