Shader高光反射Blinn-Phong模型

Bling-Phong模型的计算公式和Blinn的计算公式是一样的
但是夹角是不一样的.


代码如下:
得到平分线的方法:
用normalize()标准化两个向量的和.
对比图:

// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
Shader"Allen/09-Specular Fragment Blinn-Phong"{
       Properties{
              _Diffuse("_Diffuse Color",Color)=(1,1,1,1)//定义一个颜色.
              _Gloss("_Gloss",Range(8,200))=10//定义一个高光反射的强度
              _GlossColor("_GlossColor",Color)=(0.5,0.5,0.5,1)
       }
       SubShader{
              Pass{
              Tags{"LightMode"="ForwardBase"}//设置光照模式
                     CGPROGRAM
#include   "Lighting.cginc" //这个相当于C#中的Using Unity;引入命名空间.
//可以用他来取得第一个直射光的颜色. _LightColor0
//还能取得第一个直射光的位置 _worldSpaceLightPos0
#pragma   vertex vert
#pragma   fragment frag                    
                      fixed4   _Diffuse; //上面虽然定义了这个属性,但是这里用的时候还是要声明
                      half   _Gloss;
                      fixed4   _GlossColor;
                      struct   a2v {
                           float4  vertex : POSITION;
                            float3   normal : NORMAL;
                     
                     };
                      struct   v2f{
                            float4   position:SV_POSITION;
                            float3   worldNormal:TEXCOORD0;
                            float3   worldVertex:TEXCOORD1;
                           
                     };
                     v2f   vert   (a2v v){
                           v2f f;
                           f.position=UnityObjectToClipPos(v.vertex);             
                            f.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject);
                           f.worldVertex=mul(v.vertex , unity_WorldToObject).xyz;
                           return f;
                           
                     }
                      fixed4   frag (v2f f) : SV_Target{
                            fixed3   ambient=UNITY_LIGHTMODEL_AMBIENT.rgb; //得到环境光
                           //1 得到法线的单位向量
                            fixed3   normalDir= normalize (f.worldNormal);
                           //normalize()可以得到单位长度
                           //mul()可以让他从世界坐标转到模型坐标.
                           //这里的float3x3 可以让他强制转化为三维乘以三维
                           //2 得到直射光的向量
                            fixed3   lightDir= normalize (_WorldSpaceLightPos0.xyz);
                           //对于每一个顶点来说光的位置就是光的方向.因为光源是平行光
                           //这个_WorldSpaceLightPos0是通过上面的标记的Tags和引入的include从系统中得到的.
                           //3 获取漫反射的颜色
                            fixed3   diffuse =_LightColor0.rgb* max ( dot (normalDir,lightDir),0)*_Diffuse.rgb;
                           //_LightColor0是从上面的标记的Tags和引入的include从系统中得到的.
                           //_LightColor0.rgb 里面的rgb分别代表颜色的rgba ,a表示alpha透明的,这里不需要,所以省略
                           //dot,夹角,点乘 另外注释.
                           // 高光反射 Blinn-Phong模型

                           // 得到视野方向
                           //通过_WorldSpaceCamera.xyz就能得到当前相机的位置.
                            fixed3   viewDir= normalize (_WorldSpaceCameraPos.xyz - f.worldVertex);

                           //得到平行光和视野方向的平分线
                            fixed3   halfDir= normalize (lightDir+viewDir);
                           //得到高光反射
                            fixed3   specular = _LightColor0.rgb *   pow ( max ( dot (normalDir,halfDir),0),_Gloss);
                           //5 通过参数把顶点函数的颜色返回给片元函数,让GPU进行渲染.
                            fixed3   temp=(diffuse+ambient +_GlossColor*specular);
                           return   fixed4 (temp,1);
                     }
                     ENDCG
              }
       }
       FallBack"Diffuse"
}      

以下是使用OpenGL实现Blinn-Phong光照模型的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <GL/glut.h> // 材质参数 GLfloat mat_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat mat_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_shininess[] = { 50.0 }; // 光源参数 GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; // 窗口大小 int window_width = 800; int window_height = 600; void init(void) { // 初始化材质参数 glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); // 初始化光源参数 glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); // 启用光照和深度测试 glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); } void display(void) { // 清除颜色缓冲区和深度缓冲区 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 绘制一个立方体 glutSolidCube(2.0); // 交换前后缓冲区 glutSwapBuffers(); } void reshape(int width, int height) { // 设置视口大小 glViewport(0, 0, (GLsizei)width, (GLsizei)height); // 设置投影矩阵 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat)width / (GLfloat)height, 1.0, 100.0); // 设置模型视图矩阵 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); // 更新窗口大小变量 window_width = width; window_height = height; } int main(int argc, char** argv) { // 初始化GLUT库 glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(window_width, window_height); glutInitWindowPosition(100, 100); glutCreateWindow("Blinn-Phong Lighting Model"); // 调用初始化函数 init(); // 注册回调函数 glutDisplayFunc(display); glutReshapeFunc(reshape); // 进入主循环 glutMainLoop(); return 0; } ``` 此代码实现了一个简单的立方体和Blinn-Phong光照模型。其中,材质参数和光源参数可以根据需要进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值