Merge branch 'master' of https://github.com/DustyBagel/minetest-lan
This commit is contained in:
commit
52237d279e
@ -406,6 +406,7 @@ bilinear_filter (Bilinear filtering) bool false
|
||||
trilinear_filter (Trilinear filtering) bool false
|
||||
|
||||
# Use anisotropic filtering when looking at textures from an angle.
|
||||
# This provides a significant improvement when used together with mipmapping.
|
||||
anisotropic_filter (Anisotropic filtering) bool false
|
||||
|
||||
# Select the antialiasing method to apply.
|
||||
@ -1884,12 +1885,11 @@ world_aligned_mode (World-aligned textures mode) enum enable disable,enable,forc
|
||||
# Warning: This option is EXPERIMENTAL!
|
||||
autoscale_mode (Autoscaling mode) enum disable disable,enable,force
|
||||
|
||||
# When using bilinear/trilinear/anisotropic filters, low-resolution textures
|
||||
# can be blurred, so automatically upscale them with nearest-neighbor
|
||||
# interpolation to preserve crisp pixels. This sets the minimum texture size
|
||||
# for the upscaled textures; higher values look sharper, but require more
|
||||
# memory. Powers of 2 are recommended. This setting is ONLY applied if
|
||||
# bilinear/trilinear/anisotropic filtering is enabled.
|
||||
# When using bilinear/trilinear filtering, low-resolution textures
|
||||
# can be blurred, so this option automatically upscales them to preserve
|
||||
# crisp pixels. This defines the minimum texture size for the upscaled textures;
|
||||
# higher values look sharper, but require more memory.
|
||||
# This setting is ONLY applied if any of the mentioned filters are enabled.
|
||||
# This is also used as the base node texture size for world-aligned
|
||||
# texture autoscaling.
|
||||
texture_min_size (Base texture size) int 64 1 32768
|
||||
|
@ -23,7 +23,12 @@ void main(void)
|
||||
vec2 uv = varTexCoord.st;
|
||||
vec3 color = texture2D(rendered, uv).rgb;
|
||||
// translate to linear colorspace (approximate)
|
||||
#ifdef GL_ES
|
||||
// clamp color to [0,1] range in lieu of centroids
|
||||
color = pow(clamp(color, 0.0, 1.0), vec3(2.2));
|
||||
#else
|
||||
color = pow(color, vec3(2.2));
|
||||
#endif
|
||||
|
||||
color *= exposureParams.compensationFactor * bloomStrength;
|
||||
|
||||
|
@ -39,14 +39,16 @@ varying vec3 vPosition;
|
||||
// cameraOffset + worldPosition (for large coordinates the limits of float
|
||||
// precision must be considered).
|
||||
varying vec3 worldPosition;
|
||||
varying lowp vec4 varColor;
|
||||
#ifdef GL_ES
|
||||
varying lowp vec4 varColor;
|
||||
varying mediump vec2 varTexCoord;
|
||||
varying float nightRatio;
|
||||
#else
|
||||
centroid varying lowp vec4 varColor;
|
||||
centroid varying vec2 varTexCoord;
|
||||
centroid varying float nightRatio;
|
||||
#endif
|
||||
varying highp vec3 eyeVec;
|
||||
varying float nightRatio;
|
||||
|
||||
#ifdef ENABLE_DYNAMIC_SHADOWS
|
||||
#if (defined(ENABLE_WATER_REFLECTIONS) && MATERIAL_WAVING_LIQUID && ENABLE_WAVING_WATER)
|
||||
|
@ -14,14 +14,17 @@ varying vec3 vPosition;
|
||||
// cameraOffset + worldPosition (for large coordinates the limits of float
|
||||
// precision must be considered).
|
||||
varying vec3 worldPosition;
|
||||
varying lowp vec4 varColor;
|
||||
// The centroid keyword ensures that after interpolation the texture coordinates
|
||||
// lie within the same bounds when MSAA is en- and disabled.
|
||||
// This fixes the stripes problem with nearest-neighbor textures and MSAA.
|
||||
#ifdef GL_ES
|
||||
varying lowp vec4 varColor;
|
||||
varying mediump vec2 varTexCoord;
|
||||
varying float nightRatio;
|
||||
#else
|
||||
centroid varying lowp vec4 varColor;
|
||||
centroid varying vec2 varTexCoord;
|
||||
centroid varying float nightRatio;
|
||||
#endif
|
||||
#ifdef ENABLE_DYNAMIC_SHADOWS
|
||||
// shadow uniforms
|
||||
@ -44,7 +47,6 @@ centroid varying vec2 varTexCoord;
|
||||
varying float area_enable_parallax;
|
||||
|
||||
varying highp vec3 eyeVec;
|
||||
varying float nightRatio;
|
||||
// Color of the light emitted by the light sources.
|
||||
const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
|
||||
const float e = 2.718281828459;
|
||||
|
@ -188,7 +188,6 @@ Mod directory structure
|
||||
│ ├── models
|
||||
│ ├── textures
|
||||
│ │ ├── modname_stuff.png
|
||||
│ │ ├── modname_stuff_normal.png
|
||||
│ │ ├── modname_something_else.png
|
||||
│ │ ├── subfolder_foo
|
||||
│ │ │ ├── modname_more_stuff.png
|
||||
|
@ -1,85 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "irrTypes.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Compile target enumeration for the addHighLevelShaderMaterial() method.
|
||||
enum E_VERTEX_SHADER_TYPE
|
||||
{
|
||||
EVST_VS_1_1 = 0,
|
||||
EVST_VS_2_0,
|
||||
EVST_VS_2_a,
|
||||
EVST_VS_3_0,
|
||||
EVST_VS_4_0,
|
||||
EVST_VS_4_1,
|
||||
EVST_VS_5_0,
|
||||
|
||||
//! This is not a type, but a value indicating how much types there are.
|
||||
EVST_COUNT
|
||||
};
|
||||
|
||||
//! Names for all vertex shader types, each entry corresponds to a E_VERTEX_SHADER_TYPE entry.
|
||||
const c8 *const VERTEX_SHADER_TYPE_NAMES[] = {
|
||||
"vs_1_1",
|
||||
"vs_2_0",
|
||||
"vs_2_a",
|
||||
"vs_3_0",
|
||||
"vs_4_0",
|
||||
"vs_4_1",
|
||||
"vs_5_0",
|
||||
0};
|
||||
|
||||
//! Compile target enumeration for the addHighLevelShaderMaterial() method.
|
||||
enum E_PIXEL_SHADER_TYPE
|
||||
{
|
||||
EPST_PS_1_1 = 0,
|
||||
EPST_PS_1_2,
|
||||
EPST_PS_1_3,
|
||||
EPST_PS_1_4,
|
||||
EPST_PS_2_0,
|
||||
EPST_PS_2_a,
|
||||
EPST_PS_2_b,
|
||||
EPST_PS_3_0,
|
||||
EPST_PS_4_0,
|
||||
EPST_PS_4_1,
|
||||
EPST_PS_5_0,
|
||||
|
||||
//! This is not a type, but a value indicating how much types there are.
|
||||
EPST_COUNT
|
||||
};
|
||||
|
||||
//! Names for all pixel shader types, each entry corresponds to a E_PIXEL_SHADER_TYPE entry.
|
||||
const c8 *const PIXEL_SHADER_TYPE_NAMES[] = {
|
||||
"ps_1_1",
|
||||
"ps_1_2",
|
||||
"ps_1_3",
|
||||
"ps_1_4",
|
||||
"ps_2_0",
|
||||
"ps_2_a",
|
||||
"ps_2_b",
|
||||
"ps_3_0",
|
||||
"ps_4_0",
|
||||
"ps_4_1",
|
||||
"ps_5_0",
|
||||
0};
|
||||
|
||||
//! Enum for supported geometry shader types
|
||||
enum E_GEOMETRY_SHADER_TYPE
|
||||
{
|
||||
EGST_GS_4_0 = 0,
|
||||
|
||||
//! This is not a type, but a value indicating how much types there are.
|
||||
EGST_COUNT
|
||||
};
|
||||
|
||||
//! String names for supported geometry shader types
|
||||
const c8 *const GEOMETRY_SHADER_TYPE_NAMES[] = {
|
||||
"gs_4_0",
|
||||
0};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
@ -4,7 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "EShaderTypes.h"
|
||||
#include "EMaterialTypes.h"
|
||||
#include "EPrimitiveTypes.h"
|
||||
#include "path.h"
|
||||
@ -31,26 +30,15 @@ public:
|
||||
virtual ~IGPUProgrammingServices() {}
|
||||
|
||||
//! Adds a new high-level shading material renderer to the VideoDriver.
|
||||
/** Currently only HLSL/D3D9 and GLSL/OpenGL are supported.
|
||||
/**
|
||||
\param vertexShaderProgram String containing the source of the vertex
|
||||
shader program. This can be 0 if no vertex program shall be used.
|
||||
\param vertexShaderEntryPointName Name of the entry function of the
|
||||
vertexShaderProgram (p.e. "main")
|
||||
\param vsCompileTarget Vertex shader version the high level shader
|
||||
shall be compiled to.
|
||||
\param pixelShaderProgram String containing the source of the pixel
|
||||
shader program. This can be 0 if no pixel shader shall be used.
|
||||
\param pixelShaderEntryPointName Entry name of the function of the
|
||||
pixelShaderProgram (p.e. "main")
|
||||
\param psCompileTarget Pixel shader version the high level shader
|
||||
shall be compiled to.
|
||||
\param geometryShaderProgram String containing the source of the
|
||||
geometry shader program. This can be 0 if no geometry shader shall be
|
||||
used.
|
||||
\param geometryShaderEntryPointName Entry name of the function of the
|
||||
geometryShaderProgram (p.e. "main")
|
||||
\param gsCompileTarget Geometry shader version the high level shader
|
||||
shall be compiled to.
|
||||
\param shaderName Name of the shader for debug purposes
|
||||
\param inType Type of vertices passed to geometry shader
|
||||
\param outType Type of vertices created by geometry shader
|
||||
\param verticesOut Maximal number of vertices created by geometry
|
||||
@ -73,108 +61,43 @@ public:
|
||||
error log and can be caught with a custom event receiver. */
|
||||
virtual s32 addHighLevelShaderMaterial(
|
||||
const c8 *vertexShaderProgram,
|
||||
const c8 *vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8 *pixelShaderProgram,
|
||||
const c8 *pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
const c8 *geometryShaderProgram,
|
||||
const c8 *geometryShaderEntryPointName = "main",
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
||||
const c8 *shaderName = nullptr,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
IShaderConstantSetCallBack *callback = nullptr,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0) = 0;
|
||||
|
||||
//! convenience function for use without geometry shaders
|
||||
s32 addHighLevelShaderMaterial(
|
||||
const c8 *vertexShaderProgram,
|
||||
const c8 *vertexShaderEntryPointName = "main",
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1,
|
||||
const c8 *pixelShaderProgram = 0,
|
||||
const c8 *pixelShaderEntryPointName = "main",
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
const c8 *pixelShaderProgram = nullptr,
|
||||
const c8 *shaderName = nullptr,
|
||||
IShaderConstantSetCallBack *callback = nullptr,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0)
|
||||
{
|
||||
return addHighLevelShaderMaterial(
|
||||
vertexShaderProgram, vertexShaderEntryPointName,
|
||||
vsCompileTarget, pixelShaderProgram,
|
||||
pixelShaderEntryPointName, psCompileTarget,
|
||||
0, "main", EGST_GS_4_0,
|
||||
vertexShaderProgram, pixelShaderProgram,
|
||||
nullptr, shaderName,
|
||||
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0,
|
||||
callback, baseMaterial, userData);
|
||||
}
|
||||
|
||||
//! convenience function for use with many defaults, without geometry shader
|
||||
/** All shader names are set to "main" and compile targets are shader
|
||||
type 1.1.
|
||||
*/
|
||||
s32 addHighLevelShaderMaterial(
|
||||
const c8 *vertexShaderProgram,
|
||||
const c8 *pixelShaderProgram = 0,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0)
|
||||
{
|
||||
return addHighLevelShaderMaterial(
|
||||
vertexShaderProgram, "main",
|
||||
EVST_VS_1_1, pixelShaderProgram,
|
||||
"main", EPST_PS_1_1,
|
||||
0, "main", EGST_GS_4_0,
|
||||
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0,
|
||||
callback, baseMaterial, userData);
|
||||
}
|
||||
|
||||
//! convenience function for use with many defaults, with geometry shader
|
||||
/** All shader names are set to "main" and compile targets are shader
|
||||
type 1.1 and geometry shader 4.0.
|
||||
*/
|
||||
s32 addHighLevelShaderMaterial(
|
||||
const c8 *vertexShaderProgram,
|
||||
const c8 *pixelShaderProgram = 0,
|
||||
const c8 *geometryShaderProgram = 0,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0)
|
||||
{
|
||||
return addHighLevelShaderMaterial(
|
||||
vertexShaderProgram, "main",
|
||||
EVST_VS_1_1, pixelShaderProgram,
|
||||
"main", EPST_PS_1_1,
|
||||
geometryShaderProgram, "main", EGST_GS_4_0,
|
||||
inType, outType, verticesOut,
|
||||
callback, baseMaterial, userData);
|
||||
}
|
||||
|
||||
//! Like addHighLevelShaderMaterial(), but loads from files.
|
||||
/** \param vertexShaderProgramFileName Text file containing the source
|
||||
of the vertex shader program. Set to empty string if no vertex shader
|
||||
shall be created.
|
||||
\param vertexShaderEntryPointName Name of the entry function of the
|
||||
vertexShaderProgram (p.e. "main")
|
||||
\param vsCompileTarget Vertex shader version the high level shader
|
||||
shall be compiled to.
|
||||
\param pixelShaderProgramFileName Text file containing the source of
|
||||
the pixel shader program. Set to empty string if no pixel shader shall
|
||||
be created.
|
||||
\param pixelShaderEntryPointName Entry name of the function of the
|
||||
pixelShaderProgram (p.e. "main")
|
||||
\param psCompileTarget Pixel shader version the high level shader
|
||||
shall be compiled to.
|
||||
\param geometryShaderProgramFileName Name of the source of
|
||||
the geometry shader program. Set to empty string if no geometry shader
|
||||
shall be created.
|
||||
\param geometryShaderEntryPointName Entry name of the function of the
|
||||
geometryShaderProgram (p.e. "main")
|
||||
\param gsCompileTarget Geometry shader version the high level shader
|
||||
shall be compiled to.
|
||||
\param shaderName Name of the shader for debug purposes
|
||||
\param inType Type of vertices passed to geometry shader
|
||||
\param outType Type of vertices created by geometry shader
|
||||
\param verticesOut Maximal number of vertices created by geometry
|
||||
@ -197,164 +120,16 @@ public:
|
||||
error log and can be caught with a custom event receiver. */
|
||||
virtual s32 addHighLevelShaderMaterialFromFiles(
|
||||
const io::path &vertexShaderProgramFileName,
|
||||
const c8 *vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const io::path &pixelShaderProgramFileName,
|
||||
const c8 *pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
const io::path &geometryShaderProgramFileName,
|
||||
const c8 *geometryShaderEntryPointName = "main",
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
||||
const c8 *shaderName = nullptr,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
IShaderConstantSetCallBack *callback = nullptr,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0) = 0;
|
||||
|
||||
//! convenience function for use without geometry shaders
|
||||
s32 addHighLevelShaderMaterialFromFiles(
|
||||
const io::path &vertexShaderProgramFileName,
|
||||
const c8 *vertexShaderEntryPointName = "main",
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1,
|
||||
const io::path &pixelShaderProgramFileName = "",
|
||||
const c8 *pixelShaderEntryPointName = "main",
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0)
|
||||
{
|
||||
return addHighLevelShaderMaterialFromFiles(
|
||||
vertexShaderProgramFileName, vertexShaderEntryPointName,
|
||||
vsCompileTarget, pixelShaderProgramFileName,
|
||||
pixelShaderEntryPointName, psCompileTarget,
|
||||
"", "main", EGST_GS_4_0,
|
||||
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0,
|
||||
callback, baseMaterial, userData);
|
||||
}
|
||||
|
||||
//! convenience function for use with many defaults, without geometry shader
|
||||
/** All shader names are set to "main" and compile targets are shader
|
||||
type 1.1.
|
||||
*/
|
||||
s32 addHighLevelShaderMaterialFromFiles(
|
||||
const io::path &vertexShaderProgramFileName,
|
||||
const io::path &pixelShaderProgramFileName = "",
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0)
|
||||
{
|
||||
return addHighLevelShaderMaterialFromFiles(
|
||||
vertexShaderProgramFileName, "main",
|
||||
EVST_VS_1_1, pixelShaderProgramFileName,
|
||||
"main", EPST_PS_1_1,
|
||||
"", "main", EGST_GS_4_0,
|
||||
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0,
|
||||
callback, baseMaterial, userData);
|
||||
}
|
||||
|
||||
//! convenience function for use with many defaults, with geometry shader
|
||||
/** All shader names are set to "main" and compile targets are shader
|
||||
type 1.1 and geometry shader 4.0.
|
||||
*/
|
||||
s32 addHighLevelShaderMaterialFromFiles(
|
||||
const io::path &vertexShaderProgramFileName,
|
||||
const io::path &pixelShaderProgramFileName = "",
|
||||
const io::path &geometryShaderProgramFileName = "",
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0)
|
||||
{
|
||||
return addHighLevelShaderMaterialFromFiles(
|
||||
vertexShaderProgramFileName, "main",
|
||||
EVST_VS_1_1, pixelShaderProgramFileName,
|
||||
"main", EPST_PS_1_1,
|
||||
geometryShaderProgramFileName, "main", EGST_GS_4_0,
|
||||
inType, outType, verticesOut,
|
||||
callback, baseMaterial, userData);
|
||||
}
|
||||
|
||||
//! Like addHighLevelShaderMaterial(), but loads from files.
|
||||
/** \param vertexShaderProgram Text file handle containing the source
|
||||
of the vertex shader program. Set to 0 if no vertex shader shall be
|
||||
created.
|
||||
\param vertexShaderEntryPointName Name of the entry function of the
|
||||
vertexShaderProgram
|
||||
\param vsCompileTarget Vertex shader version the high level shader
|
||||
shall be compiled to.
|
||||
\param pixelShaderProgram Text file handle containing the source of
|
||||
the pixel shader program. Set to 0 if no pixel shader shall be created.
|
||||
\param pixelShaderEntryPointName Entry name of the function of the
|
||||
pixelShaderProgram (p.e. "main")
|
||||
\param psCompileTarget Pixel shader version the high level shader
|
||||
shall be compiled to.
|
||||
\param geometryShaderProgram Text file handle containing the source of
|
||||
the geometry shader program. Set to 0 if no geometry shader shall be
|
||||
created.
|
||||
\param geometryShaderEntryPointName Entry name of the function of the
|
||||
geometryShaderProgram (p.e. "main")
|
||||
\param gsCompileTarget Geometry shader version the high level shader
|
||||
shall be compiled to.
|
||||
\param inType Type of vertices passed to geometry shader
|
||||
\param outType Type of vertices created by geometry shader
|
||||
\param verticesOut Maximal number of vertices created by geometry
|
||||
shader. If 0, maximal number supported is assumed.
|
||||
\param callback Pointer to an implementation of
|
||||
IShaderConstantSetCallBack in which you can set the needed vertex and
|
||||
pixel shader program constants. Set this to 0 if you don't need this.
|
||||
\param baseMaterial Base material which renderstates will be used to
|
||||
shade the material.
|
||||
\param userData a user data int. This int can be set to any value and
|
||||
will be set as parameter in the callback method when calling
|
||||
OnSetConstants(). In this way it is easily possible to use the same
|
||||
callback method for multiple materials and distinguish between them
|
||||
during the call.
|
||||
\return Number of the material type which can be set in
|
||||
SMaterial::MaterialType to use the renderer. -1 is returned if an
|
||||
error occurred, e.g. if a shader program could not be compiled or a
|
||||
compile target is not reachable. The error strings are then printed to
|
||||
the error log and can be caught with a custom event receiver. */
|
||||
virtual s32 addHighLevelShaderMaterialFromFiles(
|
||||
io::IReadFile *vertexShaderProgram,
|
||||
const c8 *vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
io::IReadFile *pixelShaderProgram,
|
||||
const c8 *pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
io::IReadFile *geometryShaderProgram,
|
||||
const c8 *geometryShaderEntryPointName = "main",
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0) = 0;
|
||||
|
||||
//! convenience function for use without geometry shaders
|
||||
s32 addHighLevelShaderMaterialFromFiles(
|
||||
io::IReadFile *vertexShaderProgram,
|
||||
const c8 *vertexShaderEntryPointName = "main",
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1,
|
||||
io::IReadFile *pixelShaderProgram = 0,
|
||||
const c8 *pixelShaderEntryPointName = "main",
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0)
|
||||
{
|
||||
return addHighLevelShaderMaterialFromFiles(
|
||||
vertexShaderProgram, vertexShaderEntryPointName,
|
||||
vsCompileTarget, pixelShaderProgram,
|
||||
pixelShaderEntryPointName, psCompileTarget,
|
||||
0, "main", EGST_GS_4_0,
|
||||
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0,
|
||||
callback, baseMaterial, userData);
|
||||
}
|
||||
|
||||
//! Delete a shader material and associated data.
|
||||
/**
|
||||
After you have deleted a material it is invalid to still use and doing
|
||||
|
@ -61,8 +61,8 @@ struct SFrameStats {
|
||||
u32 PrimitivesDrawn = 0;
|
||||
//! Number of hardware buffers uploaded (new or updated)
|
||||
u32 HWBuffersUploaded = 0;
|
||||
//! Sum of uploaded hardware buffer size
|
||||
u32 HWBuffersUploadedSize = 0;
|
||||
//! Number of active hardware buffers
|
||||
u32 HWBuffersActive = 0;
|
||||
};
|
||||
|
||||
//! Interface to driver which is able to perform 2d and 3d graphics functions.
|
||||
|
@ -218,7 +218,7 @@ bool CNullDriver::beginScene(u16 clearFlag, SColor clearColor, f32 clearDepth, u
|
||||
bool CNullDriver::endScene()
|
||||
{
|
||||
FPSCounter.registerFrame(os::Timer::getRealTime());
|
||||
updateAllHardwareBuffers();
|
||||
expireHardwareBuffers();
|
||||
updateAllOcclusionQueries();
|
||||
return true;
|
||||
}
|
||||
@ -1141,33 +1141,47 @@ CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IIndexBuffer
|
||||
return createHardwareBuffer(ib); // no hardware links, and mesh wants one, create it
|
||||
}
|
||||
|
||||
//! Update all hardware buffers, remove unused ones
|
||||
void CNullDriver::updateAllHardwareBuffers()
|
||||
void CNullDriver::registerHardwareBuffer(SHWBufferLink *HWBuffer)
|
||||
{
|
||||
// FIXME: this method can take a lot of time just doing the refcount
|
||||
// checks and iteration (too much pointer chasing?) for
|
||||
// large buffer counts (e.g. 50000)
|
||||
_IRR_DEBUG_BREAK_IF(!HWBuffer)
|
||||
HWBuffer->ListPosition = HWBufferList.size();
|
||||
HWBufferList.push_back(HWBuffer);
|
||||
}
|
||||
|
||||
auto it = HWBufferList.begin();
|
||||
while (it != HWBufferList.end()) {
|
||||
SHWBufferLink *Link = *it;
|
||||
++it;
|
||||
void CNullDriver::expireHardwareBuffers()
|
||||
{
|
||||
for (size_t i = 0; i < HWBufferList.size(); ) {
|
||||
auto *Link = HWBufferList[i];
|
||||
|
||||
if (Link->IsVertex) {
|
||||
if (!Link->VertexBuffer || Link->VertexBuffer->getReferenceCount() == 1)
|
||||
deleteHardwareBuffer(Link);
|
||||
} else {
|
||||
if (!Link->IndexBuffer || Link->IndexBuffer->getReferenceCount() == 1)
|
||||
deleteHardwareBuffer(Link);
|
||||
}
|
||||
bool del;
|
||||
if (Link->IsVertex)
|
||||
del = !Link->VertexBuffer || Link->VertexBuffer->getReferenceCount() == 1;
|
||||
else
|
||||
del = !Link->IndexBuffer || Link->IndexBuffer->getReferenceCount() == 1;
|
||||
// deleting can reorder, so don't advance in list
|
||||
if (del)
|
||||
deleteHardwareBuffer(Link);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
FrameStats.HWBuffersActive = HWBufferList.size();
|
||||
}
|
||||
|
||||
void CNullDriver::deleteHardwareBuffer(SHWBufferLink *HWBuffer)
|
||||
{
|
||||
if (!HWBuffer)
|
||||
return;
|
||||
HWBufferList.erase(HWBuffer->listPosition);
|
||||
const size_t pos = HWBuffer->ListPosition;
|
||||
_IRR_DEBUG_BREAK_IF(HWBufferList.at(pos) != HWBuffer)
|
||||
if (HWBufferList.size() < 2 || pos == HWBufferList.size() - 1) {
|
||||
HWBufferList.erase(HWBufferList.begin() + pos);
|
||||
} else {
|
||||
// swap with last
|
||||
std::swap(HWBufferList[pos], HWBufferList.back());
|
||||
HWBufferList.pop_back();
|
||||
HWBufferList[pos]->ListPosition = pos;
|
||||
}
|
||||
delete HWBuffer;
|
||||
}
|
||||
|
||||
@ -1506,34 +1520,24 @@ IGPUProgrammingServices *CNullDriver::getGPUProgrammingServices()
|
||||
//! Adds a new material renderer to the VideoDriver, based on a high level shading language.
|
||||
s32 CNullDriver::addHighLevelShaderMaterial(
|
||||
const c8 *vertexShaderProgram,
|
||||
const c8 *vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8 *pixelShaderProgram,
|
||||
const c8 *pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
const c8 *geometryShaderProgram,
|
||||
const c8 *geometryShaderEntryPointName,
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
|
||||
const c8 *shaderName,
|
||||
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
|
||||
u32 verticesOut,
|
||||
IShaderConstantSetCallBack *callback,
|
||||
E_MATERIAL_TYPE baseMaterial,
|
||||
s32 userData)
|
||||
{
|
||||
os::Printer::log("High level shader materials not available (yet) in this driver, sorry");
|
||||
os::Printer::log("Shader materials not available in this driver", ELL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
|
||||
const io::path &vertexShaderProgramFileName,
|
||||
const c8 *vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const io::path &pixelShaderProgramFileName,
|
||||
const c8 *pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
const io::path &geometryShaderProgramFileName,
|
||||
const c8 *geometryShaderEntryPointName,
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
|
||||
const c8 *shaderName,
|
||||
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
|
||||
u32 verticesOut,
|
||||
IShaderConstantSetCallBack *callback,
|
||||
@ -1569,9 +1573,7 @@ s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
|
||||
}
|
||||
|
||||
s32 result = addHighLevelShaderMaterialFromFiles(
|
||||
vsfile, vertexShaderEntryPointName, vsCompileTarget,
|
||||
psfile, pixelShaderEntryPointName, psCompileTarget,
|
||||
gsfile, geometryShaderEntryPointName, gsCompileTarget,
|
||||
vsfile, psfile, gsfile, shaderName,
|
||||
inType, outType, verticesOut,
|
||||
callback, baseMaterial, userData);
|
||||
|
||||
@ -1589,14 +1591,9 @@ s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
|
||||
|
||||
s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
|
||||
io::IReadFile *vertexShaderProgram,
|
||||
const c8 *vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
io::IReadFile *pixelShaderProgram,
|
||||
const c8 *pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
io::IReadFile *geometryShaderProgram,
|
||||
const c8 *geometryShaderEntryPointName,
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
|
||||
const c8 *shaderName,
|
||||
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
|
||||
u32 verticesOut,
|
||||
IShaderConstantSetCallBack *callback,
|
||||
@ -1642,9 +1639,7 @@ s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
|
||||
}
|
||||
|
||||
s32 result = this->addHighLevelShaderMaterial(
|
||||
vs, vertexShaderEntryPointName, vsCompileTarget,
|
||||
ps, pixelShaderEntryPointName, psCompileTarget,
|
||||
gs, geometryShaderEntryPointName, gsCompileTarget,
|
||||
vs, ps, gs, shaderName,
|
||||
inType, outType, verticesOut,
|
||||
callback, baseMaterial, userData);
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "S3DVertex.h"
|
||||
#include "SVertexIndex.h"
|
||||
#include "SExposedVideoData.h"
|
||||
#include <list>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
@ -293,7 +292,7 @@ protected:
|
||||
struct SHWBufferLink
|
||||
{
|
||||
SHWBufferLink(const scene::IVertexBuffer *vb) :
|
||||
VertexBuffer(vb), ChangedID(0), IsVertex(true)
|
||||
VertexBuffer(vb), IsVertex(true)
|
||||
{
|
||||
if (VertexBuffer) {
|
||||
VertexBuffer->grab();
|
||||
@ -301,7 +300,7 @@ protected:
|
||||
}
|
||||
}
|
||||
SHWBufferLink(const scene::IIndexBuffer *ib) :
|
||||
IndexBuffer(ib), ChangedID(0), IsVertex(false)
|
||||
IndexBuffer(ib), IsVertex(false)
|
||||
{
|
||||
if (IndexBuffer) {
|
||||
IndexBuffer->grab();
|
||||
@ -324,9 +323,9 @@ protected:
|
||||
const scene::IVertexBuffer *VertexBuffer;
|
||||
const scene::IIndexBuffer *IndexBuffer;
|
||||
};
|
||||
u32 ChangedID;
|
||||
size_t ListPosition = static_cast<size_t>(-1);
|
||||
u32 ChangedID = 0;
|
||||
bool IsVertex;
|
||||
std::list<SHWBufferLink*>::iterator listPosition;
|
||||
};
|
||||
|
||||
//! Gets hardware buffer link from a vertex buffer (may create or update buffer)
|
||||
@ -361,8 +360,8 @@ public:
|
||||
//! Remove all hardware buffers
|
||||
void removeAllHardwareBuffers() override;
|
||||
|
||||
//! Update all hardware buffers, remove unused ones
|
||||
virtual void updateAllHardwareBuffers();
|
||||
//! Run garbage-collection on all HW buffers
|
||||
void expireHardwareBuffers();
|
||||
|
||||
//! is vbo recommended?
|
||||
virtual bool isHardwareBufferRecommend(const scene::IVertexBuffer *mb);
|
||||
@ -450,54 +449,39 @@ public:
|
||||
//! Adds a new material renderer to the VideoDriver, based on a high level shading language.
|
||||
virtual s32 addHighLevelShaderMaterial(
|
||||
const c8 *vertexShaderProgram,
|
||||
const c8 *vertexShaderEntryPointName = 0,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1,
|
||||
const c8 *pixelShaderProgram = 0,
|
||||
const c8 *pixelShaderEntryPointName = 0,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1,
|
||||
const c8 *geometryShaderProgram = 0,
|
||||
const c8 *geometryShaderEntryPointName = "main",
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
||||
const c8 *pixelShaderProgram,
|
||||
const c8 *geometryShaderProgram,
|
||||
const c8 *shaderName = nullptr,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
IShaderConstantSetCallBack *callback = nullptr,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0) override;
|
||||
s32 userData = 0)override;
|
||||
|
||||
virtual s32 addHighLevelShaderMaterialFromFiles(
|
||||
const io::path &vertexShaderProgramFile,
|
||||
const c8 *vertexShaderEntryPointName = "main",
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1,
|
||||
const io::path &pixelShaderProgramFile = "",
|
||||
const c8 *pixelShaderEntryPointName = "main",
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1,
|
||||
const io::path &geometryShaderProgramFileName = "",
|
||||
const c8 *geometryShaderEntryPointName = "main",
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
||||
const io::path &vertexShaderProgramFileName,
|
||||
const io::path &pixelShaderProgramFileName,
|
||||
const io::path &geometryShaderProgramFileName,
|
||||
const c8 *shaderName = nullptr,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
IShaderConstantSetCallBack *callback = nullptr,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0) override;
|
||||
|
||||
virtual s32 addHighLevelShaderMaterialFromFiles(
|
||||
s32 addHighLevelShaderMaterialFromFiles(
|
||||
io::IReadFile *vertexShaderProgram,
|
||||
const c8 *vertexShaderEntryPointName = "main",
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1,
|
||||
io::IReadFile *pixelShaderProgram = 0,
|
||||
const c8 *pixelShaderEntryPointName = "main",
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1,
|
||||
io::IReadFile *geometryShaderProgram = 0,
|
||||
const c8 *geometryShaderEntryPointName = "main",
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
||||
const c8 *shaderName = nullptr,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
IShaderConstantSetCallBack *callback = nullptr,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0) override;
|
||||
s32 userData = 0);
|
||||
|
||||
virtual void deleteShaderMaterial(s32 material) override;
|
||||
|
||||
@ -582,13 +566,16 @@ protected:
|
||||
//! deletes all material renderers
|
||||
void deleteMaterialRenders();
|
||||
|
||||
// adds a created hardware buffer to the relevant data structure
|
||||
void registerHardwareBuffer(SHWBufferLink *HWBuffer);
|
||||
|
||||
// prints renderer version
|
||||
void printVersion();
|
||||
|
||||
inline void accountHWBufferUpload(u32 size)
|
||||
{
|
||||
FrameStats.HWBuffersUploaded++;
|
||||
FrameStats.HWBuffersUploadedSize += size;
|
||||
(void)size;
|
||||
}
|
||||
|
||||
inline bool getWriteZBuffer(const SMaterial &material) const
|
||||
@ -705,7 +692,7 @@ protected:
|
||||
core::array<video::IImageWriter *> SurfaceWriter;
|
||||
core::array<SMaterialRenderer> MaterialRenderers;
|
||||
|
||||
std::list<SHWBufferLink *> HWBufferList;
|
||||
std::vector<SHWBufferLink *> HWBufferList;
|
||||
|
||||
io::IFileSystem *FileSystem;
|
||||
|
||||
|
@ -430,9 +430,7 @@ COpenGLDriver::SHWBufferLink *COpenGLDriver::createHardwareBuffer(const scene::I
|
||||
return 0;
|
||||
|
||||
SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(vb);
|
||||
|
||||
// add to map
|
||||
HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer);
|
||||
registerHardwareBuffer(HWBuffer);
|
||||
|
||||
if (!updateVertexHardwareBuffer(HWBuffer)) {
|
||||
deleteHardwareBuffer(HWBuffer);
|
||||
@ -453,9 +451,7 @@ COpenGLDriver::SHWBufferLink *COpenGLDriver::createHardwareBuffer(const scene::I
|
||||
return 0;
|
||||
|
||||
SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(ib);
|
||||
|
||||
// add to map
|
||||
HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer);
|
||||
registerHardwareBuffer(HWBuffer);
|
||||
|
||||
if (!updateIndexHardwareBuffer(HWBuffer)) {
|
||||
deleteHardwareBuffer(HWBuffer);
|
||||
@ -2658,14 +2654,9 @@ bool COpenGLDriver::setPixelShaderConstant(s32 index, const u32 *ints, int count
|
||||
//! Adds a new material renderer to the VideoDriver, using GLSL to render geometry.
|
||||
s32 COpenGLDriver::addHighLevelShaderMaterial(
|
||||
const c8 *vertexShaderProgram,
|
||||
const c8 *vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8 *pixelShaderProgram,
|
||||
const c8 *pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
const c8 *geometryShaderProgram,
|
||||
const c8 *geometryShaderEntryPointName,
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
|
||||
const c8 *shaderName,
|
||||
scene::E_PRIMITIVE_TYPE inType,
|
||||
scene::E_PRIMITIVE_TYPE outType,
|
||||
u32 verticesOut,
|
||||
@ -2677,9 +2668,9 @@ s32 COpenGLDriver::addHighLevelShaderMaterial(
|
||||
|
||||
COpenGLSLMaterialRenderer *r = new COpenGLSLMaterialRenderer(
|
||||
this, nr,
|
||||
vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget,
|
||||
pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget,
|
||||
geometryShaderProgram, geometryShaderEntryPointName, gsCompileTarget,
|
||||
vertexShaderProgram,
|
||||
pixelShaderProgram,
|
||||
geometryShaderProgram,
|
||||
inType, outType, verticesOut,
|
||||
callback, baseMaterial, userData);
|
||||
|
||||
|
@ -240,18 +240,13 @@ public:
|
||||
//! Adds a new material renderer to the VideoDriver, using GLSL to render geometry.
|
||||
virtual s32 addHighLevelShaderMaterial(
|
||||
const c8 *vertexShaderProgram,
|
||||
const c8 *vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8 *pixelShaderProgram,
|
||||
const c8 *pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
const c8 *geometryShaderProgram,
|
||||
const c8 *geometryShaderEntryPointName = "main",
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
||||
const c8 *shaderName = nullptr,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
IShaderConstantSetCallBack *callback = nullptr,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0) override;
|
||||
|
||||
|
@ -34,14 +34,8 @@ namespace video
|
||||
//! Constructor
|
||||
COpenGLSLMaterialRenderer::COpenGLSLMaterialRenderer(video::COpenGLDriver *driver,
|
||||
s32 &outMaterialTypeNr, const c8 *vertexShaderProgram,
|
||||
const c8 *vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8 *pixelShaderProgram,
|
||||
const c8 *pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
const c8 *geometryShaderProgram,
|
||||
const c8 *geometryShaderEntryPointName,
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
|
||||
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
|
||||
u32 verticesOut,
|
||||
IShaderConstantSetCallBack *callback,
|
||||
|
@ -33,14 +33,8 @@ public:
|
||||
COpenGLDriver *driver,
|
||||
s32 &outMaterialTypeNr,
|
||||
const c8 *vertexShaderProgram = 0,
|
||||
const c8 *vertexShaderEntryPointName = 0,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget = video::EVST_VS_1_1,
|
||||
const c8 *pixelShaderProgram = 0,
|
||||
const c8 *pixelShaderEntryPointName = 0,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget = video::EPST_PS_1_1,
|
||||
const c8 *geometryShaderProgram = 0,
|
||||
const c8 *geometryShaderEntryPointName = "main",
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
|
@ -386,28 +386,28 @@ void COpenGL3DriverBase::createMaterialRenderers()
|
||||
|
||||
// EMT_SOLID
|
||||
core::stringc FragmentShader = OGLES2ShaderPath + "Solid.fsh";
|
||||
addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",
|
||||
EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, SolidCB, EMT_SOLID, 0);
|
||||
addHighLevelShaderMaterialFromFiles(VertexShader, FragmentShader, "", "Solid",
|
||||
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, SolidCB, EMT_SOLID, 0);
|
||||
|
||||
// EMT_TRANSPARENT_ALPHA_CHANNEL
|
||||
FragmentShader = OGLES2ShaderPath + "TransparentAlphaChannel.fsh";
|
||||
addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",
|
||||
EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAlphaChannelCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);
|
||||
addHighLevelShaderMaterialFromFiles(VertexShader, FragmentShader, "", "TransparentAlphaChannel",
|
||||
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAlphaChannelCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);
|
||||
|
||||
// EMT_TRANSPARENT_ALPHA_CHANNEL_REF
|
||||
FragmentShader = OGLES2ShaderPath + "TransparentAlphaChannelRef.fsh";
|
||||
addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",
|
||||
EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAlphaChannelRefCB, EMT_SOLID, 0);
|
||||
addHighLevelShaderMaterialFromFiles(VertexShader, FragmentShader, "", "TransparentAlphaChannelRef",
|
||||
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAlphaChannelRefCB, EMT_SOLID, 0);
|
||||
|
||||
// EMT_TRANSPARENT_VERTEX_ALPHA
|
||||
FragmentShader = OGLES2ShaderPath + "TransparentVertexAlpha.fsh";
|
||||
addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",
|
||||
EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentVertexAlphaCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);
|
||||
addHighLevelShaderMaterialFromFiles(VertexShader, FragmentShader, "", "TransparentVertexAlpha",
|
||||
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentVertexAlphaCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);
|
||||
|
||||
// EMT_ONETEXTURE_BLEND
|
||||
FragmentShader = OGLES2ShaderPath + "OneTextureBlend.fsh";
|
||||
addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",
|
||||
EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, OneTextureBlendCB, EMT_ONETEXTURE_BLEND, 0);
|
||||
addHighLevelShaderMaterialFromFiles(VertexShader, FragmentShader, "", "OneTextureBlend",
|
||||
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, OneTextureBlendCB, EMT_ONETEXTURE_BLEND, 0);
|
||||
|
||||
// Drop callbacks.
|
||||
|
||||
@ -566,10 +566,8 @@ COpenGL3DriverBase::SHWBufferLink *COpenGL3DriverBase::createHardwareBuffer(cons
|
||||
if (!vb || vb->getHardwareMappingHint() == scene::EHM_NEVER)
|
||||
return 0;
|
||||
|
||||
SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(vb);
|
||||
|
||||
// add to map
|
||||
HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer);
|
||||
auto *HWBuffer = new SHWBufferLink_opengl(vb);
|
||||
registerHardwareBuffer(HWBuffer);
|
||||
|
||||
if (!updateVertexHardwareBuffer(HWBuffer)) {
|
||||
deleteHardwareBuffer(HWBuffer);
|
||||
@ -584,10 +582,8 @@ COpenGL3DriverBase::SHWBufferLink *COpenGL3DriverBase::createHardwareBuffer(cons
|
||||
if (!ib || ib->getHardwareMappingHint() == scene::EHM_NEVER)
|
||||
return 0;
|
||||
|
||||
SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(ib);
|
||||
|
||||
// add to map
|
||||
HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer);
|
||||
auto *HWBuffer = new SHWBufferLink_opengl(ib);
|
||||
registerHardwareBuffer(HWBuffer);
|
||||
|
||||
if (!updateIndexHardwareBuffer(HWBuffer)) {
|
||||
deleteHardwareBuffer(HWBuffer);
|
||||
@ -1344,60 +1340,74 @@ void COpenGL3DriverBase::setTextureRenderStates(const SMaterial &material, bool
|
||||
|
||||
CacheHandler->setActiveTexture(GL_TEXTURE0 + i);
|
||||
|
||||
if (resetAllRenderstates)
|
||||
tmpTexture->getStatesCache().IsCached = false;
|
||||
const auto &layer = material.TextureLayers[i];
|
||||
auto &states = tmpTexture->getStatesCache();
|
||||
|
||||
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayers[i].MagFilter != tmpTexture->getStatesCache().MagFilter) {
|
||||
E_TEXTURE_MAG_FILTER magFilter = material.TextureLayers[i].MagFilter;
|
||||
if (resetAllRenderstates)
|
||||
states.IsCached = false;
|
||||
|
||||
if (!states.IsCached || layer.MagFilter != states.MagFilter) {
|
||||
E_TEXTURE_MAG_FILTER magFilter = layer.MagFilter;
|
||||
GL.TexParameteri(tmpTextureType, GL_TEXTURE_MAG_FILTER,
|
||||
magFilter == ETMAGF_NEAREST ? GL_NEAREST : (assert(magFilter == ETMAGF_LINEAR), GL_LINEAR));
|
||||
|
||||
tmpTexture->getStatesCache().MagFilter = magFilter;
|
||||
states.MagFilter = magFilter;
|
||||
}
|
||||
|
||||
if (material.UseMipMaps && tmpTexture->hasMipMaps()) {
|
||||
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayers[i].MinFilter != tmpTexture->getStatesCache().MinFilter ||
|
||||
!tmpTexture->getStatesCache().MipMapStatus) {
|
||||
E_TEXTURE_MIN_FILTER minFilter = material.TextureLayers[i].MinFilter;
|
||||
if (!states.IsCached || layer.MinFilter != states.MinFilter ||
|
||||
!states.MipMapStatus) {
|
||||
E_TEXTURE_MIN_FILTER minFilter = layer.MinFilter;
|
||||
GL.TexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,
|
||||
minFilter == ETMINF_NEAREST_MIPMAP_NEAREST ? GL_NEAREST_MIPMAP_NEAREST : minFilter == ETMINF_LINEAR_MIPMAP_NEAREST ? GL_LINEAR_MIPMAP_NEAREST
|
||||
: minFilter == ETMINF_NEAREST_MIPMAP_LINEAR ? GL_NEAREST_MIPMAP_LINEAR
|
||||
: (assert(minFilter == ETMINF_LINEAR_MIPMAP_LINEAR), GL_LINEAR_MIPMAP_LINEAR));
|
||||
|
||||
tmpTexture->getStatesCache().MinFilter = minFilter;
|
||||
tmpTexture->getStatesCache().MipMapStatus = true;
|
||||
states.MinFilter = minFilter;
|
||||
states.MipMapStatus = true;
|
||||
}
|
||||
} else {
|
||||
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayers[i].MinFilter != tmpTexture->getStatesCache().MinFilter ||
|
||||
tmpTexture->getStatesCache().MipMapStatus) {
|
||||
E_TEXTURE_MIN_FILTER minFilter = material.TextureLayers[i].MinFilter;
|
||||
if (!states.IsCached || layer.MinFilter != states.MinFilter ||
|
||||
states.MipMapStatus) {
|
||||
E_TEXTURE_MIN_FILTER minFilter = layer.MinFilter;
|
||||
GL.TexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,
|
||||
(minFilter == ETMINF_NEAREST_MIPMAP_NEAREST || minFilter == ETMINF_NEAREST_MIPMAP_LINEAR) ? GL_NEAREST : (assert(minFilter == ETMINF_LINEAR_MIPMAP_NEAREST || minFilter == ETMINF_LINEAR_MIPMAP_LINEAR), GL_LINEAR));
|
||||
|
||||
tmpTexture->getStatesCache().MinFilter = minFilter;
|
||||
tmpTexture->getStatesCache().MipMapStatus = false;
|
||||
states.MinFilter = minFilter;
|
||||
states.MipMapStatus = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (LODBiasSupported &&
|
||||
(!states.IsCached || layer.LODBias != states.LODBias)) {
|
||||
if (layer.LODBias) {
|
||||
const float tmp = core::clamp(layer.LODBias * 0.125f, -MaxTextureLODBias, MaxTextureLODBias);
|
||||
GL.TexParameterf(tmpTextureType, GL.TEXTURE_LOD_BIAS, tmp);
|
||||
} else
|
||||
GL.TexParameterf(tmpTextureType, GL.TEXTURE_LOD_BIAS, 0.f);
|
||||
|
||||
states.LODBias = layer.LODBias;
|
||||
}
|
||||
|
||||
if (AnisotropicFilterSupported &&
|
||||
(!tmpTexture->getStatesCache().IsCached || material.TextureLayers[i].AnisotropicFilter != tmpTexture->getStatesCache().AnisotropicFilter)) {
|
||||
(!states.IsCached || layer.AnisotropicFilter != states.AnisotropicFilter)) {
|
||||
GL.TexParameteri(tmpTextureType, GL.TEXTURE_MAX_ANISOTROPY,
|
||||
material.TextureLayers[i].AnisotropicFilter > 1 ? core::min_(MaxAnisotropy, material.TextureLayers[i].AnisotropicFilter) : 1);
|
||||
layer.AnisotropicFilter > 1 ? core::min_(MaxAnisotropy, layer.AnisotropicFilter) : 1);
|
||||
|
||||
tmpTexture->getStatesCache().AnisotropicFilter = material.TextureLayers[i].AnisotropicFilter;
|
||||
states.AnisotropicFilter = layer.AnisotropicFilter;
|
||||
}
|
||||
|
||||
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayers[i].TextureWrapU != tmpTexture->getStatesCache().WrapU) {
|
||||
GL.TexParameteri(tmpTextureType, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayers[i].TextureWrapU));
|
||||
tmpTexture->getStatesCache().WrapU = material.TextureLayers[i].TextureWrapU;
|
||||
if (!states.IsCached || layer.TextureWrapU != states.WrapU) {
|
||||
GL.TexParameteri(tmpTextureType, GL_TEXTURE_WRAP_S, getTextureWrapMode(layer.TextureWrapU));
|
||||
states.WrapU = layer.TextureWrapU;
|
||||
}
|
||||
|
||||
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayers[i].TextureWrapV != tmpTexture->getStatesCache().WrapV) {
|
||||
GL.TexParameteri(tmpTextureType, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayers[i].TextureWrapV));
|
||||
tmpTexture->getStatesCache().WrapV = material.TextureLayers[i].TextureWrapV;
|
||||
if (!states.IsCached || layer.TextureWrapV != states.WrapV) {
|
||||
GL.TexParameteri(tmpTextureType, GL_TEXTURE_WRAP_T, getTextureWrapMode(layer.TextureWrapV));
|
||||
states.WrapV = layer.TextureWrapV;
|
||||
}
|
||||
|
||||
tmpTexture->getStatesCache().IsCached = true;
|
||||
states.IsCached = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1592,14 +1602,9 @@ bool COpenGL3DriverBase::setPixelShaderConstant(s32 index, const u32 *ints, int
|
||||
//! Adds a new material renderer to the VideoDriver, using GLSL to render geometry.
|
||||
s32 COpenGL3DriverBase::addHighLevelShaderMaterial(
|
||||
const c8 *vertexShaderProgram,
|
||||
const c8 *vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8 *pixelShaderProgram,
|
||||
const c8 *pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
const c8 *geometryShaderProgram,
|
||||
const c8 *geometryShaderEntryPointName,
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
|
||||
const c8 *shaderName,
|
||||
scene::E_PRIMITIVE_TYPE inType,
|
||||
scene::E_PRIMITIVE_TYPE outType,
|
||||
u32 verticesOut,
|
||||
|
@ -189,18 +189,13 @@ public:
|
||||
//! Adds a new material renderer to the VideoDriver
|
||||
virtual s32 addHighLevelShaderMaterial(
|
||||
const c8 *vertexShaderProgram,
|
||||
const c8 *vertexShaderEntryPointName = 0,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1,
|
||||
const c8 *pixelShaderProgram = 0,
|
||||
const c8 *pixelShaderEntryPointName = 0,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1,
|
||||
const c8 *geometryShaderProgram = 0,
|
||||
const c8 *geometryShaderEntryPointName = "main",
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
||||
const c8 *pixelShaderProgram,
|
||||
const c8 *geometryShaderProgram = nullptr,
|
||||
const c8 *shaderName = nullptr,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack *callback = 0,
|
||||
IShaderConstantSetCallBack *callback = nullptr,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0) override;
|
||||
|
||||
|
@ -161,6 +161,7 @@ public:
|
||||
GL.BlendEquation(mode);
|
||||
}
|
||||
|
||||
bool LODBiasSupported = false;
|
||||
bool AnisotropicFilterSupported = false;
|
||||
bool BlendMinMaxSupported = false;
|
||||
bool TextureMultisampleSupported = false;
|
||||
|
@ -69,6 +69,7 @@ void COpenGL3Driver::initFeatures()
|
||||
TextureFormats[ECF_D24S8] = {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8};
|
||||
|
||||
AnisotropicFilterSupported = isVersionAtLeast(4, 6) || queryExtension("GL_ARB_texture_filter_anisotropic") || queryExtension("GL_EXT_texture_filter_anisotropic");
|
||||
LODBiasSupported = true;
|
||||
BlendMinMaxSupported = true;
|
||||
TextureMultisampleSupported = true;
|
||||
|
||||
|
@ -120,10 +120,10 @@ void COpenGLES2Driver::initFeatures()
|
||||
}
|
||||
|
||||
const bool MRTSupported = Version.Major >= 3 || queryExtension("GL_EXT_draw_buffers");
|
||||
LODBiasSupported = queryExtension("GL_EXT_texture_lod_bias");
|
||||
AnisotropicFilterSupported = queryExtension("GL_EXT_texture_filter_anisotropic");
|
||||
BlendMinMaxSupported = (Version.Major >= 3) || FeatureAvailable[IRR_GL_EXT_blend_minmax];
|
||||
TextureMultisampleSupported = isVersionAtLeast(3, 1);
|
||||
const bool TextureLODBiasSupported = queryExtension("GL_EXT_texture_lod_bias");
|
||||
|
||||
// COGLESCoreExtensionHandler::Feature
|
||||
static_assert(MATERIAL_MAX_TEXTURES <= 8, "Only up to 8 textures are guaranteed");
|
||||
@ -141,7 +141,7 @@ void COpenGLES2Driver::initFeatures()
|
||||
if (Version.Major >= 3 || queryExtension("GL_EXT_draw_range_elements"))
|
||||
MaxIndices = GetInteger(GL_MAX_ELEMENTS_INDICES);
|
||||
MaxTextureSize = GetInteger(GL_MAX_TEXTURE_SIZE);
|
||||
if (TextureLODBiasSupported)
|
||||
if (LODBiasSupported)
|
||||
GL.GetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &MaxTextureLODBias);
|
||||
GL.GetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, DimAliasedLine); // NOTE: this is not in the OpenGL ES 2.0 spec...
|
||||
GL.GetFloatv(GL_ALIASED_POINT_SIZE_RANGE, DimAliasedPoint);
|
||||
|
@ -1706,8 +1706,8 @@ void Game::updateProfilers(const RunStats &stats, const FpsControl &draw_times,
|
||||
if (stats2.Drawcalls > 0)
|
||||
g_profiler->avg("Irr: primitives per drawcall",
|
||||
stats2.PrimitivesDrawn / float(stats2.Drawcalls));
|
||||
g_profiler->avg("Irr: buffers uploaded", stats2.HWBuffersUploaded);
|
||||
g_profiler->avg("Irr: buffers uploaded (bytes)", stats2.HWBuffersUploadedSize);
|
||||
g_profiler->avg("Irr: HW buffers uploaded", stats2.HWBuffersUploaded);
|
||||
g_profiler->avg("Irr: HW buffers active", stats2.HWBuffersActive);
|
||||
}
|
||||
|
||||
void Game::updateStats(RunStats *stats, const FpsControl &draw_times,
|
||||
|
@ -874,7 +874,6 @@ void Hud::drawSelectionMesh()
|
||||
{
|
||||
if (m_mode == HIGHLIGHT_NONE || (m_mode == HIGHLIGHT_HALO && !m_selection_mesh))
|
||||
return;
|
||||
const video::SMaterial oldmaterial = driver->getMaterial2D();
|
||||
driver->setMaterial(m_selection_material);
|
||||
const core::matrix4 oldtransform = driver->getTransform(video::ETS_WORLD);
|
||||
|
||||
@ -910,7 +909,6 @@ void Hud::drawSelectionMesh()
|
||||
driver->drawMeshBuffer(buf);
|
||||
}
|
||||
}
|
||||
driver->setMaterial(oldmaterial);
|
||||
driver->setTransform(video::ETS_WORLD, oldtransform);
|
||||
}
|
||||
|
||||
@ -935,17 +933,11 @@ void Hud::drawBlockBounds()
|
||||
return;
|
||||
}
|
||||
|
||||
video::SMaterial old_material = driver->getMaterial2D();
|
||||
driver->setMaterial(m_block_bounds_material);
|
||||
|
||||
u16 mesh_chunk_size = std::max<u16>(1, g_settings->getU16("client_mesh_chunk"));
|
||||
|
||||
v3s16 pos = player->getStandingNodePos();
|
||||
v3s16 block_pos(
|
||||
floorf((float) pos.X / MAP_BLOCKSIZE),
|
||||
floorf((float) pos.Y / MAP_BLOCKSIZE),
|
||||
floorf((float) pos.Z / MAP_BLOCKSIZE)
|
||||
);
|
||||
v3s16 block_pos = getContainerPos(player->getStandingNodePos(), MAP_BLOCKSIZE);
|
||||
|
||||
v3f cam_offset = intToFloat(client->getCamera()->getOffset(), BS);
|
||||
|
||||
@ -988,8 +980,6 @@ void Hud::drawBlockBounds()
|
||||
choose_color(block_pos.Y, block_pos.Z)
|
||||
);
|
||||
}
|
||||
|
||||
driver->setMaterial(old_material);
|
||||
}
|
||||
|
||||
void Hud::updateSelectionMesh(const v3s16 &camera_offset)
|
||||
|
@ -148,17 +148,6 @@ static void imageCleanTransparentWithInlining(video::IImage *src, u32 threshold)
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in RGB values for transparent pixels, to correct for odd colors
|
||||
* appearing at borders when blending. This is because many PNG optimizers
|
||||
* like to discard RGB values of transparent pixels, but when blending then
|
||||
* with non-transparent neighbors, their RGB values will show up nonetheless.
|
||||
*
|
||||
* This function modifies the original image in-place.
|
||||
*
|
||||
* Parameter "threshold" is the alpha level below which pixels are considered
|
||||
* transparent. Should be 127 when the texture is used with ALPHA_CHANNEL_REF,
|
||||
* 0 when alpha blending is used.
|
||||
*/
|
||||
void imageCleanTransparent(video::IImage *src, u32 threshold)
|
||||
{
|
||||
if (src->getColorFormat() == video::ECF_A8R8G8B8)
|
||||
@ -167,13 +156,109 @@ void imageCleanTransparent(video::IImage *src, u32 threshold)
|
||||
imageCleanTransparentWithInlining<false>(src, threshold);
|
||||
}
|
||||
|
||||
/* Scale a region of an image into another image, using nearest-neighbor with
|
||||
* anti-aliasing; treat pixels as crisp rectangles, but blend them at boundaries
|
||||
* to prevent non-integer scaling ratio artifacts. Note that this may cause
|
||||
* some blending at the edges where pixels don't line up perfectly, but this
|
||||
* filter is designed to produce the most accurate results for both upscaling
|
||||
* and downscaling.
|
||||
*/
|
||||
/**********************************/
|
||||
|
||||
namespace {
|
||||
// For more colorspace transformations, see for example
|
||||
// <https://github.com/tobspr/GLSL-Color-Spaces/blob/master/ColorSpaces.inc.glsl>
|
||||
|
||||
inline float linear_to_srgb_component(float v)
|
||||
{
|
||||
if (v > 0.0031308f)
|
||||
return 1.055f * powf(v, 1.0f / 2.4f) - 0.055f;
|
||||
return 12.92f * v;
|
||||
}
|
||||
inline float srgb_to_linear_component(float v)
|
||||
{
|
||||
if (v > 0.04045f)
|
||||
return powf((v + 0.055f) / 1.055f, 2.4f);
|
||||
return v / 12.92f;
|
||||
}
|
||||
|
||||
template <float (*F)(float)>
|
||||
struct LUT8 {
|
||||
std::array<float, 256> t;
|
||||
LUT8() {
|
||||
for (size_t i = 0; i < t.size(); i++)
|
||||
t[i] = F(i / 255.0f);
|
||||
}
|
||||
};
|
||||
LUT8<srgb_to_linear_component> srgb_to_linear_lut;
|
||||
|
||||
v3f srgb_to_linear(const video::SColor col_srgb)
|
||||
{
|
||||
v3f col(srgb_to_linear_lut.t[col_srgb.getRed()],
|
||||
srgb_to_linear_lut.t[col_srgb.getGreen()],
|
||||
srgb_to_linear_lut.t[col_srgb.getBlue()]);
|
||||
return col;
|
||||
}
|
||||
|
||||
video::SColor linear_to_srgb(const v3f col_linear)
|
||||
{
|
||||
v3f col;
|
||||
// we can't LUT this without losing precision, but thankfully we call
|
||||
// it just once :)
|
||||
col.X = linear_to_srgb_component(col_linear.X);
|
||||
col.Y = linear_to_srgb_component(col_linear.Y);
|
||||
col.Z = linear_to_srgb_component(col_linear.Z);
|
||||
col *= 255.0f;
|
||||
col.X = core::clamp<float>(col.X, 0.0f, 255.0f);
|
||||
col.Y = core::clamp<float>(col.Y, 0.0f, 255.0f);
|
||||
col.Z = core::clamp<float>(col.Z, 0.0f, 255.0f);
|
||||
return video::SColor(0xff, myround(col.X), myround(col.Y),
|
||||
myround(col.Z));
|
||||
}
|
||||
}
|
||||
|
||||
template <bool IS_A8R8G8B8>
|
||||
static video::SColor imageAverageColorInline(const video::IImage *src)
|
||||
{
|
||||
void *const src_data = src->getData();
|
||||
const core::dimension2du dim = src->getDimension();
|
||||
|
||||
auto get_pixel = [=](u32 x, u32 y) -> video::SColor {
|
||||
if constexpr (IS_A8R8G8B8) {
|
||||
return reinterpret_cast<u32 *>(src_data)[y*dim.Width + x];
|
||||
} else {
|
||||
return src->getPixel(x, y);
|
||||
}
|
||||
};
|
||||
|
||||
u32 total = 0;
|
||||
v3f col_acc;
|
||||
// limit runtime cost
|
||||
const u32 stepx = std::max(1U, dim.Width / 16),
|
||||
stepy = std::max(1U, dim.Height / 16);
|
||||
for (u32 x = 0; x < dim.Width; x += stepx) {
|
||||
for (u32 y = 0; y < dim.Height; y += stepy) {
|
||||
video::SColor c = get_pixel(x, y);
|
||||
if (c.getAlpha() > 0) {
|
||||
total++;
|
||||
col_acc += srgb_to_linear(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
video::SColor ret(0, 0, 0, 0);
|
||||
if (total > 0) {
|
||||
col_acc /= total;
|
||||
ret = linear_to_srgb(col_acc);
|
||||
}
|
||||
ret.setAlpha(255);
|
||||
return ret;
|
||||
}
|
||||
|
||||
video::SColor imageAverageColor(const video::IImage *img)
|
||||
{
|
||||
if (img->getColorFormat() == video::ECF_A8R8G8B8)
|
||||
return imageAverageColorInline<true>(img);
|
||||
else
|
||||
return imageAverageColorInline<false>(img);
|
||||
}
|
||||
|
||||
|
||||
/**********************************/
|
||||
|
||||
void imageScaleNNAA(video::IImage *src, const core::rect<s32> &srcrect, video::IImage *dest)
|
||||
{
|
||||
double sx, sy, minsx, maxsx, minsy, maxsy, area, ra, ga, ba, aa, pw, ph, pa;
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
#include <rect.h>
|
||||
#include <SColor.h>
|
||||
|
||||
namespace irr::video
|
||||
{
|
||||
@ -26,6 +27,10 @@ namespace irr::video
|
||||
*/
|
||||
void imageCleanTransparent(video::IImage *src, u32 threshold);
|
||||
|
||||
/* Returns the gamma-correct average color of the image, with transparent pixels
|
||||
* ignored. */
|
||||
video::SColor imageAverageColor(const video::IImage *img);
|
||||
|
||||
/* Scale a region of an image into another image, using nearest-neighbor with
|
||||
* anti-aliasing; treat pixels as crisp rectangles, but blend them at boundaries
|
||||
* to prevent non-integer scaling ratio artifacts. Note that this may cause
|
||||
|
@ -31,8 +31,7 @@ void SourceImageCache::insert(const std::string &name, video::IImage *img, bool
|
||||
{
|
||||
assert(img); // Pre-condition
|
||||
// Remove old image
|
||||
std::map<std::string, video::IImage*>::iterator n;
|
||||
n = m_images.find(name);
|
||||
auto n = m_images.find(name);
|
||||
if (n != m_images.end()){
|
||||
if (n->second)
|
||||
n->second->drop();
|
||||
@ -63,8 +62,7 @@ void SourceImageCache::insert(const std::string &name, video::IImage *img, bool
|
||||
|
||||
video::IImage* SourceImageCache::get(const std::string &name)
|
||||
{
|
||||
std::map<std::string, video::IImage*>::iterator n;
|
||||
n = m_images.find(name);
|
||||
auto n = m_images.find(name);
|
||||
if (n != m_images.end())
|
||||
return n->second;
|
||||
return nullptr;
|
||||
@ -73,8 +71,7 @@ video::IImage* SourceImageCache::get(const std::string &name)
|
||||
// Primarily fetches from cache, secondarily tries to read from filesystem
|
||||
video::IImage* SourceImageCache::getOrLoad(const std::string &name)
|
||||
{
|
||||
std::map<std::string, video::IImage*>::iterator n;
|
||||
n = m_images.find(name);
|
||||
auto n = m_images.find(name);
|
||||
if (n != m_images.end()){
|
||||
n->second->grab(); // Grab for caller
|
||||
return n->second;
|
||||
@ -166,13 +163,13 @@ static void draw_crack(video::IImage *crack, video::IImage *dst,
|
||||
video::IVideoDriver *driver, u8 tiles = 1);
|
||||
|
||||
// Brighten image
|
||||
void brighten(video::IImage *image);
|
||||
static void brighten(video::IImage *image);
|
||||
// Parse a transform name
|
||||
u32 parseImageTransform(std::string_view s);
|
||||
static u32 parseImageTransform(std::string_view s);
|
||||
// Apply transform to image dimension
|
||||
core::dimension2d<u32> imageTransformDimension(u32 transform, core::dimension2d<u32> dim);
|
||||
static core::dimension2du imageTransformDimension(u32 transform, core::dimension2du dim);
|
||||
// Apply transform to image data
|
||||
void imageTransform(u32 transform, video::IImage *src, video::IImage *dst);
|
||||
static void imageTransform(u32 transform, video::IImage *src, video::IImage *dst);
|
||||
|
||||
inline static void applyShadeFactor(video::SColor &color, u32 factor)
|
||||
{
|
||||
@ -289,7 +286,7 @@ static video::IImage *createInventoryCubeImage(
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string unescape_string(const std::string &str, const char esc = '\\')
|
||||
static std::string unescape_string(std::string_view str, const char esc = '\\')
|
||||
{
|
||||
std::string out;
|
||||
size_t pos = 0, cpos;
|
||||
@ -300,7 +297,8 @@ static std::string unescape_string(const std::string &str, const char esc = '\\'
|
||||
out += str.substr(pos);
|
||||
break;
|
||||
}
|
||||
out += str.substr(pos, cpos - pos) + str[cpos + 1];
|
||||
out += str.substr(pos, cpos - pos);
|
||||
out += str[cpos + 1];
|
||||
pos = cpos + 2;
|
||||
}
|
||||
return out;
|
||||
@ -312,7 +310,7 @@ static std::string unescape_string(const std::string &str, const char esc = '\\'
|
||||
Ensure no other references to these images are being held, as one may
|
||||
get dropped and switched with a new image.
|
||||
*/
|
||||
void upscaleImagesToMatchLargest(video::IImage *& img1,
|
||||
static void upscaleImagesToMatchLargest(video::IImage *& img1,
|
||||
video::IImage *& img2)
|
||||
{
|
||||
core::dimension2d<u32> dim1 = img1->getDimension();
|
||||
@ -340,7 +338,7 @@ void upscaleImagesToMatchLargest(video::IImage *& img1,
|
||||
}
|
||||
}
|
||||
|
||||
void blitBaseImage(video::IImage* &src, video::IImage* &dst)
|
||||
static void blitBaseImage(video::IImage* &src, video::IImage* &dst)
|
||||
{
|
||||
//infostream<<"Blitting "<<part_of_name<<" on base"<<std::endl;
|
||||
upscaleImagesToMatchLargest(dst, src);
|
||||
@ -411,9 +409,10 @@ void blit_pixel(video::SColor src_col, video::SColor &dst_col)
|
||||
dst_col.set(dst_a, dst.r, dst.g, dst.b);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace (anonymous)
|
||||
|
||||
template<bool overlay>
|
||||
void blit_with_alpha(video::IImage *src, video::IImage *dst, v2s32 dst_pos,
|
||||
static void blit_with_alpha(video::IImage *src, video::IImage *dst, v2s32 dst_pos,
|
||||
v2u32 size)
|
||||
{
|
||||
if (dst->getColorFormat() != video::ECF_A8R8G8B8)
|
||||
@ -427,13 +426,12 @@ void blit_with_alpha(video::IImage *src, video::IImage *dst, v2s32 dst_pos,
|
||||
video::IVideoDriver *driver = RenderingEngine::get_video_driver();
|
||||
video::IImage *src_converted = driver->createImage(video::ECF_A8R8G8B8,
|
||||
src_dim);
|
||||
if (!src_converted)
|
||||
throw BaseException("blit_with_alpha() failed to convert the "
|
||||
"source image to ECF_A8R8G8B8.");
|
||||
sanity_check(src_converted != nullptr);
|
||||
src->copyTo(src_converted);
|
||||
src = src_converted;
|
||||
drop_src = true;
|
||||
}
|
||||
|
||||
video::SColor *pixels_src =
|
||||
reinterpret_cast<video::SColor *>(src->getData());
|
||||
video::SColor *pixels_dst =
|
||||
@ -453,6 +451,7 @@ void blit_with_alpha(video::IImage *src, video::IImage *dst, v2s32 dst_pos,
|
||||
blit_pixel<overlay>(pixels_src[i_src++], pixels_dst[i_dst++]);
|
||||
}
|
||||
}
|
||||
|
||||
if (drop_src)
|
||||
src->drop();
|
||||
}
|
||||
@ -726,7 +725,7 @@ static void apply_mask(video::IImage *mask, video::IImage *dst,
|
||||
}
|
||||
}
|
||||
|
||||
video::IImage *create_crack_image(video::IImage *crack, s32 frame_index,
|
||||
static video::IImage *create_crack_image(video::IImage *crack, s32 frame_index,
|
||||
core::dimension2d<u32> size, u8 tiles, video::IVideoDriver *driver)
|
||||
{
|
||||
core::dimension2d<u32> strip_size = crack->getDimension();
|
||||
@ -804,7 +803,7 @@ static void draw_crack(video::IImage *crack, video::IImage *dst,
|
||||
crack_scaled->drop();
|
||||
}
|
||||
|
||||
void brighten(video::IImage *image)
|
||||
static void brighten(video::IImage *image)
|
||||
{
|
||||
if (image == NULL)
|
||||
return;
|
||||
@ -822,7 +821,7 @@ void brighten(video::IImage *image)
|
||||
}
|
||||
}
|
||||
|
||||
u32 parseImageTransform(std::string_view s)
|
||||
static u32 parseImageTransform(std::string_view s)
|
||||
{
|
||||
int total_transform = 0;
|
||||
|
||||
@ -872,15 +871,15 @@ u32 parseImageTransform(std::string_view s)
|
||||
return total_transform;
|
||||
}
|
||||
|
||||
core::dimension2d<u32> imageTransformDimension(u32 transform, core::dimension2d<u32> dim)
|
||||
static core::dimension2du imageTransformDimension(u32 transform, core::dimension2du dim)
|
||||
{
|
||||
if (transform % 2 == 0)
|
||||
return dim;
|
||||
|
||||
return core::dimension2d<u32>(dim.Height, dim.Width);
|
||||
return core::dimension2du(dim.Height, dim.Width);
|
||||
}
|
||||
|
||||
void imageTransform(u32 transform, video::IImage *src, video::IImage *dst)
|
||||
static void imageTransform(u32 transform, video::IImage *src, video::IImage *dst)
|
||||
{
|
||||
if (src == NULL || dst == NULL)
|
||||
return;
|
||||
@ -925,48 +924,6 @@ void imageTransform(u32 transform, video::IImage *src, video::IImage *dst)
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
// For more colorspace transformations, see for example
|
||||
// https://github.com/tobspr/GLSL-Color-Spaces/blob/master/ColorSpaces.inc.glsl
|
||||
|
||||
inline float linear_to_srgb_component(float v)
|
||||
{
|
||||
if (v > 0.0031308f)
|
||||
return 1.055f * powf(v, 1.0f / 2.4f) - 0.055f;
|
||||
return 12.92f * v;
|
||||
}
|
||||
inline float srgb_to_linear_component(float v)
|
||||
{
|
||||
if (v > 0.04045f)
|
||||
return powf((v + 0.055f) / 1.055f, 2.4f);
|
||||
return v / 12.92f;
|
||||
}
|
||||
|
||||
v3f srgb_to_linear(const video::SColor col_srgb)
|
||||
{
|
||||
v3f col(col_srgb.getRed(), col_srgb.getGreen(), col_srgb.getBlue());
|
||||
col /= 255.0f;
|
||||
col.X = srgb_to_linear_component(col.X);
|
||||
col.Y = srgb_to_linear_component(col.Y);
|
||||
col.Z = srgb_to_linear_component(col.Z);
|
||||
return col;
|
||||
}
|
||||
|
||||
video::SColor linear_to_srgb(const v3f col_linear)
|
||||
{
|
||||
v3f col;
|
||||
col.X = linear_to_srgb_component(col_linear.X);
|
||||
col.Y = linear_to_srgb_component(col_linear.Y);
|
||||
col.Z = linear_to_srgb_component(col_linear.Z);
|
||||
col *= 255.0f;
|
||||
col.X = core::clamp<float>(col.X, 0.0f, 255.0f);
|
||||
col.Y = core::clamp<float>(col.Y, 0.0f, 255.0f);
|
||||
col.Z = core::clamp<float>(col.Z, 0.0f, 255.0f);
|
||||
return video::SColor(0xff, myround(col.X), myround(col.Y),
|
||||
myround(col.Z));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// ImageSource Functions //
|
||||
@ -1017,18 +974,12 @@ bool ImageSource::generateImagePart(std::string_view part_of_name,
|
||||
std::string part_s(part_of_name);
|
||||
source_image_names.insert(part_s);
|
||||
video::IImage *image = m_sourcecache.getOrLoad(part_s);
|
||||
|
||||
if (!image) {
|
||||
// Do not create the dummy texture
|
||||
if (part_of_name.empty())
|
||||
return true;
|
||||
|
||||
// Do not create normalmap dummies
|
||||
if (str_ends_with(part_of_name, "_normal.png")) {
|
||||
warningstream << "generateImagePart(): Could not load normal map \""
|
||||
<< part_of_name << "\"" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
errorstream << "generateImagePart(): Could not load image \""
|
||||
<< part_of_name << "\" while building texture; "
|
||||
"Creating a dummy image" << std::endl;
|
||||
@ -1040,16 +991,15 @@ bool ImageSource::generateImagePart(std::string_view part_of_name,
|
||||
myrand()%256,myrand()%256));
|
||||
}
|
||||
|
||||
// If base image is NULL, load as base.
|
||||
if (baseimg == NULL)
|
||||
// load as base or blit
|
||||
if (!baseimg)
|
||||
{
|
||||
/*
|
||||
Copy it this way to get an alpha channel.
|
||||
Otherwise images with alpha cannot be blitted on
|
||||
images that don't have alpha in the original file.
|
||||
*/
|
||||
core::dimension2d<u32> dim = image->getDimension();
|
||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, image->getDimension());
|
||||
image->copyTo(baseimg);
|
||||
}
|
||||
// Else blit on base.
|
||||
@ -1705,14 +1655,17 @@ bool ImageSource::generateImagePart(std::string_view part_of_name,
|
||||
return false;
|
||||
}
|
||||
|
||||
// blit or use as base
|
||||
if (baseimg) {
|
||||
blitBaseImage(pngimg, baseimg);
|
||||
} else {
|
||||
core::dimension2d<u32> dim = pngimg->getDimension();
|
||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||
pngimg->drop();
|
||||
} else if (pngimg->getColorFormat() != video::ECF_A8R8G8B8) {
|
||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, pngimg->getDimension());
|
||||
pngimg->copyTo(baseimg);
|
||||
pngimg->drop();
|
||||
} else {
|
||||
baseimg = pngimg;
|
||||
}
|
||||
pngimg->drop();
|
||||
}
|
||||
/*
|
||||
[hsl:hue:saturation:lightness
|
||||
@ -1945,32 +1898,7 @@ video::IImage* ImageSource::generateImage(std::string_view name,
|
||||
return baseimg;
|
||||
}
|
||||
|
||||
video::SColor ImageSource::getImageAverageColor(const video::IImage &image)
|
||||
void ImageSource::insertSourceImage(const std::string &name, video::IImage *img, bool prefer_local)
|
||||
{
|
||||
video::SColor c(0, 0, 0, 0);
|
||||
u32 total = 0;
|
||||
v3f col_acc(0, 0, 0);
|
||||
core::dimension2d<u32> dim = image.getDimension();
|
||||
u16 step = 1;
|
||||
if (dim.Width > 16)
|
||||
step = dim.Width / 16;
|
||||
for (u16 x = 0; x < dim.Width; x += step) {
|
||||
for (u16 y = 0; y < dim.Width; y += step) {
|
||||
c = image.getPixel(x,y);
|
||||
if (c.getAlpha() > 0) {
|
||||
total++;
|
||||
col_acc += srgb_to_linear(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (total > 0) {
|
||||
col_acc /= total;
|
||||
c = linear_to_srgb(col_acc);
|
||||
}
|
||||
c.setAlpha(255);
|
||||
return c;
|
||||
}
|
||||
|
||||
void ImageSource::insertSourceImage(const std::string &name, video::IImage *img, bool prefer_local) {
|
||||
m_sourcecache.insert(name, img, prefer_local);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <IImage.h>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
@ -28,7 +28,7 @@ public:
|
||||
// Primarily fetches from cache, secondarily tries to read from filesystem.
|
||||
video::IImage *getOrLoad(const std::string &name);
|
||||
private:
|
||||
std::map<std::string, video::IImage*> m_images;
|
||||
std::unordered_map<std::string, video::IImage*> m_images;
|
||||
};
|
||||
|
||||
// Generates images using texture modifiers, and caches source images.
|
||||
@ -45,9 +45,6 @@ struct ImageSource {
|
||||
// Insert a source image into the cache without touching the filesystem.
|
||||
void insertSourceImage(const std::string &name, video::IImage *img, bool prefer_local);
|
||||
|
||||
// TODO should probably be moved elsewhere
|
||||
static video::SColor getImageAverageColor(const video::IImage &image);
|
||||
|
||||
private:
|
||||
|
||||
// Generate image based on a string like "stone.png" or "[crack:1:0".
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <IMaterialRendererServices.h>
|
||||
#include <IShaderConstantSetCallBack.h>
|
||||
#include "client/renderingengine.h"
|
||||
#include <EShaderTypes.h>
|
||||
#include "gettext.h"
|
||||
#include "log.h"
|
||||
#include "gamedef.h"
|
||||
@ -615,10 +614,16 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
|
||||
#define textureFlags texture2
|
||||
)";
|
||||
|
||||
/// Unique name of this shader, for debug/logging
|
||||
std::string log_name = name;
|
||||
|
||||
/* Define constants for node and object shaders */
|
||||
const bool node_shader = drawtype != NodeDrawType_END;
|
||||
if (node_shader) {
|
||||
|
||||
log_name.append(" mat=").append(itos(material_type))
|
||||
.append(" draw=").append(itos(drawtype));
|
||||
|
||||
bool use_discard = fully_programmable;
|
||||
if (!use_discard) {
|
||||
// workaround for a certain OpenGL implementation lacking GL_ALPHA_TEST
|
||||
@ -762,18 +767,15 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
|
||||
geometry_shader_ptr = geometry_shader.c_str();
|
||||
}
|
||||
|
||||
irr_ptr<ShaderCallback> cb{new ShaderCallback(m_setter_factories)};
|
||||
infostream<<"Compiling high level shaders for "<<name<<std::endl;
|
||||
auto cb = make_irr<ShaderCallback>(m_setter_factories);
|
||||
infostream << "Compiling high level shaders for " << log_name << std::endl;
|
||||
s32 shadermat = gpu->addHighLevelShaderMaterial(
|
||||
vertex_shader.c_str(), nullptr, video::EVST_VS_1_1,
|
||||
fragment_shader.c_str(), nullptr, video::EPST_PS_1_1,
|
||||
geometry_shader_ptr, nullptr, video::EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLES, 0,
|
||||
cb.get(), shaderinfo.base_material, 1);
|
||||
vertex_shader.c_str(), fragment_shader.c_str(), geometry_shader_ptr,
|
||||
log_name.c_str(), scene::EPT_TRIANGLES, scene::EPT_TRIANGLES, 0,
|
||||
cb.get(), shaderinfo.base_material);
|
||||
if (shadermat == -1) {
|
||||
errorstream<<"generate_shader(): "
|
||||
"failed to generate \""<<name<<"\", "
|
||||
"addHighLevelShaderMaterial failed."
|
||||
<<std::endl;
|
||||
errorstream << "generateShader(): failed to generate shaders for "
|
||||
<< log_name << ", addHighLevelShaderMaterial failed." << std::endl;
|
||||
dumpShaderProgram(warningstream, "Vertex", vertex_shader);
|
||||
dumpShaderProgram(warningstream, "Fragment", fragment_shader);
|
||||
dumpShaderProgram(warningstream, "Geometry", geometry_shader);
|
||||
|
@ -14,10 +14,9 @@
|
||||
#include "client/client.h"
|
||||
#include "client/clientmap.h"
|
||||
#include "profiler.h"
|
||||
#include "EShaderTypes.h"
|
||||
#include "IGPUProgrammingServices.h"
|
||||
#include "IMaterialRenderer.h"
|
||||
#include <IVideoDriver.h>
|
||||
#include "IVideoDriver.h"
|
||||
|
||||
ShadowRenderer::ShadowRenderer(IrrlichtDevice *device, Client *client) :
|
||||
m_smgr(device->getSceneManager()), m_driver(device->getVideoDriver()),
|
||||
@ -539,10 +538,9 @@ void ShadowRenderer::createShaders()
|
||||
m_shadow_depth_cb = new ShadowDepthShaderCB();
|
||||
|
||||
depth_shader = gpu->addHighLevelShaderMaterial(
|
||||
readShaderFile(depth_shader_vs).c_str(), "vertexMain",
|
||||
video::EVST_VS_1_1,
|
||||
readShaderFile(depth_shader_fs).c_str(), "pixelMain",
|
||||
video::EPST_PS_1_2, m_shadow_depth_cb, video::EMT_ONETEXTURE_BLEND);
|
||||
readShaderFile(depth_shader_vs).c_str(),
|
||||
readShaderFile(depth_shader_fs).c_str(), nullptr,
|
||||
m_shadow_depth_cb, video::EMT_ONETEXTURE_BLEND);
|
||||
|
||||
if (depth_shader == -1) {
|
||||
// upsi, something went wrong loading shader.
|
||||
@ -578,10 +576,9 @@ void ShadowRenderer::createShaders()
|
||||
m_shadow_depth_entity_cb = new ShadowDepthShaderCB();
|
||||
|
||||
depth_shader_entities = gpu->addHighLevelShaderMaterial(
|
||||
readShaderFile(depth_shader_vs).c_str(), "vertexMain",
|
||||
video::EVST_VS_1_1,
|
||||
readShaderFile(depth_shader_fs).c_str(), "pixelMain",
|
||||
video::EPST_PS_1_2, m_shadow_depth_entity_cb);
|
||||
readShaderFile(depth_shader_vs).c_str(),
|
||||
readShaderFile(depth_shader_fs).c_str(), nullptr,
|
||||
m_shadow_depth_entity_cb);
|
||||
|
||||
if (depth_shader_entities == -1) {
|
||||
// upsi, something went wrong loading shader.
|
||||
@ -616,10 +613,9 @@ void ShadowRenderer::createShaders()
|
||||
m_shadow_mix_cb = new shadowScreenQuadCB();
|
||||
m_screen_quad = new shadowScreenQuad();
|
||||
mixcsm_shader = gpu->addHighLevelShaderMaterial(
|
||||
readShaderFile(depth_shader_vs).c_str(), "vertexMain",
|
||||
video::EVST_VS_1_1,
|
||||
readShaderFile(depth_shader_fs).c_str(), "pixelMain",
|
||||
video::EPST_PS_1_2, m_shadow_mix_cb);
|
||||
readShaderFile(depth_shader_vs).c_str(),
|
||||
readShaderFile(depth_shader_fs).c_str(), nullptr,
|
||||
m_shadow_mix_cb);
|
||||
|
||||
m_screen_quad->getMaterial().MaterialType =
|
||||
(video::E_MATERIAL_TYPE)mixcsm_shader;
|
||||
@ -655,10 +651,9 @@ void ShadowRenderer::createShaders()
|
||||
m_shadow_depth_trans_cb = new ShadowDepthShaderCB();
|
||||
|
||||
depth_shader_trans = gpu->addHighLevelShaderMaterial(
|
||||
readShaderFile(depth_shader_vs).c_str(), "vertexMain",
|
||||
video::EVST_VS_1_1,
|
||||
readShaderFile(depth_shader_fs).c_str(), "pixelMain",
|
||||
video::EPST_PS_1_2, m_shadow_depth_trans_cb);
|
||||
readShaderFile(depth_shader_vs).c_str(),
|
||||
readShaderFile(depth_shader_fs).c_str(), nullptr,
|
||||
m_shadow_depth_trans_cb);
|
||||
|
||||
if (depth_shader_trans == -1) {
|
||||
// upsi, something went wrong loading shader.
|
||||
|
@ -121,7 +121,6 @@ public:
|
||||
// Shall be called from the main thread.
|
||||
void rebuildImagesAndTextures();
|
||||
|
||||
video::ITexture* getNormalTexture(const std::string &name);
|
||||
video::SColor getTextureAverageColor(const std::string &name);
|
||||
|
||||
private:
|
||||
@ -488,40 +487,20 @@ void TextureSource::rebuildTexture(video::IVideoDriver *driver, TextureInfo &ti)
|
||||
m_texture_trash.push_back(t_old);
|
||||
}
|
||||
|
||||
video::ITexture* TextureSource::getNormalTexture(const std::string &name)
|
||||
{
|
||||
if (isKnownSourceImage("override_normal.png"))
|
||||
return getTexture("override_normal.png");
|
||||
std::string fname_base = name;
|
||||
static const char *normal_ext = "_normal.png";
|
||||
static const u32 normal_ext_size = strlen(normal_ext);
|
||||
size_t pos = fname_base.find('.');
|
||||
std::string fname_normal = fname_base.substr(0, pos) + normal_ext;
|
||||
if (isKnownSourceImage(fname_normal)) {
|
||||
// look for image extension and replace it
|
||||
size_t i = 0;
|
||||
while ((i = fname_base.find('.', i)) != std::string::npos) {
|
||||
fname_base.replace(i, 4, normal_ext);
|
||||
i += normal_ext_size;
|
||||
}
|
||||
return getTexture(fname_base);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
video::SColor TextureSource::getTextureAverageColor(const std::string &name)
|
||||
{
|
||||
video::IVideoDriver *driver = RenderingEngine::get_video_driver();
|
||||
video::ITexture *texture = getTexture(name);
|
||||
if (!texture)
|
||||
return {0, 0, 0, 0};
|
||||
// Note: this downloads the texture back from the GPU, which is pointless
|
||||
video::IImage *image = driver->createImage(texture,
|
||||
core::position2d<s32>(0, 0),
|
||||
texture->getOriginalSize());
|
||||
if (!image)
|
||||
return {0, 0, 0, 0};
|
||||
|
||||
video::SColor c = ImageSource::getImageAverageColor(*image);
|
||||
video::SColor c = imageAverageColor(image);
|
||||
image->drop();
|
||||
|
||||
return c;
|
||||
|
@ -54,7 +54,6 @@ public:
|
||||
*/
|
||||
virtual Palette* getPalette(const std::string &name) = 0;
|
||||
virtual bool isKnownSourceImage(const std::string &name)=0;
|
||||
virtual video::ITexture* getNormalTexture(const std::string &name)=0;
|
||||
virtual video::SColor getTextureAverageColor(const std::string &name)=0;
|
||||
};
|
||||
|
||||
@ -75,7 +74,6 @@ public:
|
||||
virtual void processQueue()=0;
|
||||
virtual void insertSourceImage(const std::string &name, video::IImage *img)=0;
|
||||
virtual void rebuildImagesAndTextures()=0;
|
||||
virtual video::ITexture* getNormalTexture(const std::string &name)=0;
|
||||
virtual video::SColor getTextureAverageColor(const std::string &name)=0;
|
||||
};
|
||||
|
||||
|
@ -312,7 +312,7 @@ void set_default_settings()
|
||||
|
||||
// Effects
|
||||
settings->setDefault("enable_post_processing", "true");
|
||||
settings->setDefault("post_processing_texture_bits", "16");
|
||||
settings->setDefault("post_processing_texture_bits", "10");
|
||||
settings->setDefault("directional_colored_fog", "true");
|
||||
settings->setDefault("inventory_items_animations", "false");
|
||||
settings->setDefault("mip_map", "false");
|
||||
|
@ -85,8 +85,8 @@ void GUIInventoryList::draw()
|
||||
v2s32 p((i % m_geom.X) * m_slot_spacing.X,
|
||||
(i / m_geom.X) * m_slot_spacing.Y);
|
||||
core::rect<s32> rect = imgrect + base_pos + p;
|
||||
ItemStack item = ilist->getItem(item_i);
|
||||
ItemStack orig_item = item;
|
||||
const ItemStack &orig_item = ilist->getItem(item_i);
|
||||
ItemStack item = orig_item;
|
||||
|
||||
bool selected = selected_item
|
||||
&& m_invmgr->getInventory(selected_item->inventoryloc) == inv
|
||||
@ -137,12 +137,26 @@ void GUIInventoryList::draw()
|
||||
client, rotation_kind);
|
||||
}
|
||||
|
||||
// Add hovering tooltip
|
||||
// Add hovering tooltip. The tooltip disappears if any item is selected,
|
||||
// including the currently hovered one.
|
||||
bool show_tooltip = !item.empty() && hovering && !selected_item;
|
||||
// Make it possible to see item tooltips on touchscreens
|
||||
|
||||
if (RenderingEngine::getLastPointerType() == PointerType::Touch) {
|
||||
// Touchscreen users cannot hover over an item without selecting it.
|
||||
// To allow touchscreen users to see item tooltips, we also show the
|
||||
// tooltip if the item is selected and the finger is still on the
|
||||
// source slot.
|
||||
// The selected amount may be 0 in rare cases during "left-dragging"
|
||||
// (used to distribute items evenly).
|
||||
// In this case, the user doesn't see an item being dragged,
|
||||
// so we don't show the tooltip.
|
||||
// Note: `m_fs_menu->getSelectedAmount() != 0` below refers to the
|
||||
// part of the selected item the user is dragging.
|
||||
// `!item.empty()` would refer to the part of the selected item
|
||||
// remaining in the source slot.
|
||||
show_tooltip |= hovering && selected && m_fs_menu->getSelectedAmount() != 0;
|
||||
}
|
||||
|
||||
if (show_tooltip) {
|
||||
std::string tooltip = orig_item.getDescription(client->idef());
|
||||
if (m_fs_menu->doTooltipAppendItemname())
|
||||
|
@ -29,52 +29,47 @@
|
||||
|
||||
TouchControls *g_touchcontrols;
|
||||
|
||||
static void load_button_texture(IGUIImage *gui_button, const std::string &path,
|
||||
const recti &button_rect, ISimpleTextureSource *tsrc, video::IVideoDriver *driver)
|
||||
void TouchControls::emitKeyboardEvent(EKEY_CODE keycode, bool pressed)
|
||||
{
|
||||
video::ITexture *texture = guiScalingImageButton(driver,
|
||||
tsrc->getTexture(path), button_rect.getWidth(),
|
||||
button_rect.getHeight());
|
||||
SEvent e{};
|
||||
e.EventType = EET_KEY_INPUT_EVENT;
|
||||
e.KeyInput.Key = keycode;
|
||||
e.KeyInput.Control = false;
|
||||
e.KeyInput.Shift = false;
|
||||
e.KeyInput.Char = 0;
|
||||
e.KeyInput.PressedDown = pressed;
|
||||
m_receiver->OnEvent(e);
|
||||
}
|
||||
|
||||
void TouchControls::loadButtonTexture(IGUIImage *gui_button, const std::string &path)
|
||||
{
|
||||
auto rect = gui_button->getRelativePosition();
|
||||
video::ITexture *texture = guiScalingImageButton(m_device->getVideoDriver(),
|
||||
m_texturesource->getTexture(path), rect.getWidth(), rect.getHeight());
|
||||
gui_button->setImage(texture);
|
||||
gui_button->setScaleImage(true);
|
||||
}
|
||||
|
||||
void button_info::emitAction(bool action, video::IVideoDriver *driver,
|
||||
IEventReceiver *receiver, ISimpleTextureSource *tsrc)
|
||||
void TouchControls::buttonEmitAction(button_info &btn, bool action)
|
||||
{
|
||||
if (keycode == KEY_UNKNOWN)
|
||||
if (btn.keycode == KEY_UNKNOWN)
|
||||
return;
|
||||
|
||||
SEvent translated{};
|
||||
translated.EventType = EET_KEY_INPUT_EVENT;
|
||||
translated.KeyInput.Key = keycode;
|
||||
translated.KeyInput.Control = false;
|
||||
translated.KeyInput.Shift = false;
|
||||
translated.KeyInput.Char = 0;
|
||||
emitKeyboardEvent(btn.keycode, action);
|
||||
|
||||
if (action) {
|
||||
translated.KeyInput.PressedDown = true;
|
||||
receiver->OnEvent(translated);
|
||||
if (btn.toggleable == button_info::FIRST_TEXTURE) {
|
||||
btn.toggleable = button_info::SECOND_TEXTURE;
|
||||
loadButtonTexture(btn.gui_button.get(), btn.toggle_textures[1]);
|
||||
|
||||
if (toggleable == button_info::FIRST_TEXTURE) {
|
||||
toggleable = button_info::SECOND_TEXTURE;
|
||||
load_button_texture(gui_button.get(), toggle_textures[1],
|
||||
gui_button->getRelativePosition(),
|
||||
tsrc, driver);
|
||||
} else if (toggleable == button_info::SECOND_TEXTURE) {
|
||||
toggleable = button_info::FIRST_TEXTURE;
|
||||
load_button_texture(gui_button.get(), toggle_textures[0],
|
||||
gui_button->getRelativePosition(),
|
||||
tsrc, driver);
|
||||
} else if (btn.toggleable == button_info::SECOND_TEXTURE) {
|
||||
btn.toggleable = button_info::FIRST_TEXTURE;
|
||||
loadButtonTexture(btn.gui_button.get(), btn.toggle_textures[0]);
|
||||
}
|
||||
} else {
|
||||
translated.KeyInput.PressedDown = false;
|
||||
receiver->OnEvent(translated);
|
||||
}
|
||||
}
|
||||
|
||||
static bool buttons_handlePress(std::vector<button_info> &buttons, size_t pointer_id, IGUIElement *element,
|
||||
video::IVideoDriver *driver, IEventReceiver *receiver, ISimpleTextureSource *tsrc)
|
||||
bool TouchControls::buttonsHandlePress(std::vector<button_info> &buttons, size_t pointer_id, IGUIElement *element)
|
||||
{
|
||||
if (!element)
|
||||
return false;
|
||||
@ -87,7 +82,7 @@ static bool buttons_handlePress(std::vector<button_info> &buttons, size_t pointe
|
||||
if (btn.pointer_ids.size() > 1)
|
||||
return true;
|
||||
|
||||
btn.emitAction(true, driver, receiver, tsrc);
|
||||
buttonEmitAction(btn, true);
|
||||
btn.repeat_counter = -BUTTON_REPEAT_DELAY;
|
||||
return true;
|
||||
}
|
||||
@ -97,8 +92,7 @@ static bool buttons_handlePress(std::vector<button_info> &buttons, size_t pointe
|
||||
}
|
||||
|
||||
|
||||
static bool buttons_handleRelease(std::vector<button_info> &buttons, size_t pointer_id,
|
||||
video::IVideoDriver *driver, IEventReceiver *receiver, ISimpleTextureSource *tsrc)
|
||||
bool TouchControls::buttonsHandleRelease(std::vector<button_info> &buttons, size_t pointer_id)
|
||||
{
|
||||
for (button_info &btn : buttons) {
|
||||
auto it = std::find(btn.pointer_ids.begin(), btn.pointer_ids.end(), pointer_id);
|
||||
@ -108,7 +102,7 @@ static bool buttons_handleRelease(std::vector<button_info> &buttons, size_t poin
|
||||
if (!btn.pointer_ids.empty())
|
||||
return true;
|
||||
|
||||
btn.emitAction(false, driver, receiver, tsrc);
|
||||
buttonEmitAction(btn, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -116,8 +110,7 @@ static bool buttons_handleRelease(std::vector<button_info> &buttons, size_t poin
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool buttons_step(std::vector<button_info> &buttons, float dtime,
|
||||
video::IVideoDriver *driver, IEventReceiver *receiver, ISimpleTextureSource *tsrc)
|
||||
bool TouchControls::buttonsStep(std::vector<button_info> &buttons, float dtime)
|
||||
{
|
||||
bool has_pointers = false;
|
||||
|
||||
@ -130,8 +123,8 @@ static bool buttons_step(std::vector<button_info> &buttons, float dtime,
|
||||
if (btn.repeat_counter < BUTTON_REPEAT_INTERVAL)
|
||||
continue;
|
||||
|
||||
btn.emitAction(false, driver, receiver, tsrc);
|
||||
btn.emitAction(true, driver, receiver, tsrc);
|
||||
buttonEmitAction(btn, false);
|
||||
buttonEmitAction(btn, true);
|
||||
btn.repeat_counter = 0.0f;
|
||||
}
|
||||
|
||||
@ -340,8 +333,7 @@ void TouchControls::addButton(std::vector<button_info> &buttons, touch_gui_butto
|
||||
{
|
||||
IGUIImage *btn_gui_button = m_guienv->addImage(rect, nullptr, id);
|
||||
btn_gui_button->setVisible(visible);
|
||||
load_button_texture(btn_gui_button, image, rect,
|
||||
m_texturesource, m_device->getVideoDriver());
|
||||
loadButtonTexture(btn_gui_button, image);
|
||||
|
||||
button_info &btn = buttons.emplace_back();
|
||||
btn.keycode = id_to_keycode(id);
|
||||
@ -363,8 +355,7 @@ IGUIImage *TouchControls::makeButtonDirect(touch_gui_button_id id,
|
||||
{
|
||||
IGUIImage *btn_gui_button = m_guienv->addImage(rect, nullptr, id);
|
||||
btn_gui_button->setVisible(visible);
|
||||
load_button_texture(btn_gui_button, button_image_names[id], rect,
|
||||
m_texturesource, m_device->getVideoDriver());
|
||||
loadButtonTexture(btn_gui_button, button_image_names[id]);
|
||||
|
||||
return btn_gui_button;
|
||||
}
|
||||
@ -399,11 +390,9 @@ void TouchControls::handleReleaseEvent(size_t pointer_id)
|
||||
m_pointer_pos.erase(pointer_id);
|
||||
|
||||
// handle buttons
|
||||
if (buttons_handleRelease(m_buttons, pointer_id, m_device->getVideoDriver(),
|
||||
m_receiver, m_texturesource))
|
||||
if (buttonsHandleRelease(m_buttons, pointer_id))
|
||||
return;
|
||||
if (buttons_handleRelease(m_overflow_buttons, pointer_id, m_device->getVideoDriver(),
|
||||
m_receiver, m_texturesource))
|
||||
if (buttonsHandleRelease(m_overflow_buttons, pointer_id))
|
||||
return;
|
||||
|
||||
if (m_has_move_id && pointer_id == m_move_id) {
|
||||
@ -481,8 +470,7 @@ void TouchControls::translateEvent(const SEvent &event)
|
||||
}
|
||||
}
|
||||
|
||||
if (buttons_handlePress(m_overflow_buttons, pointer_id, element,
|
||||
m_device->getVideoDriver(), m_receiver, m_texturesource))
|
||||
if (buttonsHandlePress(m_overflow_buttons, pointer_id, element))
|
||||
return;
|
||||
|
||||
toggleOverflowMenu();
|
||||
@ -494,8 +482,7 @@ void TouchControls::translateEvent(const SEvent &event)
|
||||
}
|
||||
|
||||
// handle buttons
|
||||
if (buttons_handlePress(m_buttons, pointer_id, element,
|
||||
m_device->getVideoDriver(), m_receiver, m_texturesource))
|
||||
if (buttonsHandlePress(m_buttons, pointer_id, element))
|
||||
return;
|
||||
|
||||
// handle hotbar
|
||||
@ -614,16 +601,10 @@ void TouchControls::translateEvent(const SEvent &event)
|
||||
void TouchControls::applyJoystickStatus()
|
||||
{
|
||||
if (m_joystick_triggers_aux1) {
|
||||
SEvent translated{};
|
||||
translated.EventType = EET_KEY_INPUT_EVENT;
|
||||
translated.KeyInput.Key = id_to_keycode(aux1_id);
|
||||
translated.KeyInput.PressedDown = false;
|
||||
m_receiver->OnEvent(translated);
|
||||
|
||||
if (m_joystick_status_aux1) {
|
||||
translated.KeyInput.PressedDown = true;
|
||||
m_receiver->OnEvent(translated);
|
||||
}
|
||||
auto key = id_to_keycode(aux1_id);
|
||||
emitKeyboardEvent(key, false);
|
||||
if (m_joystick_status_aux1)
|
||||
emitKeyboardEvent(key, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -639,8 +620,8 @@ void TouchControls::step(float dtime)
|
||||
}
|
||||
|
||||
// simulate keyboard repeats
|
||||
buttons_step(m_buttons, dtime, m_device->getVideoDriver(), m_receiver, m_texturesource);
|
||||
buttons_step(m_overflow_buttons, dtime, m_device->getVideoDriver(), m_receiver, m_texturesource);
|
||||
buttonsStep(m_buttons, dtime);
|
||||
buttonsStep(m_overflow_buttons, dtime);
|
||||
|
||||
// joystick
|
||||
applyJoystickStatus();
|
||||
|
@ -67,9 +67,6 @@ struct button_info
|
||||
SECOND_TEXTURE
|
||||
} toggleable = NOT_TOGGLEABLE;
|
||||
std::string toggle_textures[2];
|
||||
|
||||
void emitAction(bool action, video::IVideoDriver *driver,
|
||||
IEventReceiver *receiver, ISimpleTextureSource *tsrc);
|
||||
};
|
||||
|
||||
|
||||
@ -186,6 +183,19 @@ private:
|
||||
|
||||
std::shared_ptr<IGUIStaticText> m_status_text;
|
||||
|
||||
// Note: TouchControls intentionally uses IGUIImage instead of IGUIButton
|
||||
// for its buttons. We only want static image display, not interactivity,
|
||||
// from Irrlicht.
|
||||
|
||||
void emitKeyboardEvent(EKEY_CODE keycode, bool pressed);
|
||||
|
||||
void loadButtonTexture(IGUIImage *gui_button, const std::string &path);
|
||||
void buttonEmitAction(button_info &btn, bool action);
|
||||
|
||||
bool buttonsHandlePress(std::vector<button_info> &buttons, size_t pointer_id, IGUIElement *element);
|
||||
bool buttonsHandleRelease(std::vector<button_info> &buttons, size_t pointer_id);
|
||||
bool buttonsStep(std::vector<button_info> &buttons, float dtime);
|
||||
|
||||
void toggleOverflowMenu();
|
||||
void updateVisibility();
|
||||
void releaseAll();
|
||||
|
@ -88,12 +88,11 @@ void ItemStackMetadata::deSerialize(std::istream &is)
|
||||
void ItemStackMetadata::updateToolCapabilities()
|
||||
{
|
||||
if (contains(TOOLCAP_KEY)) {
|
||||
toolcaps_overridden = true;
|
||||
toolcaps_override = ToolCapabilities();
|
||||
std::istringstream is(getString(TOOLCAP_KEY));
|
||||
toolcaps_override.deserializeJson(is);
|
||||
toolcaps_override->deserializeJson(is);
|
||||
} else {
|
||||
toolcaps_overridden = false;
|
||||
toolcaps_override = std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,8 +15,7 @@ class IItemDefManager;
|
||||
class ItemStackMetadata : public SimpleMetadata
|
||||
{
|
||||
public:
|
||||
ItemStackMetadata():
|
||||
toolcaps_overridden(false)
|
||||
ItemStackMetadata()
|
||||
{}
|
||||
|
||||
// Overrides
|
||||
@ -29,7 +28,7 @@ public:
|
||||
const ToolCapabilities &getToolCapabilities(
|
||||
const ToolCapabilities &default_caps) const
|
||||
{
|
||||
return toolcaps_overridden ? toolcaps_override : default_caps;
|
||||
return toolcaps_override.has_value() ? *toolcaps_override : default_caps;
|
||||
}
|
||||
|
||||
void setToolCapabilities(const ToolCapabilities &caps);
|
||||
@ -40,7 +39,6 @@ public:
|
||||
return wear_bar_override;
|
||||
}
|
||||
|
||||
|
||||
void setWearBarParams(const WearBarParams ¶ms);
|
||||
void clearWearBarParams();
|
||||
|
||||
@ -48,7 +46,6 @@ private:
|
||||
void updateToolCapabilities();
|
||||
void updateWearBarParams();
|
||||
|
||||
bool toolcaps_overridden;
|
||||
ToolCapabilities toolcaps_override;
|
||||
std::optional<ToolCapabilities> toolcaps_override;
|
||||
std::optional<WearBarParams> wear_bar_override;
|
||||
};
|
||||
|
@ -742,7 +742,7 @@ static void fillTileAttribs(ITextureSource *tsrc, TileLayer *layer,
|
||||
}
|
||||
}
|
||||
|
||||
bool isWorldAligned(AlignStyle style, WorldAlignMode mode, NodeDrawType drawtype)
|
||||
static bool isWorldAligned(AlignStyle style, WorldAlignMode mode, NodeDrawType drawtype)
|
||||
{
|
||||
if (style == ALIGN_STYLE_WORLD)
|
||||
return true;
|
||||
|
@ -1594,7 +1594,7 @@ ToolCapabilities read_tool_capabilities(
|
||||
// key at index -2 and value at index -1
|
||||
int rating = luaL_checkinteger(L, -2);
|
||||
float time = luaL_checknumber(L, -1);
|
||||
groupcap.times[rating] = time;
|
||||
groupcap.times.emplace_back(rating, time);
|
||||
// removes value, keeps key for next iteration
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
19
src/tool.cpp
19
src/tool.cpp
@ -47,7 +47,7 @@ void ToolGroupCap::fromJson(const Json::Value &json)
|
||||
|
||||
for (Json::ArrayIndex i = 0; i < size; ++i) {
|
||||
if (times_object[i].isDouble())
|
||||
times[i] = times_object[i].asFloat();
|
||||
times.emplace_back(i, times_object[i].asFloat());
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,7 +106,7 @@ void ToolCapabilities::deSerialize(std::istream &is)
|
||||
for(u32 i = 0; i < times_size; i++) {
|
||||
int level = readS16(is);
|
||||
float time = readF32(is);
|
||||
cap.times[level] = time;
|
||||
cap.times.emplace_back(level, time);
|
||||
}
|
||||
groupcaps[name] = cap;
|
||||
}
|
||||
@ -272,21 +272,11 @@ std::optional<WearBarParams> WearBarParams::deserializeJson(std::istream &is)
|
||||
return WearBarParams(colorStops, blend);
|
||||
}
|
||||
|
||||
video::SColor WearBarParams::getWearBarColor(f32 durabilityPercent) {
|
||||
video::SColor WearBarParams::getWearBarColor(f32 durabilityPercent)
|
||||
{
|
||||
if (colorStops.empty())
|
||||
return video::SColor();
|
||||
|
||||
/*
|
||||
* Strategy:
|
||||
* Find upper bound of durabilityPercent
|
||||
*
|
||||
* if it == stops.end() -> return last color in the map
|
||||
* if it == stops.begin() -> return first color in the map
|
||||
*
|
||||
* else:
|
||||
* lower_bound = it - 1
|
||||
* interpolate/do constant
|
||||
*/
|
||||
auto upper = colorStops.upper_bound(durabilityPercent);
|
||||
|
||||
if (upper == colorStops.end()) // durability is >= the highest defined color stop
|
||||
@ -295,6 +285,7 @@ video::SColor WearBarParams::getWearBarColor(f32 durabilityPercent) {
|
||||
if (upper == colorStops.begin()) // durability is <= the lowest defined color stop
|
||||
return upper->second;
|
||||
|
||||
// between two values, interpolate
|
||||
auto lower = std::prev(upper);
|
||||
f32 lower_bound = lower->first;
|
||||
video::SColor lower_color = lower->second;
|
||||
|
37
src/tool.h
37
src/tool.h
@ -12,26 +12,33 @@
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <optional>
|
||||
|
||||
struct ItemDefinition;
|
||||
class IItemDefManager;
|
||||
|
||||
/*
|
||||
* NOTE: these structs intentionally use vector<pair<>> or map<> over unordered_map<>
|
||||
* to avoid blowing up the structure sizes. Also because the linear "dumb" approach
|
||||
* works better if you have just a handful of items.
|
||||
*/
|
||||
|
||||
struct ToolGroupCap
|
||||
{
|
||||
std::unordered_map<int, float> times;
|
||||
std::vector<std::pair<int, float>> times;
|
||||
int maxlevel = 1;
|
||||
int uses = 20;
|
||||
|
||||
ToolGroupCap() = default;
|
||||
|
||||
std::optional<float> getTime(int rating) const {
|
||||
auto i = times.find(rating);
|
||||
if (i == times.end())
|
||||
return std::nullopt;
|
||||
return i->second;
|
||||
for (auto &it : times) {
|
||||
if (it.first == rating)
|
||||
return it.second;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void toJson(Json::Value &object) const;
|
||||
@ -39,16 +46,16 @@ struct ToolGroupCap
|
||||
};
|
||||
|
||||
|
||||
typedef std::unordered_map<std::string, struct ToolGroupCap> ToolGCMap;
|
||||
typedef std::unordered_map<std::string, s16> DamageGroup;
|
||||
typedef std::map<std::string, ToolGroupCap> ToolGCMap;
|
||||
typedef std::map<std::string, s16> DamageGroup;
|
||||
|
||||
struct ToolCapabilities
|
||||
{
|
||||
float full_punch_interval;
|
||||
int max_drop_level;
|
||||
int punch_attack_uses;
|
||||
ToolGCMap groupcaps;
|
||||
DamageGroup damageGroups;
|
||||
int punch_attack_uses;
|
||||
|
||||
ToolCapabilities(
|
||||
float full_punch_interval_ = 1.4f,
|
||||
@ -59,9 +66,9 @@ struct ToolCapabilities
|
||||
):
|
||||
full_punch_interval(full_punch_interval_),
|
||||
max_drop_level(max_drop_level_),
|
||||
punch_attack_uses(punch_attack_uses_),
|
||||
groupcaps(groupcaps_),
|
||||
damageGroups(damageGroups_),
|
||||
punch_attack_uses(punch_attack_uses_)
|
||||
damageGroups(damageGroups_)
|
||||
{}
|
||||
|
||||
void serialize(std::ostream &os, u16 version) const;
|
||||
@ -76,17 +83,18 @@ private:
|
||||
|
||||
struct WearBarParams
|
||||
{
|
||||
std::map<f32, video::SColor> colorStops;
|
||||
enum BlendMode : u8 {
|
||||
BLEND_MODE_CONSTANT,
|
||||
BLEND_MODE_LINEAR,
|
||||
BlendMode_END // Dummy for validity check
|
||||
};
|
||||
constexpr const static EnumString es_BlendMode[3] = {
|
||||
{WearBarParams::BLEND_MODE_CONSTANT, "constant"},
|
||||
{WearBarParams::BLEND_MODE_LINEAR, "linear"},
|
||||
{BLEND_MODE_CONSTANT, "constant"},
|
||||
{BLEND_MODE_LINEAR, "linear"},
|
||||
{0, nullptr}
|
||||
};
|
||||
|
||||
std::map<f32, video::SColor> colorStops;
|
||||
BlendMode blend;
|
||||
|
||||
WearBarParams(const std::map<f32, video::SColor> &colorStops, BlendMode blend):
|
||||
@ -102,6 +110,7 @@ struct WearBarParams
|
||||
static WearBarParams deserialize(std::istream &is);
|
||||
void serializeJson(std::ostream &os) const;
|
||||
static std::optional<WearBarParams> deserializeJson(std::istream &is);
|
||||
|
||||
video::SColor getWearBarColor(f32 durabilityPercent);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user