Path: blob/master/scene/resources/3d/fog_material.cpp
9898 views
/**************************************************************************/1/* fog_material.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "fog_material.h"3132#include "core/version.h"3334Mutex FogMaterial::shader_mutex;35RID FogMaterial::shader;3637void FogMaterial::set_density(float p_density) {38density = p_density;39RS::get_singleton()->material_set_param(_get_material(), "density", density);40}4142float FogMaterial::get_density() const {43return density;44}4546void FogMaterial::set_albedo(Color p_albedo) {47albedo = p_albedo;48RS::get_singleton()->material_set_param(_get_material(), "albedo", albedo);49}5051Color FogMaterial::get_albedo() const {52return albedo;53}5455void FogMaterial::set_emission(Color p_emission) {56emission = p_emission;57RS::get_singleton()->material_set_param(_get_material(), "emission", emission);58}5960Color FogMaterial::get_emission() const {61return emission;62}6364void FogMaterial::set_height_falloff(float p_falloff) {65height_falloff = MAX(p_falloff, 0.0f);66RS::get_singleton()->material_set_param(_get_material(), "height_falloff", height_falloff);67}6869float FogMaterial::get_height_falloff() const {70return height_falloff;71}7273void FogMaterial::set_edge_fade(float p_edge_fade) {74edge_fade = MAX(p_edge_fade, 0.0f);75RS::get_singleton()->material_set_param(_get_material(), "edge_fade", edge_fade);76}7778float FogMaterial::get_edge_fade() const {79return edge_fade;80}8182void FogMaterial::set_density_texture(const Ref<Texture3D> &p_texture) {83density_texture = p_texture;84Variant tex_rid = p_texture.is_valid() ? Variant(p_texture->get_rid()) : Variant();85RS::get_singleton()->material_set_param(_get_material(), "density_texture", tex_rid);86}8788Ref<Texture3D> FogMaterial::get_density_texture() const {89return density_texture;90}9192Shader::Mode FogMaterial::get_shader_mode() const {93return Shader::MODE_FOG;94}9596RID FogMaterial::get_shader_rid() const {97_update_shader();98return shader;99}100101RID FogMaterial::get_rid() const {102_update_shader();103if (!shader_set) {104RS::get_singleton()->material_set_shader(_get_material(), shader);105shader_set = true;106}107return _get_material();108}109110void FogMaterial::_bind_methods() {111ClassDB::bind_method(D_METHOD("set_density", "density"), &FogMaterial::set_density);112ClassDB::bind_method(D_METHOD("get_density"), &FogMaterial::get_density);113ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &FogMaterial::set_albedo);114ClassDB::bind_method(D_METHOD("get_albedo"), &FogMaterial::get_albedo);115ClassDB::bind_method(D_METHOD("set_emission", "emission"), &FogMaterial::set_emission);116ClassDB::bind_method(D_METHOD("get_emission"), &FogMaterial::get_emission);117ClassDB::bind_method(D_METHOD("set_height_falloff", "height_falloff"), &FogMaterial::set_height_falloff);118ClassDB::bind_method(D_METHOD("get_height_falloff"), &FogMaterial::get_height_falloff);119ClassDB::bind_method(D_METHOD("set_edge_fade", "edge_fade"), &FogMaterial::set_edge_fade);120ClassDB::bind_method(D_METHOD("get_edge_fade"), &FogMaterial::get_edge_fade);121ClassDB::bind_method(D_METHOD("set_density_texture", "density_texture"), &FogMaterial::set_density_texture);122ClassDB::bind_method(D_METHOD("get_density_texture"), &FogMaterial::get_density_texture);123124ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "density", PROPERTY_HINT_RANGE, "-8.0,8.0,0.0001,or_greater,or_less"), "set_density", "get_density");125ADD_PROPERTY(PropertyInfo(Variant::COLOR, "albedo", PROPERTY_HINT_COLOR_NO_ALPHA), "set_albedo", "get_albedo");126ADD_PROPERTY(PropertyInfo(Variant::COLOR, "emission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_emission", "get_emission");127ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height_falloff", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_height_falloff", "get_height_falloff");128ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_fade", PROPERTY_HINT_EXP_EASING), "set_edge_fade", "get_edge_fade");129ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "density_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_density_texture", "get_density_texture");130}131132void FogMaterial::cleanup_shader() {133if (shader.is_valid()) {134ERR_FAIL_NULL(RenderingServer::get_singleton());135RS::get_singleton()->free(shader);136}137}138139void FogMaterial::_update_shader() {140MutexLock shader_lock(shader_mutex);141if (shader.is_null()) {142shader = RS::get_singleton()->shader_create();143144// Add a comment to describe the shader origin (useful when converting to ShaderMaterial).145RS::get_singleton()->shader_set_code(shader, R"(146// NOTE: Shader automatically converted from )" GODOT_VERSION_NAME " " GODOT_VERSION_FULL_CONFIG R"('s FogMaterial.147148shader_type fog;149150uniform float density : hint_range(0, 1, 0.0001) = 1.0;151uniform vec4 albedo : source_color = vec4(1.0);152uniform vec4 emission : source_color = vec4(0, 0, 0, 1);153uniform float height_falloff = 0.0;154uniform float edge_fade = 0.1;155uniform sampler3D density_texture: hint_default_white;156157158void fog() {159DENSITY = density * clamp(exp2(-height_falloff * (WORLD_POSITION.y - OBJECT_POSITION.y)), 0.0, 1.0);160DENSITY *= texture(density_texture, UVW).r;161DENSITY *= pow(clamp(-2.0 * SDF / min(min(SIZE.x, SIZE.y), SIZE.z), 0.0, 1.0), edge_fade);162ALBEDO = albedo.rgb;163EMISSION = emission.rgb;164}165)");166}167}168169FogMaterial::FogMaterial() {170_set_material(RS::get_singleton()->material_create());171172set_density(1.0);173set_albedo(Color(1, 1, 1, 1));174set_emission(Color(0, 0, 0, 1));175176set_height_falloff(0.0);177set_edge_fade(0.1);178}179180FogMaterial::~FogMaterial() {181RS::get_singleton()->material_set_shader(_get_material(), RID());182}183184185