/* * Copyright (c) 2023 lax1dude. All Rights Reserved. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ifdef LIB_INCLUDE_WAVING_BLOCKS_FUNCTION #ifndef _HAS_INCLUDED_WAVING_BLOCKS #define _HAS_INCLUDED_WAVING_BLOCKS #define _WAVING_BLOCK_TYPE_LEAF_BLOCK 1 #define _WAVING_BLOCK_TYPE_LEAF_BLOCK_F 1.0 #define _WAVING_BLOCK_TYPE_TALL_GRASS 2 #define _WAVING_BLOCK_TYPE_TALL_GRASS_F 2.0 #define _WAVING_BLOCK_TYPE_CROPS 3 #define _WAVING_BLOCK_TYPE_CROPS_F 3.0 #define _WAVING_BLOCK_TYPE_DOUBLE_PLANT_BOTTOM 4 #define _WAVING_BLOCK_TYPE_DOUBLE_PLANT_BOTTOM_F 4.0 #define _WAVING_BLOCK_TYPE_DOUBLE_PLANT_TOP 5 #define _WAVING_BLOCK_TYPE_DOUBLE_PLANT_TOP_F 5.0 #define _WAVING_BLOCK_TYPE_PLANT 6 #define _WAVING_BLOCK_TYPE_PLANT_F 6.0 #define _WAVING_BLOCK_TYPE_SUGARCANE 7 #define _WAVING_BLOCK_TYPE_SUGARCANE_F 7.0 #define _WAVING_BLOCK_TYPE_VINES 8 #define _WAVING_BLOCK_TYPE_VINES_F 8.0 #define _WAVING_BLOCK_TYPE_WATER_STILL 9 #define _WAVING_BLOCK_TYPE_WATER_STILL_F 9.0 #define _WAVING_BLOCK_TYPE_WATER_FLOW 10 #define _WAVING_BLOCK_TYPE_WATER_FLOW_F 10.0 #define _WAVING_BLOCK_TYPE_LILYPAD 11 #define _WAVING_BLOCK_TYPE_LILYPAD_F 11.0 #define _WAVING_BLOCK_TYPE_FIRE_FLOOR 12 #define _WAVING_BLOCK_TYPE_FIRE_FLOOR_F 12.0 #define _WAVING_BLOCK_TYPE_FIRE_WALL 13 #define _WAVING_BLOCK_TYPE_FIRE_WALL_F 13.0 // ignore wall fire for now, they clip #define _WAVING_BLOCK_MIN _WAVING_BLOCK_TYPE_LEAF_BLOCK_F #define _WAVING_BLOCK_MAX _WAVING_BLOCK_TYPE_FIRE_FLOOR_F #ifndef FAKE_SIN #error the FAKE_SIN function must be defined to use waving blocks #endif #define _WAVING_BLOCK_COORD_DERIVE_HACK 0.001 #define _WAVING_BLOCK_COORD_DERIVE_HACK_05 0.0005 #define _WAVING_BLOCK_COORD_DERIVE_HACK_INV 1000.0 vec3 _computeWavingBlockNoise(in vec3 pos, in vec3 amp1, in float timer) { float fac, fac2; fac = dot(vec4(pos, timer), vec4(0.5, 0.5, 0.5, 0.0027)); FAKE_SIN(fac, fac2) fac2 *= 0.04; fac2 += 0.04; vec3 vf0, d0; vf0 = timer * vec3(0.0127, 0.0089, 0.0114); FAKE_SIN(vf0, d0); d0.xyz += d0.yzx; d0.xyz += timer * vec3(0.0063, 0.0224, 0.0015); d0.y += pos.z; d0.xz += pos.y; d0.xz += pos.zx; d0.xz -= pos.xz; vec3 ret; FAKE_SIN(d0, ret) ret *= fac2; return ret * amp1; } vec3 _computeWavingBlockNoise(in vec3 pos, in vec3 vf_a, in vec3 vf_b, in vec3 amp1, in vec3 amp2, in float timer) { float fac, fac2; fac = dot(vec4(pos, timer), vec4(0.5, 0.5, 0.5, 0.0027)); FAKE_SIN(fac, fac2) fac2 *= 0.04; fac2 += 0.04; vec3 vf0, d0; vf0 = timer * vec3(0.0127, 0.0089, 0.0114); FAKE_SIN(vf0, d0); d0.xyz += d0.yzx; d0.xyz += timer * vec3(0.0063, 0.0224, 0.0015); d0.y += pos.z; d0.xz += pos.y; d0.xz += pos.zx; d0.xz -= pos.xz; vec3 ret; FAKE_SIN(d0, ret) ret *= fac2; vec3 move = ret * amp1; vec3 pos2 = move + pos; fac = dot(vec4(pos2, timer), vec4(0.5, 0.5, 0.5, 0.0027)); FAKE_SIN(fac, fac2) fac2 *= 0.04; fac2 += 0.04; vf0 = timer * vf_a; FAKE_SIN(vf0, d0); d0.xyz += d0.yzx; d0.xyz += timer * vf_b; d0.y += pos2.z; d0.xz += pos2.y; d0.xz += pos2.zx; d0.xz -= pos2.xz; FAKE_SIN(d0, ret) ret *= fac2; move += ret * amp2; return move; } vec3 _computeWavingBlockById(in vec3 realPos, in vec3 referencePos, in vec4 wavingBlockParam, in float type) { int typeInt = int(type); highp float refY, fractY1, fractY2; refY = referencePos.y; switch(typeInt) { case _WAVING_BLOCK_TYPE_CROPS: refY += 0.0625625; case _WAVING_BLOCK_TYPE_TALL_GRASS: case _WAVING_BLOCK_TYPE_PLANT: case _WAVING_BLOCK_TYPE_DOUBLE_PLANT_BOTTOM: case _WAVING_BLOCK_TYPE_FIRE_FLOOR: // check if it is the bottom half of the block, // if vertex is at Y = 0.0 then don't offset fractY1 = fract(refY + _WAVING_BLOCK_COORD_DERIVE_HACK_05); fractY2 = fract(refY - _WAVING_BLOCK_COORD_DERIVE_HACK_05); if(fractY2 > fractY1) { return vec3(0.0); } default: break; } vec3 ret = vec3(0.0); switch(typeInt) { case _WAVING_BLOCK_TYPE_LEAF_BLOCK: ret = _computeWavingBlockNoise( referencePos, vec3(0.0040, 0.0064, 0.0043), vec3(0.0035, 0.0037, 0.0041), vec3(1.0, 0.2, 1.0), vec3(0.5, 0.1, 0.5), wavingBlockParam.y); break; case _WAVING_BLOCK_TYPE_TALL_GRASS: case _WAVING_BLOCK_TYPE_CROPS: ret = _computeWavingBlockNoise( referencePos, vec3(1.0, 0.2, 1.0), wavingBlockParam.y); break; case _WAVING_BLOCK_TYPE_PLANT: case _WAVING_BLOCK_TYPE_DOUBLE_PLANT_BOTTOM: case _WAVING_BLOCK_TYPE_DOUBLE_PLANT_TOP: ret = _computeWavingBlockNoise( referencePos, vec3(0.0041, 0.007, 0.0044), vec3(0.0038, 0.024, 0.0), vec3(0.8, 0.0, 0.8), vec3(0.4, 0.0, 0.4), wavingBlockParam.y); break; case _WAVING_BLOCK_TYPE_SUGARCANE: ret = _computeWavingBlockNoise( referencePos, vec3(0.3, 0.0, 0.3), wavingBlockParam.y); break; case _WAVING_BLOCK_TYPE_VINES: ret = _computeWavingBlockNoise( referencePos, vec3(0.0040, 0.0064, 0.0043), vec3(0.0035, 0.0037, 0.0041), vec3(0.5, 0.3, 0.5), vec3(0.25, 0.2, 0.25), wavingBlockParam.y); break; case _WAVING_BLOCK_TYPE_WATER_STILL: break; case _WAVING_BLOCK_TYPE_WATER_FLOW: break; case _WAVING_BLOCK_TYPE_FIRE_FLOOR: ret = _computeWavingBlockNoise( referencePos, vec3(0.0105, 0.0096, 0.0087), vec3(0.0063, 0.0097, 0.0156), vec3(1.2, 0.4, 1.2), vec3(0.8, 0.8, 0.8), wavingBlockParam.y); break; default: break; } return ret; } #define COMPUTE_WAVING_BLOCKS(pos4f, amount, range, block1f, modelMatrix, viewMatrix, modelViewMatrix, wavingBlockOffset, wavingBlockParam)\ if(block1f >= _WAVING_BLOCK_MIN && block1f <= _WAVING_BLOCK_MAX) {\ pos4f = modelMatrix * pos4f;\ pos4f.xyz /= pos4f.w;\ pos4f.w = 1.0;\ if(dot(pos4f.xyz, pos4f.xyz) < range * range) {\ pos4f.xyz += _computeWavingBlockById(pos4f.xyz, pos4f.xyz + wavingBlockOffset, wavingBlockParam, block1f) * amount * 0.5;\ }\ pos4f = viewMatrix * pos4f;\ }else {\ pos4f = modelViewMatrix * pos4f;\ } #endif #endif