LayaBox2.0使用自定义Shader(WebGL)踩坑系列

11 篇文章 3 订阅
5 篇文章 0 订阅

-前言-

因为工作需要,要在游戏中自定义Shader,去翻论坛的时候发现2.0已经没有官方支持自定义Shader了。

只好研究研究自定义Shader如何实现。这个方法会涉及修改laya.core.js中源代码。如果对Laya2D渲染感兴趣的也可以去看看具体实现。

之前关于阅读Laya源代码的文章提到过,Laya核心帧循环逻辑在Render中的render函数。我们的自定义Shader就要跟laya底层生成的Shader一起渲染。

注意:这个方法目前只适合Shader在舞台最底层的情况,如果需要在舞台中间插入Shader逻辑,对于引擎改动比较大。如果你又闲心,可以去研究研究。需要自定义一个图元提交函数

-相关对象-

Laya底层对于Shader的实现做了一部分封装,要实现自己的Shader也要去遵循这个规则。

Value2D:这个对象中存储Shader对象Texture,对应ID等信息,这里面有个很干的ShaderDefine2D存在,我感觉特别坑,后面会讲到具体是拿来干嘛的。

Mesh2D:这个对象就是我们用来存储buffer的东西了,别人是在注释中说明了,只具备数据存储功能,不具备渲染功能。

Context:这个是渲染对象,我们需要将我们的Shader渲染到什么地方的一个上下文,我们所有的渲染都是到Laya.Render._context,所以这里不会变化。

有了这三个对象,我们就凑齐了,可以初始化我们的核心对象SubmitTexture,我们需要拿着这个对象去申请重绘。

-流程-

初始化Shader程序

Laya中Shader都是通过预编译实现的,实现逻辑对应在Shader2D.__init__

不过我们可以直接new一个Shader对象

//vs:顶点着色器 fs:片元着色器
var shader:Laya.Shader = new Laya.Shader(vs,fs,0x900);
//上面这个0x900是shader的一个id,到时从Shader提交会从数组中取Shader的时候会用到
//这个0x900就跟之前说的Value2D里面很坑的ShaderDefine2D相关

 创建纹理

这一步就比较简单,直接暴力的方式就是直接创建一个Image对象,但是我们只需要其中的WebGLTexture对象

var img:Laya.Image = new Laya.Image("url");

创建自定义Shader渲染对象

  这一步就是核心逻辑了,我们需要创建一个SubmitTexture对象,其中存储之前所说的几个对象。

//1.创建mesh
var mesh:Laya.Mesh2D = new Laya.Mesh2D(5 * Float32Array.BYTES_PER_ELEMENT,4,0);
var vertexBuffer:Laya.VertexBuffer2D = mesh.getVBR();
vertexBuffer.append(new Float32Array(顶点数据数组));
//相当于gl.vertexAttribPointer
mesh.setAttributes([
   WebGLRenderingContext.FLOAT, 3, 0,
   WebGLRenderingContext.FLOAT, 2, Float32Array.BYTES_PER_ELEMENT * 3
]);
var indexBuffer:Laya.IndexBuffer2D = mesh.getIBR();
//
indexBuffer.append(顶点序列集合);

//2.创建value2d
//这里创建了一个自定义的Value2D
var value2d:Laya.CustomValue2D = new Laya.CustomValue2D(0);
//将着色器uniform属性都存在这里
value2d.uSampler = image.source.bitmap['_glTexture']//之前创建的image对象
....
....


//3.实例一个SubmitTexture对象
this._renderSubmit = Laya.SubmitTexture.create(Laya.Render._context,mesh,value2d);
this._renderSubmit.shaderValue.textureHost = image.source;
this._renderSubmit._key.other = image.source.bitmap.id;
this._renderSubmit._numEle += 顶点数量;

更新着色器

在说更新着色器之前,先说下Laya中存在一个批提交概念,一个提交就是我们之前定义SubmitTexture的提交函数执行一次。

Laya底层中的Submit都是存储在一个数组中的,我们这种做法是绕过了底层的逻辑去清除重绘,所以我们需要稍微修改下Render帧循环的代码,这也是因为为什么这种做法只适合Shader应用于Stage最底层的情况。

我们在Laya的Stage对象中,添加一个数组存储我们之前创建的Program

/**自定义shader */
this._customShader = [];


//修改render函数
RunDriver.clear(this._bgColor);//清空舞台
//下面添加我们的自定义shader更新逻辑
for(var i=0,n=this._customShader.length;i < n;++i)
this._customShader[i]._update();
//laya自己的渲染函数
context.flush();

CustomValue2D里面有什么

var CustomValue2D=(function(_super){
	function CustomValue2D(subID){
		(subID===void 0)&& (subID=0);
		this.uSampler = null;
		this.u_Stage_Size = null;
		this.a_Time = null;
		CustomValue2D.__super.call(this,0x900,subID);//设置mainID为0x900
	}
	__class(CustomValue2D,'laya.webgl.shader.d2.value.CustomValue2D',_super);
	var __proto=CustomValue2D.prototype;
	__proto.clear=function(){
		this.texture=null;
		this.shader=null;
		this.defines._value=this.subID+(WebGL.shaderHighPrecision? 0x900:1);
	}

	return CustomValue2D;
})(Value2D)

为什么需要设置0x900

设置这个标志位主要是因为,存储在Value2D中的mainID会拿来取Shader集合里面的Shader,我们想取到我们自己的自定义Shader,就必须设置一个区别于普通的标志位id。

-效果-


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值