1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-11 07:34:33 +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 LOG_SHADERS
#if defined(_OS_IOS) || defined(_GAPI_D3D9) || defined(_GAPI_GXM)
#define USE_SCREEN_TEX
#endif
struct ShaderCache {
enum Effect { FX_NONE = 0, FX_UNDERWATER = 1, FX_ALPHA_TEST = 2, FX_CLIP_PLANE = 4 };
@@ -519,8 +523,8 @@ struct WaterCache {
maxX++;
maxZ++;
int w = nextPow2(maxX - minX);
int h = nextPow2(maxZ - minZ);
int w = maxX - minX;
int h = maxZ - minZ;
uint16 *m = new uint16[w * h];
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;
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));
item.data[0]->bind(sDiffuse);
item.data[0]->bind(sNormal);
Core::setTarget(item.data[1], NULL, RT_STORE_COLOR);
Core::setViewport(0, 0, int(s.x + 0.5f), int(s.y + 0.5f));
game->getMesh()->renderQuad();
@@ -732,12 +736,13 @@ struct WaterCache {
vec2 s(item.size.x * DETAIL * 2.0f, item.size.z * DETAIL * 2.0f);
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(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) {
// water step
item.data[0]->bind(sDiffuse);
item.data[0]->bind(sNormal);
Core::setTarget(item.data[1], NULL, RT_STORE_COLOR);
Core::setViewport(0, 0, int(s.x + 0.5f), int(s.y + 0.5f));
game->getMesh()->renderQuad();
@@ -850,9 +855,9 @@ struct WaterCache {
PROFILE_MARKER("WATER_REFRACT_INIT");
delete refract;
refract = new Texture(w, h, FMT_RGBA, OPT_TARGET);
#ifdef _OS_IOS
#ifdef USE_SCREEN_TEX
delete screen;
screen = new Texture(w, h, FMT_RGBA, OPT_TARGET);
screen = new Texture(w, h, FMT_RGBA, OPT_TARGET);
#endif
}
return screen;
@@ -886,6 +891,7 @@ struct WaterCache {
if (!item.visible) continue;
if (item.timer >= SIMULATE_TIMESTEP || dropCount) {
Core::noiseTex->bind(sDiffuse);
item.mask->bind(sMask);
// add water drops
drop(item);
@@ -984,6 +990,7 @@ struct WaterCache {
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(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);
reflect->bind(sReflect);
@@ -1035,6 +1042,13 @@ struct WaterCache {
vertices[2].texCoord = short4(32767, 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::setBlendMode(bmNone);

View File

@@ -339,6 +339,7 @@ namespace Core {
#define MAX_LIGHTS 4
#define MAX_RENDER_BUFFERS 32
#define MAX_CONTACTS 15
#define NOISE_TEX_SIZE 32
struct Shader;
struct Texture;
@@ -540,7 +541,7 @@ namespace Core {
vec4 fogParams;
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;
@@ -681,6 +682,7 @@ namespace Core {
data = 0;
blackTex = new Texture(1, 1, FMT_RGBA, OPT_NEAREST, &data);
// generate dithering texture
uint8 ditherData[] = {
0x00, 0x7F, 0x1F, 0x9F, 0x07, 0x87, 0x27, 0xA7,
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);
// 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
settings.version = SETTINGS_VERSION;
@@ -793,6 +804,7 @@ namespace Core {
delete whiteCube;
delete blackTex;
delete ditherTex;
delete noiseTex;
GAPI::deinit();
NAPI::deinit();

View File

@@ -269,11 +269,11 @@ void joyUpdate() {
if (caps.wNumAxes > 0) {
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))
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) {
float z = joyAxis(info.dwZpos, caps.wZmin, caps.wZmax);
@@ -294,6 +294,7 @@ void joyUpdate() {
for (int i = 0; i < 10; i++)
Input::setJoyDown(j, JoyKey(jkA + i), (info.dwButtons & (1 << i)) > 0);
} else {
joyFree();
joyInit();

View File

@@ -20,6 +20,10 @@ varying vec3 vLightVec;
varying vec3 vNewPos;
#endif
#if defined(WATER_COMPOSE) || defined(WATER_SIMULATE)
varying vec2 vMaskCoord;
#endif
uniform vec4 uViewPos;
uniform mat4 uViewProj;
uniform vec4 uLightPos[MAX_LIGHTS];
@@ -27,6 +31,7 @@ uniform vec4 uPosScale[2];
uniform vec4 uTexParam;
uniform vec4 uParam;
uniform vec4 uRoomSize;
uniform sampler2D sNormal;
@@ -38,6 +43,10 @@ uniform sampler2D sNormal;
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)
float height = 0.0;
@@ -59,7 +68,7 @@ uniform sampler2D sNormal;
vec3 light = vec3(0.0, 0.0, 1.0);
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);
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 v = texture2D(sDiffuse, vTexCoord);
vec4 v = texture2D(sNormal, vTexCoord);
float drop = max(0.0, 1.0 - length(uParam.xy - vTexCoord / uTexParam.xy) / uParam.z);
drop = 0.5 - cos(drop * PI) * 0.5;
@@ -103,48 +112,18 @@ uniform sampler2D sNormal;
return v;
}
vec3 hash33(vec3 p3) {
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;
}
#ifdef WATER_SIMULATE
vec4 simulate() {
vec2 tc = vTexCoord;
if (texture2D(sMask, tc).x < 0.5)
if (texture2D(sMask, vMaskCoord).a < 0.5)
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);
vec4 f = vec4(texture2D(sDiffuse, tc + d.xz).x, texture2D(sDiffuse, tc + d.zy).x,
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(sNormal, tc - d.xz).x, texture2D(sNormal, tc - d.zy).x);
float average = dot(f, vec4(0.25));
// normal
@@ -153,13 +132,14 @@ uniform sampler2D sNormal;
// integrate
const float vel = 1.4;
const float vis = 0.995;
v.y += (average - v.x) * vel;
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;
}
#endif
#ifdef WATER_CAUSTICS
vec4 caustics() {
@@ -173,13 +153,13 @@ uniform sampler2D sNormal;
#ifdef WATER_RAYS
float boxIntersect(vec3 rayPos, vec3 rayDir, vec3 center, vec3 hsize) {
center -= rayPos;
vec3 bMin = (center - hsize) / rayDir;
vec3 bMax = (center + hsize) / rayDir;
vec3 m = min(bMin, bMax);
return max(0.0, max(m.x, max(m.y, m.z)));
}
float boxIntersect(vec3 rayPos, vec3 rayDir, vec3 center, vec3 hsize) {
center -= rayPos;
vec3 bMin = (center - hsize) / rayDir;
vec3 bMax = (center + hsize) / rayDir;
vec3 m = min(bMin, bMax);
return max(0.0, max(m.x, max(m.y, m.z)));
}
vec4 rays() {
#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);
}
#ifdef WATER_COMPOSE
vec4 compose() {
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);
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);
return color;
}
#endif
vec4 pass() {
#ifdef WATER_DROP

View File

@@ -16,7 +16,19 @@ float2 invUV(float2 uv) {
}
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
@@ -33,18 +45,22 @@ VS_OUTPUT main(VS_INPUT In) {
float3 coord = In.aCoord.xyz * (1.0 / 32767.0);
Out.texCoord = getUV(coord.xy, uTexParam);
if (WATER_COMPOSE) {
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.viewVec = uViewPos.xyz - Out.coord.xyz;
Out.lightVec = uLightPos[0].xyz - Out.coord.xyz;
Out.oldPos = getInvUV(coord.xy, uTexParam);
Out.texCoord = getUV(coord.xy, uRoomSize);
} else if (WATER_DROP) {
Out.pos = float4(coord.xyz, 1.0);
Out.oldPos = getInvUV(coord.xy, uTexParam);
} else if (WATER_SIMULATE) {
Out.pos = float4(coord.xyz, 1.0);
Out.oldPos = getInvUV(coord.xy, uTexParam);
Out.pos = float4(coord.xyz, 1.0);
Out.oldPos = getInvUV(coord.xy, uTexParam);
Out.texCoord = getUV(coord.xy, uRoomSize);
} else if (WATER_CAUSTICS) {
float3 rCoord = float3(coord.x, coord.y, 0.0) * uPosScale[1].xzy;
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.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;
}
@@ -84,7 +99,7 @@ float calcFresnel(float VoH, float f0) {
float4 drop(VS_OUTPUT In) {
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);
value = 0.5 - cos(value * PI) * 0.5;
@@ -94,50 +109,19 @@ float4 drop(VS_OUTPUT In) {
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) {
float2 iuv = In.oldPos.xy;
float2 uv = In.texCoord;
if (tex2D(sMask, uv).x < 0.5)
if (tex2D(sMask, uv).a < 0.5)
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);
float4 f = float4(
tex2D(sDiffuse, iuv + d.xz).x, tex2D(sDiffuse, 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,
tex2D(sNormal, iuv - d.xz).x, tex2D(sNormal, iuv - d.zy).x
);
float average = dot(f, (float4)0.25);
@@ -151,7 +135,7 @@ float4 simulate(VS_OUTPUT In) {
v.y += (average - v.x) * vel;
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;
}
@@ -228,7 +212,7 @@ float4 compose(VS_OUTPUT In) {
float fresnel = calcFresnel(max(0.0, dot(normal, viewVec)), 0.12);
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;
dist *= step(In.coord.y, uViewPos.y);