Added day&night cycle. Also fixed world loading
Build / build (push) Has been cancelled

This commit is contained in:
milkwx3
2026-07-07 22:02:10 +03:00
parent 7ab2d5a083
commit 04d1969084
25 changed files with 3018 additions and 888 deletions
-2
View File
@@ -13,5 +13,3 @@ cd ..
mkdir OUTPUT-Linux mkdir OUTPUT-Linux
cp build/src/RCRAFT OUTPUT-Linux/CubeGame cp build/src/RCRAFT OUTPUT-Linux/CubeGame
cp -r data/resources OUTPUT-Linux cp -r data/resources OUTPUT-Linux
mkdir OUTPUT-Linux/user
mkdir OUTPUT-Linux/user/worlds
-2
View File
@@ -13,5 +13,3 @@ cd ..
mkdir OUTPUT-w32 mkdir OUTPUT-w32
cp build/src/RCRAFT.exe OUTPUT-w32/CubeGame.exe cp build/src/RCRAFT.exe OUTPUT-w32/CubeGame.exe
cp -r data/resources OUTPUT-w32 cp -r data/resources OUTPUT-w32
mkdir OUTPUT-w32/user
mkdir OUTPUT-w32/user/worlds
-2
View File
@@ -13,5 +13,3 @@ cd ..
mkdir OUTPUT-w64 mkdir OUTPUT-w64
cp build/src/RCRAFT.exe OUTPUT-w64/CubeGame.exe cp build/src/RCRAFT.exe OUTPUT-w64/CubeGame.exe
cp -r data/resources OUTPUT-w64 cp -r data/resources OUTPUT-w64
mkdir OUTPUT-w64/user
mkdir OUTPUT-w64/user/worlds
-64
View File
@@ -1,64 +0,0 @@
211d25
413d42
5c5b63
7c808b
a5b0b6
d6dede
ffffff
dcded1
aab1a1
7b8375
585f57
3c3c3c
635d5a
8d837d
b4aea4
dedcd1
eadedf
bcacb1
8f8189
685d66
643747
b2434d
e55858
fa8971
ffb999
ffe0b7
ffbdc1
ef93b5
c971a2
944e89
4c3d57
5d558f
777dc4
96b1e7
bedef6
aae3db
5ac5ce
4694a8
346376
2a3b4a
29684a
379648
79b547
b8cf61
f3db6f
f4ba7a
e79055
ce6442
944940
91555d
b76f6b
cd9383
e1ba9e
facafb
d49ce5
9f76b8
725689
edb762
fcfbc9
de9463
b66a4d
333f29
4e5c2c
708939
Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

+6 -8
View File
@@ -14,12 +14,14 @@ speed_up: Fly faster
fly: Toggle flying fly: Toggle flying
chat: Open chat chat: Open chat
swap_mouse: Swap LMB/RMB swap_mouse: Swap LMB/RMB
inventory: Open inventory
# Menu # Menu
select_level: Singleplayer select_level: Singleplayer
multiplayer: Multiplayer multiplayer: Multiplayer
join: Join join: Join
exit: Exit exit: Exit
options: Options options: Options
create_world: Create world
# Multiplayer errors # Multiplayer errors
error_notfound: Host not found! error_notfound: Host not found!
error_internal: Internal enet error! error_internal: Internal enet error!
@@ -41,21 +43,17 @@ item.dirt: "Dirt"
item.sand: "Sand" item.sand: "Sand"
item.water: "Water" item.water: "Water"
item.planks: "Wooden Planks" item.planks: "Wooden Planks"
item.gray_bricks: "Gray Bricks" item.stone_bricks: "Stone Bricks"
item.red_bricks: "Red Bricks" item.copper_block: "Copper Block"
item.blue_bricks: "Blue Bricks" item.silver_block: "Silver Block"
item.green_bricks: "Green Bricks" item.gold_block: "Gold Block"
item.glass: "Glass" item.glass: "Glass"
item.log: "Log" item.log: "Log"
item.spruce_planks: "Spruce Planks" item.spruce_planks: "Spruce Planks"
item.red_block: "Red Block" item.red_block: "Red Block"
item.green_block: "Green Block" item.green_block: "Green Block"
item.blue_block: "Blue Block" item.blue_block: "Blue Block"
item.yellow_block: "Yellow Block"
item.cyan_block: "Cyan Block"
item.magenta_block: "Magenta Block"
item.white_block: "White Block" item.white_block: "White Block"
item.black_block: "Black Block"
item.leaves: "Leaves" item.leaves: "Leaves"
item.copper_ore: "Copper Ore" item.copper_ore: "Copper Ore"
item.silver_ore: "Silver Ore" item.silver_ore: "Silver Ore"
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

+37
View File
@@ -0,0 +1,37 @@
#version 330
in vec2 fragTexCoord;
in vec4 fragColor;
in vec3 fragPosition;
in vec3 fragNormal;
uniform sampler2D texture0;
uniform vec4 sunlightColor;
uniform vec3 lightDir;
out vec4 finalColor;
void main()
{
vec4 texelColor = texture(texture0, fragTexCoord);
vec3 N = normalize(fragNormal);
vec3 L = normalize(lightDir);
float ndotl = max(dot(N, L), 0.0);
float ambient = 0.1;
float sunfactor = ambient + (1.0 - ambient) * ndotl;
sunfactor *= 1+min(0, L.y);
vec3 Lmoon = normalize(-lightDir);
float ndotlMoon = max(dot(N, Lmoon), 0.0);
float moonfactor = (ambient + (1.0 - ambient) * ndotlMoon) * 8;
moonfactor *= max(0, -L.y);
// In fragColor, 'r' is blocklight R, 'g' is blocklight G, 'b' is blocklight B and 'a' is sunlight
texelColor.r *= fragColor.a * sunlightColor.r * (sunfactor+moonfactor) + fragColor.r;
texelColor.g *= fragColor.a * sunlightColor.g * (sunfactor+moonfactor) + fragColor.g;
texelColor.b *= fragColor.a * sunlightColor.b * (sunfactor+moonfactor) + fragColor.b;
finalColor = texelColor;
}
+32
View File
@@ -0,0 +1,32 @@
#version 330
// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
in vec4 vertexColor;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
uniform mat4 matNormal;
// Output vertex attributes (to fragment shader)
out vec3 fragPosition;
out vec2 fragTexCoord;
out vec4 fragColor;
out vec3 fragNormal;
// NOTE: Add your custom variables here
void main()
{
// Send vertex attributes to fragment shader
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0)));
// Calculate final vertex position
gl_Position = mvp*vec4(vertexPosition, 1.0);
}
+46
View File
@@ -0,0 +1,46 @@
#version 330
in vec2 fragTexCoord;
in vec4 fragColor;
in vec3 fragPosition;
in vec3 fragNormal;
uniform sampler2D texture0;
uniform vec4 sunlightColor;
uniform vec4 skyColor;
uniform vec3 lightDir;
out vec4 finalColor;
void main()
{
vec4 texelColor = texture(texture0, fragTexCoord);
vec3 N = normalize(fragNormal);
vec3 L = normalize(lightDir);
float ndotl = max(dot(N, L), 0.0);
float ambient = 0.1;
float sunfactor = ambient + (1.0 - ambient) * ndotl;
sunfactor *= 1+min(0, L.y);
vec3 Lmoon = normalize(-lightDir);
float ndotlMoon = max(dot(N, Lmoon), 0.0);
float moonfactor = (ambient + (1.0 - ambient) * ndotlMoon) * 8;
moonfactor *= max(0, -L.y);
// In fragColor, 'r' is blocklight R, 'g' is blocklight G, 'b' is blocklight B and 'a' is sunlight
float sunlight = fragColor.a;
texelColor.r *= sunlight * sunlightColor.r * (sunfactor+moonfactor) + fragColor.r;
texelColor.g *= sunlight * sunlightColor.g * (sunfactor+moonfactor) + fragColor.g;
texelColor.b *= sunlight * sunlightColor.b * (sunfactor+moonfactor) + fragColor.b;
float highlight = texelColor.a;
if(highlight < 0.25) highlight = 0;
float highlight_final = abs(N.y)*highlight * 4;
vec3 highlightColor = sunlightColor.rgb*highlight_final*sunlight;
highlightColor.r += fragColor.r*highlight_final;
highlightColor.g += fragColor.g*highlight_final;
highlightColor.b += fragColor.b*highlight_final;
finalColor = texelColor + vec4(highlightColor, min(1.0, highlight_final));
}
+34
View File
@@ -0,0 +1,34 @@
#version 330
// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
in vec4 vertexColor;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
uniform mat4 matNormal;
uniform float time;
// Output vertex attributes (to fragment shader)
out vec3 fragPosition;
out vec2 fragTexCoord;
out vec4 fragColor;
out vec3 fragNormal;
// NOTE: Add your custom variables here
void main()
{
// Send vertex attributes to fragment shader
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0)));
// Calculate final vertex position
vec3 pos = vertexPosition + vec3(0, sin(time * 2.0 + vertexPosition.x * 1.5) / 20.0 + cos(time * 2.0 + vertexPosition.z * 1.5) / 20.0-0.1, 0);
gl_Position = mvp*vec4(pos, 1.0);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

+1 -1
View File
@@ -5,7 +5,7 @@ add_subdirectory(helpers)
set(YAML_BUILD_SHARED_LIBS OFF) set(YAML_BUILD_SHARED_LIBS OFF)
set(YAML_MSVC_SHARED_RT OFF) set(YAML_MSVC_SHARED_RT OFF)
set(OPENGL_VERSION 2.1) set(OPENGL_VERSION 3.3)
add_subdirectory(libraries/raylib) add_subdirectory(libraries/raylib)
add_subdirectory(libraries/enet) add_subdirectory(libraries/enet)
+2441
View File
File diff suppressed because it is too large Load Diff
-659
View File
@@ -1,659 +0,0 @@
//----------------------------------------------------------------------------------------
//
// siv::PerlinNoise
// Perlin noise library for modern C++
//
// Copyright (C) 2013-2021 Ryo Suzuki <reputeless@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//----------------------------------------------------------------------------------------
# pragma once
# include <cstdint>
# include <algorithm>
# include <array>
# include <iterator>
# include <numeric>
# include <random>
# include <type_traits>
# if __has_include(<concepts>) && defined(__cpp_concepts)
# include <concepts>
# endif
// Library major version
# define SIVPERLIN_VERSION_MAJOR 3
// Library minor version
# define SIVPERLIN_VERSION_MINOR 0
// Library revision version
# define SIVPERLIN_VERSION_REVISION 0
// Library version
# define SIVPERLIN_VERSION ((SIVPERLIN_VERSION_MAJOR * 100 * 100) + (SIVPERLIN_VERSION_MINOR * 100) + (SIVPERLIN_VERSION_REVISION))
// [[nodiscard]] for constructors
# if (201907L <= __has_cpp_attribute(nodiscard))
# define SIVPERLIN_NODISCARD_CXX20 [[nodiscard]]
# else
# define SIVPERLIN_NODISCARD_CXX20
# endif
// std::uniform_random_bit_generator concept
# if __cpp_lib_concepts
# define SIVPERLIN_CONCEPT_URBG template <std::uniform_random_bit_generator URBG>
# define SIVPERLIN_CONCEPT_URBG_ template <std::uniform_random_bit_generator URBG>
# else
# define SIVPERLIN_CONCEPT_URBG template <class URBG, std::enable_if_t<std::conjunction_v<std::is_invocable<URBG&>, std::is_unsigned<std::invoke_result_t<URBG&>>>>* = nullptr>
# define SIVPERLIN_CONCEPT_URBG_ template <class URBG, std::enable_if_t<std::conjunction_v<std::is_invocable<URBG&>, std::is_unsigned<std::invoke_result_t<URBG&>>>>*>
# endif
// arbitrary value for increasing entropy
# ifndef SIVPERLIN_DEFAULT_Y
# define SIVPERLIN_DEFAULT_Y (0.12345)
# endif
// arbitrary value for increasing entropy
# ifndef SIVPERLIN_DEFAULT_Z
# define SIVPERLIN_DEFAULT_Z (0.34567)
# endif
namespace siv
{
template <class Float>
class BasicPerlinNoise
{
public:
static_assert(std::is_floating_point_v<Float>);
///////////////////////////////////////
//
// Typedefs
//
using state_type = std::array<std::uint8_t, 256>;
using value_type = Float;
using default_random_engine = std::mt19937;
using seed_type = typename default_random_engine::result_type;
///////////////////////////////////////
//
// Constructors
//
SIVPERLIN_NODISCARD_CXX20
constexpr BasicPerlinNoise() noexcept;
SIVPERLIN_NODISCARD_CXX20
explicit BasicPerlinNoise(seed_type seed);
SIVPERLIN_CONCEPT_URBG
SIVPERLIN_NODISCARD_CXX20
explicit BasicPerlinNoise(URBG&& urbg);
///////////////////////////////////////
//
// Reseed
//
void reseed(seed_type seed);
SIVPERLIN_CONCEPT_URBG
void reseed(URBG&& urbg);
///////////////////////////////////////
//
// Serialization
//
[[nodiscard]]
constexpr const state_type& serialize() const noexcept;
constexpr void deserialize(const state_type& state) noexcept;
///////////////////////////////////////
//
// Noise (The result is in the range [-1, 1])
//
[[nodiscard]]
value_type noise1D(value_type x) const noexcept;
[[nodiscard]]
value_type noise2D(value_type x, value_type y) const noexcept;
[[nodiscard]]
value_type noise3D(value_type x, value_type y, value_type z) const noexcept;
///////////////////////////////////////
//
// Noise (The result is remapped to the range [0, 1])
//
[[nodiscard]]
value_type noise1D_01(value_type x) const noexcept;
[[nodiscard]]
value_type noise2D_01(value_type x, value_type y) const noexcept;
[[nodiscard]]
value_type noise3D_01(value_type x, value_type y, value_type z) const noexcept;
///////////////////////////////////////
//
// Octave noise (The result can be out of the range [-1, 1])
//
[[nodiscard]]
value_type octave1D(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
[[nodiscard]]
value_type octave2D(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
[[nodiscard]]
value_type octave3D(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
///////////////////////////////////////
//
// Octave noise (The result is clamped to the range [-1, 1])
//
[[nodiscard]]
value_type octave1D_11(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
[[nodiscard]]
value_type octave2D_11(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
[[nodiscard]]
value_type octave3D_11(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
///////////////////////////////////////
//
// Octave noise (The result is clamped and remapped to the range [0, 1])
//
[[nodiscard]]
value_type octave1D_01(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
[[nodiscard]]
value_type octave2D_01(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
[[nodiscard]]
value_type octave3D_01(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
///////////////////////////////////////
//
// Octave noise (The result is normalized to the range [-1, 1])
//
[[nodiscard]]
value_type normalizedOctave1D(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
[[nodiscard]]
value_type normalizedOctave2D(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
[[nodiscard]]
value_type normalizedOctave3D(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
///////////////////////////////////////
//
// Octave noise (The result is normalized and remapped to the range [0, 1])
//
[[nodiscard]]
value_type normalizedOctave1D_01(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
[[nodiscard]]
value_type normalizedOctave2D_01(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
[[nodiscard]]
value_type normalizedOctave3D_01(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
private:
state_type m_permutation;
};
using PerlinNoise = BasicPerlinNoise<double>;
namespace perlin_detail
{
////////////////////////////////////////////////
//
// These functions are provided for consistency.
// You may get different results from std::shuffle() with different standard library implementations.
//
SIVPERLIN_CONCEPT_URBG
[[nodiscard]]
inline std::uint64_t Random(const std::uint64_t max, URBG&& urbg)
{
return (urbg() % (max + 1));
}
template <class RandomIt, class URBG>
inline void Shuffle(RandomIt first, RandomIt last, URBG&& urbg)
{
if (first == last)
{
return;
}
using difference_type = typename std::iterator_traits<RandomIt>::difference_type;
for (RandomIt it = first + 1; it < last; ++it)
{
const std::uint64_t n = static_cast<std::uint64_t>(it - first);
std::iter_swap(it, first + static_cast<difference_type>(Random(n, std::forward<URBG>(urbg))));
}
}
//
////////////////////////////////////////////////
template <class Float>
[[nodiscard]]
inline constexpr Float Fade(const Float t) noexcept
{
return t * t * t * (t * (t * 6 - 15) + 10);
}
template <class Float>
[[nodiscard]]
inline constexpr Float Lerp(const Float a, const Float b, const Float t) noexcept
{
return (a + (b - a) * t);
}
template <class Float>
[[nodiscard]]
inline constexpr Float Grad(const std::uint8_t hash, const Float x, const Float y, const Float z) noexcept
{
const std::uint8_t h = hash & 15;
const Float u = h < 8 ? x : y;
const Float v = h < 4 ? y : h == 12 || h == 14 ? x : z;
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
}
template <class Float>
[[nodiscard]]
inline constexpr Float Remap_01(const Float x) noexcept
{
return (x * Float(0.5) + Float(0.5));
}
template <class Float>
[[nodiscard]]
inline constexpr Float Clamp_11(const Float x) noexcept
{
return std::clamp(x, Float(-1.0), Float(1.0));
}
template <class Float>
[[nodiscard]]
inline constexpr Float RemapClamp_01(const Float x) noexcept
{
if (x <= Float(-1.0))
{
return Float(0.0);
}
else if (Float(1.0) <= x)
{
return Float(1.0);
}
return (x * Float(0.5) + Float(0.5));
}
template <class Noise, class Float>
[[nodiscard]]
inline auto Octave1D(const Noise& noise, Float x, const std::int32_t octaves, const Float persistence) noexcept
{
using value_type = Float;
value_type result = 0;
value_type amplitude = 1;
for (std::int32_t i = 0; i < octaves; ++i)
{
result += (noise.noise1D(x) * amplitude);
x *= 2;
amplitude *= persistence;
}
return result;
}
template <class Noise, class Float>
[[nodiscard]]
inline auto Octave2D(const Noise& noise, Float x, Float y, const std::int32_t octaves, const Float persistence) noexcept
{
using value_type = Float;
value_type result = 0;
value_type amplitude = 1;
for (std::int32_t i = 0; i < octaves; ++i)
{
result += (noise.noise2D(x, y) * amplitude);
x *= 2;
y *= 2;
amplitude *= persistence;
}
return result;
}
template <class Noise, class Float>
[[nodiscard]]
inline auto Octave3D(const Noise& noise, Float x, Float y, Float z, const std::int32_t octaves, const Float persistence) noexcept
{
using value_type = Float;
value_type result = 0;
value_type amplitude = 1;
for (std::int32_t i = 0; i < octaves; ++i)
{
result += (noise.noise3D(x, y, z) * amplitude);
x *= 2;
y *= 2;
z *= 2;
amplitude *= persistence;
}
return result;
}
template <class Float>
[[nodiscard]]
inline constexpr Float MaxAmplitude(const std::int32_t octaves, const Float persistence) noexcept
{
using value_type = Float;
value_type result = 0;
value_type amplitude = 1;
for (std::int32_t i = 0; i < octaves; ++i)
{
result += amplitude;
amplitude *= persistence;
}
return result;
}
}
///////////////////////////////////////
template <class Float>
inline constexpr BasicPerlinNoise<Float>::BasicPerlinNoise() noexcept
: m_permutation{ 151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 } {}
template <class Float>
inline BasicPerlinNoise<Float>::BasicPerlinNoise(const seed_type seed)
{
reseed(seed);
}
template <class Float>
SIVPERLIN_CONCEPT_URBG_
inline BasicPerlinNoise<Float>::BasicPerlinNoise(URBG&& urbg)
{
reseed(std::forward<URBG>(urbg));
}
///////////////////////////////////////
template <class Float>
inline void BasicPerlinNoise<Float>::reseed(const seed_type seed)
{
reseed(default_random_engine{ seed });
}
template <class Float>
SIVPERLIN_CONCEPT_URBG_
inline void BasicPerlinNoise<Float>::reseed(URBG&& urbg)
{
std::iota(m_permutation.begin(), m_permutation.end(), uint8_t{ 0 });
perlin_detail::Shuffle(m_permutation.begin(), m_permutation.end(), std::forward<URBG>(urbg));
}
///////////////////////////////////////
template <class Float>
inline constexpr const typename BasicPerlinNoise<Float>::state_type& BasicPerlinNoise<Float>::serialize() const noexcept
{
return m_permutation;
}
template <class Float>
inline constexpr void BasicPerlinNoise<Float>::deserialize(const state_type& state) noexcept
{
m_permutation = state;
}
///////////////////////////////////////
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise1D(const value_type x) const noexcept
{
return noise3D(x,
static_cast<value_type>(SIVPERLIN_DEFAULT_Y),
static_cast<value_type>(SIVPERLIN_DEFAULT_Z));
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise2D(const value_type x, const value_type y) const noexcept
{
return noise3D(x,
y,
static_cast<value_type>(SIVPERLIN_DEFAULT_Z));
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise3D(const value_type x, const value_type y, const value_type z) const noexcept
{
const value_type _x = std::floor(x);
const value_type _y = std::floor(y);
const value_type _z = std::floor(z);
const std::int32_t ix = static_cast<std::int32_t>(_x) & 255;
const std::int32_t iy = static_cast<std::int32_t>(_y) & 255;
const std::int32_t iz = static_cast<std::int32_t>(_z) & 255;
const value_type fx = (x - _x);
const value_type fy = (y - _y);
const value_type fz = (z - _z);
const value_type u = perlin_detail::Fade(fx);
const value_type v = perlin_detail::Fade(fy);
const value_type w = perlin_detail::Fade(fz);
const std::uint8_t A = (m_permutation[ix & 255] + iy) & 255;
const std::uint8_t B = (m_permutation[(ix + 1) & 255] + iy) & 255;
const std::uint8_t AA = (m_permutation[A] + iz) & 255;
const std::uint8_t AB = (m_permutation[(A + 1) & 255] + iz) & 255;
const std::uint8_t BA = (m_permutation[B] + iz) & 255;
const std::uint8_t BB = (m_permutation[(B + 1) & 255] + iz) & 255;
const value_type p0 = perlin_detail::Grad(m_permutation[AA], fx, fy, fz);
const value_type p1 = perlin_detail::Grad(m_permutation[BA], fx - 1, fy, fz);
const value_type p2 = perlin_detail::Grad(m_permutation[AB], fx, fy - 1, fz);
const value_type p3 = perlin_detail::Grad(m_permutation[BB], fx - 1, fy - 1, fz);
const value_type p4 = perlin_detail::Grad(m_permutation[(AA + 1) & 255], fx, fy, fz - 1);
const value_type p5 = perlin_detail::Grad(m_permutation[(BA + 1) & 255], fx - 1, fy, fz - 1);
const value_type p6 = perlin_detail::Grad(m_permutation[(AB + 1) & 255], fx, fy - 1, fz - 1);
const value_type p7 = perlin_detail::Grad(m_permutation[(BB + 1) & 255], fx - 1, fy - 1, fz - 1);
const value_type q0 = perlin_detail::Lerp(p0, p1, u);
const value_type q1 = perlin_detail::Lerp(p2, p3, u);
const value_type q2 = perlin_detail::Lerp(p4, p5, u);
const value_type q3 = perlin_detail::Lerp(p6, p7, u);
const value_type r0 = perlin_detail::Lerp(q0, q1, v);
const value_type r1 = perlin_detail::Lerp(q2, q3, v);
return perlin_detail::Lerp(r0, r1, w);
}
///////////////////////////////////////
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise1D_01(const value_type x) const noexcept
{
return perlin_detail::Remap_01(noise1D(x));
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise2D_01(const value_type x, const value_type y) const noexcept
{
return perlin_detail::Remap_01(noise2D(x, y));
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise3D_01(const value_type x, const value_type y, const value_type z) const noexcept
{
return perlin_detail::Remap_01(noise3D(x, y, z));
}
///////////////////////////////////////
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave1D(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
{
return perlin_detail::Octave1D(*this, x, octaves, persistence);
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave2D(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
{
return perlin_detail::Octave2D(*this, x, y, octaves, persistence);
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave3D(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
{
return perlin_detail::Octave3D(*this, x, y, z, octaves, persistence);
}
///////////////////////////////////////
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave1D_11(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
{
return perlin_detail::Clamp_11(octave1D(x, octaves, persistence));
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave2D_11(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
{
return perlin_detail::Clamp_11(octave2D(x, y, octaves, persistence));
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave3D_11(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
{
return perlin_detail::Clamp_11(octave3D(x, y, z, octaves, persistence));
}
///////////////////////////////////////
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave1D_01(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
{
return perlin_detail::RemapClamp_01(octave1D(x, octaves, persistence));
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave2D_01(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
{
return perlin_detail::RemapClamp_01(octave2D(x, y, octaves, persistence));
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave3D_01(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
{
return perlin_detail::RemapClamp_01(octave3D(x, y, z, octaves, persistence));
}
///////////////////////////////////////
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave1D(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
{
return (octave1D(x, octaves, persistence) / perlin_detail::MaxAmplitude(octaves, persistence));
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave2D(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
{
return (octave2D(x, y, octaves, persistence) / perlin_detail::MaxAmplitude(octaves, persistence));
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave3D(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
{
return (octave3D(x, y, z, octaves, persistence) / perlin_detail::MaxAmplitude(octaves, persistence));
}
///////////////////////////////////////
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave1D_01(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
{
return perlin_detail::Remap_01(normalizedOctave1D(x, octaves, persistence));
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave2D_01(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
{
return perlin_detail::Remap_01(normalizedOctave2D(x, y, octaves, persistence));
}
template <class Float>
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave3D_01(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
{
return perlin_detail::Remap_01(normalizedOctave3D(x, y, z, octaves, persistence));
}
}
# undef SIVPERLIN_NODISCARD_CXX20
# undef SIVPERLIN_CONCEPT_URBG
# undef SIVPERLIN_CONCEPT_URBG_
+148 -79
View File
@@ -9,9 +9,12 @@
#include <iostream> #include <iostream>
#include <queue> #include <queue>
#define FNL_IMPL
#include "../FastNoiseLite.h"
#define HUMIDITY_OFFSET 12.3f #define HUMIDITY_OFFSET 12.3f
#define CAVE_OFFSET 45.6f #define CAVE_OFFSET 45.6f
#define SCALE 0.01f #define SCALE 0.1f
#define CAVE_COEFF 0.06 #define CAVE_COEFF 0.06
#define EDGES_FADE 64 #define EDGES_FADE 64
#define CLOUD_SCALE 0.25f #define CLOUD_SCALE 0.25f
@@ -19,7 +22,9 @@
#define BIOME_FOREST 0 #define BIOME_FOREST 0
#define BIOME_TAIGA 1 #define BIOME_TAIGA 1
static const siv::PerlinNoise perlin; static fnl_state perlin;
static fnl_state perlin2;
static fnl_state perlinLofi;
static int world_type = 0; static int world_type = 0;
@@ -31,10 +36,10 @@ std::vector<BlockDef> BLOCKS = {
BlockDef{ "sand", R_Normal, B_Dirt, 2, 0, 4}, BlockDef{ "sand", R_Normal, B_Dirt, 2, 0, 4},
BlockDef{ "water", R_Translucent, B_Stone, 0, 0, 14}, BlockDef{ "water", R_Translucent, B_Stone, 0, 0, 14},
BlockDef{ "planks", R_Normal, B_Wood, 3, 0, 11}, BlockDef{ "planks", R_Normal, B_Wood, 3, 0, 11},
BlockDef{ "gray_bricks", R_Normal, B_Stone, 5, 1, 16}, BlockDef{ "stone_bricks", R_Normal, B_Stone, 5, 1, 16},
BlockDef{ "red_bricks", R_Normal, B_Stone, 5, 1, 17}, BlockDef{ "copper_block", R_Normal, B_Stone, 5, 1, 17},
BlockDef{ "blue_bricks", R_Normal, B_Stone, 5, 1, 18}, BlockDef{ "silver_block", R_Normal, B_Stone, 5, 1, 18},
BlockDef{ "green_bricks", R_Normal, B_Stone, 5, 1, 19}, BlockDef{ "gold_block", R_Normal, B_Stone, 5, 1, 19},
BlockDef{ "glass", R_Translucent, B_Stone, 3, 1, 12}, BlockDef{ "glass", R_Translucent, B_Stone, 3, 1, 12},
BlockDef{ "log", R_TriSide, B_Wood, 5, 0, 10, 9, 10}, BlockDef{ "log", R_TriSide, B_Wood, 5, 0, 10, 9, 10},
BlockDef{ "spruce_planks", R_Normal, B_Wood, 3, 0, 13}, BlockDef{ "spruce_planks", R_Normal, B_Wood, 3, 0, 13},
@@ -67,24 +72,38 @@ int GetNumericIDFromString(std::string s) {
} }
static std::bitset<256> marked; static std::bitset<256> marked;
static int GetBlockRegularWorld(int x, int y, int z) { static int GetBlockRegularWorld(int _x, int y, int _z) {
float fade_x = (fmax(EDGES_FADE - x, 0) + fmax(EDGES_FADE - WORLD_SIZE_BLOCKS + x, 0)) / (float)EDGES_FADE; int x = _x + 0;
float fade_z = (fmax(EDGES_FADE - z, 0) + fmax(EDGES_FADE - WORLD_SIZE_BLOCKS + z, 0)) / (float)EDGES_FADE; int z = _z + 0;
float fade = 1 - (fade_x + fade_z); const int SEA_HEIGHT = 64;
const int BEACH_DEPTH = 3;
const float heightBias = 24;
float p0 = fnlGetNoise3D(&perlin, (float)x, y / 2.0f, z);
float p1 = fnlGetNoise3D(&perlin2, x, y / 2.0f, z);
float pr = fnlGetNoise3D(&perlinLofi, x, y / 2.0f, z)*12.75f;
float P = 0;
if(pr >= 1) P = p1;
if(pr <= 0) P = p0;
if(pr>0&&pr<1) P = Lerp(p0, p1, pr);
float density = P + (WORLD_HEIGHT-(y+60)) / heightBias;
if(density > 0.5f) {
return BLOCK_STONE;
}
if(density > 0) {
return BLOCK_DIRT;
}
if(y < SEA_HEIGHT) {
return BLOCK_WATERS;
}
//float height0 = (fnlGetNoise3D(&perlin, x, y, z) + 1.0f ) / 2.0f * 8.0f;
//float height1 = (fnlGetNoise3D(&perlin2, x, y, z) + 1.0f ) / 2.0f * 16.0f;
const int SEA_HEIGHT = 32; // sea surface y //int height = Lerp(height0, height1, fnlGetNoise2D(&perlinLofi, x, z)) + 26 + 48;
const int BEACH_DEPTH = 3; // how many blocks below surface become sand //float dist = Vector2Distance({(float)x, (float)z}, {MAX_WORLD_SIZE*CHUNK_SIZE/2, MAX_WORLD_SIZE*CHUNK_SIZE/2});
float height0 = (perlin.noise2D((double)x * 1.5f * SCALE, (double)z * 1.5f * SCALE) + 1.0f ) / 2.0f * 16.0f; //height = Lerp(32, height, fmin(1.0f, -fmin(0.0f, dist - (MAX_WORLD_SIZE*CHUNK_SIZE/2)-48)/96.0f));
float mountains = pow((perlin.noise2D((double)x * 0.5f, (double)z * 0.5f * SCALE) + 1.0f ) / 2.0f, 16); /*if (y <= height) {
float height1 = (perlin.noise2D((double)x * 4.5f * SCALE, (double)z * 4.5f * SCALE) + 1.0f ) / 2.0f * 24.0f * mountains; //if(caveNoise < 0.02f) return BLOCK_AIR;
int height = floor((height0 + height1) * fade) + 26;
float caveNoise = fabs(perlin.noise3D((double)x * 1.0f * SCALE + CAVE_OFFSET, (double)y * 4.0f * SCALE + CAVE_OFFSET, (double)z * 1.0f * SCALE + CAVE_OFFSET));
if (y <= height) {
if(caveNoise < 0.02f) return BLOCK_AIR;
if (y == height) { if (y == height) {
if (height <= SEA_HEIGHT) { if (height <= SEA_HEIGHT) {
return BLOCK_SAND; return BLOCK_SAND;
@@ -96,13 +115,13 @@ static int GetBlockRegularWorld(int x, int y, int z) {
if (y > height - BEACH_DEPTH && height <= SEA_HEIGHT + 2) { if (y > height - BEACH_DEPTH && height <= SEA_HEIGHT + 2) {
return BLOCK_SAND; return BLOCK_SAND;
} }
if(caveNoise < 0.2f || y < 4) return BLOCK_STONE; //if(caveNoise < 0.2f || y < 4) return BLOCK_STONE;
return BLOCK_DIRT; return BLOCK_DIRT;
} }
if (y <= SEA_HEIGHT && height < SEA_HEIGHT) { if (y <= SEA_HEIGHT && height < SEA_HEIGHT) {
return BLOCK_WATERS; return BLOCK_WATERS;
} }*/
return BLOCK_AIR; return BLOCK_AIR;
} }
@@ -162,6 +181,7 @@ int GetBLight(World &world, int x, int y, int z) {
int skyLight = light & 0xF; int skyLight = light & 0xF;
return skyLight; return skyLight;
} }
Color GetSunlightColor();
Color GetLight(World &world, int x, int y, int z) { Color GetLight(World &world, int x, int y, int z) {
if(CheckOOBWorld(x, y, z)) return {0, 0, 0, 0}; if(CheckOOBWorld(x, y, z)) return {0, 0, 0, 0};
int locX = x % CHUNK_SIZE; int locX = x % CHUNK_SIZE;
@@ -173,24 +193,41 @@ Color GetLight(World &world, int x, int y, int z) {
Color r = {((light >> 8) & 0xF) * 16, 0, 0, 255}; Color r = {((light >> 8) & 0xF) * 16, 0, 0, 255};
Color g = {0, ((light >> 4) & 0xF) * 16, 0, 255}; Color g = {0, ((light >> 4) & 0xF) * 16, 0, 255};
Color b = {0, 0, ((light >> 0) & 0xF) * 16, 255}; Color b = {0, 0, ((light >> 0) & 0xF) * 16, 255};
Color sun = GetSunlightColor();
return { return {
fmin((int)skyLight + (int)r.r, 255), fmax((int)skyLight * (sun.r/255.0f), (int)r.r),
fmin((int)skyLight + (int)g.g, 255), fmax((int)skyLight * (sun.g/255.0f), (int)g.g),
fmin((int)skyLight + (int)b.b, 255), fmax((int)skyLight * (sun.b/255.0f), (int)b.b),
255 255
}; };
} }
Color GetLightMesher(World &world, int x, int y, int z) {
if(CheckOOBWorld(x, y, z)) return {0, 0, 0, 0};
int locX = x % CHUNK_SIZE;
int locZ = z % CHUNK_SIZE;
int cx = x / CHUNK_SIZE;
int cz = z / CHUNK_SIZE;
uint16_t light = world.chunks[GetIndexWorld(cx, cz)].light[GetIndexChunk(locX, y, locZ)];
int skyLight = powf(((light >> 12) & 0xF) / 15.0f, 1) * 255;
return {
((light >> 8) & 0xF) * 16,
((light >> 4) & 0xF) * 16,
((light >> 0) & 0xF) * 16,
skyLight
};
}
bool CanTick(int blockType) { // TODO: make smarter in case other blocks can tick too! bool CanTick(int blockType) { // TODO: make smarter in case other blocks can tick too!
return blockType == BLOCK_SAND; return blockType == BLOCK_SAND;
} }
bool GetCloud(int x, int z) { bool GetCloud(int x, int z) {
return (perlin.noise2D((x / 8) * 1.5f * CLOUD_SCALE, (z / 8) * 1.5f * CLOUD_SCALE) + 1.0f) / 2.0f > 0.5f; //return (perlin.noise2D((x / 8) * 1.5f * CLOUD_SCALE, (z / 8) * 1.5f * CLOUD_SCALE) + 1.0f) / 2.0f > 0.5f;
return false;
} }
static int GetBlockCaveWorld(int x, int y, int z) { static int GetBlockCaveWorld(int x, int y, int z) {
float caveNoise = (perlin.noise3D((float)x * 3.0f * SCALE + CAVE_OFFSET, (float)y * 3.0f * SCALE + CAVE_OFFSET, (float)z * 3.0f * SCALE + CAVE_OFFSET) + 1.0f) / 2.0f; /*float caveNoise = (perlin.noise3D((float)x * 3.0f * SCALE + CAVE_OFFSET, (float)y * 3.0f * SCALE + CAVE_OFFSET, (float)z * 3.0f * SCALE + CAVE_OFFSET) + 1.0f) / 2.0f;
if(caveNoise > 0.5f) { if(caveNoise > 0.5f) {
return BLOCK_STONE; return BLOCK_STONE;
} }*/
return BLOCK_AIR; return BLOCK_AIR;
} }
static int has_block(int x, int y, int z) static int has_block(int x, int y, int z)
@@ -311,8 +348,24 @@ void SetLight(World &world, int x, int y, int z, uint8_t sky, uint8_t r, uint8_t
} }
void InitWorldgen(int worldType) { void InitWorldgen(int worldType) {
const siv::PerlinNoise::seed_type seed = 0u; perlin = fnlCreateState();
const siv::PerlinNoise perlin{ seed }; perlin.noise_type = FNL_NOISE_OPENSIMPLEX2;
perlin.fractal_type = FNL_FRACTAL_FBM;
perlin.frequency = 0.00522f;
perlin.octaves = 8;
perlinLofi = fnlCreateState();
perlinLofi.noise_type = FNL_NOISE_OPENSIMPLEX2;
perlinLofi.fractal_type = FNL_FRACTAL_FBM;
perlinLofi.frequency = 0.01671f;
perlinLofi.octaves = 4;
perlin2 = fnlCreateState();
perlin2.noise_type = FNL_NOISE_OPENSIMPLEX2;
perlin2.fractal_type = FNL_FRACTAL_FBM;
perlin2.frequency = 0.00522f;
perlin2.octaves = 8;
constexpr size_t MAX = 128; // allowed range: 0..MAX-1 constexpr size_t MAX = 128; // allowed range: 0..MAX-1
for (int i = 0; i < BLOCKS.size(); i++) for (int i = 0; i < BLOCKS.size(); i++)
{ {
@@ -332,17 +385,12 @@ Chunk GenerateChunk(int _x, int _y) {
new_chunk.x = _x; new_chunk.x = _x;
new_chunk.z = _y; new_chunk.z = _y;
memset(&new_chunk.light, 0, sizeof(new_chunk.light)); memset(&new_chunk.light, 0, sizeof(new_chunk.light));
for (int x = 0; x < CHUNK_SIZE; x++)
{
for (int y = 0; y < WORLD_HEIGHT; y++) for (int y = 0; y < WORLD_HEIGHT; y++)
{ for (int x = 0; x < CHUNK_SIZE; x++)
for (int z = 0; z < CHUNK_SIZE; z++) for (int z = 0; z < CHUNK_SIZE; z++) {
{
int id = has_block(_x * CHUNK_SIZE + x,y,_y * CHUNK_SIZE + z); int id = has_block(_x * CHUNK_SIZE + x,y,_y * CHUNK_SIZE + z);
SetBlockChunk(&new_chunk, x, y, z, id); SetBlockChunk(&new_chunk, x, y, z, id);
} }
}
}
return new_chunk; return new_chunk;
} }
void GenerateWorldAdditional(World &world) { void GenerateWorldAdditional(World &world) {
@@ -357,33 +405,8 @@ void GenerateWorldAdditional(World &world) {
Chunk c = world.chunks[GetIndexWorld(x / CHUNK_SIZE, z / CHUNK_SIZE)]; Chunk c = world.chunks[GetIndexWorld(x / CHUNK_SIZE, z / CHUNK_SIZE)];
int highestY = c.highestBlock[GetIndexChunk2D(x % CHUNK_SIZE, z % CHUNK_SIZE)]; int highestY = c.highestBlock[GetIndexChunk2D(x % CHUNK_SIZE, z % CHUNK_SIZE)];
int b = fetch_block(c, x % CHUNK_SIZE, highestY, z % CHUNK_SIZE); int b = fetch_block(c, x % CHUNK_SIZE, highestY, z % CHUNK_SIZE);
for (int _ = 0; _ < GetRandomValue(0, 6); _++) if(b == BLOCK_DIRT) {
{ SetBlock(world, x, highestY, z, BLOCK_GRASS);
if(GetRandomValue(0, 800) == 0) {
int max = GetRandomValue(10, 120);
Vector3 pos = {x, GetRandomValue(12, WORLD_HEIGHT-32), z};
Vector3 direction = {GetRandomValue(-100, 100) / 100.0f, GetRandomValue(-100, -5) / 100.0f, GetRandomValue(-100, 100) / 100.0f};
int radius = 2;
for (int _ = 0; _ < max; _++)
{
for (int x = -radius; x < radius; x++)
{
for (int y = -radius; y < radius; y++)
{
for (int z = -radius; z < radius; z++)
{
if(Vector3Distance({pos.x + x, pos.y + y, pos.z + z}, pos) <= radius) {
if(!CheckOOBWorld(pos.x + x, pos.y + y, pos.z + z)) {
SetBlock(world, pos.x + x, pos.y + y, pos.z + z, 0);
}
}
}
}
}
direction += {GetRandomValue(-100, 100) / 100.0f, GetRandomValue(-100, -5) / 100.0f, GetRandomValue(-100, 100) / 100.0f};
pos += direction;
}
}
} }
for (int _ = 0; _ < GetRandomValue(8, 24); _++) for (int _ = 0; _ < GetRandomValue(8, 24); _++)
{ {
@@ -424,7 +447,7 @@ void GenerateWorldAdditional(World &world) {
Chunk c = world.chunks[GetIndexWorld(x / CHUNK_SIZE, z / CHUNK_SIZE)]; Chunk c = world.chunks[GetIndexWorld(x / CHUNK_SIZE, z / CHUNK_SIZE)];
int highestY = c.highestBlock[GetIndexChunk2D(x % CHUNK_SIZE, z % CHUNK_SIZE)]; int highestY = c.highestBlock[GetIndexChunk2D(x % CHUNK_SIZE, z % CHUNK_SIZE)];
int b = fetch_block(c, x % CHUNK_SIZE, highestY, z % CHUNK_SIZE); int b = fetch_block(c, x % CHUNK_SIZE, highestY, z % CHUNK_SIZE);
if(b == BLOCK_GRASS && GetRandomValue(0, 100) < 4 && biome == BIOME_FOREST) { // Regular trees if(b == BLOCK_GRASS && GetRandomValue(0, 100) == 0 && biome == BIOME_FOREST) { // Regular trees
SetBlock(world, x, highestY, z, BLOCK_DIRT); SetBlock(world, x, highestY, z, BLOCK_DIRT);
int maxY = GetRandomValue(5, 7); int maxY = GetRandomValue(5, 7);
for (int y = 1; y < maxY; y++) for (int y = 1; y < maxY; y++)
@@ -441,7 +464,7 @@ void GenerateWorldAdditional(World &world) {
SetBlock(world, x, wy, z, 12); // log SetBlock(world, x, wy, z, 12); // log
} }
} }
if(b == BLOCK_GRASS && GetRandomValue(0, 100) < 2 && biome == BIOME_TAIGA) { // Spruce if(b == BLOCK_GRASS && GetRandomValue(0, 100) == 0 && biome == BIOME_TAIGA) { // Spruce
SetBlock(world, x, highestY, z, BLOCK_DIRT); SetBlock(world, x, highestY, z, BLOCK_DIRT);
int maxY = 8; int maxY = 8;
for (int y = 1; y < maxY; y++) for (int y = 1; y < maxY; y++)
@@ -658,7 +681,6 @@ void RebuildLighting(World &world, int startX, int startZ) {
} }
} }
} }
std::cout << nodes.size() << std::endl;
while (!nodes.empty()) { while (!nodes.empty()) {
LightNode node = nodes.front(); LightNode node = nodes.front();
nodes.pop(); nodes.pop();
@@ -696,7 +718,6 @@ void RebuildLighting(World &world, int startX, int startZ) {
if (CheckOOBWorld(x, y, z)) continue; if (CheckOOBWorld(x, y, z)) continue;
if(chunk.blocks[i] != 18 && chunk.blocks[i] != 21) continue; if(chunk.blocks[i] != 18 && chunk.blocks[i] != 21) continue;
Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE }; Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE };
std::cout << pos.y << std::endl;
LightNode node{pos, 15}; LightNode node{pos, 15};
nodesR.push(node); nodesR.push(node);
} }
@@ -704,7 +725,6 @@ void RebuildLighting(World &world, int startX, int startZ) {
} }
while (!nodesR.empty()) { while (!nodesR.empty()) {
std::cout << nodesR.size() << std::endl;
LightNode node = nodesR.front(); LightNode node = nodesR.front();
nodesR.pop(); nodesR.pop();
@@ -741,7 +761,6 @@ void RebuildLighting(World &world, int startX, int startZ) {
if (CheckOOBWorld(x, y, z)) continue; if (CheckOOBWorld(x, y, z)) continue;
if(chunk.blocks[i] != 19 && chunk.blocks[i] != 21) continue; if(chunk.blocks[i] != 19 && chunk.blocks[i] != 21) continue;
Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE }; Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE };
std::cout << pos.y << std::endl;
LightNode node{pos, 15}; LightNode node{pos, 15};
nodesG.push(node); nodesG.push(node);
} }
@@ -749,7 +768,6 @@ void RebuildLighting(World &world, int startX, int startZ) {
} }
while (!nodesG.empty()) { while (!nodesG.empty()) {
std::cout << nodesG.size() << std::endl;
LightNode node = nodesG.front(); LightNode node = nodesG.front();
nodesG.pop(); nodesG.pop();
@@ -786,7 +804,6 @@ void RebuildLighting(World &world, int startX, int startZ) {
if (CheckOOBWorld(x, y, z)) continue; if (CheckOOBWorld(x, y, z)) continue;
if(chunk.blocks[i] != 20 && chunk.blocks[i] != 21) continue; if(chunk.blocks[i] != 20 && chunk.blocks[i] != 21) continue;
Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE }; Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE };
std::cout << pos.y << std::endl;
LightNode node{pos, 15}; LightNode node{pos, 15};
nodesB.push(node); nodesB.push(node);
} }
@@ -794,7 +811,6 @@ void RebuildLighting(World &world, int startX, int startZ) {
} }
while (!nodesB.empty()) { while (!nodesB.empty()) {
std::cout << nodesB.size() << std::endl;
LightNode node = nodesB.front(); LightNode node = nodesB.front();
nodesB.pop(); nodesB.pop();
@@ -887,6 +903,55 @@ ChunkRenderData GenerateCRDTranslucent(Chunk chunk, World &world) {
new_chunk.sides[i2] = 0xFF; new_chunk.sides[i2] = 0xFF;
continue; continue;
} }
if(BLOCKS[fetch_block(chunk, _x, y, _z)].name == "water") {
continue;
}
int x = _x + chunk.x * CHUNK_SIZE;
int z = _z + chunk.z * CHUNK_SIZE;
bool l = (_x > 0) ? !TestMask(mask, i2-1) : !TestAirMaskWorld(world, x - 1, y, z);
bool r = (_x < CHUNK_SIZE-1) ? !TestMask(mask, i2+1) : !TestAirMaskWorld(world, x + 1, y, z);
bool u = (y==WORLD_HEIGHT-1) ? false : !TestMask(mask, i2+CHUNK_SIZE_SQR);
bool d = (y==0) ? true : !TestMask(mask, i2-CHUNK_SIZE_SQR);
bool b = (_z==0) ? !TestAirMaskWorld(world, x, y, z - 1) : !TestMask(mask, i2-CHUNK_SIZE);
bool f = (_z==CHUNK_SIZE-1) ? !TestAirMaskWorld(world, x, y, z + 1) : !TestMask(mask, i2+CHUNK_SIZE);
new_chunk.sides[i2] = pack6(
!l,
!r,
!u,
!d,
!b,
!f
);
}
}
return new_chunk;
}
//Generates a CRD for water (ChunkRenderData). Outputs the CRD.
ChunkRenderData GenerateCRDWater(Chunk chunk, World &world) {
struct ChunkRenderData new_chunk = { 0 };
uint16_t *mask0= chunk.opaqueMask;
uint16_t *mask = chunk.airMask;
for (int step = 0; step < CHUNK_DATA_SIZE/16; ++step)
{
uint16_t m = ~(mask[step]);
if(m == 0) continue;
while (m) {
int bit = __builtin_ctz(m);
m &= m - 1;
int i2 = (step<<4) + bit;
int _x = bit;
int y = step >> 4;
int _z = step & 0xF;
if (TestMask(mask0, i2)) {
new_chunk.sides[i2] = 0;
continue;
};
if(BLOCKS[fetch_block(chunk, _x, y, _z)].name != "water") {
continue;
}
int x = _x + chunk.x * CHUNK_SIZE; int x = _x + chunk.x * CHUNK_SIZE;
int z = _z + chunk.z * CHUNK_SIZE; int z = _z + chunk.z * CHUNK_SIZE;
bool l = (_x > 0) ? !TestMask(mask, i2-1) : !TestAirMaskWorld(world, x - 1, y, z); bool l = (_x > 0) ? !TestMask(mask, i2-1) : !TestAirMaskWorld(world, x - 1, y, z);
@@ -957,6 +1022,7 @@ void SaveWorld(World &world, const char* path) {
} }
void Debug_Write(const std::string &stuff); void Debug_Write(const std::string &stuff);
bool LoadWorld(World &world, const char* path) { bool LoadWorld(World &world, const char* path) {
std::ifstream data(path, std::ios::binary); std::ifstream data(path, std::ios::binary);
if (!data) return false; if (!data) return false;
@@ -986,19 +1052,22 @@ bool LoadWorld(World &world, const char* path) {
return false; return false;
} }
} }
Chunk *c = &world.chunks[i]; Chunk c = {0};
c.x = i % 16;
c.z = i >> 4;
int outIndex = 0; int outIndex = 0;
for (size_t p = 0; p + 1 < size; p += 2) { for (size_t p = 0; p + 1 < size; p += 2) {
uint8_t count = temp[p]; uint8_t count = temp[p];
uint8_t value = temp[p + 1]; uint8_t value = temp[p + 1];
for (uint8_t k = 0; k < count; ++k) { for (uint8_t k = 0; k < count; ++k) {
SetBlockChunkFast(c, outIndex++, value); SetBlockChunkFast(&c, outIndex++, value);
} }
} }
while (outIndex < CHUNK_DATA_SIZE) { while (outIndex < CHUNK_DATA_SIZE) {
SetBlockChunkFast(c, outIndex++, 0); SetBlockChunkFast(&c, outIndex++, 0);
} }
RebuildHeightmap(*c); RebuildHeightmap(c);
memcpy(&world.chunks[i], &c, sizeof(c));
} }
free(temp); free(temp);
return true; return true;
+11 -5
View File
@@ -11,7 +11,6 @@
#endif #endif
#include <functional> #include <functional>
#include "glfw_keycodes_to_string.h" #include "glfw_keycodes_to_string.h"
#include "../PerlinNoise.hpp"
#include "raylib.h" #include "raylib.h"
#include "raymath.h" #include "raymath.h"
#include <stdint.h> #include <stdint.h>
@@ -76,9 +75,9 @@
#define GAME_NAME "CubeGame" #define GAME_NAME "CubeGame"
#define GAME_VERSION_INT 0 #define GAME_VERSION_INT 0
#define DEFAULT_FONT_SIZE 16 #define DEFAULT_FONT_SIZE 16
#define TPS 30.0 #define TPS 30
#define TPS_DIV 1.0 / TPS #define TPS_DIV 1.0 / TPS
#define RENDER_DISTANCE 5 #define RENDER_DISTANCE 16
#define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE #define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE
#define MAX_HP 100 #define MAX_HP 100
#define PATH_APPEND "resources/" #define PATH_APPEND "resources/"
@@ -87,6 +86,8 @@
#define INVENTORY_WIDTH 8 #define INVENTORY_WIDTH 8
#define INVENTORY_HEIGHT 6 #define INVENTORY_HEIGHT 6
#define INVENTORY_SIZE INVENTORY_WIDTH*INVENTORY_HEIGHT #define INVENTORY_SIZE INVENTORY_WIDTH*INVENTORY_HEIGHT
#define WORLD_TIME_SECONDS (24*60)
#define WORLD_TIME_TICKS WORLD_TIME_SECONDS*TPS
enum BlockType { enum BlockType {
B_Wood, B_Wood,
B_Stone, B_Stone,
@@ -311,7 +312,9 @@ int GetSkyLight(World&world,int x,int y,int z);
int GetRLight(World&world,int x,int y,int z); int GetRLight(World&world,int x,int y,int z);
int GetGLight(World&world,int x,int y,int z); int GetGLight(World&world,int x,int y,int z);
int GetBLight(World&world,int x,int y,int z); int GetBLight(World&world,int x,int y,int z);
Color GetSunlightColor();
Color GetLight(World&world,int x,int y,int z); Color GetLight(World&world,int x,int y,int z);
Color GetLightMesher(World&world,int x,int y,int z);
bool CanTick(int blockType); bool CanTick(int blockType);
bool GetCloud(int x,int z); bool GetCloud(int x,int z);
bool IsTranslucent(int blockType); bool IsTranslucent(int blockType);
@@ -333,6 +336,7 @@ void RebuildLighting(World&world,int startX,int startZ);
#if !defined(SERVER) #if !defined(SERVER)
ChunkRenderData GenerateCRDOpaque(Chunk&chunk,World&world); ChunkRenderData GenerateCRDOpaque(Chunk&chunk,World&world);
ChunkRenderData GenerateCRDTranslucent(Chunk chunk,World&world); ChunkRenderData GenerateCRDTranslucent(Chunk chunk,World&world);
ChunkRenderData GenerateCRDWater(Chunk chunk,World&world);
#endif #endif
void SaveWorld(World&world,const char *path); void SaveWorld(World&world,const char *path);
bool LoadWorld(World&world,const char *path); bool LoadWorld(World&world,const char *path);
@@ -444,10 +448,12 @@ const char *Pathify(const char *src);
const char *PathifyUser(const char *src); const char *PathifyUser(const char *src);
#if !defined(SERVER) #if !defined(SERVER)
void DrawCubeTexture(Texture2D texture,Vector3 position,float width,float height,float length,Color color,int offsetX,int offsetY,int sizeX,int sizeY); void DrawCubeTexture(Texture2D texture,Vector3 position,float width,float height,float length,Color color,int offsetX,int offsetY,int sizeX,int sizeY);
void DrawCubeBlock(Texture2D texture,Vector3 position,float width,float height,float length,BlockDef def); void DrawCubeBlock(Texture2D texture,Vector3 position,float width,float height,float length,BlockDef def,Color tint);
void DrawTextCodepoint3D(Font font,int codepoint,Vector3 position,float fontSize,bool backface,Color tint); void DrawTextCodepoint3D(Font font,int codepoint,Vector3 position,float fontSize,bool backface,Color tint);
void DrawText3D(Font font,const char *text,Vector3 position,float fontSize,float fontSpacing,float lineSpacing,bool backface,Color tint); void DrawText3D(Font font,const char *text,Vector3 position,float fontSize,float fontSpacing,float lineSpacing,bool backface,Color tint);
#endif #endif
RenderTexture2D LoadRenderTextureDepthTex(int width,int height);
void UnloadRenderTextureDepthTex(RenderTexture2D target);
inline uint8_t pack6(bool b0,bool b1,bool b2,bool b3,bool b4,bool b5){ inline uint8_t pack6(bool b0,bool b1,bool b2,bool b3,bool b4,bool b5){
return (uint8_t)( return (uint8_t)(
((uint8_t)(b0 ? 1 : 0) << 0) | ((uint8_t)(b0 ? 1 : 0) << 0) |
@@ -619,7 +625,7 @@ void HotbarAddItemLots(Item *registry,int damage,int amount);
void InitHotbar(); void InitHotbar();
void DrawHotbar(); void DrawHotbar();
InventoryItem HotbarGetSelected(); InventoryItem HotbarGetSelected();
void DrawSelectedItem(); void DrawSelectedItem(Color tint);
void CloseInventory(); void CloseInventory();
void UpdateHotbar(); void UpdateHotbar();
void LocaleUpdate(); void LocaleUpdate();
+1 -1
View File
@@ -363,7 +363,7 @@ void DrawEntities(float dt) {
DrawCube(pos_lerped, 1, 1, 1, RED); DrawCube(pos_lerped, 1, 1, 1, RED);
} }
if(ent.type == 4) { if(ent.type == 4) {
DrawCubeBlock(terrain, pos_lerped, 1,1,1, GetBlockDefinition(ent.data[1])); DrawCubeBlock(terrain, pos_lerped, 1,1,1, GetBlockDefinition(ent.data[1]), WHITE);
} }
} }
} }
+4 -4
View File
@@ -63,7 +63,7 @@ Vector2 InputGetWalkAxis() {
float y = 0; float y = 0;
if(isJoystick) { if(isJoystick) {
x = GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X); x = GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X);
y = GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y); y = -GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y);
if(abs(x) < 0.5f) { if(abs(x) < 0.5f) {
x = 0; x = 0;
} }
@@ -84,8 +84,8 @@ Vector2 InputGetLookAxis() {
float x = 0; float x = 0;
float y = 0; float y = 0;
if(isJoystick) { if(isJoystick) {
x = GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X); x = GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X)*3.0f;
y = GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y); y = GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y)*3.0f;
if(abs(x) < 0.1f) { if(abs(x) < 0.1f) {
x = 0; x = 0;
} }
@@ -108,6 +108,7 @@ Vector2 InputGetDPAD() {
if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) { x = 1; } if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) { x = 1; }
if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) { x = -1; } if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) { x = -1; }
} }
return {x, y}; return {x, y};
} }
void InputWriteControls() { void InputWriteControls() {
@@ -136,7 +137,6 @@ void InputInit() {
controls[key] = val; controls[key] = val;
} }
swap_mouse = config["Swap mouse buttons"].as<bool>(); swap_mouse = config["Swap mouse buttons"].as<bool>();
} }
} }
+4 -4
View File
@@ -441,7 +441,7 @@ void DrawHotbar() {
InventoryItem HotbarGetSelected() { InventoryItem HotbarGetSelected() {
return hotbar[selected]; return hotbar[selected];
} }
void DrawSelectedItem() { void DrawSelectedItem(Color tint) {
InventoryItem item = hotbar[selected]; InventoryItem item = hotbar[selected];
Vector3 center = {-0.75f, -0.45f, 0.5f}; Vector3 center = {-0.75f, -0.45f, 0.5f};
rlPushMatrix(); rlPushMatrix();
@@ -458,16 +458,16 @@ void DrawSelectedItem() {
rlRotatef(-45, 1, 0, 0); rlRotatef(-45, 1, 0, 0);
rlRotatef(25, 0, 0, 1); rlRotatef(25, 0, 0, 1);
DrawCubeTexture(playerTex, {0, -12*PIXUNIT/2, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4); DrawCubeTexture(playerTex, {0, -12*PIXUNIT/2, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, tint, 44,20,4,4);
if(item.item != nullptr) { if(item.item != nullptr) {
if(item.item->type == IType_Block) { if(item.item->type == IType_Block) {
DrawCubeBlock(terrain, {0, -12*PIXUNIT - 0.25f, 0}, 0.5f, 0.5f, 0.5f, GetBlockDefinition(item.damage)); DrawCubeBlock(terrain, {0, -12*PIXUNIT - 0.25f, 0}, 0.5f, 0.5f, 0.5f, GetBlockDefinition(item.damage), tint);
} }
else { else {
UVCorners left = GetUVTex(item.item->texture); UVCorners left = GetUVTex(item.item->texture);
rlSetTexture(item_atlas.id); rlSetTexture(item_atlas.id);
rlBegin(RL_QUADS); rlBegin(RL_QUADS);
rlColor4ub(255, 255, 255, 255); rlColor4ub(tint.r, tint.g, tint.b, 255);
rlNormal3f(1.0f, 0.0f, 0.0f); rlNormal3f(1.0f, 0.0f, 0.0f);
const float size = 0.5f; const float size = 0.5f;
rlTexCoord2f(left.corner0.x, left.corner0.y); rlVertex3f(0, -12*PIXUNIT - size, 0.25f - size); rlTexCoord2f(left.corner0.x, left.corner0.y); rlVertex3f(0, -12*PIXUNIT - size, 0.25f - size);
+6 -6
View File
@@ -72,7 +72,7 @@ MeshData GenerateChunkMesh(World &world, ChunkRenderData chunkRenderData, Chunk
positions.push_back(verts[3]); positions.push_back(verts[3]);
normals.push_back(normal); normals.push_back(normal);
Color clr = GetLight(world, wx-1, wy, wz); Color clr = GetLightMesher(world, wx-1, wy, wz);
colors.push_back(clr); colors.push_back(clr);
uvs.push_back(corners[0]); uvs.push_back(corners[0]);
@@ -112,7 +112,7 @@ MeshData GenerateChunkMesh(World &world, ChunkRenderData chunkRenderData, Chunk
positions.push_back(verts[3]); positions.push_back(verts[3]);
normals.push_back(normal); normals.push_back(normal);
Color clr = GetLight(world, wx+1, wy, wz); Color clr = GetLightMesher(world, wx+1, wy, wz);
colors.push_back(clr); colors.push_back(clr);
uvs.push_back(corners[0]); uvs.push_back(corners[0]);
@@ -152,7 +152,7 @@ MeshData GenerateChunkMesh(World &world, ChunkRenderData chunkRenderData, Chunk
positions.push_back(verts[3]); positions.push_back(verts[3]);
normals.push_back(normal); normals.push_back(normal);
Color clr = GetLight(world, wx, wy-1, wz); Color clr = GetLightMesher(world, wx, wy-1, wz);
colors.push_back(clr); colors.push_back(clr);
uvs.push_back(corners[0]); uvs.push_back(corners[0]);
@@ -192,7 +192,7 @@ MeshData GenerateChunkMesh(World &world, ChunkRenderData chunkRenderData, Chunk
positions.push_back(verts[3]); positions.push_back(verts[3]);
normals.push_back(normal); normals.push_back(normal);
Color clr = GetLight(world, wx, wy+1, wz); Color clr = GetLightMesher(world, wx, wy+1, wz);
colors.push_back(clr); colors.push_back(clr);
uvs.push_back(corners[0]); uvs.push_back(corners[0]);
@@ -232,7 +232,7 @@ MeshData GenerateChunkMesh(World &world, ChunkRenderData chunkRenderData, Chunk
positions.push_back(verts[3]); positions.push_back(verts[3]);
normals.push_back(normal); normals.push_back(normal);
Color clr = GetLight(world, wx, wy, wz+1); Color clr = GetLightMesher(world, wx, wy, wz+1);
colors.push_back(clr); colors.push_back(clr);
uvs.push_back(corners[0]); uvs.push_back(corners[0]);
@@ -272,7 +272,7 @@ MeshData GenerateChunkMesh(World &world, ChunkRenderData chunkRenderData, Chunk
positions.push_back(verts[3]); positions.push_back(verts[3]);
normals.push_back(normal); normals.push_back(normal);
Color clr = GetLight(world, wx, wy, wz-1); Color clr = GetLightMesher(world, wx, wy, wz-1);
colors.push_back(clr); colors.push_back(clr);
uvs.push_back(corners[0]); uvs.push_back(corners[0]);
+55 -2
View File
@@ -87,7 +87,7 @@ void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float hei
rlSetTexture(0); rlSetTexture(0);
} }
void DrawCubeBlock(Texture2D texture, Vector3 position, float width, float height, float length, BlockDef def) void DrawCubeBlock(Texture2D texture, Vector3 position, float width, float height, float length, BlockDef def, Color tint)
{ {
float x = position.x; float x = position.x;
float y = position.y; float y = position.y;
@@ -104,7 +104,7 @@ void DrawCubeBlock(Texture2D texture, Vector3 position, float width, float heigh
UVCorners right = GetUVTex(def.textureSide); UVCorners right = GetUVTex(def.textureSide);
rlSetTexture(texture.id); rlSetTexture(texture.id);
rlBegin(RL_QUADS); rlBegin(RL_QUADS);
rlColor4ub(255, 255, 255, 255); rlColor4ub(tint.r, tint.g, tint.b, 255);
// Front Face // Front Face
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
rlTexCoord2f(front.corner0.x, front.corner0.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(front.corner0.x, front.corner0.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
@@ -254,3 +254,56 @@ void DrawText3D(Font font, const char *text, Vector3 position, float fontSize, f
} }
} }
#endif #endif
RenderTexture2D LoadRenderTextureDepthTex(int width, int height)
{
RenderTexture2D target = { 0 };
target.id = rlLoadFramebuffer(); // Load an empty framebuffer
if (target.id > 0)
{
rlEnableFramebuffer(target.id);
// Create color texture (default to RGBA)
target.texture.id = rlLoadTexture(0, width, height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
target.texture.width = width;
target.texture.height = height;
target.texture.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
target.texture.mipmaps = 1;
// Create depth texture buffer (instead of raylib default renderbuffer)
target.depth.id = rlLoadTextureDepth(width, height, false);
target.depth.width = width;
target.depth.height = height;
target.depth.format = 19; // DEPTH_COMPONENT_24BIT: Not defined in raylib
target.depth.mipmaps = 1;
// Attach color texture and depth texture to FBO
rlFramebufferAttach(target.id, target.texture.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0);
rlFramebufferAttach(target.id, target.depth.id, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_TEXTURE2D, 0);
// Check if fbo is complete with attachments (valid)
if (rlFramebufferComplete(target.id)) TRACELOG(LOG_INFO, "FBO: [ID %i] Framebuffer object created successfully", target.id);
rlDisableFramebuffer();
}
else TRACELOG(LOG_WARNING, "FBO: Framebuffer object can not be created");
return target;
}
// Unload render texture from GPU memory (VRAM)
void UnloadRenderTextureDepthTex(RenderTexture2D target)
{
if (target.id > 0)
{
// Color texture attached to FBO is deleted
rlUnloadTexture(target.texture.id);
rlUnloadTexture(target.depth.id);
// NOTE: Depth texture is automatically
// queried and deleted before deleting framebuffer
rlUnloadFramebuffer(target.id);
}
}
+4 -3
View File
@@ -5,7 +5,6 @@
#undef Escape #undef Escape
#endif #endif
#include "glfw_keycodes_to_string.h" #include "glfw_keycodes_to_string.h"
#include "../PerlinNoise.hpp"
#ifdef WIN32 #ifdef WIN32
#include "external/fix_win32_compatibility.h" #include "external/fix_win32_compatibility.h"
@@ -99,10 +98,10 @@
#define GAME_VERSION_INT 0 #define GAME_VERSION_INT 0
#define DEFAULT_FONT_SIZE 16 #define DEFAULT_FONT_SIZE 16
#define TPS 30.0 #define TPS 30
#define TPS_DIV 1.0 / TPS #define TPS_DIV 1.0 / TPS
//Rendering //Rendering
#define RENDER_DISTANCE 5 #define RENDER_DISTANCE 16
#define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE #define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE
//Game stuff //Game stuff
@@ -115,6 +114,8 @@
#define INVENTORY_HEIGHT 6 #define INVENTORY_HEIGHT 6
#define INVENTORY_SIZE INVENTORY_WIDTH*INVENTORY_HEIGHT #define INVENTORY_SIZE INVENTORY_WIDTH*INVENTORY_HEIGHT
#define WORLD_TIME_SECONDS (24*60)
#define WORLD_TIME_TICKS WORLD_TIME_SECONDS*TPS
enum BlockType { enum BlockType {
B_Wood, B_Wood,
B_Stone, B_Stone,
+181 -39
View File
@@ -15,6 +15,7 @@
#include <list> #include <list>
#include <climits> #include <climits>
#include <queue> #include <queue>
#include <map>
#define MAX_RAY_DISTANCE 8.0f #define MAX_RAY_DISTANCE 8.0f
struct MessageData { struct MessageData {
std::string message; std::string message;
@@ -57,15 +58,21 @@ static Sound wood_place;
static Sound stone_place; static Sound stone_place;
static Sound dirt_place; static Sound dirt_place;
static Sound grass_place; static Sound grass_place;
bool tick_entities; static Texture2D sun;
static Texture2D moon;
static Texture2D stars;
bool tick_entities = true;
const std::string LocaleGet(std::string loc); const std::string LocaleGet(std::string loc);
bool InputGetKeyDown(const std::string name); bool InputGetKeyDown(const std::string name);
bool InputGetKeyPressed(const std::string name); bool InputGetKeyPressed(const std::string name);
extern std::list<Entity> entities; extern std::list<Entity> entities;
std::bitset<WORLD_SIZE_BLOCKS*WORLD_SIZE_BLOCKS/8/8> clouds; std::bitset<WORLD_SIZE_BLOCKS*WORLD_SIZE_BLOCKS/8/8> clouds;
std::queue<Vector3I> tickedBlocks; std::queue<Vector3I> tickedBlocks;
struct MeshUnit { struct MeshUnit {
Model model; Model model;
Model modelTransparent;
Model modelWater;
int vertices; int vertices;
}; };
struct ProfilerPart { struct ProfilerPart {
@@ -91,8 +98,17 @@ static Vector3 CameraForwardFromYawPitch(float yaw, float pitch)
} }
World world; World world;
static MeshUnit rendering[MAX_WORLD_AREA]; static MeshUnit rendering[MAX_WORLD_AREA];
static MeshUnit renderingT[MAX_WORLD_AREA];
std::map<std::string, Shader> loadedShaders;
static void LoadNewShader(std::string name) {
Shader temp = LoadShader(
TextFormat("%s/shaders/%s.vs", PATH_APPEND, name.c_str()),
TextFormat("%s/shaders/%s.fs", PATH_APPEND, name.c_str())
);
temp.locs[SHADER_LOC_MATRIX_MODEL] = GetShaderLocation(temp, "matModel");
temp.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(temp, "viewPos");
loadedShaders[name] = temp;
}
GameState state = GAME_STATE_MAINMENU; GameState state = GAME_STATE_MAINMENU;
bool loaderParam_remeshOnly = false; bool loaderParam_remeshOnly = false;
int worldCreationProgress = 0; int worldCreationProgress = 0;
@@ -274,37 +290,37 @@ void Debug_EndMeasureLoops(const std::string &stuff, int loops);
static void RemeshChunk(int x, int y) { static void RemeshChunk(int x, int y) {
int idx = GetIndexWorld(x, y); int idx = GetIndexWorld(x, y);
if(loadedChunks[idx]) { if(loadedChunks[idx]) {
UnloadModel(renderingT[idx].model);
UnloadModel(rendering[idx].model); UnloadModel(rendering[idx].model);
UnloadModel(rendering[idx].modelTransparent);
UnloadModel(rendering[idx].modelWater);
} }
Chunk &chunk = world.chunks[idx]; Chunk &chunk = world.chunks[idx];
RebuildOpaqueMask(chunk); RebuildOpaqueMask(chunk);
/*for (int i = 0; i < 4; i++)
{
Vector3I dir = dirs2d[i];
if(!CheckOOBWorldChunk(x+dir.x, y+dir.z)) {
RebuildLighting(world, world.chunks[GetIndexWorld(x+dir.x, y+dir.z)]);
}
}*/
RebuildLighting(world, chunk.x, chunk.z); RebuildLighting(world, chunk.x, chunk.z);
MeshData renderDataOpq = GenerateChunkMesh(world, GenerateCRDOpaque(chunk, world), chunk, x, y, 0xFF); MeshData renderDataOpq = GenerateChunkMesh(world, GenerateCRDOpaque(chunk, world), chunk, x, y, 0xFF);
MeshData renderDataTsl = GenerateChunkMesh(world, GenerateCRDTranslucent(chunk, world), chunk, x, y, 0xFF); Model model0 = LoadModelFromMesh(GenChunkMesh(renderDataOpq));
model0.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = terrain;
Model model = LoadModelFromMesh(GenChunkMesh(renderDataOpq)); model0.materials[0].shader = loadedShaders["terrain"];
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = terrain;
MeshUnit munit0; MeshUnit munit0;
munit0.model = model; munit0.model = model0;
munit0.vertices += renderDataOpq.vertexCount; munit0.vertices += renderDataOpq.vertexCount;
rendering[idx] = munit0;
model = LoadModelFromMesh(GenChunkMesh(renderDataTsl));
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = terrain;
MeshUnit munit1;
munit1.model = model;
munit1.vertices += renderDataTsl.vertexCount;
renderingT[idx] = munit1;
loadedChunks[idx] = true;
MeshData renderDataTsl = GenerateChunkMesh(world, GenerateCRDTranslucent(chunk, world), chunk, x, y, 0xFF);
Model model1 = LoadModelFromMesh(GenChunkMesh(renderDataTsl));
model1.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = terrain;
model1.materials[0].shader = loadedShaders["terrain"];
munit0.modelTransparent = model1;
MeshData renderDataWtr = GenerateChunkMesh(world, GenerateCRDWater(chunk, world), chunk, x, y, 0xFF);
Model model2 = LoadModelFromMesh(GenChunkMesh(renderDataWtr));
model2.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = terrain;
model2.materials[0].shader = loadedShaders["water"];
munit0.modelWater = model2;
loadedChunks[idx] = true;
rendering[idx] = munit0;
} }
static bool RaycastBlock(Vector3 origin, Vector3 dir, float maxDist, Vector3 *outBlock, Vector3 *outPrev) static bool RaycastBlock(Vector3 origin, Vector3 dir, float maxDist, Vector3 *outBlock, Vector3 *outPrev)
@@ -549,6 +565,54 @@ void TakeDamage(float amount) {
int currentlyTickedChunk = 0; int currentlyTickedChunk = 0;
Vector3 highlightBlock = {-1, -1, -1}; Vector3 highlightBlock = {-1, -1, -1};
float GetDayProgression() {
return (float)(worldTime % (unsigned long long)(WORLD_TIME_TICKS)) / (float)(WORLD_TIME_TICKS);
}
Color GetSkyColor() {
float progression = GetDayProgression();
Color night = ColorBrightness(BLUE, -0.9f);
Color sunrise = ColorBrightness(ORANGE, -0.25f);
Color noon = BLUE;
if(progression > 0.5f) {
progression = 1 - progression;
}
if(progression < 0.20f) {
return night;
}
if(progression>=0.20f&&progression<0.30f) {
return ColorLerp(night, sunrise, (progression - 0.2f) / 0.1f);
}
if(progression>=0.30f&&progression<0.35f) {
return ColorLerp(sunrise, noon, (progression - 0.3f) / 0.05f);
}
return noon;
}
Color GetSunlightColor() {
float progression = GetDayProgression();
Color night = ColorBrightness(BLUE, -0.9f);
Color sunrise = ColorBrightness(ORANGE, -0.25f);
Color noon = WHITE;
if(progression > 0.5f) {
progression = 1 - progression;
}
if(progression < 0.20f) {
return night;
}
if(progression>=0.20f&&progression<0.30f) {
return ColorLerp(night, sunrise, (progression - 0.2f) / 0.1f);
}
if(progression>=0.30f&&progression<0.35f) {
return ColorLerp(sunrise, noon, (progression - 0.3f) / 0.05f);
}
return noon;
}
static Vector3 GetSunDirection() {
float time = GetDayProgression() - 0.25f;
return Vector3Normalize({-sinf(time*PI*2), -sinf(time*PI*2)/2.0f, -cosf(time*PI*2)});
}
static void GameUpdate(Camera camera, float &time) { static void GameUpdate(Camera camera, float &time) {
if (player_position.y < 0 || if (player_position.y < 0 ||
player_position.x < 0 || player_position.x < 0 ||
@@ -691,6 +755,9 @@ static void GameUpdate(Camera camera, float &time) {
if(IsKeyPressed(KEY_F10)) { if(IsKeyPressed(KEY_F10)) {
tick_entities = !tick_entities; tick_entities = !tick_entities;
} }
if(IsKeyDown(KEY_F11)) {
worldTime+=8;
}
if(IsKeyPressed(KEY_B) && !online) { if(IsKeyPressed(KEY_B) && !online) {
Entity temp = NewEntity(); Entity temp = NewEntity();
temp.type = 3; temp.type = 3;
@@ -888,12 +955,13 @@ static void GameUpdate(Camera camera, float &time) {
PROFCOUNT = GetTime(); PROFCOUNT = GetTime();
if(tick_entities) { if(tick_entities) {
entUpdateCounter += dt; entUpdateCounter += dt / 2.0f;
if(entUpdateCounter > TPS_DIV) { if(entUpdateCounter > TPS_DIV) {
while (entUpdateCounter > 0) while (entUpdateCounter > 0)
{ {
UpdateEntities(world, TPS_DIV / 2.0f); UpdateEntities(world, TPS_DIV / 2.0f);
entUpdateCounter-= TPS_DIV; entUpdateCounter-= TPS_DIV;
worldTime++;
} }
TickAvailableBlocks(); TickAvailableBlocks();
entUpdateCounter = 0.0f; entUpdateCounter = 0.0f;
@@ -917,12 +985,56 @@ static void GameUpdate(Camera camera, float &time) {
UpdateCamera(&camera, CAMERA_CUSTOM); UpdateCamera(&camera, CAMERA_CUSTOM);
unsigned int debug_verts_opaque = 0; unsigned int debug_verts_opaque = 0;
unsigned int debug_verts_transparent = 0;
UpdateHotbar(); UpdateHotbar();
Frustum frustum = ExtractFrustumPlanes(camera, (float)GetScreenWidth() / (float)GetScreenHeight()); Frustum frustum = ExtractFrustumPlanes(camera, (float)GetScreenWidth() / (float)GetScreenHeight());
BeginDrawing(); BeginDrawing();
ClearBackground(RAYWHITE); UpdateCamera(&camera, CAMERA_CUSTOM);
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLUE);
ClearBackground(GetSkyColor());
BeginMode3D(camera);
float time = GetDayProgression() - 0.25f;
Vector3 sunOffset = Vector3Negate(GetSunDirection());
Vector3 _forward = Vector3Subtract(camera.target, camera.position);
Vector3 up = { 0.0f, 1.0f, 0.0f };
Vector3 _right = Vector3CrossProduct(up, _forward);
up = Vector3CrossProduct(_forward, _right);
up = Vector3Normalize(up);
SetRandomSeed(1337);
time += 0.25f;
if(time > 0.5f) {
time = 1-time;
}
float starAlpha = 0.0f;
if(time > 0.2f && time <= 0.3f) {
starAlpha = 1-(time - 0.2f) / 0.1f;
}
if(time <= 0.2f) {
starAlpha = 1;
}
rlSetBlendMode(BLEND_ADDITIVE);
DrawBillboardPro(camera, sun, {0, 0, 64, 64}, player_position+sunOffset*1000, up, {150, 150}, {0.5f, 0.5f}, 0, WHITE);
DrawBillboardPro(camera, moon, {0, 0, 64, 64}, player_position-sunOffset*1000, up, {150, 150}, {0.5f, 0.5f}, 0, WHITE);
for (int i = 0; i < 120; i++)
{
float u = GetRandomValue(0, 100) / 100.0f;
float v = GetRandomValue(0, 100) / 100.0f;
double theta = 2.0 * M_PI * u;
double z = v;
double r = std::sqrt(1.0 - z*z);
Vector3 starOffset = {
r * std::cos(theta),
z,
r * std::sin(theta)
};
Vector3 tgt = starOffset*1000;
float alphaModMoon = fmax(0, fmin(1, Vector3Distance(starOffset, (Vector3Negate(sunOffset)))/0.25f-1));
float alphaModSun = fmax(0, fmin(1, Vector3Distance(starOffset, sunOffset)/0.25f-0.25f));
DrawBillboardPro(camera, stars, {(float)GetRandomValue(0, stars.width/8)*8, 0, 8, 8}, player_position+tgt, up, {10, 10}, {0.5f, 0.5f}, GetRandomValue(0, 360), ColorAlpha(WHITE, starAlpha*alphaModMoon*alphaModSun));
}
rlSetBlendMode(BLEND_ALPHA);
EndMode3D();
BeginMode3D(camera); BeginMode3D(camera);
@@ -1017,8 +1129,8 @@ static void GameUpdate(Camera camera, float &time) {
for (auto &p : distances) { for (auto &p : distances) {
int idx = p.second; int idx = p.second;
DrawModel(renderingT[idx].model, {0, 0, 0}, 1.0f, WHITE); DrawModel(rendering[idx].modelTransparent, {0, 0, 0}, 1.0f, WHITE);
debug_verts_transparent += renderingT[idx].vertices; DrawModel(rendering[idx].modelWater, {0, 0, 0}, 1.0f, WHITE);
} }
AddProfilerPart("chunk render tsl", GetTime()-PROFCOUNT, RED); AddProfilerPart("chunk render tsl", GetTime()-PROFCOUNT, RED);
if (highlightValid) if (highlightValid)
@@ -1037,7 +1149,7 @@ static void GameUpdate(Camera camera, float &time) {
BeginMode3D(camera); BeginMode3D(camera);
rlDisableDepthMask(); rlDisableDepthMask();
rlDisableDepthTest(); rlDisableDepthTest();
DrawSelectedItem(); DrawSelectedItem(GetLight(world, (int)player_position.x, (int)player_position.y, (int)player_position.z));
rlEnableDepthTest(); rlEnableDepthTest();
rlEnableDepthMask(); rlEnableDepthMask();
EndMode3D(); EndMode3D();
@@ -1076,6 +1188,13 @@ static void GameUpdate(Camera camera, float &time) {
GetBLight(world, ppos.x, ppos.y, ppos.z) GetBLight(world, ppos.x, ppos.y, ppos.z)
); );
DrawTextB(text, 20, 100, DEFAULT_FONT_SIZE, WHITE); DrawTextB(text, 20, 100, DEFAULT_FONT_SIZE, WHITE);
sprintf(text, "world time %dt (%.1fs)", worldTime, worldTime * TPS_DIV);
DrawTextB(text, 20, 120, DEFAULT_FONT_SIZE, WHITE);
float progress = GetDayProgression();
int hours = progress*24;
int minutes = (int)(progress*24*60)%60;
sprintf(text, "%02d:%02d", hours, minutes);
DrawTextB(text, 20, 140, DEFAULT_FONT_SIZE, WHITE);
DrawRectangle(GetScreenWidth()/2-3, GetScreenHeight()/2-3, 6, 6, BLACK); DrawRectangle(GetScreenWidth()/2-3, GetScreenHeight()/2-3, 6, 6, BLACK);
DrawRectangle(GetScreenWidth()/2-2, GetScreenHeight()/2-2, 4, 4, WHITE); DrawRectangle(GetScreenWidth()/2-2, GetScreenHeight()/2-2, 4, 4, WHITE);
@@ -1176,6 +1295,7 @@ static void GameUpdate(Camera camera, float &time) {
} }
} }
static void GameStart() { static void GameStart() {
const int cloudMapSize = MAX_WORLD_SIZE*CHUNK_SIZE/8; const int cloudMapSize = MAX_WORLD_SIZE*CHUNK_SIZE/8;
for (int x = 0; x < cloudMapSize; x++) for (int x = 0; x < cloudMapSize; x++)
{ {
@@ -1191,6 +1311,8 @@ static void GameStart() {
SendPacketR(peer, data, 1); // Tell the server to fetch all players SendPacketR(peer, data, 1); // Tell the server to fetch all players
} }
worldTime = (int)(WORLD_TIME_TICKS * 0.3f);
camera = { 0 }; camera = { 0 };
camera.position = (Vector3){ MAX_WORLD_SIZE / 2 * CHUNK_SIZE, 12.0f, MAX_WORLD_SIZE / 2 * CHUNK_SIZE}; camera.position = (Vector3){ MAX_WORLD_SIZE / 2 * CHUNK_SIZE, 12.0f, MAX_WORLD_SIZE / 2 * CHUNK_SIZE};
camera.target = (Vector3){camera.position.x, camera.position.y, camera.position.z + 1}; camera.target = (Vector3){camera.position.x, camera.position.y, camera.position.z + 1};
@@ -1408,14 +1530,6 @@ void GameModeCleanupFull() {
enet_host_destroy(client); enet_host_destroy(client);
online = false; online = false;
} }
for (int idx = 0; idx < MAX_WORLD_AREA; idx++)
{
if(loadedChunks[idx]) {
//UnloadModel(renderingT[idx]);
//UnloadModel(rendering[idx]);
}
}
memset(loadedChunks, 0, sizeof(loadedChunks)); memset(loadedChunks, 0, sizeof(loadedChunks));
memset(dirtyChunks, 0, sizeof(dirtyChunks)); memset(dirtyChunks, 0, sizeof(dirtyChunks));
entities.clear(); entities.clear();
@@ -1439,6 +1553,13 @@ int main(void)
SetTraceLogLevel(LOG_WARNING); SetTraceLogLevel(LOG_WARNING);
SetConfigFlags(FLAG_WINDOW_RESIZABLE); SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(WIDTH, HEIGHT, GAME_NAME); InitWindow(WIDTH, HEIGHT, GAME_NAME);
if(!DirectoryExists(PathifyUser(""))) {
MakeDirectory(PathifyUser(""));
}
if(!DirectoryExists(PathifyUser("worlds"))) {
MakeDirectory(PathifyUser("worlds"));
}
InitWorldgen(0); InitWorldgen(0);
InitAudioDevice(); InitAudioDevice();
InitMenu(); InitMenu();
@@ -1456,6 +1577,9 @@ int main(void)
fnt = LoadFontEx(Pathify("font.ttf"), 32, NULL, 1024*8); fnt = LoadFontEx(Pathify("font.ttf"), 32, NULL, 1024*8);
terrain = LoadTexture(Pathify("terrain.png")); terrain = LoadTexture(Pathify("terrain.png"));
sun = LoadTexture(Pathify("sun.png"));
moon = LoadTexture(Pathify("moon.png"));
stars = LoadTexture(Pathify("stars.png"));
GenTextureMipmaps(&terrain); GenTextureMipmaps(&terrain);
Image temp = GenImageColor(1, 1, WHITE); Image temp = GenImageColor(1, 1, WHITE);
white_pixel = LoadTextureFromImage(temp); white_pixel = LoadTextureFromImage(temp);
@@ -1471,14 +1595,32 @@ int main(void)
ImageCrop(&copied, src0); ImageCrop(&copied, src0);
water = LoadTextureFromImage(copied); water = LoadTextureFromImage(copied);
SetTextureWrap(terrain, TEXTURE_WRAP_REPEAT);
SetTextureWrap(water, TEXTURE_WRAP_REPEAT); SetTextureWrap(water, TEXTURE_WRAP_REPEAT);
SetTargetFPS(-1); SetTargetFPS(-1);
float time; float time;
LoadNewShader("terrain");
LoadNewShader("water");
SetExitKey(KEY_NULL); SetExitKey(KEY_NULL);
while (!WindowShouldClose()) while (!WindowShouldClose())
{ {
for (const auto& [key, shader] : loadedShaders) {
Vector4 sunlight = ColorNormalize(GetSunlightColor());
SetShaderValue(shader, GetShaderLocation(shader, "sunlightColor"), &sunlight, SHADER_UNIFORM_VEC4);
Vector4 skyColor = ColorNormalize(GetSkyColor());
SetShaderValue(shader, GetShaderLocation(shader, "skyColor"), &skyColor, SHADER_UNIFORM_VEC4);
Vector3 sunlightDir = Vector3Negate(GetSunDirection());
SetShaderValue(shader, GetShaderLocation(shader, "lightDir"), &sunlightDir, SHADER_UNIFORM_VEC3);
float time = (float)GetTime();
SetShaderValue(shader, GetShaderLocation(shader, "time"), &time, SHADER_UNIFORM_FLOAT);
}
NetworkUpdate(); NetworkUpdate();
InputUpdate(); InputUpdate();