mirror of
https://github.com/luanti-org/luanti.git
synced 2026-01-04 04:05:21 +01:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -131,6 +131,7 @@ if(NOT CUSTOM_LOCALEDIR STREQUAL "")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/builtin" DESTINATION "${SHAREDIR}")
|
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/builtin" DESTINATION "${SHAREDIR}")
|
||||||
|
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/client" DESTINATION "${SHAREDIR}")
|
||||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/minimal" DESTINATION "${SHAREDIR}/games")
|
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/minimal" DESTINATION "${SHAREDIR}/games")
|
||||||
set(MINETEST_GAME_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/games/minetest_game")
|
set(MINETEST_GAME_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/games/minetest_game")
|
||||||
if(EXISTS ${MINETEST_GAME_SOURCE} AND IS_DIRECTORY ${MINETEST_GAME_SOURCE})
|
if(EXISTS ${MINETEST_GAME_SOURCE} AND IS_DIRECTORY ${MINETEST_GAME_SOURCE})
|
||||||
|
|||||||
@@ -91,6 +91,48 @@ function spawn_falling_node(p, nodename)
|
|||||||
obj:get_luaentity():set_node(nodename)
|
obj:get_luaentity():set_node(nodename)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function drop_attached_node(p)
|
||||||
|
local nn = minetest.env:get_node(p).name
|
||||||
|
minetest.env:remove_node(p)
|
||||||
|
for _,item in ipairs(minetest.get_node_drops(nn, "")) do
|
||||||
|
local pos = {
|
||||||
|
x = p.x + math.random(60)/60-0.3,
|
||||||
|
y = p.y + math.random(60)/60-0.3,
|
||||||
|
z = p.z + math.random(60)/60-0.3,
|
||||||
|
}
|
||||||
|
minetest.env:add_item(pos, item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function check_attached_node(p, n)
|
||||||
|
local def = minetest.registered_nodes[n.name]
|
||||||
|
local d = {x=0, y=0, z=0}
|
||||||
|
if def.paramtype2 == "wallmounted" then
|
||||||
|
if n.param2 == 0 then
|
||||||
|
d.y = 1
|
||||||
|
elseif n.param2 == 1 then
|
||||||
|
d.y = -1
|
||||||
|
elseif n.param2 == 2 then
|
||||||
|
d.x = 1
|
||||||
|
elseif n.param2 == 3 then
|
||||||
|
d.x = -1
|
||||||
|
elseif n.param2 == 4 then
|
||||||
|
d.z = 1
|
||||||
|
elseif n.param2 == 5 then
|
||||||
|
d.z = -1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
d.y = -1
|
||||||
|
end
|
||||||
|
local p2 = {x=p.x+d.x, y=p.y+d.y, z=p.z+d.z}
|
||||||
|
local nn = minetest.env:get_node(p2).name
|
||||||
|
local def2 = minetest.registered_nodes[nn]
|
||||||
|
if def2 and not def2.walkable then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Some common functions
|
-- Some common functions
|
||||||
--
|
--
|
||||||
@@ -108,6 +150,13 @@ function nodeupdate_single(p)
|
|||||||
nodeupdate(p)
|
nodeupdate(p)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if minetest.get_node_group(n.name, "attached_node") ~= 0 then
|
||||||
|
if not check_attached_node(p, n) then
|
||||||
|
drop_attached_node(p)
|
||||||
|
nodeupdate(p)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function nodeupdate(p)
|
function nodeupdate(p)
|
||||||
|
|||||||
@@ -181,6 +181,14 @@ function minetest.item_place_node(itemstack, placer, pointed_thing)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Check if the node is attached and if it can be placed there
|
||||||
|
if minetest.get_item_group(def.name, "attached_node") ~= 0 and
|
||||||
|
not check_attached_node(place_to, newnode) then
|
||||||
|
minetest.log("action", "attached node " .. def.name ..
|
||||||
|
" can not be placed at " .. minetest.pos_to_string(place_to))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- Add node and update
|
-- Add node and update
|
||||||
minetest.env:add_node(place_to, newnode)
|
minetest.env:add_node(place_to, newnode)
|
||||||
|
|
||||||
|
|||||||
1
client/shaders/test_shader_1/base.txt
Normal file
1
client/shaders/test_shader_1/base.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
trans_alphach_ref
|
||||||
25
client/shaders/test_shader_1/opengl_fragment.glsl
Normal file
25
client/shaders/test_shader_1/opengl_fragment.glsl
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
uniform sampler2D myTexture;
|
||||||
|
uniform vec4 skyBgColor;
|
||||||
|
uniform float fogDistance;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
|
||||||
|
void main (void)
|
||||||
|
{
|
||||||
|
//vec4 col = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
|
vec4 col = texture2D(myTexture, vec2(gl_TexCoord[0]));
|
||||||
|
float a = col.a;
|
||||||
|
col *= gl_Color;
|
||||||
|
col = col * col; // SRGB -> Linear
|
||||||
|
col *= 1.8;
|
||||||
|
col.r = 1.0 - exp(1.0 - col.r) / exp(1.0);
|
||||||
|
col.g = 1.0 - exp(1.0 - col.g) / exp(1.0);
|
||||||
|
col.b = 1.0 - exp(1.0 - col.b) / exp(1.0);
|
||||||
|
col = sqrt(col); // Linear -> SRGB
|
||||||
|
if(fogDistance != 0.0){
|
||||||
|
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
||||||
|
col = mix(col, skyBgColor, d);
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(col.r, col.g, col.b, a);
|
||||||
|
}
|
||||||
25
client/shaders/test_shader_1/opengl_vertex.glsl
Normal file
25
client/shaders/test_shader_1/opengl_vertex.glsl
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
uniform mat4 mWorldViewProj;
|
||||||
|
uniform mat4 mInvWorld;
|
||||||
|
uniform mat4 mTransWorld;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
gl_Position = mWorldViewProj * gl_Vertex;
|
||||||
|
|
||||||
|
vPosition = (mWorldViewProj * gl_Vertex).xyz;
|
||||||
|
|
||||||
|
if(gl_Normal.y > 0.5)
|
||||||
|
gl_FrontColor = gl_BackColor = gl_Color;
|
||||||
|
else
|
||||||
|
gl_FrontColor = gl_BackColor = gl_Color * 0.7;
|
||||||
|
|
||||||
|
/*if(gl_Normal.y > 0.5)
|
||||||
|
gl_FrontColor = gl_BackColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
else
|
||||||
|
gl_FrontColor = gl_BackColor = vec4(1.0, 1.0, 1.0, 1.0) * 0.7;*/
|
||||||
|
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
}
|
||||||
1
client/shaders/test_shader_2/base.txt
Normal file
1
client/shaders/test_shader_2/base.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
trans_alphach
|
||||||
23
client/shaders/test_shader_2/opengl_fragment.glsl
Normal file
23
client/shaders/test_shader_2/opengl_fragment.glsl
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
uniform sampler2D myTexture;
|
||||||
|
uniform float fogDistance;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
|
||||||
|
void main (void)
|
||||||
|
{
|
||||||
|
vec4 col = texture2D(myTexture, vec2(gl_TexCoord[0]));
|
||||||
|
col *= gl_Color;
|
||||||
|
float a = gl_Color.a;
|
||||||
|
col = col * col; // SRGB -> Linear
|
||||||
|
col *= 1.8;
|
||||||
|
col.r = 1.0 - exp(1.0 - col.r) / exp(1.0);
|
||||||
|
col.g = 1.0 - exp(1.0 - col.g) / exp(1.0);
|
||||||
|
col.b = 1.0 - exp(1.0 - col.b) / exp(1.0);
|
||||||
|
col = sqrt(col); // Linear -> SRGB
|
||||||
|
if(fogDistance != 0.0){
|
||||||
|
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
||||||
|
a = mix(a, 0.0, d);
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(col.r, col.g, col.b, a);
|
||||||
|
}
|
||||||
20
client/shaders/test_shader_2/opengl_vertex.glsl
Normal file
20
client/shaders/test_shader_2/opengl_vertex.glsl
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
uniform mat4 mWorldViewProj;
|
||||||
|
uniform mat4 mInvWorld;
|
||||||
|
uniform mat4 mTransWorld;
|
||||||
|
|
||||||
|
varying vec3 vPosition;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
vec4 pos = gl_Vertex;
|
||||||
|
pos.y -= 2.0;
|
||||||
|
gl_Position = mWorldViewProj * pos;
|
||||||
|
|
||||||
|
vPosition = (mWorldViewProj * gl_Vertex).xyz;
|
||||||
|
|
||||||
|
gl_FrontColor = gl_BackColor = gl_Color;
|
||||||
|
//gl_FrontColor = gl_BackColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
}
|
||||||
@@ -457,6 +457,9 @@ Special groups
|
|||||||
- fall_damage_add_percent: damage speed = speed * (1 + value/100)
|
- fall_damage_add_percent: damage speed = speed * (1 + value/100)
|
||||||
- bouncy: value is bounce speed in percent
|
- bouncy: value is bounce speed in percent
|
||||||
- falling_node: if there is no walkable block under the node it will fall
|
- falling_node: if there is no walkable block under the node it will fall
|
||||||
|
- attached_node: if the node under it is not a walkable block the node will be
|
||||||
|
dropped as an item. If the node is wallmounted the
|
||||||
|
wallmounted direction is checked.
|
||||||
|
|
||||||
Known damage and digging time defining groups
|
Known damage and digging time defining groups
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
@@ -694,6 +697,10 @@ image[<X>,<Y>;<W>,<H>;<texture name>]
|
|||||||
^ Show an image
|
^ Show an image
|
||||||
^ Position and size units are inventory slots
|
^ Position and size units are inventory slots
|
||||||
|
|
||||||
|
item_image[<X>,<Y>;<W>,<H>;<item name>]
|
||||||
|
^ Show an inventory image of registered item/node
|
||||||
|
^ Position and size units are inventory slots
|
||||||
|
|
||||||
background[<X>,<Y>;<W>,<H>;<texture name>]
|
background[<X>,<Y>;<W>,<H>;<texture name>]
|
||||||
^ Use a background. Inventory rectangles are not drawn then.
|
^ Use a background. Inventory rectangles are not drawn then.
|
||||||
^ Position and size units are inventory slots
|
^ Position and size units are inventory slots
|
||||||
@@ -735,6 +742,12 @@ image_button[<X>,<Y>;<W>,<H>;<texture name>;<name>;<label>]
|
|||||||
^ image is the filename of an image
|
^ image is the filename of an image
|
||||||
^ Position and size units are inventory slots
|
^ Position and size units are inventory slots
|
||||||
|
|
||||||
|
item_image_button[<X>,<Y>;<W>,<H>;<item name>;<name>;<label>]
|
||||||
|
^ x, y, w, h, name and label work as per button
|
||||||
|
^ item name is the registered name of an item/node,
|
||||||
|
tooltip will be made out of its descritption
|
||||||
|
^ Position and size units are inventory slots
|
||||||
|
|
||||||
button_exit[<X>,<Y>;<W>,<H>;<name>;<label>]
|
button_exit[<X>,<Y>;<W>,<H>;<name>;<label>]
|
||||||
^ When clicked, fields will be sent and the form will quit.
|
^ When clicked, fields will be sent and the form will quit.
|
||||||
|
|
||||||
|
|||||||
@@ -837,7 +837,7 @@ minetest.register_node("default:junglegrass", {
|
|||||||
wield_image = "default_junglegrass.png",
|
wield_image = "default_junglegrass.png",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
walkable = false,
|
walkable = false,
|
||||||
groups = {snappy=3},
|
groups = {snappy=3,attached_node=1},
|
||||||
sounds = default.node_sound_leaves_defaults(),
|
sounds = default.node_sound_leaves_defaults(),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1106,7 +1106,7 @@ minetest.register_node("default:torch", {
|
|||||||
wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
|
wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
|
||||||
wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
|
wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
|
||||||
},
|
},
|
||||||
groups = {choppy=2,dig_immediate=3},
|
groups = {choppy=2,dig_immediate=3,attached_node=1},
|
||||||
legacy_wallmounted = true,
|
legacy_wallmounted = true,
|
||||||
sounds = default.node_sound_defaults(),
|
sounds = default.node_sound_defaults(),
|
||||||
})
|
})
|
||||||
@@ -1127,7 +1127,7 @@ minetest.register_node("default:sign_wall", {
|
|||||||
--wall_bottom = <default>
|
--wall_bottom = <default>
|
||||||
--wall_side = <default>
|
--wall_side = <default>
|
||||||
},
|
},
|
||||||
groups = {choppy=2,dig_immediate=2},
|
groups = {choppy=2,dig_immediate=2,attached_node=1},
|
||||||
legacy_wallmounted = true,
|
legacy_wallmounted = true,
|
||||||
sounds = default.node_sound_defaults(),
|
sounds = default.node_sound_defaults(),
|
||||||
on_construct = function(pos)
|
on_construct = function(pos)
|
||||||
@@ -1495,7 +1495,7 @@ minetest.register_node("default:sapling", {
|
|||||||
wield_image = "default_sapling.png",
|
wield_image = "default_sapling.png",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
walkable = false,
|
walkable = false,
|
||||||
groups = {snappy=2,dig_immediate=3},
|
groups = {snappy=2,dig_immediate=3,attached_node=1},
|
||||||
sounds = default.node_sound_defaults(),
|
sounds = default.node_sound_defaults(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -117,6 +117,9 @@
|
|||||||
#screenshot_path = .
|
#screenshot_path = .
|
||||||
# Amount of view bobbing (0 = no view bobbing, 1.0 = normal, 2.0 = double)
|
# Amount of view bobbing (0 = no view bobbing, 1.0 = normal, 2.0 = double)
|
||||||
#view_bobbing_amount = 1.0
|
#view_bobbing_amount = 1.0
|
||||||
|
# Anaglyph stereo
|
||||||
|
#anaglyph = false
|
||||||
|
#anaglyph_strength = 0.1
|
||||||
# In-game chat console background color (R,G,B)
|
# In-game chat console background color (R,G,B)
|
||||||
#console_color = (0,0,0)
|
#console_color = (0,0,0)
|
||||||
# In-game chat console background alpha (opaqueness, between 0 and 255)
|
# In-game chat console background alpha (opaqueness, between 0 and 255)
|
||||||
@@ -126,6 +129,17 @@
|
|||||||
#sound_volume = 0.7
|
#sound_volume = 0.7
|
||||||
# Whether node texture animations should be desynchronized per MapBlock
|
# Whether node texture animations should be desynchronized per MapBlock
|
||||||
#desynchronize_mapblock_texture_animation = true
|
#desynchronize_mapblock_texture_animation = true
|
||||||
|
# Texture filtering settings
|
||||||
|
#mip_map = false
|
||||||
|
#anisotropic_filter = false
|
||||||
|
#bilinear_filter = false
|
||||||
|
#trilinear_filter = false
|
||||||
|
# Set to true to pre-generate all item visuals
|
||||||
|
#preload_item_visuals = false
|
||||||
|
# 0: disable shaders
|
||||||
|
# (1: low level shaders; not implemented)
|
||||||
|
# 2: enable high level shaders
|
||||||
|
#enable_shaders = 2
|
||||||
|
|
||||||
#
|
#
|
||||||
# Server stuff
|
# Server stuff
|
||||||
|
|||||||
@@ -262,6 +262,7 @@ set(minetest_SRCS
|
|||||||
client.cpp
|
client.cpp
|
||||||
filecache.cpp
|
filecache.cpp
|
||||||
tile.cpp
|
tile.cpp
|
||||||
|
shader.cpp
|
||||||
game.cpp
|
game.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ void Camera::step(f32 dtime)
|
|||||||
|
|
||||||
if (m_digging_button != -1)
|
if (m_digging_button != -1)
|
||||||
{
|
{
|
||||||
f32 offset = dtime * 4.5;
|
f32 offset = dtime * 3.5;
|
||||||
float m_digging_anim_was = m_digging_anim;
|
float m_digging_anim_was = m_digging_anim;
|
||||||
m_digging_anim += offset;
|
m_digging_anim += offset;
|
||||||
if (m_digging_anim >= 1)
|
if (m_digging_anim >= 1)
|
||||||
@@ -529,7 +529,7 @@ void Camera::setDigging(s32 button)
|
|||||||
void Camera::wield(const ItemStack &item)
|
void Camera::wield(const ItemStack &item)
|
||||||
{
|
{
|
||||||
IItemDefManager *idef = m_gamedef->idef();
|
IItemDefManager *idef = m_gamedef->idef();
|
||||||
scene::IMesh *wield_mesh = item.getDefinition(idef).wield_mesh;
|
scene::IMesh *wield_mesh = idef->getWieldMesh(item.getDefinition(idef).name, m_gamedef);
|
||||||
if(wield_mesh)
|
if(wield_mesh)
|
||||||
{
|
{
|
||||||
m_wieldnode->setMesh(wield_mesh);
|
m_wieldnode->setMesh(wield_mesh);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "nodemetadata.h"
|
#include "nodemetadata.h"
|
||||||
#include "nodedef.h"
|
#include "nodedef.h"
|
||||||
#include "itemdef.h"
|
#include "itemdef.h"
|
||||||
|
#include "shader.h"
|
||||||
#include <IFileSystem.h>
|
#include <IFileSystem.h>
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
@@ -228,12 +229,14 @@ Client::Client(
|
|||||||
std::string password,
|
std::string password,
|
||||||
MapDrawControl &control,
|
MapDrawControl &control,
|
||||||
IWritableTextureSource *tsrc,
|
IWritableTextureSource *tsrc,
|
||||||
|
IWritableShaderSource *shsrc,
|
||||||
IWritableItemDefManager *itemdef,
|
IWritableItemDefManager *itemdef,
|
||||||
IWritableNodeDefManager *nodedef,
|
IWritableNodeDefManager *nodedef,
|
||||||
ISoundManager *sound,
|
ISoundManager *sound,
|
||||||
MtEventManager *event
|
MtEventManager *event
|
||||||
):
|
):
|
||||||
m_tsrc(tsrc),
|
m_tsrc(tsrc),
|
||||||
|
m_shsrc(shsrc),
|
||||||
m_itemdef(itemdef),
|
m_itemdef(itemdef),
|
||||||
m_nodedef(nodedef),
|
m_nodedef(nodedef),
|
||||||
m_sound(sound),
|
m_sound(sound),
|
||||||
@@ -1468,8 +1471,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||||||
|
|
||||||
int num_files = readU16(is);
|
int num_files = readU16(is);
|
||||||
|
|
||||||
verbosestream<<"Client received TOCLIENT_ANNOUNCE_MEDIA ("
|
infostream<<"Client: Received media announcement: packet size: "
|
||||||
<<num_files<<" files)"<<std::endl;
|
<<datasize<<std::endl;
|
||||||
|
|
||||||
core::list<MediaRequest> file_requests;
|
core::list<MediaRequest> file_requests;
|
||||||
|
|
||||||
@@ -2438,7 +2441,7 @@ ClientEvent Client::getClientEvent()
|
|||||||
|
|
||||||
void Client::afterContentReceived()
|
void Client::afterContentReceived()
|
||||||
{
|
{
|
||||||
verbosestream<<"Client::afterContentReceived() started"<<std::endl;
|
infostream<<"Client::afterContentReceived() started"<<std::endl;
|
||||||
assert(m_itemdef_received);
|
assert(m_itemdef_received);
|
||||||
assert(m_nodedef_received);
|
assert(m_nodedef_received);
|
||||||
assert(m_media_received);
|
assert(m_media_received);
|
||||||
@@ -2448,31 +2451,43 @@ void Client::afterContentReceived()
|
|||||||
m_media_name_sha1_map.clear();
|
m_media_name_sha1_map.clear();
|
||||||
|
|
||||||
// Rebuild inherited images and recreate textures
|
// Rebuild inherited images and recreate textures
|
||||||
verbosestream<<"Rebuilding images and textures"<<std::endl;
|
infostream<<"- Rebuilding images and textures"<<std::endl;
|
||||||
m_tsrc->rebuildImagesAndTextures();
|
m_tsrc->rebuildImagesAndTextures();
|
||||||
|
|
||||||
// Update texture atlas
|
// Update texture atlas
|
||||||
verbosestream<<"Updating texture atlas"<<std::endl;
|
infostream<<"- Updating texture atlas"<<std::endl;
|
||||||
if(g_settings->getBool("enable_texture_atlas"))
|
if(g_settings->getBool("enable_texture_atlas"))
|
||||||
m_tsrc->buildMainAtlas(this);
|
m_tsrc->buildMainAtlas(this);
|
||||||
|
|
||||||
|
// Rebuild shaders
|
||||||
|
m_shsrc->rebuildShaders();
|
||||||
|
|
||||||
// Update node aliases
|
// Update node aliases
|
||||||
verbosestream<<"Updating node aliases"<<std::endl;
|
infostream<<"- Updating node aliases"<<std::endl;
|
||||||
m_nodedef->updateAliases(m_itemdef);
|
m_nodedef->updateAliases(m_itemdef);
|
||||||
|
|
||||||
// Update node textures
|
// Update node textures
|
||||||
verbosestream<<"Updating node textures"<<std::endl;
|
infostream<<"- Updating node textures"<<std::endl;
|
||||||
m_nodedef->updateTextures(m_tsrc);
|
m_nodedef->updateTextures(m_tsrc);
|
||||||
|
|
||||||
// Update item textures and meshes
|
// Preload item textures and meshes if configured to
|
||||||
verbosestream<<"Updating item textures and meshes"<<std::endl;
|
if(g_settings->getBool("preload_item_visuals"))
|
||||||
m_itemdef->updateTexturesAndMeshes(this);
|
{
|
||||||
|
verbosestream<<"Updating item textures and meshes"<<std::endl;
|
||||||
|
std::set<std::string> names = m_itemdef->getAll();
|
||||||
|
for(std::set<std::string>::const_iterator
|
||||||
|
i = names.begin(); i != names.end(); ++i){
|
||||||
|
// Asking for these caches the result
|
||||||
|
m_itemdef->getInventoryTexture(*i, this);
|
||||||
|
m_itemdef->getWieldMesh(*i, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Start mesh update thread after setting up content definitions
|
// Start mesh update thread after setting up content definitions
|
||||||
verbosestream<<"Starting mesh update thread"<<std::endl;
|
infostream<<"- Starting mesh update thread"<<std::endl;
|
||||||
m_mesh_update_thread.Start();
|
m_mesh_update_thread.Start();
|
||||||
|
|
||||||
verbosestream<<"Client::afterContentReceived() done"<<std::endl;
|
infostream<<"Client::afterContentReceived() done"<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Client::getRTT(void)
|
float Client::getRTT(void)
|
||||||
@@ -2503,6 +2518,10 @@ ITextureSource* Client::getTextureSource()
|
|||||||
{
|
{
|
||||||
return m_tsrc;
|
return m_tsrc;
|
||||||
}
|
}
|
||||||
|
IShaderSource* Client::getShaderSource()
|
||||||
|
{
|
||||||
|
return m_shsrc;
|
||||||
|
}
|
||||||
u16 Client::allocateUnknownNodeId(const std::string &name)
|
u16 Client::allocateUnknownNodeId(const std::string &name)
|
||||||
{
|
{
|
||||||
errorstream<<"Client::allocateUnknownNodeId(): "
|
errorstream<<"Client::allocateUnknownNodeId(): "
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ struct MeshMakeData;
|
|||||||
class MapBlockMesh;
|
class MapBlockMesh;
|
||||||
class IGameDef;
|
class IGameDef;
|
||||||
class IWritableTextureSource;
|
class IWritableTextureSource;
|
||||||
|
class IWritableShaderSource;
|
||||||
class IWritableItemDefManager;
|
class IWritableItemDefManager;
|
||||||
class IWritableNodeDefManager;
|
class IWritableNodeDefManager;
|
||||||
//class IWritableCraftDefManager;
|
//class IWritableCraftDefManager;
|
||||||
@@ -174,6 +175,7 @@ public:
|
|||||||
std::string password,
|
std::string password,
|
||||||
MapDrawControl &control,
|
MapDrawControl &control,
|
||||||
IWritableTextureSource *tsrc,
|
IWritableTextureSource *tsrc,
|
||||||
|
IWritableShaderSource *shsrc,
|
||||||
IWritableItemDefManager *itemdef,
|
IWritableItemDefManager *itemdef,
|
||||||
IWritableNodeDefManager *nodedef,
|
IWritableNodeDefManager *nodedef,
|
||||||
ISoundManager *sound,
|
ISoundManager *sound,
|
||||||
@@ -305,6 +307,7 @@ public:
|
|||||||
virtual INodeDefManager* getNodeDefManager();
|
virtual INodeDefManager* getNodeDefManager();
|
||||||
virtual ICraftDefManager* getCraftDefManager();
|
virtual ICraftDefManager* getCraftDefManager();
|
||||||
virtual ITextureSource* getTextureSource();
|
virtual ITextureSource* getTextureSource();
|
||||||
|
virtual IShaderSource* getShaderSource();
|
||||||
virtual u16 allocateUnknownNodeId(const std::string &name);
|
virtual u16 allocateUnknownNodeId(const std::string &name);
|
||||||
virtual ISoundManager* getSoundManager();
|
virtual ISoundManager* getSoundManager();
|
||||||
virtual MtEventManager* getEventManager();
|
virtual MtEventManager* getEventManager();
|
||||||
@@ -337,6 +340,7 @@ private:
|
|||||||
IntervalLimiter m_map_timer_and_unload_interval;
|
IntervalLimiter m_map_timer_and_unload_interval;
|
||||||
|
|
||||||
IWritableTextureSource *m_tsrc;
|
IWritableTextureSource *m_tsrc;
|
||||||
|
IWritableShaderSource *m_shsrc;
|
||||||
IWritableItemDefManager *m_itemdef;
|
IWritableItemDefManager *m_itemdef;
|
||||||
IWritableNodeDefManager *m_nodedef;
|
IWritableNodeDefManager *m_nodedef;
|
||||||
ISoundManager *m_sound;
|
ISoundManager *m_sound;
|
||||||
|
|||||||
@@ -472,7 +472,7 @@ void ItemCAO::updateTexture()
|
|||||||
IItemDefManager *idef = m_gamedef->idef();
|
IItemDefManager *idef = m_gamedef->idef();
|
||||||
ItemStack item;
|
ItemStack item;
|
||||||
item.deSerialize(is, idef);
|
item.deSerialize(is, idef);
|
||||||
texture = item.getDefinition(idef).inventory_texture;
|
texture = idef->getInventoryTexture(item.getDefinition(idef).name, m_gamedef);
|
||||||
}
|
}
|
||||||
catch(SerializationError &e)
|
catch(SerializationError &e)
|
||||||
{
|
{
|
||||||
@@ -957,7 +957,7 @@ public:
|
|||||||
infostream<<"textures[0]: "<<m_prop.textures[0]<<std::endl;
|
infostream<<"textures[0]: "<<m_prop.textures[0]<<std::endl;
|
||||||
IItemDefManager *idef = m_gamedef->idef();
|
IItemDefManager *idef = m_gamedef->idef();
|
||||||
ItemStack item(m_prop.textures[0], 1, 0, "", idef);
|
ItemStack item(m_prop.textures[0], 1, 0, "", idef);
|
||||||
scene::IMesh *item_mesh = item.getDefinition(idef).wield_mesh;
|
scene::IMesh *item_mesh = idef->getWieldMesh(item.getDefinition(idef).name, m_gamedef);
|
||||||
|
|
||||||
// Copy mesh to be able to set unique vertex colors
|
// Copy mesh to be able to set unique vertex colors
|
||||||
scene::IMeshManipulator *manip =
|
scene::IMeshManipulator *manip =
|
||||||
|
|||||||
@@ -52,7 +52,10 @@ void set_default_settings(Settings *settings)
|
|||||||
settings->setDefault("keymap_toggle_profiler", "KEY_F6");
|
settings->setDefault("keymap_toggle_profiler", "KEY_F6");
|
||||||
settings->setDefault("keymap_increase_viewing_range_min", "+");
|
settings->setDefault("keymap_increase_viewing_range_min", "+");
|
||||||
settings->setDefault("keymap_decrease_viewing_range_min", "-");
|
settings->setDefault("keymap_decrease_viewing_range_min", "-");
|
||||||
|
settings->setDefault("anaglyph", "false");
|
||||||
|
settings->setDefault("anaglyph_strength", "0.1");
|
||||||
settings->setDefault("aux1_descends", "false");
|
settings->setDefault("aux1_descends", "false");
|
||||||
|
|
||||||
// Some (temporary) keys for debugging
|
// Some (temporary) keys for debugging
|
||||||
settings->setDefault("keymap_print_debug_stacks", "KEY_KEY_P");
|
settings->setDefault("keymap_print_debug_stacks", "KEY_KEY_P");
|
||||||
settings->setDefault("keymap_quicktune_prev", "KEY_HOME");
|
settings->setDefault("keymap_quicktune_prev", "KEY_HOME");
|
||||||
@@ -89,6 +92,7 @@ void set_default_settings(Settings *settings)
|
|||||||
settings->setDefault("smooth_lighting", "true");
|
settings->setDefault("smooth_lighting", "true");
|
||||||
settings->setDefault("enable_texture_atlas", "true");
|
settings->setDefault("enable_texture_atlas", "true");
|
||||||
settings->setDefault("texture_path", "");
|
settings->setDefault("texture_path", "");
|
||||||
|
settings->setDefault("shader_path", "");
|
||||||
settings->setDefault("video_driver", "opengl");
|
settings->setDefault("video_driver", "opengl");
|
||||||
settings->setDefault("free_move", "false");
|
settings->setDefault("free_move", "false");
|
||||||
settings->setDefault("continuous_forward", "false");
|
settings->setDefault("continuous_forward", "false");
|
||||||
@@ -110,6 +114,8 @@ void set_default_settings(Settings *settings)
|
|||||||
settings->setDefault("anisotropic_filter", "false");
|
settings->setDefault("anisotropic_filter", "false");
|
||||||
settings->setDefault("bilinear_filter", "false");
|
settings->setDefault("bilinear_filter", "false");
|
||||||
settings->setDefault("trilinear_filter", "false");
|
settings->setDefault("trilinear_filter", "false");
|
||||||
|
settings->setDefault("preload_item_visuals", "false");
|
||||||
|
settings->setDefault("enable_shaders", "2");
|
||||||
|
|
||||||
// Server stuff
|
// Server stuff
|
||||||
// "map-dir" doesn't exist by default.
|
// "map-dir" doesn't exist by default.
|
||||||
|
|||||||
144
src/game.cpp
144
src/game.cpp
@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <IGUIButton.h>
|
#include <IGUIButton.h>
|
||||||
#include <IGUIStaticText.h>
|
#include <IGUIStaticText.h>
|
||||||
#include <IGUIFont.h>
|
#include <IGUIFont.h>
|
||||||
|
#include <IMaterialRendererServices.h>
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "guiPauseMenu.h"
|
#include "guiPauseMenu.h"
|
||||||
@@ -50,6 +51,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "main.h" // For g_settings
|
#include "main.h" // For g_settings
|
||||||
#include "itemdef.h"
|
#include "itemdef.h"
|
||||||
#include "tile.h" // For TextureSource
|
#include "tile.h" // For TextureSource
|
||||||
|
#include "shader.h" // For ShaderSource
|
||||||
#include "logoutputbuffer.h"
|
#include "logoutputbuffer.h"
|
||||||
#include "subgame.h"
|
#include "subgame.h"
|
||||||
#include "quicktune_shortcutter.h"
|
#include "quicktune_shortcutter.h"
|
||||||
@@ -834,6 +836,49 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GameGlobalShaderConstantSetter : public IShaderConstantSetter
|
||||||
|
{
|
||||||
|
Sky *m_sky;
|
||||||
|
bool *m_force_fog_off;
|
||||||
|
f32 *m_fog_range;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off,
|
||||||
|
f32 *fog_range):
|
||||||
|
m_sky(sky),
|
||||||
|
m_force_fog_off(force_fog_off),
|
||||||
|
m_fog_range(fog_range)
|
||||||
|
{}
|
||||||
|
~GameGlobalShaderConstantSetter() {}
|
||||||
|
|
||||||
|
virtual void onSetConstants(video::IMaterialRendererServices *services,
|
||||||
|
bool is_highlevel)
|
||||||
|
{
|
||||||
|
if(!is_highlevel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Background color
|
||||||
|
video::SColor bgcolor = m_sky->getBgColor();
|
||||||
|
video::SColorf bgcolorf(bgcolor);
|
||||||
|
float bgcolorfa[4] = {
|
||||||
|
bgcolorf.r,
|
||||||
|
bgcolorf.g,
|
||||||
|
bgcolorf.b,
|
||||||
|
bgcolorf.a,
|
||||||
|
};
|
||||||
|
services->setPixelShaderConstant("skyBgColor", bgcolorfa, 4);
|
||||||
|
|
||||||
|
// Fog distance
|
||||||
|
float fog_distance = *m_fog_range;
|
||||||
|
if(*m_force_fog_off)
|
||||||
|
fog_distance = 10000*BS;
|
||||||
|
services->setPixelShaderConstant("fogDistance", &fog_distance, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
IrrlichtDevice *m_device;
|
||||||
|
};
|
||||||
|
|
||||||
void the_game(
|
void the_game(
|
||||||
bool &kill,
|
bool &kill,
|
||||||
bool random_input,
|
bool random_input,
|
||||||
@@ -876,6 +921,9 @@ void the_game(
|
|||||||
// Create texture source
|
// Create texture source
|
||||||
IWritableTextureSource *tsrc = createTextureSource(device);
|
IWritableTextureSource *tsrc = createTextureSource(device);
|
||||||
|
|
||||||
|
// Create shader source
|
||||||
|
IWritableShaderSource *shsrc = createShaderSource(device);
|
||||||
|
|
||||||
// These will be filled by data received from the server
|
// These will be filled by data received from the server
|
||||||
// Create item definition manager
|
// Create item definition manager
|
||||||
IWritableItemDefManager *itemdef = createItemDefManager();
|
IWritableItemDefManager *itemdef = createItemDefManager();
|
||||||
@@ -943,7 +991,7 @@ void the_game(
|
|||||||
MapDrawControl draw_control;
|
MapDrawControl draw_control;
|
||||||
|
|
||||||
Client client(device, playername.c_str(), password, draw_control,
|
Client client(device, playername.c_str(), password, draw_control,
|
||||||
tsrc, itemdef, nodedef, sound, &eventmgr);
|
tsrc, shsrc, itemdef, nodedef, sound, &eventmgr);
|
||||||
|
|
||||||
// Client acts as our GameDef
|
// Client acts as our GameDef
|
||||||
IGameDef *gamedef = &client;
|
IGameDef *gamedef = &client;
|
||||||
@@ -1246,6 +1294,7 @@ void the_game(
|
|||||||
bool show_hud = true;
|
bool show_hud = true;
|
||||||
bool show_chat = true;
|
bool show_chat = true;
|
||||||
bool force_fog_off = false;
|
bool force_fog_off = false;
|
||||||
|
f32 fog_range = 100*BS;
|
||||||
bool disable_camera_update = false;
|
bool disable_camera_update = false;
|
||||||
bool show_debug = g_settings->getBool("show_debug");
|
bool show_debug = g_settings->getBool("show_debug");
|
||||||
bool show_profiler_graph = false;
|
bool show_profiler_graph = false;
|
||||||
@@ -1255,6 +1304,12 @@ void the_game(
|
|||||||
float time_of_day = 0;
|
float time_of_day = 0;
|
||||||
float time_of_day_smooth = 0;
|
float time_of_day_smooth = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Shader constants
|
||||||
|
*/
|
||||||
|
shsrc->addGlobalConstantSetter(
|
||||||
|
new GameGlobalShaderConstantSetter(sky, &force_fog_off, &fog_range));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Main loop
|
Main loop
|
||||||
*/
|
*/
|
||||||
@@ -1416,11 +1471,17 @@ void the_game(
|
|||||||
g_gamecallback->changepassword_requested = false;
|
g_gamecallback->changepassword_requested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Process TextureSource's queue */
|
||||||
Process TextureSource's queue
|
|
||||||
*/
|
|
||||||
tsrc->processQueue();
|
tsrc->processQueue();
|
||||||
|
|
||||||
|
/* Process ItemDefManager's queue */
|
||||||
|
itemdef->processQueue(gamedef);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Process ShaderSource's queue
|
||||||
|
*/
|
||||||
|
shsrc->processQueue();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Random calculations
|
Random calculations
|
||||||
*/
|
*/
|
||||||
@@ -2424,7 +2485,6 @@ void the_game(
|
|||||||
Fog range
|
Fog range
|
||||||
*/
|
*/
|
||||||
|
|
||||||
f32 fog_range;
|
|
||||||
if(farmesh)
|
if(farmesh)
|
||||||
{
|
{
|
||||||
fog_range = BS*farmesh_range;
|
fog_range = BS*farmesh_range;
|
||||||
@@ -2750,6 +2810,76 @@ void the_game(
|
|||||||
{
|
{
|
||||||
TimeTaker timer("smgr");
|
TimeTaker timer("smgr");
|
||||||
smgr->drawAll();
|
smgr->drawAll();
|
||||||
|
|
||||||
|
if(g_settings->getBool("anaglyph"))
|
||||||
|
{
|
||||||
|
irr::core::vector3df oldPosition = camera.getCameraNode()->getPosition();
|
||||||
|
irr::core::vector3df oldTarget = camera.getCameraNode()->getTarget();
|
||||||
|
|
||||||
|
irr::core::matrix4 startMatrix = camera.getCameraNode()->getAbsoluteTransformation();
|
||||||
|
|
||||||
|
irr::core::vector3df focusPoint = (camera.getCameraNode()->getTarget() -
|
||||||
|
camera.getCameraNode()->getAbsolutePosition()).setLength(1) +
|
||||||
|
camera.getCameraNode()->getAbsolutePosition() ;
|
||||||
|
|
||||||
|
//Left eye...
|
||||||
|
irr::core::vector3df leftEye;
|
||||||
|
irr::core::matrix4 leftMove;
|
||||||
|
|
||||||
|
leftMove.setTranslation( irr::core::vector3df(-g_settings->getFloat("anaglyph_strength"),0.0f,0.0f) );
|
||||||
|
leftEye=(startMatrix*leftMove).getTranslation();
|
||||||
|
|
||||||
|
//clear the depth buffer, and color
|
||||||
|
driver->beginScene( true, true, irr::video::SColor(0,200,200,255) );
|
||||||
|
|
||||||
|
driver->getOverrideMaterial().Material.ColorMask = irr::video::ECP_RED;
|
||||||
|
driver->getOverrideMaterial().EnableFlags = irr::video::EMF_COLOR_MASK;
|
||||||
|
driver->getOverrideMaterial().EnablePasses = irr::scene::ESNRP_SKY_BOX +
|
||||||
|
irr::scene::ESNRP_SOLID +
|
||||||
|
irr::scene::ESNRP_TRANSPARENT +
|
||||||
|
irr::scene::ESNRP_TRANSPARENT_EFFECT +
|
||||||
|
irr::scene::ESNRP_SHADOW;
|
||||||
|
|
||||||
|
camera.getCameraNode()->setPosition( leftEye );
|
||||||
|
camera.getCameraNode()->setTarget( focusPoint );
|
||||||
|
|
||||||
|
smgr->drawAll(); // 'smgr->drawAll();' may go here
|
||||||
|
|
||||||
|
|
||||||
|
//Right eye...
|
||||||
|
irr::core::vector3df rightEye;
|
||||||
|
irr::core::matrix4 rightMove;
|
||||||
|
|
||||||
|
rightMove.setTranslation( irr::core::vector3df(g_settings->getFloat("anaglyph_strength"),0.0f,0.0f) );
|
||||||
|
rightEye=(startMatrix*rightMove).getTranslation();
|
||||||
|
|
||||||
|
//clear the depth buffer
|
||||||
|
driver->clearZBuffer();
|
||||||
|
|
||||||
|
driver->getOverrideMaterial().Material.ColorMask = irr::video::ECP_GREEN + irr::video::ECP_BLUE;
|
||||||
|
driver->getOverrideMaterial().EnableFlags = irr::video::EMF_COLOR_MASK;
|
||||||
|
driver->getOverrideMaterial().EnablePasses = irr::scene::ESNRP_SKY_BOX +
|
||||||
|
irr::scene::ESNRP_SOLID +
|
||||||
|
irr::scene::ESNRP_TRANSPARENT +
|
||||||
|
irr::scene::ESNRP_TRANSPARENT_EFFECT +
|
||||||
|
irr::scene::ESNRP_SHADOW;
|
||||||
|
|
||||||
|
camera.getCameraNode()->setPosition( rightEye );
|
||||||
|
camera.getCameraNode()->setTarget( focusPoint );
|
||||||
|
|
||||||
|
smgr->drawAll(); // 'smgr->drawAll();' may go here
|
||||||
|
|
||||||
|
|
||||||
|
//driver->endScene();
|
||||||
|
|
||||||
|
driver->getOverrideMaterial().Material.ColorMask=irr::video::ECP_ALL;
|
||||||
|
driver->getOverrideMaterial().EnableFlags=0;
|
||||||
|
driver->getOverrideMaterial().EnablePasses=0;
|
||||||
|
|
||||||
|
camera.getCameraNode()->setPosition( oldPosition );
|
||||||
|
camera.getCameraNode()->setTarget( oldTarget );
|
||||||
|
}
|
||||||
|
|
||||||
scenetime = timer.stop(true);
|
scenetime = timer.stop(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2931,9 +3061,11 @@ void the_game(
|
|||||||
|
|
||||||
if(!sound_is_dummy)
|
if(!sound_is_dummy)
|
||||||
delete sound;
|
delete sound;
|
||||||
|
|
||||||
|
delete tsrc;
|
||||||
|
delete shsrc;
|
||||||
delete nodedef;
|
delete nodedef;
|
||||||
delete itemdef;
|
delete itemdef;
|
||||||
delete tsrc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class INodeDefManager;
|
|||||||
class ICraftDefManager;
|
class ICraftDefManager;
|
||||||
class ITextureSource;
|
class ITextureSource;
|
||||||
class ISoundManager;
|
class ISoundManager;
|
||||||
|
class IShaderSource;
|
||||||
class MtEventManager;
|
class MtEventManager;
|
||||||
class IRollbackReportSink;
|
class IRollbackReportSink;
|
||||||
|
|
||||||
@@ -48,6 +49,8 @@ public:
|
|||||||
// This is always thread-safe, but referencing the irrlicht texture
|
// This is always thread-safe, but referencing the irrlicht texture
|
||||||
// pointers in other threads than main thread will make things explode.
|
// pointers in other threads than main thread will make things explode.
|
||||||
virtual ITextureSource* getTextureSource()=0;
|
virtual ITextureSource* getTextureSource()=0;
|
||||||
|
|
||||||
|
virtual IShaderSource* getShaderSource()=0;
|
||||||
|
|
||||||
// Used for keeping track of names/ids of unknown nodes
|
// Used for keeping track of names/ids of unknown nodes
|
||||||
virtual u16 allocateUnknownNodeId(const std::string &name)=0;
|
virtual u16 allocateUnknownNodeId(const std::string &name)=0;
|
||||||
@@ -70,6 +73,7 @@ public:
|
|||||||
ICraftDefManager* cdef(){return getCraftDefManager();}
|
ICraftDefManager* cdef(){return getCraftDefManager();}
|
||||||
ITextureSource* tsrc(){return getTextureSource();}
|
ITextureSource* tsrc(){return getTextureSource();}
|
||||||
ISoundManager* sound(){return getSoundManager();}
|
ISoundManager* sound(){return getSoundManager();}
|
||||||
|
IShaderSource* shsrc(){return getShaderSource();}
|
||||||
MtEventManager* event(){return getEventManager();}
|
MtEventManager* event(){return getEventManager();}
|
||||||
IRollbackReportSink* rollback(){return getRollbackReportSink();}
|
IRollbackReportSink* rollback(){return getRollbackReportSink();}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ void drawItemStack(video::IVideoDriver *driver,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const ItemDefinition &def = item.getDefinition(gamedef->idef());
|
const ItemDefinition &def = item.getDefinition(gamedef->idef());
|
||||||
video::ITexture *texture = def.inventory_texture;
|
video::ITexture *texture = gamedef->idef()->getInventoryTexture(def.name, gamedef);
|
||||||
|
|
||||||
// Draw the inventory texture
|
// Draw the inventory texture
|
||||||
if(texture != NULL)
|
if(texture != NULL)
|
||||||
@@ -201,6 +201,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
|||||||
m_inventorylists.clear();
|
m_inventorylists.clear();
|
||||||
m_images.clear();
|
m_images.clear();
|
||||||
m_backgrounds.clear();
|
m_backgrounds.clear();
|
||||||
|
m_itemimages.clear();
|
||||||
m_fields.clear();
|
m_fields.clear();
|
||||||
|
|
||||||
Strfnd f(m_formspec_string);
|
Strfnd f(m_formspec_string);
|
||||||
@@ -283,6 +284,23 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
|||||||
errorstream<<"WARNING: invalid use of image without a size[] element"<<std::endl;
|
errorstream<<"WARNING: invalid use of image without a size[] element"<<std::endl;
|
||||||
m_images.push_back(ImageDrawSpec(name, pos, geom));
|
m_images.push_back(ImageDrawSpec(name, pos, geom));
|
||||||
}
|
}
|
||||||
|
else if(type == "item_image")
|
||||||
|
{
|
||||||
|
v2s32 pos = basepos;
|
||||||
|
pos.X += stof(f.next(",")) * (float)spacing.X;
|
||||||
|
pos.Y += stof(f.next(";")) * (float)spacing.Y;
|
||||||
|
v2s32 geom;
|
||||||
|
geom.X = stof(f.next(",")) * (float)imgsize.X;
|
||||||
|
geom.Y = stof(f.next(";")) * (float)imgsize.Y;
|
||||||
|
std::string name = f.next("]");
|
||||||
|
errorstream<<"item name="<<name
|
||||||
|
<<", pos=("<<pos.X<<","<<pos.Y<<")"
|
||||||
|
<<", geom=("<<geom.X<<","<<geom.Y<<")"
|
||||||
|
<<std::endl;
|
||||||
|
if(bp_set != 2)
|
||||||
|
errorstream<<"WARNING: invalid use of item_image without a size[] element"<<std::endl;
|
||||||
|
m_itemimages.push_back(ImageDrawSpec(name, pos, geom));
|
||||||
|
}
|
||||||
else if(type == "background")
|
else if(type == "background")
|
||||||
{
|
{
|
||||||
v2s32 pos = basepos;
|
v2s32 pos = basepos;
|
||||||
@@ -484,6 +502,43 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
|||||||
|
|
||||||
m_fields.push_back(spec);
|
m_fields.push_back(spec);
|
||||||
}
|
}
|
||||||
|
else if(type == "item_image_button")
|
||||||
|
{
|
||||||
|
v2s32 pos = padding;
|
||||||
|
pos.X += stof(f.next(",")) * (float)spacing.X;
|
||||||
|
pos.Y += stof(f.next(";")) * (float)spacing.Y;
|
||||||
|
v2s32 geom;
|
||||||
|
geom.X = (stof(f.next(",")) * (float)spacing.X)-(spacing.X-imgsize.X);
|
||||||
|
geom.Y = (stof(f.next(";")) * (float)spacing.Y)-(spacing.Y-imgsize.Y);
|
||||||
|
rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
|
||||||
|
std::string fimage = f.next(";");
|
||||||
|
std::string fname = f.next(";");
|
||||||
|
std::string flabel = f.next("]");
|
||||||
|
if(bp_set != 2)
|
||||||
|
errorstream<<"WARNING: invalid use of item_image_button without a size[] element"<<std::endl;
|
||||||
|
IItemDefManager *idef = m_gamedef->idef();
|
||||||
|
ItemStack item;
|
||||||
|
item.deSerialize(fimage, idef);
|
||||||
|
video::ITexture *texture = idef->getInventoryTexture(item.getDefinition(idef).name, m_gamedef);
|
||||||
|
std::string tooltip = item.getDefinition(idef).description;
|
||||||
|
FieldSpec spec = FieldSpec(
|
||||||
|
narrow_to_wide(fname.c_str()),
|
||||||
|
narrow_to_wide(flabel.c_str()),
|
||||||
|
narrow_to_wide(fimage.c_str()),
|
||||||
|
258+m_fields.size()
|
||||||
|
);
|
||||||
|
gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, spec.flabel.c_str());
|
||||||
|
e->setUseAlphaChannel(true);
|
||||||
|
e->setImage(texture);
|
||||||
|
e->setPressedImage(texture);
|
||||||
|
e->setScaleImage(true);
|
||||||
|
spec.is_button = true;
|
||||||
|
rect+=basepos-padding;
|
||||||
|
spec.rect=rect;
|
||||||
|
if (tooltip!="")
|
||||||
|
spec.tooltip=tooltip;
|
||||||
|
m_fields.push_back(spec);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Ignore others
|
// Ignore others
|
||||||
@@ -767,15 +822,40 @@ void GUIFormSpecMenu::drawMenu()
|
|||||||
drawList(m_inventorylists[i], phase);
|
drawList(m_inventorylists[i], phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Draw dragged item stack
|
|
||||||
*/
|
|
||||||
drawSelectedItem();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Call base class
|
Call base class
|
||||||
*/
|
*/
|
||||||
gui::IGUIElement::draw();
|
gui::IGUIElement::draw();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Draw fields/buttons tooltips
|
||||||
|
*/
|
||||||
|
for(u32 i=0; i<m_fields.size(); i++)
|
||||||
|
{
|
||||||
|
const FieldSpec &spec = m_fields[i];
|
||||||
|
if (spec.tooltip != "")
|
||||||
|
{
|
||||||
|
core::rect<s32> rect = spec.rect;
|
||||||
|
if (rect.isPointInside(m_pointer))
|
||||||
|
{
|
||||||
|
m_tooltip_element->setVisible(true);
|
||||||
|
this->bringToFront(m_tooltip_element);
|
||||||
|
m_tooltip_element->setText(narrow_to_wide(spec.tooltip).c_str());
|
||||||
|
s32 tooltip_x = m_pointer.X + 15;
|
||||||
|
s32 tooltip_y = m_pointer.Y + 15;
|
||||||
|
s32 tooltip_width = m_tooltip_element->getTextWidth() + 15;
|
||||||
|
s32 tooltip_height = m_tooltip_element->getTextHeight() + 5;
|
||||||
|
m_tooltip_element->setRelativePosition(core::rect<s32>(
|
||||||
|
core::position2d<s32>(tooltip_x, tooltip_y),
|
||||||
|
core::dimension2d<s32>(tooltip_width, tooltip_height)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Draw dragged item stack
|
||||||
|
*/
|
||||||
|
drawSelectedItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::updateSelectedItem()
|
void GUIFormSpecMenu::updateSelectedItem()
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ class GUIFormSpecMenu : public GUIModalMenu
|
|||||||
send = false;
|
send = false;
|
||||||
is_button = false;
|
is_button = false;
|
||||||
is_exit = false;
|
is_exit = false;
|
||||||
|
tooltip="";
|
||||||
}
|
}
|
||||||
std::wstring fname;
|
std::wstring fname;
|
||||||
std::wstring flabel;
|
std::wstring flabel;
|
||||||
@@ -141,6 +142,8 @@ class GUIFormSpecMenu : public GUIModalMenu
|
|||||||
bool send;
|
bool send;
|
||||||
bool is_button;
|
bool is_button;
|
||||||
bool is_exit;
|
bool is_exit;
|
||||||
|
core::rect<s32> rect;
|
||||||
|
std::string tooltip;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -209,6 +212,7 @@ protected:
|
|||||||
core::array<ListDrawSpec> m_inventorylists;
|
core::array<ListDrawSpec> m_inventorylists;
|
||||||
core::array<ImageDrawSpec> m_backgrounds;
|
core::array<ImageDrawSpec> m_backgrounds;
|
||||||
core::array<ImageDrawSpec> m_images;
|
core::array<ImageDrawSpec> m_images;
|
||||||
|
core::array<ImageDrawSpec> m_itemimages;
|
||||||
core::array<FieldSpec> m_fields;
|
core::array<FieldSpec> m_fields;
|
||||||
|
|
||||||
ItemSpec *m_selected_item;
|
ItemSpec *m_selected_item;
|
||||||
|
|||||||
@@ -102,6 +102,8 @@ enum
|
|||||||
GUI_ID_ANISOTROPIC_CB,
|
GUI_ID_ANISOTROPIC_CB,
|
||||||
GUI_ID_BILINEAR_CB,
|
GUI_ID_BILINEAR_CB,
|
||||||
GUI_ID_TRILINEAR_CB,
|
GUI_ID_TRILINEAR_CB,
|
||||||
|
GUI_ID_SHADERS_CB,
|
||||||
|
GUI_ID_PRELOAD_ITEM_VISUALS_CB,
|
||||||
GUI_ID_DAMAGE_CB,
|
GUI_ID_DAMAGE_CB,
|
||||||
GUI_ID_CREATIVE_CB,
|
GUI_ID_CREATIVE_CB,
|
||||||
GUI_ID_JOIN_GAME_BUTTON,
|
GUI_ID_JOIN_GAME_BUTTON,
|
||||||
@@ -616,6 +618,21 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
|
|||||||
GUI_ID_TRILINEAR_CB, wgettext("Tri-Linear Filtering"));
|
GUI_ID_TRILINEAR_CB, wgettext("Tri-Linear Filtering"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shader/on demand image loading settings
|
||||||
|
{
|
||||||
|
core::rect<s32> rect(0, 0, option_w+20, 30);
|
||||||
|
rect += m_topleft_client + v2s32(option_x+175*2, option_y);
|
||||||
|
Environment->addCheckBox(m_data->enable_shaders, rect, this,
|
||||||
|
GUI_ID_SHADERS_CB, wgettext("Shaders"));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
core::rect<s32> rect(0, 0, option_w+20+20, 30);
|
||||||
|
rect += m_topleft_client + v2s32(option_x+175*2, option_y+20);
|
||||||
|
Environment->addCheckBox(m_data->preload_item_visuals, rect, this,
|
||||||
|
GUI_ID_PRELOAD_ITEM_VISUALS_CB, wgettext("Preload item visuals"));
|
||||||
|
}
|
||||||
|
|
||||||
// Key change button
|
// Key change button
|
||||||
{
|
{
|
||||||
core::rect<s32> rect(0, 0, 120, 30);
|
core::rect<s32> rect(0, 0, 120, 30);
|
||||||
@@ -820,6 +837,18 @@ void GUIMainMenu::readInput(MainMenuData *dst)
|
|||||||
dst->trilinear_filter = ((gui::IGUICheckBox*)e)->isChecked();
|
dst->trilinear_filter = ((gui::IGUICheckBox*)e)->isChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
gui::IGUIElement *e = getElementFromId(GUI_ID_SHADERS_CB);
|
||||||
|
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
|
||||||
|
dst->enable_shaders = ((gui::IGUICheckBox*)e)->isChecked() ? 2 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
gui::IGUIElement *e = getElementFromId(GUI_ID_PRELOAD_ITEM_VISUALS_CB);
|
||||||
|
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
|
||||||
|
dst->preload_item_visuals = ((gui::IGUICheckBox*)e)->isChecked();
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
|
gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
|
||||||
if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
|
if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ struct MainMenuData
|
|||||||
bool anisotropic_filter;
|
bool anisotropic_filter;
|
||||||
bool bilinear_filter;
|
bool bilinear_filter;
|
||||||
bool trilinear_filter;
|
bool trilinear_filter;
|
||||||
|
int enable_shaders;
|
||||||
|
bool preload_item_visuals;
|
||||||
// Server options
|
// Server options
|
||||||
bool creative_mode;
|
bool creative_mode;
|
||||||
bool enable_damage;
|
bool enable_damage;
|
||||||
|
|||||||
440
src/itemdef.cpp
440
src/itemdef.cpp
@@ -31,6 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#endif
|
#endif
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "util/serialize.h"
|
#include "util/serialize.h"
|
||||||
|
#include "util/container.h"
|
||||||
|
#include "util/thread.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
@@ -71,14 +73,6 @@ ItemDefinition& ItemDefinition::operator=(const ItemDefinition &def)
|
|||||||
}
|
}
|
||||||
groups = def.groups;
|
groups = def.groups;
|
||||||
node_placement_prediction = def.node_placement_prediction;
|
node_placement_prediction = def.node_placement_prediction;
|
||||||
#ifndef SERVER
|
|
||||||
inventory_texture = def.inventory_texture;
|
|
||||||
if(def.wield_mesh)
|
|
||||||
{
|
|
||||||
wield_mesh = def.wield_mesh;
|
|
||||||
wield_mesh->grab();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,10 +85,6 @@ void ItemDefinition::resetInitial()
|
|||||||
{
|
{
|
||||||
// Initialize pointers to NULL so reset() does not delete undefined pointers
|
// Initialize pointers to NULL so reset() does not delete undefined pointers
|
||||||
tool_capabilities = NULL;
|
tool_capabilities = NULL;
|
||||||
#ifndef SERVER
|
|
||||||
inventory_texture = NULL;
|
|
||||||
wield_mesh = NULL;
|
|
||||||
#endif
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,15 +107,6 @@ void ItemDefinition::reset()
|
|||||||
groups.clear();
|
groups.clear();
|
||||||
|
|
||||||
node_placement_prediction = "";
|
node_placement_prediction = "";
|
||||||
|
|
||||||
#ifndef SERVER
|
|
||||||
inventory_texture = NULL;
|
|
||||||
if(wield_mesh)
|
|
||||||
{
|
|
||||||
wield_mesh->drop();
|
|
||||||
wield_mesh = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemDefinition::serialize(std::ostream &os) const
|
void ItemDefinition::serialize(std::ostream &os) const
|
||||||
@@ -203,13 +184,39 @@ void ItemDefinition::deSerialize(std::istream &is)
|
|||||||
|
|
||||||
class CItemDefManager: public IWritableItemDefManager
|
class CItemDefManager: public IWritableItemDefManager
|
||||||
{
|
{
|
||||||
|
#ifndef SERVER
|
||||||
|
struct ClientCached
|
||||||
|
{
|
||||||
|
video::ITexture *inventory_texture;
|
||||||
|
scene::IMesh *wield_mesh;
|
||||||
|
|
||||||
|
ClientCached():
|
||||||
|
inventory_texture(NULL),
|
||||||
|
wield_mesh(NULL)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CItemDefManager()
|
CItemDefManager()
|
||||||
{
|
{
|
||||||
|
#ifndef SERVER
|
||||||
|
m_main_thread = get_current_thread_id();
|
||||||
|
#endif
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
virtual ~CItemDefManager()
|
virtual ~CItemDefManager()
|
||||||
{
|
{
|
||||||
|
#ifndef SERVER
|
||||||
|
const core::list<ClientCached*> &values = m_clientcached.getValues();
|
||||||
|
for(core::list<ClientCached*>::ConstIterator
|
||||||
|
i = values.begin(); i != values.end(); ++i)
|
||||||
|
{
|
||||||
|
ClientCached *cc = *i;
|
||||||
|
cc->wield_mesh->drop();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
virtual const ItemDefinition& get(const std::string &name_) const
|
virtual const ItemDefinition& get(const std::string &name_) const
|
||||||
{
|
{
|
||||||
@@ -256,6 +263,220 @@ public:
|
|||||||
std::map<std::string, ItemDefinition*>::const_iterator i;
|
std::map<std::string, ItemDefinition*>::const_iterator i;
|
||||||
return m_item_definitions.find(name) != m_item_definitions.end();
|
return m_item_definitions.find(name) != m_item_definitions.end();
|
||||||
}
|
}
|
||||||
|
#ifndef SERVER
|
||||||
|
ClientCached* createClientCachedDirect(const std::string &name,
|
||||||
|
IGameDef *gamedef) const
|
||||||
|
{
|
||||||
|
infostream<<"Lazily creating item texture and mesh for \""
|
||||||
|
<<name<<"\""<<std::endl;
|
||||||
|
|
||||||
|
// This is not thread-safe
|
||||||
|
assert(get_current_thread_id() == m_main_thread);
|
||||||
|
|
||||||
|
// Skip if already in cache
|
||||||
|
ClientCached *cc = NULL;
|
||||||
|
m_clientcached.get(name, &cc);
|
||||||
|
if(cc)
|
||||||
|
return cc;
|
||||||
|
|
||||||
|
ITextureSource *tsrc = gamedef->getTextureSource();
|
||||||
|
INodeDefManager *nodedef = gamedef->getNodeDefManager();
|
||||||
|
IrrlichtDevice *device = tsrc->getDevice();
|
||||||
|
video::IVideoDriver *driver = device->getVideoDriver();
|
||||||
|
const ItemDefinition *def = &get(name);
|
||||||
|
|
||||||
|
// Create new ClientCached
|
||||||
|
cc = new ClientCached();
|
||||||
|
|
||||||
|
bool need_node_mesh = false;
|
||||||
|
|
||||||
|
// Create an inventory texture
|
||||||
|
cc->inventory_texture = NULL;
|
||||||
|
if(def->inventory_image != "")
|
||||||
|
{
|
||||||
|
cc->inventory_texture = tsrc->getTextureRaw(def->inventory_image);
|
||||||
|
}
|
||||||
|
else if(def->type == ITEM_NODE)
|
||||||
|
{
|
||||||
|
need_node_mesh = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a wield mesh
|
||||||
|
if(cc->wield_mesh != NULL)
|
||||||
|
{
|
||||||
|
cc->wield_mesh->drop();
|
||||||
|
cc->wield_mesh = NULL;
|
||||||
|
}
|
||||||
|
if(def->type == ITEM_NODE && def->wield_image == "")
|
||||||
|
{
|
||||||
|
need_node_mesh = true;
|
||||||
|
}
|
||||||
|
else if(def->wield_image != "" || def->inventory_image != "")
|
||||||
|
{
|
||||||
|
// Extrude the wield image into a mesh
|
||||||
|
|
||||||
|
std::string imagename;
|
||||||
|
if(def->wield_image != "")
|
||||||
|
imagename = def->wield_image;
|
||||||
|
else
|
||||||
|
imagename = def->inventory_image;
|
||||||
|
|
||||||
|
cc->wield_mesh = createExtrudedMesh(
|
||||||
|
tsrc->getTextureRaw(imagename),
|
||||||
|
driver,
|
||||||
|
def->wield_scale * v3f(40.0, 40.0, 4.0));
|
||||||
|
if(cc->wield_mesh == NULL)
|
||||||
|
{
|
||||||
|
infostream<<"ItemDefManager: WARNING: "
|
||||||
|
<<"updateTexturesAndMeshes(): "
|
||||||
|
<<"Unable to create extruded mesh for item "
|
||||||
|
<<def->name<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(need_node_mesh)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Get node properties
|
||||||
|
*/
|
||||||
|
content_t id = nodedef->getId(def->name);
|
||||||
|
const ContentFeatures &f = nodedef->get(id);
|
||||||
|
|
||||||
|
u8 param1 = 0;
|
||||||
|
if(f.param_type == CPT_LIGHT)
|
||||||
|
param1 = 0xee;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Make a mesh from the node
|
||||||
|
*/
|
||||||
|
MeshMakeData mesh_make_data(gamedef);
|
||||||
|
MapNode mesh_make_node(id, param1, 0);
|
||||||
|
mesh_make_data.fillSingleNode(&mesh_make_node);
|
||||||
|
MapBlockMesh mapblock_mesh(&mesh_make_data);
|
||||||
|
|
||||||
|
scene::IMesh *node_mesh = mapblock_mesh.getMesh();
|
||||||
|
assert(node_mesh);
|
||||||
|
setMeshColor(node_mesh, video::SColor(255, 255, 255, 255));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Scale and translate the mesh so it's a unit cube
|
||||||
|
centered on the origin
|
||||||
|
*/
|
||||||
|
scaleMesh(node_mesh, v3f(1.0/BS, 1.0/BS, 1.0/BS));
|
||||||
|
translateMesh(node_mesh, v3f(-1.0, -1.0, -1.0));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Draw node mesh into a render target texture
|
||||||
|
*/
|
||||||
|
if(cc->inventory_texture == NULL)
|
||||||
|
{
|
||||||
|
core::dimension2d<u32> dim(64,64);
|
||||||
|
std::string rtt_texture_name = "INVENTORY_"
|
||||||
|
+ def->name + "_RTT";
|
||||||
|
v3f camera_position(0, 1.0, -1.5);
|
||||||
|
camera_position.rotateXZBy(45);
|
||||||
|
v3f camera_lookat(0, 0, 0);
|
||||||
|
core::CMatrix4<f32> camera_projection_matrix;
|
||||||
|
// Set orthogonal projection
|
||||||
|
camera_projection_matrix.buildProjectionMatrixOrthoLH(
|
||||||
|
1.65, 1.65, 0, 100);
|
||||||
|
|
||||||
|
video::SColorf ambient_light(0.2,0.2,0.2);
|
||||||
|
v3f light_position(10, 100, -50);
|
||||||
|
video::SColorf light_color(0.5,0.5,0.5);
|
||||||
|
f32 light_radius = 1000;
|
||||||
|
|
||||||
|
cc->inventory_texture = generateTextureFromMesh(
|
||||||
|
node_mesh, device, dim, rtt_texture_name,
|
||||||
|
camera_position,
|
||||||
|
camera_lookat,
|
||||||
|
camera_projection_matrix,
|
||||||
|
ambient_light,
|
||||||
|
light_position,
|
||||||
|
light_color,
|
||||||
|
light_radius);
|
||||||
|
|
||||||
|
// render-to-target didn't work
|
||||||
|
if(cc->inventory_texture == NULL)
|
||||||
|
{
|
||||||
|
cc->inventory_texture =
|
||||||
|
tsrc->getTextureRaw(f.tiledef[0].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Use the node mesh as the wield mesh
|
||||||
|
*/
|
||||||
|
if(cc->wield_mesh == NULL)
|
||||||
|
{
|
||||||
|
// Scale to proper wield mesh proportions
|
||||||
|
scaleMesh(node_mesh, v3f(30.0, 30.0, 30.0)
|
||||||
|
* def->wield_scale);
|
||||||
|
cc->wield_mesh = node_mesh;
|
||||||
|
cc->wield_mesh->grab();
|
||||||
|
}
|
||||||
|
|
||||||
|
// falling outside of here deletes node_mesh
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put in cache
|
||||||
|
m_clientcached.set(name, cc);
|
||||||
|
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
ClientCached* getClientCached(const std::string &name,
|
||||||
|
IGameDef *gamedef) const
|
||||||
|
{
|
||||||
|
ClientCached *cc = NULL;
|
||||||
|
m_clientcached.get(name, &cc);
|
||||||
|
if(cc)
|
||||||
|
return cc;
|
||||||
|
|
||||||
|
if(get_current_thread_id() == m_main_thread)
|
||||||
|
{
|
||||||
|
return createClientCachedDirect(name, gamedef);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We're gonna ask the result to be put into here
|
||||||
|
ResultQueue<std::string, ClientCached*, u8, u8> result_queue;
|
||||||
|
// Throw a request in
|
||||||
|
m_get_clientcached_queue.add(name, 0, 0, &result_queue);
|
||||||
|
try{
|
||||||
|
// Wait result for a second
|
||||||
|
GetResult<std::string, ClientCached*, u8, u8>
|
||||||
|
result = result_queue.pop_front(1000);
|
||||||
|
// Check that at least something worked OK
|
||||||
|
assert(result.key == name);
|
||||||
|
// Return it
|
||||||
|
return result.item;
|
||||||
|
}
|
||||||
|
catch(ItemNotFoundException &e)
|
||||||
|
{
|
||||||
|
errorstream<<"Waiting for clientcached timed out."<<std::endl;
|
||||||
|
return &m_dummy_clientcached;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get item inventory texture
|
||||||
|
virtual video::ITexture* getInventoryTexture(const std::string &name,
|
||||||
|
IGameDef *gamedef) const
|
||||||
|
{
|
||||||
|
ClientCached *cc = getClientCached(name, gamedef);
|
||||||
|
if(!cc)
|
||||||
|
return NULL;
|
||||||
|
return cc->inventory_texture;
|
||||||
|
}
|
||||||
|
// Get item wield mesh
|
||||||
|
virtual scene::IMesh* getWieldMesh(const std::string &name,
|
||||||
|
IGameDef *gamedef) const
|
||||||
|
{
|
||||||
|
ClientCached *cc = getClientCached(name, gamedef);
|
||||||
|
if(!cc)
|
||||||
|
return NULL;
|
||||||
|
return cc->wield_mesh;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
for(std::map<std::string, ItemDefinition*>::const_iterator
|
for(std::map<std::string, ItemDefinition*>::const_iterator
|
||||||
@@ -321,157 +542,6 @@ public:
|
|||||||
m_aliases[name] = convert_to;
|
m_aliases[name] = convert_to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updateTexturesAndMeshes(IGameDef *gamedef)
|
|
||||||
{
|
|
||||||
#ifndef SERVER
|
|
||||||
infostream<<"ItemDefManager::updateTexturesAndMeshes(): Updating "
|
|
||||||
<<"textures and meshes in item definitions"<<std::endl;
|
|
||||||
|
|
||||||
ITextureSource *tsrc = gamedef->getTextureSource();
|
|
||||||
INodeDefManager *nodedef = gamedef->getNodeDefManager();
|
|
||||||
IrrlichtDevice *device = tsrc->getDevice();
|
|
||||||
video::IVideoDriver *driver = device->getVideoDriver();
|
|
||||||
|
|
||||||
for(std::map<std::string, ItemDefinition*>::iterator
|
|
||||||
i = m_item_definitions.begin();
|
|
||||||
i != m_item_definitions.end(); i++)
|
|
||||||
{
|
|
||||||
ItemDefinition *def = i->second;
|
|
||||||
|
|
||||||
bool need_node_mesh = false;
|
|
||||||
|
|
||||||
// Create an inventory texture
|
|
||||||
def->inventory_texture = NULL;
|
|
||||||
if(def->inventory_image != "")
|
|
||||||
{
|
|
||||||
def->inventory_texture = tsrc->getTextureRaw(def->inventory_image);
|
|
||||||
}
|
|
||||||
else if(def->type == ITEM_NODE)
|
|
||||||
{
|
|
||||||
need_node_mesh = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a wield mesh
|
|
||||||
if(def->wield_mesh != NULL)
|
|
||||||
{
|
|
||||||
def->wield_mesh->drop();
|
|
||||||
def->wield_mesh = NULL;
|
|
||||||
}
|
|
||||||
if(def->type == ITEM_NODE && def->wield_image == "")
|
|
||||||
{
|
|
||||||
need_node_mesh = true;
|
|
||||||
}
|
|
||||||
else if(def->wield_image != "" || def->inventory_image != "")
|
|
||||||
{
|
|
||||||
// Extrude the wield image into a mesh
|
|
||||||
|
|
||||||
std::string imagename;
|
|
||||||
if(def->wield_image != "")
|
|
||||||
imagename = def->wield_image;
|
|
||||||
else
|
|
||||||
imagename = def->inventory_image;
|
|
||||||
|
|
||||||
def->wield_mesh = createExtrudedMesh(
|
|
||||||
tsrc->getTextureRaw(imagename),
|
|
||||||
driver,
|
|
||||||
def->wield_scale * v3f(40.0, 40.0, 4.0));
|
|
||||||
if(def->wield_mesh == NULL)
|
|
||||||
{
|
|
||||||
infostream<<"ItemDefManager: WARNING: "
|
|
||||||
<<"updateTexturesAndMeshes(): "
|
|
||||||
<<"Unable to create extruded mesh for item "
|
|
||||||
<<def->name<<std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(need_node_mesh)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Get node properties
|
|
||||||
*/
|
|
||||||
content_t id = nodedef->getId(def->name);
|
|
||||||
const ContentFeatures &f = nodedef->get(id);
|
|
||||||
|
|
||||||
u8 param1 = 0;
|
|
||||||
if(f.param_type == CPT_LIGHT)
|
|
||||||
param1 = 0xee;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Make a mesh from the node
|
|
||||||
*/
|
|
||||||
MeshMakeData mesh_make_data(gamedef);
|
|
||||||
MapNode mesh_make_node(id, param1, 0);
|
|
||||||
mesh_make_data.fillSingleNode(&mesh_make_node);
|
|
||||||
MapBlockMesh mapblock_mesh(&mesh_make_data);
|
|
||||||
|
|
||||||
scene::IMesh *node_mesh = mapblock_mesh.getMesh();
|
|
||||||
assert(node_mesh);
|
|
||||||
setMeshColor(node_mesh, video::SColor(255, 255, 255, 255));
|
|
||||||
|
|
||||||
/*
|
|
||||||
Scale and translate the mesh so it's a unit cube
|
|
||||||
centered on the origin
|
|
||||||
*/
|
|
||||||
scaleMesh(node_mesh, v3f(1.0/BS, 1.0/BS, 1.0/BS));
|
|
||||||
translateMesh(node_mesh, v3f(-1.0, -1.0, -1.0));
|
|
||||||
|
|
||||||
/*
|
|
||||||
Draw node mesh into a render target texture
|
|
||||||
*/
|
|
||||||
if(def->inventory_texture == NULL)
|
|
||||||
{
|
|
||||||
core::dimension2d<u32> dim(64,64);
|
|
||||||
std::string rtt_texture_name = "INVENTORY_"
|
|
||||||
+ def->name + "_RTT";
|
|
||||||
v3f camera_position(0, 1.0, -1.5);
|
|
||||||
camera_position.rotateXZBy(45);
|
|
||||||
v3f camera_lookat(0, 0, 0);
|
|
||||||
core::CMatrix4<f32> camera_projection_matrix;
|
|
||||||
// Set orthogonal projection
|
|
||||||
camera_projection_matrix.buildProjectionMatrixOrthoLH(
|
|
||||||
1.65, 1.65, 0, 100);
|
|
||||||
|
|
||||||
video::SColorf ambient_light(0.2,0.2,0.2);
|
|
||||||
v3f light_position(10, 100, -50);
|
|
||||||
video::SColorf light_color(0.5,0.5,0.5);
|
|
||||||
f32 light_radius = 1000;
|
|
||||||
|
|
||||||
def->inventory_texture = generateTextureFromMesh(
|
|
||||||
node_mesh, device, dim, rtt_texture_name,
|
|
||||||
camera_position,
|
|
||||||
camera_lookat,
|
|
||||||
camera_projection_matrix,
|
|
||||||
ambient_light,
|
|
||||||
light_position,
|
|
||||||
light_color,
|
|
||||||
light_radius);
|
|
||||||
|
|
||||||
// render-to-target didn't work
|
|
||||||
if(def->inventory_texture == NULL)
|
|
||||||
{
|
|
||||||
def->inventory_texture =
|
|
||||||
tsrc->getTextureRaw(f.tiledef[0].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Use the node mesh as the wield mesh
|
|
||||||
*/
|
|
||||||
if(def->wield_mesh == NULL)
|
|
||||||
{
|
|
||||||
// Scale to proper wield mesh proportions
|
|
||||||
scaleMesh(node_mesh, v3f(30.0, 30.0, 30.0)
|
|
||||||
* def->wield_scale);
|
|
||||||
def->wield_mesh = node_mesh;
|
|
||||||
def->wield_mesh->grab();
|
|
||||||
}
|
|
||||||
|
|
||||||
// falling outside of here deletes node_mesh
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
void serialize(std::ostream &os)
|
void serialize(std::ostream &os)
|
||||||
{
|
{
|
||||||
writeU8(os, 0); // version
|
writeU8(os, 0); // version
|
||||||
@@ -521,11 +591,37 @@ public:
|
|||||||
registerAlias(name, convert_to);
|
registerAlias(name, convert_to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void processQueue(IGameDef *gamedef)
|
||||||
|
{
|
||||||
|
#ifndef SERVER
|
||||||
|
while(m_get_clientcached_queue.size() > 0)
|
||||||
|
{
|
||||||
|
GetRequest<std::string, ClientCached*, u8, u8>
|
||||||
|
request = m_get_clientcached_queue.pop();
|
||||||
|
GetResult<std::string, ClientCached*, u8, u8>
|
||||||
|
result;
|
||||||
|
result.key = request.key;
|
||||||
|
result.callers = request.callers;
|
||||||
|
result.item = createClientCachedDirect(request.key, gamedef);
|
||||||
|
request.dest->push_back(result);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
// Key is name
|
// Key is name
|
||||||
std::map<std::string, ItemDefinition*> m_item_definitions;
|
std::map<std::string, ItemDefinition*> m_item_definitions;
|
||||||
// Aliases
|
// Aliases
|
||||||
std::map<std::string, std::string> m_aliases;
|
std::map<std::string, std::string> m_aliases;
|
||||||
|
#ifndef SERVER
|
||||||
|
// The id of the thread that is allowed to use irrlicht directly
|
||||||
|
threadid_t m_main_thread;
|
||||||
|
// A reference to this can be returned when nothing is found, to avoid NULLs
|
||||||
|
mutable ClientCached m_dummy_clientcached;
|
||||||
|
// Cached textures and meshes
|
||||||
|
mutable MutexedMap<std::string, ClientCached*> m_clientcached;
|
||||||
|
// Queued clientcached fetches (to be processed by the main thread)
|
||||||
|
mutable RequestQueue<std::string, ClientCached*, u8, u8> m_get_clientcached_queue;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
IWritableItemDefManager* createItemDefManager()
|
IWritableItemDefManager* createItemDefManager()
|
||||||
|
|||||||
@@ -72,14 +72,6 @@ struct ItemDefinition
|
|||||||
// "" = no prediction
|
// "" = no prediction
|
||||||
std::string node_placement_prediction;
|
std::string node_placement_prediction;
|
||||||
|
|
||||||
/*
|
|
||||||
Cached stuff
|
|
||||||
*/
|
|
||||||
#ifndef SERVER
|
|
||||||
video::ITexture *inventory_texture;
|
|
||||||
scene::IMesh *wield_mesh;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Some helpful methods
|
Some helpful methods
|
||||||
*/
|
*/
|
||||||
@@ -108,6 +100,14 @@ public:
|
|||||||
virtual std::set<std::string> getAll() const=0;
|
virtual std::set<std::string> getAll() const=0;
|
||||||
// Check if item is known
|
// Check if item is known
|
||||||
virtual bool isKnown(const std::string &name) const=0;
|
virtual bool isKnown(const std::string &name) const=0;
|
||||||
|
#ifndef SERVER
|
||||||
|
// Get item inventory texture
|
||||||
|
virtual video::ITexture* getInventoryTexture(const std::string &name,
|
||||||
|
IGameDef *gamedef) const=0;
|
||||||
|
// Get item wield mesh
|
||||||
|
virtual scene::IMesh* getWieldMesh(const std::string &name,
|
||||||
|
IGameDef *gamedef) const=0;
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual void serialize(std::ostream &os)=0;
|
virtual void serialize(std::ostream &os)=0;
|
||||||
};
|
};
|
||||||
@@ -126,6 +126,14 @@ public:
|
|||||||
virtual std::set<std::string> getAll() const=0;
|
virtual std::set<std::string> getAll() const=0;
|
||||||
// Check if item is known
|
// Check if item is known
|
||||||
virtual bool isKnown(const std::string &name) const=0;
|
virtual bool isKnown(const std::string &name) const=0;
|
||||||
|
#ifndef SERVER
|
||||||
|
// Get item inventory texture
|
||||||
|
virtual video::ITexture* getInventoryTexture(const std::string &name,
|
||||||
|
IGameDef *gamedef) const=0;
|
||||||
|
// Get item wield mesh
|
||||||
|
virtual scene::IMesh* getWieldMesh(const std::string &name,
|
||||||
|
IGameDef *gamedef) const=0;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Remove all registered item and node definitions and aliases
|
// Remove all registered item and node definitions and aliases
|
||||||
// Then re-add the builtin item definitions
|
// Then re-add the builtin item definitions
|
||||||
@@ -138,15 +146,11 @@ public:
|
|||||||
virtual void registerAlias(const std::string &name,
|
virtual void registerAlias(const std::string &name,
|
||||||
const std::string &convert_to)=0;
|
const std::string &convert_to)=0;
|
||||||
|
|
||||||
/*
|
|
||||||
Update inventory textures and wield meshes to latest
|
|
||||||
return values of ITextureSource and INodeDefManager.
|
|
||||||
Call after updating the texture atlas of a texture source.
|
|
||||||
*/
|
|
||||||
virtual void updateTexturesAndMeshes(IGameDef *gamedef)=0;
|
|
||||||
|
|
||||||
virtual void serialize(std::ostream &os)=0;
|
virtual void serialize(std::ostream &os)=0;
|
||||||
virtual void deSerialize(std::istream &is)=0;
|
virtual void deSerialize(std::istream &is)=0;
|
||||||
|
|
||||||
|
// Do stuff asked by threads that can only be done in the main thread
|
||||||
|
virtual void processQueue(IGameDef *gamedef)=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
IWritableItemDefManager* createItemDefManager();
|
IWritableItemDefManager* createItemDefManager();
|
||||||
|
|||||||
@@ -1440,6 +1440,8 @@ int main(int argc, char *argv[])
|
|||||||
menudata.anisotropic_filter = g_settings->getBool("anisotropic_filter");
|
menudata.anisotropic_filter = g_settings->getBool("anisotropic_filter");
|
||||||
menudata.bilinear_filter = g_settings->getBool("bilinear_filter");
|
menudata.bilinear_filter = g_settings->getBool("bilinear_filter");
|
||||||
menudata.trilinear_filter = g_settings->getBool("trilinear_filter");
|
menudata.trilinear_filter = g_settings->getBool("trilinear_filter");
|
||||||
|
menudata.enable_shaders = g_settings->getS32("enable_shaders");
|
||||||
|
menudata.preload_item_visuals = g_settings->getBool("preload_item_visuals");
|
||||||
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, menudata.mip_map);
|
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, menudata.mip_map);
|
||||||
menudata.creative_mode = g_settings->getBool("creative_mode");
|
menudata.creative_mode = g_settings->getBool("creative_mode");
|
||||||
menudata.enable_damage = g_settings->getBool("enable_damage");
|
menudata.enable_damage = g_settings->getBool("enable_damage");
|
||||||
@@ -1560,6 +1562,9 @@ int main(int argc, char *argv[])
|
|||||||
g_settings->set("bilinear_filter", itos(menudata.bilinear_filter));
|
g_settings->set("bilinear_filter", itos(menudata.bilinear_filter));
|
||||||
g_settings->set("trilinear_filter", itos(menudata.trilinear_filter));
|
g_settings->set("trilinear_filter", itos(menudata.trilinear_filter));
|
||||||
|
|
||||||
|
g_settings->setS32("enable_shaders", menudata.enable_shaders);
|
||||||
|
g_settings->set("preload_item_visuals", itos(menudata.preload_item_visuals));
|
||||||
|
|
||||||
g_settings->set("creative_mode", itos(menudata.creative_mode));
|
g_settings->set("creative_mode", itos(menudata.creative_mode));
|
||||||
g_settings->set("enable_damage", itos(menudata.enable_damage));
|
g_settings->set("enable_damage", itos(menudata.enable_damage));
|
||||||
g_settings->set("name", playername);
|
g_settings->set("name", playername);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "content_mapblock.h"
|
#include "content_mapblock.h"
|
||||||
#include "noise.h"
|
#include "noise.h"
|
||||||
|
#include "shader.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "util/directiontables.h"
|
#include "util/directiontables.h"
|
||||||
|
|
||||||
@@ -1011,6 +1012,11 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
|
|||||||
Convert MeshCollector to SMesh
|
Convert MeshCollector to SMesh
|
||||||
Also store animation info
|
Also store animation info
|
||||||
*/
|
*/
|
||||||
|
bool enable_shaders = (g_settings->getS32("enable_shaders") > 0);
|
||||||
|
video::E_MATERIAL_TYPE shadermat1 = m_gamedef->getShaderSource()->
|
||||||
|
getShader("test_shader_1").material;
|
||||||
|
video::E_MATERIAL_TYPE shadermat2 = m_gamedef->getShaderSource()->
|
||||||
|
getShader("test_shader_2").material;
|
||||||
for(u32 i = 0; i < collector.prebuffers.size(); i++)
|
for(u32 i = 0; i < collector.prebuffers.size(); i++)
|
||||||
{
|
{
|
||||||
PreMeshBuffer &p = collector.prebuffers[i];
|
PreMeshBuffer &p = collector.prebuffers[i];
|
||||||
@@ -1075,7 +1081,10 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
|
|||||||
material.MaterialType
|
material.MaterialType
|
||||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
material.setTexture(0, p.tile.texture.atlas);
|
material.setTexture(0, p.tile.texture.atlas);
|
||||||
p.tile.applyMaterialOptions(material);
|
if(enable_shaders)
|
||||||
|
p.tile.applyMaterialOptionsWithShaders(material, shadermat1, shadermat2);
|
||||||
|
else
|
||||||
|
p.tile.applyMaterialOptions(material);
|
||||||
|
|
||||||
// Create meshbuffer
|
// Create meshbuffer
|
||||||
|
|
||||||
|
|||||||
@@ -555,6 +555,7 @@ public:
|
|||||||
tiledef[j].name = "unknown_block.png";
|
tiledef[j].name = "unknown_block.png";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_liquid = false;
|
||||||
switch(f->drawtype){
|
switch(f->drawtype){
|
||||||
default:
|
default:
|
||||||
case NDT_NORMAL:
|
case NDT_NORMAL:
|
||||||
@@ -573,12 +574,14 @@ public:
|
|||||||
f->solidness = 1;
|
f->solidness = 1;
|
||||||
f->backface_culling = false;
|
f->backface_culling = false;
|
||||||
}
|
}
|
||||||
|
is_liquid = true;
|
||||||
break;
|
break;
|
||||||
case NDT_FLOWINGLIQUID:
|
case NDT_FLOWINGLIQUID:
|
||||||
assert(f->liquid_type == LIQUID_FLOWING);
|
assert(f->liquid_type == LIQUID_FLOWING);
|
||||||
f->solidness = 0;
|
f->solidness = 0;
|
||||||
if(opaque_water)
|
if(opaque_water)
|
||||||
f->alpha = 255;
|
f->alpha = 255;
|
||||||
|
is_liquid = true;
|
||||||
break;
|
break;
|
||||||
case NDT_GLASSLIKE:
|
case NDT_GLASSLIKE:
|
||||||
f->solidness = 0;
|
f->solidness = 0;
|
||||||
@@ -611,16 +614,24 @@ public:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 material_type = 0;
|
||||||
|
if(is_liquid){
|
||||||
|
if(f->alpha == 255)
|
||||||
|
material_type = TILE_MATERIAL_LIQUID_OPAQUE;
|
||||||
|
else
|
||||||
|
material_type = TILE_MATERIAL_LIQUID_TRANSPARENT;
|
||||||
|
} else{
|
||||||
|
material_type = TILE_MATERIAL_BASIC;
|
||||||
|
}
|
||||||
|
|
||||||
// Tiles (fill in f->tiles[])
|
// Tiles (fill in f->tiles[])
|
||||||
for(u16 j=0; j<6; j++){
|
for(u16 j=0; j<6; j++){
|
||||||
// Texture
|
// Texture
|
||||||
f->tiles[j].texture = tsrc->getTexture(tiledef[j].name);
|
f->tiles[j].texture = tsrc->getTexture(tiledef[j].name);
|
||||||
// Alpha
|
// Alpha
|
||||||
f->tiles[j].alpha = f->alpha;
|
f->tiles[j].alpha = f->alpha;
|
||||||
if(f->alpha == 255)
|
// Material type
|
||||||
f->tiles[j].material_type = MATERIAL_ALPHA_SIMPLE;
|
f->tiles[j].material_type = material_type;
|
||||||
else
|
|
||||||
f->tiles[j].material_type = MATERIAL_ALPHA_VERTEX;
|
|
||||||
// Material flags
|
// Material flags
|
||||||
f->tiles[j].material_flags = 0;
|
f->tiles[j].material_flags = 0;
|
||||||
if(f->backface_culling)
|
if(f->backface_culling)
|
||||||
@@ -661,10 +672,8 @@ public:
|
|||||||
tsrc->getTexture(f->tiledef_special[j].name);
|
tsrc->getTexture(f->tiledef_special[j].name);
|
||||||
// Alpha
|
// Alpha
|
||||||
f->special_tiles[j].alpha = f->alpha;
|
f->special_tiles[j].alpha = f->alpha;
|
||||||
if(f->alpha == 255)
|
// Material type
|
||||||
f->special_tiles[j].material_type = MATERIAL_ALPHA_SIMPLE;
|
f->special_tiles[j].material_type = material_type;
|
||||||
else
|
|
||||||
f->special_tiles[j].material_type = MATERIAL_ALPHA_VERTEX;
|
|
||||||
// Material flags
|
// Material flags
|
||||||
f->special_tiles[j].material_flags = 0;
|
f->special_tiles[j].material_flags = 0;
|
||||||
if(f->tiledef_special[j].backface_culling)
|
if(f->tiledef_special[j].backface_culling)
|
||||||
|
|||||||
@@ -4688,6 +4688,10 @@ ITextureSource* Server::getTextureSource()
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
IShaderSource* Server::getShaderSource()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
u16 Server::allocateUnknownNodeId(const std::string &name)
|
u16 Server::allocateUnknownNodeId(const std::string &name)
|
||||||
{
|
{
|
||||||
return m_nodedef->allocateDummy(name);
|
return m_nodedef->allocateDummy(name);
|
||||||
|
|||||||
@@ -560,6 +560,7 @@ public:
|
|||||||
virtual INodeDefManager* getNodeDefManager();
|
virtual INodeDefManager* getNodeDefManager();
|
||||||
virtual ICraftDefManager* getCraftDefManager();
|
virtual ICraftDefManager* getCraftDefManager();
|
||||||
virtual ITextureSource* getTextureSource();
|
virtual ITextureSource* getTextureSource();
|
||||||
|
virtual IShaderSource* getShaderSource();
|
||||||
virtual u16 allocateUnknownNodeId(const std::string &name);
|
virtual u16 allocateUnknownNodeId(const std::string &name);
|
||||||
virtual ISoundManager* getSoundManager();
|
virtual ISoundManager* getSoundManager();
|
||||||
virtual MtEventManager* getEventManager();
|
virtual MtEventManager* getEventManager();
|
||||||
|
|||||||
793
src/shader.cpp
Normal file
793
src/shader.cpp
Normal file
@@ -0,0 +1,793 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
Copyright (C) 2012 Kahrl <kahrl@gmx.net>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU 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 "shader.h"
|
||||||
|
#include "irrlichttypes_extrabloated.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "main.h" // for g_settings
|
||||||
|
#include "filesys.h"
|
||||||
|
#include "util/container.h"
|
||||||
|
#include "util/thread.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include <iterator>
|
||||||
|
#include <ICameraSceneNode.h>
|
||||||
|
#include <IGPUProgrammingServices.h>
|
||||||
|
#include <IMaterialRenderer.h>
|
||||||
|
#include <IMaterialRendererServices.h>
|
||||||
|
#include <IShaderConstantSetCallBack.h>
|
||||||
|
#include "EShaderTypes.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "gamedef.h"
|
||||||
|
#include "strfnd.h" // trim()
|
||||||
|
|
||||||
|
/*
|
||||||
|
A cache from shader name to shader path
|
||||||
|
*/
|
||||||
|
MutexedMap<std::string, std::string> g_shadername_to_path_cache;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Gets the path to a shader by first checking if the file
|
||||||
|
name_of_shader/filename
|
||||||
|
exists in shader_path and if not, using the data path.
|
||||||
|
|
||||||
|
If not found, returns "".
|
||||||
|
|
||||||
|
Utilizes a thread-safe cache.
|
||||||
|
*/
|
||||||
|
std::string getShaderPath(const std::string &name_of_shader,
|
||||||
|
const std::string &filename)
|
||||||
|
{
|
||||||
|
std::string combined = name_of_shader + DIR_DELIM + filename;
|
||||||
|
std::string fullpath = "";
|
||||||
|
/*
|
||||||
|
Check from cache
|
||||||
|
*/
|
||||||
|
bool incache = g_shadername_to_path_cache.get(combined, &fullpath);
|
||||||
|
if(incache)
|
||||||
|
return fullpath;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check from shader_path
|
||||||
|
*/
|
||||||
|
std::string shader_path = g_settings->get("shader_path");
|
||||||
|
if(shader_path != "")
|
||||||
|
{
|
||||||
|
std::string testpath = shader_path + DIR_DELIM + combined;
|
||||||
|
if(fs::PathExists(testpath))
|
||||||
|
fullpath = testpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check from default data directory
|
||||||
|
*/
|
||||||
|
if(fullpath == "")
|
||||||
|
{
|
||||||
|
std::string rel_path = std::string("client") + DIR_DELIM
|
||||||
|
+ "shaders" + DIR_DELIM
|
||||||
|
+ name_of_shader + DIR_DELIM
|
||||||
|
+ filename;
|
||||||
|
std::string testpath = porting::path_share + DIR_DELIM + rel_path;
|
||||||
|
if(fs::PathExists(testpath))
|
||||||
|
fullpath = testpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to cache (also an empty result is cached)
|
||||||
|
g_shadername_to_path_cache.set(combined, fullpath);
|
||||||
|
|
||||||
|
// Finally return it
|
||||||
|
return fullpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
SourceShaderCache: A cache used for storing source shaders.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class SourceShaderCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void insert(const std::string &name_of_shader,
|
||||||
|
const std::string &filename,
|
||||||
|
const std::string &program,
|
||||||
|
bool prefer_local)
|
||||||
|
{
|
||||||
|
std::string combined = name_of_shader + DIR_DELIM + filename;
|
||||||
|
// Try to use local shader instead if asked to
|
||||||
|
if(prefer_local){
|
||||||
|
std::string path = getShaderPath(name_of_shader, filename);
|
||||||
|
if(path != ""){
|
||||||
|
std::string p = readFile(path);
|
||||||
|
if(p != ""){
|
||||||
|
m_programs[combined] = p;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_programs[combined] = program;
|
||||||
|
}
|
||||||
|
std::string get(const std::string &name_of_shader,
|
||||||
|
const std::string &filename)
|
||||||
|
{
|
||||||
|
std::string combined = name_of_shader + DIR_DELIM + filename;
|
||||||
|
core::map<std::string, std::string>::Node *n;
|
||||||
|
n = m_programs.find(combined);
|
||||||
|
if(n)
|
||||||
|
return n->getValue();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
// Primarily fetches from cache, secondarily tries to read from filesystem
|
||||||
|
std::string getOrLoad(const std::string &name_of_shader,
|
||||||
|
const std::string &filename)
|
||||||
|
{
|
||||||
|
std::string combined = name_of_shader + DIR_DELIM + filename;
|
||||||
|
core::map<std::string, std::string>::Node *n;
|
||||||
|
n = m_programs.find(combined);
|
||||||
|
if(n)
|
||||||
|
return n->getValue();
|
||||||
|
std::string path = getShaderPath(name_of_shader, filename);
|
||||||
|
if(path == ""){
|
||||||
|
infostream<<"SourceShaderCache::getOrLoad(): No path found for \""
|
||||||
|
<<combined<<"\""<<std::endl;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
infostream<<"SourceShaderCache::getOrLoad(): Loading path \""<<path
|
||||||
|
<<"\""<<std::endl;
|
||||||
|
std::string p = readFile(path);
|
||||||
|
if(p != ""){
|
||||||
|
m_programs[combined] = p;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
core::map<std::string, std::string> m_programs;
|
||||||
|
std::string readFile(const std::string &path)
|
||||||
|
{
|
||||||
|
std::ifstream is(path.c_str(), std::ios::binary);
|
||||||
|
if(!is.is_open())
|
||||||
|
return "";
|
||||||
|
std::ostringstream tmp_os;
|
||||||
|
tmp_os << is.rdbuf();
|
||||||
|
return tmp_os.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
ShaderCallback: Sets constants that can be used in shaders
|
||||||
|
*/
|
||||||
|
|
||||||
|
class IShaderConstantSetterRegistry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IShaderConstantSetterRegistry(){};
|
||||||
|
virtual void onSetConstants(video::IMaterialRendererServices *services,
|
||||||
|
bool is_highlevel, const std::string &name) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShaderCallback : public video::IShaderConstantSetCallBack
|
||||||
|
{
|
||||||
|
IShaderConstantSetterRegistry *m_scsr;
|
||||||
|
std::string m_name;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShaderCallback(IShaderConstantSetterRegistry *scsr, const std::string &name):
|
||||||
|
m_scsr(scsr),
|
||||||
|
m_name(name)
|
||||||
|
{}
|
||||||
|
~ShaderCallback() {}
|
||||||
|
|
||||||
|
virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData)
|
||||||
|
{
|
||||||
|
video::IVideoDriver *driver = services->getVideoDriver();
|
||||||
|
assert(driver);
|
||||||
|
|
||||||
|
bool is_highlevel = userData;
|
||||||
|
|
||||||
|
m_scsr->onSetConstants(services, is_highlevel, m_name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
MainShaderConstantSetter: Set basic constants required for almost everything
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MainShaderConstantSetter : public IShaderConstantSetter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MainShaderConstantSetter(IrrlichtDevice *device):
|
||||||
|
m_device(device)
|
||||||
|
{}
|
||||||
|
~MainShaderConstantSetter() {}
|
||||||
|
|
||||||
|
virtual void onSetConstants(video::IMaterialRendererServices *services,
|
||||||
|
bool is_highlevel)
|
||||||
|
{
|
||||||
|
video::IVideoDriver *driver = services->getVideoDriver();
|
||||||
|
assert(driver);
|
||||||
|
|
||||||
|
// set inverted world matrix
|
||||||
|
core::matrix4 invWorld = driver->getTransform(video::ETS_WORLD);
|
||||||
|
invWorld.makeInverse();
|
||||||
|
if(is_highlevel)
|
||||||
|
services->setVertexShaderConstant("mInvWorld", invWorld.pointer(), 16);
|
||||||
|
else
|
||||||
|
services->setVertexShaderConstant(invWorld.pointer(), 0, 4);
|
||||||
|
|
||||||
|
// set clip matrix
|
||||||
|
core::matrix4 worldViewProj;
|
||||||
|
worldViewProj = driver->getTransform(video::ETS_PROJECTION);
|
||||||
|
worldViewProj *= driver->getTransform(video::ETS_VIEW);
|
||||||
|
worldViewProj *= driver->getTransform(video::ETS_WORLD);
|
||||||
|
if(is_highlevel)
|
||||||
|
services->setVertexShaderConstant("mWorldViewProj", worldViewProj.pointer(), 16);
|
||||||
|
else
|
||||||
|
services->setVertexShaderConstant(worldViewProj.pointer(), 4, 4);
|
||||||
|
|
||||||
|
// set transposed world matrix
|
||||||
|
core::matrix4 world = driver->getTransform(video::ETS_WORLD);
|
||||||
|
world = world.getTransposed();
|
||||||
|
if(is_highlevel)
|
||||||
|
services->setVertexShaderConstant("mTransWorld", world.pointer(), 16);
|
||||||
|
else
|
||||||
|
services->setVertexShaderConstant(world.pointer(), 8, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
IrrlichtDevice *m_device;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
ShaderSource
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ShaderSource : public IWritableShaderSource, public IShaderConstantSetterRegistry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShaderSource(IrrlichtDevice *device);
|
||||||
|
~ShaderSource();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Gets a shader material id from cache or
|
||||||
|
- if main thread, from getShaderIdDirect
|
||||||
|
- if other thread, adds to request queue and waits for main thread
|
||||||
|
*/
|
||||||
|
u32 getShaderId(const std::string &name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
- If shader material specified by name is found from cache,
|
||||||
|
return the cached id.
|
||||||
|
- Otherwise generate the shader material, add to cache and return id.
|
||||||
|
|
||||||
|
The id 0 points to a null shader. Its material is EMT_SOLID.
|
||||||
|
*/
|
||||||
|
u32 getShaderIdDirect(const std::string &name);
|
||||||
|
|
||||||
|
// Finds out the name of a cached shader.
|
||||||
|
std::string getShaderName(u32 id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
If shader specified by the name pointed by the id doesn't
|
||||||
|
exist, create it, then return the cached shader.
|
||||||
|
|
||||||
|
Can be called from any thread. If called from some other thread
|
||||||
|
and not found in cache, the call is queued to the main thread
|
||||||
|
for processing.
|
||||||
|
*/
|
||||||
|
ShaderInfo getShader(u32 id);
|
||||||
|
|
||||||
|
ShaderInfo getShader(const std::string &name)
|
||||||
|
{
|
||||||
|
return getShader(getShaderId(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processes queued shader requests from other threads.
|
||||||
|
// Shall be called from the main thread.
|
||||||
|
void processQueue();
|
||||||
|
|
||||||
|
// Insert a shader program into the cache without touching the
|
||||||
|
// filesystem. Shall be called from the main thread.
|
||||||
|
void insertSourceShader(const std::string &name_of_shader,
|
||||||
|
const std::string &filename, const std::string &program);
|
||||||
|
|
||||||
|
// Rebuild shaders from the current set of source shaders
|
||||||
|
// Shall be called from the main thread.
|
||||||
|
void rebuildShaders();
|
||||||
|
|
||||||
|
void addGlobalConstantSetter(IShaderConstantSetter *setter)
|
||||||
|
{
|
||||||
|
m_global_setters.push_back(setter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSetConstants(video::IMaterialRendererServices *services,
|
||||||
|
bool is_highlevel, const std::string &name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// The id of the thread that is allowed to use irrlicht directly
|
||||||
|
threadid_t m_main_thread;
|
||||||
|
// The irrlicht device
|
||||||
|
IrrlichtDevice *m_device;
|
||||||
|
// The set-constants callback
|
||||||
|
ShaderCallback *m_shader_callback;
|
||||||
|
|
||||||
|
// Cache of source shaders
|
||||||
|
// This should be only accessed from the main thread
|
||||||
|
SourceShaderCache m_sourcecache;
|
||||||
|
|
||||||
|
// A shader id is index in this array.
|
||||||
|
// The first position contains a dummy shader.
|
||||||
|
core::array<ShaderInfo> m_shaderinfo_cache;
|
||||||
|
// Maps a shader name to an index in the former.
|
||||||
|
core::map<std::string, u32> m_name_to_id;
|
||||||
|
// The two former containers are behind this mutex
|
||||||
|
JMutex m_shaderinfo_cache_mutex;
|
||||||
|
|
||||||
|
// Queued shader fetches (to be processed by the main thread)
|
||||||
|
RequestQueue<std::string, u32, u8, u8> m_get_shader_queue;
|
||||||
|
|
||||||
|
// Global constant setters
|
||||||
|
// TODO: Delete these in the destructor
|
||||||
|
core::array<IShaderConstantSetter*> m_global_setters;
|
||||||
|
};
|
||||||
|
|
||||||
|
IWritableShaderSource* createShaderSource(IrrlichtDevice *device)
|
||||||
|
{
|
||||||
|
return new ShaderSource(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generate shader given the shader name.
|
||||||
|
*/
|
||||||
|
ShaderInfo generate_shader(std::string name, IrrlichtDevice *device,
|
||||||
|
video::IShaderConstantSetCallBack *callback,
|
||||||
|
SourceShaderCache *sourcecache);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Load shader programs
|
||||||
|
*/
|
||||||
|
void load_shaders(std::string name, SourceShaderCache *sourcecache,
|
||||||
|
video::E_DRIVER_TYPE drivertype, s32 enable_shaders,
|
||||||
|
std::string &vertex_program, std::string &pixel_program,
|
||||||
|
std::string &geometry_program, bool &is_highlevel);
|
||||||
|
|
||||||
|
ShaderSource::ShaderSource(IrrlichtDevice *device):
|
||||||
|
m_device(device)
|
||||||
|
{
|
||||||
|
assert(m_device);
|
||||||
|
|
||||||
|
m_shader_callback = new ShaderCallback(this, "default");
|
||||||
|
|
||||||
|
m_shaderinfo_cache_mutex.Init();
|
||||||
|
|
||||||
|
m_main_thread = get_current_thread_id();
|
||||||
|
|
||||||
|
// Add a dummy ShaderInfo as the first index, named ""
|
||||||
|
m_shaderinfo_cache.push_back(ShaderInfo());
|
||||||
|
m_name_to_id[""] = 0;
|
||||||
|
|
||||||
|
// Add main global constant setter
|
||||||
|
addGlobalConstantSetter(new MainShaderConstantSetter(device));
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderSource::~ShaderSource()
|
||||||
|
{
|
||||||
|
//m_shader_callback->drop();
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ShaderSource::getShaderId(const std::string &name)
|
||||||
|
{
|
||||||
|
//infostream<<"getShaderId(): \""<<name<<"\""<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
See if shader already exists
|
||||||
|
*/
|
||||||
|
JMutexAutoLock lock(m_shaderinfo_cache_mutex);
|
||||||
|
core::map<std::string, u32>::Node *n;
|
||||||
|
n = m_name_to_id.find(name);
|
||||||
|
if(n != NULL)
|
||||||
|
return n->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get shader
|
||||||
|
*/
|
||||||
|
if(get_current_thread_id() == m_main_thread){
|
||||||
|
return getShaderIdDirect(name);
|
||||||
|
} else {
|
||||||
|
infostream<<"getShaderId(): Queued: name=\""<<name<<"\""<<std::endl;
|
||||||
|
|
||||||
|
// We're gonna ask the result to be put into here
|
||||||
|
ResultQueue<std::string, u32, u8, u8> result_queue;
|
||||||
|
|
||||||
|
// Throw a request in
|
||||||
|
m_get_shader_queue.add(name, 0, 0, &result_queue);
|
||||||
|
|
||||||
|
infostream<<"Waiting for shader from main thread, name=\""
|
||||||
|
<<name<<"\""<<std::endl;
|
||||||
|
|
||||||
|
try{
|
||||||
|
// Wait result for a second
|
||||||
|
GetResult<std::string, u32, u8, u8>
|
||||||
|
result = result_queue.pop_front(1000);
|
||||||
|
|
||||||
|
// Check that at least something worked OK
|
||||||
|
assert(result.key == name);
|
||||||
|
|
||||||
|
return result.item;
|
||||||
|
}
|
||||||
|
catch(ItemNotFoundException &e){
|
||||||
|
infostream<<"Waiting for shader timed out."<<std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
infostream<<"getShaderId(): Failed"<<std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This method generates all the shaders
|
||||||
|
*/
|
||||||
|
u32 ShaderSource::getShaderIdDirect(const std::string &name)
|
||||||
|
{
|
||||||
|
//infostream<<"getShaderIdDirect(): name=\""<<name<<"\""<<std::endl;
|
||||||
|
|
||||||
|
// Empty name means shader 0
|
||||||
|
if(name == ""){
|
||||||
|
infostream<<"getShaderIdDirect(): name is empty"<<std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calling only allowed from main thread
|
||||||
|
*/
|
||||||
|
if(get_current_thread_id() != m_main_thread){
|
||||||
|
errorstream<<"ShaderSource::getShaderIdDirect() "
|
||||||
|
"called not from main thread"<<std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
See if shader already exists
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_shaderinfo_cache_mutex);
|
||||||
|
|
||||||
|
core::map<std::string, u32>::Node *n;
|
||||||
|
n = m_name_to_id.find(name);
|
||||||
|
if(n != NULL){
|
||||||
|
/*infostream<<"getShaderIdDirect(): \""<<name
|
||||||
|
<<"\" found in cache"<<std::endl;*/
|
||||||
|
return n->getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*infostream<<"getShaderIdDirect(): \""<<name
|
||||||
|
<<"\" NOT found in cache. Creating it."<<std::endl;*/
|
||||||
|
|
||||||
|
ShaderInfo info = generate_shader(name, m_device,
|
||||||
|
m_shader_callback, &m_sourcecache);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add shader to caches (add dummy shaders too)
|
||||||
|
*/
|
||||||
|
|
||||||
|
JMutexAutoLock lock(m_shaderinfo_cache_mutex);
|
||||||
|
|
||||||
|
u32 id = m_shaderinfo_cache.size();
|
||||||
|
m_shaderinfo_cache.push_back(info);
|
||||||
|
m_name_to_id.insert(name, id);
|
||||||
|
|
||||||
|
/*infostream<<"getShaderIdDirect(): "
|
||||||
|
<<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl;*/
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ShaderSource::getShaderName(u32 id)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_shaderinfo_cache_mutex);
|
||||||
|
|
||||||
|
if(id >= m_shaderinfo_cache.size()){
|
||||||
|
errorstream<<"ShaderSource::getShaderName(): id="<<id
|
||||||
|
<<" >= m_shaderinfo_cache.size()="
|
||||||
|
<<m_shaderinfo_cache.size()<<std::endl;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_shaderinfo_cache[id].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderInfo ShaderSource::getShader(u32 id)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_shaderinfo_cache_mutex);
|
||||||
|
|
||||||
|
if(id >= m_shaderinfo_cache.size())
|
||||||
|
return ShaderInfo();
|
||||||
|
|
||||||
|
return m_shaderinfo_cache[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderSource::processQueue()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Fetch shaders
|
||||||
|
*/
|
||||||
|
if(m_get_shader_queue.size() > 0){
|
||||||
|
GetRequest<std::string, u32, u8, u8>
|
||||||
|
request = m_get_shader_queue.pop();
|
||||||
|
|
||||||
|
/*infostream<<"ShaderSource::processQueue(): "
|
||||||
|
<<"got shader request with "
|
||||||
|
<<"name=\""<<request.key<<"\""
|
||||||
|
<<std::endl;*/
|
||||||
|
|
||||||
|
GetResult<std::string, u32, u8, u8>
|
||||||
|
result;
|
||||||
|
result.key = request.key;
|
||||||
|
result.callers = request.callers;
|
||||||
|
result.item = getShaderIdDirect(request.key);
|
||||||
|
|
||||||
|
request.dest->push_back(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderSource::insertSourceShader(const std::string &name_of_shader,
|
||||||
|
const std::string &filename, const std::string &program)
|
||||||
|
{
|
||||||
|
/*infostream<<"ShaderSource::insertSourceShader(): "
|
||||||
|
"name_of_shader=\""<<name_of_shader<<"\", "
|
||||||
|
"filename=\""<<filename<<"\""<<std::endl;*/
|
||||||
|
|
||||||
|
assert(get_current_thread_id() == m_main_thread);
|
||||||
|
|
||||||
|
m_sourcecache.insert(name_of_shader, filename, program, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderSource::rebuildShaders()
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_shaderinfo_cache_mutex);
|
||||||
|
|
||||||
|
/*// Oh well... just clear everything, they'll load sometime.
|
||||||
|
m_shaderinfo_cache.clear();
|
||||||
|
m_name_to_id.clear();*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
FIXME: Old shader materials can't be deleted in Irrlicht,
|
||||||
|
or can they?
|
||||||
|
(This would be nice to do in the destructor too)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Recreate shaders
|
||||||
|
for(u32 i=0; i<m_shaderinfo_cache.size(); i++){
|
||||||
|
ShaderInfo *info = &m_shaderinfo_cache[i];
|
||||||
|
*info = generate_shader(info->name, m_device,
|
||||||
|
m_shader_callback, &m_sourcecache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderSource::onSetConstants(video::IMaterialRendererServices *services,
|
||||||
|
bool is_highlevel, const std::string &name)
|
||||||
|
{
|
||||||
|
for(u32 i=0; i<m_global_setters.size(); i++){
|
||||||
|
IShaderConstantSetter *setter = m_global_setters[i];
|
||||||
|
setter->onSetConstants(services, is_highlevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderInfo generate_shader(std::string name, IrrlichtDevice *device,
|
||||||
|
video::IShaderConstantSetCallBack *callback,
|
||||||
|
SourceShaderCache *sourcecache)
|
||||||
|
{
|
||||||
|
/*infostream<<"generate_shader(): "
|
||||||
|
"\""<<name<<"\""<<std::endl;*/
|
||||||
|
|
||||||
|
ShaderInfo shaderinfo;
|
||||||
|
shaderinfo.name = name;
|
||||||
|
shaderinfo.material = video::EMT_SOLID;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the base material
|
||||||
|
*/
|
||||||
|
std::string base_material_name =
|
||||||
|
trim(sourcecache->getOrLoad(name, "base.txt"));
|
||||||
|
for(s32 i = 0; video::sBuiltInMaterialTypeNames[i] != 0; i++){
|
||||||
|
if(video::sBuiltInMaterialTypeNames[i] == base_material_name){
|
||||||
|
shaderinfo.material = (video::E_MATERIAL_TYPE) i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0 = off, 1 = assembly shaders only, 2 = highlevel or assembly
|
||||||
|
s32 enable_shaders = g_settings->getS32("enable_shaders");
|
||||||
|
if(enable_shaders <= 0)
|
||||||
|
return shaderinfo;
|
||||||
|
|
||||||
|
video::IVideoDriver* driver = device->getVideoDriver();
|
||||||
|
assert(driver);
|
||||||
|
|
||||||
|
video::IGPUProgrammingServices *gpu = driver->getGPUProgrammingServices();
|
||||||
|
if(!gpu){
|
||||||
|
errorstream<<"generate_shader(): "
|
||||||
|
"failed to generate \""<<name<<"\", "
|
||||||
|
"GPU programming not supported."
|
||||||
|
<<std::endl;
|
||||||
|
return shaderinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choose shader language depending on driver type and settings
|
||||||
|
// Then load shaders
|
||||||
|
std::string vertex_program;
|
||||||
|
std::string pixel_program;
|
||||||
|
std::string geometry_program;
|
||||||
|
bool is_highlevel;
|
||||||
|
load_shaders(name, sourcecache, driver->getDriverType(),
|
||||||
|
enable_shaders, vertex_program, pixel_program,
|
||||||
|
geometry_program, is_highlevel);
|
||||||
|
|
||||||
|
// Check hardware/driver support
|
||||||
|
if(vertex_program != "" &&
|
||||||
|
!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
|
||||||
|
!driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)){
|
||||||
|
infostream<<"generate_shader(): vertex shaders disabled "
|
||||||
|
"because of missing driver/hardware support."
|
||||||
|
<<std::endl;
|
||||||
|
vertex_program = "";
|
||||||
|
}
|
||||||
|
if(pixel_program != "" &&
|
||||||
|
!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
|
||||||
|
!driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)){
|
||||||
|
infostream<<"generate_shader(): pixel shaders disabled "
|
||||||
|
"because of missing driver/hardware support."
|
||||||
|
<<std::endl;
|
||||||
|
pixel_program = "";
|
||||||
|
}
|
||||||
|
if(geometry_program != "" &&
|
||||||
|
!driver->queryFeature(video::EVDF_GEOMETRY_SHADER)){
|
||||||
|
infostream<<"generate_shader(): geometry shaders disabled "
|
||||||
|
"because of missing driver/hardware support."
|
||||||
|
<<std::endl;
|
||||||
|
geometry_program = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no shaders are used, don't make a separate material type
|
||||||
|
if(vertex_program == "" && pixel_program == "" && geometry_program == "")
|
||||||
|
return shaderinfo;
|
||||||
|
|
||||||
|
// Call addHighLevelShaderMaterial() or addShaderMaterial()
|
||||||
|
const c8* vertex_program_ptr = 0;
|
||||||
|
const c8* pixel_program_ptr = 0;
|
||||||
|
const c8* geometry_program_ptr = 0;
|
||||||
|
if(vertex_program != "")
|
||||||
|
vertex_program_ptr = vertex_program.c_str();
|
||||||
|
if(pixel_program != "")
|
||||||
|
pixel_program_ptr = pixel_program.c_str();
|
||||||
|
if(geometry_program != "")
|
||||||
|
geometry_program_ptr = geometry_program.c_str();
|
||||||
|
s32 shadermat = -1;
|
||||||
|
if(is_highlevel){
|
||||||
|
infostream<<"Compiling high level shaders for "<<name<<std::endl;
|
||||||
|
shadermat = gpu->addHighLevelShaderMaterial(
|
||||||
|
vertex_program_ptr, // Vertex shader program
|
||||||
|
"vertexMain", // Vertex shader entry point
|
||||||
|
video::EVST_VS_1_1, // Vertex shader version
|
||||||
|
pixel_program_ptr, // Pixel shader program
|
||||||
|
"pixelMain", // Pixel shader entry point
|
||||||
|
video::EPST_PS_1_1, // Pixel shader version
|
||||||
|
geometry_program_ptr, // Geometry shader program
|
||||||
|
"geometryMain", // Geometry shader entry point
|
||||||
|
video::EGST_GS_4_0, // Geometry shader version
|
||||||
|
scene::EPT_TRIANGLES, // Geometry shader input
|
||||||
|
scene::EPT_TRIANGLE_STRIP, // Geometry shader output
|
||||||
|
0, // Support maximum number of vertices
|
||||||
|
callback, // Set-constant callback
|
||||||
|
shaderinfo.material, // Base material
|
||||||
|
1 // Userdata passed to callback
|
||||||
|
);
|
||||||
|
|
||||||
|
if(shadermat == -1){
|
||||||
|
errorstream<<"generate_shader(): "
|
||||||
|
"failed to generate \""<<name<<"\", "
|
||||||
|
"addHighLevelShaderMaterial failed."
|
||||||
|
<<std::endl;
|
||||||
|
return shaderinfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
infostream<<"Compiling assembly shaders for "<<name<<std::endl;
|
||||||
|
shadermat = gpu->addShaderMaterial(
|
||||||
|
vertex_program_ptr, // Vertex shader program
|
||||||
|
pixel_program_ptr, // Pixel shader program
|
||||||
|
callback, // Set-constant callback
|
||||||
|
shaderinfo.material, // Base material
|
||||||
|
0 // Userdata passed to callback
|
||||||
|
);
|
||||||
|
|
||||||
|
if(shadermat == -1){
|
||||||
|
errorstream<<"generate_shader(): "
|
||||||
|
"failed to generate \""<<name<<"\", "
|
||||||
|
"addShaderMaterial failed."
|
||||||
|
<<std::endl;
|
||||||
|
return shaderinfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK, TODO: investigate this better
|
||||||
|
// Grab the material renderer once more so minetest doesn't crash on exit
|
||||||
|
driver->getMaterialRenderer(shadermat)->grab();
|
||||||
|
|
||||||
|
// Apply the newly created material type
|
||||||
|
shaderinfo.material = (video::E_MATERIAL_TYPE) shadermat;
|
||||||
|
return shaderinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_shaders(std::string name, SourceShaderCache *sourcecache,
|
||||||
|
video::E_DRIVER_TYPE drivertype, s32 enable_shaders,
|
||||||
|
std::string &vertex_program, std::string &pixel_program,
|
||||||
|
std::string &geometry_program, bool &is_highlevel)
|
||||||
|
{
|
||||||
|
vertex_program = "";
|
||||||
|
pixel_program = "";
|
||||||
|
geometry_program = "";
|
||||||
|
is_highlevel = false;
|
||||||
|
|
||||||
|
if(enable_shaders >= 2){
|
||||||
|
// Look for high level shaders
|
||||||
|
if(drivertype == video::EDT_DIRECT3D9){
|
||||||
|
// Direct3D 9: HLSL
|
||||||
|
// (All shaders in one file)
|
||||||
|
vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl");
|
||||||
|
pixel_program = vertex_program;
|
||||||
|
geometry_program = vertex_program;
|
||||||
|
}
|
||||||
|
else if(drivertype == video::EDT_OPENGL){
|
||||||
|
// OpenGL: GLSL
|
||||||
|
vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl");
|
||||||
|
pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl");
|
||||||
|
geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl");
|
||||||
|
}
|
||||||
|
if(vertex_program != "" || pixel_program != "" || geometry_program != ""){
|
||||||
|
is_highlevel = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(enable_shaders >= 1){
|
||||||
|
// Look for assembly shaders
|
||||||
|
if(drivertype == video::EDT_DIRECT3D8){
|
||||||
|
// Direct3D 8 assembly shaders
|
||||||
|
vertex_program = sourcecache->getOrLoad(name, "d3d8_vertex.asm");
|
||||||
|
pixel_program = sourcecache->getOrLoad(name, "d3d8_pixel.asm");
|
||||||
|
}
|
||||||
|
else if(drivertype == video::EDT_DIRECT3D9){
|
||||||
|
// Direct3D 9 assembly shaders
|
||||||
|
vertex_program = sourcecache->getOrLoad(name, "d3d9_vertex.asm");
|
||||||
|
pixel_program = sourcecache->getOrLoad(name, "d3d9_pixel.asm");
|
||||||
|
}
|
||||||
|
else if(drivertype == video::EDT_OPENGL){
|
||||||
|
// OpenGL assembly shaders
|
||||||
|
vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.asm");
|
||||||
|
pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.asm");
|
||||||
|
}
|
||||||
|
if(vertex_program != "" || pixel_program != "")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
106
src/shader.h
Normal file
106
src/shader.h
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
Copyright (C) 2012 Kahrl <kahrl@gmx.net>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHADER_HEADER
|
||||||
|
#define SHADER_HEADER
|
||||||
|
|
||||||
|
#include "irrlichttypes_extrabloated.h"
|
||||||
|
#include "threads.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class IGameDef;
|
||||||
|
|
||||||
|
/*
|
||||||
|
shader.{h,cpp}: Shader handling stuff.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Gets the path to a shader by first checking if the file
|
||||||
|
name_of_shader/filename
|
||||||
|
exists in shader_path and if not, using the data path.
|
||||||
|
|
||||||
|
If not found, returns "".
|
||||||
|
|
||||||
|
Utilizes a thread-safe cache.
|
||||||
|
*/
|
||||||
|
std::string getShaderPath(const std::string &name_of_shader,
|
||||||
|
const std::string &filename);
|
||||||
|
|
||||||
|
struct ShaderInfo
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
video::E_MATERIAL_TYPE material;
|
||||||
|
|
||||||
|
ShaderInfo(): name(""), material(video::EMT_SOLID) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Setter of constants for shaders
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace irr { namespace video {
|
||||||
|
class IMaterialRendererServices;
|
||||||
|
} }
|
||||||
|
|
||||||
|
class IShaderConstantSetter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IShaderConstantSetter(){};
|
||||||
|
virtual void onSetConstants(video::IMaterialRendererServices *services,
|
||||||
|
bool is_highlevel) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
ShaderSource creates and caches shaders.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class IShaderSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IShaderSource(){}
|
||||||
|
virtual ~IShaderSource(){}
|
||||||
|
virtual u32 getShaderId(const std::string &name){return 0;}
|
||||||
|
virtual u32 getShaderIdDirect(const std::string &name){return 0;}
|
||||||
|
virtual std::string getShaderName(u32 id){return "";}
|
||||||
|
virtual ShaderInfo getShader(u32 id){return ShaderInfo();}
|
||||||
|
virtual ShaderInfo getShader(const std::string &name){return ShaderInfo();}
|
||||||
|
};
|
||||||
|
|
||||||
|
class IWritableShaderSource : public IShaderSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IWritableShaderSource(){}
|
||||||
|
virtual ~IWritableShaderSource(){}
|
||||||
|
virtual u32 getShaderId(const std::string &name){return 0;}
|
||||||
|
virtual u32 getShaderIdDirect(const std::string &name){return 0;}
|
||||||
|
virtual std::string getShaderName(u32 id){return "";}
|
||||||
|
virtual ShaderInfo getShader(u32 id){return ShaderInfo();}
|
||||||
|
virtual ShaderInfo getShader(const std::string &name){return ShaderInfo();}
|
||||||
|
|
||||||
|
virtual void processQueue()=0;
|
||||||
|
virtual void insertSourceShader(const std::string &name_of_shader,
|
||||||
|
const std::string &filename, const std::string &program)=0;
|
||||||
|
virtual void rebuildShaders()=0;
|
||||||
|
virtual void addGlobalConstantSetter(IShaderConstantSetter *setter)=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
IWritableShaderSource* createShaderSource(IrrlichtDevice *device);
|
||||||
|
|
||||||
|
#endif
|
||||||
48
src/tile.h
48
src/tile.h
@@ -161,10 +161,9 @@ public:
|
|||||||
IWritableTextureSource* createTextureSource(IrrlichtDevice *device);
|
IWritableTextureSource* createTextureSource(IrrlichtDevice *device);
|
||||||
|
|
||||||
enum MaterialType{
|
enum MaterialType{
|
||||||
MATERIAL_ALPHA_NONE,
|
TILE_MATERIAL_BASIC,
|
||||||
MATERIAL_ALPHA_VERTEX,
|
TILE_MATERIAL_LIQUID_TRANSPARENT,
|
||||||
MATERIAL_ALPHA_SIMPLE, // >127 = opaque
|
TILE_MATERIAL_LIQUID_OPAQUE,
|
||||||
MATERIAL_ALPHA_BLEND,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Material flags
|
// Material flags
|
||||||
@@ -178,6 +177,8 @@ enum MaterialType{
|
|||||||
// Animation made up by splitting the texture to vertical frames, as
|
// Animation made up by splitting the texture to vertical frames, as
|
||||||
// defined by extra parameters
|
// defined by extra parameters
|
||||||
#define MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES 0x08
|
#define MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES 0x08
|
||||||
|
// Whether liquid shader should be used
|
||||||
|
#define MATERIAL_FLAG_
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This fully defines the looks of a tile.
|
This fully defines the looks of a tile.
|
||||||
@@ -188,9 +189,7 @@ struct TileSpec
|
|||||||
TileSpec():
|
TileSpec():
|
||||||
texture(0),
|
texture(0),
|
||||||
alpha(255),
|
alpha(255),
|
||||||
//material_type(MATERIAL_ALPHA_NONE),
|
material_type(TILE_MATERIAL_BASIC),
|
||||||
// Use this so that leaves don't need a separate material
|
|
||||||
material_type(MATERIAL_ALPHA_SIMPLE),
|
|
||||||
material_flags(
|
material_flags(
|
||||||
//0 // <- DEBUG, Use the one below
|
//0 // <- DEBUG, Use the one below
|
||||||
MATERIAL_FLAG_BACKFACE_CULLING
|
MATERIAL_FLAG_BACKFACE_CULLING
|
||||||
@@ -218,15 +217,34 @@ struct TileSpec
|
|||||||
// Sets everything else except the texture in the material
|
// Sets everything else except the texture in the material
|
||||||
void applyMaterialOptions(video::SMaterial &material) const
|
void applyMaterialOptions(video::SMaterial &material) const
|
||||||
{
|
{
|
||||||
if(material_type == MATERIAL_ALPHA_NONE)
|
switch(material_type){
|
||||||
material.MaterialType = video::EMT_SOLID;
|
case TILE_MATERIAL_BASIC:
|
||||||
else if(material_type == MATERIAL_ALPHA_VERTEX)
|
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
|
||||||
else if(material_type == MATERIAL_ALPHA_SIMPLE)
|
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
else if(material_type == MATERIAL_ALPHA_BLEND)
|
break;
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
case TILE_MATERIAL_LIQUID_TRANSPARENT:
|
||||||
|
material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
||||||
|
break;
|
||||||
|
case TILE_MATERIAL_LIQUID_OPAQUE:
|
||||||
|
material.MaterialType = video::EMT_SOLID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) ? true : false;
|
||||||
|
}
|
||||||
|
void applyMaterialOptionsWithShaders(video::SMaterial &material,
|
||||||
|
const video::E_MATERIAL_TYPE &basic,
|
||||||
|
const video::E_MATERIAL_TYPE &liquid) const
|
||||||
|
{
|
||||||
|
switch(material_type){
|
||||||
|
case TILE_MATERIAL_BASIC:
|
||||||
|
material.MaterialType = basic;
|
||||||
|
break;
|
||||||
|
case TILE_MATERIAL_LIQUID_TRANSPARENT:
|
||||||
|
material.MaterialType = liquid;
|
||||||
|
break;
|
||||||
|
case TILE_MATERIAL_LIQUID_OPAQUE:
|
||||||
|
material.MaterialType = liquid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) ? true : false;
|
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,17 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core::list<Value> getValues()
|
||||||
|
{
|
||||||
|
core::list<Value> result;
|
||||||
|
for(typename core::map<Key, Value>::Iterator
|
||||||
|
i = m_values.getIterator();
|
||||||
|
i.atEnd() == false; i++){
|
||||||
|
result.push_back(i.getNode()->getValue());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
core::map<Key, Value> m_values;
|
core::map<Key, Value> m_values;
|
||||||
JMutex m_mutex;
|
JMutex m_mutex;
|
||||||
|
|||||||
Reference in New Issue
Block a user