AFrame中渲染器的写法

AFrame中渲染器的写法

渲染器在AFrame中作为材质的一个属性使用,全局注册后可以作为一种材质配置在material下
我们知道WebGL是基于OpenGL的,而OpenGL用GLSL(OpenGL Shading Language)这一着色器语言完成着色器工作,因此,WebGL的着色器程序大致与GLSL相同。着色器通常分为几何着色器(Geometry Shader)、顶点着色器(Vertex Shader)、片元着色器(Fragment Shader)等等。由于WebGL基于OpenGL ES 2.0,因此WebGL支持的着色器只有顶点着色器与片元着色器。

渲染器的全局注册

AFRAME.registerShader('my-custom', {
// 用户自定义参数的定义 可以通过Material传参数
  schema: {
    color: {type: 'color', is: 'uniform', default: 'red'},
    opacity: {type: 'number', is: 'uniform', default: 1.0}
  },
// 点元着色器
  vertexShader:
      ` varying vec2 vUv;
		void main() {
			gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
		}`,
// 片元着色器
fragmentShader:
	  ` varying vec2 vUv;
	  // 定义的方法
	  // 数据类型 方法名(){}
	  
	  // 主函数
		void main() {
			gl_FragColor = vec4( color, opacity );
		}`,
});
  • Aframe中本身使用的数据格式为下表中的 A-Frame Type,即Schema中定义的type格式
  • 着色器是一段在GPU中执行的一种Clike语法,顶点着色器对于每个顶点调用一次,片元着色器对于每个片元调用一次。但着色器(点元、片元)语法是GLSL的数据类型。在声明时要注意对应。
  • 一些变量的声明方法:
    uniform 数据类型 变量名 通常用于用户自定义的参数,每个顶点/片元对应相同的值(CPU 和GPU的桥梁)
    varying 数据类型 变量名 只能在点元着色器中获取/计算的参数,最终要传给片元着色器
    attribute 数据类型 变量名 从JavaScript代码传递到顶点着色器中,每个顶点对应不同的值
    常量用const声明就可以
  • 定义时间参数时,GLSL是以毫秒为单位,需要进行转化后再使用
  • float 型和 int型不会进行自动转换,浮点数写成 *.0
  • precision定义精度

Aframe中支持的数据结构

  • 没错 基于three.js开发的Aframe使用的两种数据类型一个是AFrame本身的数据类型。一个是OpenGL的数据类型。和three.js没有半毛钱的关系
A-Frame TypeTHREE TypeGLSL Shader Type
arrayv3vec3
colorv3vec3
intiint
numberffloat
maptmap
timeffloat (milliseconds)
vec2v2vec2
vec3v3vec3
vec4v4vec4

定义在渲染器外的常量

定义在渲染器外且也符合GLSL语法的常量在点元/片元着色器中也可以使用
以点元着色器举例:

const pnoise3 = `……`
vertexShader:
      pnoise3 +`
// 点元着色器的内容
`

内置参数

three.js中的一些默认参数,在Aframe中不用声明,可以直接使用,声明会报错,仅限点元着色器
至少我现在还没有用到过attribute声明变量的情况

  • attribute vec3 position 顶点在物体中的坐标位置
  • attribute vec3 normal 法向量
  • attribute vec2 uv uv 坐标,可用 uv.x 和 uv.y 分别获取顶点的横纵坐标
  • uniform mat3 normalMatrix; 法向矩阵,modelViewMatrix 的反转
  • uniform mat4 model modelMatrix; 模型空间矩阵
  • uniform mat4 viewMatrix; 视图空间矩阵
  • uniform mat4 modelViewMatrix; 模型空间矩阵和视图空间矩阵的组合 (viewMatrix * modelMatrix)
  • uniform mat4 projectionMatrix; 投影矩阵,用于转换 3D 坐标到 2D 平面
  • uniform vec3 cameraPosition; 镜头在 world space 中的位置

点元着色器

  • uv 横纵坐标
    点元着色器中可以直接获得uv(不需要声明), 但是片元着色器中没有,需要通过varying方法抛出。
    它代表了该顶点在UV映射时的横纵坐标。简单地说,一个物体的模型可能很复杂,对其贴图的一个简单有效的方法就是UV映射,将每个面片贴的图统一映射到一张纹理上,记录每个面片贴图在纹理上对应的位置。

uv的计算原理:

vec2 uv = fragCoord.xy / iResolution.xy // 将坐标转换到【0,1】之间
uv = 2.0 * uv - 1.0;// 将坐标转换到[-1,1]之间
  • normal 法线
vec3 vNormal = normalize(normalMatrix * normal);//归一化将法向量映射到 [0,1] 间
  • gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    利用投影矩阵、模型矩阵计算三维模型在二维显示屏上的坐标。position也没有预先定义过,position也是Three.js为我们提供的一个方便。position是顶点在物体坐标系(而不是世界坐标系)中的位置。这就意味着,一个正方体位于世界坐标系的(2, 0, 0)与位于(0, 0, 0)将不会改变任何顶点的position,这个position是相对于正方体的锚点而言的。
    通过调节position调节着色器的渲染位置,通过后面的参数(1.0)调节模型渲染的大小
//一些光照属性在点元着色器中的应用
        uniform vec3 u_LightColor;
        uniform vec3 u_LightDirction;
        uniform vec3 u_AmbientLight;
        uniform vec3 u_Color;
        varying vec4 v_Color;
        void main(){
            gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
            //计算变换后的法向量并归一化
            vec3 newnormal=normalize(vec3(normalMatrix*normal));
            //计算光线方向和法向量的点积
            float nDotL=max(dot(u_LightDirction,newnormal),0.0);
            //计算漫反射光的颜色
            vec3 diffuse=u_LightColor*u_Color.rgb*nDotL;
            //计算环境光产生的反射光的颜色
            vec3 ambient=u_AmbientLight*u_Color.rgb;
            //将以上两者相加作为最终的颜色,需要传给片元着色器渲染
            v_Color=vec4(diffuse+ambient,1.0);

片元着色器

由于Aframe单一Buffer好像没什么需要介绍的

一些没有验证的猜想:

  • 转换顶点坐标到视图空间
void main(){
    vec3 vertex = vec3(1.0,1.0,1.0);
    vec4 vertexCameraSpace = modelViewMatrix * vec4(vertex,1.0);    
}

void main() {
    vec3 light = vec3(1.0,1.0,1.0);
    vec4 lightCameraSpace = viewMatrix * vec4(vertex,1.0);    
}
  • 计算光照
//顶点着色器
varying vec3 vNormal;
void main(){
    vNormal = normal;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
//片元着色器
varying vec3 vNormal;
void main() {
    vec3 color = vec3(1, 1, 0); 
    vec3 light = normalize(vec3(0, 10, 10));
    float dProd = max(0.0,dot(vNormal, light));
    gl_FragColor = vec4(color.r * dProd, color.g * dProd, color.b * dProd, 1.0);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值