WebGL实践篇(九)—— 光照:点光源
1.点光源的光照值
光照来源于点,太阳也算是一个点光源,光照射到物体的同一面上有明有暗(即光照值不同),将面上的每个点到光源的矢量与法向量点乘得到的值就是光照值。
顶点着色器:
主要添加了光照位置的参数,并将顶点着色器中求出来的光照向量传值给着色器进行渲染。
<script id="vertex-shader-3D" type="x-shader/x-vertex">attribute vec4 a_position;attribute vec3 a_normal;//光源位置uniform vec3 u_lightWorldPosition;uniform mat4 u_world;uniform mat4 u_worldViewProjection;uniform mat4 u_worldInverseTranspose;varying vec3 v_normal;varying vec3 v_surfaceToLight;void main(){gl_Position = u_worldViewProjection * a_position;v_normal = mat3(u_worldInverseTranspose) * a_normal;vec3 surfaceWorldPosition = (u_world * a_position).xyz;v_surfaceToLight = u_lightWorldPosition - surfaceWorldPosition;}</script>
片段着色器(比较重要的就是点乘获取光照值进行渲染):
<script id="fragment-shader-3D" type="x-shader/x-fragment">precision mediump float;varying vec3 v_normal;varying vec3 v_surfaceToLight;uniform vec4 u_color;void main() {vec3 normal = normalize(v_normal);vec3 surfaceToLightDirection = normalize(v_surfaceToLight);float light = dot(normal, surfaceToLightDirection);gl_FragColor = u_color;gl_FragColor.rgb *= light;} </script>
获取参数以及设定
var MVPUniformLocation = webgl.getUniformLocation(program, "u_worldViewProjection");var worldUniformLocation = webgl.getUniformLocation(program, "u_world");var worldITUniformLocation = webgl.getUniformLocation(program, "u_worldInverseTranspose");var lightPUniformLocation = webgl.getUniformLocation(program, "u_lightWorldPosition");//投影矩阵var projectionMatrix = m4.perspective(fieldofViewInRadians, webgl.canvas.clientWidth / webgl.canvas.clientHeight, 1, 2000);var cameraPosition = [100, 150, 200];var targetPosition = [0, 35, 0];var up = [0, 1, 0];//相机矩阵var cameraMatrix = m4.lookAt(cameraPosition, targetPosition, up);//视图矩阵var viewMatrix = m4.inverse(cameraMatrix);//视图投影矩阵var viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);//模型矩阵var worldMatrix = m4.yRotation(fRotationRadians);var worldInverseMatrix = m4.inverse(worldMatrix);var worldInverseTransposeMatrix = m4.transpose(worldInverseMatrix);//模型视图投影矩阵var worldViewProjectionMatrix = m4.multiply(viewProjectionMatrix, worldMatrix);webgl.uniformMatrix4fv(MVPUniformLocation, false, worldViewProjectionMatrix);webgl.uniformMatrix4fv(worldITUniformLocation, false, worldInverseTransposeMatrix);webgl.uniformMatrix4fv(worldUniformLocation, false, worldMatrix);//设置光照方向,光源来源webgl.uniform3fv(lightPUniformLocation, [20, 30, 60]);
结果如下:
2.镜面反射
如果入射角和反射角恰好与眼睛和光源的夹角相同,那么光线就会反射到眼前且会特别亮,就如镜子一般。将halfVector向量与物体表面法向量点乘,+1表示方向一致,0表示垂直,-1表示方向相反;方向一致时,光就会进入人眼。
顶点着色器(加了个相机位置跟物体表面到相机的向量):
<script id="vertex-shader-3D" type="x-shader/x-vertex">attribute vec4 a_position;attribute vec3 a_normal;//光源位置uniform vec3 u_lightWorldPosition;//相机位置uniform vec3 u_viewWorldPosition;uniform mat4 u_world;uniform mat4 u_worldViewProjection;uniform mat4 u_worldInverseTranspose;varying vec3 v_normal;varying vec3 v_surfaceToLight;varying vec3 v_surfaceToView;void main(){gl_Position = u_worldViewProjection * a_position;v_normal = mat3(u_worldInverseTranspose) * a_normal;vec3 surfaceWorldPosition = (u_world * a_position).xyz;v_surfaceToLight = u_lightWorldPosition - surfaceWorldPosition;v_surfaceToView = u_viewWorldPosition - surfaceWorldPosition;}</script>
片段着色器(主要是halfVector和specular):
<script id="fragment-shader-3D" type="x-shader/x-fragment">precision mediump float;varying vec3 v_normal;varying vec3 v_surfaceToLight;varying vec3 v_surfaceToView;uniform vec4 u_color;void main() {vec3 normal = normalize(v_normal);vec3 surfaceToLightDirection = normalize(v_surfaceToLight);vec3 surfaceToViewDirection = normalize(v_surfaceToView);vec3 halfVector = normalize(surfaceToLightDirection + surfaceToViewDirection);float light = dot(normal, surfaceToLightDirection);float specular = dot(normal,halfVector);gl_FragColor = u_color;gl_FragColor.rgb *= light;//加上高光gl_FragColor.rgb += specular;} </script>
参数设置:
var viewPUniformLocation = webgl.getUniformLocation(program, "u_viewWorldPosition");webgl.uniform3fv(viewPUniformLocation, cameraPosition);
结果如下:
太亮啦!那我们调整一下吧
3. 镜面光的优化
将高光从线性变换变成指数变换,即 y = pow(x,a),a越大,图中阴影面积就越小,越接近指数变换,a越小阴影面积就越接近整个矩形,这样光照就变强了。
只用修改片段着色器:
light的点乘结果有可能为赋值,这里只取正值做高光的计算,如果为负的话,高光设为0
<script id="fragment-shader-3D" type="x-shader/x-fragment">precision mediump float;varying vec3 v_normal;varying vec3 v_surfaceToLight;varying vec3 v_surfaceToView;uniform vec4 u_color;uniform float u_shininess;void main() {vec3 normal = normalize(v_normal);vec3 surfaceToLightDirection = normalize(v_surfaceToLight);vec3 surfaceToViewDirection = normalize(v_surfaceToView);vec3 halfVector = normalize(surfaceToLightDirection + surfaceToViewDirection);float light = dot(normal, surfaceToLightDirection);//float specular = dot(normal,halfVector);float specular = 0.0;if(light>0.0){specular = pow(dot(normal,halfVector),u_shininess);}gl_FragColor = u_color;gl_FragColor.rgb *= light;gl_FragColor.rgb += specular;} </script>
设置参数:
var shininessUniformLocation = webgl.getUniformLocation(program, "u_shininess");var shininess = 150;webgl.uniform1f(shininessUniformLocation, shininess);
结果如下:
看 仿佛一个小灯。
4. 光源颜色的修改
片段着色器(加了光源颜色和高光颜色):
<script id="fragment-shader-3D" type="x-shader/x-fragment">precision mediump float;varying vec3 v_normal;varying vec3 v_surfaceToLight;varying vec3 v_surfaceToView;uniform vec4 u_color;uniform float u_shininess;uniform vec3 u_lightColor;uniform vec3 u_specularColor;void main() {vec3 normal = normalize(v_normal);vec3 surfaceToLightDirection = normalize(v_surfaceToLight);vec3 surfaceToViewDirection = normalize(v_surfaceToView);vec3 halfVector = normalize(surfaceToLightDirection + surfaceToViewDirection);float light = dot(normal, surfaceToLightDirection);//float specular = dot(normal,halfVector);float specular = 0.0;if(light>0.0){specular = pow(dot(normal,halfVector),u_shininess);}gl_FragColor = u_color;gl_FragColor.rgb *= light * u_lightColor;gl_FragColor.rgb += specular * u_specularColor;} </script>
参数设置:
var lightColorUnifromLoation = webgl.getUniformLocation(program, "u_lightColor");var specularColorUniformLocation = webgl.getUniformLocation(program, "u_specularColor");webgl.uniform3fv(lightColorUnifromLoation, m4.normalize([1, 0.6, 0.6]));webgl.uniform3fv(specularColorUniformLocation, m4.normalize([1, 0.2, 0.2]));
结果如下:
将~暖光来了。
WebGL实践篇(九)—— 光照:点光源相关推荐
- unity 烘焙参数 设置_Unity通用渲染管线(URP)系列(九)——点光源和聚光灯
200+篇教程总入口,欢迎收藏: 放牛的星星:[教程汇总+持续更新]Unity从入门到入坟--收藏这一篇就够了zhuanlan.zhihu.com 本文重点内容: 1.支持更多类型的灯光 2.包含实 ...
- WebGL 实践篇(三)—— 二维图形的平移、旋转、缩放
一 平移 (1)平移直接体现在代码当中 在二维当中,平移相当于就是改变x,y的位置. function setRectangle(gl, x, y, width, height) {var x1 = ...
- webgl——给场景添加光
文章目录 前言 光照理论介绍 光照效果 光源类型 反射光颜色 向场景中添加光 向场景中添加环境光和点光源 逐片元光照--更加逼真 总结 前言 在之前的学习中已经将三维物体添加到了场景中,但是并没有在场 ...
- WebGL展示3D房屋内景
由于生活和工作上的原因,从年前开始一直到处奔波,没有太多的时间去关注和学习WebGL图形学相关的技术, 不过陆陆续续都有学习使用blender进行3D建模, 而这篇文章涉及到的房屋内景3D建模就是我 ...
- threejs添加立方体_前端图形学(三十)——从源码去看threejs中的光照模型
欢迎来到[畅哥聊技术]前端图形学相关技术文章,更多精彩内容持续更新中,敬请关注. 上章节回顾 熟悉了threejs中内置的几何图形的渲染原理就是通过顶点渲染 传入自定义顶点渲染自定义的几何图形 本章目 ...
- 【教程汇总+持续更新】Unity游戏开发从入门到入坟
新的一年,本该在年前整理的年终总结被拖到了年后开工.去年大量时间投入在Catlike教程的翻译上,截止目前位置,教程的进度已经完全追平原作者. 去年还有一部分是断断续续的更新SLG实战教程,但遗憾的是 ...
- API理解清晰(转载)
1.API的概念: AIP全称(Aplication Programming Interface),一般来说就是 软件组件之间信息交互的桥梁. 2.举个例子: 假如你有一个银行,客户想 ...
- API是什么?有哪些常见的API?
转自 https://blog.csdn.net/cumtdeyurenjie/article/details/80211896#t2 和https://blog.csdn.net/weixin_38 ...
- 什么是API,API的概念
1.API的概念: AIP全称(Aplication Programming Interface),一般来说就是 软件组件之间信息交互的桥梁. 2.举个例子: 假如你有一个银行,客户想 ...
最新文章
- c语言程序解决生活中的问题作文,生活中烦恼的事五年级满分作文
- xml配置linux启动脚本,linux中利用Shell脚本实现自动安装部署weblogic服务
- MySQL工作中的实际用_数据库在工作中的应用,以及什么是MySQL?
- 146. LRU Cache
- MyBatis 缓存详解-一级缓存的不足
- [蓝桥杯][2013年第四届真题]核桃的数量-枚举(水题)
- [crypto][ipsec] 简述ESP协议的sequence number机制
- nbu WIN平台下面(mtx/robtest/tar/nt_ttu)手动测试driver是否正常
- New ipad与ipad2有何不同
- (tip_修订0618)bmp 32位转24位
- 迄今为止2020年AI的奋斗与成功
- Windows中ActiveX控件注册的方法
- 一、Fiddler抓包工具 — Fiddler介绍与安装
- Linux中文件颜色代表类型
- 繁体字转换 java_java代码实现简体繁体转换
- 赛码输入输出java_(赛码编程)博弈问题
- 梦想经不起等待 -- 美文转载
- 情感天地——《不能牵手就握手吧》
- 2019年04月01日_拔剑-浆糊的传说_新浪博客
- ARMV8体系结构简介:预备知识