Merge branch 'minetest:master' into master
This commit is contained in:
commit
fdc8d752f3
@ -406,6 +406,7 @@ bilinear_filter (Bilinear filtering) bool false
|
|||||||
trilinear_filter (Trilinear filtering) bool false
|
trilinear_filter (Trilinear filtering) bool false
|
||||||
|
|
||||||
# Use anisotropic filtering when looking at textures from an angle.
|
# 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
|
anisotropic_filter (Anisotropic filtering) bool false
|
||||||
|
|
||||||
# Select the antialiasing method to apply.
|
# 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!
|
# Warning: This option is EXPERIMENTAL!
|
||||||
autoscale_mode (Autoscaling mode) enum disable disable,enable,force
|
autoscale_mode (Autoscaling mode) enum disable disable,enable,force
|
||||||
|
|
||||||
# When using bilinear/trilinear/anisotropic filters, low-resolution textures
|
# When using bilinear/trilinear filtering, low-resolution textures
|
||||||
# can be blurred, so automatically upscale them with nearest-neighbor
|
# can be blurred, so this option automatically upscales them to preserve
|
||||||
# interpolation to preserve crisp pixels. This sets the minimum texture size
|
# crisp pixels. This defines the minimum texture size for the upscaled textures;
|
||||||
# for the upscaled textures; higher values look sharper, but require more
|
# higher values look sharper, but require more memory.
|
||||||
# memory. Powers of 2 are recommended. This setting is ONLY applied if
|
# This setting is ONLY applied if any of the mentioned filters are enabled.
|
||||||
# bilinear/trilinear/anisotropic filtering is enabled.
|
|
||||||
# This is also used as the base node texture size for world-aligned
|
# This is also used as the base node texture size for world-aligned
|
||||||
# texture autoscaling.
|
# texture autoscaling.
|
||||||
texture_min_size (Base texture size) int 64 1 32768
|
texture_min_size (Base texture size) int 64 1 32768
|
||||||
|
@ -23,7 +23,12 @@ void main(void)
|
|||||||
vec2 uv = varTexCoord.st;
|
vec2 uv = varTexCoord.st;
|
||||||
vec3 color = texture2D(rendered, uv).rgb;
|
vec3 color = texture2D(rendered, uv).rgb;
|
||||||
// translate to linear colorspace (approximate)
|
// 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));
|
color = pow(clamp(color, 0.0, 1.0), vec3(2.2));
|
||||||
|
#else
|
||||||
|
color = pow(color, vec3(2.2));
|
||||||
|
#endif
|
||||||
|
|
||||||
color *= exposureParams.compensationFactor * bloomStrength;
|
color *= exposureParams.compensationFactor * bloomStrength;
|
||||||
|
|
||||||
|
@ -39,14 +39,16 @@ varying vec3 vPosition;
|
|||||||
// cameraOffset + worldPosition (for large coordinates the limits of float
|
// cameraOffset + worldPosition (for large coordinates the limits of float
|
||||||
// precision must be considered).
|
// precision must be considered).
|
||||||
varying vec3 worldPosition;
|
varying vec3 worldPosition;
|
||||||
varying lowp vec4 varColor;
|
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
|
varying lowp vec4 varColor;
|
||||||
varying mediump vec2 varTexCoord;
|
varying mediump vec2 varTexCoord;
|
||||||
|
varying float nightRatio;
|
||||||
#else
|
#else
|
||||||
|
centroid varying lowp vec4 varColor;
|
||||||
centroid varying vec2 varTexCoord;
|
centroid varying vec2 varTexCoord;
|
||||||
|
centroid varying float nightRatio;
|
||||||
#endif
|
#endif
|
||||||
varying highp vec3 eyeVec;
|
varying highp vec3 eyeVec;
|
||||||
varying float nightRatio;
|
|
||||||
|
|
||||||
#ifdef ENABLE_DYNAMIC_SHADOWS
|
#ifdef ENABLE_DYNAMIC_SHADOWS
|
||||||
#if (defined(ENABLE_WATER_REFLECTIONS) && MATERIAL_WAVING_LIQUID && ENABLE_WAVING_WATER)
|
#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
|
// cameraOffset + worldPosition (for large coordinates the limits of float
|
||||||
// precision must be considered).
|
// precision must be considered).
|
||||||
varying vec3 worldPosition;
|
varying vec3 worldPosition;
|
||||||
varying lowp vec4 varColor;
|
|
||||||
// The centroid keyword ensures that after interpolation the texture coordinates
|
// The centroid keyword ensures that after interpolation the texture coordinates
|
||||||
// lie within the same bounds when MSAA is en- and disabled.
|
// lie within the same bounds when MSAA is en- and disabled.
|
||||||
// This fixes the stripes problem with nearest-neighbor textures and MSAA.
|
// This fixes the stripes problem with nearest-neighbor textures and MSAA.
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
|
varying lowp vec4 varColor;
|
||||||
varying mediump vec2 varTexCoord;
|
varying mediump vec2 varTexCoord;
|
||||||
|
varying float nightRatio;
|
||||||
#else
|
#else
|
||||||
|
centroid varying lowp vec4 varColor;
|
||||||
centroid varying vec2 varTexCoord;
|
centroid varying vec2 varTexCoord;
|
||||||
|
centroid varying float nightRatio;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_DYNAMIC_SHADOWS
|
#ifdef ENABLE_DYNAMIC_SHADOWS
|
||||||
// shadow uniforms
|
// shadow uniforms
|
||||||
@ -44,7 +47,6 @@ centroid varying vec2 varTexCoord;
|
|||||||
varying float area_enable_parallax;
|
varying float area_enable_parallax;
|
||||||
|
|
||||||
varying highp vec3 eyeVec;
|
varying highp vec3 eyeVec;
|
||||||
varying float nightRatio;
|
|
||||||
// Color of the light emitted by the light sources.
|
// Color of the light emitted by the light sources.
|
||||||
const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
|
const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
|
||||||
const float e = 2.718281828459;
|
const float e = 2.718281828459;
|
||||||
|
@ -188,7 +188,6 @@ Mod directory structure
|
|||||||
│ ├── models
|
│ ├── models
|
||||||
│ ├── textures
|
│ ├── textures
|
||||||
│ │ ├── modname_stuff.png
|
│ │ ├── modname_stuff.png
|
||||||
│ │ ├── modname_stuff_normal.png
|
|
||||||
│ │ ├── modname_something_else.png
|
│ │ ├── modname_something_else.png
|
||||||
│ │ ├── subfolder_foo
|
│ │ ├── subfolder_foo
|
||||||
│ │ │ ├── modname_more_stuff.png
|
│ │ │ ├── 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
|
#pragma once
|
||||||
|
|
||||||
#include "EShaderTypes.h"
|
|
||||||
#include "EMaterialTypes.h"
|
#include "EMaterialTypes.h"
|
||||||
#include "EPrimitiveTypes.h"
|
#include "EPrimitiveTypes.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
@ -31,26 +30,15 @@ public:
|
|||||||
virtual ~IGPUProgrammingServices() {}
|
virtual ~IGPUProgrammingServices() {}
|
||||||
|
|
||||||
//! Adds a new high-level shading material renderer to the VideoDriver.
|
//! 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
|
\param vertexShaderProgram String containing the source of the vertex
|
||||||
shader program. This can be 0 if no vertex program shall be used.
|
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
|
\param pixelShaderProgram String containing the source of the pixel
|
||||||
shader program. This can be 0 if no pixel shader shall be used.
|
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
|
\param geometryShaderProgram String containing the source of the
|
||||||
geometry shader program. This can be 0 if no geometry shader shall be
|
geometry shader program. This can be 0 if no geometry shader shall be
|
||||||
used.
|
used.
|
||||||
\param geometryShaderEntryPointName Entry name of the function of the
|
\param shaderName Name of the shader for debug purposes
|
||||||
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 inType Type of vertices passed to geometry shader
|
||||||
\param outType Type of vertices created by geometry shader
|
\param outType Type of vertices created by geometry shader
|
||||||
\param verticesOut Maximal number of vertices created by geometry
|
\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. */
|
error log and can be caught with a custom event receiver. */
|
||||||
virtual s32 addHighLevelShaderMaterial(
|
virtual s32 addHighLevelShaderMaterial(
|
||||||
const c8 *vertexShaderProgram,
|
const c8 *vertexShaderProgram,
|
||||||
const c8 *vertexShaderEntryPointName,
|
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
|
||||||
const c8 *pixelShaderProgram,
|
const c8 *pixelShaderProgram,
|
||||||
const c8 *pixelShaderEntryPointName,
|
|
||||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
|
||||||
const c8 *geometryShaderProgram,
|
const c8 *geometryShaderProgram,
|
||||||
const c8 *geometryShaderEntryPointName = "main",
|
const c8 *shaderName = nullptr,
|
||||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
|
||||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||||
u32 verticesOut = 0,
|
u32 verticesOut = 0,
|
||||||
IShaderConstantSetCallBack *callback = 0,
|
IShaderConstantSetCallBack *callback = nullptr,
|
||||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||||
s32 userData = 0) = 0;
|
s32 userData = 0) = 0;
|
||||||
|
|
||||||
//! convenience function for use without geometry shaders
|
//! convenience function for use without geometry shaders
|
||||||
s32 addHighLevelShaderMaterial(
|
s32 addHighLevelShaderMaterial(
|
||||||
const c8 *vertexShaderProgram,
|
const c8 *vertexShaderProgram,
|
||||||
const c8 *vertexShaderEntryPointName = "main",
|
const c8 *pixelShaderProgram = nullptr,
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1,
|
const c8 *shaderName = nullptr,
|
||||||
const c8 *pixelShaderProgram = 0,
|
IShaderConstantSetCallBack *callback = nullptr,
|
||||||
const c8 *pixelShaderEntryPointName = "main",
|
|
||||||
E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1,
|
|
||||||
IShaderConstantSetCallBack *callback = 0,
|
|
||||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||||
s32 userData = 0)
|
s32 userData = 0)
|
||||||
{
|
{
|
||||||
return addHighLevelShaderMaterial(
|
return addHighLevelShaderMaterial(
|
||||||
vertexShaderProgram, vertexShaderEntryPointName,
|
vertexShaderProgram, pixelShaderProgram,
|
||||||
vsCompileTarget, pixelShaderProgram,
|
nullptr, shaderName,
|
||||||
pixelShaderEntryPointName, psCompileTarget,
|
|
||||||
0, "main", EGST_GS_4_0,
|
|
||||||
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0,
|
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0,
|
||||||
callback, baseMaterial, userData);
|
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.
|
//! Like addHighLevelShaderMaterial(), but loads from files.
|
||||||
/** \param vertexShaderProgramFileName Text file containing the source
|
/** \param vertexShaderProgramFileName Text file containing the source
|
||||||
of the vertex shader program. Set to empty string if no vertex shader
|
of the vertex shader program. Set to empty string if no vertex shader
|
||||||
shall be created.
|
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
|
\param pixelShaderProgramFileName Text file containing the source of
|
||||||
the pixel shader program. Set to empty string if no pixel shader shall
|
the pixel shader program. Set to empty string if no pixel shader shall
|
||||||
be created.
|
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
|
\param geometryShaderProgramFileName Name of the source of
|
||||||
the geometry shader program. Set to empty string if no geometry shader
|
the geometry shader program. Set to empty string if no geometry shader
|
||||||
shall be created.
|
shall be created.
|
||||||
\param geometryShaderEntryPointName Entry name of the function of the
|
\param shaderName Name of the shader for debug purposes
|
||||||
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 inType Type of vertices passed to geometry shader
|
||||||
\param outType Type of vertices created by geometry shader
|
\param outType Type of vertices created by geometry shader
|
||||||
\param verticesOut Maximal number of vertices created by geometry
|
\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. */
|
error log and can be caught with a custom event receiver. */
|
||||||
virtual s32 addHighLevelShaderMaterialFromFiles(
|
virtual s32 addHighLevelShaderMaterialFromFiles(
|
||||||
const io::path &vertexShaderProgramFileName,
|
const io::path &vertexShaderProgramFileName,
|
||||||
const c8 *vertexShaderEntryPointName,
|
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
|
||||||
const io::path &pixelShaderProgramFileName,
|
const io::path &pixelShaderProgramFileName,
|
||||||
const c8 *pixelShaderEntryPointName,
|
|
||||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
|
||||||
const io::path &geometryShaderProgramFileName,
|
const io::path &geometryShaderProgramFileName,
|
||||||
const c8 *geometryShaderEntryPointName = "main",
|
const c8 *shaderName = nullptr,
|
||||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
|
||||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||||
u32 verticesOut = 0,
|
u32 verticesOut = 0,
|
||||||
IShaderConstantSetCallBack *callback = 0,
|
IShaderConstantSetCallBack *callback = nullptr,
|
||||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||||
s32 userData = 0) = 0;
|
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.
|
//! Delete a shader material and associated data.
|
||||||
/**
|
/**
|
||||||
After you have deleted a material it is invalid to still use and doing
|
After you have deleted a material it is invalid to still use and doing
|
||||||
|
@ -61,8 +61,8 @@ struct SFrameStats {
|
|||||||
u32 PrimitivesDrawn = 0;
|
u32 PrimitivesDrawn = 0;
|
||||||
//! Number of hardware buffers uploaded (new or updated)
|
//! Number of hardware buffers uploaded (new or updated)
|
||||||
u32 HWBuffersUploaded = 0;
|
u32 HWBuffersUploaded = 0;
|
||||||
//! Sum of uploaded hardware buffer size
|
//! Number of active hardware buffers
|
||||||
u32 HWBuffersUploadedSize = 0;
|
u32 HWBuffersActive = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Interface to driver which is able to perform 2d and 3d graphics functions.
|
//! 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()
|
bool CNullDriver::endScene()
|
||||||
{
|
{
|
||||||
FPSCounter.registerFrame(os::Timer::getRealTime());
|
FPSCounter.registerFrame(os::Timer::getRealTime());
|
||||||
updateAllHardwareBuffers();
|
expireHardwareBuffers();
|
||||||
updateAllOcclusionQueries();
|
updateAllOcclusionQueries();
|
||||||
return true;
|
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
|
return createHardwareBuffer(ib); // no hardware links, and mesh wants one, create it
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Update all hardware buffers, remove unused ones
|
void CNullDriver::registerHardwareBuffer(SHWBufferLink *HWBuffer)
|
||||||
void CNullDriver::updateAllHardwareBuffers()
|
|
||||||
{
|
{
|
||||||
// FIXME: this method can take a lot of time just doing the refcount
|
_IRR_DEBUG_BREAK_IF(!HWBuffer)
|
||||||
// checks and iteration (too much pointer chasing?) for
|
HWBuffer->ListPosition = HWBufferList.size();
|
||||||
// large buffer counts (e.g. 50000)
|
HWBufferList.push_back(HWBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
auto it = HWBufferList.begin();
|
void CNullDriver::expireHardwareBuffers()
|
||||||
while (it != HWBufferList.end()) {
|
{
|
||||||
SHWBufferLink *Link = *it;
|
for (size_t i = 0; i < HWBufferList.size(); ) {
|
||||||
++it;
|
auto *Link = HWBufferList[i];
|
||||||
|
|
||||||
if (Link->IsVertex) {
|
bool del;
|
||||||
if (!Link->VertexBuffer || Link->VertexBuffer->getReferenceCount() == 1)
|
if (Link->IsVertex)
|
||||||
deleteHardwareBuffer(Link);
|
del = !Link->VertexBuffer || Link->VertexBuffer->getReferenceCount() == 1;
|
||||||
} else {
|
else
|
||||||
if (!Link->IndexBuffer || Link->IndexBuffer->getReferenceCount() == 1)
|
del = !Link->IndexBuffer || Link->IndexBuffer->getReferenceCount() == 1;
|
||||||
deleteHardwareBuffer(Link);
|
// deleting can reorder, so don't advance in list
|
||||||
}
|
if (del)
|
||||||
|
deleteHardwareBuffer(Link);
|
||||||
|
else
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrameStats.HWBuffersActive = HWBufferList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNullDriver::deleteHardwareBuffer(SHWBufferLink *HWBuffer)
|
void CNullDriver::deleteHardwareBuffer(SHWBufferLink *HWBuffer)
|
||||||
{
|
{
|
||||||
if (!HWBuffer)
|
if (!HWBuffer)
|
||||||
return;
|
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;
|
delete HWBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1506,34 +1520,24 @@ IGPUProgrammingServices *CNullDriver::getGPUProgrammingServices()
|
|||||||
//! Adds a new material renderer to the VideoDriver, based on a high level shading language.
|
//! Adds a new material renderer to the VideoDriver, based on a high level shading language.
|
||||||
s32 CNullDriver::addHighLevelShaderMaterial(
|
s32 CNullDriver::addHighLevelShaderMaterial(
|
||||||
const c8 *vertexShaderProgram,
|
const c8 *vertexShaderProgram,
|
||||||
const c8 *vertexShaderEntryPointName,
|
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
|
||||||
const c8 *pixelShaderProgram,
|
const c8 *pixelShaderProgram,
|
||||||
const c8 *pixelShaderEntryPointName,
|
|
||||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
|
||||||
const c8 *geometryShaderProgram,
|
const c8 *geometryShaderProgram,
|
||||||
const c8 *geometryShaderEntryPointName,
|
const c8 *shaderName,
|
||||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
|
|
||||||
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
|
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
|
||||||
u32 verticesOut,
|
u32 verticesOut,
|
||||||
IShaderConstantSetCallBack *callback,
|
IShaderConstantSetCallBack *callback,
|
||||||
E_MATERIAL_TYPE baseMaterial,
|
E_MATERIAL_TYPE baseMaterial,
|
||||||
s32 userData)
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
|
s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
|
||||||
const io::path &vertexShaderProgramFileName,
|
const io::path &vertexShaderProgramFileName,
|
||||||
const c8 *vertexShaderEntryPointName,
|
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
|
||||||
const io::path &pixelShaderProgramFileName,
|
const io::path &pixelShaderProgramFileName,
|
||||||
const c8 *pixelShaderEntryPointName,
|
|
||||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
|
||||||
const io::path &geometryShaderProgramFileName,
|
const io::path &geometryShaderProgramFileName,
|
||||||
const c8 *geometryShaderEntryPointName,
|
const c8 *shaderName,
|
||||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
|
|
||||||
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
|
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
|
||||||
u32 verticesOut,
|
u32 verticesOut,
|
||||||
IShaderConstantSetCallBack *callback,
|
IShaderConstantSetCallBack *callback,
|
||||||
@ -1569,9 +1573,7 @@ s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32 result = addHighLevelShaderMaterialFromFiles(
|
s32 result = addHighLevelShaderMaterialFromFiles(
|
||||||
vsfile, vertexShaderEntryPointName, vsCompileTarget,
|
vsfile, psfile, gsfile, shaderName,
|
||||||
psfile, pixelShaderEntryPointName, psCompileTarget,
|
|
||||||
gsfile, geometryShaderEntryPointName, gsCompileTarget,
|
|
||||||
inType, outType, verticesOut,
|
inType, outType, verticesOut,
|
||||||
callback, baseMaterial, userData);
|
callback, baseMaterial, userData);
|
||||||
|
|
||||||
@ -1589,14 +1591,9 @@ s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
|
|||||||
|
|
||||||
s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
|
s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
|
||||||
io::IReadFile *vertexShaderProgram,
|
io::IReadFile *vertexShaderProgram,
|
||||||
const c8 *vertexShaderEntryPointName,
|
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
|
||||||
io::IReadFile *pixelShaderProgram,
|
io::IReadFile *pixelShaderProgram,
|
||||||
const c8 *pixelShaderEntryPointName,
|
|
||||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
|
||||||
io::IReadFile *geometryShaderProgram,
|
io::IReadFile *geometryShaderProgram,
|
||||||
const c8 *geometryShaderEntryPointName,
|
const c8 *shaderName,
|
||||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
|
|
||||||
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
|
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
|
||||||
u32 verticesOut,
|
u32 verticesOut,
|
||||||
IShaderConstantSetCallBack *callback,
|
IShaderConstantSetCallBack *callback,
|
||||||
@ -1642,9 +1639,7 @@ s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32 result = this->addHighLevelShaderMaterial(
|
s32 result = this->addHighLevelShaderMaterial(
|
||||||
vs, vertexShaderEntryPointName, vsCompileTarget,
|
vs, ps, gs, shaderName,
|
||||||
ps, pixelShaderEntryPointName, psCompileTarget,
|
|
||||||
gs, geometryShaderEntryPointName, gsCompileTarget,
|
|
||||||
inType, outType, verticesOut,
|
inType, outType, verticesOut,
|
||||||
callback, baseMaterial, userData);
|
callback, baseMaterial, userData);
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include "S3DVertex.h"
|
#include "S3DVertex.h"
|
||||||
#include "SVertexIndex.h"
|
#include "SVertexIndex.h"
|
||||||
#include "SExposedVideoData.h"
|
#include "SExposedVideoData.h"
|
||||||
#include <list>
|
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
@ -293,7 +292,7 @@ protected:
|
|||||||
struct SHWBufferLink
|
struct SHWBufferLink
|
||||||
{
|
{
|
||||||
SHWBufferLink(const scene::IVertexBuffer *vb) :
|
SHWBufferLink(const scene::IVertexBuffer *vb) :
|
||||||
VertexBuffer(vb), ChangedID(0), IsVertex(true)
|
VertexBuffer(vb), IsVertex(true)
|
||||||
{
|
{
|
||||||
if (VertexBuffer) {
|
if (VertexBuffer) {
|
||||||
VertexBuffer->grab();
|
VertexBuffer->grab();
|
||||||
@ -301,7 +300,7 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
SHWBufferLink(const scene::IIndexBuffer *ib) :
|
SHWBufferLink(const scene::IIndexBuffer *ib) :
|
||||||
IndexBuffer(ib), ChangedID(0), IsVertex(false)
|
IndexBuffer(ib), IsVertex(false)
|
||||||
{
|
{
|
||||||
if (IndexBuffer) {
|
if (IndexBuffer) {
|
||||||
IndexBuffer->grab();
|
IndexBuffer->grab();
|
||||||
@ -324,9 +323,9 @@ protected:
|
|||||||
const scene::IVertexBuffer *VertexBuffer;
|
const scene::IVertexBuffer *VertexBuffer;
|
||||||
const scene::IIndexBuffer *IndexBuffer;
|
const scene::IIndexBuffer *IndexBuffer;
|
||||||
};
|
};
|
||||||
u32 ChangedID;
|
size_t ListPosition = static_cast<size_t>(-1);
|
||||||
|
u32 ChangedID = 0;
|
||||||
bool IsVertex;
|
bool IsVertex;
|
||||||
std::list<SHWBufferLink*>::iterator listPosition;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Gets hardware buffer link from a vertex buffer (may create or update buffer)
|
//! Gets hardware buffer link from a vertex buffer (may create or update buffer)
|
||||||
@ -361,8 +360,8 @@ public:
|
|||||||
//! Remove all hardware buffers
|
//! Remove all hardware buffers
|
||||||
void removeAllHardwareBuffers() override;
|
void removeAllHardwareBuffers() override;
|
||||||
|
|
||||||
//! Update all hardware buffers, remove unused ones
|
//! Run garbage-collection on all HW buffers
|
||||||
virtual void updateAllHardwareBuffers();
|
void expireHardwareBuffers();
|
||||||
|
|
||||||
//! is vbo recommended?
|
//! is vbo recommended?
|
||||||
virtual bool isHardwareBufferRecommend(const scene::IVertexBuffer *mb);
|
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.
|
//! Adds a new material renderer to the VideoDriver, based on a high level shading language.
|
||||||
virtual s32 addHighLevelShaderMaterial(
|
virtual s32 addHighLevelShaderMaterial(
|
||||||
const c8 *vertexShaderProgram,
|
const c8 *vertexShaderProgram,
|
||||||
const c8 *vertexShaderEntryPointName = 0,
|
const c8 *pixelShaderProgram,
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1,
|
const c8 *geometryShaderProgram,
|
||||||
const c8 *pixelShaderProgram = 0,
|
const c8 *shaderName = nullptr,
|
||||||
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,
|
|
||||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||||
u32 verticesOut = 0,
|
u32 verticesOut = 0,
|
||||||
IShaderConstantSetCallBack *callback = 0,
|
IShaderConstantSetCallBack *callback = nullptr,
|
||||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||||
s32 userData = 0) override;
|
s32 userData = 0)override;
|
||||||
|
|
||||||
virtual s32 addHighLevelShaderMaterialFromFiles(
|
virtual s32 addHighLevelShaderMaterialFromFiles(
|
||||||
const io::path &vertexShaderProgramFile,
|
const io::path &vertexShaderProgramFileName,
|
||||||
const c8 *vertexShaderEntryPointName = "main",
|
const io::path &pixelShaderProgramFileName,
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1,
|
const io::path &geometryShaderProgramFileName,
|
||||||
const io::path &pixelShaderProgramFile = "",
|
const c8 *shaderName = nullptr,
|
||||||
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,
|
|
||||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||||
u32 verticesOut = 0,
|
u32 verticesOut = 0,
|
||||||
IShaderConstantSetCallBack *callback = 0,
|
IShaderConstantSetCallBack *callback = nullptr,
|
||||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||||
s32 userData = 0) override;
|
s32 userData = 0) override;
|
||||||
|
|
||||||
virtual s32 addHighLevelShaderMaterialFromFiles(
|
s32 addHighLevelShaderMaterialFromFiles(
|
||||||
io::IReadFile *vertexShaderProgram,
|
io::IReadFile *vertexShaderProgram,
|
||||||
const c8 *vertexShaderEntryPointName = "main",
|
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1,
|
|
||||||
io::IReadFile *pixelShaderProgram = 0,
|
io::IReadFile *pixelShaderProgram = 0,
|
||||||
const c8 *pixelShaderEntryPointName = "main",
|
|
||||||
E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1,
|
|
||||||
io::IReadFile *geometryShaderProgram = 0,
|
io::IReadFile *geometryShaderProgram = 0,
|
||||||
const c8 *geometryShaderEntryPointName = "main",
|
const c8 *shaderName = nullptr,
|
||||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
|
||||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||||
u32 verticesOut = 0,
|
u32 verticesOut = 0,
|
||||||
IShaderConstantSetCallBack *callback = 0,
|
IShaderConstantSetCallBack *callback = nullptr,
|
||||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||||
s32 userData = 0) override;
|
s32 userData = 0);
|
||||||
|
|
||||||
virtual void deleteShaderMaterial(s32 material) override;
|
virtual void deleteShaderMaterial(s32 material) override;
|
||||||
|
|
||||||
@ -582,13 +566,16 @@ protected:
|
|||||||
//! deletes all material renderers
|
//! deletes all material renderers
|
||||||
void deleteMaterialRenders();
|
void deleteMaterialRenders();
|
||||||
|
|
||||||
|
// adds a created hardware buffer to the relevant data structure
|
||||||
|
void registerHardwareBuffer(SHWBufferLink *HWBuffer);
|
||||||
|
|
||||||
// prints renderer version
|
// prints renderer version
|
||||||
void printVersion();
|
void printVersion();
|
||||||
|
|
||||||
inline void accountHWBufferUpload(u32 size)
|
inline void accountHWBufferUpload(u32 size)
|
||||||
{
|
{
|
||||||
FrameStats.HWBuffersUploaded++;
|
FrameStats.HWBuffersUploaded++;
|
||||||
FrameStats.HWBuffersUploadedSize += size;
|
(void)size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool getWriteZBuffer(const SMaterial &material) const
|
inline bool getWriteZBuffer(const SMaterial &material) const
|
||||||
@ -705,7 +692,7 @@ protected:
|
|||||||
core::array<video::IImageWriter *> SurfaceWriter;
|
core::array<video::IImageWriter *> SurfaceWriter;
|
||||||
core::array<SMaterialRenderer> MaterialRenderers;
|
core::array<SMaterialRenderer> MaterialRenderers;
|
||||||
|
|
||||||
std::list<SHWBufferLink *> HWBufferList;
|
std::vector<SHWBufferLink *> HWBufferList;
|
||||||
|
|
||||||
io::IFileSystem *FileSystem;
|
io::IFileSystem *FileSystem;
|
||||||
|
|
||||||
|
@ -430,9 +430,7 @@ COpenGLDriver::SHWBufferLink *COpenGLDriver::createHardwareBuffer(const scene::I
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(vb);
|
SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(vb);
|
||||||
|
registerHardwareBuffer(HWBuffer);
|
||||||
// add to map
|
|
||||||
HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer);
|
|
||||||
|
|
||||||
if (!updateVertexHardwareBuffer(HWBuffer)) {
|
if (!updateVertexHardwareBuffer(HWBuffer)) {
|
||||||
deleteHardwareBuffer(HWBuffer);
|
deleteHardwareBuffer(HWBuffer);
|
||||||
@ -453,9 +451,7 @@ COpenGLDriver::SHWBufferLink *COpenGLDriver::createHardwareBuffer(const scene::I
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(ib);
|
SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(ib);
|
||||||
|
registerHardwareBuffer(HWBuffer);
|
||||||
// add to map
|
|
||||||
HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer);
|
|
||||||
|
|
||||||
if (!updateIndexHardwareBuffer(HWBuffer)) {
|
if (!updateIndexHardwareBuffer(HWBuffer)) {
|
||||||
deleteHardwareBuffer(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.
|
//! Adds a new material renderer to the VideoDriver, using GLSL to render geometry.
|
||||||
s32 COpenGLDriver::addHighLevelShaderMaterial(
|
s32 COpenGLDriver::addHighLevelShaderMaterial(
|
||||||
const c8 *vertexShaderProgram,
|
const c8 *vertexShaderProgram,
|
||||||
const c8 *vertexShaderEntryPointName,
|
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
|
||||||
const c8 *pixelShaderProgram,
|
const c8 *pixelShaderProgram,
|
||||||
const c8 *pixelShaderEntryPointName,
|
|
||||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
|
||||||
const c8 *geometryShaderProgram,
|
const c8 *geometryShaderProgram,
|
||||||
const c8 *geometryShaderEntryPointName,
|
const c8 *shaderName,
|
||||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
|
|
||||||
scene::E_PRIMITIVE_TYPE inType,
|
scene::E_PRIMITIVE_TYPE inType,
|
||||||
scene::E_PRIMITIVE_TYPE outType,
|
scene::E_PRIMITIVE_TYPE outType,
|
||||||
u32 verticesOut,
|
u32 verticesOut,
|
||||||
@ -2677,9 +2668,9 @@ s32 COpenGLDriver::addHighLevelShaderMaterial(
|
|||||||
|
|
||||||
COpenGLSLMaterialRenderer *r = new COpenGLSLMaterialRenderer(
|
COpenGLSLMaterialRenderer *r = new COpenGLSLMaterialRenderer(
|
||||||
this, nr,
|
this, nr,
|
||||||
vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget,
|
vertexShaderProgram,
|
||||||
pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget,
|
pixelShaderProgram,
|
||||||
geometryShaderProgram, geometryShaderEntryPointName, gsCompileTarget,
|
geometryShaderProgram,
|
||||||
inType, outType, verticesOut,
|
inType, outType, verticesOut,
|
||||||
callback, baseMaterial, userData);
|
callback, baseMaterial, userData);
|
||||||
|
|
||||||
|
@ -240,18 +240,13 @@ public:
|
|||||||
//! Adds a new material renderer to the VideoDriver, using GLSL to render geometry.
|
//! Adds a new material renderer to the VideoDriver, using GLSL to render geometry.
|
||||||
virtual s32 addHighLevelShaderMaterial(
|
virtual s32 addHighLevelShaderMaterial(
|
||||||
const c8 *vertexShaderProgram,
|
const c8 *vertexShaderProgram,
|
||||||
const c8 *vertexShaderEntryPointName,
|
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
|
||||||
const c8 *pixelShaderProgram,
|
const c8 *pixelShaderProgram,
|
||||||
const c8 *pixelShaderEntryPointName,
|
|
||||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
|
||||||
const c8 *geometryShaderProgram,
|
const c8 *geometryShaderProgram,
|
||||||
const c8 *geometryShaderEntryPointName = "main",
|
const c8 *shaderName = nullptr,
|
||||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
|
||||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||||
u32 verticesOut = 0,
|
u32 verticesOut = 0,
|
||||||
IShaderConstantSetCallBack *callback = 0,
|
IShaderConstantSetCallBack *callback = nullptr,
|
||||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||||
s32 userData = 0) override;
|
s32 userData = 0) override;
|
||||||
|
|
||||||
|
@ -34,14 +34,8 @@ namespace video
|
|||||||
//! Constructor
|
//! Constructor
|
||||||
COpenGLSLMaterialRenderer::COpenGLSLMaterialRenderer(video::COpenGLDriver *driver,
|
COpenGLSLMaterialRenderer::COpenGLSLMaterialRenderer(video::COpenGLDriver *driver,
|
||||||
s32 &outMaterialTypeNr, const c8 *vertexShaderProgram,
|
s32 &outMaterialTypeNr, const c8 *vertexShaderProgram,
|
||||||
const c8 *vertexShaderEntryPointName,
|
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
|
||||||
const c8 *pixelShaderProgram,
|
const c8 *pixelShaderProgram,
|
||||||
const c8 *pixelShaderEntryPointName,
|
|
||||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
|
||||||
const c8 *geometryShaderProgram,
|
const c8 *geometryShaderProgram,
|
||||||
const c8 *geometryShaderEntryPointName,
|
|
||||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
|
|
||||||
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
|
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
|
||||||
u32 verticesOut,
|
u32 verticesOut,
|
||||||
IShaderConstantSetCallBack *callback,
|
IShaderConstantSetCallBack *callback,
|
||||||
|
@ -33,14 +33,8 @@ public:
|
|||||||
COpenGLDriver *driver,
|
COpenGLDriver *driver,
|
||||||
s32 &outMaterialTypeNr,
|
s32 &outMaterialTypeNr,
|
||||||
const c8 *vertexShaderProgram = 0,
|
const c8 *vertexShaderProgram = 0,
|
||||||
const c8 *vertexShaderEntryPointName = 0,
|
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget = video::EVST_VS_1_1,
|
|
||||||
const c8 *pixelShaderProgram = 0,
|
const c8 *pixelShaderProgram = 0,
|
||||||
const c8 *pixelShaderEntryPointName = 0,
|
|
||||||
E_PIXEL_SHADER_TYPE psCompileTarget = video::EPST_PS_1_1,
|
|
||||||
const c8 *geometryShaderProgram = 0,
|
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 inType = scene::EPT_TRIANGLES,
|
||||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||||
u32 verticesOut = 0,
|
u32 verticesOut = 0,
|
||||||
|
@ -386,28 +386,28 @@ void COpenGL3DriverBase::createMaterialRenderers()
|
|||||||
|
|
||||||
// EMT_SOLID
|
// EMT_SOLID
|
||||||
core::stringc FragmentShader = OGLES2ShaderPath + "Solid.fsh";
|
core::stringc FragmentShader = OGLES2ShaderPath + "Solid.fsh";
|
||||||
addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",
|
addHighLevelShaderMaterialFromFiles(VertexShader, FragmentShader, "", "Solid",
|
||||||
EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, SolidCB, EMT_SOLID, 0);
|
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, SolidCB, EMT_SOLID, 0);
|
||||||
|
|
||||||
// EMT_TRANSPARENT_ALPHA_CHANNEL
|
// EMT_TRANSPARENT_ALPHA_CHANNEL
|
||||||
FragmentShader = OGLES2ShaderPath + "TransparentAlphaChannel.fsh";
|
FragmentShader = OGLES2ShaderPath + "TransparentAlphaChannel.fsh";
|
||||||
addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",
|
addHighLevelShaderMaterialFromFiles(VertexShader, FragmentShader, "", "TransparentAlphaChannel",
|
||||||
EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAlphaChannelCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);
|
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAlphaChannelCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);
|
||||||
|
|
||||||
// EMT_TRANSPARENT_ALPHA_CHANNEL_REF
|
// EMT_TRANSPARENT_ALPHA_CHANNEL_REF
|
||||||
FragmentShader = OGLES2ShaderPath + "TransparentAlphaChannelRef.fsh";
|
FragmentShader = OGLES2ShaderPath + "TransparentAlphaChannelRef.fsh";
|
||||||
addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",
|
addHighLevelShaderMaterialFromFiles(VertexShader, FragmentShader, "", "TransparentAlphaChannelRef",
|
||||||
EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAlphaChannelRefCB, EMT_SOLID, 0);
|
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAlphaChannelRefCB, EMT_SOLID, 0);
|
||||||
|
|
||||||
// EMT_TRANSPARENT_VERTEX_ALPHA
|
// EMT_TRANSPARENT_VERTEX_ALPHA
|
||||||
FragmentShader = OGLES2ShaderPath + "TransparentVertexAlpha.fsh";
|
FragmentShader = OGLES2ShaderPath + "TransparentVertexAlpha.fsh";
|
||||||
addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",
|
addHighLevelShaderMaterialFromFiles(VertexShader, FragmentShader, "", "TransparentVertexAlpha",
|
||||||
EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentVertexAlphaCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);
|
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentVertexAlphaCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);
|
||||||
|
|
||||||
// EMT_ONETEXTURE_BLEND
|
// EMT_ONETEXTURE_BLEND
|
||||||
FragmentShader = OGLES2ShaderPath + "OneTextureBlend.fsh";
|
FragmentShader = OGLES2ShaderPath + "OneTextureBlend.fsh";
|
||||||
addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",
|
addHighLevelShaderMaterialFromFiles(VertexShader, FragmentShader, "", "OneTextureBlend",
|
||||||
EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, OneTextureBlendCB, EMT_ONETEXTURE_BLEND, 0);
|
scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, OneTextureBlendCB, EMT_ONETEXTURE_BLEND, 0);
|
||||||
|
|
||||||
// Drop callbacks.
|
// Drop callbacks.
|
||||||
|
|
||||||
@ -566,10 +566,8 @@ COpenGL3DriverBase::SHWBufferLink *COpenGL3DriverBase::createHardwareBuffer(cons
|
|||||||
if (!vb || vb->getHardwareMappingHint() == scene::EHM_NEVER)
|
if (!vb || vb->getHardwareMappingHint() == scene::EHM_NEVER)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(vb);
|
auto *HWBuffer = new SHWBufferLink_opengl(vb);
|
||||||
|
registerHardwareBuffer(HWBuffer);
|
||||||
// add to map
|
|
||||||
HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer);
|
|
||||||
|
|
||||||
if (!updateVertexHardwareBuffer(HWBuffer)) {
|
if (!updateVertexHardwareBuffer(HWBuffer)) {
|
||||||
deleteHardwareBuffer(HWBuffer);
|
deleteHardwareBuffer(HWBuffer);
|
||||||
@ -584,10 +582,8 @@ COpenGL3DriverBase::SHWBufferLink *COpenGL3DriverBase::createHardwareBuffer(cons
|
|||||||
if (!ib || ib->getHardwareMappingHint() == scene::EHM_NEVER)
|
if (!ib || ib->getHardwareMappingHint() == scene::EHM_NEVER)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(ib);
|
auto *HWBuffer = new SHWBufferLink_opengl(ib);
|
||||||
|
registerHardwareBuffer(HWBuffer);
|
||||||
// add to map
|
|
||||||
HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer);
|
|
||||||
|
|
||||||
if (!updateIndexHardwareBuffer(HWBuffer)) {
|
if (!updateIndexHardwareBuffer(HWBuffer)) {
|
||||||
deleteHardwareBuffer(HWBuffer);
|
deleteHardwareBuffer(HWBuffer);
|
||||||
@ -1344,60 +1340,74 @@ void COpenGL3DriverBase::setTextureRenderStates(const SMaterial &material, bool
|
|||||||
|
|
||||||
CacheHandler->setActiveTexture(GL_TEXTURE0 + i);
|
CacheHandler->setActiveTexture(GL_TEXTURE0 + i);
|
||||||
|
|
||||||
if (resetAllRenderstates)
|
const auto &layer = material.TextureLayers[i];
|
||||||
tmpTexture->getStatesCache().IsCached = false;
|
auto &states = tmpTexture->getStatesCache();
|
||||||
|
|
||||||
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayers[i].MagFilter != tmpTexture->getStatesCache().MagFilter) {
|
if (resetAllRenderstates)
|
||||||
E_TEXTURE_MAG_FILTER magFilter = material.TextureLayers[i].MagFilter;
|
states.IsCached = false;
|
||||||
|
|
||||||
|
if (!states.IsCached || layer.MagFilter != states.MagFilter) {
|
||||||
|
E_TEXTURE_MAG_FILTER magFilter = layer.MagFilter;
|
||||||
GL.TexParameteri(tmpTextureType, GL_TEXTURE_MAG_FILTER,
|
GL.TexParameteri(tmpTextureType, GL_TEXTURE_MAG_FILTER,
|
||||||
magFilter == ETMAGF_NEAREST ? GL_NEAREST : (assert(magFilter == ETMAGF_LINEAR), GL_LINEAR));
|
magFilter == ETMAGF_NEAREST ? GL_NEAREST : (assert(magFilter == ETMAGF_LINEAR), GL_LINEAR));
|
||||||
|
|
||||||
tmpTexture->getStatesCache().MagFilter = magFilter;
|
states.MagFilter = magFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (material.UseMipMaps && tmpTexture->hasMipMaps()) {
|
if (material.UseMipMaps && tmpTexture->hasMipMaps()) {
|
||||||
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayers[i].MinFilter != tmpTexture->getStatesCache().MinFilter ||
|
if (!states.IsCached || layer.MinFilter != states.MinFilter ||
|
||||||
!tmpTexture->getStatesCache().MipMapStatus) {
|
!states.MipMapStatus) {
|
||||||
E_TEXTURE_MIN_FILTER minFilter = material.TextureLayers[i].MinFilter;
|
E_TEXTURE_MIN_FILTER minFilter = layer.MinFilter;
|
||||||
GL.TexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,
|
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_NEAREST ? GL_NEAREST_MIPMAP_NEAREST : minFilter == ETMINF_LINEAR_MIPMAP_NEAREST ? GL_LINEAR_MIPMAP_NEAREST
|
||||||
: minFilter == ETMINF_NEAREST_MIPMAP_LINEAR ? GL_NEAREST_MIPMAP_LINEAR
|
: minFilter == ETMINF_NEAREST_MIPMAP_LINEAR ? GL_NEAREST_MIPMAP_LINEAR
|
||||||
: (assert(minFilter == ETMINF_LINEAR_MIPMAP_LINEAR), GL_LINEAR_MIPMAP_LINEAR));
|
: (assert(minFilter == ETMINF_LINEAR_MIPMAP_LINEAR), GL_LINEAR_MIPMAP_LINEAR));
|
||||||
|
|
||||||
tmpTexture->getStatesCache().MinFilter = minFilter;
|
states.MinFilter = minFilter;
|
||||||
tmpTexture->getStatesCache().MipMapStatus = true;
|
states.MipMapStatus = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayers[i].MinFilter != tmpTexture->getStatesCache().MinFilter ||
|
if (!states.IsCached || layer.MinFilter != states.MinFilter ||
|
||||||
tmpTexture->getStatesCache().MipMapStatus) {
|
states.MipMapStatus) {
|
||||||
E_TEXTURE_MIN_FILTER minFilter = material.TextureLayers[i].MinFilter;
|
E_TEXTURE_MIN_FILTER minFilter = layer.MinFilter;
|
||||||
GL.TexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,
|
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));
|
(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;
|
states.MinFilter = minFilter;
|
||||||
tmpTexture->getStatesCache().MipMapStatus = false;
|
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 &&
|
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,
|
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) {
|
if (!states.IsCached || layer.TextureWrapU != states.WrapU) {
|
||||||
GL.TexParameteri(tmpTextureType, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayers[i].TextureWrapU));
|
GL.TexParameteri(tmpTextureType, GL_TEXTURE_WRAP_S, getTextureWrapMode(layer.TextureWrapU));
|
||||||
tmpTexture->getStatesCache().WrapU = material.TextureLayers[i].TextureWrapU;
|
states.WrapU = layer.TextureWrapU;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayers[i].TextureWrapV != tmpTexture->getStatesCache().WrapV) {
|
if (!states.IsCached || layer.TextureWrapV != states.WrapV) {
|
||||||
GL.TexParameteri(tmpTextureType, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayers[i].TextureWrapV));
|
GL.TexParameteri(tmpTextureType, GL_TEXTURE_WRAP_T, getTextureWrapMode(layer.TextureWrapV));
|
||||||
tmpTexture->getStatesCache().WrapV = material.TextureLayers[i].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.
|
//! Adds a new material renderer to the VideoDriver, using GLSL to render geometry.
|
||||||
s32 COpenGL3DriverBase::addHighLevelShaderMaterial(
|
s32 COpenGL3DriverBase::addHighLevelShaderMaterial(
|
||||||
const c8 *vertexShaderProgram,
|
const c8 *vertexShaderProgram,
|
||||||
const c8 *vertexShaderEntryPointName,
|
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
|
||||||
const c8 *pixelShaderProgram,
|
const c8 *pixelShaderProgram,
|
||||||
const c8 *pixelShaderEntryPointName,
|
|
||||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
|
||||||
const c8 *geometryShaderProgram,
|
const c8 *geometryShaderProgram,
|
||||||
const c8 *geometryShaderEntryPointName,
|
const c8 *shaderName,
|
||||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
|
|
||||||
scene::E_PRIMITIVE_TYPE inType,
|
scene::E_PRIMITIVE_TYPE inType,
|
||||||
scene::E_PRIMITIVE_TYPE outType,
|
scene::E_PRIMITIVE_TYPE outType,
|
||||||
u32 verticesOut,
|
u32 verticesOut,
|
||||||
|
@ -189,18 +189,13 @@ public:
|
|||||||
//! Adds a new material renderer to the VideoDriver
|
//! Adds a new material renderer to the VideoDriver
|
||||||
virtual s32 addHighLevelShaderMaterial(
|
virtual s32 addHighLevelShaderMaterial(
|
||||||
const c8 *vertexShaderProgram,
|
const c8 *vertexShaderProgram,
|
||||||
const c8 *vertexShaderEntryPointName = 0,
|
const c8 *pixelShaderProgram,
|
||||||
E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1,
|
const c8 *geometryShaderProgram = nullptr,
|
||||||
const c8 *pixelShaderProgram = 0,
|
const c8 *shaderName = nullptr,
|
||||||
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,
|
|
||||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||||
u32 verticesOut = 0,
|
u32 verticesOut = 0,
|
||||||
IShaderConstantSetCallBack *callback = 0,
|
IShaderConstantSetCallBack *callback = nullptr,
|
||||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||||
s32 userData = 0) override;
|
s32 userData = 0) override;
|
||||||
|
|
||||||
|
@ -161,6 +161,7 @@ public:
|
|||||||
GL.BlendEquation(mode);
|
GL.BlendEquation(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LODBiasSupported = false;
|
||||||
bool AnisotropicFilterSupported = false;
|
bool AnisotropicFilterSupported = false;
|
||||||
bool BlendMinMaxSupported = false;
|
bool BlendMinMaxSupported = false;
|
||||||
bool TextureMultisampleSupported = 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};
|
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");
|
AnisotropicFilterSupported = isVersionAtLeast(4, 6) || queryExtension("GL_ARB_texture_filter_anisotropic") || queryExtension("GL_EXT_texture_filter_anisotropic");
|
||||||
|
LODBiasSupported = true;
|
||||||
BlendMinMaxSupported = true;
|
BlendMinMaxSupported = true;
|
||||||
TextureMultisampleSupported = true;
|
TextureMultisampleSupported = true;
|
||||||
|
|
||||||
|
@ -120,10 +120,10 @@ void COpenGLES2Driver::initFeatures()
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bool MRTSupported = Version.Major >= 3 || queryExtension("GL_EXT_draw_buffers");
|
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");
|
AnisotropicFilterSupported = queryExtension("GL_EXT_texture_filter_anisotropic");
|
||||||
BlendMinMaxSupported = (Version.Major >= 3) || FeatureAvailable[IRR_GL_EXT_blend_minmax];
|
BlendMinMaxSupported = (Version.Major >= 3) || FeatureAvailable[IRR_GL_EXT_blend_minmax];
|
||||||
TextureMultisampleSupported = isVersionAtLeast(3, 1);
|
TextureMultisampleSupported = isVersionAtLeast(3, 1);
|
||||||
const bool TextureLODBiasSupported = queryExtension("GL_EXT_texture_lod_bias");
|
|
||||||
|
|
||||||
// COGLESCoreExtensionHandler::Feature
|
// COGLESCoreExtensionHandler::Feature
|
||||||
static_assert(MATERIAL_MAX_TEXTURES <= 8, "Only up to 8 textures are guaranteed");
|
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"))
|
if (Version.Major >= 3 || queryExtension("GL_EXT_draw_range_elements"))
|
||||||
MaxIndices = GetInteger(GL_MAX_ELEMENTS_INDICES);
|
MaxIndices = GetInteger(GL_MAX_ELEMENTS_INDICES);
|
||||||
MaxTextureSize = GetInteger(GL_MAX_TEXTURE_SIZE);
|
MaxTextureSize = GetInteger(GL_MAX_TEXTURE_SIZE);
|
||||||
if (TextureLODBiasSupported)
|
if (LODBiasSupported)
|
||||||
GL.GetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &MaxTextureLODBias);
|
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_LINE_WIDTH_RANGE, DimAliasedLine); // NOTE: this is not in the OpenGL ES 2.0 spec...
|
||||||
GL.GetFloatv(GL_ALIASED_POINT_SIZE_RANGE, DimAliasedPoint);
|
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)
|
if (stats2.Drawcalls > 0)
|
||||||
g_profiler->avg("Irr: primitives per drawcall",
|
g_profiler->avg("Irr: primitives per drawcall",
|
||||||
stats2.PrimitivesDrawn / float(stats2.Drawcalls));
|
stats2.PrimitivesDrawn / float(stats2.Drawcalls));
|
||||||
g_profiler->avg("Irr: buffers uploaded", stats2.HWBuffersUploaded);
|
g_profiler->avg("Irr: HW buffers uploaded", stats2.HWBuffersUploaded);
|
||||||
g_profiler->avg("Irr: buffers uploaded (bytes)", stats2.HWBuffersUploadedSize);
|
g_profiler->avg("Irr: HW buffers active", stats2.HWBuffersActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::updateStats(RunStats *stats, const FpsControl &draw_times,
|
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))
|
if (m_mode == HIGHLIGHT_NONE || (m_mode == HIGHLIGHT_HALO && !m_selection_mesh))
|
||||||
return;
|
return;
|
||||||
const video::SMaterial oldmaterial = driver->getMaterial2D();
|
|
||||||
driver->setMaterial(m_selection_material);
|
driver->setMaterial(m_selection_material);
|
||||||
const core::matrix4 oldtransform = driver->getTransform(video::ETS_WORLD);
|
const core::matrix4 oldtransform = driver->getTransform(video::ETS_WORLD);
|
||||||
|
|
||||||
@ -910,7 +909,6 @@ void Hud::drawSelectionMesh()
|
|||||||
driver->drawMeshBuffer(buf);
|
driver->drawMeshBuffer(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
driver->setMaterial(oldmaterial);
|
|
||||||
driver->setTransform(video::ETS_WORLD, oldtransform);
|
driver->setTransform(video::ETS_WORLD, oldtransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -935,17 +933,11 @@ void Hud::drawBlockBounds()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
video::SMaterial old_material = driver->getMaterial2D();
|
|
||||||
driver->setMaterial(m_block_bounds_material);
|
driver->setMaterial(m_block_bounds_material);
|
||||||
|
|
||||||
u16 mesh_chunk_size = std::max<u16>(1, g_settings->getU16("client_mesh_chunk"));
|
u16 mesh_chunk_size = std::max<u16>(1, g_settings->getU16("client_mesh_chunk"));
|
||||||
|
|
||||||
v3s16 pos = player->getStandingNodePos();
|
v3s16 block_pos = getContainerPos(player->getStandingNodePos(), MAP_BLOCKSIZE);
|
||||||
v3s16 block_pos(
|
|
||||||
floorf((float) pos.X / MAP_BLOCKSIZE),
|
|
||||||
floorf((float) pos.Y / MAP_BLOCKSIZE),
|
|
||||||
floorf((float) pos.Z / MAP_BLOCKSIZE)
|
|
||||||
);
|
|
||||||
|
|
||||||
v3f cam_offset = intToFloat(client->getCamera()->getOffset(), BS);
|
v3f cam_offset = intToFloat(client->getCamera()->getOffset(), BS);
|
||||||
|
|
||||||
@ -988,8 +980,6 @@ void Hud::drawBlockBounds()
|
|||||||
choose_color(block_pos.Y, block_pos.Z)
|
choose_color(block_pos.Y, block_pos.Z)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
driver->setMaterial(old_material);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hud::updateSelectionMesh(const v3s16 &camera_offset)
|
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)
|
void imageCleanTransparent(video::IImage *src, u32 threshold)
|
||||||
{
|
{
|
||||||
if (src->getColorFormat() == video::ECF_A8R8G8B8)
|
if (src->getColorFormat() == video::ECF_A8R8G8B8)
|
||||||
@ -167,13 +156,109 @@ void imageCleanTransparent(video::IImage *src, u32 threshold)
|
|||||||
imageCleanTransparentWithInlining<false>(src, 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
|
namespace {
|
||||||
* some blending at the edges where pixels don't line up perfectly, but this
|
// For more colorspace transformations, see for example
|
||||||
* filter is designed to produce the most accurate results for both upscaling
|
// <https://github.com/tobspr/GLSL-Color-Spaces/blob/master/ColorSpaces.inc.glsl>
|
||||||
* and downscaling.
|
|
||||||
*/
|
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)
|
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;
|
double sx, sy, minsx, maxsx, minsy, maxsy, area, ra, ga, ba, aa, pw, ph, pa;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
#include <rect.h>
|
#include <rect.h>
|
||||||
|
#include <SColor.h>
|
||||||
|
|
||||||
namespace irr::video
|
namespace irr::video
|
||||||
{
|
{
|
||||||
@ -26,6 +27,10 @@ namespace irr::video
|
|||||||
*/
|
*/
|
||||||
void imageCleanTransparent(video::IImage *src, u32 threshold);
|
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
|
/* 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
|
* anti-aliasing; treat pixels as crisp rectangles, but blend them at boundaries
|
||||||
* to prevent non-integer scaling ratio artifacts. Note that this may cause
|
* 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
|
assert(img); // Pre-condition
|
||||||
// Remove old image
|
// Remove old image
|
||||||
std::map<std::string, video::IImage*>::iterator n;
|
auto n = m_images.find(name);
|
||||||
n = m_images.find(name);
|
|
||||||
if (n != m_images.end()){
|
if (n != m_images.end()){
|
||||||
if (n->second)
|
if (n->second)
|
||||||
n->second->drop();
|
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)
|
video::IImage* SourceImageCache::get(const std::string &name)
|
||||||
{
|
{
|
||||||
std::map<std::string, video::IImage*>::iterator n;
|
auto n = m_images.find(name);
|
||||||
n = m_images.find(name);
|
|
||||||
if (n != m_images.end())
|
if (n != m_images.end())
|
||||||
return n->second;
|
return n->second;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -73,8 +71,7 @@ video::IImage* SourceImageCache::get(const std::string &name)
|
|||||||
// Primarily fetches from cache, secondarily tries to read from filesystem
|
// Primarily fetches from cache, secondarily tries to read from filesystem
|
||||||
video::IImage* SourceImageCache::getOrLoad(const std::string &name)
|
video::IImage* SourceImageCache::getOrLoad(const std::string &name)
|
||||||
{
|
{
|
||||||
std::map<std::string, video::IImage*>::iterator n;
|
auto n = m_images.find(name);
|
||||||
n = m_images.find(name);
|
|
||||||
if (n != m_images.end()){
|
if (n != m_images.end()){
|
||||||
n->second->grab(); // Grab for caller
|
n->second->grab(); // Grab for caller
|
||||||
return n->second;
|
return n->second;
|
||||||
@ -166,13 +163,13 @@ static void draw_crack(video::IImage *crack, video::IImage *dst,
|
|||||||
video::IVideoDriver *driver, u8 tiles = 1);
|
video::IVideoDriver *driver, u8 tiles = 1);
|
||||||
|
|
||||||
// Brighten image
|
// Brighten image
|
||||||
void brighten(video::IImage *image);
|
static void brighten(video::IImage *image);
|
||||||
// Parse a transform name
|
// Parse a transform name
|
||||||
u32 parseImageTransform(std::string_view s);
|
static u32 parseImageTransform(std::string_view s);
|
||||||
// Apply transform to image dimension
|
// 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
|
// 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)
|
inline static void applyShadeFactor(video::SColor &color, u32 factor)
|
||||||
{
|
{
|
||||||
@ -289,7 +286,7 @@ static video::IImage *createInventoryCubeImage(
|
|||||||
return result;
|
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;
|
std::string out;
|
||||||
size_t pos = 0, cpos;
|
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);
|
out += str.substr(pos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
out += str.substr(pos, cpos - pos) + str[cpos + 1];
|
out += str.substr(pos, cpos - pos);
|
||||||
|
out += str[cpos + 1];
|
||||||
pos = cpos + 2;
|
pos = cpos + 2;
|
||||||
}
|
}
|
||||||
return out;
|
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
|
Ensure no other references to these images are being held, as one may
|
||||||
get dropped and switched with a new image.
|
get dropped and switched with a new image.
|
||||||
*/
|
*/
|
||||||
void upscaleImagesToMatchLargest(video::IImage *& img1,
|
static void upscaleImagesToMatchLargest(video::IImage *& img1,
|
||||||
video::IImage *& img2)
|
video::IImage *& img2)
|
||||||
{
|
{
|
||||||
core::dimension2d<u32> dim1 = img1->getDimension();
|
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;
|
//infostream<<"Blitting "<<part_of_name<<" on base"<<std::endl;
|
||||||
upscaleImagesToMatchLargest(dst, src);
|
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);
|
dst_col.set(dst_a, dst.r, dst.g, dst.b);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace (anonymous)
|
||||||
|
|
||||||
template<bool overlay>
|
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)
|
v2u32 size)
|
||||||
{
|
{
|
||||||
if (dst->getColorFormat() != video::ECF_A8R8G8B8)
|
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::IVideoDriver *driver = RenderingEngine::get_video_driver();
|
||||||
video::IImage *src_converted = driver->createImage(video::ECF_A8R8G8B8,
|
video::IImage *src_converted = driver->createImage(video::ECF_A8R8G8B8,
|
||||||
src_dim);
|
src_dim);
|
||||||
if (!src_converted)
|
sanity_check(src_converted != nullptr);
|
||||||
throw BaseException("blit_with_alpha() failed to convert the "
|
|
||||||
"source image to ECF_A8R8G8B8.");
|
|
||||||
src->copyTo(src_converted);
|
src->copyTo(src_converted);
|
||||||
src = src_converted;
|
src = src_converted;
|
||||||
drop_src = true;
|
drop_src = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
video::SColor *pixels_src =
|
video::SColor *pixels_src =
|
||||||
reinterpret_cast<video::SColor *>(src->getData());
|
reinterpret_cast<video::SColor *>(src->getData());
|
||||||
video::SColor *pixels_dst =
|
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++]);
|
blit_pixel<overlay>(pixels_src[i_src++], pixels_dst[i_dst++]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drop_src)
|
if (drop_src)
|
||||||
src->drop();
|
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> size, u8 tiles, video::IVideoDriver *driver)
|
||||||
{
|
{
|
||||||
core::dimension2d<u32> strip_size = crack->getDimension();
|
core::dimension2d<u32> strip_size = crack->getDimension();
|
||||||
@ -804,7 +803,7 @@ static void draw_crack(video::IImage *crack, video::IImage *dst,
|
|||||||
crack_scaled->drop();
|
crack_scaled->drop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void brighten(video::IImage *image)
|
static void brighten(video::IImage *image)
|
||||||
{
|
{
|
||||||
if (image == NULL)
|
if (image == NULL)
|
||||||
return;
|
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;
|
int total_transform = 0;
|
||||||
|
|
||||||
@ -872,15 +871,15 @@ u32 parseImageTransform(std::string_view s)
|
|||||||
return total_transform;
|
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)
|
if (transform % 2 == 0)
|
||||||
return dim;
|
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)
|
if (src == NULL || dst == NULL)
|
||||||
return;
|
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 //
|
// ImageSource Functions //
|
||||||
@ -1017,18 +974,12 @@ bool ImageSource::generateImagePart(std::string_view part_of_name,
|
|||||||
std::string part_s(part_of_name);
|
std::string part_s(part_of_name);
|
||||||
source_image_names.insert(part_s);
|
source_image_names.insert(part_s);
|
||||||
video::IImage *image = m_sourcecache.getOrLoad(part_s);
|
video::IImage *image = m_sourcecache.getOrLoad(part_s);
|
||||||
|
|
||||||
if (!image) {
|
if (!image) {
|
||||||
// Do not create the dummy texture
|
// Do not create the dummy texture
|
||||||
if (part_of_name.empty())
|
if (part_of_name.empty())
|
||||||
return true;
|
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 \""
|
errorstream << "generateImagePart(): Could not load image \""
|
||||||
<< part_of_name << "\" while building texture; "
|
<< part_of_name << "\" while building texture; "
|
||||||
"Creating a dummy image" << std::endl;
|
"Creating a dummy image" << std::endl;
|
||||||
@ -1040,16 +991,15 @@ bool ImageSource::generateImagePart(std::string_view part_of_name,
|
|||||||
myrand()%256,myrand()%256));
|
myrand()%256,myrand()%256));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If base image is NULL, load as base.
|
// load as base or blit
|
||||||
if (baseimg == NULL)
|
if (!baseimg)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Copy it this way to get an alpha channel.
|
Copy it this way to get an alpha channel.
|
||||||
Otherwise images with alpha cannot be blitted on
|
Otherwise images with alpha cannot be blitted on
|
||||||
images that don't have alpha in the original file.
|
images that don't have alpha in the original file.
|
||||||
*/
|
*/
|
||||||
core::dimension2d<u32> dim = image->getDimension();
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, image->getDimension());
|
||||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
|
||||||
image->copyTo(baseimg);
|
image->copyTo(baseimg);
|
||||||
}
|
}
|
||||||
// Else blit on base.
|
// Else blit on base.
|
||||||
@ -1705,14 +1655,17 @@ bool ImageSource::generateImagePart(std::string_view part_of_name,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// blit or use as base
|
||||||
if (baseimg) {
|
if (baseimg) {
|
||||||
blitBaseImage(pngimg, baseimg);
|
blitBaseImage(pngimg, baseimg);
|
||||||
} else {
|
pngimg->drop();
|
||||||
core::dimension2d<u32> dim = pngimg->getDimension();
|
} else if (pngimg->getColorFormat() != video::ECF_A8R8G8B8) {
|
||||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, pngimg->getDimension());
|
||||||
pngimg->copyTo(baseimg);
|
pngimg->copyTo(baseimg);
|
||||||
|
pngimg->drop();
|
||||||
|
} else {
|
||||||
|
baseimg = pngimg;
|
||||||
}
|
}
|
||||||
pngimg->drop();
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
[hsl:hue:saturation:lightness
|
[hsl:hue:saturation:lightness
|
||||||
@ -1945,32 +1898,7 @@ video::IImage* ImageSource::generateImage(std::string_view name,
|
|||||||
return baseimg;
|
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);
|
m_sourcecache.insert(name, img, prefer_local);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <IImage.h>
|
#include <IImage.h>
|
||||||
#include <map>
|
#include <unordered_map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ public:
|
|||||||
// Primarily fetches from cache, secondarily tries to read from filesystem.
|
// Primarily fetches from cache, secondarily tries to read from filesystem.
|
||||||
video::IImage *getOrLoad(const std::string &name);
|
video::IImage *getOrLoad(const std::string &name);
|
||||||
private:
|
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.
|
// 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.
|
// Insert a source image into the cache without touching the filesystem.
|
||||||
void insertSourceImage(const std::string &name, video::IImage *img, bool prefer_local);
|
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:
|
private:
|
||||||
|
|
||||||
// Generate image based on a string like "stone.png" or "[crack:1:0".
|
// Generate image based on a string like "stone.png" or "[crack:1:0".
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include <IMaterialRendererServices.h>
|
#include <IMaterialRendererServices.h>
|
||||||
#include <IShaderConstantSetCallBack.h>
|
#include <IShaderConstantSetCallBack.h>
|
||||||
#include "client/renderingengine.h"
|
#include "client/renderingengine.h"
|
||||||
#include <EShaderTypes.h>
|
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "gamedef.h"
|
#include "gamedef.h"
|
||||||
@ -615,10 +614,16 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
|
|||||||
#define textureFlags texture2
|
#define textureFlags texture2
|
||||||
)";
|
)";
|
||||||
|
|
||||||
|
/// Unique name of this shader, for debug/logging
|
||||||
|
std::string log_name = name;
|
||||||
|
|
||||||
/* Define constants for node and object shaders */
|
/* Define constants for node and object shaders */
|
||||||
const bool node_shader = drawtype != NodeDrawType_END;
|
const bool node_shader = drawtype != NodeDrawType_END;
|
||||||
if (node_shader) {
|
if (node_shader) {
|
||||||
|
|
||||||
|
log_name.append(" mat=").append(itos(material_type))
|
||||||
|
.append(" draw=").append(itos(drawtype));
|
||||||
|
|
||||||
bool use_discard = fully_programmable;
|
bool use_discard = fully_programmable;
|
||||||
if (!use_discard) {
|
if (!use_discard) {
|
||||||
// workaround for a certain OpenGL implementation lacking GL_ALPHA_TEST
|
// 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();
|
geometry_shader_ptr = geometry_shader.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
irr_ptr<ShaderCallback> cb{new ShaderCallback(m_setter_factories)};
|
auto cb = make_irr<ShaderCallback>(m_setter_factories);
|
||||||
infostream<<"Compiling high level shaders for "<<name<<std::endl;
|
infostream << "Compiling high level shaders for " << log_name << std::endl;
|
||||||
s32 shadermat = gpu->addHighLevelShaderMaterial(
|
s32 shadermat = gpu->addHighLevelShaderMaterial(
|
||||||
vertex_shader.c_str(), nullptr, video::EVST_VS_1_1,
|
vertex_shader.c_str(), fragment_shader.c_str(), geometry_shader_ptr,
|
||||||
fragment_shader.c_str(), nullptr, video::EPST_PS_1_1,
|
log_name.c_str(), scene::EPT_TRIANGLES, scene::EPT_TRIANGLES, 0,
|
||||||
geometry_shader_ptr, nullptr, video::EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLES, 0,
|
cb.get(), shaderinfo.base_material);
|
||||||
cb.get(), shaderinfo.base_material, 1);
|
|
||||||
if (shadermat == -1) {
|
if (shadermat == -1) {
|
||||||
errorstream<<"generate_shader(): "
|
errorstream << "generateShader(): failed to generate shaders for "
|
||||||
"failed to generate \""<<name<<"\", "
|
<< log_name << ", addHighLevelShaderMaterial failed." << std::endl;
|
||||||
"addHighLevelShaderMaterial failed."
|
|
||||||
<<std::endl;
|
|
||||||
dumpShaderProgram(warningstream, "Vertex", vertex_shader);
|
dumpShaderProgram(warningstream, "Vertex", vertex_shader);
|
||||||
dumpShaderProgram(warningstream, "Fragment", fragment_shader);
|
dumpShaderProgram(warningstream, "Fragment", fragment_shader);
|
||||||
dumpShaderProgram(warningstream, "Geometry", geometry_shader);
|
dumpShaderProgram(warningstream, "Geometry", geometry_shader);
|
||||||
|
@ -14,10 +14,9 @@
|
|||||||
#include "client/client.h"
|
#include "client/client.h"
|
||||||
#include "client/clientmap.h"
|
#include "client/clientmap.h"
|
||||||
#include "profiler.h"
|
#include "profiler.h"
|
||||||
#include "EShaderTypes.h"
|
|
||||||
#include "IGPUProgrammingServices.h"
|
#include "IGPUProgrammingServices.h"
|
||||||
#include "IMaterialRenderer.h"
|
#include "IMaterialRenderer.h"
|
||||||
#include <IVideoDriver.h>
|
#include "IVideoDriver.h"
|
||||||
|
|
||||||
ShadowRenderer::ShadowRenderer(IrrlichtDevice *device, Client *client) :
|
ShadowRenderer::ShadowRenderer(IrrlichtDevice *device, Client *client) :
|
||||||
m_smgr(device->getSceneManager()), m_driver(device->getVideoDriver()),
|
m_smgr(device->getSceneManager()), m_driver(device->getVideoDriver()),
|
||||||
@ -539,10 +538,9 @@ void ShadowRenderer::createShaders()
|
|||||||
m_shadow_depth_cb = new ShadowDepthShaderCB();
|
m_shadow_depth_cb = new ShadowDepthShaderCB();
|
||||||
|
|
||||||
depth_shader = gpu->addHighLevelShaderMaterial(
|
depth_shader = gpu->addHighLevelShaderMaterial(
|
||||||
readShaderFile(depth_shader_vs).c_str(), "vertexMain",
|
readShaderFile(depth_shader_vs).c_str(),
|
||||||
video::EVST_VS_1_1,
|
readShaderFile(depth_shader_fs).c_str(), nullptr,
|
||||||
readShaderFile(depth_shader_fs).c_str(), "pixelMain",
|
m_shadow_depth_cb, video::EMT_ONETEXTURE_BLEND);
|
||||||
video::EPST_PS_1_2, m_shadow_depth_cb, video::EMT_ONETEXTURE_BLEND);
|
|
||||||
|
|
||||||
if (depth_shader == -1) {
|
if (depth_shader == -1) {
|
||||||
// upsi, something went wrong loading shader.
|
// upsi, something went wrong loading shader.
|
||||||
@ -578,10 +576,9 @@ void ShadowRenderer::createShaders()
|
|||||||
m_shadow_depth_entity_cb = new ShadowDepthShaderCB();
|
m_shadow_depth_entity_cb = new ShadowDepthShaderCB();
|
||||||
|
|
||||||
depth_shader_entities = gpu->addHighLevelShaderMaterial(
|
depth_shader_entities = gpu->addHighLevelShaderMaterial(
|
||||||
readShaderFile(depth_shader_vs).c_str(), "vertexMain",
|
readShaderFile(depth_shader_vs).c_str(),
|
||||||
video::EVST_VS_1_1,
|
readShaderFile(depth_shader_fs).c_str(), nullptr,
|
||||||
readShaderFile(depth_shader_fs).c_str(), "pixelMain",
|
m_shadow_depth_entity_cb);
|
||||||
video::EPST_PS_1_2, m_shadow_depth_entity_cb);
|
|
||||||
|
|
||||||
if (depth_shader_entities == -1) {
|
if (depth_shader_entities == -1) {
|
||||||
// upsi, something went wrong loading shader.
|
// upsi, something went wrong loading shader.
|
||||||
@ -616,10 +613,9 @@ void ShadowRenderer::createShaders()
|
|||||||
m_shadow_mix_cb = new shadowScreenQuadCB();
|
m_shadow_mix_cb = new shadowScreenQuadCB();
|
||||||
m_screen_quad = new shadowScreenQuad();
|
m_screen_quad = new shadowScreenQuad();
|
||||||
mixcsm_shader = gpu->addHighLevelShaderMaterial(
|
mixcsm_shader = gpu->addHighLevelShaderMaterial(
|
||||||
readShaderFile(depth_shader_vs).c_str(), "vertexMain",
|
readShaderFile(depth_shader_vs).c_str(),
|
||||||
video::EVST_VS_1_1,
|
readShaderFile(depth_shader_fs).c_str(), nullptr,
|
||||||
readShaderFile(depth_shader_fs).c_str(), "pixelMain",
|
m_shadow_mix_cb);
|
||||||
video::EPST_PS_1_2, m_shadow_mix_cb);
|
|
||||||
|
|
||||||
m_screen_quad->getMaterial().MaterialType =
|
m_screen_quad->getMaterial().MaterialType =
|
||||||
(video::E_MATERIAL_TYPE)mixcsm_shader;
|
(video::E_MATERIAL_TYPE)mixcsm_shader;
|
||||||
@ -655,10 +651,9 @@ void ShadowRenderer::createShaders()
|
|||||||
m_shadow_depth_trans_cb = new ShadowDepthShaderCB();
|
m_shadow_depth_trans_cb = new ShadowDepthShaderCB();
|
||||||
|
|
||||||
depth_shader_trans = gpu->addHighLevelShaderMaterial(
|
depth_shader_trans = gpu->addHighLevelShaderMaterial(
|
||||||
readShaderFile(depth_shader_vs).c_str(), "vertexMain",
|
readShaderFile(depth_shader_vs).c_str(),
|
||||||
video::EVST_VS_1_1,
|
readShaderFile(depth_shader_fs).c_str(), nullptr,
|
||||||
readShaderFile(depth_shader_fs).c_str(), "pixelMain",
|
m_shadow_depth_trans_cb);
|
||||||
video::EPST_PS_1_2, m_shadow_depth_trans_cb);
|
|
||||||
|
|
||||||
if (depth_shader_trans == -1) {
|
if (depth_shader_trans == -1) {
|
||||||
// upsi, something went wrong loading shader.
|
// upsi, something went wrong loading shader.
|
||||||
|
@ -121,7 +121,6 @@ public:
|
|||||||
// Shall be called from the main thread.
|
// Shall be called from the main thread.
|
||||||
void rebuildImagesAndTextures();
|
void rebuildImagesAndTextures();
|
||||||
|
|
||||||
video::ITexture* getNormalTexture(const std::string &name);
|
|
||||||
video::SColor getTextureAverageColor(const std::string &name);
|
video::SColor getTextureAverageColor(const std::string &name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -488,40 +487,20 @@ void TextureSource::rebuildTexture(video::IVideoDriver *driver, TextureInfo &ti)
|
|||||||
m_texture_trash.push_back(t_old);
|
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::SColor TextureSource::getTextureAverageColor(const std::string &name)
|
||||||
{
|
{
|
||||||
video::IVideoDriver *driver = RenderingEngine::get_video_driver();
|
video::IVideoDriver *driver = RenderingEngine::get_video_driver();
|
||||||
video::ITexture *texture = getTexture(name);
|
video::ITexture *texture = getTexture(name);
|
||||||
if (!texture)
|
if (!texture)
|
||||||
return {0, 0, 0, 0};
|
return {0, 0, 0, 0};
|
||||||
|
// Note: this downloads the texture back from the GPU, which is pointless
|
||||||
video::IImage *image = driver->createImage(texture,
|
video::IImage *image = driver->createImage(texture,
|
||||||
core::position2d<s32>(0, 0),
|
core::position2d<s32>(0, 0),
|
||||||
texture->getOriginalSize());
|
texture->getOriginalSize());
|
||||||
if (!image)
|
if (!image)
|
||||||
return {0, 0, 0, 0};
|
return {0, 0, 0, 0};
|
||||||
|
|
||||||
video::SColor c = ImageSource::getImageAverageColor(*image);
|
video::SColor c = imageAverageColor(image);
|
||||||
image->drop();
|
image->drop();
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
|
@ -54,7 +54,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual Palette* getPalette(const std::string &name) = 0;
|
virtual Palette* getPalette(const std::string &name) = 0;
|
||||||
virtual bool isKnownSourceImage(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;
|
virtual video::SColor getTextureAverageColor(const std::string &name)=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -75,7 +74,6 @@ public:
|
|||||||
virtual void processQueue()=0;
|
virtual void processQueue()=0;
|
||||||
virtual void insertSourceImage(const std::string &name, video::IImage *img)=0;
|
virtual void insertSourceImage(const std::string &name, video::IImage *img)=0;
|
||||||
virtual void rebuildImagesAndTextures()=0;
|
virtual void rebuildImagesAndTextures()=0;
|
||||||
virtual video::ITexture* getNormalTexture(const std::string &name)=0;
|
|
||||||
virtual video::SColor getTextureAverageColor(const std::string &name)=0;
|
virtual video::SColor getTextureAverageColor(const std::string &name)=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -312,7 +312,7 @@ void set_default_settings()
|
|||||||
|
|
||||||
// Effects
|
// Effects
|
||||||
settings->setDefault("enable_post_processing", "true");
|
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("directional_colored_fog", "true");
|
||||||
settings->setDefault("inventory_items_animations", "false");
|
settings->setDefault("inventory_items_animations", "false");
|
||||||
settings->setDefault("mip_map", "false");
|
settings->setDefault("mip_map", "false");
|
||||||
|
@ -85,8 +85,8 @@ void GUIInventoryList::draw()
|
|||||||
v2s32 p((i % m_geom.X) * m_slot_spacing.X,
|
v2s32 p((i % m_geom.X) * m_slot_spacing.X,
|
||||||
(i / m_geom.X) * m_slot_spacing.Y);
|
(i / m_geom.X) * m_slot_spacing.Y);
|
||||||
core::rect<s32> rect = imgrect + base_pos + p;
|
core::rect<s32> rect = imgrect + base_pos + p;
|
||||||
ItemStack item = ilist->getItem(item_i);
|
const ItemStack &orig_item = ilist->getItem(item_i);
|
||||||
ItemStack orig_item = item;
|
ItemStack item = orig_item;
|
||||||
|
|
||||||
bool selected = selected_item
|
bool selected = selected_item
|
||||||
&& m_invmgr->getInventory(selected_item->inventoryloc) == inv
|
&& m_invmgr->getInventory(selected_item->inventoryloc) == inv
|
||||||
@ -137,12 +137,26 @@ void GUIInventoryList::draw()
|
|||||||
client, rotation_kind);
|
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;
|
bool show_tooltip = !item.empty() && hovering && !selected_item;
|
||||||
// Make it possible to see item tooltips on touchscreens
|
|
||||||
if (RenderingEngine::getLastPointerType() == PointerType::Touch) {
|
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;
|
show_tooltip |= hovering && selected && m_fs_menu->getSelectedAmount() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_tooltip) {
|
if (show_tooltip) {
|
||||||
std::string tooltip = orig_item.getDescription(client->idef());
|
std::string tooltip = orig_item.getDescription(client->idef());
|
||||||
if (m_fs_menu->doTooltipAppendItemname())
|
if (m_fs_menu->doTooltipAppendItemname())
|
||||||
|
@ -29,52 +29,47 @@
|
|||||||
|
|
||||||
TouchControls *g_touchcontrols;
|
TouchControls *g_touchcontrols;
|
||||||
|
|
||||||
static void load_button_texture(IGUIImage *gui_button, const std::string &path,
|
void TouchControls::emitKeyboardEvent(EKEY_CODE keycode, bool pressed)
|
||||||
const recti &button_rect, ISimpleTextureSource *tsrc, video::IVideoDriver *driver)
|
|
||||||
{
|
{
|
||||||
video::ITexture *texture = guiScalingImageButton(driver,
|
SEvent e{};
|
||||||
tsrc->getTexture(path), button_rect.getWidth(),
|
e.EventType = EET_KEY_INPUT_EVENT;
|
||||||
button_rect.getHeight());
|
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->setImage(texture);
|
||||||
gui_button->setScaleImage(true);
|
gui_button->setScaleImage(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void button_info::emitAction(bool action, video::IVideoDriver *driver,
|
void TouchControls::buttonEmitAction(button_info &btn, bool action)
|
||||||
IEventReceiver *receiver, ISimpleTextureSource *tsrc)
|
|
||||||
{
|
{
|
||||||
if (keycode == KEY_UNKNOWN)
|
if (btn.keycode == KEY_UNKNOWN)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SEvent translated{};
|
emitKeyboardEvent(btn.keycode, action);
|
||||||
translated.EventType = EET_KEY_INPUT_EVENT;
|
|
||||||
translated.KeyInput.Key = keycode;
|
|
||||||
translated.KeyInput.Control = false;
|
|
||||||
translated.KeyInput.Shift = false;
|
|
||||||
translated.KeyInput.Char = 0;
|
|
||||||
|
|
||||||
if (action) {
|
if (action) {
|
||||||
translated.KeyInput.PressedDown = true;
|
if (btn.toggleable == button_info::FIRST_TEXTURE) {
|
||||||
receiver->OnEvent(translated);
|
btn.toggleable = button_info::SECOND_TEXTURE;
|
||||||
|
loadButtonTexture(btn.gui_button.get(), btn.toggle_textures[1]);
|
||||||
|
|
||||||
if (toggleable == button_info::FIRST_TEXTURE) {
|
} else if (btn.toggleable == button_info::SECOND_TEXTURE) {
|
||||||
toggleable = button_info::SECOND_TEXTURE;
|
btn.toggleable = button_info::FIRST_TEXTURE;
|
||||||
load_button_texture(gui_button.get(), toggle_textures[1],
|
loadButtonTexture(btn.gui_button.get(), btn.toggle_textures[0]);
|
||||||
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 {
|
|
||||||
translated.KeyInput.PressedDown = false;
|
|
||||||
receiver->OnEvent(translated);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool buttons_handlePress(std::vector<button_info> &buttons, size_t pointer_id, IGUIElement *element,
|
bool TouchControls::buttonsHandlePress(std::vector<button_info> &buttons, size_t pointer_id, IGUIElement *element)
|
||||||
video::IVideoDriver *driver, IEventReceiver *receiver, ISimpleTextureSource *tsrc)
|
|
||||||
{
|
{
|
||||||
if (!element)
|
if (!element)
|
||||||
return false;
|
return false;
|
||||||
@ -87,7 +82,7 @@ static bool buttons_handlePress(std::vector<button_info> &buttons, size_t pointe
|
|||||||
if (btn.pointer_ids.size() > 1)
|
if (btn.pointer_ids.size() > 1)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
btn.emitAction(true, driver, receiver, tsrc);
|
buttonEmitAction(btn, true);
|
||||||
btn.repeat_counter = -BUTTON_REPEAT_DELAY;
|
btn.repeat_counter = -BUTTON_REPEAT_DELAY;
|
||||||
return true;
|
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,
|
bool TouchControls::buttonsHandleRelease(std::vector<button_info> &buttons, size_t pointer_id)
|
||||||
video::IVideoDriver *driver, IEventReceiver *receiver, ISimpleTextureSource *tsrc)
|
|
||||||
{
|
{
|
||||||
for (button_info &btn : buttons) {
|
for (button_info &btn : buttons) {
|
||||||
auto it = std::find(btn.pointer_ids.begin(), btn.pointer_ids.end(), pointer_id);
|
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())
|
if (!btn.pointer_ids.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
btn.emitAction(false, driver, receiver, tsrc);
|
buttonEmitAction(btn, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,8 +110,7 @@ static bool buttons_handleRelease(std::vector<button_info> &buttons, size_t poin
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool buttons_step(std::vector<button_info> &buttons, float dtime,
|
bool TouchControls::buttonsStep(std::vector<button_info> &buttons, float dtime)
|
||||||
video::IVideoDriver *driver, IEventReceiver *receiver, ISimpleTextureSource *tsrc)
|
|
||||||
{
|
{
|
||||||
bool has_pointers = false;
|
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)
|
if (btn.repeat_counter < BUTTON_REPEAT_INTERVAL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
btn.emitAction(false, driver, receiver, tsrc);
|
buttonEmitAction(btn, false);
|
||||||
btn.emitAction(true, driver, receiver, tsrc);
|
buttonEmitAction(btn, true);
|
||||||
btn.repeat_counter = 0.0f;
|
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);
|
IGUIImage *btn_gui_button = m_guienv->addImage(rect, nullptr, id);
|
||||||
btn_gui_button->setVisible(visible);
|
btn_gui_button->setVisible(visible);
|
||||||
load_button_texture(btn_gui_button, image, rect,
|
loadButtonTexture(btn_gui_button, image);
|
||||||
m_texturesource, m_device->getVideoDriver());
|
|
||||||
|
|
||||||
button_info &btn = buttons.emplace_back();
|
button_info &btn = buttons.emplace_back();
|
||||||
btn.keycode = id_to_keycode(id);
|
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);
|
IGUIImage *btn_gui_button = m_guienv->addImage(rect, nullptr, id);
|
||||||
btn_gui_button->setVisible(visible);
|
btn_gui_button->setVisible(visible);
|
||||||
load_button_texture(btn_gui_button, button_image_names[id], rect,
|
loadButtonTexture(btn_gui_button, button_image_names[id]);
|
||||||
m_texturesource, m_device->getVideoDriver());
|
|
||||||
|
|
||||||
return btn_gui_button;
|
return btn_gui_button;
|
||||||
}
|
}
|
||||||
@ -399,11 +390,9 @@ void TouchControls::handleReleaseEvent(size_t pointer_id)
|
|||||||
m_pointer_pos.erase(pointer_id);
|
m_pointer_pos.erase(pointer_id);
|
||||||
|
|
||||||
// handle buttons
|
// handle buttons
|
||||||
if (buttons_handleRelease(m_buttons, pointer_id, m_device->getVideoDriver(),
|
if (buttonsHandleRelease(m_buttons, pointer_id))
|
||||||
m_receiver, m_texturesource))
|
|
||||||
return;
|
return;
|
||||||
if (buttons_handleRelease(m_overflow_buttons, pointer_id, m_device->getVideoDriver(),
|
if (buttonsHandleRelease(m_overflow_buttons, pointer_id))
|
||||||
m_receiver, m_texturesource))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_has_move_id && pointer_id == m_move_id) {
|
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,
|
if (buttonsHandlePress(m_overflow_buttons, pointer_id, element))
|
||||||
m_device->getVideoDriver(), m_receiver, m_texturesource))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
toggleOverflowMenu();
|
toggleOverflowMenu();
|
||||||
@ -494,8 +482,7 @@ void TouchControls::translateEvent(const SEvent &event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle buttons
|
// handle buttons
|
||||||
if (buttons_handlePress(m_buttons, pointer_id, element,
|
if (buttonsHandlePress(m_buttons, pointer_id, element))
|
||||||
m_device->getVideoDriver(), m_receiver, m_texturesource))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// handle hotbar
|
// handle hotbar
|
||||||
@ -614,16 +601,10 @@ void TouchControls::translateEvent(const SEvent &event)
|
|||||||
void TouchControls::applyJoystickStatus()
|
void TouchControls::applyJoystickStatus()
|
||||||
{
|
{
|
||||||
if (m_joystick_triggers_aux1) {
|
if (m_joystick_triggers_aux1) {
|
||||||
SEvent translated{};
|
auto key = id_to_keycode(aux1_id);
|
||||||
translated.EventType = EET_KEY_INPUT_EVENT;
|
emitKeyboardEvent(key, false);
|
||||||
translated.KeyInput.Key = id_to_keycode(aux1_id);
|
if (m_joystick_status_aux1)
|
||||||
translated.KeyInput.PressedDown = false;
|
emitKeyboardEvent(key, true);
|
||||||
m_receiver->OnEvent(translated);
|
|
||||||
|
|
||||||
if (m_joystick_status_aux1) {
|
|
||||||
translated.KeyInput.PressedDown = true;
|
|
||||||
m_receiver->OnEvent(translated);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,8 +620,8 @@ void TouchControls::step(float dtime)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// simulate keyboard repeats
|
// simulate keyboard repeats
|
||||||
buttons_step(m_buttons, dtime, m_device->getVideoDriver(), m_receiver, m_texturesource);
|
buttonsStep(m_buttons, dtime);
|
||||||
buttons_step(m_overflow_buttons, dtime, m_device->getVideoDriver(), m_receiver, m_texturesource);
|
buttonsStep(m_overflow_buttons, dtime);
|
||||||
|
|
||||||
// joystick
|
// joystick
|
||||||
applyJoystickStatus();
|
applyJoystickStatus();
|
||||||
|
@ -67,9 +67,6 @@ struct button_info
|
|||||||
SECOND_TEXTURE
|
SECOND_TEXTURE
|
||||||
} toggleable = NOT_TOGGLEABLE;
|
} toggleable = NOT_TOGGLEABLE;
|
||||||
std::string toggle_textures[2];
|
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;
|
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 toggleOverflowMenu();
|
||||||
void updateVisibility();
|
void updateVisibility();
|
||||||
void releaseAll();
|
void releaseAll();
|
||||||
|
@ -88,12 +88,11 @@ void ItemStackMetadata::deSerialize(std::istream &is)
|
|||||||
void ItemStackMetadata::updateToolCapabilities()
|
void ItemStackMetadata::updateToolCapabilities()
|
||||||
{
|
{
|
||||||
if (contains(TOOLCAP_KEY)) {
|
if (contains(TOOLCAP_KEY)) {
|
||||||
toolcaps_overridden = true;
|
|
||||||
toolcaps_override = ToolCapabilities();
|
toolcaps_override = ToolCapabilities();
|
||||||
std::istringstream is(getString(TOOLCAP_KEY));
|
std::istringstream is(getString(TOOLCAP_KEY));
|
||||||
toolcaps_override.deserializeJson(is);
|
toolcaps_override->deserializeJson(is);
|
||||||
} else {
|
} else {
|
||||||
toolcaps_overridden = false;
|
toolcaps_override = std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,7 @@ class IItemDefManager;
|
|||||||
class ItemStackMetadata : public SimpleMetadata
|
class ItemStackMetadata : public SimpleMetadata
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ItemStackMetadata():
|
ItemStackMetadata()
|
||||||
toolcaps_overridden(false)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// Overrides
|
// Overrides
|
||||||
@ -29,7 +28,7 @@ public:
|
|||||||
const ToolCapabilities &getToolCapabilities(
|
const ToolCapabilities &getToolCapabilities(
|
||||||
const ToolCapabilities &default_caps) const
|
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);
|
void setToolCapabilities(const ToolCapabilities &caps);
|
||||||
@ -40,7 +39,6 @@ public:
|
|||||||
return wear_bar_override;
|
return wear_bar_override;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setWearBarParams(const WearBarParams ¶ms);
|
void setWearBarParams(const WearBarParams ¶ms);
|
||||||
void clearWearBarParams();
|
void clearWearBarParams();
|
||||||
|
|
||||||
@ -48,7 +46,6 @@ private:
|
|||||||
void updateToolCapabilities();
|
void updateToolCapabilities();
|
||||||
void updateWearBarParams();
|
void updateWearBarParams();
|
||||||
|
|
||||||
bool toolcaps_overridden;
|
std::optional<ToolCapabilities> toolcaps_override;
|
||||||
ToolCapabilities toolcaps_override;
|
|
||||||
std::optional<WearBarParams> wear_bar_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)
|
if (style == ALIGN_STYLE_WORLD)
|
||||||
return true;
|
return true;
|
||||||
|
@ -1594,7 +1594,7 @@ ToolCapabilities read_tool_capabilities(
|
|||||||
// key at index -2 and value at index -1
|
// key at index -2 and value at index -1
|
||||||
int rating = luaL_checkinteger(L, -2);
|
int rating = luaL_checkinteger(L, -2);
|
||||||
float time = luaL_checknumber(L, -1);
|
float time = luaL_checknumber(L, -1);
|
||||||
groupcap.times[rating] = time;
|
groupcap.times.emplace_back(rating, time);
|
||||||
// removes value, keeps key for next iteration
|
// removes value, keeps key for next iteration
|
||||||
lua_pop(L, 1);
|
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) {
|
for (Json::ArrayIndex i = 0; i < size; ++i) {
|
||||||
if (times_object[i].isDouble())
|
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++) {
|
for(u32 i = 0; i < times_size; i++) {
|
||||||
int level = readS16(is);
|
int level = readS16(is);
|
||||||
float time = readF32(is);
|
float time = readF32(is);
|
||||||
cap.times[level] = time;
|
cap.times.emplace_back(level, time);
|
||||||
}
|
}
|
||||||
groupcaps[name] = cap;
|
groupcaps[name] = cap;
|
||||||
}
|
}
|
||||||
@ -272,21 +272,11 @@ std::optional<WearBarParams> WearBarParams::deserializeJson(std::istream &is)
|
|||||||
return WearBarParams(colorStops, blend);
|
return WearBarParams(colorStops, blend);
|
||||||
}
|
}
|
||||||
|
|
||||||
video::SColor WearBarParams::getWearBarColor(f32 durabilityPercent) {
|
video::SColor WearBarParams::getWearBarColor(f32 durabilityPercent)
|
||||||
|
{
|
||||||
if (colorStops.empty())
|
if (colorStops.empty())
|
||||||
return video::SColor();
|
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);
|
auto upper = colorStops.upper_bound(durabilityPercent);
|
||||||
|
|
||||||
if (upper == colorStops.end()) // durability is >= the highest defined color stop
|
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
|
if (upper == colorStops.begin()) // durability is <= the lowest defined color stop
|
||||||
return upper->second;
|
return upper->second;
|
||||||
|
|
||||||
|
// between two values, interpolate
|
||||||
auto lower = std::prev(upper);
|
auto lower = std::prev(upper);
|
||||||
f32 lower_bound = lower->first;
|
f32 lower_bound = lower->first;
|
||||||
video::SColor lower_color = lower->second;
|
video::SColor lower_color = lower->second;
|
||||||
|
37
src/tool.h
37
src/tool.h
@ -12,26 +12,33 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
struct ItemDefinition;
|
struct ItemDefinition;
|
||||||
class IItemDefManager;
|
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
|
struct ToolGroupCap
|
||||||
{
|
{
|
||||||
std::unordered_map<int, float> times;
|
std::vector<std::pair<int, float>> times;
|
||||||
int maxlevel = 1;
|
int maxlevel = 1;
|
||||||
int uses = 20;
|
int uses = 20;
|
||||||
|
|
||||||
ToolGroupCap() = default;
|
ToolGroupCap() = default;
|
||||||
|
|
||||||
std::optional<float> getTime(int rating) const {
|
std::optional<float> getTime(int rating) const {
|
||||||
auto i = times.find(rating);
|
for (auto &it : times) {
|
||||||
if (i == times.end())
|
if (it.first == rating)
|
||||||
return std::nullopt;
|
return it.second;
|
||||||
return i->second;
|
}
|
||||||
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void toJson(Json::Value &object) const;
|
void toJson(Json::Value &object) const;
|
||||||
@ -39,16 +46,16 @@ struct ToolGroupCap
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef std::unordered_map<std::string, struct ToolGroupCap> ToolGCMap;
|
typedef std::map<std::string, ToolGroupCap> ToolGCMap;
|
||||||
typedef std::unordered_map<std::string, s16> DamageGroup;
|
typedef std::map<std::string, s16> DamageGroup;
|
||||||
|
|
||||||
struct ToolCapabilities
|
struct ToolCapabilities
|
||||||
{
|
{
|
||||||
float full_punch_interval;
|
float full_punch_interval;
|
||||||
int max_drop_level;
|
int max_drop_level;
|
||||||
|
int punch_attack_uses;
|
||||||
ToolGCMap groupcaps;
|
ToolGCMap groupcaps;
|
||||||
DamageGroup damageGroups;
|
DamageGroup damageGroups;
|
||||||
int punch_attack_uses;
|
|
||||||
|
|
||||||
ToolCapabilities(
|
ToolCapabilities(
|
||||||
float full_punch_interval_ = 1.4f,
|
float full_punch_interval_ = 1.4f,
|
||||||
@ -59,9 +66,9 @@ struct ToolCapabilities
|
|||||||
):
|
):
|
||||||
full_punch_interval(full_punch_interval_),
|
full_punch_interval(full_punch_interval_),
|
||||||
max_drop_level(max_drop_level_),
|
max_drop_level(max_drop_level_),
|
||||||
|
punch_attack_uses(punch_attack_uses_),
|
||||||
groupcaps(groupcaps_),
|
groupcaps(groupcaps_),
|
||||||
damageGroups(damageGroups_),
|
damageGroups(damageGroups_)
|
||||||
punch_attack_uses(punch_attack_uses_)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void serialize(std::ostream &os, u16 version) const;
|
void serialize(std::ostream &os, u16 version) const;
|
||||||
@ -76,17 +83,18 @@ private:
|
|||||||
|
|
||||||
struct WearBarParams
|
struct WearBarParams
|
||||||
{
|
{
|
||||||
std::map<f32, video::SColor> colorStops;
|
|
||||||
enum BlendMode : u8 {
|
enum BlendMode : u8 {
|
||||||
BLEND_MODE_CONSTANT,
|
BLEND_MODE_CONSTANT,
|
||||||
BLEND_MODE_LINEAR,
|
BLEND_MODE_LINEAR,
|
||||||
BlendMode_END // Dummy for validity check
|
BlendMode_END // Dummy for validity check
|
||||||
};
|
};
|
||||||
constexpr const static EnumString es_BlendMode[3] = {
|
constexpr const static EnumString es_BlendMode[3] = {
|
||||||
{WearBarParams::BLEND_MODE_CONSTANT, "constant"},
|
{BLEND_MODE_CONSTANT, "constant"},
|
||||||
{WearBarParams::BLEND_MODE_LINEAR, "linear"},
|
{BLEND_MODE_LINEAR, "linear"},
|
||||||
{0, nullptr}
|
{0, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::map<f32, video::SColor> colorStops;
|
||||||
BlendMode blend;
|
BlendMode blend;
|
||||||
|
|
||||||
WearBarParams(const 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);
|
static WearBarParams deserialize(std::istream &is);
|
||||||
void serializeJson(std::ostream &os) const;
|
void serializeJson(std::ostream &os) const;
|
||||||
static std::optional<WearBarParams> deserializeJson(std::istream &is);
|
static std::optional<WearBarParams> deserializeJson(std::istream &is);
|
||||||
|
|
||||||
video::SColor getWearBarColor(f32 durabilityPercent);
|
video::SColor getWearBarColor(f32 durabilityPercent);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user