mirror of
https://github.com/minetest/minetest.git
synced 2024-06-30 21:20:36 +02:00
Compare commits
18 Commits
aa41e44265
...
7f588a2963
Author | SHA1 | Date | |
---|---|---|---|
|
7f588a2963 | ||
|
9a1501ae89 | ||
|
514e106414 | ||
|
b08ee987a6 | ||
|
d3b63ba06f | ||
|
385bb3c801 | ||
|
56392c2d08 | ||
|
80418e0069 | ||
|
698a63cc5c | ||
|
1aa03addec | ||
|
4a351df32b | ||
|
41ab0eb0fd | ||
|
8a7676d2f6 | ||
|
811f5bacde | ||
|
220ece672c | ||
|
ff7ba2b7a1 | ||
|
17a75185e1 | ||
|
02d0c826fe |
@ -38,6 +38,7 @@ varying vec3 vPosition;
|
||||
// precision must be considered).
|
||||
varying vec3 worldPosition;
|
||||
varying lowp vec4 varColor;
|
||||
varying lowp vec3 hwColor;
|
||||
#ifdef GL_ES
|
||||
varying mediump vec2 varTexCoord;
|
||||
#else
|
||||
@ -375,7 +376,7 @@ void main(void)
|
||||
#endif
|
||||
|
||||
color = base.rgb;
|
||||
vec4 col = vec4(color.rgb * varColor.rgb, 1.0);
|
||||
vec4 col = vec4(color * hwColor * varColor.rgb, 1.0);
|
||||
|
||||
#ifdef ENABLE_DYNAMIC_SHADOWS
|
||||
if (f_shadow_strength > 0.0) {
|
||||
|
@ -6,6 +6,8 @@ uniform vec3 dayLight;
|
||||
uniform highp vec3 cameraOffset;
|
||||
uniform float animationTimer;
|
||||
|
||||
uniform vec3 ambientLight;
|
||||
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vPosition;
|
||||
// World position in the visible world (i.e. relative to the cameraOffset.)
|
||||
@ -15,6 +17,7 @@ varying vec3 vPosition;
|
||||
// precision must be considered).
|
||||
varying vec3 worldPosition;
|
||||
varying lowp vec4 varColor;
|
||||
varying lowp vec3 hwColor;
|
||||
// The centroid keyword ensures that after interpolation the texture coordinates
|
||||
// lie within the same bounds when MSAA is en- and disabled.
|
||||
// This fixes the stripes problem with nearest-neighbor textures and MSAA.
|
||||
@ -220,8 +223,12 @@ void main(void)
|
||||
color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) +
|
||||
0.07 * brightness);
|
||||
|
||||
color.rgb += ambientLight;
|
||||
|
||||
varColor = clamp(color, 0.0, 1.0);
|
||||
|
||||
hwColor = inVertexTangent.xyz;
|
||||
|
||||
#ifdef ENABLE_DYNAMIC_SHADOWS
|
||||
if (f_shadow_strength > 0.0) {
|
||||
#if MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS
|
||||
|
@ -2,6 +2,7 @@ uniform mat4 mWorld;
|
||||
uniform vec3 dayLight;
|
||||
uniform float animationTimer;
|
||||
uniform lowp vec4 emissiveColor;
|
||||
uniform vec3 ambientLight;
|
||||
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vPosition;
|
||||
@ -129,6 +130,8 @@ void main(void)
|
||||
color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) +
|
||||
0.07 * brightness);
|
||||
|
||||
color.rgb += ambientLight;
|
||||
|
||||
varColor = clamp(color, 0.0, 1.0);
|
||||
|
||||
|
||||
|
@ -3902,6 +3902,7 @@ Operators
|
||||
---------
|
||||
|
||||
Operators can be used if all of the involved vectors have metatables:
|
||||
|
||||
* `v1 == v2`:
|
||||
* Returns whether `v1` and `v2` are identical.
|
||||
* `-v`:
|
||||
@ -8408,6 +8409,14 @@ child will follow movement and rotation of that bone.
|
||||
* `set_lighting(light_definition)`: sets lighting for the player
|
||||
* Passing no arguments resets lighting to its default values.
|
||||
* `light_definition` is a table with the following optional fields:
|
||||
* `ambient_light` is a ColorSpec controlling color of global ambient light;
|
||||
(default: `{a = 255, r = 0, g = 0, b = 0}` / last set value).
|
||||
* It works only if shaders are enabled.
|
||||
* Alpha is ignored (it is always set to 255).
|
||||
* Note: Total light is clamped before being applied.
|
||||
This means that when an object is fully lit, ambient light
|
||||
will take no effect. Setting ambient light to `"#FFFFFF"`
|
||||
will make all objects be fully lit at all times ("fullbright").
|
||||
* `saturation` sets the saturation (vividness; default: `1.0`).
|
||||
* values > 1 increase the saturation
|
||||
* values in [0,1] decrease the saturation
|
||||
|
@ -14,6 +14,14 @@ local lighting_sections = {
|
||||
{n = "speed_bright_dark", d = "Dark scene adaptation speed", min = -10, max = 10, type="log2"},
|
||||
{n = "center_weight_power", d = "Power factor for center-weighting", min = 0.1, max = 10},
|
||||
}
|
||||
},
|
||||
{
|
||||
n = "ambient_light", d = "Ambient Light",
|
||||
entries = {
|
||||
{n = "r", d = "Red", min = 0, max = 255},
|
||||
{n = "g", d = "Green", min = 0, max = 255},
|
||||
{n = "b", d = "Blue", min = 0, max = 255}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,7 +69,7 @@ minetest.register_chatcommand("set_lighting", {
|
||||
|
||||
local form = {
|
||||
"formspec_version[2]",
|
||||
"size[15,30]",
|
||||
"size[15,32]",
|
||||
"position[0.99,0.15]",
|
||||
"anchor[1,0]",
|
||||
"padding[0.05,0.1]",
|
||||
@ -137,4 +145,4 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
player:hud_change(hud_id, "text", debug_value)
|
||||
|
||||
player:set_lighting(lighting)
|
||||
end)
|
||||
end)
|
||||
|
@ -129,9 +129,9 @@ EM_BOOL CIrrDeviceSDL::MouseLeaveCallback(int eventType, const EmscriptenMouseEv
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE key)
|
||||
bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE irrlichtKey)
|
||||
{
|
||||
switch (key) {
|
||||
switch (irrlichtKey) {
|
||||
// keys which are known to have safe special character interpretation
|
||||
// could need changes over time (removals and additions!)
|
||||
case KEY_RETURN:
|
||||
@ -189,24 +189,68 @@ bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE key)
|
||||
}
|
||||
}
|
||||
|
||||
int CIrrDeviceSDL::findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key)
|
||||
int CIrrDeviceSDL::findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtKey, bool numlock)
|
||||
{
|
||||
switch (irrlichtKey) {
|
||||
// special cases that always return a char regardless of how the SDL keycode
|
||||
// looks
|
||||
switch (key) {
|
||||
case KEY_RETURN:
|
||||
case KEY_ESCAPE:
|
||||
return (int)key;
|
||||
return (int)irrlichtKey;
|
||||
|
||||
// This is necessary for keys on the numpad because they don't use the same
|
||||
// keycodes as their non-numpad versions (whose keycodes correspond to chars),
|
||||
// but have their own SDL keycodes and their own Irrlicht keycodes (which
|
||||
// don't correspond to chars).
|
||||
case KEY_MULTIPLY:
|
||||
return '*';
|
||||
case KEY_ADD:
|
||||
return '+';
|
||||
case KEY_SUBTRACT:
|
||||
return '-';
|
||||
case KEY_DIVIDE:
|
||||
return '/';
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (numlock) {
|
||||
// Number keys on the numpad are also affected, but we only want them
|
||||
// to produce number chars when numlock is enabled.
|
||||
switch (irrlichtKey) {
|
||||
case KEY_NUMPAD0:
|
||||
return '0';
|
||||
case KEY_NUMPAD1:
|
||||
return '1';
|
||||
case KEY_NUMPAD2:
|
||||
return '2';
|
||||
case KEY_NUMPAD3:
|
||||
return '3';
|
||||
case KEY_NUMPAD4:
|
||||
return '4';
|
||||
case KEY_NUMPAD5:
|
||||
return '5';
|
||||
case KEY_NUMPAD6:
|
||||
return '6';
|
||||
case KEY_NUMPAD7:
|
||||
return '7';
|
||||
case KEY_NUMPAD8:
|
||||
return '8';
|
||||
case KEY_NUMPAD9:
|
||||
return '9';
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// SDL in-place ORs values with no character representation with 1<<30
|
||||
// https://wiki.libsdl.org/SDL2/SDLKeycodeLookup
|
||||
if (assumedChar & (1 << 30))
|
||||
// This also affects the numpad keys btw.
|
||||
if (sdlKey & (1 << 30))
|
||||
return 0;
|
||||
|
||||
switch (key) {
|
||||
switch (irrlichtKey) {
|
||||
case KEY_PRIOR:
|
||||
case KEY_NEXT:
|
||||
case KEY_HOME:
|
||||
@ -218,7 +262,7 @@ int CIrrDeviceSDL::findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key)
|
||||
case KEY_NUMLOCK:
|
||||
return 0;
|
||||
default:
|
||||
return assumedChar;
|
||||
return sdlKey;
|
||||
}
|
||||
}
|
||||
|
||||
@ -825,7 +869,8 @@ bool CIrrDeviceSDL::run()
|
||||
irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN);
|
||||
irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0;
|
||||
irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL) != 0;
|
||||
irrevent.KeyInput.Char = findCharToPassToIrrlicht(mp.SDLKey, key);
|
||||
irrevent.KeyInput.Char = findCharToPassToIrrlicht(mp.SDLKey, key,
|
||||
(SDL_event.key.keysym.mod & KMOD_NUM) != 0);
|
||||
postEventFromUser(irrevent);
|
||||
} break;
|
||||
|
||||
|
@ -273,10 +273,10 @@ class CIrrDeviceSDL : public CIrrDeviceStub
|
||||
|
||||
#endif
|
||||
// Check if a key is a known special character with no side effects on text boxes.
|
||||
static bool keyIsKnownSpecial(EKEY_CODE key);
|
||||
static bool keyIsKnownSpecial(EKEY_CODE irrlichtKey);
|
||||
|
||||
// Return the Char that should be sent to Irrlicht for the given key (either the one passed in or 0).
|
||||
static int findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key);
|
||||
static int findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtKey, bool numlock);
|
||||
|
||||
// Check if a text box is in focus. Enable or disable SDL_TEXTINPUT events only if in focus.
|
||||
void resetReceiveTextInputEvents();
|
||||
|
@ -57,6 +57,7 @@ set(client_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/inputhandler.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/joystick_controller.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/keycode.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/light_colors.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/localplayer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mapblock_mesh.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh.cpp
|
||||
|
@ -139,7 +139,7 @@ void Camera::step(f32 dtime)
|
||||
|
||||
if (m_wield_change_timer >= 0 && was_under_zero) {
|
||||
m_wieldnode->setItem(m_wield_item_next, m_client);
|
||||
m_wieldnode->setNodeLightColor(m_player_light_color);
|
||||
m_wieldnode->setColor(m_player_light_color);
|
||||
}
|
||||
|
||||
if (m_view_bobbing_state != 0)
|
||||
@ -552,7 +552,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 tool_reload_ratio)
|
||||
m_wieldnode->setRotation(wield_rotation);
|
||||
|
||||
m_player_light_color = player->light_color;
|
||||
m_wieldnode->setNodeLightColor(m_player_light_color);
|
||||
m_wieldnode->setColor(m_player_light_color);
|
||||
|
||||
// Set render distance
|
||||
updateViewingRange();
|
||||
|
@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "porting.h"
|
||||
#include <algorithm>
|
||||
#include "client/renderingengine.h"
|
||||
#include "light_colors.h"
|
||||
|
||||
/*
|
||||
ClientEnvironment
|
||||
@ -262,7 +263,11 @@ void ClientEnvironment::step(float dtime)
|
||||
|
||||
u16 light = getInteriorLight(node_at_lplayer, 0, m_client->ndef());
|
||||
lplayer->light_color = encode_light(light, 0); // this transfers light.alpha
|
||||
final_color_blend(&lplayer->light_color, light, day_night_ratio);
|
||||
|
||||
video::SColor ambient_light = g_settings->getBool("enable_shaders") ?
|
||||
lplayer->getLighting().ambient_light : video::SColor(255, 0, 0, 0);
|
||||
|
||||
final_color_blend(&lplayer->light_color, light, day_night_ratio, ambient_light);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -48,6 +48,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "client/shader.h"
|
||||
#include "client/minimap.h"
|
||||
#include <quaternion.h>
|
||||
#include "light_colors.h"
|
||||
|
||||
class Settings;
|
||||
struct ToolCapabilities;
|
||||
@ -921,7 +922,7 @@ void GenericCAO::setNodeLight(const video::SColor &light_color)
|
||||
{
|
||||
if (m_prop.visual == "wielditem" || m_prop.visual == "item") {
|
||||
if (m_wield_meshnode)
|
||||
m_wield_meshnode->setNodeLightColor(light_color);
|
||||
m_wield_meshnode->setColor(light_color);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "client/renderingengine.h"
|
||||
#include "client.h"
|
||||
#include "noise.h"
|
||||
#include "light_colors.h"
|
||||
|
||||
// Distance of light extrapolation (for oversized nodes)
|
||||
// After this distance, it gives up and considers light level constant
|
||||
|
@ -79,6 +79,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "hud.h"
|
||||
#include "clientdynamicinfo.h"
|
||||
#include <IAnimatedMeshSceneNode.h>
|
||||
#include "light_colors.h"
|
||||
|
||||
#if USE_SOUND
|
||||
#include "client/sound/sound_openal.h"
|
||||
@ -382,6 +383,7 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
|
||||
CachedPixelShaderSetting<float>
|
||||
m_animation_timer_delta_pixel{"animationTimerDelta"};
|
||||
CachedPixelShaderSetting<float, 3> m_day_light{"dayLight"};
|
||||
CachedVertexShaderSetting<float, 3> m_ambient_light{"ambientLight"};
|
||||
CachedPixelShaderSetting<float, 3> m_minimap_yaw{"yawVec"};
|
||||
CachedPixelShaderSetting<float, 3> m_camera_offset_pixel{"cameraOffset"};
|
||||
CachedVertexShaderSetting<float, 3> m_camera_offset_vertex{"cameraOffset"};
|
||||
@ -473,6 +475,11 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
|
||||
get_sunlight_color(&sunlight, daynight_ratio);
|
||||
m_day_light.set(sunlight, services);
|
||||
|
||||
Lighting &lighting = m_client->getEnv().getLocalPlayer()->getLighting();
|
||||
|
||||
video::SColorf ambient_light_f(lighting.ambient_light);
|
||||
m_ambient_light.set(ambient_light_f, services);
|
||||
|
||||
u32 animation_timer = m_client->getEnv().getFrameTime() % 1000000;
|
||||
float animation_timer_f = (float)animation_timer / 100000.f;
|
||||
m_animation_timer_vertex.set(&animation_timer_f, services);
|
||||
@ -504,7 +511,7 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
|
||||
m_texel_size0_vertex.set(m_texel_size0, services);
|
||||
m_texel_size0_pixel.set(m_texel_size0, services);
|
||||
|
||||
const AutoExposure &exposure_params = m_client->getEnv().getLocalPlayer()->getLighting().exposure;
|
||||
const AutoExposure &exposure_params = lighting.exposure;
|
||||
std::array<float, 7> exposure_buffer = {
|
||||
std::pow(2.0f, exposure_params.luminance_min),
|
||||
std::pow(2.0f, exposure_params.luminance_max),
|
||||
@ -522,7 +529,6 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
|
||||
m_bloom_strength_pixel.set(&m_bloom_strength, services);
|
||||
}
|
||||
|
||||
const auto &lighting = m_client->getEnv().getLocalPlayer()->getLighting();
|
||||
float saturation = lighting.saturation;
|
||||
m_saturation_pixel.set(&saturation, services);
|
||||
|
||||
@ -1446,7 +1452,7 @@ void Game::copyServerClientCache()
|
||||
{
|
||||
// It would be possible to let the client directly read the media files
|
||||
// from where the server knows they are. But aside from being more complicated
|
||||
// it would also *not* fill the media cache and cause slower joining of
|
||||
// it would also *not* fill the media cache and cause slower joining of
|
||||
// remote servers.
|
||||
// (Imagine that you launch a game once locally and then connect to a server.)
|
||||
|
||||
|
@ -1139,9 +1139,9 @@ void drawItemStack(
|
||||
if (p.needColorize(c)) {
|
||||
buf->setDirty(scene::EBT_VERTEX);
|
||||
if (imesh->needs_shading)
|
||||
colorizeMeshBuffer(buf, &c);
|
||||
colorizeMeshBufferTangents(buf, &c);
|
||||
else
|
||||
setMeshBufferColor(buf, c);
|
||||
setMeshBufferTangentsColor(buf, c);
|
||||
}
|
||||
|
||||
video::SMaterial &material = buf->getMaterial();
|
||||
|
99
src/client/light_colors.cpp
Normal file
99
src/client/light_colors.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2024 Andrey2470T, AndreyT <andreyt2203@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "light_colors.h"
|
||||
|
||||
video::SColor encode_light(u16 light, u8 emissive_light)
|
||||
{
|
||||
// Get components
|
||||
u32 day = (light & 0xff);
|
||||
u32 night = (light >> 8);
|
||||
// Add emissive light
|
||||
night += emissive_light * 2.5f;
|
||||
if (night > 255)
|
||||
night = 255;
|
||||
// Since we don't know if the day light is sunlight or
|
||||
// artificial light, assume it is artificial when the night
|
||||
// light bank is also lit.
|
||||
if (day < night)
|
||||
day = 0;
|
||||
else
|
||||
day = day - night;
|
||||
u32 sum = day + night;
|
||||
// Ratio of sunlight:
|
||||
u32 r;
|
||||
if (sum > 0)
|
||||
r = day * 255 / sum;
|
||||
else
|
||||
r = 0;
|
||||
// Average light:
|
||||
float b = (day + night) / 2;
|
||||
return video::SColor(r, b, b, b);
|
||||
}
|
||||
|
||||
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio)
|
||||
{
|
||||
f32 rg = daynight_ratio / 1000.0f - 0.04f;
|
||||
f32 b = (0.98f * daynight_ratio) / 1000.0f + 0.078f;
|
||||
sunlight->r = rg;
|
||||
sunlight->g = rg;
|
||||
sunlight->b = b;
|
||||
}
|
||||
|
||||
void final_color_blend(video::SColor *result,
|
||||
u16 light, u32 daynight_ratio, const video::SColorf &ambientLight)
|
||||
{
|
||||
video::SColorf dayLight;
|
||||
get_sunlight_color(&dayLight, daynight_ratio);
|
||||
final_color_blend(result,
|
||||
encode_light(light, 0), dayLight, ambientLight);
|
||||
}
|
||||
|
||||
void final_color_blend(video::SColor *result,
|
||||
const video::SColor &data, const video::SColorf &dayLight,
|
||||
const video::SColorf &ambientLight)
|
||||
{
|
||||
static const video::SColorf artificialColor(1.04f, 1.04f, 1.04f);
|
||||
|
||||
video::SColorf c(data);
|
||||
f32 n = 1 - c.a;
|
||||
|
||||
f32 r = c.r * (c.a * dayLight.r + n * artificialColor.r) * 2.0f;
|
||||
f32 g = c.g * (c.a * dayLight.g + n * artificialColor.g) * 2.0f;
|
||||
f32 b = c.b * (c.a * dayLight.b + n * artificialColor.b) * 2.0f;
|
||||
|
||||
// Emphase blue a bit in darker places
|
||||
// Each entry of this array represents a range of 8 blue levels
|
||||
static const u8 emphase_blue_when_dark[32] = {
|
||||
1, 4, 6, 6, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
b += emphase_blue_when_dark[irr::core::clamp((s32) ((r + g + b) / 3 * 255),
|
||||
0, 255) / 8] / 255.0f;
|
||||
|
||||
// Add ambient light
|
||||
r += ambientLight.r;
|
||||
g += ambientLight.g;
|
||||
b += ambientLight.b;
|
||||
|
||||
result->setRed(core::clamp((s32)(r * 255.f), 0, 255));
|
||||
result->setGreen(core::clamp((s32)(g * 255.f), 0, 255));
|
||||
result->setBlue(core::clamp((s32)(b * 255.f), 0, 255));
|
||||
}
|
61
src/client/light_colors.h
Normal file
61
src/client/light_colors.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2024 Andrey2470T, AndreyT <andreyt2203@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
|
||||
/*!
|
||||
* Encodes light of a node.
|
||||
* The result is not the final color, but a
|
||||
* half-baked vertex color.
|
||||
* You have to multiply the resulting color
|
||||
* with the node's color.
|
||||
*
|
||||
* \param light the first 8 bits are day light,
|
||||
* the last 8 bits are night light
|
||||
* \param emissive_light amount of light the surface emits,
|
||||
* from 0 to LIGHT_SUN.
|
||||
*/
|
||||
video::SColor encode_light(u16 light, u8 emissive_light);
|
||||
|
||||
/*!
|
||||
* Returns the sunlight's color from the current
|
||||
* day-night ratio.
|
||||
*/
|
||||
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio);
|
||||
|
||||
/*!
|
||||
* Gives the final SColor shown on screen.
|
||||
*
|
||||
* \param result output color
|
||||
* \param light first 8 bits are day light, second 8 bits are
|
||||
* night light
|
||||
*/
|
||||
void final_color_blend(video::SColor *result,
|
||||
u16 light, u32 daynight_ratio, const video::SColorf &ambientLight=video::SColorf(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
/*!
|
||||
* Gives the final SColor shown on screen.
|
||||
*
|
||||
* \param result output color
|
||||
* \param data the half-baked vertex color
|
||||
* \param dayLight color of the sunlight
|
||||
*/
|
||||
void final_color_blend(video::SColor *result,
|
||||
const video::SColor &data, const video::SColorf &dayLight,
|
||||
const video::SColorf &ambientLight=video::SColorf(0.0f, 0.0f, 0.0f, 1.0f));
|
@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include "client/texturesource.h"
|
||||
#include "light_colors.h"
|
||||
|
||||
/*
|
||||
MeshMakeData
|
||||
@ -281,49 +282,6 @@ u16 getSmoothLightTransparent(const v3s16 &p, const v3s16 &corner, MeshMakeData
|
||||
return getSmoothLightCombined(p, dirs, data);
|
||||
}
|
||||
|
||||
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio){
|
||||
f32 rg = daynight_ratio / 1000.0f - 0.04f;
|
||||
f32 b = (0.98f * daynight_ratio) / 1000.0f + 0.078f;
|
||||
sunlight->r = rg;
|
||||
sunlight->g = rg;
|
||||
sunlight->b = b;
|
||||
}
|
||||
|
||||
void final_color_blend(video::SColor *result,
|
||||
u16 light, u32 daynight_ratio)
|
||||
{
|
||||
video::SColorf dayLight;
|
||||
get_sunlight_color(&dayLight, daynight_ratio);
|
||||
final_color_blend(result,
|
||||
encode_light(light, 0), dayLight);
|
||||
}
|
||||
|
||||
void final_color_blend(video::SColor *result,
|
||||
const video::SColor &data, const video::SColorf &dayLight)
|
||||
{
|
||||
static const video::SColorf artificialColor(1.04f, 1.04f, 1.04f);
|
||||
|
||||
video::SColorf c(data);
|
||||
f32 n = 1 - c.a;
|
||||
|
||||
f32 r = c.r * (c.a * dayLight.r + n * artificialColor.r) * 2.0f;
|
||||
f32 g = c.g * (c.a * dayLight.g + n * artificialColor.g) * 2.0f;
|
||||
f32 b = c.b * (c.a * dayLight.b + n * artificialColor.b) * 2.0f;
|
||||
|
||||
// Emphase blue a bit in darker places
|
||||
// Each entry of this array represents a range of 8 blue levels
|
||||
static const u8 emphase_blue_when_dark[32] = {
|
||||
1, 4, 6, 6, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
b += emphase_blue_when_dark[irr::core::clamp((s32) ((r + g + b) / 3 * 255),
|
||||
0, 255) / 8] / 255.0f;
|
||||
|
||||
result->setRed(core::clamp((s32) (r * 255.0f), 0, 255));
|
||||
result->setGreen(core::clamp((s32) (g * 255.0f), 0, 255));
|
||||
result->setBlue(core::clamp((s32) (b * 255.0f), 0, 255));
|
||||
}
|
||||
|
||||
/*
|
||||
Mesh generation helpers
|
||||
@ -672,7 +630,8 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
|
||||
{
|
||||
PreMeshBuffer &p = collector.prebuffers[layer][i];
|
||||
|
||||
applyTileColor(p);
|
||||
if (!m_enable_shaders)
|
||||
applyTileColor(p);
|
||||
|
||||
// Generate animation data
|
||||
// - Cracks
|
||||
@ -759,10 +718,25 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
|
||||
p.layer.applyMaterialOptions(material);
|
||||
}
|
||||
|
||||
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents();
|
||||
buf->Material = material;
|
||||
|
||||
std::vector<video::S3DVertexTangents> tangents;
|
||||
|
||||
// Copy S3DVertex to S3DVertexTangents
|
||||
for (auto &v : p.vertices) {
|
||||
video::SColor &c = p.layer.color;
|
||||
v3f hw_color{0.0f};
|
||||
|
||||
if (m_enable_shaders) {
|
||||
hw_color.X = c.getRed() / 255.0f;
|
||||
hw_color.Y = c.getGreen() / 255.0f;
|
||||
hw_color.Z = c.getBlue() / 255.0f;
|
||||
}
|
||||
tangents.emplace_back(v.Pos, v.Normal, v.Color, v.TCoords, hw_color);
|
||||
}
|
||||
if (p.layer.isTransparent()) {
|
||||
buf->append(&p.vertices[0], p.vertices.size(), nullptr, 0);
|
||||
buf->append(&tangents[0], tangents.size(), nullptr, 0);
|
||||
|
||||
MeshTriangle t;
|
||||
t.buffer = buf;
|
||||
@ -775,7 +749,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
|
||||
m_transparent_triangles.push_back(t);
|
||||
}
|
||||
} else {
|
||||
buf->append(&p.vertices[0], p.vertices.size(),
|
||||
buf->append(&tangents[0], tangents.size(),
|
||||
&p.indices[0], p.indices.size());
|
||||
}
|
||||
mesh->addMeshBuffer(buf);
|
||||
@ -813,7 +787,7 @@ MapBlockMesh::~MapBlockMesh()
|
||||
}
|
||||
|
||||
bool MapBlockMesh::animate(bool faraway, float time, int crack,
|
||||
u32 daynight_ratio)
|
||||
u32 daynight_ratio)
|
||||
{
|
||||
if (!m_has_animation) {
|
||||
m_animation_force_timer = 100000;
|
||||
@ -876,20 +850,19 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
|
||||
if (!m_enable_shaders && (daynight_ratio != m_last_daynight_ratio)) {
|
||||
video::SColorf day_color;
|
||||
get_sunlight_color(&day_color, daynight_ratio);
|
||||
|
||||
for (auto &daynight_diff : m_daynight_diffs) {
|
||||
auto *mesh = m_mesh[daynight_diff.first.first];
|
||||
mesh->setDirty(scene::EBT_VERTEX); // force reload to VBO
|
||||
scene::IMeshBuffer *buf = mesh->
|
||||
getMeshBuffer(daynight_diff.first.second);
|
||||
video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices();
|
||||
video::S3DVertexTangents *vertices = static_cast<video::S3DVertexTangents*>(buf->getVertices());
|
||||
|
||||
for (const auto &j : daynight_diff.second)
|
||||
final_color_blend(&(vertices[j.first].Color), j.second,
|
||||
day_color);
|
||||
day_color);
|
||||
}
|
||||
m_last_daynight_ratio = daynight_ratio;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -908,7 +881,7 @@ void MapBlockMesh::updateTransparentBuffers(v3f camera_pos, v3s16 block_pos)
|
||||
// arrange index sequences into partial buffers
|
||||
m_transparent_buffers.clear();
|
||||
|
||||
scene::SMeshBuffer *current_buffer = nullptr;
|
||||
scene::SMeshBufferTangents *current_buffer = nullptr;
|
||||
std::vector<u16> current_strain;
|
||||
for (auto i : triangle_refs) {
|
||||
const auto &t = m_transparent_triangles[i];
|
||||
@ -932,7 +905,7 @@ void MapBlockMesh::consolidateTransparentBuffers()
|
||||
{
|
||||
m_transparent_buffers.clear();
|
||||
|
||||
scene::SMeshBuffer *current_buffer = nullptr;
|
||||
scene::SMeshBufferTangents *current_buffer = nullptr;
|
||||
std::vector<u16> current_strain;
|
||||
|
||||
// use the fact that m_transparent_triangles is already arranged by buffer
|
||||
@ -954,34 +927,6 @@ void MapBlockMesh::consolidateTransparentBuffers()
|
||||
}
|
||||
}
|
||||
|
||||
video::SColor encode_light(u16 light, u8 emissive_light)
|
||||
{
|
||||
// Get components
|
||||
u32 day = (light & 0xff);
|
||||
u32 night = (light >> 8);
|
||||
// Add emissive light
|
||||
night += emissive_light * 2.5f;
|
||||
if (night > 255)
|
||||
night = 255;
|
||||
// Since we don't know if the day light is sunlight or
|
||||
// artificial light, assume it is artificial when the night
|
||||
// light bank is also lit.
|
||||
if (day < night)
|
||||
day = 0;
|
||||
else
|
||||
day = day - night;
|
||||
u32 sum = day + night;
|
||||
// Ratio of sunlight:
|
||||
u32 r;
|
||||
if (sum > 0)
|
||||
r = day * 255 / sum;
|
||||
else
|
||||
r = 0;
|
||||
// Average light:
|
||||
float b = (day + night) / 2;
|
||||
return video::SColor(r, b, b, b);
|
||||
}
|
||||
|
||||
u8 get_solid_sides(MeshMakeData *data)
|
||||
{
|
||||
std::unordered_map<v3s16, u8> results;
|
||||
|
@ -74,7 +74,7 @@ struct MeshMakeData
|
||||
class MeshTriangle
|
||||
{
|
||||
public:
|
||||
scene::SMeshBuffer *buffer;
|
||||
scene::SMeshBufferTangents *buffer;
|
||||
u16 p1, p2, p3;
|
||||
v3f centroid;
|
||||
float areaSQ;
|
||||
@ -152,7 +152,7 @@ class MapBlockBspTree
|
||||
class PartialMeshBuffer
|
||||
{
|
||||
public:
|
||||
PartialMeshBuffer(scene::SMeshBuffer *buffer, std::vector<u16> &&vertex_indexes) :
|
||||
PartialMeshBuffer(scene::SMeshBufferTangents *buffer, std::vector<u16> &&vertex_indexes) :
|
||||
m_buffer(buffer), m_vertex_indexes(std::move(vertex_indexes))
|
||||
{}
|
||||
|
||||
@ -162,7 +162,7 @@ class PartialMeshBuffer
|
||||
void beforeDraw() const;
|
||||
void afterDraw() const;
|
||||
private:
|
||||
scene::SMeshBuffer *m_buffer;
|
||||
scene::SMeshBufferTangents *m_buffer;
|
||||
mutable std::vector<u16> m_vertex_indexes;
|
||||
};
|
||||
|
||||
@ -284,52 +284,12 @@ class MapBlockMesh
|
||||
std::vector<PartialMeshBuffer> m_transparent_buffers;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Encodes light of a node.
|
||||
* The result is not the final color, but a
|
||||
* half-baked vertex color.
|
||||
* You have to multiply the resulting color
|
||||
* with the node's color.
|
||||
*
|
||||
* \param light the first 8 bits are day light,
|
||||
* the last 8 bits are night light
|
||||
* \param emissive_light amount of light the surface emits,
|
||||
* from 0 to LIGHT_SUN.
|
||||
*/
|
||||
video::SColor encode_light(u16 light, u8 emissive_light);
|
||||
|
||||
// Compute light at node
|
||||
u16 getInteriorLight(MapNode n, s32 increment, const NodeDefManager *ndef);
|
||||
u16 getFaceLight(MapNode n, MapNode n2, const NodeDefManager *ndef);
|
||||
u16 getSmoothLightSolid(const v3s16 &p, const v3s16 &face_dir, const v3s16 &corner, MeshMakeData *data);
|
||||
u16 getSmoothLightTransparent(const v3s16 &p, const v3s16 &corner, MeshMakeData *data);
|
||||
|
||||
/*!
|
||||
* Returns the sunlight's color from the current
|
||||
* day-night ratio.
|
||||
*/
|
||||
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio);
|
||||
|
||||
/*!
|
||||
* Gives the final SColor shown on screen.
|
||||
*
|
||||
* \param result output color
|
||||
* \param light first 8 bits are day light, second 8 bits are
|
||||
* night light
|
||||
*/
|
||||
void final_color_blend(video::SColor *result,
|
||||
u16 light, u32 daynight_ratio);
|
||||
|
||||
/*!
|
||||
* Gives the final SColor shown on screen.
|
||||
*
|
||||
* \param result output color
|
||||
* \param data the half-baked vertex color
|
||||
* \param dayLight color of the sunlight
|
||||
*/
|
||||
void final_color_blend(video::SColor *result,
|
||||
const video::SColor &data, const video::SColorf &dayLight);
|
||||
|
||||
// Retrieves the TileSpec of a face of a node
|
||||
// Adds MATERIAL_FLAG_CRACK if the node is cracked
|
||||
// TileSpec should be passed as reference due to the underlying TileFrame and its vector
|
||||
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <IAnimatedMesh.h>
|
||||
#include <SAnimatedMesh.h>
|
||||
#include <IAnimatedMeshSceneNode.h>
|
||||
#include <array>
|
||||
|
||||
inline static void applyShadeFactor(video::SColor& color, float factor)
|
||||
{
|
||||
@ -53,50 +54,55 @@ void applyFacesShading(video::SColor &color, const v3f &normal)
|
||||
applyShadeFactor(color, 0.670820f * x2 + 1.000000f * y2 + 0.836660f * z2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::array<T, 24> getCubeVertices(video::SColor c)
|
||||
{
|
||||
return std::array<T, 24>{
|
||||
// Up
|
||||
T(-0.5,+0.5,-0.5, 0,1,0, c, 0,1),
|
||||
T(-0.5,+0.5,+0.5, 0,1,0, c, 0,0),
|
||||
T(+0.5,+0.5,+0.5, 0,1,0, c, 1,0),
|
||||
T(+0.5,+0.5,-0.5, 0,1,0, c, 1,1),
|
||||
// Down
|
||||
T(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0),
|
||||
T(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0),
|
||||
T(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1),
|
||||
T(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1),
|
||||
// Right
|
||||
T(+0.5,-0.5,-0.5, 1,0,0, c, 0,1),
|
||||
T(+0.5,+0.5,-0.5, 1,0,0, c, 0,0),
|
||||
T(+0.5,+0.5,+0.5, 1,0,0, c, 1,0),
|
||||
T(+0.5,-0.5,+0.5, 1,0,0, c, 1,1),
|
||||
// Left
|
||||
T(-0.5,-0.5,-0.5, -1,0,0, c, 1,1),
|
||||
T(-0.5,-0.5,+0.5, -1,0,0, c, 0,1),
|
||||
T(-0.5,+0.5,+0.5, -1,0,0, c, 0,0),
|
||||
T(-0.5,+0.5,-0.5, -1,0,0, c, 1,0),
|
||||
// Back
|
||||
T(-0.5,-0.5,+0.5, 0,0,1, c, 1,1),
|
||||
T(+0.5,-0.5,+0.5, 0,0,1, c, 0,1),
|
||||
T(+0.5,+0.5,+0.5, 0,0,1, c, 0,0),
|
||||
T(-0.5,+0.5,+0.5, 0,0,1, c, 1,0),
|
||||
// Front
|
||||
T(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
|
||||
T(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
|
||||
T(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
|
||||
T(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
|
||||
};
|
||||
}
|
||||
|
||||
scene::IAnimatedMesh* createCubeMesh(v3f scale)
|
||||
{
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[24] =
|
||||
{
|
||||
// Up
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1),
|
||||
// Down
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1),
|
||||
// Right
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1),
|
||||
// Left
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0),
|
||||
// Back
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0),
|
||||
// Front
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
|
||||
};
|
||||
|
||||
std::array<video::S3DVertex, 24> vertices = getCubeVertices<video::S3DVertex>(c);
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
for (u32 i=0; i<6; ++i)
|
||||
{
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
buf->append(vertices + 4 * i, 4, indices, 6);
|
||||
buf->append(&vertices[0] + 4 * i, 4, indices, 6);
|
||||
// Set default material
|
||||
buf->getMaterial().Lighting = false;
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
@ -115,9 +121,39 @@ scene::IAnimatedMesh* createCubeMesh(v3f scale)
|
||||
return anim_mesh;
|
||||
}
|
||||
|
||||
scene::IAnimatedMesh* createCubeMeshTangents(v3f scale)
|
||||
{
|
||||
video::SColor c(255,255,255,255);
|
||||
|
||||
std::array<video::S3DVertexTangents, 24> vertices = getCubeVertices<video::S3DVertexTangents>(c);
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
for (u32 i=0; i<6; ++i)
|
||||
{
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBufferTangents();
|
||||
buf->append(&vertices[0] + 4 * i, 4, indices, 6);
|
||||
// Set default material
|
||||
buf->getMaterial().Lighting = false;
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
buf->getMaterial().forEachTexture([] (auto &tex) {
|
||||
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
|
||||
tex.MagFilter = video::ETMAGF_NEAREST;
|
||||
});
|
||||
// Add mesh buffer to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
|
||||
scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh);
|
||||
mesh->drop();
|
||||
scaleMeshTangents(anim_mesh, scale); // also recalculates bounding box
|
||||
return anim_mesh;
|
||||
}
|
||||
|
||||
void scaleMesh(scene::IMesh *mesh, v3f scale)
|
||||
{
|
||||
if (mesh == NULL)
|
||||
if (!mesh)
|
||||
return;
|
||||
|
||||
aabb3f bbox;
|
||||
@ -126,11 +162,9 @@ void scaleMesh(scene::IMesh *mesh, v3f scale)
|
||||
u32 mc = mesh->getMeshBufferCount();
|
||||
for (u32 j = 0; j < mc; j++) {
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
const u32 stride = getVertexPitchFromType(buf->getVertexType());
|
||||
u32 vertex_count = buf->getVertexCount();
|
||||
u8 *vertices = (u8 *)buf->getVertices();
|
||||
for (u32 i = 0; i < vertex_count; i++)
|
||||
((video::S3DVertex *)(vertices + i * stride))->Pos *= scale;
|
||||
video::S3DVertex *vertices = static_cast<video::S3DVertex*>(buf->getVertices());
|
||||
for (u32 i = 0; i < buf->getVertexCount(); i++)
|
||||
vertices[i].Pos *= scale;
|
||||
|
||||
buf->recalculateBoundingBox();
|
||||
|
||||
@ -143,9 +177,9 @@ void scaleMesh(scene::IMesh *mesh, v3f scale)
|
||||
mesh->setBoundingBox(bbox);
|
||||
}
|
||||
|
||||
void translateMesh(scene::IMesh *mesh, v3f vec)
|
||||
void scaleMeshTangents(scene::IMesh *mesh, v3f scale)
|
||||
{
|
||||
if (mesh == NULL)
|
||||
if (!mesh)
|
||||
return;
|
||||
|
||||
aabb3f bbox;
|
||||
@ -154,11 +188,35 @@ void translateMesh(scene::IMesh *mesh, v3f vec)
|
||||
u32 mc = mesh->getMeshBufferCount();
|
||||
for (u32 j = 0; j < mc; j++) {
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
const u32 stride = getVertexPitchFromType(buf->getVertexType());
|
||||
u32 vertex_count = buf->getVertexCount();
|
||||
u8 *vertices = (u8 *)buf->getVertices();
|
||||
for (u32 i = 0; i < vertex_count; i++)
|
||||
((video::S3DVertex *)(vertices + i * stride))->Pos += vec;
|
||||
video::S3DVertexTangents *vertices = static_cast<video::S3DVertexTangents*>(buf->getVertices());
|
||||
for (u32 i = 0; i < buf->getVertexCount(); i++)
|
||||
vertices[i].Pos *= scale;
|
||||
|
||||
buf->recalculateBoundingBox();
|
||||
|
||||
// calculate total bounding box
|
||||
if (j == 0)
|
||||
bbox = buf->getBoundingBox();
|
||||
else
|
||||
bbox.addInternalBox(buf->getBoundingBox());
|
||||
}
|
||||
mesh->setBoundingBox(bbox);
|
||||
}
|
||||
|
||||
void translateMeshTangents(scene::IMesh *mesh, v3f vec)
|
||||
{
|
||||
if (!mesh)
|
||||
return;
|
||||
|
||||
aabb3f bbox;
|
||||
bbox.reset(0, 0, 0);
|
||||
|
||||
u32 mc = mesh->getMeshBufferCount();
|
||||
for (u32 j = 0; j < mc; j++) {
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertexTangents *vertices = static_cast<video::S3DVertexTangents*>(buf->getVertices());
|
||||
for (u32 i = 0; i < buf->getVertexCount(); i++)
|
||||
vertices[i].Pos += vec;
|
||||
|
||||
buf->recalculateBoundingBox();
|
||||
|
||||
@ -173,11 +231,20 @@ void translateMesh(scene::IMesh *mesh, v3f vec)
|
||||
|
||||
void setMeshBufferColor(scene::IMeshBuffer *buf, const video::SColor &color)
|
||||
{
|
||||
const u32 stride = getVertexPitchFromType(buf->getVertexType());
|
||||
u32 vertex_count = buf->getVertexCount();
|
||||
u8 *vertices = (u8 *) buf->getVertices();
|
||||
for (u32 i = 0; i < vertex_count; i++)
|
||||
((video::S3DVertex *) (vertices + i * stride))->Color = color;
|
||||
video::S3DVertex *vertices = static_cast<video::S3DVertex*>(buf->getVertices());
|
||||
for (u32 i = 0; i < buf->getVertexCount(); i++)
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
|
||||
void setMeshBufferTangentsColor(scene::IMeshBuffer *buf,
|
||||
const video::SColor &color, const video::SColor &hw_color)
|
||||
{
|
||||
video::S3DVertexTangents *vertices = static_cast<video::S3DVertexTangents*>(buf->getVertices());
|
||||
|
||||
for (u32 i = 0; i < buf->getVertexCount(); i++) {
|
||||
vertices[i].Color = color;
|
||||
vertices[i].Tangent = v3f(hw_color.getRed(), hw_color.getGreen(), hw_color.getBlue());
|
||||
}
|
||||
}
|
||||
|
||||
void setAnimatedMeshColor(scene::IAnimatedMeshSceneNode *node, const video::SColor &color)
|
||||
@ -189,44 +256,37 @@ void setAnimatedMeshColor(scene::IAnimatedMeshSceneNode *node, const video::SCol
|
||||
|
||||
void setMeshColor(scene::IMesh *mesh, const video::SColor &color)
|
||||
{
|
||||
if (mesh == NULL)
|
||||
if (!mesh)
|
||||
return;
|
||||
|
||||
u32 mc = mesh->getMeshBufferCount();
|
||||
for (u32 j = 0; j < mc; j++)
|
||||
for (u32 j = 0; j < mesh->getMeshBufferCount(); j++)
|
||||
setMeshBufferColor(mesh->getMeshBuffer(j), color);
|
||||
}
|
||||
|
||||
void setMeshBufferTextureCoords(scene::IMeshBuffer *buf, const v2f *uv, u32 count)
|
||||
{
|
||||
const u32 stride = getVertexPitchFromType(buf->getVertexType());
|
||||
assert(buf->getVertexCount() >= count);
|
||||
u8 *vertices = (u8 *) buf->getVertices();
|
||||
video::S3DVertex *vertices = static_cast<video::S3DVertex*>(buf->getVertices());
|
||||
for (u32 i = 0; i < count; i++)
|
||||
((video::S3DVertex*) (vertices + i * stride))->TCoords = uv[i];
|
||||
vertices[i].TCoords = uv[i];
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
template <typename T, typename F>
|
||||
static void applyToMesh(scene::IMesh *mesh, const F &fn)
|
||||
{
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for (u16 j = 0; j < mc; j++) {
|
||||
for (u16 j = 0; j < mesh->getMeshBufferCount(); j++) {
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
const u32 stride = getVertexPitchFromType(buf->getVertexType());
|
||||
u32 vertex_count = buf->getVertexCount();
|
||||
char *vertices = reinterpret_cast<char *>(buf->getVertices());
|
||||
for (u32 i = 0; i < vertex_count; i++)
|
||||
fn(reinterpret_cast<video::S3DVertex *>(vertices + i * stride));
|
||||
T *vertices = static_cast<T*>(buf->getVertices());
|
||||
for (u32 i = 0; i < buf->getVertexCount(); i++)
|
||||
fn(&vertices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void colorizeMeshBuffer(scene::IMeshBuffer *buf, const video::SColor *buffercolor)
|
||||
void colorizeMeshBufferTangents(scene::IMeshBuffer *buf, const video::SColor *buffercolor)
|
||||
{
|
||||
const u32 stride = getVertexPitchFromType(buf->getVertexType());
|
||||
u32 vertex_count = buf->getVertexCount();
|
||||
u8 *vertices = (u8 *) buf->getVertices();
|
||||
for (u32 i = 0; i < vertex_count; i++) {
|
||||
video::S3DVertex *vertex = (video::S3DVertex *) (vertices + i * stride);
|
||||
video::S3DVertexTangents *vertices = static_cast<video::S3DVertexTangents*>(buf->getVertices());
|
||||
for (u32 i = 0; i < buf->getVertexCount(); i++) {
|
||||
video::S3DVertexTangents *vertex = &vertices[i];
|
||||
video::SColor *vc = &(vertex->Color);
|
||||
// Reset color
|
||||
*vc = *buffercolor;
|
||||
@ -235,27 +295,6 @@ void colorizeMeshBuffer(scene::IMeshBuffer *buf, const video::SColor *buffercolo
|
||||
}
|
||||
}
|
||||
|
||||
void setMeshColorByNormalXYZ(scene::IMesh *mesh,
|
||||
const video::SColor &colorX,
|
||||
const video::SColor &colorY,
|
||||
const video::SColor &colorZ)
|
||||
{
|
||||
if (!mesh)
|
||||
return;
|
||||
auto colorizator = [=] (video::S3DVertex *vertex) {
|
||||
f32 x = fabs(vertex->Normal.X);
|
||||
f32 y = fabs(vertex->Normal.Y);
|
||||
f32 z = fabs(vertex->Normal.Z);
|
||||
if (x >= y && x >= z)
|
||||
vertex->Color = colorX;
|
||||
else if (y >= z)
|
||||
vertex->Color = colorY;
|
||||
else
|
||||
vertex->Color = colorZ;
|
||||
};
|
||||
applyToMesh(mesh, colorizator);
|
||||
}
|
||||
|
||||
void setMeshColorByNormal(scene::IMesh *mesh, const v3f &normal,
|
||||
const video::SColor &color)
|
||||
{
|
||||
@ -265,37 +304,47 @@ void setMeshColorByNormal(scene::IMesh *mesh, const v3f &normal,
|
||||
if (vertex->Normal == normal)
|
||||
vertex->Color = color;
|
||||
};
|
||||
applyToMesh(mesh, colorizator);
|
||||
applyToMesh<video::S3DVertex>(mesh, colorizator);
|
||||
}
|
||||
|
||||
template <float v3f::*U, float v3f::*V>
|
||||
template <typename T, float v3f::*U, float v3f::*V>
|
||||
static void rotateMesh(scene::IMesh *mesh, float degrees)
|
||||
{
|
||||
degrees *= M_PI / 180.0f;
|
||||
float c = std::cos(degrees);
|
||||
float s = std::sin(degrees);
|
||||
auto rotator = [c, s] (video::S3DVertex *vertex) {
|
||||
auto rotator = [c, s] (T *vertex) {
|
||||
float u = vertex->Pos.*U;
|
||||
float v = vertex->Pos.*V;
|
||||
vertex->Pos.*U = c * u - s * v;
|
||||
vertex->Pos.*V = s * u + c * v;
|
||||
};
|
||||
applyToMesh(mesh, rotator);
|
||||
applyToMesh<T>(mesh, rotator);
|
||||
}
|
||||
|
||||
void rotateMeshXYby(scene::IMesh *mesh, f64 degrees)
|
||||
{
|
||||
rotateMesh<&v3f::X, &v3f::Y>(mesh, degrees);
|
||||
rotateMesh<video::S3DVertex, &v3f::X, &v3f::Y>(mesh, degrees);
|
||||
}
|
||||
|
||||
void rotateMeshXZby(scene::IMesh *mesh, f64 degrees)
|
||||
{
|
||||
rotateMesh<&v3f::X, &v3f::Z>(mesh, degrees);
|
||||
rotateMesh<video::S3DVertex, &v3f::X, &v3f::Z>(mesh, degrees);
|
||||
}
|
||||
|
||||
void rotateMeshTangentsXZby(scene::IMesh *mesh, f64 degrees)
|
||||
{
|
||||
rotateMesh<video::S3DVertexTangents, &v3f::X, &v3f::Z>(mesh, degrees);
|
||||
}
|
||||
|
||||
void rotateMeshYZby(scene::IMesh *mesh, f64 degrees)
|
||||
{
|
||||
rotateMesh<&v3f::Y, &v3f::Z>(mesh, degrees);
|
||||
rotateMesh<video::S3DVertex, &v3f::Y, &v3f::Z>(mesh, degrees);
|
||||
}
|
||||
|
||||
void rotateMeshTangentsYZby(scene::IMesh *mesh, f64 degrees)
|
||||
{
|
||||
rotateMesh<video::S3DVertexTangents, &v3f::Y, &v3f::Z>(mesh, degrees);
|
||||
}
|
||||
|
||||
void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir)
|
||||
@ -357,7 +406,7 @@ scene::IMeshBuffer* cloneMeshBuffer(scene::IMeshBuffer *mesh_buffer)
|
||||
{
|
||||
switch (mesh_buffer->getVertexType()) {
|
||||
case video::EVT_STANDARD: {
|
||||
video::S3DVertex *v = (video::S3DVertex *) mesh_buffer->getVertices();
|
||||
video::S3DVertex *v = static_cast<video::S3DVertex*>(mesh_buffer->getVertices());
|
||||
u16 *indices = mesh_buffer->getIndices();
|
||||
scene::SMeshBuffer *cloned_buffer = new scene::SMeshBuffer();
|
||||
cloned_buffer->append(v, mesh_buffer->getVertexCount(), indices,
|
||||
@ -366,7 +415,7 @@ scene::IMeshBuffer* cloneMeshBuffer(scene::IMeshBuffer *mesh_buffer)
|
||||
}
|
||||
case video::EVT_2TCOORDS: {
|
||||
video::S3DVertex2TCoords *v =
|
||||
(video::S3DVertex2TCoords *) mesh_buffer->getVertices();
|
||||
static_cast<video::S3DVertex2TCoords*>(mesh_buffer->getVertices());
|
||||
u16 *indices = mesh_buffer->getIndices();
|
||||
scene::SMeshBufferLightMap *cloned_buffer =
|
||||
new scene::SMeshBufferLightMap();
|
||||
@ -376,7 +425,7 @@ scene::IMeshBuffer* cloneMeshBuffer(scene::IMeshBuffer *mesh_buffer)
|
||||
}
|
||||
case video::EVT_TANGENTS: {
|
||||
video::S3DVertexTangents *v =
|
||||
(video::S3DVertexTangents *) mesh_buffer->getVertices();
|
||||
static_cast<video::S3DVertexTangents*>(mesh_buffer->getVertices());
|
||||
u16 *indices = mesh_buffer->getIndices();
|
||||
scene::SMeshBufferTangents *cloned_buffer =
|
||||
new scene::SMeshBufferTangents();
|
||||
|
@ -38,27 +38,33 @@ void applyFacesShading(video::SColor &color, const v3f &normal);
|
||||
*/
|
||||
scene::IAnimatedMesh* createCubeMesh(v3f scale);
|
||||
|
||||
scene::IAnimatedMesh* createCubeMeshTangents(v3f scale);
|
||||
|
||||
/*
|
||||
Multiplies each vertex coordinate by the specified scaling factors
|
||||
(componentwise vector multiplication).
|
||||
*/
|
||||
void scaleMesh(scene::IMesh *mesh, v3f scale);
|
||||
void scaleMeshTangents(scene::IMesh *mesh, v3f scale);
|
||||
|
||||
/*
|
||||
Translate each vertex coordinate by the specified vector.
|
||||
*/
|
||||
void translateMesh(scene::IMesh *mesh, v3f vec);
|
||||
void translateMeshTangents(scene::IMesh *mesh, v3f vec);
|
||||
|
||||
/*!
|
||||
* Sets a constant color for all vertices in the mesh buffer.
|
||||
*/
|
||||
void setMeshBufferColor(scene::IMeshBuffer *buf, const video::SColor &color);
|
||||
void setMeshBufferTangentsColor(scene::IMeshBuffer *buf,
|
||||
const video::SColor &color, const video::SColor &hw_color=video::SColor(0xFFFFFFFF));
|
||||
|
||||
/*
|
||||
Set a constant color for all vertices in the mesh
|
||||
*/
|
||||
void setMeshColor(scene::IMesh *mesh, const video::SColor &color);
|
||||
|
||||
void setMeshTangentsColor(scene::IMesh *mesh, const video::SColor &color,
|
||||
const video::SColor &hw_color=video::SColor(0xFFFFFFFF));
|
||||
|
||||
/*
|
||||
Sets texture coords for vertices in the mesh buffer.
|
||||
@ -75,18 +81,7 @@ void setAnimatedMeshColor(scene::IAnimatedMeshSceneNode *node, const video::SCol
|
||||
* Overwrites the color of a mesh buffer.
|
||||
* The color is darkened based on the normal vector of the vertices.
|
||||
*/
|
||||
void colorizeMeshBuffer(scene::IMeshBuffer *buf, const video::SColor *buffercolor);
|
||||
|
||||
/*
|
||||
Set the color of all vertices in the mesh.
|
||||
For each vertex, determine the largest absolute entry in
|
||||
the normal vector, and choose one of colorX, colorY or
|
||||
colorZ accordingly.
|
||||
*/
|
||||
void setMeshColorByNormalXYZ(scene::IMesh *mesh,
|
||||
const video::SColor &colorX,
|
||||
const video::SColor &colorY,
|
||||
const video::SColor &colorZ);
|
||||
void colorizeMeshBufferTangents(scene::IMeshBuffer *buf, const video::SColor *buffercolor);
|
||||
|
||||
void setMeshColorByNormal(scene::IMesh *mesh, const v3f &normal,
|
||||
const video::SColor &color);
|
||||
@ -102,7 +97,9 @@ void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir);
|
||||
*/
|
||||
void rotateMeshXYby (scene::IMesh *mesh, f64 degrees);
|
||||
void rotateMeshXZby (scene::IMesh *mesh, f64 degrees);
|
||||
void rotateMeshTangentsXZby(scene::IMesh *mesh, f64 degrees);
|
||||
void rotateMeshYZby (scene::IMesh *mesh, f64 degrees);
|
||||
void rotateMeshTangentsYZby(scene::IMesh *mesh, f64 degrees);
|
||||
|
||||
/*
|
||||
* Clone the mesh buffer.
|
||||
@ -139,5 +136,5 @@ bool checkMeshNormals(scene::IMesh *mesh);
|
||||
Set the MinFilter, MagFilter and AnisotropicFilter properties of a texture
|
||||
layer according to the three relevant boolean values found in the Minetest
|
||||
settings.
|
||||
*/
|
||||
*/
|
||||
void setMaterialFilters(video::SMaterialLayer &tex, bool bilinear, bool trilinear, bool anisotropic);
|
||||
|
@ -35,6 +35,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "client.h"
|
||||
#include "settings.h"
|
||||
#include "profiler.h"
|
||||
#include "client/mapblock_mesh.h"
|
||||
#include "light_colors.h"
|
||||
|
||||
ClientParticleTexture::ClientParticleTexture(const ServerParticleTexture& p, ITextureSource *tsrc)
|
||||
{
|
||||
@ -185,11 +187,18 @@ video::SColor Particle::updateLight(ClientEnvironment *env)
|
||||
else
|
||||
light = blend_light(env->getDayNightRatio(), LIGHT_SUN, 0);
|
||||
|
||||
u8 m_light = decode_light(light + m_p.glow);
|
||||
light = decode_light(light + m_p.glow);
|
||||
|
||||
video::SColor light_color(0xFFFFFFFF);
|
||||
video::SColor ambient_light = g_settings->getBool("enable_shaders") ?
|
||||
env->getLocalPlayer()->getLighting().ambient_light : video::SColor(255, 0, 0, 0);
|
||||
|
||||
final_color_blend(&light_color, static_cast<u16>(light) * 255, env->getDayNightRatio(),
|
||||
ambient_light);
|
||||
return video::SColor(255,
|
||||
m_light * m_base_color.getRed() / 255,
|
||||
m_light * m_base_color.getGreen() / 255,
|
||||
m_light * m_base_color.getBlue() / 255);
|
||||
light_color.getRed() * m_base_color.getRed() / 255,
|
||||
light_color.getGreen() * m_base_color.getGreen() / 255,
|
||||
light_color.getBlue() * m_base_color.getBlue() / 255);
|
||||
}
|
||||
|
||||
void Particle::updateVertices(ClientEnvironment *env, video::SColor color)
|
||||
|
@ -45,23 +45,22 @@ static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y)
|
||||
{
|
||||
const f32 r = 0.5;
|
||||
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents();
|
||||
video::SColor c(255,255,255,255);
|
||||
v3f scale(1.0, 1.0, 0.1);
|
||||
|
||||
// Front and back
|
||||
{
|
||||
video::S3DVertex vertices[8] = {
|
||||
video::S3DVertexTangents vertices[8] = {
|
||||
// z-
|
||||
video::S3DVertex(-r,+r,-r, 0,0,-1, c, 0,0),
|
||||
video::S3DVertex(+r,+r,-r, 0,0,-1, c, 1,0),
|
||||
video::S3DVertex(+r,-r,-r, 0,0,-1, c, 1,1),
|
||||
video::S3DVertex(-r,-r,-r, 0,0,-1, c, 0,1),
|
||||
video::S3DVertexTangents(-r,+r,-r, 0,0,-1, c, 0,0),
|
||||
video::S3DVertexTangents(+r,+r,-r, 0,0,-1, c, 1,0),
|
||||
video::S3DVertexTangents(+r,-r,-r, 0,0,-1, c, 1,1),
|
||||
video::S3DVertexTangents(-r,-r,-r, 0,0,-1, c, 0,1),
|
||||
// z+
|
||||
video::S3DVertex(-r,+r,+r, 0,0,+1, c, 0,0),
|
||||
video::S3DVertex(-r,-r,+r, 0,0,+1, c, 0,1),
|
||||
video::S3DVertex(+r,-r,+r, 0,0,+1, c, 1,1),
|
||||
video::S3DVertex(+r,+r,+r, 0,0,+1, c, 1,0),
|
||||
video::S3DVertexTangents(-r,+r,+r, 0,0,+1, c, 0,0),
|
||||
video::S3DVertexTangents(-r,-r,+r, 0,0,+1, c, 0,1),
|
||||
video::S3DVertexTangents(+r,-r,+r, 0,0,+1, c, 1,1),
|
||||
video::S3DVertexTangents(+r,+r,+r, 0,0,+1, c, 1,0),
|
||||
};
|
||||
u16 indices[12] = {0,1,2,2,3,0,4,5,6,6,7,4};
|
||||
buf->append(vertices, 8, indices, 12);
|
||||
@ -76,17 +75,17 @@ static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y)
|
||||
f32 x1 = pixelpos_x + pixelsize_x;
|
||||
f32 tex0 = (i + 0.1) * pixelsize_x;
|
||||
f32 tex1 = (i + 0.9) * pixelsize_x;
|
||||
video::S3DVertex vertices[8] = {
|
||||
video::S3DVertexTangents vertices[8] = {
|
||||
// x-
|
||||
video::S3DVertex(x0,-r,-r, -1,0,0, c, tex0,1),
|
||||
video::S3DVertex(x0,-r,+r, -1,0,0, c, tex1,1),
|
||||
video::S3DVertex(x0,+r,+r, -1,0,0, c, tex1,0),
|
||||
video::S3DVertex(x0,+r,-r, -1,0,0, c, tex0,0),
|
||||
video::S3DVertexTangents(x0,-r,-r, -1,0,0, c, tex0,1),
|
||||
video::S3DVertexTangents(x0,-r,+r, -1,0,0, c, tex1,1),
|
||||
video::S3DVertexTangents(x0,+r,+r, -1,0,0, c, tex1,0),
|
||||
video::S3DVertexTangents(x0,+r,-r, -1,0,0, c, tex0,0),
|
||||
// x+
|
||||
video::S3DVertex(x1,-r,-r, +1,0,0, c, tex0,1),
|
||||
video::S3DVertex(x1,+r,-r, +1,0,0, c, tex0,0),
|
||||
video::S3DVertex(x1,+r,+r, +1,0,0, c, tex1,0),
|
||||
video::S3DVertex(x1,-r,+r, +1,0,0, c, tex1,1),
|
||||
video::S3DVertexTangents(x1,-r,-r, +1,0,0, c, tex0,1),
|
||||
video::S3DVertexTangents(x1,+r,-r, +1,0,0, c, tex0,0),
|
||||
video::S3DVertexTangents(x1,+r,+r, +1,0,0, c, tex1,0),
|
||||
video::S3DVertexTangents(x1,-r,+r, +1,0,0, c, tex1,1),
|
||||
};
|
||||
u16 indices[12] = {0,1,2,2,3,0,4,5,6,6,7,4};
|
||||
buf->append(vertices, 8, indices, 12);
|
||||
@ -97,17 +96,17 @@ static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y)
|
||||
f32 y1 = -pixelpos_y;
|
||||
f32 tex0 = (i + 0.1) * pixelsize_y;
|
||||
f32 tex1 = (i + 0.9) * pixelsize_y;
|
||||
video::S3DVertex vertices[8] = {
|
||||
video::S3DVertexTangents vertices[8] = {
|
||||
// y-
|
||||
video::S3DVertex(-r,y0,-r, 0,-1,0, c, 0,tex0),
|
||||
video::S3DVertex(+r,y0,-r, 0,-1,0, c, 1,tex0),
|
||||
video::S3DVertex(+r,y0,+r, 0,-1,0, c, 1,tex1),
|
||||
video::S3DVertex(-r,y0,+r, 0,-1,0, c, 0,tex1),
|
||||
video::S3DVertexTangents(-r,y0,-r, 0,-1,0, c, 0,tex0),
|
||||
video::S3DVertexTangents(+r,y0,-r, 0,-1,0, c, 1,tex0),
|
||||
video::S3DVertexTangents(+r,y0,+r, 0,-1,0, c, 1,tex1),
|
||||
video::S3DVertexTangents(-r,y0,+r, 0,-1,0, c, 0,tex1),
|
||||
// y+
|
||||
video::S3DVertex(-r,y1,-r, 0,+1,0, c, 0,tex0),
|
||||
video::S3DVertex(-r,y1,+r, 0,+1,0, c, 0,tex1),
|
||||
video::S3DVertex(+r,y1,+r, 0,+1,0, c, 1,tex1),
|
||||
video::S3DVertex(+r,y1,-r, 0,+1,0, c, 1,tex0),
|
||||
video::S3DVertexTangents(-r,y1,-r, 0,+1,0, c, 0,tex0),
|
||||
video::S3DVertexTangents(-r,y1,+r, 0,+1,0, c, 0,tex1),
|
||||
video::S3DVertexTangents(+r,y1,+r, 0,+1,0, c, 1,tex1),
|
||||
video::S3DVertexTangents(+r,y1,-r, 0,+1,0, c, 1,tex0),
|
||||
};
|
||||
u16 indices[12] = {0,1,2,2,3,0,4,5,6,6,7,4};
|
||||
buf->append(vertices, 8, indices, 12);
|
||||
@ -117,7 +116,7 @@ static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y)
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
scaleMesh(mesh, scale); // also recalculates bounding box
|
||||
scaleMeshTangents(mesh, scale); // also recalculates bounding box
|
||||
return mesh;
|
||||
}
|
||||
|
||||
@ -144,7 +143,7 @@ class ExtrusionMeshCache: public IReferenceCounted
|
||||
m_extrusion_meshes[resolution] =
|
||||
createExtrusionMesh(resolution, resolution);
|
||||
}
|
||||
m_cube = createCubeMesh(v3f(1.0, 1.0, 1.0));
|
||||
m_cube = createCubeMeshTangents(v3f(1.0, 1.0, 1.0));
|
||||
}
|
||||
// Destructor
|
||||
virtual ~ExtrusionMeshCache()
|
||||
@ -345,14 +344,16 @@ static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n,
|
||||
p.layer.texture = frame.texture;
|
||||
p.layer.normal_texture = frame.normal_texture;
|
||||
}
|
||||
std::vector<video::S3DVertexTangents> tangents;
|
||||
for (video::S3DVertex &v : p.vertices) {
|
||||
v.Color.setAlpha(255);
|
||||
tangents.emplace_back(v);
|
||||
}
|
||||
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents();
|
||||
buf->Material.setTexture(0, p.layer.texture);
|
||||
p.layer.applyMaterialOptions(buf->Material);
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->append(&p.vertices[0], p.vertices.size(),
|
||||
buf->append(&tangents[0], tangents.size(),
|
||||
&p.indices[0], p.indices.size());
|
||||
buf->drop();
|
||||
colors->push_back(
|
||||
@ -374,7 +375,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
||||
scene::SMesh *mesh = nullptr;
|
||||
|
||||
if (m_enable_shaders) {
|
||||
u32 shader_id = shdrsrc->getShader("object_shader", TILE_MATERIAL_BASIC, NDT_NORMAL);
|
||||
u32 shader_id = shdrsrc->getShader("nodes_shader", TILE_MATERIAL_BASIC, NDT_NORMAL);
|
||||
m_material_type = shdrsrc->getShaderInfo(shader_id).material;
|
||||
}
|
||||
|
||||
@ -500,33 +501,37 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
||||
|
||||
void WieldMeshSceneNode::setColor(video::SColor c)
|
||||
{
|
||||
if (!m_meshnode)
|
||||
return;
|
||||
|
||||
assert(!m_lighting);
|
||||
scene::IMesh *mesh = m_meshnode->getMesh();
|
||||
if (!mesh)
|
||||
return;
|
||||
|
||||
u8 red = c.getRed();
|
||||
u8 green = c.getGreen();
|
||||
u8 blue = c.getBlue();
|
||||
|
||||
const u32 mc = mesh->getMeshBufferCount();
|
||||
if (mc > m_colors.size())
|
||||
m_colors.resize(mc);
|
||||
for (u32 j = 0; j < mc; j++) {
|
||||
video::SColor bc(m_base_color);
|
||||
m_colors[j].applyOverride(bc);
|
||||
video::SColor buffercolor(255,
|
||||
bc.getRed() * red / 255,
|
||||
bc.getGreen() * green / 255,
|
||||
bc.getBlue() * blue / 255);
|
||||
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
|
||||
video::SColor buffercolor(255,
|
||||
bc.getRed() * c.getRed() / 255,
|
||||
bc.getGreen() * c.getGreen() / 255,
|
||||
bc.getBlue() * c.getBlue() / 255);
|
||||
|
||||
if (m_colors[j].needColorize(buffercolor)) {
|
||||
buf->setDirty(scene::EBT_VERTEX);
|
||||
if (m_enable_shaders)
|
||||
setMeshBufferColor(buf, buffercolor);
|
||||
if (m_enable_shaders) {
|
||||
setMeshBufferTangentsColor(buf,
|
||||
video::SColor(255, c.getRed(), c.getGreen(), c.getBlue()),
|
||||
video::SColor(255, bc.getRed() / 255, bc.getGreen() / 255, bc.getBlue() / 255));
|
||||
}
|
||||
else
|
||||
colorizeMeshBuffer(buf, &buffercolor);
|
||||
colorizeMeshBufferTangents(buf, &buffercolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -619,15 +624,15 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
|
||||
mesh = cloneMesh(cube);
|
||||
cube->drop();
|
||||
if (f.drawtype == NDT_FLOWINGLIQUID) {
|
||||
scaleMesh(mesh, v3f(1.2, 0.03, 1.2));
|
||||
translateMesh(mesh, v3f(0, -0.57, 0));
|
||||
scaleMeshTangents(mesh, v3f(1.2, 0.03, 1.2));
|
||||
translateMeshTangents(mesh, v3f(0, -0.57, 0));
|
||||
} else
|
||||
scaleMesh(mesh, v3f(1.2, 1.2, 1.2));
|
||||
scaleMeshTangents(mesh, v3f(1.2, 1.2, 1.2));
|
||||
// add overlays
|
||||
postProcessNodeMesh(mesh, f, false, false, nullptr,
|
||||
&result->buffer_colors, true);
|
||||
if (f.drawtype == NDT_ALLFACES)
|
||||
scaleMesh(mesh, v3f(f.visual_scale));
|
||||
scaleMeshTangents(mesh, v3f(f.visual_scale));
|
||||
break;
|
||||
}
|
||||
case NDT_PLANTLIKE: {
|
||||
@ -656,7 +661,7 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
|
||||
n.setParam2(*def.place_param2);
|
||||
|
||||
mesh = createSpecialNodeMesh(client, n, &result->buffer_colors, f);
|
||||
scaleMesh(mesh, v3f(0.12, 0.12, 0.12));
|
||||
scaleMeshTangents(mesh, v3f(0.12, 0.12, 0.12));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -674,8 +679,8 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
|
||||
material.Lighting = false;
|
||||
}
|
||||
|
||||
rotateMeshXZby(mesh, -45);
|
||||
rotateMeshYZby(mesh, -30);
|
||||
rotateMeshTangentsXZby(mesh, -45);
|
||||
rotateMeshTangentsYZby(mesh, -30);
|
||||
}
|
||||
|
||||
// might need to be re-colorized, this is done only when needed
|
||||
@ -728,7 +733,7 @@ scene::SMesh *getExtrudedMesh(ITextureSource *tsrc,
|
||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
material.MaterialTypeParam = 0.5f;
|
||||
}
|
||||
scaleMesh(mesh, v3f(2.0, 2.0, 2.0));
|
||||
scaleMeshTangents(mesh, v3f(2.0, 2.0, 2.0));
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "irrlichttypes_bloated.h"
|
||||
|
||||
|
||||
/**
|
||||
@ -46,11 +47,11 @@ struct AutoExposure
|
||||
AutoExposure();
|
||||
};
|
||||
|
||||
/** Describes ambient light settings for a player
|
||||
*/
|
||||
struct Lighting
|
||||
{
|
||||
AutoExposure exposure;
|
||||
/// @brief Ambient light color & intensity for nodes & entities. Alpha is ignored.
|
||||
video::SColor ambient_light {255, 0, 0, 0};
|
||||
float shadow_intensity {0.0f};
|
||||
float saturation {1.0f};
|
||||
float volumetric_light_strength {0.0f};
|
||||
|
@ -1801,18 +1801,28 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt)
|
||||
{
|
||||
Lighting& lighting = m_env.getLocalPlayer()->getLighting();
|
||||
|
||||
if (pkt->getRemainingBytes() >= 4)
|
||||
*pkt >> lighting.shadow_intensity;
|
||||
if (pkt->getRemainingBytes() >= 4)
|
||||
*pkt >> lighting.saturation;
|
||||
if (pkt->getRemainingBytes() >= 24) {
|
||||
*pkt >> lighting.exposure.luminance_min
|
||||
>> lighting.exposure.luminance_max
|
||||
>> lighting.exposure.exposure_correction
|
||||
>> lighting.exposure.speed_dark_bright
|
||||
>> lighting.exposure.speed_bright_dark
|
||||
>> lighting.exposure.center_weight_power;
|
||||
}
|
||||
if (pkt->getRemainingBytes() >= 4)
|
||||
*pkt >> lighting.volumetric_light_strength;
|
||||
if (pkt->getRemainingBytes() < 4)
|
||||
return;
|
||||
*pkt >> lighting.shadow_intensity;
|
||||
|
||||
if (pkt->getRemainingBytes() < 4)
|
||||
return;
|
||||
*pkt >> lighting.saturation;
|
||||
|
||||
if (pkt->getRemainingBytes() < 24)
|
||||
return;
|
||||
*pkt >> lighting.exposure.luminance_min
|
||||
>> lighting.exposure.luminance_max
|
||||
>> lighting.exposure.exposure_correction
|
||||
>> lighting.exposure.speed_dark_bright
|
||||
>> lighting.exposure.speed_bright_dark
|
||||
>> lighting.exposure.center_weight_power;
|
||||
|
||||
if (pkt->getRemainingBytes() < 4)
|
||||
return;
|
||||
*pkt >> lighting.volumetric_light_strength;
|
||||
|
||||
if (pkt->getRemainingBytes() < 4)
|
||||
return;
|
||||
*pkt >> lighting.ambient_light;
|
||||
}
|
||||
|
@ -2534,6 +2534,13 @@ int ObjectRef::l_set_lighting(lua_State *L)
|
||||
}
|
||||
lua_pop(L, 1); // shadows
|
||||
|
||||
lua_getfield(L, 2, "ambient_light");
|
||||
if (!lua_isnil(L, -1)) {
|
||||
read_color(L, -1, &lighting.ambient_light);
|
||||
lighting.ambient_light.setAlpha(255); // alpha should always be 255
|
||||
}
|
||||
lua_pop(L, 1); // ambient light
|
||||
|
||||
getfloatfield(L, -1, "saturation", lighting.saturation);
|
||||
|
||||
lua_getfield(L, 2, "exposure");
|
||||
@ -2553,7 +2560,7 @@ int ObjectRef::l_set_lighting(lua_State *L)
|
||||
lighting.volumetric_light_strength = rangelim(lighting.volumetric_light_strength, 0.0f, 1.0f);
|
||||
}
|
||||
lua_pop(L, 1); // volumetric_light
|
||||
}
|
||||
}
|
||||
|
||||
getServer(L)->setLighting(player, lighting);
|
||||
return 0;
|
||||
@ -2575,6 +2582,16 @@ int ObjectRef::l_get_lighting(lua_State *L)
|
||||
lua_pushnumber(L, lighting.shadow_intensity);
|
||||
lua_setfield(L, -2, "intensity");
|
||||
lua_setfield(L, -2, "shadows");
|
||||
lua_newtable(L); // "ambient_light"
|
||||
lua_pushnumber(L, lighting.ambient_light.getRed());
|
||||
lua_setfield(L, -2, "r");
|
||||
lua_pushnumber(L, lighting.ambient_light.getGreen());
|
||||
lua_setfield(L, -2, "g");
|
||||
lua_pushnumber(L, lighting.ambient_light.getBlue());
|
||||
lua_setfield(L, -2, "b");
|
||||
lua_pushnumber(L, 255);
|
||||
lua_setfield(L, -2, "a");
|
||||
lua_setfield(L, -2, "ambient_light");
|
||||
lua_pushnumber(L, lighting.saturation);
|
||||
lua_setfield(L, -2, "saturation");
|
||||
lua_newtable(L); // "exposure"
|
||||
|
@ -1891,6 +1891,8 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting)
|
||||
|
||||
pkt << lighting.volumetric_light_strength;
|
||||
|
||||
pkt << lighting.ambient_light;
|
||||
|
||||
Send(&pkt);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user