cocos2dx中用shader实现折射效果

目的:给定任意法线贴图,实现折射效果

主要技术:RenderTarget,glsl

提取出一个可供使用的Sprite派生类

计算模型如下:

黑色部分为玻璃切线,红色部分为场景。绿色线为垂直于场景的视线及其延长线,红色为法线。我们求折射光,等于在给定的OB,法线向量下,求取视线经过折射后与场景的交点和视线延长线和场景交点的偏移量。求出偏移量以后,就能非常方便的利用texture2D函数采样rendertexture,得到颜色。

假设法线向量为a,则我们容易得到x, y方向的偏移为:

deltaX = a.x * OB / a.z

deltaY = a.y * OB / a.z

由于进入fragment shader的坐标系是ndc坐标系,外部需要给shader屏幕尺寸width, height,从而得到:

deltaX(ndc) = a.x * OB / (a.z * width)

deltaY(ndc) = a.y * OB / (a.z * height)

接下来就非常简单

gl_FragColor = texture2D(renderTarget, worldUV + deltaXY(ndc))

得到worldUV的方法:

在vertex shader中:

worldUV = MVP * position

worldUV = worldUV / worldUV.w  //这个很重要,必须除了w才能得到ndc坐标,否则结果不对

worldUV = vec2((worldUV.x + 1.) * 0.5, (1. - worldUV.y) * 0.5)

所有shader代码:

attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
#ifdef GL_ES
varying mediump vec2 v_texCoord;
varying mediump vec2 v_worldTexCoord;
varying mediump vec4 v_fragmentColor;
#else
varying vec2 v_texCoord;
varying vec2 v_worldTexCoord;
varying vec4 v_fragmentColor;
#endif

void main()
{
    gl_Position = CC_PMatrix * a_position;
    v_texCoord = a_texCoord;
    v_fragmentColor = a_color;
    v_worldTexCoord = gl_Position.xy / gl_Position.w;
    v_worldTexCoord = vec2((v_worldTexCoord.x + 1.) * 0.5, (1. - v_worldTexCoord.y) * 0.5);
}

#ifdef GL_ES
precision lowp float;
#endif
varying vec4 v_fragmentColor;
uniform vec2 u_screenExtent;
uniform sampler2D sceneTexture;
uniform vec3 u_rgbRatio;
uniform float u_height;
varying vec2 v_texCoord;
varying vec2 v_worldTexCoord;

void main()
{
    vec2 worldTex = vec2(v_worldTexCoord.x, 1. - v_worldTexCoord.y);
    vec4 normal = texture2D(CC_Texture0, v_texCoord) * 2. - vec4(1., 1., 1., 0);
    vec2 bias = vec2(u_height * normal.x / (normal.z * u_screenExtent.x), u_height * normal.y / (normal.z * u_screenExtent.y));
    vec4 frag = vec4(0.,0.,0.,0.);
    frag.r = texture2D(sceneTexture, worldTex + bias * u_rgbRatio.r).r;
    frag.g = texture2D(sceneTexture, worldTex + bias * u_rgbRatio.g).g;
    frag.b = texture2D(sceneTexture, worldTex + bias * u_rgbRatio.b).b;
    gl_FragColor = frag;
    gl_FragColor.a = 1.;
}

贴一个效果图:

时间: 2024-08-02 14:14:50

cocos2dx中用shader实现折射效果的相关文章

cocos2dx 关于shader高亮使用的问题

cocos2dx 使用shader 制作高亮效果,在Android下,如果手机设置"不保留活动"的话,home出去之后,shader是要被销毁. 会造成一些坐标不对,不能高亮的问题. 解决方法: 捕获重新进游戏,render recreate的事件. Director::getInstance()->getEventDispatcher()->addCustomEventListener(EVENT_RENDERER_RECREATED, [this](EventCusto

cocos2dx 编写shader 遇到 溢出问题

在 编程语言中,不论什么 数据类型 都有 各种 的 局限,无法 表示 现实世界中的 不论什么 情况. 比如 int ,char 会 溢出,float 会 有 溢出 以及 精度 不准确的 情况. 所以 我们 在 开发 中 须要 特别 注意 这些事. 近期 须要 在 cocos2dx(2.1.4) 引擎下 用 shader 做一些 效果.遇到 一些 在 windows 上 没有问题,可是 移植到 android 就会 出问题的 现象. 记录 下来.一为  加深印象 .二为 提供 遇到 同类 问题 的

cocos2d-x的popScene的动画效果

找到CCDirector.h,找到void popScene(); 在下面加上一段类模板 template <class T> void popSceneWithTransition(float t) { CCASSERT(_runningScene != nullptr, "running scene should not null"); _scenesStack.popBack(); ssize_t c = _scenesStack.size(); if (c == 0

[Shader]LOGO闪光效果

?? 这个效果在很多LOGO及广告宣传中都会用到.商业开发的做法应该是拿一张闪光的图,对其做uv移动,然后和原图两张图混合,这样运算会小很多,需要储存的变量也会小很多.本讲不用图而完全通过计算得出闪光区域,主要是借此加深uv计算实现特殊效果的实现,以及计算uv的方法.代码注释配合图解已经比较详细了,跟着做就行,随便找一张半透明的图来做地图即可. ? Shader "Custom/logo" {??? Properties {??? ??? _MainTex ("Texture

Cocos2d-x 水果忍者划痕效果

网上找的一个关于水果忍者划痕的,效果还算凑合.其原理就是基于OpenGL绘制直线,因为版本号过老,此处笔者改动了一些方法,粘贴后可直接使用 适用于Cocos2d-x 2.2.1 .h文件里须要添?的代码: void draw(); void drawLine(); virtual void ccTouchesBegan(CCSet *pTouches,CCEvent *pEvent); virtual void ccTouchesMoved(CCSet *pTouches,CCEvent *pE

cocos2dx 2.x实现闪电效果(贴画版)

cocos2dx 2.x实现闪电效果(非画线版) 在网上搜索到一个直接用opengl画线实现的版本,但放在游戏中效果不太搭,要求用贴图的.我这个版本用的也是画线版的算法. 闪动的时候效果还可以,每段衔接的地方还是不太完美,各位有其他的建议的请联系我  [email protected] 转载请注明出处 http://www.cnblogs.com/mrblue/p/4315091.html 效果图 //头文件 #ifndef __LIGINTNING_H__ #define __LIGINTNI

Unity Shader实现描边效果

http://gad.qq.com/article/detail/28346 描边效果是游戏里面非常常用的一种效果,一般是为了凸显游戏中的某个对象,会给对象增加一个描边效果.本篇文章和大家介绍下利用Shader实现描边效果,一起来看看吧. 最近又跑回去玩了玩<剑灵>,虽然出了三年了,感觉在现在的网游里面画面仍然算很好的了,剑灵里面走近或者选中NPC的一瞬间,NPC就会出现描边效果,不过这个描边效果是渐变的,会很快减弱最后消失(抓了好久才抓住一张图....) 还有就是最常见的LOL中的塔,我们把

Cocos2d-x移植android加入震动效果

cpp部分通过jni调用java静态函数 头文件: #include <jni.h> #include "cocos2d.h" #include "platform/android/jni/JniHelper.h" 在cpp类中定义方法去调用Cocos2dxSound.java中vibrate方法: static void vibrateJNI(long longtime) { JniMethodInfo methodInfo; if(!JniHelpe

Unity shader实现水效果(折射,反射,波浪,1.菲尼尔,深度颜色)

整个实现过程,包括水面的UV流动,折射,反射,根据深度进行透明值处理等等 原文地址:https://www.cnblogs.com/ubanck/p/9606626.html