diff --git a/classes/class_environment.rst b/classes/class_environment.rst index a699132a9..f8f3de312 100644 --- a/classes/class_environment.rst +++ b/classes/class_environment.rst @@ -261,8 +261,6 @@ Description Resource for environment nodes (like :ref:`WorldEnvironment`) that define multiple environment operations (such as background :ref:`Sky` or :ref:`Color`, ambient light, fog, depth-of-field...). These parameters affect the final render of the scene. The order of these operations is: - - - DOF Blur - Motion Blur diff --git a/classes/class_styleboxflat.rst b/classes/class_styleboxflat.rst index 100998313..b316a9f13 100644 --- a/classes/class_styleboxflat.rst +++ b/classes/class_styleboxflat.rst @@ -85,17 +85,15 @@ Description This stylebox can be used to achieve all kinds of looks without the need of a texture. Those properties are customizable: - - Color +- Color - - Border width (individual width for each border) +- Border width (individual width for each border) - - Rounded corners (individual radius for each corner) +- Rounded corners (individual radius for each corner) - - Shadow +- Shadow - About corner radius: - - Setting corner radius to high values is allowed. As soon as corners would overlap the stylebox will switch to a relative system. Example: +Setting corner radius to high values is allowed. As soon as corners would overlap the stylebox will switch to a relative system. Example: :: @@ -235,7 +233,7 @@ This sets the amount of vertices used for each corner. Higher values result in r For corner radius smaller than 10: 4-5 should be enough -For corner radius smaller than 30: 8-12 should be enough ... +For corner radius smaller than 30: 8-12 should be enough .. _class_StyleBoxFlat_corner_radius_bottom_left: diff --git a/classes/class_visualscriptcustomnode.rst b/classes/class_visualscriptcustomnode.rst index 8fbaa9877..bf465b6e4 100644 --- a/classes/class_visualscriptcustomnode.rst +++ b/classes/class_visualscriptcustomnode.rst @@ -171,8 +171,7 @@ Return whether the custom node has an input **sequence** port. Execute the custom node's logic, returning the index of the output sequence port to use or a :ref:`String` when there is an error. - - The ``inputs`` array contains the values of the input ports. +The ``inputs`` array contains the values of the input ports. ``outputs`` is an array whose indices should be set to the respective outputs. @@ -180,6 +179,5 @@ The ``start_mode`` is usually ``START_MODE_BEGIN_SEQUENCE``, unless you have use ``working_mem`` is an array which can be used to persist information between runs of the custom node. - - When returning, you can mask the returned value with one of the STEP\_\* constants. +When returning, you can mask the returned value with one of the STEP\_\* constants. diff --git a/conf.py b/conf.py index 764c4bbdf..feb9f8e0c 100644 --- a/conf.py +++ b/conf.py @@ -53,7 +53,7 @@ import sphinx_rtd_theme html_theme = 'sphinx_rtd_theme' html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] if on_rtd: - using_rtd_theme = True + using_rtd_theme = True # Theme options html_theme_options = { diff --git a/content/3d/making_trees.rst b/content/3d/making_trees.rst index 39de9a900..79900b80d 100644 --- a/content/3d/making_trees.rst +++ b/content/3d/making_trees.rst @@ -38,31 +38,31 @@ This is a simple example of a shader for leaves: .. code-block:: glsl - shader_type spatial; - render_mode depth_draw_alpha_prepass, cull_disabled, world_vertex_coords; + shader_type spatial; + render_mode depth_draw_alpha_prepass, cull_disabled, world_vertex_coords; This is a spatial shader. There is no front/back culling (so leaves can be seen from both sides), and alpha prepass is used, so there are less depth arctifacts that result from using transparency (and leaves cast shadow). Finally, for the sway effect, world coordinates are recommended, so the tree can be duplicated, moved, etc. and it will still work together with other trees. .. code-block:: glsl - uniform sampler2D texture_albedo : hint_albedo; - uniform vec4 transmission : hint_color; + uniform sampler2D texture_albedo : hint_albedo; + uniform vec4 transmission : hint_color; Here, the texture is read, as well as a transmission color, which is used to add some back-lighting to the leaves, simulating subsurface scattering. .. code-block:: glsl - uniform float sway_speed = 1.0; - uniform float sway_strength = 0.05; - uniform float sway_phase_len = 8.0; + uniform float sway_speed = 1.0; + uniform float sway_strength = 0.05; + uniform float sway_phase_len = 8.0; - void vertex() { - float strength = COLOR.r * sway_strength; - VERTEX.x += sin(VERTEX.x * sway_phase_len * 1.123 + TIME * sway_speed) * strength; - VERTEX.y += sin(VERTEX.y * sway_phase_len + TIME * sway_speed * 1.12412) * strength; - VERTEX.z += sin(VERTEX.z * sway_phase_len * 0.9123 + TIME * sway_speed * 1.3123) * strength; - } + void vertex() { + float strength = COLOR.r * sway_strength; + VERTEX.x += sin(VERTEX.x * sway_phase_len * 1.123 + TIME * sway_speed) * strength; + VERTEX.y += sin(VERTEX.y * sway_phase_len + TIME * sway_speed * 1.12412) * strength; + VERTEX.z += sin(VERTEX.z * sway_phase_len * 0.9123 + TIME * sway_speed * 1.3123) * strength; + } This is the code to create the sway of the leaves. It's basic (just uses a sinewave multiplying by the time and axis position, but works well). Notice that the strength is multiplied by the color. Every axis uses a different small near 1.0 multiplication factor so axes don't appear in sync. @@ -71,14 +71,14 @@ Finally all that is left is the fragment shader: .. code-block:: glsl - void fragment() { - vec4 albedo_tex = texture(texture_albedo,UV); - ALBEDO = albedo_tex.rgb; - ALPHA = albedo_tex.a; - METALLIC = 0.0; - ROUGHNESS = 1.0; - TRANSMISSION = transmission.rgb; - } + void fragment() { + vec4 albedo_tex = texture(texture_albedo,UV); + ALBEDO = albedo_tex.rgb; + ALPHA = albedo_tex.a; + METALLIC = 0.0; + ROUGHNESS = 1.0; + TRANSMISSION = transmission.rgb; + } And this is pretty much it. diff --git a/development/compiling/optimizing_for_size.rst b/development/compiling/optimizing_for_size.rst index d0d766cc2..b2837bc38 100644 --- a/development/compiling/optimizing_for_size.rst +++ b/development/compiling/optimizing_for_size.rst @@ -24,7 +24,7 @@ For 2D games, having the whole 3D engine available usually makes no sense. Becau :: - scons p=windows target=release tools=no disable_3d=yes + scons p=windows target=release tools=no disable_3d=yes Tools must be disabled in order to use this flag, as the editor is not designed to operate without 3D support. Without it, the binary size can be reduced @@ -38,7 +38,7 @@ TextEditor or GraphEdit. They can be disabled using a build flag: :: - scons p=windows target=release tools=no disable_advanced_gui=yes + scons p=windows target=release tools=no disable_advanced_gui=yes Disabling unwanted modules -------------------------- @@ -48,7 +48,7 @@ You can see a list of modules with the following command: :: - scons --help + scons --help The list of modules that can be disabled will appear, together with all build options. If you are working on a simple 2D game, you could disable @@ -56,7 +56,7 @@ a lot of them: :: - scons p=windows target=release tools=no module_bmp_enabled=no module_bullet_enabled=no module_csg_enabled=no module_dds_enabled=no module_enet_enabled=no module_etc_enabled=no module_gdnative_enabled=no module_gridmap_enabled=no module_hdr_enabled=no module_mbedtls_enabled=no module_mobile_vr_enabled=no module_opus_enabled=no module_pvr_enabled=no module_recast_enabled=no module_regex_enabled=no module_squish_enabled=no module_tga_enabled=no module_thekla_unwrap_enabled=no module_theora_enabled=no module_tinyexr_enabled=no module_vorbis_enabled=no module_webm_enabled=no module_websocket_enabled=no + scons p=windows target=release tools=no module_bmp_enabled=no module_bullet_enabled=no module_csg_enabled=no module_dds_enabled=no module_enet_enabled=no module_etc_enabled=no module_gdnative_enabled=no module_gridmap_enabled=no module_hdr_enabled=no module_mbedtls_enabled=no module_mobile_vr_enabled=no module_opus_enabled=no module_pvr_enabled=no module_recast_enabled=no module_regex_enabled=no module_squish_enabled=no module_tga_enabled=no module_thekla_unwrap_enabled=no module_theora_enabled=no module_tinyexr_enabled=no module_vorbis_enabled=no module_webm_enabled=no module_websocket_enabled=no Optimizing for size instead of speed ------------------------------------ @@ -66,7 +66,7 @@ To enable this, just set the ``optimize`` flag to ``size``: :: - scons p=windows target=release tools=no optimize=size + scons p=windows target=release tools=no optimize=size Some platforms such as WebAssembly already use this mode by default. @@ -80,7 +80,7 @@ and MSVC compilers: :: - scons p=windows target=release tools=no use_lto=yes + scons p=windows target=release tools=no use_lto=yes Linking becomes much slower with this option, so it should be used only for release builds. @@ -92,7 +92,7 @@ If you build from source, remember to strip debug symbols from binaries: :: - strip godot.64 + strip godot.64 Using UPX to compress binaries ------------------------------ diff --git a/development/cpp/binding_to_external_libraries.rst b/development/cpp/binding_to_external_libraries.rst index 7d21ca71a..009a07110 100644 --- a/development/cpp/binding_to_external_libraries.rst +++ b/development/cpp/binding_to_external_libraries.rst @@ -201,8 +201,8 @@ You can now use your newly created module from any script: :: var t = TTS.new() - var script = "Hello world. This is a test!" - var is_spoken = t.say_text(script) - print('is_spoken: ', is_spoken) + var script = "Hello world. This is a test!" + var is_spoken = t.say_text(script) + print('is_spoken: ', is_spoken) And the output will be ``is_spoken: True`` if the text is spoken. diff --git a/development/cpp/custom_audiostreams.rst b/development/cpp/custom_audiostreams.rst index c3de2a8b3..02b89c48a 100644 --- a/development/cpp/custom_audiostreams.rst +++ b/development/cpp/custom_audiostreams.rst @@ -6,17 +6,17 @@ Custom AudioStreams Introduction ------------ -AudioStream is the base class of all audio emitting objects. -AudioStreamPlayer binds onto an AudioStream to emit PCM data +AudioStream is the base class of all audio emitting objects. +AudioStreamPlayer binds onto an AudioStream to emit PCM data into an AudioServer which manages audio drivers. -All audio resources require two audio based classes: AudioStream -and AudioStreamPlayback. As a data container, AudioStream contains -the resource and exposes itself to GDScript. AudioStream references -its own internal custom AudioStreamPlayback which translates +All audio resources require two audio based classes: AudioStream +and AudioStreamPlayback. As a data container, AudioStream contains +the resource and exposes itself to GDScript. AudioStream references +its own internal custom AudioStreamPlayback which translates AudioStream into PCM data. -This guide assumes the reader knows how to create C++ modules. If not, refer to this guide +This guide assumes the reader knows how to create C++ modules. If not, refer to this guide :ref:`doc_custom_modules_in_c++`. References: @@ -25,8 +25,6 @@ References: - `servers/audio/audio_stream.h `__ - `scene/audio/audioplayer.cpp `__ - - What for? --------- @@ -37,57 +35,58 @@ What for? Create an AudioStream --------------------- - -An AudioStream consists of three components: data container, stream name, -and an AudioStreamPlayback friend class generator. Audio data can be -loaded in a number of ways such as with an internal counter for a tone generator, +An AudioStream consists of three components: data container, stream name, +and an AudioStreamPlayback friend class generator. Audio data can be +loaded in a number of ways such as with an internal counter for a tone generator, internal/external buffer, or a file reference. - -Some AudioStreams need to be stateless such as objects loaded from -ResourceLoader. ResourceLoader loads once and references the same -object regardless how many times ``load`` is called on a specific resource. +Some AudioStreams need to be stateless such as objects loaded from +ResourceLoader. ResourceLoader loads once and references the same +object regardless how many times ``load`` is called on a specific resource. Therefore, playback state must be self contained in AudioStreamPlayback. - .. code:: cpp /* audiostream_mytone.h */ - #include "reference.h" - #include "resource.h" - #include "servers/audio/audio_stream.h + #include "core/reference.h" + #include "core/resource.h" + #include "servers/audio/audio_stream.h" class AudioStreamMyTone : public AudioStream { GDCLASS(AudioStreamMyTone, AudioStream) + private: friend class AudioStreamPlaybackMyTone; uint64_t pos; int mix_rate; bool stereo; int hz; + public: void reset(); void set_position(uint64_t pos); virtual Ref instance_playback(); virtual String get_stream_name() const; - void gen_tone(int16_t *, int frames); - virtual float get_length() const { return 0; } //if supported, otherwise return 0 + void gen_tone(int16_t *pcm_buf, int size); + virtual float get_length() const { return 0; } // if supported, otherwise return 0 AudioStreamMyTone(); protected: static void _bind_methods(); }; - .. code:: cpp /* audiostream_mytone.cpp */ + + #include "audiostream_mytone.h" + AudioStreamMyTone::AudioStreamMyTone() - : mix_rate(44100), stereo(false), hz(639) { + : mix_rate(44100), stereo(false), hz(639) { } - Ref AudioStreamMyTone::instance_playback(){ + Ref AudioStreamMyTone::instance_playback() { Ref talking_tree; talking_tree.instance(); talking_tree->base = Ref(this); @@ -103,16 +102,15 @@ Therefore, playback state must be self contained in AudioStreamPlayback. void AudioStreamMyTone::set_position(uint64_t p) { pos = p; } - void AudioStreamMyTone::gen_tone(int16_t * pcm_buf, int size){ - for( int i = 0; i < size; i++){ - pcm_buf[i] = 32767.0 * sin(2.0*Math_PI*double(pos+i)/(double(mix_rate)/double(hz))); + void AudioStreamMyTone::gen_tone(int16_t *pcm_buf, int size) { + for (int i = 0; i < size; i++) { + pcm_buf[i] = 32767.0 * sin(2.0 * Math_PI * double(pos + i) / (double(mix_rate) / double(hz))); } pos += size; } - void AudioStreamMyTone::_bind_methods(){ + void AudioStreamMyTone::_bind_methods() { ClassDB::bind_method(D_METHOD("reset"), &AudioStreamMyTone::reset); ClassDB::bind_method(D_METHOD("get_stream_name"), &AudioStreamMyTone::get_stream_name); - } References: @@ -124,23 +122,24 @@ References: Create an AudioStreamPlayback ----------------------------- -AudioStreamPlayer uses ``mix`` callback to obtain PCM data. The callback must match sample rate and fill the buffer. +AudioStreamPlayer uses ``mix`` callback to obtain PCM data. The callback must match sample rate and fill the buffer. Since AudioStreamPlayback is controlled by the audio thread, i/o and dynamic memory allocation are forbidden. .. code:: cpp /* audiostreamplayer_mytone.h */ - #include "reference.h" - #include "resource.h" - #include "servers/audio/audio_stream.h" + #include "core/reference.h" + #include "core/resource.h" + #include "servers/audio/audio_stream.h" class AudioStreamPlaybackMyTone : public AudioStreamPlayback { GDCLASS(AudioStreamPlaybackMyTone, AudioStreamPlayback) friend class AudioStreamMyTone; + private: - enum{ + enum { PCM_BUFFER_SIZE = 4096 }; enum { @@ -148,34 +147,34 @@ Since AudioStreamPlayback is controlled by the audio thread, i/o and dynamic mem MIX_FRAC_LEN = (1 << MIX_FRAC_BITS), MIX_FRAC_MASK = MIX_FRAC_LEN - 1, }; - void * pcm_buffer; + void *pcm_buffer; Ref base; bool active; + public: virtual void start(float p_from_pos = 0.0); virtual void stop(); virtual bool is_playing() const; - virtual int get_loop_count() const; //times it looped + virtual int get_loop_count() const; // times it looped virtual float get_playback_position() const; virtual void seek(float p_time); virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames); - virtual float get_length() const; //if supported, otherwise return 0 + virtual float get_length() const; // if supported, otherwise return 0 AudioStreamPlaybackMyTone(); ~AudioStreamPlaybackMyTone(); - }; - - .. code:: cpp /* audiostreamplayer_mytone.cpp */ - #include "audiostreamplayer_mytone.h" - #include "math/math_funcs.h" - #include "print_string.h" - AudioStreamPlaybackMyTone::AudioStreamPlaybackMyTone() - : active(false){ + #include "audiostreamplayer_mytone.h" + + #include "core/math/math_funcs.h" + #include "core/print_string.h" + + AudioStreamPlaybackMyTone::AudioStreamPlaybackMyTone() + : active(false) { AudioServer::get_singleton()->lock(); pcm_buffer = AudioServer::get_singleton()->audio_data_alloc(PCM_BUFFER_SIZE); zeromem(pcm_buffer, PCM_BUFFER_SIZE); @@ -187,33 +186,32 @@ Since AudioStreamPlayback is controlled by the audio thread, i/o and dynamic mem pcm_buffer = NULL; } } - void AudioStreamPlaybackMyTone::stop(){ + void AudioStreamPlaybackMyTone::stop() { active = false; base->reset(); } - - void AudioStreamPlaybackMyTone::start(float p_from_pos){ + void AudioStreamPlaybackMyTone::start(float p_from_pos) { seek(p_from_pos); active = true; } - void AudioStreamPlaybackMyTone::seek(float p_time){ + void AudioStreamPlaybackMyTone::seek(float p_time) { float max = get_length(); if (p_time < 0) { p_time = 0; } base->set_position(uint64_t(p_time * base->mix_rate) << MIX_FRAC_BITS); } - void AudioStreamPlaybackMyTone::mix(AudioFrame *p_buffer, float p_rate, int p_frames){ + void AudioStreamPlaybackMyTone::mix(AudioFrame *p_buffer, float p_rate, int p_frames) { ERR_FAIL_COND(!active); if (!active) { return; } zeromem(pcm_buffer, PCM_BUFFER_SIZE); - int16_t * buf = (int16_t * )pcm_buffer; + int16_t *buf = (int16_t *)pcm_buffer; base->gen_tone(buf, p_frames); - for(int i = 0; i < p_frames; i++){ - float sample = float(buf[i])/32767.0; + for(int i = 0; i < p_frames; i++) { + float sample = float(buf[i]) / 32767.0; p_buffer[i] = AudioFrame(sample, sample); } } @@ -230,23 +228,20 @@ Since AudioStreamPlayback is controlled by the audio thread, i/o and dynamic mem return active; } - Resampling ~~~~~~~~~~ - -Godot’s AudioServer currently uses 44100 Hz sample rate. When other sample rates are -needed such as 48000, either provide one or use AudioStreamPlaybackResampled. +Godot’s AudioServer currently uses 44100 Hz sample rate. When other sample rates are +needed such as 48000, either provide one or use AudioStreamPlaybackResampled. Godot provides cubic interpolation for audio resampling. -Instead of overloading ``mix``, AudioStreamPlaybackResampled uses ``_mix_internal`` to +Instead of overloading ``mix``, AudioStreamPlaybackResampled uses ``_mix_internal`` to query AudioFrames and ``get_stream_sampling_rate`` to query current mix rate. .. code:: cpp - #include "reference.h" - #include "resource.h" - + #include "core/reference.h" + #include "core/resource.h" #include "servers/audio/audio_stream.h" class AudioStreamMyToneResampled; @@ -254,8 +249,9 @@ query AudioFrames and ``get_stream_sampling_rate`` to query current mix rate. class AudioStreamPlaybackResampledMyTone : public AudioStreamPlaybackResampled { GDCLASS(AudioStreamPlaybackResampledMyTone, AudioStreamPlaybackResampled) friend class AudioStreamMyToneResampled; + private: - enum{ + enum { PCM_BUFFER_SIZE = 4096 }; enum { @@ -263,35 +259,35 @@ query AudioFrames and ``get_stream_sampling_rate`` to query current mix rate. MIX_FRAC_LEN = (1 << MIX_FRAC_BITS), MIX_FRAC_MASK = MIX_FRAC_LEN - 1, }; - void * pcm_buffer; + void *pcm_buffer; Ref base; bool active; + protected: virtual void _mix_internal(AudioFrame *p_buffer, int p_frames); + public: virtual void start(float p_from_pos = 0.0); virtual void stop(); virtual bool is_playing() const; - virtual int get_loop_count() const; //times it looped + virtual int get_loop_count() const; // times it looped virtual float get_playback_position() const; virtual void seek(float p_time); - virtual float get_length() const; //if supported, otherwise return 0 + virtual float get_length() const; // if supported, otherwise return 0 virtual float get_stream_sampling_rate(); AudioStreamPlaybackResampledMyTone(); ~AudioStreamPlaybackResampledMyTone(); - }; - - .. code:: cpp #include "mytone_audiostream_resampled.h" - #include "math/math_funcs.h" - #include "print_string.h" - AudioStreamPlaybackResampledMyTone::AudioStreamPlaybackResampledMyTone() - : active(false){ + #include "core/math/math_funcs.h" + #include "core/print_string.h" + + AudioStreamPlaybackResampledMyTone::AudioStreamPlaybackResampledMyTone() + : active(false) { AudioServer::get_singleton()->lock(); pcm_buffer = AudioServer::get_singleton()->audio_data_alloc(PCM_BUFFER_SIZE); zeromem(pcm_buffer, PCM_BUFFER_SIZE); @@ -303,37 +299,36 @@ query AudioFrames and ``get_stream_sampling_rate`` to query current mix rate. pcm_buffer = NULL; } } - void AudioStreamPlaybackResampledMyTone::stop(){ + void AudioStreamPlaybackResampledMyTone::stop() { active = false; base->reset(); } - - void AudioStreamPlaybackResampledMyTone::start(float p_from_pos){ + void AudioStreamPlaybackResampledMyTone::start(float p_from_pos) { seek(p_from_pos); active = true; } - void AudioStreamPlaybackResampledMyTone::seek(float p_time){ + void AudioStreamPlaybackResampledMyTone::seek(float p_time) { float max = get_length(); if (p_time < 0) { p_time = 0; } base->set_position(uint64_t(p_time * base->mix_rate) << MIX_FRAC_BITS); } - void AudioStreamPlaybackResampledMyTone::_mix_internal(AudioFrame *p_buffer, int p_frames){ + void AudioStreamPlaybackResampledMyTone::_mix_internal(AudioFrame *p_buffer, int p_frames) { ERR_FAIL_COND(!active); if (!active) { return; } zeromem(pcm_buffer, PCM_BUFFER_SIZE); - int16_t * buf = (int16_t * )pcm_buffer; + int16_t *buf = (int16_t *)pcm_buffer; base->gen_tone(buf, p_frames); - for(int i = 0; i < p_frames; i++){ - float sample = float(buf[i])/32767.0; + for(int i = 0; i < p_frames; i++) { + float sample = float(buf[i]) / 32767.0; p_buffer[i] = AudioFrame(sample, sample); } } - float AudioStreamPlaybackResampledMyTone::get_stream_sampling_rate(){ + float AudioStreamPlaybackResampledMyTone::get_stream_sampling_rate() { return float(base->mix_rate); } int AudioStreamPlaybackResampledMyTone::get_loop_count() const { @@ -349,13 +344,8 @@ query AudioFrames and ``get_stream_sampling_rate`` to query current mix rate. return active; } - - - References: ~~~~~~~~~~~ - `core/math/audio_frame.h `__ - `servers/audio/audio_stream.h `__ - `scene/audio/audioplayer.cpp `__ - - diff --git a/development/cpp/custom_godot_servers.rst b/development/cpp/custom_godot_servers.rst index 81c114eb5..25cd18b1f 100644 --- a/development/cpp/custom_godot_servers.rst +++ b/development/cpp/custom_godot_servers.rst @@ -19,9 +19,7 @@ References ~~~~~~~~~~~ - `Why does Godot use servers and RIDs? `__ - - `Singleton pattern `__ - - `Mediator pattern `__ What for? @@ -45,13 +43,13 @@ an initialization state and a cleanup procedure. #ifndef HILBERT_HOTEL_H #define HILBERT_HOTEL_H - #include "object.h" - #include "list.h" - #include "rid.h" - #include "set.h" - #include "variant.h" - #include "os/thread.h" - #include "os/mutex.h" + #include "core/list.h" + #include "core/object.h" + #include "core/os/thread.h" + #include "core/os/mutex.h" + #include "core/rid.h" + #include "core/set.h" + #include "core/variant.h" class HilbertHotel : public Object { GDCLASS(HilbertHotel, Object); @@ -97,19 +95,21 @@ an initialization state and a cleanup procedure. .. code:: cpp #include "hilbert_hotel.h" - #include "variant.h" - #include "os/os.h" - #include "list.h" - #include "dictionary.h" + + #include "core/dictionary.h" + #include "core/list.h" + #include "core/os/os.h" + #include "core/variant.h" + #include "prime_225.h" - oid HilbertHotel::thread_func(void *p_udata) { + void HilbertHotel::thread_func(void *p_udata) { HilbertHotel *ac = (HilbertHotel *) p_udata; uint64_t msdelay = 1000; - while (!ac -> exit_thread) { - if (!ac -> empty()) { + while (!ac->exit_thread) { + if (!ac->empty()) { ac->lock(); ac->register_rooms(); ac->unlock(); @@ -163,8 +163,8 @@ an initialization state and a cleanup procedure. _HilbertHotel::get_singleton()->_occupy_room(room, rid); } - Variant HilbertHotel::get_bus_info(RID id){ - InfiniteBus * bus = bus_owner.getornull(id); + Variant HilbertHotel::get_bus_info(RID id) { + InfiniteBus *)bus = bus_owner.getornull(id); if (bus) { Dictionary d; @@ -240,33 +240,35 @@ an initialization state and a cleanup procedure. /* prime_225.h */ - #include "int_types.h" + #include "core/int_types.h" - const uint64_t PRIME[225] = {2,3,5,7,11,13,17,19,23, - 29,31,37,41,43,47,53,59,61, - 67,71,73,79,83,89,97,101,103, - 107,109,113,127,131,137,139,149,151, - 157,163,167,173,179,181,191,193,197, - 199,211,223,227,229,233,239,241,251, - 257,263,269,271,277,281,283,293,307, - 311,313,317,331,337,347,349,353,359, - 367,373,379,383,389,397,401,409,419, - 421,431,433,439,443,449,457,461,463, - 467,479,487,491,499,503,509,521,523, - 541,547,557,563,569,571,577,587,593, - 599,601,607,613,617,619,631,641,643, - 647,653,659,661,673,677,683,691,701, - 709,719,727,733,739,743,751,757,761, - 769,773,787,797,809,811,821,823,827, - 829,839,853,857,859,863,877,881,883, - 887,907,911,919,929,937,941,947,953, - 967,971,977,983,991,997,1009,1013,1019, - 1021,1031,1033,1039,1049,1051,1061,1063,1069, - 1087,1091,1093,1097,1103,1109,1117,1123,1129, - 1151,1153,1163,1171,1181,1187,1193,1201,1213, - 1217,1223,1229,1231,1237,1249,1259,1277,1279, - 1283,1289,1291,1297,1301,1303,1307,1319,1321, - 1327,1361,1367,1373,1381,1399,1409,1423,1427}; + const uint64_t PRIME[225] = { + 2,3,5,7,11,13,17,19,23, + 29,31,37,41,43,47,53,59,61, + 67,71,73,79,83,89,97,101,103, + 107,109,113,127,131,137,139,149,151, + 157,163,167,173,179,181,191,193,197, + 199,211,223,227,229,233,239,241,251, + 257,263,269,271,277,281,283,293,307, + 311,313,317,331,337,347,349,353,359, + 367,373,379,383,389,397,401,409,419, + 421,431,433,439,443,449,457,461,463, + 467,479,487,491,499,503,509,521,523, + 541,547,557,563,569,571,577,587,593, + 599,601,607,613,617,619,631,641,643, + 647,653,659,661,673,677,683,691,701, + 709,719,727,733,739,743,751,757,761, + 769,773,787,797,809,811,821,823,827, + 829,839,853,857,859,863,877,881,883, + 887,907,911,919,929,937,941,947,953, + 967,971,977,983,991,997,1009,1013,1019, + 1021,1031,1033,1039,1049,1051,1061,1063,1069, + 1087,1091,1093,1097,1103,1109,1117,1123,1129, + 1151,1153,1163,1171,1181,1187,1193,1201,1213, + 1217,1223,1229,1231,1237,1249,1259,1277,1279, + 1283,1289,1291,1297,1301,1303,1307,1319,1321, + 1327,1361,1367,1373,1381,1399,1409,1423,1427 + }; Custom managed resource data ---------------------------- @@ -335,9 +337,11 @@ is used to register the dummy class in GDScript. /* register_types.cpp */ #include "register_types.h" - #include "class_db.h" + + #include "core/class_db.h" + #include "core/engine.h" + #include "hilbert_hotel.h" - #include "engine.h" static HilbertHotel *hilbert_hotel = NULL; static _HilbertHotel *_hilbert_hotel = NULL; @@ -432,7 +436,7 @@ It is possible to emit signals to GDScript by calling the GDScript dummy object. return HilbertHotel::get_singleton()->delete_bus(rid); } - void _HilbertHotel::_occupy_room(int room_number, RID bus){ + void _HilbertHotel::_occupy_room(int room_number, RID bus) { emit_signal("occupy_room", room_number, bus); } @@ -479,24 +483,24 @@ Here is the GDScript sample code: .. code:: - extends Node + extends Node - func _ready(): - print("start Debugging") - HilbertHotel.connect("occupy_room", self, "_print_occupy_room") - var rid = HilbertHotel.create_bus() - OS.delay_msec(2000) - HilbertHotel.create_bus() - OS.delay_msec(2000) - HilbertHotel.create_bus() - OS.delay_msec(2000) - print(HilbertHotel.get_bus_info(rid)) - HilbertHotel.delete_bus(rid) - print("ready done") + func _ready(): + print("Start debugging") + HilbertHotel.connect("occupy_room", self, "_print_occupy_room") + var rid = HilbertHotel.create_bus() + OS.delay_msec(2000) + HilbertHotel.create_bus() + OS.delay_msec(2000) + HilbertHotel.create_bus() + OS.delay_msec(2000) + print(HilbertHotel.get_bus_info(rid)) + HilbertHotel.delete_bus(rid) + print("Ready done") - func _print_occupy_room(room_number, r_id): - print("room_num: " + str(room_number) + " rid: " + str(r_id)) - print(HilbertHotel.get_bus_info(r_id)) + func _print_occupy_room(room_number, r_id): + print("Room number: " + str(room_number) + ", RID: " + str(r_id)) + print(HilbertHotel.get_bus_info(r_id)) Notes ~~~~~ diff --git a/development/cpp/custom_resource_format_loaders.rst b/development/cpp/custom_resource_format_loaders.rst index 33b5d6878..e0e63897c 100644 --- a/development/cpp/custom_resource_format_loaders.rst +++ b/development/cpp/custom_resource_format_loaders.rst @@ -60,7 +60,7 @@ read and handle data serialization. #ifndef MY_JSON_LOADER_H #define MY_JSON_LOADER_H - #include "io/resource_loader.h" + #include "core/io/resource_loader.h" class ResourceFormatLoaderMyJson : public ResourceFormatLoader { public: @@ -120,42 +120,43 @@ Here is an example of how to create a custom datatype #ifndef MY_JSON_H #define MY_JSON_H + #include "core/dictionary.h" + #include "core/io/json.h" + #include "core/reference.h" #include "core/variant.h" - #include "reference.h" - #include "variant_parser.h" - #include "io/json.h" - #include "dictionary.h" + #include "core/variant_parser.h" - class MyJson : public Resource{ + class MyJson : public Resource { GDCLASS(MyJson, Resource); protected: static void _bind_methods() { - ClassDB::bind_method(D_METHOD("toString"), &MyJson::toString); + ClassDB::bind_method(D_METHOD("to_string"), &MyJson::to_string); } private: Dictionary dict; + public: - Error set_file(const String &p_path){ + Error set_file(const String &p_path) { Error error_file; FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &error_file); String buf = String(""); - while(!file->eof_reached()){ + while (!file->eof_reached()) { buf += file->get_line(); } String err_string; int err_line; JSON cmd; Variant ret; - Error err = cmd.parse( buf, ret, err_string, err_line); + Error err = cmd.parse(buf, ret, err_string, err_line); dict = Dictionary(ret); - file -> close(); + file->close(); return OK; } - String toString() const { + String to_string() const { return String(*this); } @@ -164,15 +165,15 @@ Here is an example of how to create a custom datatype return a.print(dict); } - MyJson() {}; - ~MyJson() {}; + MyJson() {}; + ~MyJson() {}; }; - #endif + #endif // MY_JSON_H Considerations ~~~~~~~~~~~~~~ -Some libraries may not define certain common routines such as i/o handling. +Some libraries may not define certain common routines such as IO handling. Therefore, Godot call translations are required. For example, here is the code for translating ``FileAccess`` @@ -183,9 +184,10 @@ calls into ``std::istream``. #include #include - class GodotFileInStreamBuf : public std::streambuf{ + class GodotFileInStreamBuf : public std::streambuf { + public: - GodotFileInStreamBuf(FileAccess * fa) { + GodotFileInStreamBuf(FileAccess *fa) { _file = fa; } int underflow() { @@ -194,15 +196,16 @@ calls into ``std::istream``. } else { size_t pos = _file->get_position(); uint8_t ret = _file->get_8(); - _file->seek(pos); //required since get_8() advances the read head + _file->seek(pos); // required since get_8() advances the read head return ret; } } int uflow() { - return _file->eof_reached() ? EOF : _file -> get_8(); + return _file->eof_reached() ? EOF : _file->get_8(); } + private: - FileAccess * _file; + FileAccess *_file; }; @@ -224,7 +227,7 @@ when ``load`` is called. /* register_types.cpp */ #include "register_types.h" - #include "class_db.h" + #include "core/class_db.h" #include "my_json_loader.h" #include "my_json.h" @@ -251,21 +254,21 @@ Loading it on GDScript .. code:: - { - "savefilename" : "demo.mjson", - "demo": [ - "welcome", - "to", - "godot", - "resource", - "loaders" - ] - } + { + "savefilename" : "demo.mjson", + "demo": [ + "welcome", + "to", + "godot", + "resource", + "loaders" + ] + } .. code:: - extends Node + extends Node - func _ready(): - var myjson = load("res://demo.mjson") - print( myjson.toString()) + func _ready(): + var myjson = load("res://demo.mjson") + print(myjson.to_string()) diff --git a/getting_started/scripting/gdscript/gdscript_basics.rst b/getting_started/scripting/gdscript/gdscript_basics.rst index b68706686..16f825e43 100644 --- a/getting_started/scripting/gdscript/gdscript_basics.rst +++ b/getting_started/scripting/gdscript/gdscript_basics.rst @@ -1595,12 +1595,12 @@ into an invalid state, for example: :: func my_func(): - yield(button_func(), "completed") - print("All buttons were pressed, hurray!") + yield(button_func(), "completed") + print("All buttons were pressed, hurray!") func button_func(): yield($Button0, "pressed") - yield($Button1, "pressed") + yield($Button1, "pressed") ``my_func`` will only continue execution once both the buttons are pressed. diff --git a/getting_started/step_by_step/exporting.rst b/getting_started/step_by_step/exporting.rst index 7ae416efd..ff8cbf0c3 100644 --- a/getting_started/step_by_step/exporting.rst +++ b/getting_started/step_by_step/exporting.rst @@ -82,14 +82,14 @@ changed: velocity = Vector2() # Remove keyboard controls. - # if Input.is_action_pressed("ui_right"): + # if Input.is_action_pressed("ui_right"): # velocity.x += 1 - # if Input.is_action_pressed("ui_left"): - # velocity.x -= 1 - # if Input.is_action_pressed("ui_down"): - # velocity.y += 1 - # if Input.is_action_pressed("ui_up"): - # velocity.y -= 1 + # if Input.is_action_pressed("ui_left"): + # velocity.x -= 1 + # if Input.is_action_pressed("ui_down"): + # velocity.y += 1 + # if Input.is_action_pressed("ui_up"): + # velocity.y -= 1 if velocity.length() > 0: velocity = velocity.normalized() * speed @@ -99,7 +99,7 @@ changed: $AnimatedSprite.stop() $Trail.emitting = false - position += velocity * delta + position += velocity * delta # We don't need to clamp the player's position # because you can't click outside the screen. # position.x = clamp(position.x, 0, screensize.x) diff --git a/getting_started/step_by_step/scene_tree.rst b/getting_started/step_by_step/scene_tree.rst index 4cf139f37..8599ca431 100644 --- a/getting_started/step_by_step/scene_tree.rst +++ b/getting_started/step_by_step/scene_tree.rst @@ -149,7 +149,7 @@ function: .. code-tab:: gdscript GDScript func _my_level_was_completed(): - get_tree().change_scene("res://levels/level2.tscn") + get_tree().change_scene("res://levels/level2.tscn") .. code-tab:: csharp diff --git a/getting_started/workflow/assets/escn_exporter/material.rst b/getting_started/workflow/assets/escn_exporter/material.rst index 4a9d5d068..30aa49980 100644 --- a/getting_started/workflow/assets/escn_exporter/material.rst +++ b/getting_started/workflow/assets/escn_exporter/material.rst @@ -40,10 +40,10 @@ Blender. Currently only the diffuse color and a few flags (eg unshaded) are exported. .. warning:: - Export of Blender materials is currently very primitive. However, it is the - focus of a current GSOC project + Export of Blender materials is currently very primitive. However, it is the + focus of a current GSOC project .. warning:: - Materials are currently exported using their "Blender Render" settings. - When Blender 2.8 is released, this will be removed and this part of the - exporter will change. + Materials are currently exported using their "Blender Render" settings. + When Blender 2.8 is released, this will be removed and this part of the + exporter will change. diff --git a/getting_started/workflow/assets/escn_exporter/physics.rst b/getting_started/workflow/assets/escn_exporter/physics.rst index 171f36ee6..eaaaaa5a9 100644 --- a/getting_started/workflow/assets/escn_exporter/physics.rst +++ b/getting_started/workflow/assets/escn_exporter/physics.rst @@ -38,9 +38,9 @@ There are the following caveats: what you want. .. important:: - To build compound physics shapes, parent together multiple objects with - rigid body enabled. The physics properties are taken from the parent-most - rigid body, and the rest are used as collision shapes. + To build compound physics shapes, parent together multiple objects with + rigid body enabled. The physics properties are taken from the parent-most + rigid body, and the rest are used as collision shapes. Collision Geometry Only diff --git a/getting_started/workflow/export/feature_tags.rst b/getting_started/workflow/export/feature_tags.rst index c33fe6724..9a308accd 100644 --- a/getting_started/workflow/export/feature_tags.rst +++ b/getting_started/workflow/export/feature_tags.rst @@ -21,7 +21,7 @@ Features can be queried at run-time from the singleton API by calling: :: - OS.has_feature(name) + OS.has_feature(name) Default features diff --git a/make.bat b/make.bat index 11549137d..c1e71af15 100644 --- a/make.bat +++ b/make.bat @@ -5,7 +5,7 @@ pushd %~dp0 REM Command file for Sphinx documentation on Windows if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build + set SPHINXBUILD=sphinx-build ) set SOURCEDIR=. set BUILDDIR=_build @@ -15,15 +15,15 @@ if "%1" == "" goto help %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 ) %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% diff --git a/tutorials/3d/fps_tutorial/part_five.rst b/tutorials/3d/fps_tutorial/part_five.rst index da1e645c9..c6927a2ad 100644 --- a/tutorials/3d/fps_tutorial/part_five.rst +++ b/tutorials/3d/fps_tutorial/part_five.rst @@ -11,7 +11,6 @@ In this part we're going to add grenades to the player, give the player the abil .. image:: img/PartFiveFinished.png .. note:: You are assumed to have finished :ref:`doc_fps_tutorial_part_four` before moving on to this part of the tutorial. - The finished project from :ref:`doc_fps_tutorial_part_four` will be the starting project for part 5 Let's get started! @@ -564,7 +563,7 @@ ______ The last thing we do is check to see whether or not ``grabbed_object`` is equal to ``null``, outside all of the grabbing/throwing related code. .. note:: While technically not input related, it's easy enough to place the code moving the grabbed object here - because it's only two lines, and then all of the grabbing/throwing code is in one place + because it's only two lines, and then all of the grabbing/throwing code is in one place If the player is holding a object, we set its global position to the camera's position plus ``OBJECT_GRAB_DISTANCE`` in the direction the camera is facing. @@ -579,13 +578,13 @@ want the player to be able to change weapons or reload, so change ``_physics_pro process_input(delta) process_view_input(delta) process_movement(delta) - + if grabbed_object == null: process_changing_weapons(delta) process_reloading(delta) - - # Process the UI - process_UI(delta) + + # Process the UI + process_UI(delta) Now the player cannot change weapons or reload while holding an object. @@ -717,40 +716,40 @@ Add the following to ``Turret.gd``: func fire_bullet(): - - if use_raycast == true: - node_raycast.look_at(current_target.global_transform.origin + Vector3(0, PLAYER_HEIGHT, 0), Vector3(0,1,0)) - - node_raycast.force_raycast_update() - - if node_raycast.is_colliding(): - var body = node_raycast.get_collider() - if body.has_method("bullet_hit"): - body.bullet_hit(TURRET_DAMAGE_RAYCAST, node_raycast.get_collision_point()) - - ammo_in_turret -= 1 - - else: - var clone = bullet_scene.instance() - var scene_root = get_tree().root.get_children()[0] - scene_root.add_child(clone) - - clone.global_transform = $Head/Barrel_End.global_transform - clone.scale = Vector3(8, 8, 8) - clone.BULLET_DAMAGE = TURRET_DAMAGE_BULLET - clone.BULLET_SPEED = 60 - - ammo_in_turret -= 1 - - node_flash_one.visible = true - node_flash_two.visible = true - - flash_timer = FLASH_TIME - fire_timer = FIRE_TIME - - if ammo_in_turret <= 0: - ammo_reload_timer = AMMO_RELOAD_TIME - + + if use_raycast == true: + node_raycast.look_at(current_target.global_transform.origin + Vector3(0, PLAYER_HEIGHT, 0), Vector3(0,1,0)) + + node_raycast.force_raycast_update() + + if node_raycast.is_colliding(): + var body = node_raycast.get_collider() + if body.has_method("bullet_hit"): + body.bullet_hit(TURRET_DAMAGE_RAYCAST, node_raycast.get_collision_point()) + + ammo_in_turret -= 1 + + else: + var clone = bullet_scene.instance() + var scene_root = get_tree().root.get_children()[0] + scene_root.add_child(clone) + + clone.global_transform = $Head/Barrel_End.global_transform + clone.scale = Vector3(8, 8, 8) + clone.BULLET_DAMAGE = TURRET_DAMAGE_BULLET + clone.BULLET_SPEED = 60 + + ammo_in_turret -= 1 + + node_flash_one.visible = true + node_flash_two.visible = true + + flash_timer = FLASH_TIME + fire_timer = FIRE_TIME + + if ammo_in_turret <= 0: + ammo_reload_timer = AMMO_RELOAD_TIME + func body_entered_vision(body): if current_target == null: diff --git a/tutorials/3d/fps_tutorial/part_four.rst b/tutorials/3d/fps_tutorial/part_four.rst index 81705e080..411f5ce57 100644 --- a/tutorials/3d/fps_tutorial/part_four.rst +++ b/tutorials/3d/fps_tutorial/part_four.rst @@ -11,7 +11,6 @@ In this part we will be adding health pick ups, ammo pick ups, targets the playe .. image:: img/PartFourFinished.png .. note:: You are assumed to have finished :ref:`doc_fps_tutorial_part_three` before moving on to this part of the tutorial. - The finished project from :ref:`doc_fps_tutorial_part_three` will be the starting project for part 4 Let's get started! diff --git a/tutorials/3d/fps_tutorial/part_six.rst b/tutorials/3d/fps_tutorial/part_six.rst index 2189c57c0..ff9157bc9 100644 --- a/tutorials/3d/fps_tutorial/part_six.rst +++ b/tutorials/3d/fps_tutorial/part_six.rst @@ -14,7 +14,6 @@ This is the last part of the FPS tutorial, by the end of this you will have a so .. image:: img/FinishedTutorialPicture.png .. note:: You are assumed to have finished :ref:`doc_fps_tutorial_part_five` before moving on to this part of the tutorial. - The finished project from :ref:`doc_fps_tutorial_part_four` will be the starting project for part 6 Let's get started! @@ -495,9 +494,9 @@ Instead of: # Capturing/Freeing cursor if Input.is_action_just_pressed("ui_cancel"): if Input.get_mouse_mode() == Input.MOUSE_MODE_VISIBLE: - Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) - else: - Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + else: + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) You will leave only: @@ -561,7 +560,7 @@ Next we need to make a few changes to ``physics_process``. Change ``physics_proc :: func _physics_process(delta): - + if !is_dead: process_input(delta) process_view_input(delta) @@ -841,8 +840,8 @@ First, open up ``SimpleAudioPlayer.gd`` and change it to the following: audio_node.stream = audio_stream # If you are using a AudioPlayer3D, then uncomment these lines to set the position. - # if position != null: - # audio_node.global_transform.origin = position + #if position != null: + # audio_node.global_transform.origin = position audio_node.play(0.0) diff --git a/tutorials/3d/fps_tutorial/part_three.rst b/tutorials/3d/fps_tutorial/part_three.rst index fb5c0e645..2c269de46 100644 --- a/tutorials/3d/fps_tutorial/part_three.rst +++ b/tutorials/3d/fps_tutorial/part_three.rst @@ -13,7 +13,6 @@ weapons fire. .. image:: img/PartThreeFinished.png .. note:: You are assumed to have finished :ref:`doc_fps_tutorial_part_two` before moving on to this part of the tutorial. - The finished project from :ref:`doc_fps_tutorial_part_two` will be the starting project for part 3 Let's get started! @@ -516,8 +515,8 @@ and insert the following code: return # If you are using a AudioPlayer3D, then uncomment these lines to set the position. - # if position != null: - # audio_node.global_transform.origin = position + #if position != null: + # audio_node.global_transform.origin = position audio_node.play() diff --git a/tutorials/3d/fps_tutorial/part_two.rst b/tutorials/3d/fps_tutorial/part_two.rst index 1d1ac3c2f..d14e42ec8 100644 --- a/tutorials/3d/fps_tutorial/part_two.rst +++ b/tutorials/3d/fps_tutorial/part_two.rst @@ -15,7 +15,6 @@ rifle, and attack using a knife. The player will also now have animations with t and the weapons will interact with objects in the environment. .. note:: You are assumed to have finished :ref:`doc_fps_tutorial_part_one` before moving on to this part of the tutorial. - The finished project from :ref:`doc_fps_tutorial_part_one` will be the starting project for part 2 Let's get started! @@ -1056,7 +1055,7 @@ Now lets add all of the player input code for the weapons in ``process_input``. if current_weapon != null: if animation_manager.current_state == current_weapon.IDLE_ANIM_NAME: animation_manager.set_animation(current_weapon.FIRE_ANIM_NAME) - # ---------------------------------- + # ---------------------------------- Lets go over the additions, starting with how we're changing weapons. diff --git a/tutorials/networking/high_level_multiplayer.rst b/tutorials/networking/high_level_multiplayer.rst index 56ccd4d26..cb741a9da 100644 --- a/tutorials/networking/high_level_multiplayer.rst +++ b/tutorials/networking/high_level_multiplayer.rst @@ -26,30 +26,30 @@ Because of the large difference in performance it often makes sense to re-build In summary you can use the low-level networking API for maximum control and implement everything on top of bare network protocols or use the high-level API based on :ref:`SceneTree ` that does most of the heavy lifting behind the scenes in a generally optimized way. .. note:: Most of Godot's supported platforms offer all or most of the mentioned high- and low-level networking - features. As networking is always largely hardware and operating system dependent, however, - some features may change or not be available on some target platforms. Most notably, - the HTML5 platform currently only offers WebSocket support and lacks some of the higher level features as - well as raw access to low-level protocols like TCP and UDP. + features. As networking is always largely hardware and operating system dependent, however, + some features may change or not be available on some target platforms. Most notably, + the HTML5 platform currently only offers WebSocket support and lacks some of the higher level features as + well as raw access to low-level protocols like TCP and UDP. .. note:: More about TCP/IP, UDP, and networking: - https://gafferongames.com/post/udp_vs_tcp/ - - Gaffer On Games has a lot of useful articles about networking in Games - (`here `__), including the comprehensive - `introduction to networking models in games `__. - - If you want to use your low-level networking library of choice instead of Godot's built-in networking, - see here for an example: - https://github.com/PerduGames/gdnet3 + https://gafferongames.com/post/udp_vs_tcp/ + + Gaffer On Games has a lot of useful articles about networking in Games + (`here `__), including the comprehensive + `introduction to networking models in games `__. + + If you want to use your low-level networking library of choice instead of Godot's built-in networking, + see here for an example: + https://github.com/PerduGames/gdnet3 .. warning:: Adding networking to your game comes with some responsibility. - It can make your application vulnerable if done wrong and may lead to cheats or exploits. - It may even allow an attacker to compromise the machines your application runs on - and use your servers to send spam, attack others or steal your users data if they play your game. - - This is always the case when networking is involved and has nothing to do with Godot. - You can of course experiment, but when you release a networked application, - always take care of any possible security concerns. + It can make your application vulnerable if done wrong and may lead to cheats or exploits. + It may even allow an attacker to compromise the machines your application runs on + and use your servers to send spam, attack others or steal your users data if they play your game. + + This is always the case when networking is involved and has nothing to do with Godot. + You can of course experiment, but when you release a networked application, + always take care of any possible security concerns. Mid level abstraction --------------------- @@ -276,7 +276,7 @@ every peer and RPC will work great! Here is an example: :: remote func pre_configure_game(): - var selfPeerID = get_tree().get_network_unique_id() + var selfPeerID = get_tree().get_network_unique_id() # Load world var world = load(which_level).instance() @@ -367,7 +367,7 @@ If you have paid attention to the previous example, it's possible you noticed th var player = preload("res://player.tscn").instance() player.set_name(str(p)) get_node("/root/world/players").add_child(player) - [...] + [...] Each time this piece of code is executed on each peer, the peer makes itself master on the node it controls, and all other nodes remain as puppets with the server being their network master. diff --git a/tutorials/networking/http_request_class.rst b/tutorials/networking/http_request_class.rst index 5fa95a0f3..9ea536252 100644 --- a/tutorials/networking/http_request_class.rst +++ b/tutorials/networking/http_request_class.rst @@ -28,14 +28,14 @@ Below is all the code we need to make it work. The URL points to an online API m extends CanvasLayer func _ready(): - pass + pass func _on_Button_pressed(): - $HTTPRequest.request("http://www.mocky.io/v2/5185415ba171ea3a00704eed") + $HTTPRequest.request("http://www.mocky.io/v2/5185415ba171ea3a00704eed") func _on_HTTPRequest_request_completed( result, response_code, headers, body ): - var json = JSON.parse(body.get_string_from_utf8()) - print(json.result) + var json = JSON.parse(body.get_string_from_utf8()) + print(json.result) With this, you should see ``(hello:world)`` printed on the console; hello being a key, and world being a value, both of them strings. diff --git a/tutorials/physics/physics_introduction.rst b/tutorials/physics/physics_introduction.rst index 56a65159b..6b749ed3c 100644 --- a/tutorials/physics/physics_introduction.rst +++ b/tutorials/physics/physics_introduction.rst @@ -398,22 +398,22 @@ the ground (including slopes) and jump when standing on the ground: var velocity = Vector2() func get_input(): - velocity.x = 0 - var right = Input.is_action_pressed('ui_right') - var left = Input.is_action_pressed('ui_left') - var jump = Input.is_action_just_pressed('ui_select') - - if is_on_floor() and jump: - velocity.y = jump_speed - if right: - velocity.x += run_speed - if left: - velocity.x -= run_speed - + velocity.x = 0 + var right = Input.is_action_pressed('ui_right') + var left = Input.is_action_pressed('ui_left') + var jump = Input.is_action_just_pressed('ui_select') + + if is_on_floor() and jump: + velocity.y = jump_speed + if right: + velocity.x += run_speed + if left: + velocity.x -= run_speed + func _physics_process(delta): - velocity.y += gravity * delta - get_input() - velocity = move_and_slide(velocity, Vector2(0, -1)) + velocity.y += gravity * delta + get_input() + velocity = move_and_slide(velocity, Vector2(0, -1)) .. code-tab:: csharp diff --git a/tutorials/physics/rigid_body.rst b/tutorials/physics/rigid_body.rst index eb866e316..4d409d17b 100644 --- a/tutorials/physics/rigid_body.rst +++ b/tutorials/physics/rigid_body.rst @@ -33,16 +33,16 @@ Here is a custom ``look_at()`` function that will work reliably with rigid bodie extends RigidBody func look_follow(state, current_transform, target_position): - var up_dir = Vector3(0, 1, 0) - var cur_dir = current_transform.basis.xform(Vector3(0, 0, 1)) - var target_dir = (target_position - current_transform.origin).normalized() - var rotation_angle = acos(cur_dir.x) - acos(target_dir.x) + var up_dir = Vector3(0, 1, 0) + var cur_dir = current_transform.basis.xform(Vector3(0, 0, 1)) + var target_dir = (target_position - current_transform.origin).normalized() + var rotation_angle = acos(cur_dir.x) - acos(target_dir.x) - state.set_angular_velocity(up_dir * (rotation_angle / state.get_step())) + state.set_angular_velocity(up_dir * (rotation_angle / state.get_step())) func _integrate_forces(state): - var target_position = $my_target_spatial_node.get_global_transform().origin - look_follow(state, get_global_transform(), target_position) + var target_position = $my_target_spatial_node.get_global_transform().origin + look_follow(state, get_global_transform(), target_position) .. code-tab:: csharp diff --git a/tutorials/plugins/editor/import_plugins.rst b/tutorials/plugins/editor/import_plugins.rst index f01d94393..ca44bb9ec 100644 --- a/tutorials/plugins/editor/import_plugins.rst +++ b/tutorials/plugins/editor/import_plugins.rst @@ -326,8 +326,8 @@ it sets the color as a pure red instead. :: - var material = SpatialMaterial.new() - material.albedo_color = color + var material = SpatialMaterial.new() + material.albedo_color = color This part makes a new :ref:`SpatialMaterial` that is the imported resource. We create a new instance of it and then set its albedo color diff --git a/tutorials/shading/screen-reading_shaders.rst b/tutorials/shading/screen-reading_shaders.rst index 5e11a13e9..62d8e85f6 100644 --- a/tutorials/shading/screen-reading_shaders.rst +++ b/tutorials/shading/screen-reading_shaders.rst @@ -27,9 +27,9 @@ the current fragment. As a result, this simple 2D fragment shader: .. code-block:: glsl - void fragment() {} - COLOR=textureLod( SCREEN_TEXTURE, SCREEN_UV, 0.0); - } + void fragment() {} + COLOR = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0); + } results in an invisible object, because it just shows what lies behind. @@ -49,21 +49,21 @@ and saturation: .. code-block:: glsl - shader_type canvas_item; + shader_type canvas_item; - uniform float brightness = 1.0; - uniform float contrast = 1.0; - uniform float saturation = 1.0; + uniform float brightness = 1.0; + uniform float contrast = 1.0; + uniform float saturation = 1.0; - void fragment() { - vec3 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0).rgb; + void fragment() { + vec3 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0).rgb; - c.rgb = mix(vec3(0.0), c.rgb, brightness); - c.rgb = mix(vec3(0.5), c.rgb, contrast); - c.rgb = mix(vec3(dot(vec3(1.0), c.rgb)*0.33333), c.rgb, saturation); + c.rgb = mix(vec3(0.0), c.rgb, brightness); + c.rgb = mix(vec3(0.5), c.rgb, contrast); + c.rgb = mix(vec3(dot(vec3(1.0), c.rgb) * 0.33333), c.rgb, saturation); - COLOR.rgb = c; - } + COLOR.rgb = c; + } Behind the scenes ~~~~~~~~~~~~~~~~~ @@ -130,9 +130,9 @@ converted via the inverse projection matrix. The following code retrieves the 3D position below the pixel being drawn: .. code-block:: glsl - - void fragment() { - float depth = textureLod(DEPTH_TEXTURE,SCREEN_UV,0.0).r; - vec4 upos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV*2.0-1.0,depth*2.0-1.0,1.0); - vec3 pixel_position = upos.xyz/upos.w; - } + + void fragment() { + float depth = textureLod(DEPTH_TEXTURE, SCREEN_UV, 0.0).r; + vec4 upos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0); + vec3 pixel_position = upos.xyz / upos.w; + } diff --git a/tutorials/shading/shading_language.rst b/tutorials/shading/shading_language.rst index b4427000b..59a9d5433 100644 --- a/tutorials/shading/shading_language.rst +++ b/tutorials/shading/shading_language.rst @@ -157,10 +157,10 @@ If a larger matrix is constructed from a smaller matrix, the additional rows and If a smaller matrix is constructed from a larger matrix, the top, left submatrix of the larger matrix is chosen. .. code-block:: glsl - - mat3 basis = mat3(WORLD_MATRIX); - mat4 m4 = mat4(basis); - mat2 m2 = mat2(m4); + + mat3 basis = mat3(WORLD_MATRIX); + mat4 m4 = mat4(basis); + mat2 m2 = mat2(m4); Swizzling ~~~~~~~~~ diff --git a/tutorials/viewports/custom_postprocessing.rst b/tutorials/viewports/custom_postprocessing.rst index 88fecedfb..20bc4d77c 100644 --- a/tutorials/viewports/custom_postprocessing.rst +++ b/tutorials/viewports/custom_postprocessing.rst @@ -77,16 +77,16 @@ Copy the following code to your shader. The above code is a single pass edge det shader_type canvas_item; void fragment() { - vec3 col = -8.0 * texture(TEXTURE, SCREEN_UV).xyz; - col += texture(TEXTURE, SCREEN_UV + vec2(0.0, SCREEN_PIXEL_SIZE.y)).xyz; - col += texture(TEXTURE, SCREEN_UV + vec2(0.0, -SCREEN_PIXEL_SIZE.y)).xyz; - col += texture(TEXTURE, SCREEN_UV + vec2(SCREEN_PIXEL_SIZE.x, 0.0)).xyz; - col += texture(TEXTURE, SCREEN_UV + vec2(-SCREEN_PIXEL_SIZE.x, 0.0)).xyz; - col += texture(TEXTURE, SCREEN_UV + SCREEN_PIXEL_SIZE.xy).xyz; - col += texture(TEXTURE, SCREEN_UV + SCREEN_PIXEL_SIZE.xy).xyz; - col += texture(TEXTURE, SCREEN_UV + vec2(-SCREEN_PIXEL_SIZE.x, SCREEN_PIXEL_SIZE.y)).xyz; - col += texture(TEXTURE, SCREEN_UV + vec2(SCREEN_PIXEL_SIZE.x, -SCREEN_PIXEL_SIZE.y)).xyz; - COLOR.xyz = col; + vec3 col = -8.0 * texture(TEXTURE, SCREEN_UV).xyz; + col += texture(TEXTURE, SCREEN_UV + vec2(0.0, SCREEN_PIXEL_SIZE.y)).xyz; + col += texture(TEXTURE, SCREEN_UV + vec2(0.0, -SCREEN_PIXEL_SIZE.y)).xyz; + col += texture(TEXTURE, SCREEN_UV + vec2(SCREEN_PIXEL_SIZE.x, 0.0)).xyz; + col += texture(TEXTURE, SCREEN_UV + vec2(-SCREEN_PIXEL_SIZE.x, 0.0)).xyz; + col += texture(TEXTURE, SCREEN_UV + SCREEN_PIXEL_SIZE.xy).xyz; + col += texture(TEXTURE, SCREEN_UV + SCREEN_PIXEL_SIZE.xy).xyz; + col += texture(TEXTURE, SCREEN_UV + vec2(-SCREEN_PIXEL_SIZE.x, SCREEN_PIXEL_SIZE.y)).xyz; + col += texture(TEXTURE, SCREEN_UV + vec2(SCREEN_PIXEL_SIZE.x, -SCREEN_PIXEL_SIZE.y)).xyz; + COLOR.xyz = col; } .. note:: @@ -135,16 +135,16 @@ does not matter: //Blurs the screen in the X-direction void fragment() { - vec3 col = texture(TEXTURE, SCREEN_UV).xyz * 0.16; - col += texture(TEXTURE, SCREEN_UV + vec2(SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.15; - col += texture(TEXTURE, SCREEN_UV + vec2(-SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.15; - col += texture(TEXTURE, SCREEN_UV + vec2(2.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.12; - col += texture(TEXTURE, SCREEN_UV + vec2(2.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.12; - col += texture(TEXTURE, SCREEN_UV + vec2(3.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.09; - col += texture(TEXTURE, SCREEN_UV + vec2(3.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.09; - col += texture(TEXTURE, SCREEN_UV + vec2(4.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.05; - col += texture(TEXTURE, SCREEN_UV + vec2(4.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.05; - COLOR.xyz = col; + vec3 col = texture(TEXTURE, SCREEN_UV).xyz * 0.16; + col += texture(TEXTURE, SCREEN_UV + vec2(SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.15; + col += texture(TEXTURE, SCREEN_UV + vec2(-SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.15; + col += texture(TEXTURE, SCREEN_UV + vec2(2.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.12; + col += texture(TEXTURE, SCREEN_UV + vec2(2.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.12; + col += texture(TEXTURE, SCREEN_UV + vec2(3.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.09; + col += texture(TEXTURE, SCREEN_UV + vec2(3.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.09; + col += texture(TEXTURE, SCREEN_UV + vec2(4.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.05; + col += texture(TEXTURE, SCREEN_UV + vec2(4.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.05; + COLOR.xyz = col; } :: @@ -153,16 +153,16 @@ does not matter: //Blurs the screen in the Y-direction void fragment() { - vec3 col = texture(TEXTURE, SCREEN_UV).xyz * 0.16; - col += texture(TEXTURE, SCREEN_UV + vec2(0.0, SCREEN_PIXEL_SIZE.y)).xyz * 0.15; - col += texture(TEXTURE, SCREEN_UV + vec2(0.0, -SCREEN_PIXEL_SIZE.y)).xyz * 0.15; - col += texture(TEXTURE, SCREEN_UV + vec2(0.0, 2.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.12; - col += texture(TEXTURE, SCREEN_UV + vec2(0.0, 2.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.12; - col += texture(TEXTURE, SCREEN_UV + vec2(0.0, 3.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.09; - col += texture(TEXTURE, SCREEN_UV + vec2(0.0, 3.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.09; - col += texture(TEXTURE, SCREEN_UV + vec2(0.0, 4.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.05; - col += texture(TEXTURE, SCREEN_UV + vec2(0.0, 4.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.05; - COLOR.xyz = col; + vec3 col = texture(TEXTURE, SCREEN_UV).xyz * 0.16; + col += texture(TEXTURE, SCREEN_UV + vec2(0.0, SCREEN_PIXEL_SIZE.y)).xyz * 0.15; + col += texture(TEXTURE, SCREEN_UV + vec2(0.0, -SCREEN_PIXEL_SIZE.y)).xyz * 0.15; + col += texture(TEXTURE, SCREEN_UV + vec2(0.0, 2.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.12; + col += texture(TEXTURE, SCREEN_UV + vec2(0.0, 2.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.12; + col += texture(TEXTURE, SCREEN_UV + vec2(0.0, 3.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.09; + col += texture(TEXTURE, SCREEN_UV + vec2(0.0, 3.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.09; + col += texture(TEXTURE, SCREEN_UV + vec2(0.0, 4.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.05; + col += texture(TEXTURE, SCREEN_UV + vec2(0.0, 4.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.05; + COLOR.xyz = col; } Using the above code you should end up with a full screen blur effect like below. diff --git a/tutorials/viewports/using_viewport_as_texture.rst b/tutorials/viewports/using_viewport_as_texture.rst index f3001c6f3..a1a929aa1 100644 --- a/tutorials/viewports/using_viewport_as_texture.rst +++ b/tutorials/viewports/using_viewport_as_texture.rst @@ -52,16 +52,16 @@ will ensure that the :ref:`ColorRect ` takes up the entire :ref Next, we add a :ref:`Shader Material ` to the :ref:`ColorRect `. -.. note:: I'm assuming you are familiar with the basics of shading for this tutorial. Even if you aren't, all the code +.. note:: We are assuming you are familiar with the basics of shading for this tutorial. Even if you aren't, all the code will still be provided so you should have no problem following along. :: - shader_type canvas_item + shader_type canvas_item - void fragment() { - COLOR = vec4(UV.x, UV.y, 0.5, 1.0); - } + void fragment() { + COLOR = vec4(UV.x, UV.y, 0.5, 1.0); + } The above code renders a gradient like the one below. @@ -107,7 +107,7 @@ the sphere in a nice way? One solution is to use a function that repeats on the :: - COLOR.xyz = vec3(sin(UV.x * 3.14159 * 4.0) * cos(UV.y * 3.14159 * 4.0) * 0.5 + 0.5); + COLOR.xyz = vec3(sin(UV.x * 3.14159 * 4.0) * cos(UV.y * 3.14159 * 4.0) * 0.5 + 0.5); .. image:: img/planet_sincos.png @@ -118,8 +118,8 @@ projection. Which translates a spherical map onto a 2D plane. .. note:: If you are interested in a little extra information on the technique, we will be converting from spherical coordinates into Cartesian coordinates. Spherical coordinates map the longitude and - latitude of the sphere, while Cartesian coordinates are for all intents and purposes a - vector from the center of the sphere to the point. + latitude of the sphere, while Cartesian coordinates are for all intents and purposes a + vector from the center of the sphere to the point. For each pixel we will calculate its 3D position on the sphere. From that we will use 3D noise to determine a color value. By calculating the noise in 3D we solve the problem @@ -131,14 +131,14 @@ coordinates. :: - float theta = UV.y * 3.14159; - float phi = UV.x * 3.14159 * 2.0; - vec3 unit = vec3(0.0, 0.0, 0.0); + float theta = UV.y * 3.14159; + float phi = UV.x * 3.14159 * 2.0; + vec3 unit = vec3(0.0, 0.0, 0.0); - unit.x = sin(phi) * sin(theta); - unit.y = cos(theta) * -1.0; - unit.z = cos(phi) * sin(theta); - unit = normalize(unit); + unit.x = sin(phi) * sin(theta); + unit.y = cos(theta) * -1.0; + unit.z = cos(phi) * sin(theta); + unit = normalize(unit); And if we use ``unit`` as an output ``COLOR`` value we get. @@ -149,62 +149,64 @@ to make the planet. We will be using this noise function directly from a `Shader :: - vec3 hash( vec3 p ) { - p = vec3( dot(p,vec3(127.1, 311.7, 74.7)), - dot(p,vec3(269.5, 183.3, 246.1)), - dot(p,vec3(113.5, 271.9, 124.6))); + vec3 hash(vec3 p) { + p = vec3(dot(p, vec3(127.1, 311.7, 74.7)), + dot(p, vec3(269.5, 183.3, 246.1)), + dot(p, vec3(113.5, 271.9, 124.6))); - return -1.0 + 2.0 * fract(sin(p) * 43758.5453123); - } + return -1.0 + 2.0 * fract(sin(p) * 43758.5453123); + } - // return value noise (in x) and its derivatives (in yzw) - vec4 noised( in vec3 x ) { - // grid - vec3 p = floor(x); - vec3 w = fract(x); - - // quintic interpolant - vec3 u = w * w * w * (w * (w * 6.0 - 15.0) + 10.0); - vec3 du = 30.0 * w * w * (w * (w - 2.0) + 1.0); - - // gradients - vec3 ga = hash( p + vec3(0.0, 0.0, 0.0) ); - vec3 gb = hash( p + vec3(1.0, 0.0, 0.0) ); - vec3 gc = hash( p + vec3(0.0, 1.0, 0.0) ); - vec3 gd = hash( p + vec3(1.0, 1.0, 0.0) ); - vec3 ge = hash( p + vec3(0.0, 0.0, 1.0) ); - vec3 gf = hash( p + vec3(1.0, 0.0, 1.0) ); - vec3 gg = hash( p + vec3(0.0, 1.0, 1.0) ); - vec3 gh = hash( p + vec3(1.0, 1.0, 1.0) ); - - // projections - float va = dot( ga, w - vec3(0.0, 0.0, 0.0) ); - float vb = dot( gb, w - vec3(1.0, 0.0, 0.0) ); - float vc = dot( gc, w - vec3(0.0, 1.0, 0.0) ); - float vd = dot( gd, w - vec3(1.0, 1.0, 0.0) ); - float ve = dot( ge, w - vec3(0.0, 0.0, 1.0) ); - float vf = dot( gf, w - vec3(1.0, 0.0, 1.0) ); - float vg = dot( gg, w - vec3(0.0, 1.0, 1.0) ); - float vh = dot( gh, w - vec3(1.0, 1.0, 1.0) ); - - // interpolations - return vec4( va + u.x*(vb-va) + u.y*(vc-va) + u.z*(ve-va) + u.x*u.y*(va-vb-vc+vd) + u.y*u.z*(va-vc-ve+vg) + u.z*u.x*(va-vb-ve+vf) + (-va+vb+vc-vd+ve-vf-vg+vh)*u.x*u.y*u.z, // value - ga + u.x*(gb-ga) + u.y*(gc-ga) + u.z*(ge-ga) + u.x*u.y*(ga-gb-gc+gd) + u.y*u.z*(ga-gc-ge+gg) + u.z*u.x*(ga-gb-ge+gf) + (-ga+gb+gc-gd+ge-gf-gg+gh)*u.x*u.y*u.z + // derivatives - du * (vec3(vb,vc,ve) - va + u.yzx*vec3(va-vb-vc+vd,va-vc-ve+vg,va-vb-ve+vf) + u.zxy*vec3(va-vb-ve+vf,va-vb-vc+vd,va-vc-ve+vg) + u.yzx*u.zxy*(-va+vb+vc-vd+ve-vf-vg+vh) )); - } + // return value noise (in x) and its derivatives (in yzw) + vec4 noised(in vec3 x) { + // grid + vec3 p = floor(x); + vec3 w = fract(x); + + // quintic interpolant + vec3 u = w * w * w * (w * (w * 6.0 - 15.0) + 10.0); + vec3 du = 30.0 * w * w * (w * (w - 2.0) + 1.0); + + // gradients + vec3 ga = hash(p + vec3(0.0, 0.0, 0.0)); + vec3 gb = hash(p + vec3(1.0, 0.0, 0.0)); + vec3 gc = hash(p + vec3(0.0, 1.0, 0.0)); + vec3 gd = hash(p + vec3(1.0, 1.0, 0.0)); + vec3 ge = hash(p + vec3(0.0, 0.0, 1.0)); + vec3 gf = hash(p + vec3(1.0, 0.0, 1.0)); + vec3 gg = hash(p + vec3(0.0, 1.0, 1.0)); + vec3 gh = hash(p + vec3(1.0, 1.0, 1.0)); + + // projections + float va = dot(ga, w - vec3(0.0, 0.0, 0.0)); + float vb = dot(gb, w - vec3(1.0, 0.0, 0.0)); + float vc = dot(gc, w - vec3(0.0, 1.0, 0.0)); + float vd = dot(gd, w - vec3(1.0, 1.0, 0.0)); + float ve = dot(ge, w - vec3(0.0, 0.0, 1.0)); + float vf = dot(gf, w - vec3(1.0, 0.0, 1.0)); + float vg = dot(gg, w - vec3(0.0, 1.0, 1.0)); + float vh = dot(gh, w - vec3(1.0, 1.0, 1.0)); + + // interpolations + return vec4( + va + u.x*(vb-va) + u.y*(vc-va) + u.z*(ve-va) + u.x*u.y*(va-vb-vc+vd) + u.y*u.z*(va-vc-ve+vg) + u.z*u.x*(va-vb-ve+vf) + (-va+vb+vc-vd+ve-vf-vg+vh)*u.x*u.y*u.z, // value + ga + u.x*(gb-ga) + u.y*(gc-ga) + u.z*(ge-ga) + u.x*u.y*(ga-gb-gc+gd) + u.y*u.z*(ga-gc-ge+gg) + u.z*u.x*(ga-gb-ge+gf) + (-ga+gb+gc-gd+ge-gf-gg+gh)*u.x*u.y*u.z + // derivatives + du * (vec3(vb,vc,ve) - va + u.yzx*vec3(va-vb-vc+vd,va-vc-ve+vg,va-vb-ve+vf) + u.zxy*vec3(va-vb-ve+vf,va-vb-vc+vd,va-vc-ve+vg) + u.yzx*u.zxy*(-va+vb+vc-vd+ve-vf-vg+vh)) + ); + } .. note:: All credit goes to the initial author Inigo Quilez. It is published with the ``MIT`` licence. -Now to use ``noised``, add the following to the ``fragment`` function: +Now to use ``noised``, add the following to the ``fragment`` function: :: - vec4 n = noised(unit * 5.0); - COLOR.xyz = vec3(n.x * 0.5 + 0.5); + vec4 n = noised(unit * 5.0); + COLOR.xyz = vec3(n.x * 0.5 + 0.5); .. image:: img/planet_noise.png -.. note:: In order to highlight the texture, I have set the material to unshaded. +.. note:: In order to highlight the texture, we set the material to unshaded. You can see now that the noise indeed wraps seamlessly around the sphere. Although this looks nothing like the planet you were promised. So lets move onto something more colorful. @@ -224,7 +226,7 @@ values whether it be floats or vector types. :: - COLOR.xyz = mix(vec3(0.05, 0.3, 0.5), vec3(0.9, 0.4, 0.1), n.x * 0.5 + 0.5); + COLOR.xyz = mix(vec3(0.05, 0.3, 0.5), vec3(0.9, 0.4, 0.1), n.x * 0.5 + 0.5); The first color is blue for the ocean. The second color is a kind of reddish color (because all alien planets need red terrain). And finally they are mixed together by ``n.x * 0.5 + 0.5``. @@ -239,7 +241,7 @@ And thus the whole line becomes: :: - COLOR.xyz = mix(vec3(0.05, 0.3, 0.5), vec3(0.9, 0.4, 0.1), smoothstep(-0.1, 0.0, n.x)); + COLOR.xyz = mix(vec3(0.05, 0.3, 0.5), vec3(0.9, 0.4, 0.1), smoothstep(-0.1, 0.0, n.x)); What ``smoothstep`` does is return ``0`` if the third parameter is below the first and return 1 if the third parameter is larger than the second and smoothly blends between ``0`` and ``1`` if the third number @@ -257,10 +259,10 @@ instead of just one. ``n`` becomes: :: - vec4 n = noised(unit * 5.0) * 0.5; - n += noised(unit * 10.0) * 0.25; - n += noised(unit * 20.0) * 0.125; - n += noised(unit * 40.0) * 0.0625; + vec4 n = noised(unit * 5.0) * 0.5; + n += noised(unit * 10.0) * 0.25; + n += noised(unit * 20.0) * 0.125; + n += noised(unit * 40.0) * 0.0625; And now the planet looks like: @@ -279,7 +281,7 @@ into the ``alpha`` channel of our output ``COLOR`` and using it as a Roughness m :: - COLOR.a = 0.3 + 0.7 * smoothstep(-0.1, 0.0, n.x); + COLOR.a = 0.3 + 0.7 * smoothstep(-0.1, 0.0, n.x); This line returns ``0.3`` for water and ``1.0`` for land. This means that the land is going to be quite rough while the water will be quite smooth. @@ -306,7 +308,7 @@ rendering one transparent object on top of another we want to enable ``blend_pre :: - render_mode blend_premul_alpha; + render_mode blend_premul_alpha; This pre-multiplies the colors by the ``alpha`` value and then blends them correctly together. Typically when blending one transparent color on top of another, even if the background has an ``alpha`` of ``0`` (as it