把Shadertoy上的shader应用到UE4和Maya_ue4 hlsl abs_pengyancai的博客-程序员秘密

技术标签: shader  CG  材质  HLSL  maya  

1、UE4里使用HLSL。

最近再次捣鼓shader,我把https://www.shadertoy.com/这个网站上的shader应用到UE4里,在UE4里把HLSL写在custom material node,或者使用usf文件,在游戏模式下使用,这个方法可以参考官方提供的案例UE4ShaderPluginDemo-4.7,两个方法都是可行的,我这里演示下custom material node上的使用,这里我想说下,我觉得custom node局限的两个地方,一是几乎无法使用函数(我看到日本有人使用一种我无法理解的方法写function,http://monsho.blog63.fc2.com/blog-entry-194.html),第二是返回值类型只有给定的4种,当我想返回矩阵类型都没有。

下面是在custom node里的代码,来源于https://www.shadertoy.com/view/MdXSzS。这里分享一下我从GLSL转HLSL的小技巧,一个是使用预处理宏这样我就不需要去更改两种shader语法上的差异,另一个是*号,在HLSL需要使用mul函数替代。

#define vec2 float2
#define vec3 float3
#define vec4 float4
#define mat2 float2x2
#define mat3 float3x3
#define fract frac
#define mix lerp

vec2 uv = (fragCoord.xy / iResolution.xy) - .5;
	float t = iGlobalTime * .1 + ((.25 + .05 * sin(iGlobalTime * .1))/(length(uv.xy) + .07)) * 2.2;
	float si = sin(t);
	float co = cos(t);
	float2x2 ma = float2x2(co, si, -si, co);

	float v1, v2, v3;
	v1 = v2 = v3 = 0.0;
	
	float s = 0.0;
	for (int i = 0; i < 90; i++)
	{
		vec3 p = s * vec3(uv, 0.0);
		//p.xy *= ma;
		p.xy = mul(p.xy, ma);
		p += vec3(.22, .3, s - 1.5 - sin(iGlobalTime * .13) * .1);
		for (int i = 0; i < 8; i++)	p = abs(p) / dot(p,p) - 0.659;
		v1 += dot(p,p) * .0015 * (1.8 + sin(length(uv.xy * 13.0) + .5  - iGlobalTime * .2));
		v2 += dot(p,p) * .0013 * (1.5 + sin(length(uv.xy * 14.5) + 1.2 - iGlobalTime * .3));
		v3 += length(p.xy*10.) * .0003;
		s  += .035;
	}
	
	float len = length(uv);
	v1 *= smoothstep(.7, .0, len);
	v2 *= smoothstep(.5, .0, len);
	v3 *= smoothstep(.9, .0, len);
	
	vec3 col = vec3( v3 * (1.5 + sin(iGlobalTime * .2) * .4),
					(v1 + v3) * .3,
					 v2) + smoothstep(0.2, .0, len) * .85 + smoothstep(.0, .6, v3) * .3;

	vec4 fragColor = vec4(min(pow(abs(col), vec3(1.2,1.2,1.2)), 1.0), 1.0);
	return fragColor;
2、Maya里使用HLSL。

使用DirectX 11 Shader材质,这里可以加载Maya预设的一些shader看效果,我就是在官方提供的基础上修改的,这种shader的写法和底层图形接口使用的有些不一样,Maya有它的规则,主要是shader代码里暴露出来的供调节的参数有点特殊,但也挺好理解。

把下面的代码复制,保存到xxx.fx文件,就可以被DirectX 11 Shader加载了。

#include "Common10.fxh"

float gScale1 <
    string UIWidget = "slider";
    float UIMin = -1000;
    float UIMax = 1000;
    float UIStep = 0.01;
> = 1.0;
/
#define vec2 float2
#define vec3 float3
#define vec4 float4
#define mat2 float2x2
#define mat3 float3x3
#define fract frac
#define mix lerp

#define iResolution float2(1,1)
#define iGlobalTime gScale1

float4 star(float2 intputvalue)
{
// return float4(1,0,0,0);
#define fragCoord intputvalue

vec2 uv = (fragCoord.xy / iResolution.xy) - .5;
	float t = iGlobalTime * .1 + ((.25 + .05 * sin(iGlobalTime * .1))/(length(uv.xy) + .07)) * 2.2;
	float si = sin(t);
	float co = cos(t);
	float2x2 ma = float2x2(co, si, -si, co);

	float v1, v2, v3;
	v1 = v2 = v3 = 0.0;
	
	float s = 0.0;
	for (int i = 0; i < 90; i++)
	{
		vec3 p = s * vec3(uv, 0.0);
		//p.xy *= ma;
		p.xy = mul(p.xy, ma);
		p += vec3(.22, .3, s - 1.5 - sin(iGlobalTime * .13) * .1);
		for (int i = 0; i < 8; i++)	p = abs(p) / dot(p,p) - 0.659;
		v1 += dot(p,p) * .0015 * (1.8 + sin(length(uv.xy * 13.0) + .5  - iGlobalTime * .2));
		v2 += dot(p,p) * .0013 * (1.5 + sin(length(uv.xy * 14.5) + 1.2 - iGlobalTime * .3));
		v3 += length(p.xy*10.) * .0003;
		s  += .035;
	}
	
	float len = length(uv);
	v1 *= smoothstep(.7, .0, len);
	v2 *= smoothstep(.5, .0, len);
	v3 *= smoothstep(.9, .0, len);
	
	vec3 col = vec3( v3 * (1.5 + sin(iGlobalTime * .2) * .4),
					(v1 + v3) * .3,
					 v2) + smoothstep(0.2, .0, len) * .85 + smoothstep(.0, .6, v3) * .3;

	vec4 fragColor = vec4(min(pow(abs(col), vec3(1.2,1.2,1.2)), 1.0), 1.0);
	return fragColor;
}

// Pixel shader.
// NOTE: This expects screen quad vertex shader output.
float4 PS_Mandelbrot(VS_TO_PS_ScreenQuad IN) : SV_TARGET 
{
return star(IN.UV.xy);
}

// Main technique.
technique10 Main
{
    pass p0
    {
        SetVertexShader(CompileShader(vs_4_0, VS_ScreenQuad()));
        SetGeometryShader(NULL);
        SetPixelShader(CompileShader(ps_4_0, PS_Mandelbrot()));
    }
}

我再展示一个很好玩的效果

#include "Common10.fxh"

float gScale1 <
    string UIWidget = "slider";
    float UIMin = -1000;
    float UIMax = 1000;
    float UIStep = 0.01;
> = 1.0;
///
#define vec2 float2
#define vec3 float3
#define vec4 float4
#define mat2 float2x2
#define mat3 float3x3
#define fract frac
#define mix lerp

#define iResolution float2(1,1)
#define iGlobalTime gScale1
#define iMouse float2(1,1)

#define S(a, b, t) smoothstep(a, b, t)
#define B(a, b, blur, t) S(a-blur, a+blur, t)*S(b+blur, b-blur, t)
#define sat(x) clamp(x, 0., 1.)

float remap01(float a, float b, float t) {
	return sat((t-a)/(b-a));
}

float remap(float a, float b, float c, float d, float t) {
	return sat((t-a)/(b-a)) * (d-c) + c;
}

vec2 within(vec2 uv, vec4 rect) {
	return (uv-rect.xy)/(rect.zw-rect.xy);
}

vec4 Brow(vec2 uv, float smile) {
    float offs = mix(.2, 0., smile);
    uv.y += offs;
    
    float y = uv.y;
    uv.y += uv.x*mix(.5, .8, smile)-mix(.1, .3, smile);
    uv.x -= mix(.0, .1, smile);
    uv -= .5;
    
    vec4 col = vec4(0,0,0,0);
    
    float blur = .1;
    
   	float d1 = length(uv);
    float s1 = S(.45, .45-blur, d1);
    float d2 = length(uv-vec2(.1, -.2)*.7);
    float s2 = S(.5, .5-blur, d2);
    
    float browMask = sat(s1-s2);
    
    float colMask = remap01(.7, .8, y)*.75;
    colMask *= S(.6, .9, browMask);
    colMask *= smile;
    vec4 browCol = mix(vec4(.4, .2, .2, 1.), vec4(1., .75, .5, 1.), colMask); 
   
    uv.y += .15-offs*.5;
    blur += mix(.0, .1, smile);
    d1 = length(uv);
    s1 = S(.45, .45-blur, d1);
    d2 = length(uv-vec2(.1, -.2)*.7);
    s2 = S(.5, .5-blur, d2);
    float shadowMask = sat(s1-s2);
    
    col = mix(col, vec4(0.,0.,0.,1.), S(.0, 1., shadowMask)*.5);
    
    col = mix(col, browCol, S(.2, .4, browMask));
    
    return col;
}
vec4 Eye(vec2 uv, float side, vec2 m, float smile) {
    uv -= .5;
    uv.x *= side;
    
	float d = length(uv);
    vec4 irisCol = vec4(.3, .5, 1., 1.);
    vec4 col = mix(vec4(1.0,1.0,1.0,1.0), irisCol, S(.1, .7, d)*.5);		// gradient in eye-white
    col.a = S(.5, .48, d);									// eye mask
    
    col.rgb *= 1. - S(.45, .5, d)*.5*sat(-uv.y-uv.x*side); 	// eye shadow
    
    d = length(uv-m*.4);									// offset iris pos to look at mouse cursor
    col.rgb = mix(col.rgb, vec3(0.,0.,0.), S(.3, .28, d)); 		// iris outline
    
    irisCol.rgb *= 1. + S(.3, .05, d);						// iris lighter in center
    float irisMask = S(.28, .25, d);
    col.rgb = mix(col.rgb, irisCol.rgb, irisMask);			// blend in iris
    
    d = length(uv-m*.45);									// offset pupile to look at mouse cursor
    
    float pupilSize = mix(.4, .16, smile);
    float pupilMask = S(pupilSize, pupilSize*.85, d);
    pupilMask *= irisMask;
    col.rgb = mix(col.rgb, vec3(0.,0.,0.), pupilMask);		// blend in pupil
    
    float t = iGlobalTime*3.;
    vec2 offs = vec2(sin(t+uv.y*25.), sin(t+uv.x*25.));
    offs *= .01*(1.-smile);
    
    uv += offs;
    float highlight = S(.1, .09, length(uv-vec2(-.15, .15)));
    highlight += S(.07, .05, length(uv+vec2(-.08, .08)));
    col.rgb = mix(col.rgb, vec3(1.,1.,1.), highlight);			// blend in highlight
    
    return col;
}

vec4 Mouth(vec2 uv, float smile) {
    uv -= .5;
	vec4 col = vec4(.5, .18, .05, 1.);
    
    uv.y *= 1.5;
    uv.y -= uv.x*uv.x*2.*smile;
    
    uv.x *= mix(2.5, 1., smile);
    
    float d = length(uv);
    col.a = S(.5, .48, d);
    
    vec2 tUv = uv;
    tUv.y += (abs(uv.x)*.5+.1)*(1.-smile);
    float td = length(tUv-vec2(0., .6));
    
    vec3 toothCol = vec3(1.,1.,1.)*S(.6, .35, d);
    col.rgb = mix(col.rgb, toothCol, S(.4, .37, td));
    
    td = length(uv+vec2(0., .5));
    col.rgb = mix(col.rgb, vec3(1., .5, .5), S(.5, .2, td));
    return col;
}

vec4 Head(vec2 uv) {
	vec4 col = vec4(.9, .65, .1, 1.);
    
    float d = length(uv);
    
    col.a = S(.5, .49, d);
    
    float edgeShade = remap01(.35, .5, d);
    edgeShade *= edgeShade;
    col.rgb *= 1.-edgeShade*.5;
    
    col.rgb = mix(col.rgb, vec3(.6, .3, .1), S(.47, .48, d));
    
    float highlight = S(.41, .405, d);
    highlight *= remap(.41, -.1, .75, 0., uv.y);
    highlight *= S(.18, .19, length(uv-vec2(.21, .08)));
    col.rgb = mix(col.rgb, vec3(1.,1.,1.), highlight);
    
    d = length(uv-vec2(.25, -.2));
    float cheek = S(.2,.01, d)*.4;
    cheek *= S(.17, .16, d);
    col.rgb = mix(col.rgb, vec3(1., .1, .1), cheek);
    
    return col;
}

vec4 Smiley(vec2 uv, vec2 m, float smile) {
	vec4 col = vec4(0.,0.,0.,0.);
    
    if(length(uv)<.5) {					// only bother about pixels that are actually inside the head
        float side = sign(uv.x);
        uv.x = abs(uv.x);
        vec4 head = Head(uv);
        col = mix(col, head, head.a);

        if(length(uv-vec2(.2, .075))<.175) {
            vec4 eye = Eye(within(uv, vec4(.03, -.1, .37, .25)), side, m, smile);
            col = mix(col, eye, eye.a);
        }

        if(length(uv-vec2(.0, -.15))<.3) {
            vec4 mouth = Mouth(within(uv, vec4(-.3, -.43, .3, -.13)), smile);
            col = mix(col, mouth, mouth.a);
        }

        if(length(uv-vec2(.185, .325))<.18) {
            vec4 brow = Brow(within(uv, vec4(.03, .2, .4, .45)), smile);
            col = mix(col, brow, brow.a);
        }
    }
    
    return col;
}

float4 mainImage(vec2 fragCoord )
{
	float t = iGlobalTime;
    
    vec2 uv = fragCoord.xy / iResolution.xy;
    uv -= .5;
    uv.x *= iResolution.x/iResolution.y;
    
    vec2 m = iMouse.xy / iResolution.xy;
    m -= .5;
    
    if(m.x<-.49 && m.y<-.49) {			// make it that he looks around when the mouse hasn't been used
    	float s = sin(t*.5);
        float c = cos(t*.38);
        
        m = vec2(s, c)*.4;
    }
    
    if(length(m) > .707) m *= 0.;		// fix bug when coming back from fullscreen
    
    float d = dot(uv, uv);
    uv -= m*sat(.23-d);
    
    float smile = sin(t*.5)*.5+.5;
	float4 fragColor = Smiley(uv, m, smile);
	return fragColor;
}

// Pixel shader.
// NOTE: This expects screen quad vertex shader output.
float4 PS_Mandelbrot(VS_TO_PS_ScreenQuad IN) : SV_TARGET 
{
return mainImage(IN.UV.xy);
}

// Main technique.
technique10 Main
{
    pass p0
    {
        SetVertexShader(CompileShader(vs_4_0, VS_ScreenQuad()));
        SetGeometryShader(NULL);
        SetPixelShader(CompileShader(ps_4_0, PS_Mandelbrot()));
    }
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/pengyancai/article/details/64967187

智能推荐

Project DarkStar中文开发指南_xiaxj的博客-程序员秘密

Java游戏开发中的J2EE----Project DarkStar。前几天翻译了一下DarkStar的开发指南,放在了附件里,对这个项目关注了很长时间了,希望能和对这个项目感兴趣的同学交流一下。...

SQLLDR的一个CTL样例_weixin_33774615的博客-程序员秘密

LOAD DATAINFILE 'E:\84db\ot_patent2008-06-29 12-27-20.txt' BADFILE 'E:\84db\ot_patent2008-06-29 12-27-20.bad'DISCARDFILE 'E:\84db\ot_patent2008-06-29 12-27-20.dsc'INTO TABLE "HPS"."...

Qt 使用 QAxWidget 实现与 JavaScript 的交互_chisichan7657的博客-程序员秘密

首先用QAxWidget打开网页。在我的另一条文章里有说明:https://my.oschina.net/u/3907010/blog/1844600document = this-&gt;ui-&gt;axWidget-&gt;querySubObject("Document");par...

sony电视遥控器android,划重点!如何用手机当“点播遥控器”?_田智广的博客-程序员秘密

本帖最后由 eswgdeh 于 2017-8-26 17:47 编辑很多朋友买到的电视都有个随机的赠品“USB耳塞”,大家都知道怎么去用吗?楼主想着应该很多人都有这个东西所有打算给小伙伴们专门讲讲这个电视遥控扩展器也就是那个“USB耳塞”的使用方法。索尼C/D系列4K电视遥控扩展器与机顶盒联动及Video &amp; TV SideView 手机APP用法索尼电视有很多智能功能,DLNA就不多说了...

【实验】【视图】使用v$bgprocess视图获得所有后台进程信息_cuanchuwei1207的博客-程序员秘密

1.展示一下Oracle所有可能的进程名及其描述,这是一个很好的“自助式”参考信息。这里仅仅使用了v$bgprocess视图注释:所有PADDR字段非“00”的进程都是目前系统中已经启动的后台进程,...

建议收藏!211毕业女博士5面阿里巴巴,深度复盘阿里面试题总结!_博士面试阿里成功率多大_海峰的架构路的博客-程序员秘密

前言个人情况大概是从10月底开始投递简历,到12月初先后面试了CVTE、远景、美团、阿里、腾讯五家公司,也投递过一些其他的公司,有的没有面试机会(如蘑菇街、VIVO、虎牙等),有的放弃了笔试(如卡中心、360、移动、携程等),到现在算先告一段落吧,只是等待最后的结果,整理下面试中的一些问题(由于时间间隔有点久,记不大清楚了,整理下记得的一些问题,题目不分前后顺序)回馈大众,希望没出结果的都能顺利~阿里一面:触发新生代GC,如果存活对象总量大于survivor区容量,咋办如果任务很多,线程池的

随便推点

多媒体技术 || JPEG压缩算法_jpeg如何对不是8*8的矩阵进行压缩_perry0528的博客-程序员秘密

编译环境windows10下MinGW编译语言c++ &amp;amp;&amp;amp; CImg库运行命令g++ -o test main.cpp jpegCompress.cpp jpegCompress.h -O2 -lgdi321. 8x8分块因为之后的DCT变换是要对8x8的子块为一个单位进行处理,所以为了方便第一步我们就进行分块。所以源图的width和height必须要是8的倍数,所以...

PCI总线和PXI总线的区别_长弓的坚持的博客-程序员秘密

PCI技术: (应该叫总线)1992年intel 推出创立 PCI规范到如今,PCI总线已成为了事实上计算机的标准总线。请看 http://www.eebyte.com/article/list.asp?id=112PCI技术规格简介PXI技术:http://www.ednchina.com/client/ni/aboutPXI.asp1997年,美国国家仪器中国有限公司(National Ins...

Linux下安装Pcl和ceres库的步骤以及小bug_L_smartworld的博客-程序员秘密

1、Ceres是一个cmak工程,首先要安装他的依赖项,使用apt-get安装。sudo apt-get install liblapack-dev libsuitesparse-dev libcxsparse3.1.2 libgflags-dev libgoogle-glog-dev libgtest-dev2、如果安装时找不到 cxsparse 或者其他的lib,需要添加下面的源。...

C#从入门到精通19 委托(二) 模板和回调_霜叶红似二月花的博客-程序员秘密

使用1:模板方法,借用指定的外部方法来产生结果1)相当于填空题2)常位于代码中部3)委托有返回值WrapFactory包装工厂类里面的WrapProduct这个方法,这里这个委托的调用是可以修改的。传进来的委托,它封装了什么方法,在这里就可以得到这个方法产出的产品。好处在于,一旦写成这样以后,我们的Product类,Box类,以及WrapFactory类都不用再动了。我们这里只需要不断扩...

窗口面板学习Extjs4 (2_dyl_love98的博客-程序员秘密

废话就不多说了,开始。。。    Ext中的现展基本都须要窗口的持支,渲染点、术技点比较多,别心担,渐渐搞定她。这里先示展一个简略的窗口。    一、简略窗口     1 Ext.require(["*"]); 2 3 Ext.onReady(function () { 4 var win1; 5 var btnA1 = Ext.get("btnA1"

JAVA8 十大新特性详解_键圣的博客-程序员秘密

--接口中的方法都是抽象的吗?--NO场景:今天在翻看jdk的java.util.Comparator接口的时候发现了下面这段代码 /** * Returns a comparator that imposes the reverse ordering of this * comparator. * * @return a comp

推荐文章

热门文章

相关标签