[shader] 在 cocos2dx 中使用 shadertoy|glslsandbox 的 shader

前言

shadertoyglslsandbox上有许多很有意思的shader,都是用glsl编写的。
本文描述了如何直接将这两个网站的单个pass、只用2d贴图的shader,直接应用于cocos2d-x。


前排提示请严格遵守知识共享许可和开源许可协议

vertex shader

由于shadertoy和glslsanbox都是只使用像素着色器,所以顶点着色器就只需要传递整张屏幕的顶点位置即可。

###shader

	attribute vec4 a_position;
	void main()
	{
		gl_Position = a_position;
	}

###顶点绑定

	glGenVertexArrays(1, &_vao);
	glBindVertexArray(_vao);
	glGenBuffers(1, &_vbo);
	glBindBuffer(GL_ARRAY_BUFFER, _vbo);
	Vec2 vertex[] = {{-1.0f,  1.0f},
				{-1.0f, -1.0f},
				{1.0f, 1.0f},
				{1.0f, -1.0f} };

	glBufferData(GL_ARRAY_BUFFER, sizeof(Vec2) * 4, vertex, GL_STREAM_DRAW);
	// vertex
	glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
	glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(Vec2), (GLvoid*)(0));
	glBindVertexArray(0);

###fragment shader
这里只讨论shadertoy的单个pass 图像着色器,并且不含立方体贴图。
###shader

为了能直接使用需要给shader加上以下输入和调用:

"\nuniform vec3      iResolution;\
uniform float     iTime;\
uniform float     iTimeDelta;\
uniform vec4      iMouse;\
uniform int       iFrame;  \
uniform sampler2D iChannel0; \
uniform sampler2D iChannel1; \
uniform sampler2D iChannel2; \
uniform sampler2D iChannel3; \
		 "
"\nvoid main() \
{ \
mainImage(gl_FragColor, gl_FragCoord.xy); \n\
}";

主体部分可以直接复制网址分享的shader内容。

###uniform 传递
shadertoy和glslsanbox都使用大量的预定义uniform,通过官方教程就能很清楚的知道对于含义。
只要清楚含义就很好办了,这里介绍shadertoy常用的几个:
iResolution 屏幕像素分辨率
iTime shader启动时间,单位秒
iTimeDelta 每帧渲染时间,单位秒
iFrame 帧数
samplerXX iChannel0..3 四张贴图可以是2d也可以是3d立方体贴图,这里只用2d
iMouse 四维向量,xy表示鼠标悬停位置,zw表示鼠标点击位置,这里一般想转化视角可以视情况给参数即可

鼠标位置参数传递可以参考以下:

	Vec4 mouse;
	e->onMouseMove = [this, &mouse](EventMouse* event) {
		mouse.x = event->getCursorX();
		mouse.y = event->getCursorY();
		_eff->getGLProgramState()->setUniformVec4("iMouse", mouse);
	};
	e->onMouseDown = [this, &mouse] (EventMouse* event)
	{
		mouse.z = event->getCursorX();
		mouse.w = event->getCursorY();
		//_eff->getGLProgramState()->setUniformVec4("iMouse", mouse);
	};
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(e, this);

其它参数都非常简单,对于贴图可以直接从shadertoy的的shader源码下方的直接保存。
参考代码:

参考.zip (2.9 KB)

2赞

图中的的小阴影和亮圈和shader无关,做是光照和阴影的部分,截gif没有去掉

那是要看实际情况的,全默有可能效果不是很好

你这种人就是书到用时方恨少的那种人,用啥学啥一辈子就是个菜鸟

https://www.shadertoy.com/ 这里也有很多有意思的shader