多材质(Shader)实现
最近在cocos creator上打算写个U3D中shader功能的插件(能在属性面板调整shader属性)。
对其中一个功能有点疑惑,就是U3D中一个渲染物体上可以挂多个材质,后来查询了下,一个物体上挂多个材质的时候,每个材质负责渲染对应的子mesh,但如果一个object只有一个mesh时,
那么挂载在其下的所有材质都会作用在这个mesh上,达到了混合的作用。(实际上,Unity并不建议将多个材质作用于同一个mesh上,官方建议的做法是通过多个shader pass解决多种shader效果需求)
但是在OpenGl渲染中,每次渲染只能用一个shader,而每个物体也只能挂一个shader被渲染。
因此不能直接给一个物体挂多个着色器,当初我第一时刻想到的,就是shader文件混合,比如将两个着色器的main函数里的内容混合在一起,然后分别将计算结果加起来赋予到output。
今天偶然逛到一个网站,是一个类似ShaderToy的网站,能在线编辑Shder并演示(说白了就是Webgl),不过这个网站除了能在线写glsl代码,还有一个比较好玩的功能,就是可视化编辑shader

这个功能很简单,就是可以将多个代码实现的shader作为节点,组合成一个新的shader,当然,目前版本比较简单,只提供加减乘除等基础操作。
仔细一想,这个功能不就跟我想要的shader混合一样么?仔细做了个试验,发现他的混合实现果然是跟我想的一样。
首先,我在这个网站写了两个非常简单的着色器:
Shader 1:

Shader 2:

组合Shader:

将这个组合Shader导出后,查看它的Shader文件:
// 片段着色器
precision highp float;
precision highp int;
uniform vec3 color;
vec4 Simple_Shader_11475135391321_521_main()
{
vec4 Simple_Shader_11475135391321_521_gl_FragColor = vec4(0.0);
Simple_Shader_11475135391321_521_gl_FragColor = vec4(0.1, 0.2, 0.3, 0.4);
return Simple_Shader_11475135391321_521_gl_FragColor *= 1.0;
} vec4 Simple_Shader_21475135525837_573_main()
{
vec4 Simple_Shader_21475135525837_573_gl_FragColor = vec4(0.0);
Simple_Shader_21475135525837_573_gl_FragColor = vec4(color, 1.0);
return Simple_Shader_21475135525837_573_gl_FragColor *= 1.0;
} void main()
{
gl_FragColor = (Simple_Shader_11475135391321_521_main() + Simple_Shader_21475135525837_573_main());
} // 顶点着色器
precision highp float;
precision highp int;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
attribute vec3 position;
vec4 Simple_Shader_11475135391321_521_main()
{
vec4 Simple_Shader_11475135391321_521_gl_Position = vec4(0.0);
Simple_Shader_11475135391321_521_gl_Position = vec4(position, 1.0);
return Simple_Shader_11475135391321_521_gl_Position *= 1.0;
}
vec4 Simple_Shader_21475135525837_573_main()
{
vec4 Simple_Shader_21475135525837_573_gl_Position = vec4(0.0);
Simple_Shader_21475135525837_573_gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
return Simple_Shader_21475135525837_573_gl_Position *= 1.0;
}
void main()
{
gl_Position = Simple_Shader_11475135391321_521_main() + Simple_Shader_21475135525837_573_main();
}
果然不出所料,拿顶点着色器来说,首先提取两个着色器的变量并放在一起,并剔除重复的,然后将两个shader各自的main提取为一个子函数,并将之前的gl_Position替换为renturn,然后在main中将这个两个函数的返回值加起来,达到混合的目的,当然,他还加入了缩放因子控制混合比例。
非常简单粗暴。
而且这种做法,还能将drawcall控制为一个,unity我不知道他的实现原理,不过就目前来看,添加多个着色器,会导致dc相应增加,应该不是用这种做法。
多材质(Shader)实现的更多相关文章
- ThreeJS 物理材质shader源码分析(顶点着色器)
再此之前推荐一款GLTF物理材质在线编辑器https://tinygltf.xyz/ ThreeJS 物理材质shader源码分析(顶点着色器) Threejs将shader代码分为ShaderLib ...
- ThreeJS 物理材质shader源码分析(像素着色器)
再此之前推荐一款GLTF物理材质在线编辑器https://tinygltf.xyz/ 像素着色器(meshphysical_frag.glsl) #define PHYSICAL uniform ve ...
- PlayCanvas PBR材质shader代码分析(pixel shader)
#version es #define varying in out highp vec4 pc_fragColor; #define gl_FragColor pc_fragColor #defin ...
- PlayCanvas PBR材质shader代码分析(vertex shader)
顶点shader主要对顶点坐标变换,将顶点坐标从local->world->view->clip 空间变换 local空间:模型物体坐标系 world空间:世界空间坐标系 view空 ...
- 【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&颜色、光照与材质
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨) ...
- Unity 3D动态修改Shader状态,使物体透明等等
Unity动态改Shader状态透明 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- ...
- 【Unity Shader】六、使用法线贴图(Normal Map)的Shader
学习资料: http://www.sikiedu.com/course/37/task/456/show# http://www.sikiedu.com/course/37/task/458/show ...
- 【转载】Unity3D研究院之共享材质的巧妙用法(sharedMaterial效率问题)
如果你需要修改模型材质的颜色,或者是修改材质Shader的一些属性, 通常情况是用获取模型的Renderer组件,然后获取它的material属性. 举个简单的例子,修改颜色或者直接更换shader ...
- 剖析虚幻渲染体系(08)- Shader体系
目录 8.1 本篇概述 8.2 Shader基础 8.2.1 FShader 8.2.2 Shader Parameter 8.2.3 Uniform Buffer 8.2.4 Vertex Fact ...
- Unity性能优化之 Draw Call原理<转>
Unity(或者说基本所有图形引擎)生成一帧画面的处理过程大致可以这样简化描述:引擎首先经过简单的可见性测试,确定摄像机可以看到的物体,然后把这些物体的顶点(包括本地位置.法线.UV等),索引(顶点如 ...
随机推荐
- python写红包的原理流程包含random,lambda其中的使用和见简单介绍
Python写红包的原理流程 首先来说说要用到的知识点,第一个要说的是扩展包random,random模块一般用来生成一个随机数 今天要用到ramdom中unifrom的方法用于生成一个指定范围的随机 ...
- JAVA设计模式之3-抽象工厂模式
书接上文,简单工厂模式解决的是可以枚举种类的类的问题,但是带来了高耦合的问题,并且对类系列繁多无从下手,那么我们想起了一种方法,那就是抽象类,建一个抽象工厂,抽象工厂里的方法都是根据系列类的差异区分出 ...
- vue 2.0 开发实践总结之疑难篇
续上一篇文章:vue2.0 开发实践总结之入门篇 ,如果没有看过的可以移步看一下. 本篇文章目录如下: 1. vue 组件的说明和使用 2. vuex在实际开发中的使用 3. 开发实践总结 1. ...
- 详解C#中的反射
反射(Reflection) 2008年01月02日 星期三 11:21 两个现实中的例子:1.B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内脏的生理情况.这是如何做到的呢?B超是B ...
- IOS实现自动循环滚动广告--ScrollView的优化和封装
一.问题分析 在许多App中,我们都会见到循环滚动的视图,比如广告,其实想实现这个功能并不难,用ScrollView就可以轻松完成,但是在制作的过程中还存在几个小问题,如果能够正确的处理好这些小问题, ...
- Jenkins插件安装和系统配置
前面我们只是把Jenkins部署在Tomcat中了,下面来看看Jenkins中的插件和一些基础的系统配置. 1.用户管理 我们一般的项目组肯定是由多名成员组成的,如何向Jenkins添加我们的成员呢? ...
- dateRangePicker时间范围控件
Github:https://github.com/dangrossman/bootstrap-daterangepicker/ 使用daterangepicker()为元素创建一个时间范围控件 &l ...
- MapControl控件AddLayer出现错误-引发类型为“System.Windows.Forms.AxHost+InvalidActiveXStateException”的异常
出错代码: AxMapControl pMptrl = new AxMapControl(); //add data string mdbPath = string.Format("{0}\ ...
- 【BZOJ-2555】SubString 后缀自动机 + LinkCutTree
2555: SubString Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1936 Solved: 551[Submit][Status][Di ...
- [虚拟机]Virtual Box的使用--共享文件夹
最近为系统测试使用了虚拟机,VM太卡,所以使用了VBox,运行效果还不错 为了主机和客户机之前方便进行数据传输,一般采用文件夹共享的方式(当然,可以直接拖拽) 1,直接拖拽,需要做如下设置 主要的是“ ...