1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-11 23:54:09 +02:00

more ripples on the water surface, optimize noise function

This commit is contained in:
XProger
2019-01-15 09:39:22 +03:00
parent 57577ede26
commit 2a30bb5f4c
5 changed files with 96 additions and 103 deletions

View File

@@ -9,6 +9,10 @@
#define NO_CLIP_PLANE 1000000.0f #define NO_CLIP_PLANE 1000000.0f
//#define LOG_SHADERS //#define LOG_SHADERS
#if defined(_OS_IOS) || defined(_GAPI_D3D9) || defined(_GAPI_GXM)
#define USE_SCREEN_TEX
#endif
struct ShaderCache { struct ShaderCache {
enum Effect { FX_NONE = 0, FX_UNDERWATER = 1, FX_ALPHA_TEST = 2, FX_CLIP_PLANE = 4 }; enum Effect { FX_NONE = 0, FX_UNDERWATER = 1, FX_ALPHA_TEST = 2, FX_CLIP_PLANE = 4 };
@@ -519,8 +523,8 @@ struct WaterCache {
maxX++; maxX++;
maxZ++; maxZ++;
int w = nextPow2(maxX - minX); int w = maxX - minX;
int h = nextPow2(maxZ - minZ); int h = maxZ - minZ;
uint16 *m = new uint16[w * h]; uint16 *m = new uint16[w * h];
memset(m, 0, w * h * sizeof(m[0])); memset(m, 0, w * h * sizeof(m[0]));
@@ -542,9 +546,9 @@ struct WaterCache {
} }
} }
m[(x - minX) + w * (z - minZ)] = hasWater ? 0xF800 : 0; m[(x - minX) + w * (z - minZ)] = hasWater ? 0xFFFF : 0x0000; // TODO: flow map
} }
mask = new Texture(w, h, FMT_RGB16, OPT_NEAREST, m); mask = new Texture(w, h, FMT_RGBA16, OPT_NEAREST, m);
delete[] m; delete[] m;
size = vec3(float((maxX - minX) * 512), 1.0f, float((maxZ - minZ) * 512)); // half size size = vec3(float((maxX - minX) * 512), 1.0f, float((maxZ - minZ) * 512)); // half size
@@ -718,7 +722,7 @@ struct WaterCache {
Core::active.shader->setParam(uParam, vec4(p.x, p.z, drop.radius * DETAIL, -drop.strength)); Core::active.shader->setParam(uParam, vec4(p.x, p.z, drop.radius * DETAIL, -drop.strength));
item.data[0]->bind(sDiffuse); item.data[0]->bind(sNormal);
Core::setTarget(item.data[1], NULL, RT_STORE_COLOR); Core::setTarget(item.data[1], NULL, RT_STORE_COLOR);
Core::setViewport(0, 0, int(s.x + 0.5f), int(s.y + 0.5f)); Core::setViewport(0, 0, int(s.x + 0.5f), int(s.y + 0.5f));
game->getMesh()->renderQuad(); game->getMesh()->renderQuad();
@@ -732,12 +736,13 @@ struct WaterCache {
vec2 s(item.size.x * DETAIL * 2.0f, item.size.z * DETAIL * 2.0f); vec2 s(item.size.x * DETAIL * 2.0f, item.size.z * DETAIL * 2.0f);
game->setShader(Core::passWater, Shader::WATER_SIMULATE); game->setShader(Core::passWater, Shader::WATER_SIMULATE);
Core::active.shader->setParam(uParam, vec4(0.995f, 1.0f, 0, Core::params.x)); Core::active.shader->setParam(uParam, vec4(0.995f, 1.0f, randf() * 0.5f, randf() * 0.5f));
Core::active.shader->setParam(uTexParam, vec4(1.0f / item.data[0]->width, 1.0f / item.data[0]->height, s.x / item.data[0]->width, s.y / item.data[0]->height)); Core::active.shader->setParam(uTexParam, vec4(1.0f / item.data[0]->width, 1.0f / item.data[0]->height, s.x / item.data[0]->width, s.y / item.data[0]->height));
Core::active.shader->setParam(uRoomSize, vec4(1.0f / item.mask->origWidth, 1.0f / item.mask->origHeight, float(item.mask->origWidth) / item.mask->width, float(item.mask->origHeight) / item.mask->height));
while (item.timer >= SIMULATE_TIMESTEP) { while (item.timer >= SIMULATE_TIMESTEP) {
// water step // water step
item.data[0]->bind(sDiffuse); item.data[0]->bind(sNormal);
Core::setTarget(item.data[1], NULL, RT_STORE_COLOR); Core::setTarget(item.data[1], NULL, RT_STORE_COLOR);
Core::setViewport(0, 0, int(s.x + 0.5f), int(s.y + 0.5f)); Core::setViewport(0, 0, int(s.x + 0.5f), int(s.y + 0.5f));
game->getMesh()->renderQuad(); game->getMesh()->renderQuad();
@@ -850,9 +855,9 @@ struct WaterCache {
PROFILE_MARKER("WATER_REFRACT_INIT"); PROFILE_MARKER("WATER_REFRACT_INIT");
delete refract; delete refract;
refract = new Texture(w, h, FMT_RGBA, OPT_TARGET); refract = new Texture(w, h, FMT_RGBA, OPT_TARGET);
#ifdef _OS_IOS #ifdef USE_SCREEN_TEX
delete screen; delete screen;
screen = new Texture(w, h, FMT_RGBA, OPT_TARGET); screen = new Texture(w, h, FMT_RGBA, OPT_TARGET);
#endif #endif
} }
return screen; return screen;
@@ -886,6 +891,7 @@ struct WaterCache {
if (!item.visible) continue; if (!item.visible) continue;
if (item.timer >= SIMULATE_TIMESTEP || dropCount) { if (item.timer >= SIMULATE_TIMESTEP || dropCount) {
Core::noiseTex->bind(sDiffuse);
item.mask->bind(sMask); item.mask->bind(sMask);
// add water drops // add water drops
drop(item); drop(item);
@@ -984,6 +990,7 @@ struct WaterCache {
float sz = item.size.z * DETAIL / (item.data[0]->height / 2); float sz = item.size.z * DETAIL / (item.data[0]->height / 2);
Core::active.shader->setParam(uTexParam, vec4(0.0f, 0.0f, sx, sz)); Core::active.shader->setParam(uTexParam, vec4(0.0f, 0.0f, sx, sz));
Core::active.shader->setParam(uRoomSize, vec4(1.0f / item.mask->origWidth, 1.0f / item.mask->origHeight, float(item.mask->origWidth) / item.mask->width, float(item.mask->origHeight) / item.mask->height));
refract->bind(sDiffuse); refract->bind(sDiffuse);
reflect->bind(sReflect); reflect->bind(sReflect);
@@ -1035,6 +1042,13 @@ struct WaterCache {
vertices[2].texCoord = short4(32767, 0, 0, 0); vertices[2].texCoord = short4(32767, 0, 0, 0);
vertices[3].texCoord = short4( 0, 0, 0, 0); vertices[3].texCoord = short4( 0, 0, 0, 0);
#if defined(_GAPI_D3D9) || defined(_GAPI_GXM)
vertices[0].texCoord = short4( 0, 0, 0, 0);
vertices[1].texCoord = short4(32767, 0, 0, 0);
vertices[2].texCoord = short4(32767, 32767, 0, 0);
vertices[3].texCoord = short4( 0, 32767, 0, 0);
#endif
Core::setDepthTest(false); Core::setDepthTest(false);
Core::setBlendMode(bmNone); Core::setBlendMode(bmNone);

View File

@@ -339,6 +339,7 @@ namespace Core {
#define MAX_LIGHTS 4 #define MAX_LIGHTS 4
#define MAX_RENDER_BUFFERS 32 #define MAX_RENDER_BUFFERS 32
#define MAX_CONTACTS 15 #define MAX_CONTACTS 15
#define NOISE_TEX_SIZE 32
struct Shader; struct Shader;
struct Texture; struct Texture;
@@ -540,7 +541,7 @@ namespace Core {
vec4 fogParams; vec4 fogParams;
vec4 contacts[MAX_CONTACTS]; vec4 contacts[MAX_CONTACTS];
Texture *whiteTex, *whiteCube, *blackTex, *ditherTex; Texture *whiteTex, *whiteCube, *blackTex, *ditherTex, *noiseTex;
enum Pass { passCompose, passShadow, passAmbient, passWater, passFilter, passGUI, passMAX } pass; enum Pass { passCompose, passShadow, passAmbient, passWater, passFilter, passGUI, passMAX } pass;
@@ -681,6 +682,7 @@ namespace Core {
data = 0; data = 0;
blackTex = new Texture(1, 1, FMT_RGBA, OPT_NEAREST, &data); blackTex = new Texture(1, 1, FMT_RGBA, OPT_NEAREST, &data);
// generate dithering texture
uint8 ditherData[] = { uint8 ditherData[] = {
0x00, 0x7F, 0x1F, 0x9F, 0x07, 0x87, 0x27, 0xA7, 0x00, 0x7F, 0x1F, 0x9F, 0x07, 0x87, 0x27, 0xA7,
0xBF, 0x3F, 0xDF, 0x5F, 0xC7, 0x47, 0xE7, 0x67, 0xBF, 0x3F, 0xDF, 0x5F, 0xC7, 0x47, 0xE7, 0x67,
@@ -693,6 +695,15 @@ namespace Core {
}; };
ditherTex = new Texture(8, 8, FMT_LUMINANCE, OPT_REPEAT | OPT_NEAREST, &ditherData); ditherTex = new Texture(8, 8, FMT_LUMINANCE, OPT_REPEAT | OPT_NEAREST, &ditherData);
// generate noise texture
uint8 *noiseData = new uint8[SQR(NOISE_TEX_SIZE)];
for (int i = 0; i < SQR(NOISE_TEX_SIZE); i++) {
noiseData[i] = rand() % 255;
}
noiseTex = new Texture(NOISE_TEX_SIZE, NOISE_TEX_SIZE, FMT_LUMINANCE, OPT_REPEAT, noiseData);
delete[] noiseData;
// init settings // init settings
settings.version = SETTINGS_VERSION; settings.version = SETTINGS_VERSION;
@@ -793,6 +804,7 @@ namespace Core {
delete whiteCube; delete whiteCube;
delete blackTex; delete blackTex;
delete ditherTex; delete ditherTex;
delete noiseTex;
GAPI::deinit(); GAPI::deinit();
NAPI::deinit(); NAPI::deinit();

View File

@@ -269,11 +269,11 @@ void joyUpdate() {
if (caps.wNumAxes > 0) { if (caps.wNumAxes > 0) {
Input::setJoyPos(j, jkL, joyDir(joyAxis(info.dwXpos, caps.wXmin, caps.wXmax), Input::setJoyPos(j, jkL, joyDir(joyAxis(info.dwXpos, caps.wXmin, caps.wXmax),
joyAxis(info.dwYpos, caps.wYmin, caps.wYmax))); joyAxis(info.dwYpos, caps.wYmin, caps.wYmax)));
if ((caps.wCaps & JOYCAPS_HASR) && (caps.wCaps & JOYCAPS_HASU)) if ((caps.wCaps & JOYCAPS_HASR) && (caps.wCaps & JOYCAPS_HASU))
Input::setJoyPos(j, jkR, joyDir(joyAxis(info.dwUpos, caps.wUmin, caps.wUmax), Input::setJoyPos(j, jkR, joyDir(joyAxis(info.dwUpos, caps.wUmin, caps.wUmax),
joyAxis(info.dwRpos, caps.wRmin, caps.wRmax))); joyAxis(info.dwRpos, caps.wRmin, caps.wRmax)));
if (caps.wCaps & JOYCAPS_HASZ) { if (caps.wCaps & JOYCAPS_HASZ) {
float z = joyAxis(info.dwZpos, caps.wZmin, caps.wZmax); float z = joyAxis(info.dwZpos, caps.wZmin, caps.wZmax);
@@ -294,6 +294,7 @@ void joyUpdate() {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
Input::setJoyDown(j, JoyKey(jkA + i), (info.dwButtons & (1 << i)) > 0); Input::setJoyDown(j, JoyKey(jkA + i), (info.dwButtons & (1 << i)) > 0);
} else { } else {
joyFree(); joyFree();
joyInit(); joyInit();

View File

@@ -20,6 +20,10 @@ varying vec3 vLightVec;
varying vec3 vNewPos; varying vec3 vNewPos;
#endif #endif
#if defined(WATER_COMPOSE) || defined(WATER_SIMULATE)
varying vec2 vMaskCoord;
#endif
uniform vec4 uViewPos; uniform vec4 uViewPos;
uniform mat4 uViewProj; uniform mat4 uViewProj;
uniform vec4 uLightPos[MAX_LIGHTS]; uniform vec4 uLightPos[MAX_LIGHTS];
@@ -27,6 +31,7 @@ uniform vec4 uPosScale[2];
uniform vec4 uTexParam; uniform vec4 uTexParam;
uniform vec4 uParam; uniform vec4 uParam;
uniform vec4 uRoomSize;
uniform sampler2D sNormal; uniform sampler2D sNormal;
@@ -38,6 +43,10 @@ uniform sampler2D sNormal;
vTexCoord = (coord.xy * 0.5 + 0.5) * uTexParam.zw; vTexCoord = (coord.xy * 0.5 + 0.5) * uTexParam.zw;
#if defined(WATER_COMPOSE) || defined(WATER_SIMULATE)
vMaskCoord = (coord.xy * 0.5 + 0.5) * uRoomSize.zw;
#endif
#if defined(WATER_MASK) || defined(WATER_COMPOSE) #if defined(WATER_MASK) || defined(WATER_COMPOSE)
float height = 0.0; float height = 0.0;
@@ -59,7 +68,7 @@ uniform sampler2D sNormal;
vec3 light = vec3(0.0, 0.0, 1.0); vec3 light = vec3(0.0, 0.0, 1.0);
vec3 refOld = refract(-light, vec3(0.0, 0.0, 1.0), 0.75); vec3 refOld = refract(-light, vec3(0.0, 0.0, 1.0), 0.75);
vec3 refNew = refract(-light, normal, 0.75); vec3 refNew = refract(-light, normalize(normal + vec3(0.0, 0.0, 0.25)), 0.75);
vOldPos = rCoord + refOld * (-1.0 / refOld.z) + refOld * ((-refOld.z - 1.0) / refOld.z); vOldPos = rCoord + refOld * (-1.0 / refOld.z) + refOld * ((-refOld.z - 1.0) / refOld.z);
vNewPos = rCoord + refNew * ((info.r - 1.0) / refNew.z) + refOld * ((-refNew.z - 1.0) / refOld.z); vNewPos = rCoord + refNew * ((info.r - 1.0) / refNew.z) + refOld * ((-refNew.z - 1.0) / refOld.z);
@@ -94,7 +103,7 @@ uniform sampler2D sNormal;
} }
vec4 drop() { vec4 drop() {
vec4 v = texture2D(sDiffuse, vTexCoord); vec4 v = texture2D(sNormal, vTexCoord);
float drop = max(0.0, 1.0 - length(uParam.xy - vTexCoord / uTexParam.xy) / uParam.z); float drop = max(0.0, 1.0 - length(uParam.xy - vTexCoord / uTexParam.xy) / uParam.z);
drop = 0.5 - cos(drop * PI) * 0.5; drop = 0.5 - cos(drop * PI) * 0.5;
@@ -103,48 +112,18 @@ uniform sampler2D sNormal;
return v; return v;
} }
vec3 hash33(vec3 p3) { #ifdef WATER_SIMULATE
p3 = fract(p3 * vec3(.1031,.11369,.13787));
p3 += dot(p3, p3.yxz+19.19);
return -1.0 + 2.0 * fract(vec3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x));
}
float simplex_noise(vec3 p) { // https://www.shadertoy.com/view/4sc3z2
const float K1 = 0.333333333;
const float K2 = 0.166666667;
vec3 i = floor(p + (p.x + p.y + p.z) * K1);
vec3 d0 = p - (i - (i.x + i.y + i.z) * K2);
vec3 e = step(vec3(0.0), d0 - d0.yzx);
vec3 i1 = e * (1.0 - e.zxy);
vec3 i2 = 1.0 - e.zxy * (1.0 - e);
vec3 d1 = d0 - (i1 - 1.0 * K2);
vec3 d2 = d0 - (i2 - 2.0 * K2);
vec3 d3 = d0 - (1.0 - 3.0 * K2);
vec4 h = max(0.6 - vec4(dot(d0, d0), dot(d1, d1), dot(d2, d2), dot(d3, d3)), 0.0);
vec4 n = h * h * h * h * vec4(dot(d0, hash33(i)), dot(d1, hash33(i + i1)), dot(d2, hash33(i + i2)), dot(d3, hash33(i + 1.0)));
return dot(vec4(31.316), n);
}
float h(vec2 tc) {
return simplex_noise(vec3(tc * 16.0, uParam.w)) * 0.0005;
}
vec4 simulate() { vec4 simulate() {
vec2 tc = vTexCoord; vec2 tc = vTexCoord;
if (texture2D(sMask, tc).x < 0.5) if (texture2D(sMask, vMaskCoord).a < 0.5)
return vec4(0.0); return vec4(0.0);
vec4 v = texture2D(sDiffuse, tc); // height, speed, normal.xz vec4 v = texture2D(sNormal, tc); // height, speed, normal.xz
vec3 d = vec3(uTexParam.xy, 0.0); vec3 d = vec3(uTexParam.xy, 0.0);
vec4 f = vec4(texture2D(sDiffuse, tc + d.xz).x, texture2D(sDiffuse, tc + d.zy).x, vec4 f = vec4(texture2D(sNormal, tc + d.xz).x, texture2D(sNormal, tc + d.zy).x,
texture2D(sDiffuse, tc - d.xz).x, texture2D(sDiffuse, tc - d.zy).x); texture2D(sNormal, tc - d.xz).x, texture2D(sNormal, tc - d.zy).x);
float average = dot(f, vec4(0.25)); float average = dot(f, vec4(0.25));
// normal // normal
@@ -153,13 +132,14 @@ uniform sampler2D sNormal;
// integrate // integrate
const float vel = 1.4; const float vel = 1.4;
const float vis = 0.995; const float vis = 0.995;
v.y += (average - v.x) * vel; v.y += (average - v.x) * vel;
v.y *= vis; v.y *= vis;
v.x += v.y + h(tc); float noise = texture2D(sDiffuse, tc + uParam.zw * 0.5).x;
v.x += v.y + (noise * 2.0 - 1.0) * 0.00025;
return v; return v;
} }
#endif
#ifdef WATER_CAUSTICS #ifdef WATER_CAUSTICS
vec4 caustics() { vec4 caustics() {
@@ -173,13 +153,13 @@ uniform sampler2D sNormal;
#ifdef WATER_RAYS #ifdef WATER_RAYS
float boxIntersect(vec3 rayPos, vec3 rayDir, vec3 center, vec3 hsize) { float boxIntersect(vec3 rayPos, vec3 rayDir, vec3 center, vec3 hsize) {
center -= rayPos; center -= rayPos;
vec3 bMin = (center - hsize) / rayDir; vec3 bMin = (center - hsize) / rayDir;
vec3 bMax = (center + hsize) / rayDir; vec3 bMax = (center + hsize) / rayDir;
vec3 m = min(bMin, bMax); vec3 m = min(bMin, bMax);
return max(0.0, max(m.x, max(m.y, m.z))); return max(0.0, max(m.x, max(m.y, m.z)));
} }
vec4 rays() { vec4 rays() {
#define RAY_STEPS 16.0 #define RAY_STEPS 16.0
@@ -222,6 +202,7 @@ float boxIntersect(vec3 rayPos, vec3 rayDir, vec3 center, vec3 hsize) {
color.xyz = mix(UNDERWATER_COLOR * 0.2, color.xyz, fog); color.xyz = mix(UNDERWATER_COLOR * 0.2, color.xyz, fog);
} }
#ifdef WATER_COMPOSE
vec4 compose() { vec4 compose() {
vec3 viewVec = normalize(vViewVec); vec3 viewVec = normalize(vViewVec);
@@ -244,11 +225,12 @@ float boxIntersect(vec3 rayPos, vec3 rayDir, vec3 center, vec3 hsize) {
float fresnel = calcFresnel(max(0.0, dot(normal, viewVec)), 0.12); float fresnel = calcFresnel(max(0.0, dot(normal, viewVec)), 0.12);
vec4 color = mix(refr, refl, fresnel) + spec * 1.5; vec4 color = mix(refr, refl, fresnel) + spec * 1.5;
color.w *= texture2D(sMask, vTexCoord).x; color.w *= texture2D(sMask, vMaskCoord).a;
applyFog(color.xyz, vViewVec.y / viewVec.y); applyFog(color.xyz, vViewVec.y / viewVec.y);
return color; return color;
} }
#endif
vec4 pass() { vec4 pass() {
#ifdef WATER_DROP #ifdef WATER_DROP

View File

@@ -16,7 +16,19 @@ float2 invUV(float2 uv) {
} }
float3 getInvUV(float2 uv, float4 param) { float3 getInvUV(float2 uv, float4 param) {
return float3((float2(uv.x, -uv.y) * 0.5 + 0.5) * param.zw + 0.5 * param.xy, 0.0); float2 p = (float2(uv.x, -uv.y) * 0.5 + 0.5) * param.zw;
#ifndef _GAPI_GXM
p.xy += 0.5 * param.xy;
#endif
return float3(p, 0.0);
}
float2 getUV(float2 uv, float4 param) {
float2 p = (uv.xy * 0.5 + 0.5) * param.zw;
#ifndef _GAPI_GXM
//p.xy += 0.5 * param.xy;
#endif
return p;
} }
#ifdef VERTEX #ifdef VERTEX
@@ -33,18 +45,22 @@ VS_OUTPUT main(VS_INPUT In) {
float3 coord = In.aCoord.xyz * (1.0 / 32767.0); float3 coord = In.aCoord.xyz * (1.0 / 32767.0);
Out.texCoord = getUV(coord.xy, uTexParam);
if (WATER_COMPOSE) { if (WATER_COMPOSE) {
Out.coord = float3(coord.x, 0.0, coord.y) * uPosScale[1].xyz + uPosScale[0].xyz; Out.coord = float3(coord.x, 0.0, coord.y) * uPosScale[1].xyz + uPosScale[0].xyz;
Out.pos = mul(uViewProj, float4(Out.coord, 1.0)); Out.pos = mul(uViewProj, float4(Out.coord, 1.0));
Out.viewVec = uViewPos.xyz - Out.coord.xyz; Out.viewVec = uViewPos.xyz - Out.coord.xyz;
Out.lightVec = uLightPos[0].xyz - Out.coord.xyz; Out.lightVec = uLightPos[0].xyz - Out.coord.xyz;
Out.oldPos = getInvUV(coord.xy, uTexParam); Out.oldPos = getInvUV(coord.xy, uTexParam);
Out.texCoord = getUV(coord.xy, uRoomSize);
} else if (WATER_DROP) { } else if (WATER_DROP) {
Out.pos = float4(coord.xyz, 1.0); Out.pos = float4(coord.xyz, 1.0);
Out.oldPos = getInvUV(coord.xy, uTexParam); Out.oldPos = getInvUV(coord.xy, uTexParam);
} else if (WATER_SIMULATE) { } else if (WATER_SIMULATE) {
Out.pos = float4(coord.xyz, 1.0); Out.pos = float4(coord.xyz, 1.0);
Out.oldPos = getInvUV(coord.xy, uTexParam); Out.oldPos = getInvUV(coord.xy, uTexParam);
Out.texCoord = getUV(coord.xy, uRoomSize);
} else if (WATER_CAUSTICS) { } else if (WATER_CAUSTICS) {
float3 rCoord = float3(coord.x, coord.y, 0.0) * uPosScale[1].xzy; float3 rCoord = float3(coord.x, coord.y, 0.0) * uPosScale[1].xzy;
float2 uv = getInvUV(rCoord.xy, uTexParam).xy; float2 uv = getInvUV(rCoord.xy, uTexParam).xy;
@@ -68,8 +84,7 @@ VS_OUTPUT main(VS_INPUT In) {
Out.pos = mul(uViewProj, float4(Out.coord, 1.0)); Out.pos = mul(uViewProj, float4(Out.coord, 1.0));
} }
Out.texCoord = (coord.xy * 0.5 + 0.5) * uTexParam.zw + 0.5 * uTexParam.xy; // + half texel offset Out.hpos = Out.pos;
Out.hpos = Out.pos;
return Out; return Out;
} }
@@ -84,7 +99,7 @@ float calcFresnel(float VoH, float f0) {
float4 drop(VS_OUTPUT In) { float4 drop(VS_OUTPUT In) {
float2 iuv = In.oldPos.xy; float2 iuv = In.oldPos.xy;
float4 v = tex2D(sDiffuse, iuv); float4 v = tex2D(sNormal, iuv);
float value = max(0.0, 1.0 - length(uParam.xy - In.texCoord / uTexParam.xy) / uParam.z); float value = max(0.0, 1.0 - length(uParam.xy - In.texCoord / uTexParam.xy) / uParam.z);
value = 0.5 - cos(value * PI) * 0.5; value = 0.5 - cos(value * PI) * 0.5;
@@ -94,50 +109,19 @@ float4 drop(VS_OUTPUT In) {
return v; return v;
} }
float3 hash33(float3 p3) {
p3 = frac(p3 * float3(.1031,.11369,.13787));
p3 += dot(p3, p3.yxz+19.19);
return -1.0 + 2.0 * frac(float3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x));
}
float simplex_noise(float3 p) { // https://www.shadertoy.com/view/4sc3z2
const float K1 = 0.333333333;
const float K2 = 0.166666667;
float3 i = floor(p + (p.x + p.y + p.z) * K1);
float3 d0 = p - (i - (i.x + i.y + i.z) * K2);
float3 e = step((float3)0.0, d0 - d0.yzx);
float3 i1 = e * (1.0 - e.zxy);
float3 i2 = 1.0 - e.zxy * (1.0 - e);
float3 d1 = d0 - (i1 - 1.0 * K2);
float3 d2 = d0 - (i2 - 2.0 * K2);
float3 d3 = d0 - (1.0 - 3.0 * K2);
float4 h = max(0.6 - float4(dot(d0, d0), dot(d1, d1), dot(d2, d2), dot(d3, d3)), 0.0);
float4 n = h * h * h * h * float4(dot(d0, hash33(i)), dot(d1, hash33(i + i1)), dot(d2, hash33(i + i2)), dot(d3, hash33(i + 1.0)));
return dot((float4)31.316, n);
}
float h(float2 tc) {
return simplex_noise(float3(tc * 16.0, uParam.w)) * 0.0005;
}
float4 simulate(VS_OUTPUT In) { float4 simulate(VS_OUTPUT In) {
float2 iuv = In.oldPos.xy; float2 iuv = In.oldPos.xy;
float2 uv = In.texCoord; float2 uv = In.texCoord;
if (tex2D(sMask, uv).x < 0.5) if (tex2D(sMask, uv).a < 0.5)
return 0.0; return 0.0;
float4 v = tex2D(sDiffuse, iuv); // height, speed, normal.xz float4 v = tex2D(sNormal, iuv); // height, speed, normal.xz
float3 d = float3(float2(uTexParam.x, -uTexParam.y), 0.0); float3 d = float3(float2(uTexParam.x, -uTexParam.y), 0.0);
float4 f = float4( float4 f = float4(
tex2D(sDiffuse, iuv + d.xz).x, tex2D(sDiffuse, iuv + d.zy).x, tex2D(sNormal, iuv + d.xz).x, tex2D(sNormal, iuv + d.zy).x,
tex2D(sDiffuse, iuv - d.xz).x, tex2D(sDiffuse, iuv - d.zy).x tex2D(sNormal, iuv - d.xz).x, tex2D(sNormal, iuv - d.zy).x
); );
float average = dot(f, (float4)0.25); float average = dot(f, (float4)0.25);
@@ -151,7 +135,7 @@ float4 simulate(VS_OUTPUT In) {
v.y += (average - v.x) * vel; v.y += (average - v.x) * vel;
v.y *= vis; v.y *= vis;
v.x += v.y + h(uv); v.x += v.y + (tex2D(sDiffuse, uv + uParam.zw).x * 2.0 - 1.0) * 0.00025;
return v; return v;
} }
@@ -228,7 +212,7 @@ float4 compose(VS_OUTPUT In) {
float fresnel = calcFresnel(max(0.0, dot(normal, viewVec)), 0.12); float fresnel = calcFresnel(max(0.0, dot(normal, viewVec)), 0.12);
float4 color = lerp(refr, refl, fresnel) + spec * 1.5; float4 color = lerp(refr, refl, fresnel) + spec * 1.5;
color.w *= tex2D(sMask, In.texCoord).x; color.w *= tex2D(sMask, In.texCoord).a;
float dist = In.viewVec.y / viewVec.y; float dist = In.viewVec.y / viewVec.y;
dist *= step(In.coord.y, uViewPos.y); dist *= step(In.coord.y, uViewPos.y);