逐像素高光反射

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ABigDeal/article/details/81537114

//逐像素光照
Shader "Unity Shader Book/Chapter 6/Specular Vertex_Leve2"
{
	Properties
	{
		_Diffuse("Diffuse",Color) = (1,1,1,1)
		_Specular("Specular",Color) = (1,1,1,1)
		_Gloss("Gloss",Range(8.0,256)) = 20
	}
		SubShader
	{
		Pass
		{
			Tags { "LightMode" = "ForwardBase" }
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "Lighting.cginc"
			fixed4 _Diffuse;
			fixed4 _Specular;
			float _Gloss;

			struct a2v {
				float4 vertex :POSITION;
				float3 normal :NORMAL;
			};

			struct v2f {
				float4 pos:SV_POSITION;
				float3 worldNormal:TEXCOORDO;
				float3 worldPos:TEXCOORD1;
			};
			v2f vert(a2v v){
				v2f o;
				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
				o.worldNormal = mul(v.normal, (float3x3)_World2Object);
				o.worldPos = mul(_Object2World, v.vertex).xyz;
				return o;
			}
			fixed4 frag(v2f i) :SV_Target{
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
				fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);

				fixed3 diffuse = _LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal, worldLightDir));

				fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
				fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
				fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(saturate(dot(reflectDir, viewDir)), _Gloss);

				return fixed4(ambient + diffuse + specular, 1.0);
			}
				ENDCG
		}
	}
		
}

展开阅读全文

关于glsl像素光照的问题

02-02

为了实现法线贴图弄的着色器,画模型的时候用的立即模式,法线用glNormal3fv指定了(模型格式里有法线数据),切线用glVertexAttrib3fv指定了(拿的相邻顶点的坐标相减算出来的)。切线和法线都是世界坐标系下的向量。传入的一致变量(lightpos,eyepos)的坐标都是世界坐标系下的。(其实我是想弄方向光,但是不会计算lightdir,只能拿当前模型世界坐标加上一个很远的距离算出lightpos再在shader里面算lightdir)rnrn得到的光照结果非常的奇怪,不知道为什么,法线贴图是抄来的应该没问题rnrn顶点着色器rn[code=c]rnuniform vec3 lightpos;rnuniform vec3 eyepos;rnvarying vec3 lightvec;rnvarying vec3 halfvec;rnattribute vec3 tangent;rnrnvoid main(void)rnrn vec4 pos = gl_ModelViewMatrix * gl_Vertex;rn pos = pos / pos.w;rnrn vec4 vlightpos = (gl_ModelViewMatrix * vec4(lightpos, 1.0));rn vec4 veyepos = (gl_ModelViewMatrix * vec4(eyepos, 1.0));rnrn vec3 lightdir = normalize(vlightpos.xyz - pos.xyz);rn vec3 eyedir = normalize(veyepos.xyz - pos.xyz);rnrn vec3 n = normalize(gl_NormalMatrix * gl_Normal);rn vec3 t = normalize(gl_NormalMatrix * tangent);rn vec3 b = cross(n, t);rn //t = cross(n, b);rnrn vec3 halfdir = normalize(lightdir + eyedir);rnrn lightvec.x = dot(t, lightdir);rn lightvec.y = dot(b, lightdir);rn lightvec.z = dot(n, lightdir);rn lightvec = normalize(lightvec);rnrn vec3 eyevec;rn eyevec.x = dot(t, eyedir);rn eyevec.y = dot(b, eyedir);rn eyevec.z = dot(n, eyedir);rn eyevec = normalize(eyevec);rnrn halfvec = normalize(lightvec + eyevec);rnrn gl_FrontColor = gl_Color;rn gl_TexCoord[0] = gl_MultiTexCoord0;rn gl_Position = ftransform();rnrn[/code]rn片段着色器rn[code=c]rn//fragment shaderrnuniform sampler2D basetex;rnuniform sampler2D normtex;rnuniform vec4 ambient, diffuse, specular;rnuniform float shiness;rnvarying vec3 lightvec;rnvarying vec3 halfvec;rnrnvoid main(void)rnrn vec3 vlightvec = normalize(lightvec);rn vec3 vhalfvec = normalize(halfvec);rn vec4 baseCol = texture2D(basetex, gl_TexCoord[0].xy); rn vec3 tbnnorm = texture2D(normtex, gl_TexCoord[0].xy).xyz;rn rn tbnnorm = normalize(tbnnorm * 2.0 - vec3(1.0));rnrn float diffusefract = max(0.0, dot(vlightvec, tbnnorm));rn float specularfract = max(0.0, dot(vhalfvec, tbnnorm));rn if(specularfract > 0.0)rn rn specularfract = pow(specularfract, shiness);rn rn rn gl_FragColor = gl_Color * vec4(ambient.xyz * baseCol.xyz + rn diffuse.xyz * diffusefract * baseCol.xyz +rn specular.xyz * specularfract, 1.0);rnrn[/code]rnrn固定diffusefract 和specularfract :rn[img=https://img-bbs.csdn.net/upload/201502/02/1422888506_379008.png][/img]rnrn用了法线贴图之后:rn[img=https://img-bbs.csdn.net/upload/201502/02/1422888871_140998.png][/img] 论坛

AlphaBlend到底能不能进行像素Alpha混合

10-21

各位大侠,上午好!rn 本人最近在研究alpha混合问题时遇到了一个难题难以解决,向各位求助。rn我想要达到的效果:假设有两幅图像A和B,两幅图都有各自的图案(假设A中的图案是圆形的)以及背景色。我想将两幅图进行alpha混合,呈现半透明的效果,我只想将A图像中的圆形图案alpha混合到B图像中的一小块区域中去,而A图像的背景不混合,也就是说我只取了A图像的图案部分混合到B图像中。B 图像的其他区域仍是原来的样子不变。rnrn本人尝试过的解决办法:rn1、使用windows GDI的函数AlphaBlendrnAlphaBlend函数的前几个参数不再描述,它的最后一个参数是个结构体,如下:rnBLENDFUNCTION BYTE BlendOp;rn BYTE BlendFlags;rn BYTE SourceConstantAlpha;rn BYTE AlphaFormat;rnBlendOp必须为AC_SRC_OVER,BlendFlags必须为0;后两个参数的设置需要分两种情况。rn情况一: AlphaFormat 设为 0 ,此时进行的alpha混合只需要设定一个alpha值,也就是第3个参数SourceConstantAlpha,这个参数为0时表示完全透明,255时表示完全不透明,0~255之间的值则为半透明效果。rn但是这样做的一个问题就是设置的源图像和目标图像的混合区域都必须是矩形区域,也就是说A图像的背景也会和B图像进行Alpha混合,这是我要避免的,因为这样,A的背景色会影响B中图像的显示效果。并且混合之后B图像中能看到A图像的矩形轮廓,这个不能满足要求。rn也就是说这种整个矩形区域共用一个alpha值混合的方法是行不通的。rnrn情况二:AlphaFormat 设置为 AC_SRC_ALPHA, SourceConstantAlpha设置为255,msdn中说这时候,在混合时将采用per-pixel alpha(逐像素alpha)混合的方法进行混合,也就是说两幅图像的每个像素会根据源图像各个像素中alpha通道的值rn取和目标进行混合(我的图像都是32bit的,具有alpha通道)。rn 这样,我对A图像各个像素的alpha值进行了初始设置,对A图像中的图案区域(假设为圆形图案)的像素点,我将它的alpha值设为127(半透明),实现代码如下rn lpSurface[ x + y * lPitch ] &= 0x00FFFFFF;rn lpSurface[ x + y * lPitch ] |= 0x7F000000;rn而对图案之外的背景(圆外的点)中的各个像素点的alpha值设置为0。rn根据msdn中描述的在这种逐像素混合的计算公式:rn Src.Red = Src.Red * SourceConstantAlpha / 255.0;rn Src.Green = Src.Green * SourceConstantAlpha / 255.0;rn Src.Blue = Src.Blue * SourceConstantAlpha / 255.0;rn Src.Alpha = Src.Alpha * SourceConstantAlpha / 255.0;rn Dst.Red = Src.Red + (1 - Src.Alpha) * Dst.Redrn Dst.Green = Src.Green + (1 - Src.Alpha) * Dst.Greenrn Dst.Blue = Src.Blue + (1 - Src.Alpha) * Dst.Bluern Dst.Alpha = Src.Alpha + (1 - Src.Alpha) * Dst.Alpharn调用AlphaBlend将A图像混合到B上的过程,我设想是这样,A是源,B是目标,根据源的alpha值计算(已设定好)rn 对于A图像中的图案区域(圆内),因为图案区域(圆内)的所有像素点的alpha值为 127,根据公式,混合到目标区域上时,颜色应该能才生半透明的效果。而对于背景色区域(圆外),因为我将背景色的所有像素点的alpha值设为0了,这样根据公式,背景色相当于是完全透明的了,不影响目标的颜色。rn 最终效果按照这个步骤理论上应该是可以达到只混合A图像中的图案,而不混合A的背景色。rnrn但是实际的效果却和我期望的不一样,根据我上面的代码,我在 ATI 显卡(型号没看出来,不会很老)上的试验,描画出来的图像很怪异,覆盖上上面的A图像中的图案区域(圆内)出现不明的条文并遮挡住了B图像,这些条文上颜色单一,并不是A的图案,但是在没有条文的地方B都显现出来了,没条文的地方又似乎A是完全透明了,很奇怪。rnrn2、另外尝试了BitBlt 等通过 与或 或者mask遮挡等方法rn 这些都不能实现真正的透明效果,这些方法只是简单的对两幅图像的颜色合并了,要么就是去掉某幅图像背景色,然后将它覆盖在另外一副图像上,所以都不会有透明效果。想要透明效果必须操作alpha。rnrnrn对msdn中AlphaBlend函数及BLENDFUNCTION结构体的的描述看了很多很多遍,感觉使用方法没出错,到底问题出在哪,各位csdn的大侠们帮忙看看,出点主意,谢谢了。rn函数的参数SourceConstantAlpha为0~255间的整数,Src.Alpha也应该是这么个范围,为什么公式中可以有rnDst.Blue = Src.Blue + (1 - Src.Alpha) * Dst.Blue,这其中的怎么可以有 1- Src.Alpha了,不明白了。rnrn如果我的描述不清,你也可以参考之前别人写的一篇帖子。rnrn他的描述如下:rn楼主DelphiBoy2003(努力提升功力中)2005-09-05 15:35:21 在 Delphi / 语言基础/算法/系统设计 提问rnrn我现在有三副图片,其中一副为背景图,另外两幅图是一个需要透明的图片和一个掩码图片,这两幅图片进行透明贴图操作,并且需要把得到的透明贴图使用 AlphaBlend函数贴到背景图片上,我举例吧,我的一副图片是一个圆形,并且另外一副图片是这个圆形的掩码图片,背景图是一个风景图片,我现在想的是把这个圆形的贴图使用Alpha运算贴到背景图上,我写的代码无论如何只能实现没有透明前的圆形(也就是包含了边界的矩形区域的图片)Alpha的贴到背景图片上,并不能只贴一个圆形到背景图片上!rnrn3 楼Idle_(阿呆)回复于 2005-09-06 12:43:16 得分 5rnrn去看一下 Graphics.TransparentStretchBlt的实现你就知道怎么做了Toprn4 楼Linux2001(闭关开发中)回复于 2005-09-09 16:02:41 得分 40rnrn我发一个Demo给你,把邮箱告诉我rnrn参考连接rnhttp://topic.csdn.net/t/20050905/15/4250543.htmlrnrn这是之前有人发过的一个类似的帖子,可是这里面的4楼我找不到联系方式了,有人能通过昵称之类的找到他的空间吗/ 论坛

AlphaBlend到底能不能进行像素的Alpha混合

10-21

各位大侠,上午好!rn 本人最近在研究alpha混合问题时遇到了一个难题难以解决,向各位求助。rn我想要达到的效果:假设有两幅图像A和B,两幅图都有各自的图案(假设A中的图案是圆形的)以及背景色。我想将两幅图进行alpha混合,呈现半透明的效果,我只想将A图像中的圆形图案alpha混合到B图像中的一小块区域中去,而A图像的背景不混合,也就是说我只取了A图像的图案部分混合到B图像中。B图像的其他区域仍是原来的样子不变。rnrn本人尝试过的解决办法:rn1、使用windows GDI的函数AlphaBlendrnAlphaBlend函数的前几个参数不再描述,它的最后一个参数是个结构体,如下:rnBLENDFUNCTION BYTE BlendOp;rn BYTE BlendFlags;rn BYTE SourceConstantAlpha;rn BYTE AlphaFormat;rnBlendOp必须为AC_SRC_OVER,BlendFlags必须为0;后两个参数的设置需要分两种情况。rn情况一: AlphaFormat 设为 0 ,此时进行的alpha混合只需要设定一个alpha值,也就是第3个参数SourceConstantAlpha,这个参数为0时表示完全透明,255时表示完全不透明,0~255之间的值则为半透明效果。rn但是这样做的一个问题就是设置的源图像和目标图像的混合区域都必须是矩形区域,也就是说A图像的背景也会和B图像进行Alpha混合,这是我要避免的,因为这样,A的背景色会影响B中图像的显示效果。并且混合之后B图像中能看到A图像的矩形轮廓,这个不能满足要求。rn也就是说这种整个矩形区域共用一个alpha值混合的方法是行不通的。rnrn情况二:AlphaFormat 设置为 AC_SRC_ALPHA, SourceConstantAlpha设置为255,msdn中说这时候,在混合时将采用per-pixel alpha(逐像素alpha)混合的方法进行混合,也就是说两幅图像的每个像素会根据源图像各个像素中alpha通道的值rn取和目标进行混合(我的图像都是32bit的,具有alpha通道)。rn 这样,我对A图像各个像素的alpha值进行了初始设置,对A图像中的图案区域(假设为圆形图案)的像素点,我将它的alpha值设为127(半透明),实现代码如下rn lpSurface[ x + y * lPitch ] &= 0x00FFFFFF;rn lpSurface[ x + y * lPitch ] |= 0x7F000000;rn而对图案之外的背景(圆外的点)中的各个像素点的alpha值设置为0。rn根据msdn中描述的在这种逐像素混合的计算公式:rn Src.Red = Src.Red * SourceConstantAlpha / 255.0; rn Src.Green = Src.Green * SourceConstantAlpha / 255.0; rn Src.Blue = Src.Blue * SourceConstantAlpha / 255.0; rn Src.Alpha = Src.Alpha * SourceConstantAlpha / 255.0; rn Dst.Red = Src.Red + (1 - Src.Alpha) * Dst.Red rn Dst.Green = Src.Green + (1 - Src.Alpha) * Dst.Green rn Dst.Blue = Src.Blue + (1 - Src.Alpha) * Dst.Blue rn Dst.Alpha = Src.Alpha + (1 - Src.Alpha) * Dst.Alpha rn调用AlphaBlend将A图像混合到B上的过程,我设想是这样,A是源,B是目标,根据源的alpha值计算(已设定好)rn 对于A图像中的图案区域(圆内),因为图案区域(圆内)的所有像素点的alpha值为 127,根据公式,混合到目标区域上时,颜色应该能才生半透明的效果。 而对于背景色区域(圆外),因为我将背景色的所有像素点的alpha值设为0了,这样根据公式,背景色相当于是完全透明的了,不影响目标的颜色。rn 最终效果按照这个步骤理论上应该是可以达到只混合A图像中的图案,而不混合A的背景色。rnrn但是实际的效果却和我期望的不一样,根据我上面的代码,我在 ATI 显卡(型号没看出来,不会很老)上的试验,描画出来的图像很怪异,覆盖上上面的A图像中的图案区域(圆内)出现不明的条文并遮挡住了B图像,这些条文上颜色单一,并不是A的图案,但是在没有条文的地方B都显现出来了,没条文的地方又似乎A是完全透明了,很奇怪。rnrn2、另外尝试了BitBlt 等通过 与或 或者mask遮挡等方法rn 这些都不能实现真正的透明效果,这些方法只是简单的对两幅图像的颜色合并了,要么就是去掉某幅图像背景色,然后将它覆盖在另外一副图像上,所以都不会有透明效果。想要透明效果必须操作alpha。rnrnrn对msdn中AlphaBlend函数及BLENDFUNCTION结构体的的描述看了很多很多遍,感觉使用方法没出错,到底问题出在哪,各位csdn的大侠们帮忙看看,出点主意,谢谢了。rn函数的参数SourceConstantAlpha为0~255间的整数,Src.Alpha也应该是这么个范围,为什么公式中可以有rnDst.Blue = Src.Blue + (1 - Src.Alpha) * Dst.Blue,这其中的怎么可以有 1- Src.Alpha了,不明白了。rnrn如果我的描述不清,你也可以参考之前别人写的一篇帖子。rnrn他的描述如下:rn楼主DelphiBoy2003(努力提升功力中)2005-09-05 15:35:21 在 Delphi / 语言基础/算法/系统设计 提问rnrn我现在有三副图片,其中一副为背景图,另外两幅图是一个需要透明的图片和一个掩码图片,这两幅图片进行透明贴图操作,并且需要把得到的透明贴图使用 AlphaBlend函数贴到背景图片上,我举例吧,我的一副图片是一个圆形,并且另外一副图片是这个圆形的掩码图片,背景图是一个风景图片,我现在想的是把这个圆形的贴图使用Alpha运算贴到背景图上,我写的代码无论如何只能实现没有透明前的圆形(也就是包含了边界的矩形区域的图片)Alpha的贴到背景图片上,并不能只贴一个圆形到背景图片上!rnrn3 楼Idle_(阿呆)回复于 2005-09-06 12:43:16 得分 5rnrn去看一下 Graphics.TransparentStretchBlt的实现你就知道怎么做了Toprn4 楼Linux2001(闭关开发中)回复于 2005-09-09 16:02:41 得分 40rnrn我发一个Demo给你,把邮箱告诉我rnrn参考连接rnhttp://topic.csdn.net/t/20050905/15/4250543.htmlrnrn这是原贴,可是这里面的4楼我找不到联系方式了,有人能通过昵称之类的找到他的空间吗/ 论坛

没有更多推荐了,返回首页