This commit is contained in:
Sam 2018-01-24 21:51:11 +01:00
commit 37a6f464b9
109 changed files with 2114 additions and 1709 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0"?>
<graphical-restrictions>
<card is="Intel(R) HD Graphics" os="windows" version="<9.0" disable="ForceLegacyDevice"/>
<card is="Intel(R) HD Graphics" os="windows" version="<9.0" disable="HighDefinitionTextures"/>
<card is="Intel(R) HD Graphics" os="windows" version="<10.0" disable="ForceLegacyDevice"/>
<card is="Intel(R) HD Graphics" os="windows" version="<10.0" disable="HighDefinitionTextures"/>
<card is="Intel(R) HD Graphics 2000" os="windows" disable="ForceLegacyDevice"/>
<card is="Intel(R) HD Graphics 2000" os="windows" disable="HighDefinitionTextures"/>
<card is="Intel(R) HD Graphics 3000" os="windows" disable="ForceLegacyDevice"/>
@ -35,5 +35,6 @@
<card os="android" disable="ColorBufferFloat"/>
<card contains="Adreno" os="android" version="<=19" disable="VertexIdWorking"/>
<card contains="Android Emulator" os="android" disable="ForceLegacyDevice"/>
<card contains="Android Emulator" os="android" disable="NpotTextures"/>
<card vendor="Broadcom" os="linux" disable="HighDefinitionTextures256"/>
</graphical-restrictions>

View File

@ -39,7 +39,7 @@ void main(void)
vec4 particle_color = vec4(color_lifetime.zyx, 1.0);
tc = Texcoord;
#if !defined(sRGB_Framebuffer_Usable) && !defined(Advanced_Lighting_Enabled)
#if !defined(Advanced_Lighting_Enabled)
particle_color.rgb = pow(particle_color.rgb, vec3(1.0 / 2.2));
#endif
pc = particle_color;

View File

@ -1,8 +1,8 @@
uniform ivec4 color;
out vec4 FragColor;
void main()
{
FragColor = vec4(color) / 255.;
}
uniform ivec4 color;
out vec4 FragColor;
void main()
{
FragColor = vec4(color) / 255.;
}

View File

@ -1,14 +1,14 @@
uniform vec2 center;
uniform vec2 size;
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec2 Position;
#else
in vec2 Position;
#endif
void main()
{
gl_Position = vec4(Position * size + center, 0., 1.);
}
uniform vec2 center;
uniform vec2 size;
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec2 Position;
#else
in vec2 Position;
#endif
void main()
{
gl_Position = vec4(Position * size + center, 0., 1.);
}

View File

@ -1,11 +1,11 @@
uniform sampler2D tex;
in vec2 uv;
in vec4 col;
out vec4 FragColor;
void main()
{
vec4 res = texture(tex, uv);
FragColor = res * col;
}
uniform sampler2D tex;
in vec2 uv;
in vec4 col;
out vec4 FragColor;
void main()
{
vec4 res = texture(tex, uv);
FragColor = res * col;
}

View File

@ -1,24 +1,24 @@
uniform vec2 center;
uniform vec2 size;
uniform vec2 texcenter;
uniform vec2 texsize;
#ifdef Explicit_Attrib_Location_Usable
layout(location=0) in vec2 Position;
layout(location=3) in vec2 Texcoord;
layout(location=2) in vec4 Color;
#else
in vec2 Position;
in vec2 Texcoord;
in vec4 Color;
#endif
out vec2 uv;
out vec4 col;
void main()
{
col = Color.zyxw;
uv = Texcoord * texsize + texcenter;
gl_Position = vec4(Position * size + center, 0., 1.);
}
uniform vec2 center;
uniform vec2 size;
uniform vec2 texcenter;
uniform vec2 texsize;
#ifdef Explicit_Attrib_Location_Usable
layout(location=0) in vec2 Position;
layout(location=3) in vec2 Texcoord;
layout(location=2) in vec4 Color;
#else
in vec2 Position;
in vec2 Texcoord;
in vec4 Color;
#endif
out vec2 uv;
out vec4 col;
void main()
{
col = Color.zyxw;
uv = Texcoord * texsize + texcenter;
gl_Position = vec4(Position * size + center, 0., 1.);
}

View File

@ -44,7 +44,7 @@ void main(void)
vec4 particle_color = vec4(color_lifetime.zyx, 1.0) * alpha;
tc = Texcoord;
#if !defined(sRGB_Framebuffer_Usable) && !defined(Advanced_Lighting_Enabled)
#if !defined(Advanced_Lighting_Enabled)
particle_color.rgb = pow(particle_color.rgb, vec3(1.0 / 2.2));
#endif
pc = particle_color;

View File

@ -14,7 +14,7 @@ layout(location = 2) out vec2 o_gloss_map;
void main(void)
{
vec4 col = sampleTextureSlot0(uv);
vec4 col = sampleTextureLayer0(uv);
if (col.a * color.a < 0.5)
{
discard;
@ -30,17 +30,10 @@ void main(void)
}
vec3 final_color = col.xyz * color.xyz;
#if !defined(Advanced_Lighting_Enabled)
#if !defined(sRGB_Framebuffer_Usable)
final_color = final_color * 0.73; // 0.5 ^ (1. / 2.2)
#else
final_color = final_color * 0.5;
#endif
#endif
o_diffuse_color = vec4(final_color, 1.0);
#if defined(Advanced_Lighting_Enabled)
vec4 layer_2 = sampleTextureSlot2(uv);
vec4 layer_2 = sampleTextureLayer2(uv);
o_normal_depth.xy = 0.5 * EncodeNormal(normalize(normal)) + 0.5;
o_normal_depth.z = layer_2.x;
o_gloss_map = layer_2.yz;

View File

@ -11,22 +11,15 @@ layout(location = 2) out vec2 o_gloss_map;
void main(void)
{
vec4 color = sampleTextureSlot0(uv);
vec4 layer_two_tex = sampleTextureSlot1(uv_two);
vec4 color = sampleTextureLayer0(uv);
vec4 layer_two_tex = sampleTextureLayer1(uv_two);
layer_two_tex.rgb = layer_two_tex.a * layer_two_tex.rgb;
vec3 final_color = layer_two_tex.rgb + color.rgb * (1.0 - layer_two_tex.a);
#if !defined(Advanced_Lighting_Enabled)
#if !defined(sRGB_Framebuffer_Usable)
final_color = final_color * 0.73; // 0.5 ^ (1. / 2.2)
#else
final_color = final_color * 0.5;
#endif
#endif
o_diffuse_color = vec4(final_color, 1.0);
#if defined(Advanced_Lighting_Enabled)
vec4 layer_2 = sampleTextureSlot2(uv);
vec4 layer_2 = sampleTextureLayer2(uv);
o_normal_depth.xy = 0.5 * EncodeNormal(normalize(normal)) + 0.5;
o_normal_depth.z = layer_2.x;
o_gloss_map = layer_2.yz;

View File

@ -41,7 +41,7 @@ void main()
tc += (mask < 1.) ? vec2(0.) : shift;
vec4 col = texture(color_tex, tc);
vec4 blend_tex = sampleTextureSlot0(uv);
vec4 blend_tex = sampleTextureLayer0(uv);
col.rgb = blend_tex.rgb * blend_tex.a + (1. - blend_tex.a) * col.rgb;
o_diffuse_color = vec4(col.rgb, 1.);
}

View File

@ -11,14 +11,15 @@ out vec4 o_diffuse_color;
void main()
{
vec4 col = sampleTextureSlot0(uv);
vec4 col = sampleTextureLayer0(uv);
if (hue_change > 0.0)
{
float mask = col.a;
vec3 old_hsv = rgbToHsv(col.rgb);
float mask_step = step(mask, 0.5);
#if !defined(Advanced_Lighting_Enabled)
float saturation = mask * 2.1;
// For similar color
float saturation = mask * 1.825; // 2.5 * 0.5 ^ (1. / 2.2)
#else
float saturation = mask * 2.5;
#endif
@ -29,13 +30,5 @@ void main()
}
vec3 final_color = col.xyz * color.xyz;
#if !defined(Advanced_Lighting_Enabled)
#if !defined(sRGB_Framebuffer_Usable)
final_color = final_color * 0.73; // 0.5 ^ (1. / 2.2)
#else
final_color = final_color * 0.5;
#endif
#endif
o_diffuse_color = vec4((final_color * custom_alpha), custom_alpha);
}

View File

@ -13,7 +13,7 @@ layout(location = 2) out vec2 o_gloss_map;
void main(void)
{
vec4 col = sampleTextureSlot0(uv);
vec4 col = sampleTextureLayer0(uv);
if (col.a < 0.5)
{
discard;
@ -28,17 +28,10 @@ void main(void)
}
vec3 final_color = col.xyz;
#if !defined(Advanced_Lighting_Enabled)
#if !defined(sRGB_Framebuffer_Usable)
final_color = final_color * 0.73; // 0.5 ^ (1. / 2.2)
#else
final_color = final_color * 0.5;
#endif
#endif
o_diffuse_color = vec4(final_color, 1.0);
#if defined(Advanced_Lighting_Enabled)
vec4 layer_2 = sampleTextureSlot2(uv);
vec4 layer_2 = sampleTextureLayer2(uv);
o_normal_depth.xy = 0.5 * EncodeNormal(normalize(normal)) + 0.5;
o_normal_depth.z = layer_2.x;
o_gloss_map = 0.1 * layer_2.yz;

View File

@ -16,14 +16,15 @@ layout(location = 2) out vec2 o_gloss_map;
void main()
{
vec4 col = sampleTextureSlot0(uv);
vec4 col = sampleTextureLayer0(uv);
if (hue_change > 0.0)
{
float mask = col.a;
vec3 old_hsv = rgbToHsv(col.rgb);
float mask_step = step(mask, 0.5);
#if !defined(Advanced_Lighting_Enabled)
float saturation = mask * 2.1;
// For similar color
float saturation = mask * 1.825; // 2.5 * 0.5 ^ (1. / 2.2)
#else
float saturation = mask * 2.5;
#endif
@ -34,17 +35,10 @@ void main()
}
vec3 final_color = col.xyz * color.xyz;
#if !defined(Advanced_Lighting_Enabled)
#if !defined(sRGB_Framebuffer_Usable)
final_color = final_color * 0.73; // 0.5 ^ (1. / 2.2)
#else
final_color = final_color * 0.5;
#endif
#endif
o_diffuse_color = vec4(final_color, 1.0);
#if defined(Advanced_Lighting_Enabled)
vec4 layer_3 = sampleTextureSlot3(uv);
vec4 layer_3 = sampleTextureLayer3(uv);
vec3 tangent_space_normal = 2.0 * layer_3.xyz - 1.0;
vec3 frag_tangent = normalize(tangent);
vec3 frag_bitangent = normalize(bitangent);
@ -52,7 +46,7 @@ void main()
mat3 t_b_n = mat3(frag_tangent, frag_bitangent, frag_normal);
vec3 world_normal = t_b_n * tangent_space_normal;
vec4 layer_2 = sampleTextureSlot2(uv);
vec4 layer_2 = sampleTextureLayer2(uv);
o_normal_depth.xy = 0.5 * EncodeNormal(normalize(world_normal)) + 0.5;
o_normal_depth.z = layer_2.x;
o_gloss_map = layer_2.yz;

View File

@ -5,7 +5,7 @@ out vec4 o_frag_color;
void main(void)
{
vec4 col = sampleTextureSlot0(uv);
vec4 col = sampleTextureLayer0(uv);
if (col.a < 0.5)
{
discard;

View File

@ -14,14 +14,15 @@ layout(location = 2) out vec2 o_gloss_map;
void main(void)
{
vec4 col = sampleTextureSlot0(uv);
vec4 col = sampleTextureLayer0(uv);
if (hue_change > 0.0)
{
float mask = col.a;
vec3 old_hsv = rgbToHsv(col.rgb);
float mask_step = step(mask, 0.5);
#if !defined(Advanced_Lighting_Enabled)
float saturation = mask * 2.1;
// For similar color
float saturation = mask * 1.825; // 2.5 * 0.5 ^ (1. / 2.2)
#else
float saturation = mask * 2.5;
#endif
@ -32,17 +33,10 @@ void main(void)
}
vec3 final_color = col.xyz * color.xyz;
#if !defined(Advanced_Lighting_Enabled)
#if !defined(sRGB_Framebuffer_Usable)
final_color = final_color * 0.73; // 0.5 ^ (1. / 2.2)
#else
final_color = final_color * 0.5;
#endif
#endif
o_diffuse_color = vec4(final_color, 1.0);
#if defined(Advanced_Lighting_Enabled)
vec4 layer_2 = sampleTextureSlot2(uv);
vec4 layer_2 = sampleTextureLayer2(uv);
o_normal_depth.xy = 0.5 * EncodeNormal(normalize(normal)) + 0.5;
o_normal_depth.z = layer_2.x;
o_gloss_map = layer_2.yz;

View File

@ -9,7 +9,7 @@ out vec4 o_diffuse_color;
void main()
{
vec4 diffusecolor = sampleTextureSlot0(uv);
vec4 diffusecolor = sampleTextureLayer0(uv);
vec4 finalcolor = vec4(0.);
if (fog_enabled == 0)
{

View File

@ -11,20 +11,13 @@ layout(location = 2) out vec2 o_gloss_map;
void main(void)
{
vec4 col = sampleTextureSlot0(uv);
vec4 col = sampleTextureLayer0(uv);
if (col.a < 0.5)
{
discard;
}
vec3 final_color = col.xyz * color.xyz;
#if !defined(Advanced_Lighting_Enabled)
#if !defined(sRGB_Framebuffer_Usable)
final_color = final_color * 0.73; // 0.5 ^ (1. / 2.2)
#else
final_color = final_color * 0.5;
#endif
#endif
o_diffuse_color = vec4(final_color, 1.0);
#if defined(Advanced_Lighting_Enabled)

View File

@ -0,0 +1,135 @@
<spshader>
<!--
Notice: boolean Y or N here is case-sensitive
name: The name of the shader (cannot be empty), you have to make sure
no duplicated name will be introduced, and "_skinned" word is
reserved for automatic skinned mesh shader adding.
fallback-shader: The name of the shader to be used when advanced
lighting is off, make sure that shader is loaded first
(default is empty). STK will load list of sps*.xml
files in ascending order from a directory.
transparent: If Y, than this shader will be used in transparent pass
(default N).
drawing-priority: The larger this number, the later the meshes using
this shader will be drawn. Only useful in transparent
shader where drawing order matters because of alpha
blending (default 0 which means order doesn't
matter).
use-alpha-channel: If Y, this shader is going to access alpha channel
from mesh texture layers. It's used to hint STK not
to encode colorization mask for this material using
this shader which it will overwrite the alpha
channel (default N).
use-tangents: If Y, than meshes using this shader will have tangents
and bitangents defined and you can access them in shader
(default N).
srgb: Sample mesh texture layers in srgb or not (in 6 Ys / Ns), when
advanced lighting is off, srgb will always be false,
default (Y Y N N N N), even if any texture layer is unused in
shader, you cannot skip it from the above Y / N array.
You can only specific 1st and shadow pass of shader in .xml
-->
<shader-info name="solid" fallback-shader="" transparent="N"
drawing-priority="0" use-alpha-channel="N" use-tangents="N"
srgb="Y Y N N N N"/>
<!--
use-function: Specify function to be run before drawing meshes with
this shader:
alphaBlendUse will be suitable for drawing alpha blend material.
additiveUse will be suitable for drawing additive material.
ghostUse will be suitable for drawing object with translucent
effect with face culling and depth buffer writing on.
unuse-function: Specify function to be run after drawing meshes with
this shader (none at the moment).
vertex-shader: Specify the vertex shader, it will search in the
directory of the location of this xml file first, if not
found it will search in the official shader directory.
Notice: if you use #stk_include in your shader file, STK
will only search the include header in official shader
directory.
fragment-shader: Specify the fragment shader, searching rule is the
same as above.
skinned-mesh-shader: Specify the skinned mesh version of the vertex
shader, searching rule is the same as above. You
have to make sure the uniforms and the textures
used in both skinned mesh / non-skinned mesh
shader are the same.
-->
<first-pass use-function="" unuse-function="" vertex-shader="sp_pass.vert"
fragment-shader="sp_solid.frag" skinned-mesh-shader="sp_skinning.vert">
<prefilled-textures>
<!--
prefilled-textures: Define the prefilled textures used in
shaders, they will be the same for all
meshes drawn using this shader.
name: Name of the texture used in shader (cannot be empty).
file: Filename of the texture, it will search using the order
in pushed texture searching directory
(cannot be empty).
srgb: Sample in srgb or not (specify in Y/N, default is N).
When advanced lighting is off, srgb will always be
false.
sampler: nearest, nearest_clamped, bilinear,
bilinear_clamped, trilinear, trilinear_clamped
and semi_trilinear are possible right now, default
is trilinear.
Example:
<prefilled-texture name="name_used_in_shader" file="texture.png"
srgb="Y" sampler="trilinear"/>-->
</prefilled-textures>
</first-pass>
<shadow-pass use-function="" unuse-function=""
vertex-shader="sp_shadow.vert" fragment-shader="white.frag"
skinned-mesh-shader="sp_skinning_shadow.vert">
<uniforms>
<!--
uniforms: Define the uniforms in shader with the name of the
type (int, float, mat4, vec4, vec3, vec2).
-->
<uniform name="layer" type="int"/>
</uniforms>
</shadow-pass>
<!--
uniform-assigners: List of uniform assigners functions to be auto-run
when "use" the shader which set the above uniforms,
currently there are:
shadowCascadeUniformAssigner will set the current shadow
cascade being drawn.
windDirectionUniformAssigner will set the wind direction.
zeroAlphaUniformAssigner should be used in transparent shader.
fogUniformAssigner will set 0 / 1 if fog is enabled in track.
ghostAlphaUniformAssigner will set ghost (kart) color based on sun
color of track.
You have to specify the uniform name in shader together with the
bundled uniform-assigners.
-->
<uniform-assigners>
<uniform-assigner name="layer"
function="shadowCascadeUniformAssigner"/>
</uniform-assigners>
</spshader>

View File

@ -0,0 +1,18 @@
<spshader>
<shader-info name="normalmap" fallback-shader="solid" use-tangents="Y"/>
<first-pass vertex-shader="sp_pass.vert"
fragment-shader="sp_normal_map.frag"
skinned-mesh-shader="sp_skinning.vert">
</first-pass>
<shadow-pass vertex-shader="sp_shadow.vert"
fragment-shader="white.frag"
skinned-mesh-shader="sp_skinning_shadow.vert">
<uniforms>
<uniform name="layer" type="int"/>
</uniforms>
</shadow-pass>
<uniform-assigners>
<uniform-assigner name="layer"
function="shadowCascadeUniformAssigner"/>
</uniform-assigners>
</spshader>

View File

@ -0,0 +1,18 @@
<spshader>
<shader-info name="alphatest" use-alpha-channel="Y"/>
<first-pass vertex-shader="sp_pass.vert"
fragment-shader="sp_alpha_test.frag"
skinned-mesh-shader="sp_skinning.vert">
</first-pass>
<shadow-pass vertex-shader="sp_shadow.vert"
fragment-shader="sp_shadow_alpha_test.frag"
skinned-mesh-shader="sp_skinning_shadow.vert">
<uniforms>
<uniform name="layer" type="int"/>
</uniforms>
</shadow-pass>
<uniform-assigners>
<uniform-assigner name="layer"
function="shadowCascadeUniformAssigner"/>
</uniform-assigners>
</spshader>

View File

@ -0,0 +1,16 @@
<spshader>
<shader-info name="decal"/>
<first-pass vertex-shader="sp_pass.vert"
fragment-shader="sp_decal.frag" skinned-mesh-shader="sp_skinning.vert">
</first-pass>
<shadow-pass vertex-shader="sp_shadow.vert" fragment-shader="white.frag"
skinned-mesh-shader="sp_skinning_shadow.vert">
<uniforms>
<uniform name="layer" type="int"/>
</uniforms>
</shadow-pass>
<uniform-assigners>
<uniform-assigner name="layer"
function="shadowCascadeUniformAssigner"/>
</uniform-assigners>
</spshader>

View File

@ -0,0 +1,22 @@
<spshader>
<shader-info name="grass" use-alpha-channel="Y"/>
<first-pass vertex-shader="sp_grass_pass.vert"
fragment-shader="sp_grass.frag">
<uniforms>
<uniform name="wind_direction" type="vec3"/>
</uniforms>
</first-pass>
<shadow-pass vertex-shader="sp_grass_shadow.vert"
fragment-shader="sp_shadow_alpha_test.frag">
<uniforms>
<uniform name="wind_direction" type="vec3"/>
<uniform name="layer" type="int"/>
</uniforms>
</shadow-pass>
<uniform-assigners>
<uniform-assigner name="layer"
function="shadowCascadeUniformAssigner"/>
<uniform-assigner name="wind_direction"
function="windDirectionUniformAssigner"/>
</uniform-assigners>
</spshader>

View File

@ -0,0 +1,17 @@
<spshader>
<shader-info name="unlit" fallback-shader="alphatest" use-alpha-channel="Y"/>
<first-pass vertex-shader="sp_pass.vert"
fragment-shader="sp_unlit.frag" skinned-mesh-shader="sp_skinning.vert">
</first-pass>
<shadow-pass vertex-shader="sp_shadow.vert"
fragment-shader="sp_shadow_alpha_test.frag"
skinned-mesh-shader="sp_skinning_shadow.vert">
<uniforms>
<uniform name="layer" type="int"/>
</uniforms>
</shadow-pass>
<uniform-assigners>
<uniform-assigner name="layer"
function="shadowCascadeUniformAssigner"/>
</uniform-assigners>
</spshader>

View File

@ -0,0 +1,17 @@
<spshader>
<shader-info name="alphablend" transparent="Y" use-alpha-channel="Y"/>
<first-pass use-function="alphaBlendUse" vertex-shader="sp_pass.vert"
fragment-shader="sp_transparent.frag"
skinned-mesh-shader="sp_skinning.vert">
<uniforms>
<uniform name="fog_enabled" type="int"/>
<uniform name="custom_alpha" type="float"/>
</uniforms>
</first-pass>
<uniform-assigners>
<uniform-assigner name="fog_enabled"
function="fogUniformAssigner"/>
<uniform-assigner name="custom_alpha"
function="zeroAlphaUniformAssigner"/>
</uniform-assigners>
</spshader>

View File

@ -0,0 +1,17 @@
<spshader>
<shader-info name="additive" transparent="Y" use-alpha-channel="Y"/>
<first-pass use-function="additiveUse" vertex-shader="sp_pass.vert"
fragment-shader="sp_transparent.frag"
skinned-mesh-shader="sp_skinning.vert">
<uniforms>
<uniform name="fog_enabled" type="int"/>
<uniform name="custom_alpha" type="float"/>
</uniforms>
</first-pass>
<uniform-assigners>
<uniform-assigner name="fog_enabled"
function="fogUniformAssigner"/>
<uniform-assigner name="custom_alpha"
function="zeroAlphaUniformAssigner"/>
</uniform-assigners>
</spshader>

View File

@ -0,0 +1,14 @@
<spshader>
<shader-info name="ghost" transparent="Y" drawing-priority="900"/>
<first-pass use-function="ghostUse" vertex-shader="sp_pass.vert"
fragment-shader="sp_ghost.frag"
skinned-mesh-shader="sp_skinning.vert">
<uniforms>
<uniform name="custom_alpha" type="float"/>
</uniforms>
</first-pass>
<uniform-assigners>
<uniform-assigner name="custom_alpha"
function="ghostAlphaUniformAssigner"/>
</uniform-assigners>
</spshader>

View File

@ -1,9 +1,9 @@
uniform sampler2D tex;
in vec2 uv;
out vec4 FragColor;
void main()
{
FragColor = texture(tex, uv);
uniform sampler2D tex;
in vec2 uv;
out vec4 FragColor;
void main()
{
FragColor = texture(tex, uv);
}

View File

@ -13,10 +13,6 @@ void main()
// Uncharted2 tonemap with Auria's custom coefficients
vec4 perChannel = (col * (6.9 * col + .5)) / (col * (5.2 * col + 1.7) + 0.06);
#if !(!defined(sRGB_Framebuffer_Usable) && defined(Advanced_Lighting_Enabled))
perChannel = pow(perChannel, vec4(2.2));
#endif
vec2 inside = uv - 0.5;
float vignette = 1. - dot(inside, inside) * vignette_weight;
vignette = clamp(pow(vignette, 0.8), 0., 1.);

View File

@ -1,4 +1,4 @@
// Wrapper to allow easy sampling for material texture slots
// Wrapper to allow easy sampling for material texture layers
uniform sampler2D tex_layer_0;
uniform sampler2D tex_layer_1;
uniform sampler2D tex_layer_2;
@ -6,32 +6,32 @@ uniform sampler2D tex_layer_3;
uniform sampler2D tex_layer_4;
uniform sampler2D tex_layer_5;
vec4 sampleTextureSlot0(vec2 uv)
vec4 sampleTextureLayer0(vec2 uv)
{
return texture(tex_layer_0, uv);
}
vec4 sampleTextureSlot1(vec2 uv)
vec4 sampleTextureLayer1(vec2 uv)
{
return texture(tex_layer_1, uv);
}
vec4 sampleTextureSlot2(vec2 uv)
vec4 sampleTextureLayer2(vec2 uv)
{
return texture(tex_layer_2, uv);
}
vec4 sampleTextureSlot3(vec2 uv)
vec4 sampleTextureLayer3(vec2 uv)
{
return texture(tex_layer_3, uv);
}
vec4 sampleTextureSlot4(vec2 uv)
vec4 sampleTextureLayer4(vec2 uv)
{
return texture(tex_layer_4, uv);
}
vec4 sampleTextureSlot5(vec2 uv)
vec4 sampleTextureLayer5(vec2 uv)
{
return texture(tex_layer_5, uv);
}

View File

@ -286,6 +286,7 @@ bool CIrrDeviceLinux::restoreResolution()
XRROutputInfo* output = XRRGetOutputInfo(display, res, output_id);
if (!output || !output->crtc || output->connection == RR_Disconnected)
{
XRRFreeScreenResources(res);
XRRFreeOutputInfo(output);
return false;
}
@ -293,6 +294,7 @@ bool CIrrDeviceLinux::restoreResolution()
XRRCrtcInfo* crtc = XRRGetCrtcInfo(display, res, output->crtc);
if (!crtc)
{
XRRFreeScreenResources(res);
XRRFreeOutputInfo(output);
return false;
}
@ -946,6 +948,8 @@ bool CIrrDeviceLinux::createWindow()
ButtonPressMask | KeyPressMask |
ButtonReleaseMask | KeyReleaseMask;
bool netWM = false;
Atom *list;
Atom type;
int form;
@ -956,8 +960,13 @@ bool CIrrDeviceLinux::createWindow()
WMCheck, 0L, 1L, False, XA_WINDOW,
&type, &form, &len, &remain,
(unsigned char **)&list);
XFree(list);
bool netWM = (s == Success) && len;
if (s == Success)
{
XFree(list);
netWM = (len > 0);
}
if (!CreationParams.WindowId)
{
@ -1014,17 +1023,15 @@ bool CIrrDeviceLinux::createWindow()
Atom type;
int format;
unsigned long numItems, bytesAfter;
unsigned char* data = NULL;
Atom* atoms = NULL;
int s = XGetWindowProperty(display, window, WMStateAtom,
0l, 1024, False, XA_ATOM, &type,
&format, &numItems, &bytesAfter,
&data);
(unsigned char**)&atoms);
if (s == Success)
{
Atom* atoms = (Atom*)data;
for (unsigned int i = 0; i < numItems; ++i)
{
if (atoms[i] == WMFullscreenAtom)
@ -1033,9 +1040,9 @@ bool CIrrDeviceLinux::createWindow()
break;
}
}
}
XFree(data);
XFree(atoms);
}
if (fullscreen == true)
break;
@ -1770,13 +1777,20 @@ bool CIrrDeviceLinux::run()
case ClientMessage:
{
char *atom = XGetAtomName(display, event.xclient.message_type);
if (*atom == *wmDeleteWindow)
char* atom = XGetAtomName(display, event.xclient.message_type);
if (atom != NULL)
{
os::Printer::log("Quit message received.", ELL_INFORMATION);
Close = true;
if (strcmp(atom, "WM_PROTOCOLS") == 0)
{
os::Printer::log("Quit message received.", ELL_INFORMATION);
Close = true;
}
XFree(atom);
}
else
if (!Close)
{
// we assume it's a user message
irrevent.EventType = irr::EET_USER_EVENT;
@ -1784,7 +1798,6 @@ bool CIrrDeviceLinux::run()
irrevent.UserEvent.UserData2 = (s32)event.xclient.data.l[1];
postEventFromUser(irrevent);
}
XFree(atom);
}
break;
@ -2808,9 +2821,11 @@ const c8* CIrrDeviceLinux::getTextFromClipboard() const
&numItems, &dummy, &data);
if (result == Success)
{
Clipboard = (irr::c8*)data;
XFree(data);
}
XFree (data);
return Clipboard.c_str();
#else
return 0;

View File

@ -1,5 +1,5 @@
# Modify this file to change the last-modified date when you add/remove a file.
# This will then trigger a new cmake run automatically.
# This will then trigger a new cmake run automatically.
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")

View File

@ -247,19 +247,19 @@ void CPUParticleManager::drawAll()
[](const std::pair<Material*, std::string>& a,
const std::pair<Material*, std::string>& b)->bool
{
return a.first->getShaderType() > b.first->getShaderType();
return a.first->getShaderName() > b.first->getShaderName();
});
Material::ShaderType st = Material::SHADERTYPE_COUNT;
std::string shader_name;
for (auto& p : particle_drawn)
{
const bool flips = isFlipsMaterial(p.second);
const float billboard = p.second.substr(0, 4) == "_bb_" ? 1.0f : 0.0f;
Material* cur_mat = p.first;
if (cur_mat->getShaderType() != st)
if (cur_mat->getShaderName() != shader_name)
{
st = cur_mat->getShaderType();
if (cur_mat->getShaderType() == Material::SHADERTYPE_ADDITIVE)
shader_name = cur_mat->getShaderName();
if (cur_mat->getShaderName() == "additive")
{
ParticleRenderer::getInstance()->use();
glEnable(GL_DEPTH_TEST);
@ -270,8 +270,7 @@ void CPUParticleManager::drawAll()
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
}
else if (cur_mat
->getShaderType() == Material::SHADERTYPE_ALPHA_BLEND)
else if (cur_mat->getShaderName() == "alphablend")
{
ParticleRenderer::getInstance()->use();
glEnable(GL_DEPTH_TEST);
@ -293,8 +292,8 @@ void CPUParticleManager::drawAll()
}
}
if (cur_mat->getShaderType() == Material::SHADERTYPE_ADDITIVE ||
cur_mat->getShaderType() == Material::SHADERTYPE_ALPHA_BLEND)
if (cur_mat->getShaderName() == "additive" ||
cur_mat->getShaderName() == "alphablend")
{
ParticleRenderer::getInstance()->setTextureUnits
(cur_mat->getTexture()->getOpenGLTextureName(),

View File

@ -145,13 +145,6 @@ void DrawCalls::parseSceneManager(core::list<scene::ISceneNode*> &List,
if (LODNode *node = dynamic_cast<LODNode *>(*I))
{
node->updateVisibility();
if (SP::sp_first_frame)
{
for (auto* child_node : node->getAllNodes())
{
child_node->setVisible(true);
}
}
}
(*I)->updateAbsolutePosition();
if (!(*I)->isVisible())
@ -159,8 +152,7 @@ void DrawCalls::parseSceneManager(core::list<scene::ISceneNode*> &List,
if (STKParticle *node = dynamic_cast<STKParticle*>(*I))
{
if (!isCulledPrecise(cam, *I, irr_driver->getBoundingBoxesViz()) ||
SP::sp_first_frame)
if (!isCulledPrecise(cam, *I, irr_driver->getBoundingBoxesViz()))
CPUParticleManager::getInstance()->addParticleNode(node);
continue;
}
@ -168,7 +160,7 @@ void DrawCalls::parseSceneManager(core::list<scene::ISceneNode*> &List,
if (scene::IBillboardSceneNode *node =
dynamic_cast<scene::IBillboardSceneNode*>(*I))
{
if (!isCulledPrecise(cam, *I) || SP::sp_first_frame)
if (!isCulledPrecise(cam, *I))
CPUParticleManager::getInstance()->addBillboardNode(node);
continue;
}
@ -176,8 +168,7 @@ void DrawCalls::parseSceneManager(core::list<scene::ISceneNode*> &List,
if (STKTextBillboard *tb =
dynamic_cast<STKTextBillboard*>(*I))
{
if (!isCulledPrecise(cam, *I, irr_driver->getBoundingBoxesViz()) ||
SP::sp_first_frame)
if (!isCulledPrecise(cam, *I, irr_driver->getBoundingBoxesViz()))
TextBillboardDrawer::addTextBillboard(tb);
continue;
}

View File

@ -44,7 +44,7 @@ namespace GraphicsRestrictions
/** The list of names used in the XML file for the graphics
* restriction types. They must be in the same order as the types. */
std::array<std::string, 29> m_names_of_restrictions =
std::array<std::string, 30> m_names_of_restrictions =
{
{
"UniformBufferObject",
@ -75,7 +75,8 @@ namespace GraphicsRestrictions
"GI",
"ForceLegacyDevice",
"VertexIdWorking",
"HardwareSkinning"
"HardwareSkinning",
"NpotTextures"
}
};
} // namespace Private

View File

@ -63,6 +63,7 @@ namespace GraphicsRestrictions
GR_FORCE_LEGACY_DEVICE,
GR_VERTEX_ID_WORKING,
GR_HARDWARE_SKINNING,
GR_NPOT_TEXTURES,
GR_COUNT /** MUST be last entry. */
} ;

View File

@ -1015,35 +1015,15 @@ void IrrDriver::setAllMaterialFlags(scene::IMesh *mesh) const
{
scene::IMeshBuffer *mb = mesh->getMeshBuffer(i);
video::SMaterial &irr_material = mb->getMaterial();
// special case : for splatting, the main material is on layer 1.
// it was done this way to provide a fallback for computers
// where shaders are not supported
video::ITexture* t2 = irr_material.getTexture(1);
bool is_splatting = false;
if (t2)
video::ITexture* t = irr_material.getTexture(0);
if (t)
{
Material* mat = material_manager->getMaterialFor(t2, mb);
if (mat != NULL && mat->getShaderType() == Material::SHADERTYPE_SPLATTING)
{
material_manager->setAllMaterialFlags(t2, mb);
is_splatting = true;
}
material_manager->setAllMaterialFlags(t, mb);
}
if (!is_splatting)
else
{
video::ITexture* t = irr_material.getTexture(0);
if (t)
{
material_manager->setAllMaterialFlags(t, mb);
}
else
{
material_manager->setAllUntexturedMaterialFlags(mb);
}
material_manager->setAllUntexturedMaterialFlags(mb);
}
} // for i<getMeshBufferCount()
} // setAllMaterialFlags
@ -1209,17 +1189,17 @@ scene::ISceneNode *IrrDriver::addBillboard(const core::dimension2d< f32 > size,
/*strip_path*/full_path, /*install*/false);
video::ITexture* tex = m->getTexture(true/*srgb*/,
m->getShaderType() == Material::SHADERTYPE_ADDITIVE ||
m->getShaderType() == Material::SHADERTYPE_ALPHA_BLEND ?
m->getShaderName() == "additive" ||
m->getShaderName() == "alphablend" ?
true : false/*premul_alpha*/);
assert(node->getMaterialCount() > 0);
node->setMaterialTexture(0, tex);
if (!(m->getShaderType() == Material::SHADERTYPE_ADDITIVE ||
m->getShaderType() == Material::SHADERTYPE_ALPHA_BLEND))
if (!(m->getShaderName() == "additive" ||
m->getShaderName() == "alphablend"))
{
// Alpha test for billboard otherwise
m->setShaderType(Material::SHADERTYPE_ALPHA_TEST);
m->setShaderName("alphatest");
}
m->setMaterialProperties(&(node->getMaterial(0)), NULL);
return node;
@ -1929,16 +1909,6 @@ bool IrrDriver::OnEvent(const irr::SEvent &event)
return false;
} // OnEvent
// ----------------------------------------------------------------------------
bool IrrDriver::supportsSplatting()
{
#ifndef SERVER_ONLY
return CVS->isGLSL();
#else
return false;
#endif
} // supportsSplatting
// ----------------------------------------------------------------------------
scene::ISceneNode *IrrDriver::addLight(const core::vector3df &pos,
float energy, float radius,

View File

@ -289,7 +289,6 @@ public:
core::position2di getMouseLocation();
void printRenderStats();
bool supportsSplatting();
void requestScreenshot();
class GPUTimer &getGPUTimer(unsigned);

View File

@ -20,8 +20,6 @@
#include "graphics/central_settings.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/lod_node.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/material.hpp"
#include "config/user_config.hpp"
#include "karts/abstract_kart.hpp"
@ -196,19 +194,6 @@ void LODNode::OnRegisterSceneNode()
assert(node != NULL);
mesh = node->getMesh();
}
for (unsigned int n=0; n<mesh->getMeshBufferCount(); n++)
{
scene::IMeshBuffer* mb = mesh->getMeshBuffer(n);
video::ITexture* t = mb->getMaterial().getTexture(0);
if (t == NULL) continue;
Material* m = material_manager->getMaterialFor(t, mb);
if (m != NULL)
{
m->onMadeVisible(mb);
}
}
}
else if (m_previous_visibility == WAS_SHOWN && !shown)
{
@ -228,17 +213,6 @@ void LODNode::OnRegisterSceneNode()
mesh = node->getMesh();
}
for (unsigned int n=0; n<mesh->getMeshBufferCount(); n++)
{
scene::IMeshBuffer* mb = mesh->getMeshBuffer(n);
video::ITexture* t = mb->getMaterial().getTexture(0);
if (t == NULL) continue;
Material* m = material_manager->getMaterialFor(t, mb);
if (m != NULL)
{
m->onHidden(mb);
}
}
}
else if (m_previous_visibility == FIRST_PASS && !shown)
{
@ -257,18 +231,6 @@ void LODNode::OnRegisterSceneNode()
assert(node != NULL);
mesh = node->getMesh();
}
for (unsigned int n=0; n<mesh->getMeshBufferCount(); n++)
{
scene::IMeshBuffer* mb = mesh->getMeshBuffer(n);
video::ITexture* t = mb->getMaterial().getTexture(0);
if(!t) continue;
Material* m = material_manager->getMaterialFor(t, mb);
if (m != NULL)
{
m->isInitiallyHidden(mb);
}
}
}
}

View File

@ -56,7 +56,6 @@ const unsigned int VCLAMP = 2;
Material::Material(const XMLNode *node, bool deprecated)
{
m_shader_name = "solid";
m_shader_type = SHADERTYPE_SOLID;
m_deprecated = deprecated;
m_installed = false;
@ -154,12 +153,9 @@ Material::Material(const XMLNode *node, bool deprecated)
node->get("max-speed", &m_max_speed_fraction );
node->get("slowdown-time", &m_slowdown_time );
node->get("backface-culling", &m_backface_culling );
node->get("disable-z-write", &m_disable_z_write );
node->get("colorizable", &m_colorizable );
node->get("colorization-factor", &m_colorization_factor);
node->get("hue-settings", &m_hue_settings );
node->get("fog", &m_fog );
node->get("mask", &m_mask );
node->get("colorization-mask", &m_colorization_mask );
@ -195,50 +191,7 @@ Material::Material(const XMLNode *node, bool deprecated)
s = "solid";
std::string normal_map_tex;
node->get("normal-map", &normal_map_tex);
if (node->get("shader", &s))
{
if (s == "solid")
{
m_shader_type = SHADERTYPE_SOLID;
}
else if (s == "unlit")
{
m_shader_type = SHADERTYPE_SOLID_UNLIT;
}
else if (s == "additive")
{
m_shader_type = SHADERTYPE_ADDITIVE;
}
else if (s == "alphatest")
{
m_shader_type = SHADERTYPE_ALPHA_TEST;
}
else if (s == "alphablend")
{
m_shader_type = SHADERTYPE_ALPHA_BLEND;
}
else if (s == "spheremap")
{
m_shader_type = SHADERTYPE_SPHERE_MAP;
}
else if (s == "water_shader")
{
m_shader_type = SHADERTYPE_WATER;
}
else if (s == "grass")
{
m_shader_type = SHADERTYPE_VEGETATION;
}
else if (s == "splatting")
{
m_shader_type = SHADERTYPE_SPLATTING;
node->get("splatting-texture-1", &m_sampler_path[2]);
node->get("splatting-texture-2", &m_sampler_path[3]);
node->get("splatting-texture-3", &m_sampler_path[4]);
node->get("splatting-texture-4", &m_sampler_path[5]);
}
}
else
if (!node->get("shader", &s))
{
// BACKWARS COMPATIBILITY, EVENTUALLY REMOVE
@ -247,7 +200,6 @@ Material::Material(const XMLNode *node, bool deprecated)
if (b)
{
m_shader_name = "alphablend";
m_shader_type = SHADERTYPE_ADDITIVE;
}
b = false;
@ -255,7 +207,6 @@ Material::Material(const XMLNode *node, bool deprecated)
if (b)
{
m_shader_name = "alphatest";
m_shader_type = SHADERTYPE_ALPHA_TEST;
}
//node->get("lightmap", &m_lightmap);
@ -265,7 +216,6 @@ Material::Material(const XMLNode *node, bool deprecated)
if (b)
{
m_shader_name = "alphablend";
m_shader_type = SHADERTYPE_ALPHA_BLEND;
}
b = true;
@ -273,36 +223,24 @@ Material::Material(const XMLNode *node, bool deprecated)
if (!b)
{
m_shader_name = "unlit";
m_shader_type = SHADERTYPE_SOLID_UNLIT;
}
b = false;
node->get("smooth-reflection", &b);
if (b)
m_shader_type = SHADERTYPE_SPHERE_MAP;
if (node->get("compositing", &s))
{
if (s == "blend")
{
m_shader_name = "alphablend";
m_shader_type = SHADERTYPE_ALPHA_BLEND;
}
else if (s == "test")
{
m_shader_name = "alphatest";
m_shader_type = SHADERTYPE_ALPHA_TEST;
}
else if (s == "additive")
{
m_shader_name = "additive";
m_shader_type = SHADERTYPE_ADDITIVE;
}
else if (s == "coverage")
{
m_shader_name = "alphatest";
m_shader_type = SHADERTYPE_ALPHA_TEST;
}
else if (s != "none")
Log::warn("material", "Unknown compositing mode '%s'", s.c_str());
@ -311,31 +249,10 @@ Material::Material(const XMLNode *node, bool deprecated)
s = "";
node->get("graphical-effect", &s);
if (s == "grass")
if (s == "normal_map")
{
m_shader_type = SHADERTYPE_VEGETATION;
}
else if (s == "water_shader")
{
m_shader_type = SHADERTYPE_WATER;
}
else if (s == "normal_map")
{
m_shader_type = SHADERTYPE_SOLID;
node->get("normal-map", &normal_map_tex);
}
else if (s == "spheremap")
{
m_shader_type = SHADERTYPE_SPHERE_MAP;
}
else if (s == "splatting")
{
m_shader_type = SHADERTYPE_SPLATTING;
node->get("splatting-texture-1", &m_sampler_path[2]);
node->get("splatting-texture-2", &m_sampler_path[3]);
node->get("splatting-texture-3", &m_sampler_path[4]);
node->get("splatting-texture-4", &m_sampler_path[5]);
}
else if (s == "none")
{
}
@ -361,21 +278,6 @@ Material::Material(const XMLNode *node, bool deprecated)
"Could not find normal map image in materials.xml");
}
}
bool sphere_map = false;
node->get("sphere", &sphere_map);
if (sphere_map)
{
m_shader_type = SHADERTYPE_SPHERE_MAP;
}
bool water_shader = false;
node->get("water-shader", &water_shader);
if (water_shader)
{
m_shader_type = SHADERTYPE_WATER;
}
// ---- End backwards compatibility
}
@ -434,29 +336,12 @@ Material::Material(const XMLNode *node, bool deprecated)
m_sampler_path[i] = "";
}
}
#ifndef SERVER_ONLY
if (ProfileWorld::isNoGraphics() || !CVS->isDefferedEnabled())
{
for (int i = 2; i < 6; i++)
{
// When advanced pipeline is off only .spm uv textures are used
m_sampler_path[i] = "";
}
}
#endif
loadContainerId();
core::stringc texfname(m_texname.c_str());
texfname.make_lower();
m_texname = texfname.c_str();
if (m_disable_z_write && m_shader_type != SHADERTYPE_ALPHA_BLEND && m_shader_type != SHADERTYPE_ADDITIVE)
{
Log::debug("material", "Disabling writes to z buffer only makes sense when compositing is blending or additive (for %s)", m_texname.c_str());
m_disable_z_write = false;
}
// Terrain-specifc sound effect
const unsigned int children_count = node->getNumNodes();
for (unsigned int i=0; i<children_count; i++)
@ -519,7 +404,7 @@ void Material::loadContainerId()
if (!file_manager->searchTextureContainerId(m_container_id, m_texname))
{
Log::warn("Material", "Missing container id for %s, no texture"
" compression for it will be done", m_texname.c_str());
" compression for it will be done.", m_texname.c_str());
}
}
} // loadContainerId
@ -587,8 +472,6 @@ void Material::init()
{
m_texture = NULL;
m_clamp_tex = 0;
m_shader_type = SHADERTYPE_SOLID;
m_backface_culling = true;
m_high_tire_adhesion = false;
m_below_surface = false;
m_falling_effect = false;
@ -597,11 +480,9 @@ void Material::init()
m_drive_reset = false;
m_mirror_axis_when_reverse = ' ';
m_collision_reaction = NORMAL;
m_disable_z_write = false;
m_colorizable = false;
m_colorization_factor = 0.0f;
m_colorization_mask = "";
m_fog = true;
m_max_speed_fraction = 1.0f;
m_slowdown_time = 1.0f;
m_sfx_name = "";
@ -878,10 +759,8 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
m_texname.c_str());
}
// Backface culling
if(!m_backface_culling)
m->setFlag(video::EMF_BACK_FACE_CULLING, false);
// Default solid
m->MaterialType = video::EMT_SOLID;
if (race_manager->getReverseTrack() &&
m_mirror_axis_when_reverse != ' ')
{
@ -900,20 +779,19 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
}
} // reverse track and texture needs mirroring
if (m_shader_type == SHADERTYPE_SOLID_UNLIT)
if (m_shader_name == "unlit")
{
m->AmbientColor = video::SColor(255, 255, 255, 255);
m->DiffuseColor = video::SColor(255, 255, 255, 255);
m->EmissiveColor = video::SColor(255, 255, 255, 255);
m->SpecularColor = video::SColor(255, 255, 255, 255);
m->MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
}
if (m_shader_type == SHADERTYPE_ALPHA_TEST)
else if (m_shader_name == "alphatest")
{
m->MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
}
if (m_shader_type == SHADERTYPE_ALPHA_BLEND)
else if (m_shader_name == "alphablend" || m_shader_name == "displace")
{
// EMT_TRANSPARENT_ALPHA_CHANNEL doesn't include vertex color alpha into
// account, which messes up fading in/out effects. So we use the more
@ -925,8 +803,7 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
video::EMFN_MODULATE_1X,
video::EAS_TEXTURE | video::EAS_VERTEX_COLOR);
}
if (m_shader_type == SHADERTYPE_ADDITIVE)
else if (m_shader_name == "additive")
{
// EMT_TRANSPARENT_ADD_COLOR doesn't include vertex color alpha into
// account, which messes up fading in/out effects. So we use the
@ -938,31 +815,7 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
video::EAS_TEXTURE |
video::EAS_VERTEX_COLOR);
}
if (m_shader_type == SHADERTYPE_SPHERE_MAP)
{
m->MaterialType = video::EMT_SPHERE_MAP;
}
if (m_shader_type == SHADERTYPE_SPLATTING)
{
m->MaterialType = video::EMT_SOLID;
}
// Modify lightmap materials so that vertex colors are taken into account.
// But disable lighting because we assume all lighting is already part
// of the lightmap
if (m->MaterialType == video::EMT_LIGHTMAP)
{
m->MaterialType = video::EMT_LIGHTMAP_LIGHTING;
m->AmbientColor = video::SColor(255, 255, 255, 255);
m->DiffuseColor = video::SColor(255, 255, 255, 255);
m->EmissiveColor = video::SColor(255, 255, 255, 255);
m->SpecularColor = video::SColor(255, 255, 255, 255);
}
if (m_shader_type == SHADERTYPE_VEGETATION)
else if (m_shader_name == "grass")
{
m->MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
@ -979,9 +832,10 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
#endif
}
if (m_disable_z_write)
if (isTransparent())
{
m->ZWriteEnable = false;
m->BackfaceCulling = false;
}
#ifdef DEBUG
@ -1039,66 +893,3 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
#endif
} // setMaterialProperties
//-----------------------------------------------------------------------------
void Material::adjustForFog(scene::ISceneNode* parent, video::SMaterial *m,
bool use_fog) const
{
#ifndef SERVER_ONLY
if (CVS->isGLSL())
{
// to disable fog in the new pipeline, we slightly abuse the steps :
// moving an object into the transparent pass will make it rendered
// above fog and thus unaffected by it
if (use_fog && !m_fog && m_shader_type != SHADERTYPE_ALPHA_BLEND && m_shader_type != SHADERTYPE_ADDITIVE)
{
//m->ZWriteEnable = true;
//m->MaterialType = video::EMT_ONETEXTURE_BLEND;
//m->MaterialTypeParam =
// pack_textureBlendFunc(video::EBF_SRC_ALPHA,
// video::EBF_ONE_MINUS_SRC_ALPHA,
// video::EMFN_MODULATE_1X,
// video::EAS_TEXTURE | video::EAS_VERTEX_COLOR);
}
}
else
{
m->setFlag(video::EMF_FOG_ENABLE, m_fog && use_fog);
if (parent != NULL)
parent->setMaterialFlag(video::EMF_FOG_ENABLE, m_fog && use_fog);
}
#endif
} // adjustForFog
//-----------------------------------------------------------------------------
/** Callback from LOD nodes to create some effects */
void Material::onMadeVisible(scene::IMeshBuffer* who)
{
#ifndef SERVER_ONLY
if (!CVS->isGLSL()) return;
#endif
}
//-----------------------------------------------------------------------------
/** Callback from LOD nodes to create some effects */
void Material::onHidden(scene::IMeshBuffer* who)
{
#ifndef SERVER_ONLY
if (!CVS->isGLSL()) return;
#endif
}
//-----------------------------------------------------------------------------
void Material::isInitiallyHidden(scene::IMeshBuffer* who)
{
#ifndef SERVER_ONLY
if (!CVS->isGLSL()) return;
#endif
}
//-----------------------------------------------------------------------------

View File

@ -46,23 +46,6 @@ class ParticleKind;
class Material : public NoCopy
{
public:
enum ShaderType
{
SHADERTYPE_SOLID = 0,
SHADERTYPE_ALPHA_TEST,
SHADERTYPE_ALPHA_BLEND,
SHADERTYPE_ADDITIVE,
SHADERTYPE_SOLID_UNLIT,
/** Effect that makes grass wave as in the wind */
SHADERTYPE_VEGETATION,
SHADERTYPE_WATER,
SHADERTYPE_SPHERE_MAP,
SHADERTYPE_NORMAL_MAP,
SHADERTYPE_DETAIL_MAP,
SHADERTYPE_SPLATTING,
SHADERTYPE_COUNT,
};
enum ParticleConditions
{
EMIT_ON_DRIVE = 0,
@ -93,8 +76,6 @@ private:
* "" if no special sfx exists. */
std::string m_sfx_name;
ShaderType m_shader_type;
/** Either ' ' (no mirroring), 'U' or 'V' if a texture needs to be
* mirrored when driving in reverse. Typically used for arrows indicating
* the direction. */
@ -135,14 +116,6 @@ private:
* plants that a kart can just drive through. */
bool m_ignore;
bool m_fog;
/** True if backface culliing should be enabled. */
bool m_backface_culling;
/** Set to true to disable writing to the Z buffer. Usually to be used with alpha blending */
bool m_disable_z_write;
/** True if the material shouldn't be "slippy" at an angle */
bool m_high_tire_adhesion;
@ -250,11 +223,6 @@ public:
void setSFXSpeed(SFXBase *sfx, float speed, bool should_be_paused) const;
void setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* mb);
void adjustForFog(scene::ISceneNode* parent, video::SMaterial *m,
bool use_fog) const;
void onMadeVisible(scene::IMeshBuffer* who);
void onHidden(scene::IMeshBuffer* who);
void isInitiallyHidden(scene::IMeshBuffer* who);
/** Returns the ITexture associated with this material. */
video::ITexture *getTexture(bool srgb = true, bool premul_alpha = false);
@ -276,6 +244,8 @@ public:
*/
float getColorizationFactor () const { return m_colorization_factor; }
// ------------------------------------------------------------------------
bool hasRandomHue() const { return !m_hue_settings.empty(); }
// ------------------------------------------------------------------------
/** Returns a random hue when colorized.
*/
float getRandomHue()
@ -306,9 +276,8 @@ public:
// ------------------------------------------------------------------------
bool isTransparent () const
{
return m_shader_type == SHADERTYPE_ADDITIVE ||
m_shader_type == SHADERTYPE_ALPHA_BLEND ||
m_shader_type == SHADERTYPE_ALPHA_TEST;
return m_shader_name == "additive" || m_shader_name == "alphablend" ||
m_shader_name == "displace";
}
// ------------------------------------------------------------------------
@ -334,11 +303,6 @@ public:
/** Returns the name of a special sfx to play while a kart is on this
* terrain. The string will be "" if no special sfx exists. */
const std::string &getSFXName() const { return m_sfx_name; }
// ------------------------------------------------------------------------
/** Returns if fog is enabled. */
bool isFogEnabled() const { return m_fog; }
// ------------------------------------------------------------------------
/** \brief Get the kind of particles that are to be used on this material,
* in the given conditions.
@ -380,9 +344,6 @@ public:
* on lower speeds. A negative value indicates no minimum speed. */
float getZipperMinSpeed() const { return m_zipper_min_speed; }
// ------------------------------------------------------------------------
ShaderType getShaderType() const { return m_shader_type; }
void setShaderType(ShaderType st) { m_shader_type = st; }
// ------------------------------------------------------------------------
/** True if this texture should have the U coordinates mirrored. */
char getMirrorAxisInReverse() const { return m_mirror_axis_when_reverse; }
// ------------------------------------------------------------------------
@ -391,14 +352,14 @@ public:
const std::string& getColorizationMask() const
{ return m_colorization_mask; }
// ------------------------------------------------------------------------
void setShaderName(const std::string& name) { m_shader_name = name; }
// ------------------------------------------------------------------------
const std::string& getShaderName() const { return m_shader_name; }
// ------------------------------------------------------------------------
/* This is used for finding correct material for spm*/
const std::string& getUVTwoTexture() const
{ return m_uv_two_tex; }
// ------------------------------------------------------------------------
bool backFaceCulling() const { return m_backface_culling; }
// ------------------------------------------------------------------------
bool use2UV() const { return !m_uv_two_tex.empty(); }
// ------------------------------------------------------------------------
const std::string& getSamplerPath(unsigned layer) const

View File

@ -220,28 +220,7 @@ Material* MaterialManager::getDefaultSPMaterial(const std::string& shader_name,
return m;
} // getDefaultSPMaterial
//-----------------------------------------------------------------------------
void MaterialManager::adjustForFog(video::ITexture* t,
scene::IMeshBuffer *mb,
scene::ISceneNode* parent,
bool use_fog) const
{
const std::string image = StringUtils::getBasename(core::stringc(t->getName()).c_str());
// Search backward so that temporary (track) textures are found first
for(int i = (int)m_materials.size()-1; i>=0; i-- )
{
if (m_materials[i]->getTexFname()==image)
{
m_materials[i]->adjustForFog(parent, &(mb->getMaterial()), use_fog);
return;
}
} // for i
} // adjustForFog
//-----------------------------------------------------------------------------
void MaterialManager::setAllUntexturedMaterialFlags(scene::IMeshBuffer *mb)
{
irr::video::SMaterial& material = mb->getMaterial();
@ -257,6 +236,7 @@ void MaterialManager::setAllUntexturedMaterialFlags(scene::IMeshBuffer *mb)
}
}
//-----------------------------------------------------------------------------
int MaterialManager::addEntity(Material *m)
{

View File

@ -66,11 +66,6 @@ public:
const std::string& def_shader_name = "solid");
void setAllMaterialFlags(video::ITexture* t,
scene::IMeshBuffer *mb);
void adjustForFog(video::ITexture* t,
scene::IMeshBuffer *mb,
scene::ISceneNode* parent,
bool use_fog) const;
void setAllUntexturedMaterialFlags(scene::IMeshBuffer *mb);
int addEntity (Material *m);

View File

@ -33,6 +33,7 @@ MovingTexture::MovingTexture(core::matrix4 *matrix, const XMLNode &node)
m_x = 0.0f;
m_y = 0.0f;
m_count = 0.0f;
m_sp_tm = NULL;
if (m_matrix)
{
@ -49,8 +50,6 @@ MovingTexture::MovingTexture(core::matrix4 *matrix, const XMLNode &node)
node.get("dt", &m_dt);
node.get("animByStep", &m_isAnimatedByStep);
m_sp_tm[0].reset(new float(0.0f));
m_sp_tm[1].reset(new float(0.0f));
} // MovingTexture
//-----------------------------------------------------------------------------
@ -71,8 +70,8 @@ MovingTexture::MovingTexture(core::matrix4 *matrix, float dx, float dy)
core::vector3df v = m_matrix->getTranslation();
m_x = v.X;
m_y = v.Y;
m_sp_tm[0].reset(new float(0.0f));
m_sp_tm[1].reset(new float(0.0f));
m_count = 0.0f;
m_sp_tm = NULL;
} // MovingTexture
//-----------------------------------------------------------------------------
@ -85,9 +84,9 @@ MovingTexture::MovingTexture(float dx, float dy)
m_dy = dy;
m_x = 0;
m_y = 0;
m_count = 0.0f;
m_matrix = NULL;
m_sp_tm[0].reset(new float(0.0f));
m_sp_tm[1].reset(new float(0.0f));
m_sp_tm = NULL;
} // MovingTexture
//-----------------------------------------------------------------------------
@ -103,12 +102,15 @@ MovingTexture::~MovingTexture()
void MovingTexture::reset()
{
m_x = m_y = 0;
*m_sp_tm[0] = 0;
*m_sp_tm[1] = 0;
if (m_matrix)
{
m_matrix->setTextureTranslate(m_x, m_y);
}
else if (m_sp_tm)
{
m_sp_tm[0] = 0.0f;
m_sp_tm[1] = 0.0f;
}
} // reset
//-----------------------------------------------------------------------------
@ -134,10 +136,10 @@ void MovingTexture::update(float dt)
{
m_matrix->setTextureTranslate(m_x, m_y);
}
else
else if (m_sp_tm)
{
*m_sp_tm[0] = m_x;
*m_sp_tm[1] = m_y;
m_sp_tm[0] = m_x;
m_sp_tm[1] = m_y;
}
}
}
@ -151,10 +153,10 @@ void MovingTexture::update(float dt)
{
m_matrix->setTextureTranslate(m_x, m_y);
}
else
else if (m_sp_tm)
{
*m_sp_tm[0] = m_x;
*m_sp_tm[1] = m_y;
m_sp_tm[0] = m_x;
m_sp_tm[1] = m_y;
}
}
} // update

View File

@ -20,8 +20,6 @@
#define MOVING_TEXTURE_HPP
#include "utils/no_copy.hpp"
#include <array>
#include <memory>
#include <string>
#include <matrix4.h>
using namespace irr;
@ -49,7 +47,7 @@ private:
core::matrix4 *m_matrix;
// For sp
std::array<std::shared_ptr<float>, 2> m_sp_tm;
float* m_sp_tm;
public:
MovingTexture(core::matrix4 *matrix, const XMLNode &node);
@ -61,7 +59,7 @@ public:
void setSpeed(float dx, float dy) {m_dx = dx; m_dy = dy;}
/** Sets the texture matrix. */
void setTextureMatrix(core::matrix4 *matrix) {m_matrix=matrix;}
std::array<std::shared_ptr<float>, 2> getSPTM() const { return m_sp_tm; }
void setSPTM(float* sp_tm) { m_sp_tm = sp_tm; }
virtual void update (float dt);
virtual void reset ();
}

View File

@ -232,8 +232,8 @@ Material* ParticleKind::getMaterial() const
Material* material = material_manager->getMaterial(m_material_file);
if (material == NULL ||
material->getTexture(true/*srgb*/,
material->getShaderType() == Material::SHADERTYPE_ADDITIVE ||
material->getShaderType() == Material::SHADERTYPE_ALPHA_BLEND ?
material->getShaderName() == "additive" ||
material->getShaderName() == "alphablend" ?
true : false/*premul_alpha*/) == NULL)
{
throw std::runtime_error("[ParticleKind] Cannot locate file " + m_material_file);

View File

@ -248,9 +248,7 @@ void Referee::selectReadySetGo(int rsg)
SP::SPMeshNode* spmn = dynamic_cast<SP::SPMeshNode*>(m_scene_node);
if (spmn)
{
spmn->setTextureMatrix(m_st_traffic_buffer,
{{ std::make_shared<float>(0.0f),
std::make_shared<float>(rsg * 0.333f) }});
spmn->setTextureMatrix(m_st_traffic_buffer, {{ 0.0f, rsg * 0.333f }});
}
else
{

View File

@ -54,6 +54,7 @@ protected:
/** OpenGL's program id. */
GLuint m_program;
std::vector<std::shared_ptr<GLuint> > m_shaders;
// ========================================================================
/** Ends recursion. */
@ -67,13 +68,13 @@ protected:
void loadAndAttachShader(GLint shader_type, const std::string &name,
Types ... args)
{
GLint shader_id = ShaderFilesManager::getInstance()
auto shader_id = ShaderFilesManager::getInstance()
->getShaderFile(name, shader_type);
glAttachShader(m_program, shader_id);
GLint is_deleted = GL_TRUE;
glGetShaderiv(shader_id, GL_DELETE_STATUS, &is_deleted);
if (is_deleted == GL_FALSE)
glDeleteShader(shader_id);
if (shader_id)
{
m_shaders.push_back(shader_id);
glAttachShader(m_program, *shader_id);
}
loadAndAttachShader(args...);
} // loadAndAttachShader
// ------------------------------------------------------------------------
@ -87,6 +88,10 @@ protected:
public:
ShaderBase();
~ShaderBase()
{
glDeleteProgram(m_program);
}
int loadTFBProgram(const std::string &vertex_file_path,
const char **varyings,
unsigned varyingscount);
@ -346,7 +351,8 @@ public:
GLint Result = GL_FALSE;
glGetProgramiv(m_program, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE) {
if (Result == GL_FALSE)
{
int info_length;
Log::error("Shader", "Error when linking these shaders :");
printFileList(args...);
@ -356,10 +362,12 @@ public:
Log::error("Shader", error_message);
delete[] error_message;
}
// After linking all shaders can be detached
for (auto shader : m_shaders)
{
glDetachShader(m_program, *shader);
}
} // loadProgram
// ------------------------------------------------------------------------
virtual void bindCustomTextures() {}
// ------------------------------------------------------------------------
void drawFullScreenEffect(Args...args)
{

View File

@ -383,7 +383,7 @@ void ShaderBasedRenderer::renderSceneDeferred(scene::ICameraSceneNode * const ca
PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00);
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_TRANSPARENT));
SP::draw(SP::RP_1ST, SP::DCT_TRANSPARENT);
SP::draw(SP::RP_2ND, SP::DCT_TRANSPARENT);
SP::draw(SP::RP_RESERVED, SP::DCT_TRANSPARENT);
PROFILER_POP_CPU_MARKER();
}
@ -493,7 +493,7 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode,
PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00);
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_TRANSPARENT));
SP::draw(SP::RP_1ST, SP::DCT_TRANSPARENT);
SP::draw(SP::RP_2ND, SP::DCT_TRANSPARENT);
SP::draw(SP::RP_RESERVED, SP::DCT_TRANSPARENT);
PROFILER_POP_CPU_MARKER();
}
@ -639,9 +639,9 @@ ShaderBasedRenderer::~ShaderBasedRenderer()
delete m_spherical_harmonics;
delete m_skybox;
delete m_rtts;
ShaderFilesManager::kill();
ShaderBase::killShaders();
SP::destroy();
ShaderFilesManager::kill();
}
// ----------------------------------------------------------------------------
@ -886,15 +886,15 @@ void ShaderBasedRenderer::renderToTexture(GL3RenderTarget *render_target,
if (CVS->isDefferedEnabled())
{
renderSceneDeferred(camera, dt, false, true);
render_target->setFrameBuffer(m_post_processing
->render(camera, false, m_rtts));
}
else
{
renderScene(camera, dt, false, true);
render_target->setFrameBuffer(&m_rtts->getFBO(FBO_COLORS));
}
render_target->setFrameBuffer(m_post_processing
->render(camera, false, m_rtts));
// reset
glViewport(0, 0,
irr_driver->getActualScreenSize().Width,

View File

@ -54,16 +54,18 @@ const std::string& ShaderFilesManager::getHeader()
// ----------------------------------------------------------------------------
void ShaderFilesManager::readFile(const std::string& file,
std::ostringstream& code)
std::ostringstream& code, bool not_header)
{
std::ifstream stream(file_manager->getShader(file), std::ios::in);
std::ifstream stream(((file.find('/') != std::string::npos ||
file.find('\\') != std::string::npos) && not_header) ?
file : file_manager->getShader(file), std::ios::in);
if (!stream.is_open())
{
Log::error("ShaderFilesManager", "Can not open '%s'.", file.c_str());
return;
}
const std::string stk_include = "#stk_include";
std::string line;
@ -72,6 +74,7 @@ void ShaderFilesManager::readFile(const std::string& file,
const std::size_t pos = line.find(stk_include);
// load the custom file pointed by the #stk_include directive
// we only look for #stk_include in official shader directory
if (pos != std::string::npos)
{
// find the start "
@ -97,7 +100,7 @@ void ShaderFilesManager::readFile(const std::string& file,
filename = filename.substr(0, pos);
// read the whole include file
readFile(filename, code);
readFile(filename, code, false/*not_header*/);
}
else
{
@ -113,9 +116,16 @@ void ShaderFilesManager::readFile(const std::string& file,
* \param file Filename of the shader to load.
* \param type Type of the shader.
*/
GLuint ShaderFilesManager::loadShader(const std::string &file, unsigned type)
ShaderFilesManager::SharedShader ShaderFilesManager::loadShader
(const std::string& full_path, unsigned type)
{
const GLuint id = glCreateShader(type);
GLuint* ss_ptr = new GLuint;
*ss_ptr = glCreateShader(type);
SharedShader ss(ss_ptr, [](GLuint* ss)
{
glDeleteShader(*ss);
delete ss;
});
std::ostringstream code;
#if !defined(USE_GLES2)
@ -156,7 +166,7 @@ GLuint ShaderFilesManager::loadShader(const std::string &file, unsigned type)
code << "#define Converts_10bit_Vector\n";
}
code << "//" << file << "\n";
code << "//" << full_path << "\n";
if (!CVS->isARBUniformBufferObjectUsable())
code << "#define UBO_DISABLED\n";
if (CVS->needsVertexIdWorkaround())
@ -191,34 +201,37 @@ GLuint ShaderFilesManager::loadShader(const std::string &file, unsigned type)
code << getHeader();
readFile(file, code);
readFile(full_path, code);
Log::info("ShaderFilesManager", "Compiling shader : %s", file.c_str());
Log::info("ShaderFilesManager", "Compiling shader: %s",
full_path.c_str());
const std::string &source = code.str();
char const *source_pointer = source.c_str();
int len = (int)source.size();
glShaderSource(id, 1, &source_pointer, &len);
glCompileShader(id);
glShaderSource(*ss, 1, &source_pointer, &len);
glCompileShader(*ss);
GLint result = GL_FALSE;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
glGetShaderiv(*ss, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
// failed to compile
int info_length;
Log::error("ShaderFilesManager", "Error in shader %s", file.c_str());
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &info_length);
Log::error("ShaderFilesManager", "Error in shader %s",
full_path.c_str());
glGetShaderiv(*ss, GL_INFO_LOG_LENGTH, &info_length);
if (info_length < 0)
info_length = 1024;
char *error_message = new char[info_length];
error_message[0] = 0;
glGetShaderInfoLog(id, info_length, NULL, error_message);
glGetShaderInfoLog(*ss, info_length, NULL, error_message);
Log::error("ShaderFilesManager", error_message);
delete[] error_message;
return NULL;
}
glGetError();
return id;
return ss;
} // loadShader
// ----------------------------------------------------------------------------
@ -226,34 +239,40 @@ GLuint ShaderFilesManager::loadShader(const std::string &file, unsigned type)
* \param file Filename of the shader to load.
* \param type Type of the shader.
*/
GLuint ShaderFilesManager::addShaderFile(const std::string &file, unsigned type)
ShaderFilesManager::SharedShader ShaderFilesManager::addShaderFile
(const std::string& full_path, unsigned type)
{
#ifdef DEBUG
// Make sure no duplicated shader is added somewhere else
std::unordered_map<std::string, GLuint>::const_iterator i =
m_shader_files_loaded.find(file);
auto i = m_shader_files_loaded.find(full_path);
assert(i == m_shader_files_loaded.end());
#endif
const GLuint id = loadShader(file, type);
m_shader_files_loaded[file] = id;
return id;
SharedShader ss = loadShader(full_path, type);
m_shader_files_loaded[full_path] = ss;
return ss;
} // addShaderFile
// ----------------------------------------------------------------------------
/** Get a shader file. If the shader is not already in the cache it will be loaded and cached.
/** Get a shader file. If the shader is not already in the cache it will be
* loaded and cached.
* \param file Filename of the shader to load.
* \param type Type of the shader.
*/
GLuint ShaderFilesManager::getShaderFile(const std::string &file, unsigned type)
ShaderFilesManager::SharedShader ShaderFilesManager::getShaderFile
(const std::string &file, unsigned type)
{
const std::string full_path = (file.find('/') != std::string::npos ||
file.find('\\') != std::string::npos) ?
file : std::string(file_manager->getFileSystem()->getAbsolutePath
(file_manager->getShadersDir().c_str()).c_str()) + file;
// found in cache
auto it = m_shader_files_loaded.find(file);
auto it = m_shader_files_loaded.find(full_path);
if (it != m_shader_files_loaded.end())
return it->second;
// add to the cache now
return addShaderFile(file, type);
// add to the cache now
return addShaderFile(full_path, type);
} // getShaderFile
#endif // !SERVER_ONLY

View File

@ -21,38 +21,74 @@
#define HEADER_SHADER_FILES_MANAGER_HPP
#include "graphics/gl_headers.hpp"
#include "utils/log.hpp"
#include "utils/no_copy.hpp"
#include "utils/singleton.hpp"
#include <algorithm>
#include <cassert>
#include <string>
#include <memory>
#include <unordered_map>
class ShaderFilesManager : public Singleton<ShaderFilesManager>, NoCopy
{
private:
typedef std::shared_ptr<GLuint> SharedShader;
/**
* Map from a filename to a shader indentifier. Used for caching shaders.
* Map from a filename in full path to a shader indentifier.
* Used for caching shaders.
*/
std::unordered_map<std::string, GLuint> m_shader_files_loaded;
std::unordered_map<std::string, SharedShader> m_shader_files_loaded;
// ------------------------------------------------------------------------
const std::string& getHeader();
void readFile(const std::string& file, std::ostringstream& code);
// ------------------------------------------------------------------------
void readFile(const std::string& file, std::ostringstream& code,
bool not_header = true);
// ------------------------------------------------------------------------
SharedShader addShaderFile(const std::string& full_path, unsigned type);
public:
// ------------------------------------------------------------------------
ShaderFilesManager() {}
// ------------------------------------------------------------------------
~ShaderFilesManager() { clean(); }
~ShaderFilesManager()
{
removeAllShaderFiles();
}
// ------------------------------------------------------------------------
void clean() { m_shader_files_loaded.clear(); }
void removeAllShaderFiles()
{
removeUnusedShaderFiles();
if (!m_shader_files_loaded.empty())
{
#ifdef DEBUG
Log::error("ShaderFilesManager", "Some shader file > 1 ref_count");
#endif
m_shader_files_loaded.clear();
}
}
// ------------------------------------------------------------------------
GLuint loadShader(const std::string &file, unsigned type);
void removeUnusedShaderFiles()
{
for (auto it = m_shader_files_loaded.begin();
it != m_shader_files_loaded.end();)
{
if (it->second.use_count() == 1 || !it->second)
{
it = m_shader_files_loaded.erase(it);
}
else
{
it++;
}
}
}
// ------------------------------------------------------------------------
GLuint addShaderFile(const std::string &file, unsigned type);
SharedShader loadShader(const std::string& full_path, unsigned type);
// ------------------------------------------------------------------------
GLuint getShaderFile(const std::string &file, unsigned type);
SharedShader getShaderFile(const std::string& file, unsigned type);
}; // ShaderFilesManager

View File

@ -19,7 +19,7 @@
#include "graphics/shadow.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/skidding.hpp"
#include "graphics/sp/sp_base.hpp"
#include "graphics/sp/sp_shader_manager.hpp"
#include "graphics/sp/sp_dynamic_draw_call.hpp"
#include "physics/btKart.hpp"
#include "utils/mini_glm.hpp"
@ -31,7 +31,8 @@ Shadow::Shadow(Material* shadow_mat, const AbstractKart& kart)
: m_dy_dc(NULL), m_shadow_enabled(false), m_kart(kart)
{
m_dy_dc = std::make_shared<SP::SPDynamicDrawCall>
(scene::EPT_TRIANGLE_STRIP, SP::getSPShader("alphablend"), shadow_mat);
(scene::EPT_TRIANGLE_STRIP,
SP::SPShaderManager::get()->getSPShader("alphablend"), shadow_mat);
m_dy_dc->getVerticesVector().resize(4);
video::S3DVertexSkinnedMesh* v = m_dy_dc->getVerticesVector().data();

View File

@ -20,8 +20,8 @@
#include "graphics/show_curve.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/sp/sp_base.hpp"
#include "graphics/sp/sp_dynamic_draw_call.hpp"
#include "graphics/sp/sp_shader_manager.hpp"
#include "utils/mini_glm.hpp"
#include "utils/vec3.hpp"
@ -33,7 +33,8 @@ ShowCurve::ShowCurve(float width, float height,
m_first_vertices(true), m_visible(true)
{
m_dy_dc = std::make_shared<SP::SPDynamicDrawCall>
(irr::scene::EPT_TRIANGLES, SP::getSPShader("alphablend"),
(irr::scene::EPT_TRIANGLES,
SP::SPShaderManager::get()->getSPShader("alphablend"),
material_manager->getDefaultSPMaterial("alphablend"));
SP::addDynamicDrawCall(m_dy_dc);
} // ShowCurve

View File

@ -25,10 +25,9 @@
#include "karts/abstract_kart.hpp"
#include "karts/skidding.hpp"
#include "modes/world.hpp"
#include "graphics/sp/sp_base.hpp"
#include "graphics/sp/sp_dynamic_draw_call.hpp"
#include "graphics/sp/sp_per_object_uniform.hpp"
#include "graphics/sp/sp_shader.hpp"
#include "graphics/sp/sp_shader_manager.hpp"
#include "graphics/sp/sp_uniform_assigner.hpp"
#include "physics/btKart.hpp"
#include "utils/mini_glm.hpp"
@ -45,8 +44,8 @@ SkidMarks::SkidMarks(const AbstractKart& kart, float width) : m_kart(kart)
m_width = width;
m_material = material_manager->getMaterialSPM("skidmarks.png", "",
"alphablend");
m_shader = SP::getSPShader("alphablend");
assert(m_shader != NULL);
m_shader = SP::SPShaderManager::get()->getSPShader("alphablend");
assert(m_shader);
m_skid_marking = false;
} // SkidMark
@ -201,7 +200,7 @@ SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left,
const Vec3 &right,
const Vec3 &normal,
Material* material,
SP::SPShader* shader,
std::shared_ptr<SP::SPShader> shader,
float z_offset,
video::SColor* custom_color)
{

View File

@ -65,7 +65,7 @@ private:
Material* m_material;
/** Shader(alphablend) to use for the skid marks. */
SP::SPShader* m_shader;
std::shared_ptr<SP::SPShader> m_shader;
// ------------------------------------------------------------------------
class SkidMarkQuads : public NoCopy
@ -88,7 +88,7 @@ private:
public:
SkidMarkQuads (const Vec3 &left, const Vec3 &right,
const Vec3 &normal, Material* material,
SP::SPShader* shader,
std::shared_ptr<SP::SPShader> shader,
float z_offset, video::SColor* custom_color = NULL);
~SkidMarkQuads();
void add (const Vec3 &left,

View File

@ -21,10 +21,10 @@
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/sp/sp_base.hpp"
#include "graphics/sp/sp_dynamic_draw_call.hpp"
#include "graphics/sp/sp_mesh.hpp"
#include "graphics/sp/sp_mesh_node.hpp"
#include "graphics/sp/sp_shader_manager.hpp"
#include "graphics/sp/sp_uniform_assigner.hpp"
#include "io/file_manager.hpp"
#include "karts/abstract_kart.hpp"
@ -59,7 +59,7 @@ SlipStream::SlipStream(AbstractKart* kart) : MovingTexture(0, 0), m_kart(kart)
m_node->setVisible(false);
SP::SPMeshNode* spmn = dynamic_cast<SP::SPMeshNode*>(m_node);
assert(spmn);
spmn->setTextureMatrix(0, getSPTM());
setSPTM(spmn->getTextureMatrix(0).data());
}
#endif
@ -80,7 +80,8 @@ SlipStream::SlipStream(AbstractKart* kart) : MovingTexture(0, 0), m_kart(kart)
if (UserConfigParams::m_slipstream_debug)
{
m_debug_dc = std::make_shared<SP::SPDynamicDrawCall>
(scene::EPT_TRIANGLE_STRIP, SP::getSPShader("additive"),
(scene::EPT_TRIANGLE_STRIP,
SP::SPShaderManager::get()->getSPShader("additive"),
material_manager->getDefaultSPMaterial("additive"));
m_debug_dc->getVerticesVector().resize(4);
video::S3DVertexSkinnedMesh* v =

View File

@ -38,6 +38,7 @@
#include "graphics/sp/sp_mesh_buffer.hpp"
#include "graphics/sp/sp_mesh_node.hpp"
#include "graphics/sp/sp_shader.hpp"
#include "graphics/sp/sp_shader_manager.hpp"
#include "graphics/sp/sp_texture.hpp"
#include "graphics/sp/sp_texture_manager.hpp"
#include "graphics/sp/sp_uniform_assigner.hpp"
@ -68,7 +69,7 @@ bool sp_culling = true;
// ----------------------------------------------------------------------------
bool g_handle_shadow = false;
// ----------------------------------------------------------------------------
std::unordered_map<std::string, SPShader*> g_shaders;
SPShader* g_normal_visualizer = NULL;
// ----------------------------------------------------------------------------
SPShader* g_glow_shader = NULL;
// ----------------------------------------------------------------------------
@ -94,8 +95,6 @@ std::array<GLuint, 1> sp_prefilled_tex;
// ----------------------------------------------------------------------------
std::vector<float> g_bounding_boxes;
// ----------------------------------------------------------------------------
core::vector3df g_wind_dir;
// ----------------------------------------------------------------------------
std::vector<std::shared_ptr<SPDynamicDrawCall> > g_dy_dc;
// ----------------------------------------------------------------------------
float g_frustums[5][24] = { { } };
@ -121,82 +120,15 @@ void initSTKRenderer(ShaderBasedRenderer* sbr)
// ----------------------------------------------------------------------------
GLuint sp_mat_ubo[MAX_PLAYER_COUNT][3] = {};
// ----------------------------------------------------------------------------
bool sp_first_frame = false;
// ----------------------------------------------------------------------------
GLuint sp_fog_ubo = 0;
// ----------------------------------------------------------------------------
core::vector3df sp_wind_dir;
// ----------------------------------------------------------------------------
GLuint g_skinning_tex;
// ----------------------------------------------------------------------------
GLuint g_skinning_buf;
// ----------------------------------------------------------------------------
unsigned g_skinning_size;
// ----------------------------------------------------------------------------
void shadowCascadeUniformAssigner(SPUniformAssigner* ua)
{
ua->setValue(sp_cur_shadow_cascade);
} // shadowCascadeUniformAssigner
// ----------------------------------------------------------------------------
void fogUniformAssigner(SPUniformAssigner* ua)
{
int fog_enable = Track::getCurrentTrack() ?
Track::getCurrentTrack()->isFogEnabled() ? 1 : 0 : 0;
ua->setValue(fog_enable);
} // fogUniformAssigner
// ----------------------------------------------------------------------------
void zeroAlphaUniformAssigner(SPUniformAssigner* ua)
{
ua->setValue(0.0f);
} // zeroAlphaUniformAssigner
// ----------------------------------------------------------------------------
void ghostAlphaAssigner(SPUniformAssigner* ua)
{
float alpha = 1.0f;
if (Track::getCurrentTrack())
{
const video::SColor& c = Track::getCurrentTrack()->getSunColor();
float y = 0.2126f * c.getRed() + 0.7152f * c.getGreen() +
0.0722f * c.getBlue();
alpha = y > 128.0f ? 0.5f : 0.35f;
}
ua->setValue(alpha);
} // ghostAlphaAssigner
// ----------------------------------------------------------------------------
void alphaBlendUse()
{
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} // alphaBlendUse
// ----------------------------------------------------------------------------
void additiveUse()
{
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
} // additiveUse
// ----------------------------------------------------------------------------
void ghostUse()
{
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} // ghostUse
// ----------------------------------------------------------------------------
void displaceUniformAssigner(SP::SPUniformAssigner* ua)
{
@ -227,6 +159,77 @@ void displaceUniformAssigner(SP::SPUniformAssigner* ua)
ua->setValue(g_direction);
} // displaceUniformAssigner
// ----------------------------------------------------------------------------
void displaceShaderInit(SPShader* shader)
{
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("white.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->setUseFunction([]()->void
{
assert(g_stk_sbr->getRTTs() != NULL);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
g_stk_sbr->getRTTs()->getFBO(FBO_TMP1_WITH_DS).bind(),
glClear(GL_COLOR_BUFFER_BIT);
}, RP_1ST);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_RESERVED);
shader->addShaderFile("sp_displace.frag", GL_FRAGMENT_SHADER, RP_RESERVED);
shader->linkShaderFiles(RP_RESERVED);
shader->use(RP_RESERVED);
shader->addBasicUniforms(RP_RESERVED);
shader->addUniform("direction", typeid(std::array<float, 4>), RP_RESERVED);
shader->setUseFunction([]()->void
{
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
g_stk_sbr->getRTTs()->getFBO(FBO_DISPLACE).bind(),
glClear(GL_COLOR_BUFFER_BIT);
}, RP_RESERVED);
shader->addCustomPrefilledTextures(ST_BILINEAR,
GL_TEXTURE_2D, "displacement_tex", []()->GLuint
{
return irr_driver->getTexture(FileManager::TEXTURE,
"displace.png")->getOpenGLTextureName();
}, RP_RESERVED);
shader->addCustomPrefilledTextures(ST_BILINEAR,
GL_TEXTURE_2D, "mask_tex", []()->GLuint
{
return g_stk_sbr->getRTTs()->getFBO(FBO_TMP1_WITH_DS).getRTT()[0];
}, RP_RESERVED);
shader->addCustomPrefilledTextures(ST_BILINEAR,
GL_TEXTURE_2D, "color_tex", []()->GLuint
{
return g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getRTT()[0];
}, RP_RESERVED);
shader->addAllTextures(RP_RESERVED);
shader->setUnuseFunction([]()->void
{
g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).bind();
glStencilFunc(GL_EQUAL, 1, 0xFF);
g_stk_sbr->getPostProcessing()->renderPassThrough
(g_stk_sbr->getRTTs()->getFBO(FBO_DISPLACE).getRTT()[0],
g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getWidth(),
g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getHeight());
glDisable(GL_STENCIL_TEST);
}, RP_RESERVED);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("direction", displaceUniformAssigner);
} // displaceShaderInit
// ----------------------------------------------------------------------------
void resizeSkinning(unsigned number)
{
@ -317,466 +320,75 @@ void initSkinning()
sp_prefilled_tex[0] = g_skinning_tex;
} // initSkinning
// ----------------------------------------------------------------------------
void addShader(SPShader* shader)
{
g_shaders[shader->getName()] = shader;
} // addShader
// ----------------------------------------------------------------------------
void loadShaders()
{
// ========================================================================
SPShader* shader = new SPShader("solid");
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_solid.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
shader->addShaderFile("sp_shadow.vert", GL_VERTEX_SHADER, RP_SHADOW);
shader->addShaderFile("white.frag", GL_FRAGMENT_SHADER, RP_SHADOW);
shader->linkShaderFiles(RP_SHADOW);
shader->use(RP_SHADOW);
shader->addBasicUniforms(RP_SHADOW);
shader->addUniform("layer", typeid(int), RP_SHADOW);
shader->addAllTextures(RP_SHADOW);
static_cast<SPPerObjectUniform*>(shader)->addAssignerFunction("layer",
shadowCascadeUniformAssigner);
addShader(shader);
shader = new SPShader("solid_skinned");
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_solid.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
shader->addShaderFile("sp_skinning_shadow.vert", GL_VERTEX_SHADER, RP_SHADOW);
shader->addShaderFile("white.frag", GL_FRAGMENT_SHADER, RP_SHADOW);
shader->linkShaderFiles(RP_SHADOW);
shader->use(RP_SHADOW);
shader->addBasicUniforms(RP_SHADOW);
shader->addUniform("layer", typeid(int), RP_SHADOW);
shader->addAllTextures(RP_SHADOW);
static_cast<SPPerObjectUniform*>(shader)->addAssignerFunction("layer",
shadowCascadeUniformAssigner);
addShader(shader);
// ========================================================================
shader = new SPShader("decal");
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_decal.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
shader->addShaderFile("sp_shadow.vert", GL_VERTEX_SHADER, RP_SHADOW);
shader->addShaderFile("white.frag", GL_FRAGMENT_SHADER, RP_SHADOW);
shader->linkShaderFiles(RP_SHADOW);
shader->use(RP_SHADOW);
shader->addBasicUniforms(RP_SHADOW);
shader->addUniform("layer", typeid(int), RP_SHADOW);
shader->addAllTextures(RP_SHADOW);
static_cast<SPPerObjectUniform*>(shader)->addAssignerFunction("layer",
shadowCascadeUniformAssigner);
addShader(shader);
shader = new SPShader("decal_skinned");
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_decal.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
shader->addShaderFile("sp_skinning_shadow.vert", GL_VERTEX_SHADER, RP_SHADOW);
shader->addShaderFile("white.frag", GL_FRAGMENT_SHADER, RP_SHADOW);
shader->linkShaderFiles(RP_SHADOW);
shader->use(RP_SHADOW);
shader->addBasicUniforms(RP_SHADOW);
shader->addUniform("layer", typeid(int), RP_SHADOW);
shader->addAllTextures(RP_SHADOW);
static_cast<SPPerObjectUniform*>(shader)->addAssignerFunction("layer",
shadowCascadeUniformAssigner);
addShader(shader);
// ========================================================================
shader = new SPShader("alphatest", 3, false, 0, true);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_alpha_test.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
shader->addShaderFile("sp_shadow.vert", GL_VERTEX_SHADER, RP_SHADOW);
shader->addShaderFile("sp_shadow_alpha_test.frag", GL_FRAGMENT_SHADER, RP_SHADOW);
shader->linkShaderFiles(RP_SHADOW);
shader->use(RP_SHADOW);
shader->addBasicUniforms(RP_SHADOW);
shader->addUniform("layer", typeid(int), RP_SHADOW);
shader->addAllTextures(RP_SHADOW);
static_cast<SPPerObjectUniform*>(shader)->addAssignerFunction("layer",
shadowCascadeUniformAssigner);
addShader(shader);
shader = new SPShader("alphatest_skinned", 3, false, 0, true);
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_alpha_test.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
shader->addShaderFile("sp_skinning_shadow.vert", GL_VERTEX_SHADER, RP_SHADOW);
shader->addShaderFile("sp_shadow_alpha_test.frag", GL_FRAGMENT_SHADER, RP_SHADOW);
shader->linkShaderFiles(RP_SHADOW);
shader->use(RP_SHADOW);
shader->addBasicUniforms(RP_SHADOW);
shader->addUniform("layer", typeid(int), RP_SHADOW);
shader->addAllTextures(RP_SHADOW);
static_cast<SPPerObjectUniform*>(shader)->addAssignerFunction("layer",
shadowCascadeUniformAssigner);
addShader(shader);
// ========================================================================
shader = new SPShader("unlit", 3, false, 0, true);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_unlit.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
shader->addShaderFile("sp_shadow.vert", GL_VERTEX_SHADER, RP_SHADOW);
shader->addShaderFile("sp_shadow_alpha_test.frag", GL_FRAGMENT_SHADER, RP_SHADOW);
shader->linkShaderFiles(RP_SHADOW);
shader->use(RP_SHADOW);
shader->addBasicUniforms(RP_SHADOW);
shader->addUniform("layer", typeid(int), RP_SHADOW);
shader->addAllTextures(RP_SHADOW);
static_cast<SPPerObjectUniform*>(shader)->addAssignerFunction("layer",
shadowCascadeUniformAssigner);
addShader(shader);
shader = new SPShader("unlit_skinned", 3, false, 0, true);
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_unlit.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
shader->addShaderFile("sp_skinning_shadow.vert", GL_VERTEX_SHADER, RP_SHADOW);
shader->addShaderFile("sp_shadow_alpha_test.frag", GL_FRAGMENT_SHADER, RP_SHADOW);
shader->linkShaderFiles(RP_SHADOW);
shader->use(RP_SHADOW);
shader->addBasicUniforms(RP_SHADOW);
shader->addUniform("layer", typeid(int), RP_SHADOW);
shader->addAllTextures(RP_SHADOW);
static_cast<SPPerObjectUniform*>(shader)->addAssignerFunction("layer",
shadowCascadeUniformAssigner);
addShader(shader);
// ========================================================================
shader = new SPShader("normalmap");
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_normal_map.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
shader->addShaderFile("sp_shadow.vert", GL_VERTEX_SHADER, RP_SHADOW);
shader->addShaderFile("white.frag", GL_FRAGMENT_SHADER, RP_SHADOW);
shader->linkShaderFiles(RP_SHADOW);
shader->use(RP_SHADOW);
shader->addBasicUniforms(RP_SHADOW);
shader->addUniform("layer", typeid(int), RP_SHADOW);
shader->addAllTextures(RP_SHADOW);
static_cast<SPPerObjectUniform*>(shader)->addAssignerFunction("layer",
shadowCascadeUniformAssigner);
addShader(shader);
shader = new SPShader("normalmap_skinned", 3, false);
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_normal_map.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
shader->addShaderFile("sp_skinning_shadow.vert", GL_VERTEX_SHADER, RP_SHADOW);
shader->addShaderFile("white.frag", GL_FRAGMENT_SHADER, RP_SHADOW);
shader->linkShaderFiles(RP_SHADOW);
shader->use(RP_SHADOW);
shader->addBasicUniforms(RP_SHADOW);
shader->addUniform("layer", typeid(int), RP_SHADOW);
shader->addAllTextures(RP_SHADOW);
static_cast<SPPerObjectUniform*>(shader)->addAssignerFunction("layer",
shadowCascadeUniformAssigner);
addShader(shader);
// ========================================================================
shader = new SPShader("grass", 3, false, 0, true);
shader->addShaderFile("sp_grass_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_grass.frag", GL_FRAGMENT_SHADER,
RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addUniform("wind_direction", typeid(core::vector3df), RP_1ST);
shader->addAllTextures(RP_1ST);
shader->addShaderFile("sp_grass_shadow.vert", GL_VERTEX_SHADER, RP_SHADOW);
shader->addShaderFile("sp_shadow_alpha_test.frag", GL_FRAGMENT_SHADER, RP_SHADOW);
shader->linkShaderFiles(RP_SHADOW);
shader->use(RP_SHADOW);
shader->addBasicUniforms(RP_SHADOW);
shader->addUniform("wind_direction", typeid(core::vector3df), RP_SHADOW);
shader->addUniform("layer", typeid(int), RP_SHADOW);
shader->addAllTextures(RP_SHADOW);
static_cast<SPPerObjectUniform*>(shader)->addAssignerFunction("layer",
shadowCascadeUniformAssigner);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("wind_direction", [](SPUniformAssigner* ua)
{
ua->setValue(g_wind_dir);
});
addShader(shader);
// ========================================================================
// Transparent shader
// ========================================================================
shader = new SPShader("alphablend_skinned", 1, true);
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_transparent.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addUniform("fog_enabled", typeid(int), RP_1ST);
shader->addUniform("custom_alpha", typeid(float), RP_1ST);
shader->addAllTextures(RP_1ST);
shader->setUseFunction(alphaBlendUse);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("fog_enabled", fogUniformAssigner);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner);
addShader(shader);
shader = new SPShader("alphablend", 1, true);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_transparent.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addUniform("fog_enabled", typeid(int), RP_1ST);
shader->addUniform("custom_alpha", typeid(float), RP_1ST);
shader->addAllTextures(RP_1ST);
shader->setUseFunction(alphaBlendUse);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("fog_enabled", fogUniformAssigner);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner);
addShader(shader);
shader = new SPShader("additive_skinned", 1, true);
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_transparent.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addUniform("fog_enabled", typeid(int), RP_1ST);
shader->addUniform("custom_alpha", typeid(float), RP_1ST);
shader->addAllTextures(RP_1ST);
shader->setUseFunction(additiveUse);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("fog_enabled", fogUniformAssigner);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner);
addShader(shader);
shader = new SPShader("additive", 1, true);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_transparent.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addUniform("fog_enabled", typeid(int), RP_1ST);
shader->addUniform("custom_alpha", typeid(float), RP_1ST);
shader->addAllTextures(RP_1ST);
shader->setUseFunction(additiveUse);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("fog_enabled", fogUniformAssigner);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner);
addShader(shader);
shader = new SPShader("ghost_skinned", 1, true/*transparent_shader*/,
900/*drawing_priority*/);
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_ghost.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addUniform("custom_alpha", typeid(float), RP_1ST);
shader->addAllTextures(RP_1ST);
shader->setUseFunction(ghostUse);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("custom_alpha", ghostAlphaAssigner);
addShader(shader);
shader = new SPShader("ghost", 1, true/*transparent_shader*/,
900/*drawing_priority*/);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_ghost.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addUniform("custom_alpha", typeid(float), RP_1ST);
shader->addAllTextures(RP_1ST);
shader->setUseFunction(ghostUse);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("custom_alpha", ghostAlphaAssigner);
addShader(shader);
SPShaderManager::get()->loadSPShaders(file_manager->getShadersDir());
// Displace shader is not specifiable in XML due to complex callback
std::shared_ptr<SPShader> sps;
if (CVS->isDefferedEnabled())
{
// This displace shader will be drawn the last in transparent pass
shader = new SPShader("displace", 2, true/*transparent_shader*/,
999/*drawing_priority*/);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER,
RP_1ST);
shader->addShaderFile("white.frag", GL_FRAGMENT_SHADER,
RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->setUseFunction([]()->void
{
assert(g_stk_sbr->getRTTs() != NULL);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
g_stk_sbr->getRTTs()->getFBO(FBO_TMP1_WITH_DS).bind(),
glClear(GL_COLOR_BUFFER_BIT);
}, RP_1ST);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER,
RP_2ND);
shader->addShaderFile("sp_displace.frag", GL_FRAGMENT_SHADER,
RP_2ND);
shader->linkShaderFiles(RP_2ND);
shader->use(RP_2ND);
shader->addBasicUniforms(RP_2ND);
shader->addUniform("direction", typeid(std::array<float, 4>),
RP_2ND);
shader->setUseFunction([]()->void
{
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
g_stk_sbr->getRTTs()->getFBO(FBO_DISPLACE).bind(),
glClear(GL_COLOR_BUFFER_BIT);
}, RP_2ND);
shader->addCustomPrefilledTextures(ST_BILINEAR,
GL_TEXTURE_2D, "displacement_tex", []()->GLuint
{
return irr_driver->getTexture(FileManager::TEXTURE,
"displace.png")->getOpenGLTextureName();
}, RP_2ND);
shader->addCustomPrefilledTextures(ST_BILINEAR,
GL_TEXTURE_2D, "mask_tex", []()->GLuint
{
return g_stk_sbr->getRTTs()->getFBO(FBO_TMP1_WITH_DS).getRTT()[0];
}, RP_2ND);
shader->addCustomPrefilledTextures(ST_BILINEAR,
GL_TEXTURE_2D, "color_tex", []()->GLuint
{
return g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getRTT()[0];
}, RP_2ND);
shader->addAllTextures(RP_2ND);
shader->setUnuseFunction([]()->void
{
g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).bind();
glStencilFunc(GL_EQUAL, 1, 0xFF);
g_stk_sbr->getPostProcessing()->renderPassThrough
(g_stk_sbr->getRTTs()->getFBO(FBO_DISPLACE).getRTT()[0],
g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getWidth(),
g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getHeight());
glDisable(GL_STENCIL_TEST);
}, RP_2ND);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("direction", displaceUniformAssigner);
addShader(shader);
sps = std::make_shared<SPShader>("displace", displaceShaderInit,
true/*transparent_shader*/, 999/*drawing_priority*/,
true/*use_alpha_channel*/);
SPShaderManager::get()->addSPShader(sps->getName(), sps);
}
else
{
// Fallback shader
SPShaderManager::get()->addSPShader("displace",
SPShaderManager::get()->getSPShader("alphablend"));
}
// ========================================================================
// Glow shader
// ========================================================================
g_glow_shader = new SPShader("sp_glow_shader", 1);
g_glow_shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
g_glow_shader->addShaderFile("colorize.frag", GL_FRAGMENT_SHADER, RP_1ST);
g_glow_shader->linkShaderFiles(RP_1ST);
g_glow_shader->use(RP_1ST);
g_glow_shader->addBasicUniforms(RP_1ST);
g_glow_shader->addUniform("col", typeid(irr::video::SColorf), RP_1ST);
addShader(g_glow_shader);
// ========================================================================
// Normal visualizer
// ========================================================================
#ifndef USE_GLES2
if (CVS->isARBGeometryShadersUsable())
if (CVS->isDefferedEnabled())
{
shader = new SPShader("sp_normal_visualizer", 1);
shader->addShaderFile("sp_normal_visualizer.vert", GL_VERTEX_SHADER,
RP_1ST);
shader->addShaderFile("sp_normal_visualizer.geom", GL_GEOMETRY_SHADER,
RP_1ST);
shader->addShaderFile("sp_normal_visualizer.frag", GL_FRAGMENT_SHADER,
RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
addShader(shader);
}
sps = std::make_shared<SPShader>
("sp_glow_shader", [](SPShader* shader)
{
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER,
RP_1ST);
shader->addShaderFile("colorize.frag", GL_FRAGMENT_SHADER,
RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addUniform("col", typeid(irr::video::SColorf), RP_1ST);
});
SPShaderManager::get()->addSPShader(sps->getName(), sps);
g_glow_shader = sps.get();
// ====================================================================
// Normal visualizer
// ====================================================================
#ifndef USE_GLES2
if (CVS->isARBGeometryShadersUsable())
{
sps = std::make_shared<SPShader>
("sp_normal_visualizer", [](SPShader* shader)
{
shader->addShaderFile("sp_normal_visualizer.vert",
GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_normal_visualizer.geom",
GL_GEOMETRY_SHADER, RP_1ST);
shader->addShaderFile("sp_normal_visualizer.frag",
GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
});
SPShaderManager::get()->addSPShader(sps->getName(), sps);
g_normal_visualizer = sps.get();
}
#endif
}
SPShaderManager::get()->setOfficialShaders();
} // loadShaders
@ -960,12 +572,9 @@ void init()
void destroy()
{
g_dy_dc.clear();
for (auto& p : g_shaders)
{
delete p.second;
}
g_shaders.clear();
SPShaderManager::destroy();
g_glow_shader = NULL;
g_normal_visualizer = NULL;
SPTextureManager::destroy();
#ifndef USE_GLES2
@ -1005,15 +614,10 @@ SPShader* getGlowShader()
} // getGlowShader
// ----------------------------------------------------------------------------
SPShader* getSPShader(const std::string& name)
SPShader* getNormalVisualizer()
{
auto ret = g_shaders.find(name);
if (ret != g_shaders.end())
{
return ret->second;
}
return NULL;
} // getSPShader
return g_normal_visualizer;
} // getNormalVisualizer
// ----------------------------------------------------------------------------
inline void mathPlaneNormf(float *p)
@ -1128,7 +732,7 @@ void prepareDrawCalls()
return;
}
g_bounding_boxes.clear();
g_wind_dir = core::vector3df(1.0f, 0.0f, 0.0f) *
sp_wind_dir = core::vector3df(1.0f, 0.0f, 0.0f) *
(irr_driver->getDevice()->getTimer()->getTime() / 1000.0f) * 1.5f;
sp_solid_poly_count = sp_shadow_poly_count = 0;
// 1st one is identity
@ -1189,9 +793,10 @@ void addObject(SPMeshNode* node)
core::aabbox3df bb = mb->getBoundingBox();
model_matrix.transformBoxEx(bb);
std::vector<bool> discard;
discard.resize((g_handle_shadow ? 5 : 1), false);
for (int dc_type = 0; dc_type <
(g_handle_shadow ? 5 : sp_first_frame ? 0 : 1); dc_type++)
const bool handle_shadow =
g_handle_shadow && shader->hasShader(RP_SHADOW);
discard.resize((handle_shadow ? 5 : 1), false);
for (int dc_type = 0; dc_type < (handle_shadow ? 5 : 1); dc_type++)
{
for (int i = 0; i < 24; i += 4)
{
@ -1216,7 +821,7 @@ void addObject(SPMeshNode* node)
}
}
}
if (sp_first_frame || g_handle_shadow ?
if (handle_shadow ?
(discard[0] && discard[1] && discard[2] && discard[3] &&
discard[4]) : discard[0])
{
@ -1241,8 +846,7 @@ void addObject(SPMeshNode* node)
mb->uploadGLMesh();
// For first frame only need the vbo to be initialized
if (!added_for_skinning && node->getAnimationState() &&
!sp_first_frame)
if (!added_for_skinning && node->getAnimationState())
{
added_for_skinning = true;
int skinning_offset = g_skinning_offset + node->getTotalJoints();
@ -1260,21 +864,14 @@ void addObject(SPMeshNode* node)
float hue = node->getRenderInfo(m) ?
node->getRenderInfo(m)->getHue() : 0.0f;
float tm_x = 0.0f;
float tm_y = 0.0f;
const auto& ret = node->getTextureMatrix(m);
if (ret[0] && ret[1])
{
tm_x = *ret[0];
tm_y = *ret[1];
}
SPInstancedData id = SPInstancedData
(node->getAbsoluteTransformation(), tm_x, tm_y, hue,
(node->getAbsoluteTransformation(), node->getTextureMatrix(m)[0],
node->getTextureMatrix(m)[1], hue,
(short)node->getSkinningOffset());
for (int dc_type = 0; dc_type < (g_handle_shadow ? 5 : 1); dc_type++)
for (int dc_type = 0; dc_type < (handle_shadow ? 5 : 1); dc_type++)
{
if (!sp_first_frame && discard[dc_type])
if (discard[dc_type])
{
continue;
}
@ -1364,8 +961,10 @@ void handleDynamicDrawCall()
core::aabbox3df bb = dydc->getBoundingBox();
dydc->getAbsoluteTransformation().transformBoxEx(bb);
std::vector<bool> discard;
discard.resize((g_handle_shadow ? 5 : 1), false);
for (int dc_type = 0; dc_type < (g_handle_shadow ? 5 : 1); dc_type++)
const bool handle_shadow =
g_handle_shadow && shader->hasShader(RP_SHADOW);
discard.resize((handle_shadow ? 5 : 1), false);
for (int dc_type = 0; dc_type < (handle_shadow ? 5 : 1); dc_type++)
{
for (int i = 0; i < 24; i += 4)
{
@ -1390,7 +989,7 @@ void handleDynamicDrawCall()
}
}
}
if (g_handle_shadow ?
if (handle_shadow ?
(discard[0] && discard[1] && discard[2] && discard[3] &&
discard[4]) : discard[0])
{
@ -1413,7 +1012,7 @@ void handleDynamicDrawCall()
addEdgeForViz(getCorner(bb, 4), getCorner(bb, 6));
}
for (int dc_type = 0; dc_type < (g_handle_shadow ? 5 : 1); dc_type++)
for (int dc_type = 0; dc_type < (handle_shadow ? 5 : 1); dc_type++)
{
if (discard[dc_type])
{
@ -1472,7 +1071,6 @@ void updateModelMatrix()
{
// Make sure all textures (with handles) are loaded
SPTextureManager::get()->checkForGLCommand(true/*before_scene*/);
SP::sp_first_frame = false;
if (!sp_culling)
{
return;
@ -1620,13 +1218,12 @@ void uploadAll()
// ----------------------------------------------------------------------------
void drawNormal()
{
SPShader* nv = getSPShader("sp_normal_visualizer");
if (nv == NULL)
if (g_normal_visualizer == NULL)
{
return;
}
nv->use();
nv->bindPrefilledTextures();
g_normal_visualizer->use();
g_normal_visualizer->bindPrefilledTextures();
for (unsigned i = 0; i < g_final_draw_calls[0].size(); i++)
{
auto& p = g_final_draw_calls[0][i];
@ -1659,12 +1256,16 @@ void drawNormal()
}
}
}
nv->unuse();
g_normal_visualizer->unuse();
}
// ----------------------------------------------------------------------------
void drawGlow()
{
if (g_glow_meshes.empty())
{
return;
}
g_glow_shader->use();
SPUniformAssigner* glow_color_assigner =
g_glow_shader->getUniformAssigner("col");
@ -1793,6 +1394,24 @@ SPMesh* convertEVTStandard(irr::scene::IMesh* mesh,
return spm;
} // convertEVTStandard
// ----------------------------------------------------------------------------
void uploadSPM(irr::scene::IMesh* mesh)
{
if (!CVS->isGLSL())
{
return;
}
SP::SPMesh* spm = dynamic_cast<SP::SPMesh*>(mesh);
if (spm)
{
for (u32 i = 0; i < spm->getMeshBufferCount(); i++)
{
SP::SPMeshBuffer* mb = spm->getSPMeshBuffer(i);
mb->uploadGLMesh();
}
}
} // uploadSPM
}
#endif

View File

@ -23,6 +23,7 @@
#include "utils/no_copy.hpp"
#include "irrMath.h"
#include "vector3d.h"
#include <array>
#include <cmath>
@ -86,7 +87,6 @@ class SPMeshBuffer;
extern GLuint sp_mat_ubo[MAX_PLAYER_COUNT][3];
extern GLuint sp_fog_ubo;
extern bool sp_first_frame;
extern std::array<GLuint, 1> sp_prefilled_tex;
extern unsigned sp_solid_poly_count;
extern unsigned sp_shadow_poly_count;
@ -94,19 +94,17 @@ extern int sp_cur_shadow_cascade;
extern bool sp_culling;
extern unsigned sp_cur_player;
extern unsigned sp_cur_buf_id[MAX_PLAYER_COUNT];
extern irr::core::vector3df sp_wind_dir;
// ----------------------------------------------------------------------------
void init();
// ----------------------------------------------------------------------------
void addShader(SPShader*);
// ----------------------------------------------------------------------------
void destroy();
// ----------------------------------------------------------------------------
GLuint getSampler(SamplerType);
// ----------------------------------------------------------------------------
SPShader* getGlowShader();
SPShader* getNormalVisualizer();
// ----------------------------------------------------------------------------
SPShader* getSPShader(const std::string& name);
SPShader* getGlowShader();
// ----------------------------------------------------------------------------
void prepareDrawCalls();
// ----------------------------------------------------------------------------
@ -137,6 +135,8 @@ void drawBoundingBoxes();
SPMesh* convertEVTStandard(irr::scene::IMesh* mesh,
const irr::video::SColor* color = NULL);
// ----------------------------------------------------------------------------
void uploadSPM(irr::scene::IMesh* mesh);
// ----------------------------------------------------------------------------
inline uint8_t srgbToLinear(float color_srgb)
{
int ret;

View File

@ -16,10 +16,10 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/sp/sp_dynamic_draw_call.hpp"
#include "graphics/sp/sp_texture.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/graphics_restrictions.hpp"
#include "graphics/material.hpp"
#include "graphics/sp/sp_shader.hpp"
#include "graphics/sp/sp_texture.hpp"
#include "graphics/sp/sp_texture_manager.hpp"
#include "utils/mini_glm.hpp"
#include "utils/string_utils.hpp"
@ -28,20 +28,22 @@ namespace SP
{
// ----------------------------------------------------------------------------
SPDynamicDrawCall::SPDynamicDrawCall(scene::E_PRIMITIVE_TYPE pt,
SPShader* shader, Material* m)
std::shared_ptr<SPShader> shader,
Material* m)
: SPMeshBuffer()
{
#ifndef SERVER_ONLY
m_primitive_type = pt;
m_shader = shader;
m_shaders[0] = shader;
m_stk_material[0] = std::make_tuple(0u, 0u, m);
m_textures.resize(m_stk_material.size());
for (unsigned j = 0; j < 6; j++)
{
m_textures[0][j] = SPTextureManager::get()->getTexture
(std::get<2>(m_stk_material[0])->getSamplerPath(j),
m_textures[0][j] = SPTextureManager::get()->getTexture(
m_shaders[0] && m_shaders[0]->hasTextureLayer(j) ?
std::get<2>(m_stk_material[0])->getSamplerPath(j) : "",
j == 0 ? std::get<2>(m_stk_material[0]) : NULL,
j < 2 && CVS->isDefferedEnabled(),
m_shaders[0] && m_shaders[0]->isSrgbForTextureLayer(j),
std::get<2>(m_stk_material[0])->getContainerId());
}
m_tex_cmp[m_textures[0][0]->getPath() + m_textures[0][1]->getPath()] = 0;
@ -133,7 +135,7 @@ SPDynamicDrawCall::SPDynamicDrawCall(scene::E_PRIMITIVE_TYPE pt,
glVertexAttribDivisorARB(10, 1);
// Texture translation
glEnableVertexAttribArray(11);
glVertexAttribPointer(11, 2, GL_HALF_FLOAT, GL_FALSE, 32, (void*)24);
glVertexAttribPointer(11, 2, GL_SHORT, GL_TRUE, 32, (void*)24);
glVertexAttribDivisorARB(11, 1);
// Misc data (skinning offset and hue change)
glEnableVertexAttribArray(12);

View File

@ -43,8 +43,6 @@ class SPDynamicDrawCall : public SPMeshBuffer
private:
core::matrix4 m_trans;
SPShader* m_shader;
scene::ISceneNode* m_parent = NULL;
core::vector2df m_texture_trans;
@ -65,8 +63,8 @@ private:
bool initTextureDyDc();
public:
SPDynamicDrawCall(scene::E_PRIMITIVE_TYPE pt, SPShader* shader,
Material* m);
SPDynamicDrawCall(scene::E_PRIMITIVE_TYPE pt,
std::shared_ptr<SPShader> shader, Material* m);
// ------------------------------------------------------------------------
~SPDynamicDrawCall() {}
// ------------------------------------------------------------------------
@ -130,8 +128,6 @@ public:
// ------------------------------------------------------------------------
virtual void enableTextureMatrix(unsigned mat_id) {}
// ------------------------------------------------------------------------
SPShader* getShader() const { return m_shader; }
// ------------------------------------------------------------------------
std::vector<video::S3DVertexSkinnedMesh>& getVerticesVector()
{ return m_vertices; }
// ------------------------------------------------------------------------

View File

@ -71,7 +71,11 @@ public:
short s[4] = { toFloat16(scale.X), toFloat16(scale.Y),
toFloat16(scale.Z), toFloat16(rotation.W) };
memcpy(m_data + 16, s, 8);
short tm[2] = { toFloat16(texture_trans_x), toFloat16(texture_trans_y) };
short tm[2] =
{
short(texture_trans_x * 32767.0f),
short(texture_trans_y * 32767.0f)
};
memcpy(m_data + 24, tm, 4);
memcpy(m_data + 28, &skinning_offset, 2);
short hue_packed = short(core::clamp(int(hue * 100.0f), 0, 100));

View File

@ -20,6 +20,8 @@
#include "graphics/central_settings.hpp"
#include "graphics/graphics_restrictions.hpp"
#include "graphics/material.hpp"
#include "graphics/sp/sp_shader.hpp"
#include "graphics/sp/sp_shader_manager.hpp"
#include "graphics/sp/sp_texture_manager.hpp"
#include "race/race_manager.hpp"
#include "utils/mini_glm.hpp"
@ -111,28 +113,32 @@ void SPMeshBuffer::uploadGLMesh()
}
m_uploaded_gl = true;
#ifndef SERVER_ONLY
if (!m_shaders[0])
{
Log::warn("SPMeshBuffer", "%s shader is missing",
std::get<2>(m_stk_material[0])->getShaderName().c_str());
return;
}
m_textures.resize(m_stk_material.size());
for (unsigned i = 0; i < m_stk_material.size(); i++)
{
for (unsigned j = 0; j < 6; j++)
{
// Undo the effect of srgb on 0 and 1 channel of textures
// which is the uv textures from .spm when advanced lighting
m_textures[i][j] = SPTextureManager::get()->getTexture
(std::get<2>(m_stk_material[i])->getSamplerPath(j),
(m_shaders[0]->hasTextureLayer(j) ?
std::get<2>(m_stk_material[i])->getSamplerPath(j) : "",
j == 0 ? std::get<2>(m_stk_material[i]) : NULL,
j < 2 && CVS->isDefferedEnabled(),
m_shaders[0]->isSrgbForTextureLayer(j),
std::get<2>(m_stk_material[i])->getContainerId());
}
// Use .spm uv texture 1 and 2 for compare in scene manager
m_tex_cmp[m_textures[i][0]->getPath() + m_textures[i][1]->getPath()] =
i;
// Use the original spm uv texture 1 and 2 for compare in scene manager
m_tex_cmp[std::get<2>(m_stk_material[i])->getSamplerPath(0) +
std::get<2>(m_stk_material[i])->getSamplerPath(1)] = i;
}
bool use_2_uv = std::get<2>(m_stk_material[0])->use2UV();
bool use_tangents =
std::get<2>(m_stk_material[0])->getShaderName() == "normalmap" &&
CVS->isDefferedEnabled();
bool use_tangents = m_shaders[0]->useTangents();
const unsigned pitch = 48 - (use_tangents ? 0 : 4) - (use_2_uv ? 0 : 4) -
(m_skinned ? 0 : 16);
m_pitch = pitch;
@ -212,10 +218,12 @@ void SPMeshBuffer::uploadGLMesh()
void SPMeshBuffer::recreateVAO(unsigned i)
{
#ifndef SERVER_ONLY
if (!m_shaders[0])
{
return;
}
bool use_2_uv = std::get<2>(m_stk_material[0])->use2UV();
bool use_tangents =
std::get<2>(m_stk_material[0])->getShaderName() == "normalmap" &&
CVS->isDefferedEnabled();
bool use_tangents = m_shaders[0]->useTangents();
const unsigned pitch = m_pitch;
size_t offset = 0;
@ -353,7 +361,7 @@ void SPMeshBuffer::recreateVAO(unsigned i)
glVertexAttribDivisorARB(10, 1);
// Texture translation
glEnableVertexAttribArray(11);
glVertexAttribPointer(11, 2, GL_HALF_FLOAT, GL_FALSE, 32, (void*)24);
glVertexAttribPointer(11, 2, GL_SHORT, GL_TRUE, 32, (void*)24);
glVertexAttribDivisorARB(11, 1);
// Misc data (skinning offset and hue change)
glEnableVertexAttribArray(12);
@ -458,4 +466,14 @@ void SPMeshBuffer::reloadTextureCompare()
}
} // reloadTextureCompare
// ----------------------------------------------------------------------------
void SPMeshBuffer::setSTKMaterial(Material* m)
{
m_stk_material[0] = std::make_tuple(0u, getIndexCount(), m);
m_shaders[0] = SPShaderManager::get()->getSPShader(
std::get<2>(m_stk_material[0])->getShaderName());
m_shaders[1] = SPShaderManager::get()->getSPShader(
std::get<2>(m_stk_material[0])->getShaderName() + "_skinned");
} // setSTKMaterial
}

View File

@ -41,11 +41,14 @@ class Material;
namespace SP
{
class SPShader;
class SPTexture;
class SPMeshBuffer : public IMeshBuffer, public SPPerObjectUniform
{
protected:
std::shared_ptr<SPShader> m_shaders[2];
std::vector<std::tuple<size_t/*first_index_id*/,
unsigned/*indices_count*/, Material*> > m_stk_material;
@ -270,10 +273,7 @@ public:
m_indices = std::move(indices);
}
// ------------------------------------------------------------------------
void setSTKMaterial(Material* m)
{
m_stk_material[0] = std::make_tuple(0u, getIndexCount(), m);
}
void setSTKMaterial(Material* m);
// ------------------------------------------------------------------------
void reloadTextureCompare();
// ------------------------------------------------------------------------
@ -283,6 +283,9 @@ public:
m_indices.shrink_to_fit();
}
// ------------------------------------------------------------------------
SPShader* getShader(bool skinned = false) const
{ return skinned ? m_shaders[1].get() : m_shaders[0].get(); }
// ------------------------------------------------------------------------
virtual const video::SMaterial& getMaterial() const
{
static video::SMaterial unused;

View File

@ -21,6 +21,7 @@
#include "graphics/sp/sp_mesh.hpp"
#include "graphics/sp/sp_mesh_buffer.hpp"
#include "graphics/sp/sp_shader.hpp"
#include "graphics/sp/sp_shader_manager.hpp"
#include "graphics/graphics_restrictions.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
@ -88,7 +89,8 @@ void SPMeshNode::setMesh(irr::scene::IAnimatedMesh* mesh)
cleanRenderInfo();
if (m_mesh)
{
m_texture_matrices.resize(m_mesh->getMeshBufferCount());
m_texture_matrices.resize(m_mesh->getMeshBufferCount(),
{{ 0.0f, 0.0f }});
if (!m_mesh->isStatic())
{
#ifndef SERVER_ONLY
@ -190,11 +192,8 @@ SPShader* SPMeshNode::getShader(unsigned mesh_buffer_id) const
#ifndef SERVER_ONLY
if (!m_mesh || mesh_buffer_id < m_mesh->getMeshBufferCount())
{
const std::string sn = (m_shader_override.empty() ?
m_mesh->getSPMeshBuffer(mesh_buffer_id)->getSTKMaterial()
->getShaderName() : m_shader_override) +
(m_animated ? "_skinned" : "");
SPShader* shader = SP::getSPShader(sn);
SPShader* shader =
m_mesh->getSPMeshBuffer(mesh_buffer_id)->getShader(m_animated);
if (shader && shader->isTransparent())
{
// Use real transparent shader first
@ -202,8 +201,8 @@ SPShader* SPMeshNode::getShader(unsigned mesh_buffer_id) const
}
if (m_first_render_info && m_first_render_info->isTransparent())
{
return SP::getSPShader
(std::string("ghost") + (m_animated ? "_skinned" : ""));
return SPShaderManager::get()->getSPShader
(std::string("ghost") + (m_animated ? "_skinned" : "")).get();
}
return shader;
}

View File

@ -52,11 +52,9 @@ private:
std::vector<std::array<float, 16> > m_skinning_matrices;
std::string m_shader_override;
video::SColorf m_glow_color;
std::vector<std::array<std::shared_ptr<float>, 2> > m_texture_matrices;
std::vector<std::array<float, 2> > m_texture_matrices;
// ------------------------------------------------------------------------
void cleanRenderInfo();
@ -119,8 +117,6 @@ public:
// ------------------------------------------------------------------------
SPShader* getShader(unsigned mesh_buffer_id) const;
// ------------------------------------------------------------------------
void setShaderOverride(const std::string& so) { m_shader_override = so; }
// ------------------------------------------------------------------------
const std::array<float, 16>* getSkinningMatrices() const
{ return m_skinning_matrices.data(); }
// ------------------------------------------------------------------------
@ -143,14 +139,13 @@ public:
m_glow_color.b == 0.0f);
}
// ------------------------------------------------------------------------
std::array<std::shared_ptr<float>, 2>& getTextureMatrix(unsigned mb_id)
std::array<float, 2>& getTextureMatrix(unsigned mb_id)
{
assert(mb_id < m_texture_matrices.size());
return m_texture_matrices[mb_id];
}
// ------------------------------------------------------------------------
void setTextureMatrix(unsigned mb_id,
std::array<std::shared_ptr<float>, 2> tm)
void setTextureMatrix(unsigned mb_id, const std::array<float, 2>& tm)
{
assert(mb_id < m_texture_matrices.size());
m_texture_matrices[mb_id] = tm;

View File

@ -16,15 +16,12 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/sp/sp_shader.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/shader_files_manager.hpp"
#include "graphics/sp/sp_base.hpp"
#include "graphics/sp/sp_uniform_assigner.hpp"
#include "utils/no_copy.hpp"
#include "utils/string_utils.hpp"
#include <ITexture.h>
#include <string>
namespace SP
{
std::unordered_map<std::string, std::pair<unsigned, SamplerType> >
@ -37,36 +34,22 @@ std::unordered_map<std::string, std::pair<unsigned, SamplerType> >
#endif
};
// ----------------------------------------------------------------------------
SPShader::~SPShader()
{
#ifndef SERVER_ONLY
for (unsigned rp = RP_1ST; rp < RP_COUNT; rp++)
{
if (m_program[rp] != 0)
{
glDeleteProgram(m_program[rp]);
}
for (auto& p : m_uniforms[rp])
{
delete p.second;
}
}
#endif
} // ~SPShader
// ----------------------------------------------------------------------------
void SPShader::addShaderFile(const std::string& name, GLint shader_type,
RenderPass rp)
{
#ifndef SERVER_ONLY
GLint shader_id = ShaderFilesManager::getInstance()
if (m_program[rp] == 0)
{
m_program[rp] = glCreateProgram();
}
auto shader_file = ShaderFilesManager::getInstance()
->getShaderFile(name, shader_type);
glAttachShader(m_program[rp], shader_id);
GLint is_deleted = GL_TRUE;
glGetShaderiv(shader_id, GL_DELETE_STATUS, &is_deleted);
if (is_deleted == GL_FALSE)
glDeleteShader(shader_id);
if (shader_file)
{
m_shader_files.push_back(shader_file);
glAttachShader(m_program[rp], *shader_file);
}
#endif
} // addShaderFile
@ -88,6 +71,19 @@ void SPShader::linkShaderFiles(RenderPass rp)
Log::error("SPShader", error_message);
delete[] error_message;
}
// After linking all shaders can be detached
GLuint shaders[10] = {};
GLsizei count = 0;
glGetAttachedShaders(m_program[rp], 10, &count, shaders);
for (unsigned i = 0; i < (unsigned)count; i++)
{
glDetachShader(m_program[rp], shaders[i]);
}
if (result == GL_FALSE)
{
glDeleteProgram(m_program[rp]);
m_program[rp] = 0;
}
#endif
} // linkShaderFiles
@ -131,7 +127,7 @@ void SPShader::addAllTextures(RenderPass rp)
const unsigned idx =
unsigned(m_prefilled_samplers[rp].size() + m_samplers[rp].size());
glUniform1i(loc, idx);
m_samplers[rp].emplace_back(i, idx);
m_samplers[rp][i] = idx;
}
#endif
} // addPrefilledTextures
@ -161,7 +157,7 @@ void SPShader::addCustomPrefilledTextures(SamplerType st, GLuint texture_type,
} // addCustomPrefilledTextures
// ----------------------------------------------------------------------------
void SPShader::bindPrefilledTextures(RenderPass rp)
void SPShader::bindPrefilledTextures(RenderPass rp) const
{
#ifndef SERVER_ONLY
for (auto& p : m_prefilled_samplers[rp])
@ -184,7 +180,8 @@ void SPShader::bindPrefilledTextures(RenderPass rp)
} // bindPrefilledTextures
// ----------------------------------------------------------------------------
void SPShader::bindTextures(const std::array<GLuint, 6>& tex, RenderPass rp)
void SPShader::bindTextures(const std::array<GLuint, 6>& tex,
RenderPass rp) const
{
#ifndef SERVER_ONLY
for (auto& p : m_samplers[rp])
@ -197,7 +194,7 @@ void SPShader::bindTextures(const std::array<GLuint, 6>& tex, RenderPass rp)
} // bindTextures
// ----------------------------------------------------------------------------
void SPShader::addUniform(const std::string& name, const std::type_info& ti,
void SPShader::addUniform(const std::string& name, const std::type_index& ti,
RenderPass rp)
{
#ifndef SERVER_ONLY
@ -234,7 +231,7 @@ void SPShader::setUniformsPerObject(SPPerObjectUniform* sppou,
// ----------------------------------------------------------------------------
SPUniformAssigner* SPShader::getUniformAssigner(const std::string& name,
RenderPass rp)
RenderPass rp) const
{
auto ret = m_uniforms[rp].find(name);
if (ret == m_uniforms[rp].end())
@ -244,4 +241,43 @@ SPUniformAssigner* SPShader::getUniformAssigner(const std::string& name,
return ret->second;
} // getUniformAssigner
// ----------------------------------------------------------------------------
void SPShader::unload()
{
#ifndef SERVER_ONLY
for (unsigned rp = RP_1ST; rp < RP_COUNT; rp++)
{
if (m_program[rp] != 0)
{
glDeleteProgram(m_program[rp]);
m_program[rp] = 0;
}
for (auto& p : m_uniforms[rp])
{
delete p.second;
}
m_uniforms[rp].clear();
m_custom_prefilled_getter[rp].clear();
m_prefilled_samplers[rp].clear();
m_samplers[rp].clear();
m_use_function[rp] = nullptr;
m_unuse_function[rp] = nullptr;
}
m_shader_files.clear();
#endif
} // unload
// ----------------------------------------------------------------------------
bool SPShader::isSrgbForTextureLayer(unsigned layer) const
{
#ifndef SERVER_ONLY
if (!CVS->isDefferedEnabled())
{
return false;
}
#endif
assert(layer < 6);
return m_srgb[layer];
} // isSrgbForTextureLayer
}

View File

@ -27,12 +27,14 @@
#include <cstring>
#include <functional>
#include <ostream>
#include <map>
#include <memory>
#include <string>
#include <typeinfo>
#include <typeindex>
#include <unordered_map>
#include <vector>
#include <SMaterial.h>
namespace SP
{
@ -53,8 +55,8 @@ enum SamplerType: unsigned int
enum RenderPass: unsigned int
{
RP_1ST = 0,
RP_2ND,
RP_SHADOW,
RP_RESERVED,
RP_COUNT
};
@ -64,10 +66,10 @@ inline std::ostream& operator<<(std::ostream& os, const RenderPass& rp)
{
case RP_1ST:
return os << "first pass";
case RP_2ND:
return os << "second pass";
case RP_SHADOW:
return os << "shadow pass";
case RP_RESERVED:
return os << "reserved pass";
default:
return os;
}
@ -80,46 +82,56 @@ class SPShader : public NoCopy, public SPPerObjectUniform
private:
std::string m_name;
std::vector<std::shared_ptr<GLuint> > m_shader_files;
GLuint m_program[RP_COUNT];
std::vector<std::pair<unsigned, unsigned> > m_samplers[RP_COUNT];
std::map<unsigned, unsigned> m_samplers[RP_COUNT];
std::vector<std::tuple<unsigned, std::string, SamplerType,
GLuint> >m_prefilled_samplers[RP_COUNT];
std::unordered_map<std::string, SPUniformAssigner*>
m_uniforms[RP_COUNT];
std::unordered_map<std::string, SPUniformAssigner*> m_uniforms[RP_COUNT];
std::unordered_map<std::string, std::function<GLuint()> >
m_custom_prefilled_getter[RP_COUNT];
std::function<void()> m_use_function[RP_COUNT], m_unuse_function[RP_COUNT];
const std::function<void(SPShader*)> m_init_function;
const int m_drawing_priority;
const bool m_transparent_shader;
const bool m_use_alpha_channel;
const bool m_use_tangents;
const std::array<bool, 6> m_srgb;
public:
// ------------------------------------------------------------------------
SPShader(const std::string& name, unsigned pass_count = 3,
SPShader(const std::string& name,
const std::function<void(SPShader*)>& init_func,
bool transparent_shader = false, int drawing_priority = 0,
bool use_alpha_channel = false)
: m_name(name), m_drawing_priority(drawing_priority),
bool use_alpha_channel = false, bool use_tangents = false,
const std::array<bool, 6>& srgb =
{{ true, true, false, false, false, false }})
: m_name(name), m_init_function(init_func),
m_drawing_priority(drawing_priority),
m_transparent_shader(transparent_shader),
m_use_alpha_channel(use_alpha_channel || transparent_shader)
m_use_alpha_channel(use_alpha_channel),
m_use_tangents(use_tangents), m_srgb(srgb)
{
memset(m_program, 0, 12);
#ifndef SERVER_ONLY
for (unsigned rp = RP_1ST; rp < pass_count; rp++)
{
m_program[rp] = glCreateProgram();
}
#endif
m_init_function(this);
}
// ------------------------------------------------------------------------
~SPShader();
~SPShader()
{
unload();
}
// ------------------------------------------------------------------------
bool hasShader(RenderPass rp) { return m_program[rp] != 0; }
// ------------------------------------------------------------------------
@ -154,10 +166,10 @@ public:
std::function<GLuint()> func,
RenderPass rp = RP_1ST);
// ------------------------------------------------------------------------
void bindPrefilledTextures(RenderPass rp = RP_1ST);
void bindPrefilledTextures(RenderPass rp = RP_1ST) const;
// ------------------------------------------------------------------------
void bindTextures(const std::array<GLuint, 6>& tex,
RenderPass rp = RP_1ST);
RenderPass rp = RP_1ST) const;
// ------------------------------------------------------------------------
void addBasicUniforms(RenderPass rp = RP_1ST)
{
@ -170,21 +182,15 @@ public:
block_index = glGetUniformBlockIndex(m_program[rp], "SPFogData");
if (block_index != GL_INVALID_INDEX)
glUniformBlockBinding(m_program[rp], block_index, 2);
#ifndef USE_GLES2
// Assign framebuffer output
glBindFragDataLocation(m_program[rp], 0, "o_diffuse_color");
glBindFragDataLocation(m_program[rp], 1, "o_normal_depth");
glBindFragDataLocation(m_program[rp], 2, "o_gloss_map");
#endif
#endif
}
// ------------------------------------------------------------------------
const std::string& getName() const { return m_name; }
// ------------------------------------------------------------------------
SPUniformAssigner* getUniformAssigner(const std::string& name,
RenderPass rp = RP_1ST);
RenderPass rp = RP_1ST) const;
// ------------------------------------------------------------------------
void addUniform(const std::string& name, const std::type_info& ti,
void addUniform(const std::string& name, const std::type_index& ti,
RenderPass rp = RP_1ST);
// ------------------------------------------------------------------------
void setUniformsPerObject(SPPerObjectUniform* sppou,
@ -209,7 +215,33 @@ public:
// ------------------------------------------------------------------------
bool samplerLess(RenderPass rp = RP_1ST) const
{ return m_samplers[rp].empty(); }
// ------------------------------------------------------------------------
void unload();
// ------------------------------------------------------------------------
void init()
{
if (!m_shader_files.empty())
{
return;
}
m_init_function(this);
}
// ------------------------------------------------------------------------
bool isSrgbForTextureLayer(unsigned layer) const;
// ------------------------------------------------------------------------
bool useTangents() const { return m_use_tangents; }
// ------------------------------------------------------------------------
bool hasTextureLayer(unsigned layer)
{
for (unsigned rp = RP_1ST; rp < RP_COUNT; rp++)
{
if (m_samplers[rp].find(layer) != m_samplers[rp].end())
{
return true;
}
}
return false;
}
};
}

View File

@ -0,0 +1,611 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2018 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/sp/sp_shader_manager.hpp"
#include "io/file_manager.hpp"
#include "io/xml_node.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/sp/sp_base.hpp"
#include "graphics/sp/sp_shader.hpp"
#include "graphics/sp/sp_texture.hpp"
#include "graphics/sp/sp_texture_manager.hpp"
#include "graphics/sp/sp_uniform_assigner.hpp"
#include "tracks/track.hpp"
#include "utils/string_utils.hpp"
#include "utils/log.hpp"
#include <algorithm>
namespace SP
{
SPShaderManager* SPShaderManager::m_spsm = NULL;
// ----------------------------------------------------------------------------
SPShaderManager::SPShaderManager()
{
#ifndef SERVER_ONLY
m_official_types =
{
{ "int", std::type_index(typeid(int)) },
{ "float", std::type_index(typeid(float)) },
{ "mat4", std::type_index(typeid(irr::core::matrix4)) },
{ "vec4", std::type_index(typeid(std::array<float, 4>)) },
{ "vec3", std::type_index(typeid(irr::core::vector3df)) },
{ "vec2", std::type_index(typeid(irr::core::vector2df)) }
};
m_official_sampler_types =
{
{ "nearest", ST_NEAREST },
{ "nearest_clamped", ST_NEAREST_CLAMPED },
{ "bilinear", ST_BILINEAR },
{ "bilinear_clamped", ST_BILINEAR_CLAMPED },
{ "trilinear", ST_TRILINEAR },
{ "trilinear_clamped", ST_TRILINEAR_CLAMPED },
{ "semi_trilinear", ST_SEMI_TRILINEAR }
};
m_official_uniform_assigner_functions =
{
{ "shadowCascadeUniformAssigner", [](SPUniformAssigner* ua)
{
ua->setValue(sp_cur_shadow_cascade);
}
},
{ "windDirectionUniformAssigner", [](SPUniformAssigner* ua)
{
ua->setValue(sp_wind_dir);
}
},
{ "zeroAlphaUniformAssigner", [](SPUniformAssigner* ua)
{
ua->setValue(0.0f);
}
},
{ "fogUniformAssigner", [](SPUniformAssigner* ua)
{
int fog_enable = Track::getCurrentTrack() ?
Track::getCurrentTrack()->isFogEnabled() ? 1 : 0 : 0;
ua->setValue(fog_enable);
}
},
{ "ghostAlphaUniformAssigner", [](SPUniformAssigner* ua)
{
float alpha = 1.0f;
if (Track::getCurrentTrack())
{
const video::SColor& c = Track::getCurrentTrack()
->getSunColor();
float y = 0.2126f * c.getRed() + 0.7152f * c.getGreen() +
0.0722f * c.getBlue();
alpha = y > 128.0f ? 0.5f : 0.35f;
}
ua->setValue(alpha);
}
}
};
m_official_use_functions =
{
{ "alphaBlendUse", []()
{
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
},
{ "additiveUse", []()
{
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
}
},
{ "ghostUse", []()
{
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
}
};
#endif
} // SPShaderManager
// ----------------------------------------------------------------------------
SPShaderManager::~SPShaderManager()
{
m_official_shaders.clear();
removeUnusedShaders();
#ifdef DEBUG
for (auto p : m_shaders)
{
Log::error("SPShaderManager", "%s > 1 ref_count", p.first.c_str());
}
#endif
} // ~SPShaderManager
// ----------------------------------------------------------------------------
void SPShaderManager::loadEachShader(const std::string& file_name)
{
#ifndef SERVER_ONLY
std::unique_ptr<XMLNode> xml(file_manager->createXMLTree(file_name));
if (!xml || xml->getName() != "spshader")
{
Log::error("SPShaderManager", "Invalid SPShader file %s",
file_name.c_str());
return;
}
ShaderInfo si;
const XMLNode* shader_info = xml->getNode("shader-info");
if (!shader_info)
{
Log::error("SPShaderManager", "Missing shader-info header in file %s",
file_name.c_str());
return;
}
shader_info->get("name", &si.m_shader_name);
if (si.m_shader_name.empty())
{
Log::error("SPShaderManager", "Empty shader name in file %s",
file_name.c_str());
return;
}
else if (si.m_shader_name.find("_skinned") != std::string::npos)
{
Log::error("SPShaderManager", "_skinned name is reserved for auto"
" skinned mesh shader adding");
return;
}
else if (getSPShader(si.m_shader_name))
{
Log::error("SPShaderManager", "%s shader already exists",
si.m_shader_name.c_str());
return;
}
shader_info->get("fallback-shader", &si.m_fallback_name);
shader_info->get("transparent", &si.m_transparent_shader);
shader_info->get("drawing-priority", &si.m_drawing_priority);
shader_info->get("use-alpha-channel", &si.m_use_alpha_channel);
shader_info->get("use-tangents", &si.m_use_tangents);
std::string srgb_prop;
shader_info->get("srgb", &srgb_prop);
std::vector<std::string> srgb_props = StringUtils::split(srgb_prop, ' ');
if (srgb_props.size() == 6)
{
for (unsigned i = 0; i < 6; i++)
{
si.m_srgb[i] = srgb_props[i] == "Y";
}
}
else if (!srgb_prop.empty())
{
Log::error("SPShaderManager", "Invalid srgb properties in shader");
}
std::array<PassInfo, 2> pi;
loadPassInfo(xml->getNode("first-pass"), pi[0]);
if (!si.m_transparent_shader && CVS->isDefferedEnabled())
{
loadPassInfo(xml->getNode("shadow-pass"), pi[1]);
}
if (pi[0].m_vertex_shader.empty())
{
Log::error("SPShaderManager", "Missing first pass vertex shader in"
" file %s", file_name.c_str());
return;
}
if (!si.m_fallback_name.empty() && !CVS->isDefferedEnabled())
{
std::shared_ptr<SPShader> fallback_shader =
getSPShader(si.m_fallback_name);
if (!fallback_shader)
{
Log::error("SPShaderManager", "%s fallback shader missing",
si.m_fallback_name.c_str());
}
else
{
addSPShader(si.m_shader_name, fallback_shader);
if (!pi[0].m_skinned_mesh_shader.empty())
{
std::shared_ptr<SPShader> fallback_skinned_shader =
getSPShader(si.m_fallback_name + "_skinned");
if (!fallback_skinned_shader)
{
Log::error("SPShaderManager", "%s fallback skinned mesh"
" shader missing", si.m_fallback_name.c_str());
}
addSPShader(si.m_shader_name + "_skinned",
fallback_skinned_shader);
}
}
return;
}
UniformAssigners ua;
const XMLNode* uniform_assigners = xml->getNode("uniform-assigners");
if (uniform_assigners)
{
for (unsigned i = 0; i < uniform_assigners->getNumNodes(); i++)
{
const XMLNode* uniform_assigner = uniform_assigners->getNode(i);
if (uniform_assigner->getName() == "uniform-assigner")
{
std::string name, function;
uniform_assigner->get("name", &name);
uniform_assigner->get("function", &function);
if (!name.empty() && !function.empty() &&
m_official_uniform_assigner_functions.find(function) !=
m_official_uniform_assigner_functions.end())
{
ua.emplace_back(name, m_official_uniform_assigner_functions
.at(function));
}
else
{
Log::error("SPShaderManager", "Invalid uniform assigner"
" %s", function.c_str());
}
}
}
}
addSPShader(si.m_shader_name, buildSPShader(si, pi, ua, false/*skinned*/));
if (!pi[0].m_skinned_mesh_shader.empty())
{
addSPShader(si.m_shader_name + "_skinned", buildSPShader(si, pi, ua,
true/*skinned*/));
}
#endif
} // loadEachShader
// ----------------------------------------------------------------------------
void SPShaderManager::loadPassInfo(const XMLNode* pass, PassInfo& pi)
{
if (!pass)
{
return;
}
std::string use_function, unuse_function;
pass->get("use-function", &use_function);
if (!use_function.empty() && m_official_use_functions.find(use_function) !=
m_official_use_functions.end())
{
pi.m_use_function = m_official_use_functions.at(use_function);
}
pass->get("unuse-function", &unuse_function);
if (!unuse_function.empty() &&
m_official_unuse_functions.find(unuse_function) !=
m_official_unuse_functions.end())
{
pi.m_unuse_function = m_official_unuse_functions.at(unuse_function);
}
pass->get("vertex-shader", &pi.m_vertex_shader);
pi.m_vertex_shader = getShaderFullPath(pi.m_vertex_shader);
pass->get("fragment-shader", &pi.m_fragment_shader);
pi.m_fragment_shader = getShaderFullPath(pi.m_fragment_shader);
pass->get("skinned-mesh-shader", &pi.m_skinned_mesh_shader);
pi.m_skinned_mesh_shader = getShaderFullPath(pi.m_skinned_mesh_shader);
const XMLNode* uniforms = pass->getNode("uniforms");
if (uniforms)
{
for (unsigned i = 0; i < uniforms->getNumNodes(); i++)
{
const XMLNode* uniform = uniforms->getNode(i);
if (uniform->getName() == "uniform")
{
std::string name, type;
uniform->get("name", &name);
uniform->get("type", &type);
if (!name.empty() && !type.empty() &&
m_official_types.find(type) != m_official_types.end())
{
pi.m_uniforms.emplace_back(name,
m_official_types.at(type));
}
else
{
Log::error("SPShaderManager", "Invalid uniform type %s",
type.c_str());
}
}
}
}
const XMLNode* prefilled_textures = pass->getNode("prefilled-textures");
if (prefilled_textures)
{
for (unsigned i = 0; i < prefilled_textures->getNumNodes(); i++)
{
const XMLNode* prefilled_texture = prefilled_textures->getNode(i);
if (prefilled_texture->getName() == "prefilled-texture")
{
bool srgb = false;
SamplerType st = ST_TRILINEAR;
std::string name, file, srgb_props, sampler_props;
prefilled_texture->get("name", &name);
prefilled_texture->get("file", &file);
prefilled_texture->get("srgb", &srgb_props);
#ifndef SERVER_ONLY
if (!srgb_props.empty())
{
srgb = srgb_props == "Y" && CVS->isDefferedEnabled();
}
#endif
prefilled_texture->get("sampler", &sampler_props);
if (!sampler_props.empty() &&
m_official_sampler_types.find(sampler_props) !=
m_official_sampler_types.end())
{
st = m_official_sampler_types.at(sampler_props);
}
if (!name.empty() && !file.empty())
{
pi.m_prefilled_textures.emplace_back(name, file, srgb, st);
}
else
{
Log::error("SPShaderManager", "Invalid prefilled texture");
}
}
}
}
} // loadPassInfo
// ----------------------------------------------------------------------------
std::string SPShaderManager::getShaderFullPath(const std::string& name)
{
if (name.empty())
{
return "";
}
std::string cur_location = m_shader_directory + name;
if (file_manager->fileExists(cur_location))
{
return cur_location;
}
cur_location = file_manager->getAssetChecked(FileManager::SHADER, name);
if (cur_location.empty())
{
return "";
}
return file_manager->getFileSystem()->getAbsolutePath(cur_location.c_str())
.c_str();
} // getShaderFullPath
// ----------------------------------------------------------------------------
std::shared_ptr<SPShader> SPShaderManager::buildSPShader(const ShaderInfo& si,
const std::array<PassInfo, 2>& pi, const UniformAssigners& ua,
bool skinned)
{
std::shared_ptr<SPShader> sps;
#ifndef SERVER_ONLY
sps = std::make_shared<SPShader>(si.m_shader_name,
[pi, ua, skinned](SPShader* shader)
{
// First pass
assert(!pi[0].m_vertex_shader.empty() ||
(skinned && !pi[0].m_skinned_mesh_shader.empty()));
SPPerObjectUniform* pou = static_cast<SPPerObjectUniform*>(shader);
for (auto& p : ua)
{
pou->addAssignerFunction(p.first, p.second);
}
shader->addShaderFile(skinned ?
pi[0].m_skinned_mesh_shader : pi[0].m_vertex_shader,
GL_VERTEX_SHADER, RP_1ST);
if (!pi[0].m_fragment_shader.empty())
{
shader->addShaderFile(pi[0].m_fragment_shader,
GL_FRAGMENT_SHADER, RP_1ST);
}
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
addUniformsToShader(shader, pi[0].m_uniforms, RP_1ST);
if (pi[0].m_use_function)
{
shader->setUseFunction(pi[0].m_use_function, RP_1ST);
}
if (pi[0].m_unuse_function)
{
shader->setUnuseFunction(pi[0].m_unuse_function, RP_1ST);
}
addPrefilledTexturesToShader(shader, pi[0].m_prefilled_textures,
RP_1ST);
shader->addAllTextures(RP_1ST);
if (pi[1].m_vertex_shader.empty())
{
return;
}
// Shadow pass
if (skinned && pi[1].m_skinned_mesh_shader.empty())
{
Log::warn("SPShader", "Missing skinned mesh vertex shader in"
" shadow pass");
return;
}
shader->addShaderFile(skinned ?
pi[1].m_skinned_mesh_shader : pi[1].m_vertex_shader,
GL_VERTEX_SHADER, RP_SHADOW);
if (!pi[1].m_fragment_shader.empty())
{
shader->addShaderFile(pi[1].m_fragment_shader,
GL_FRAGMENT_SHADER, RP_SHADOW);
}
shader->linkShaderFiles(RP_SHADOW);
shader->use(RP_SHADOW);
shader->addBasicUniforms(RP_SHADOW);
addUniformsToShader(shader, pi[1].m_uniforms, RP_SHADOW);
if (pi[1].m_use_function)
{
shader->setUseFunction(pi[1].m_use_function, RP_SHADOW);
}
if (pi[1].m_unuse_function)
{
shader->setUnuseFunction(pi[1].m_unuse_function, RP_SHADOW);
}
addPrefilledTexturesToShader(shader, pi[1].m_prefilled_textures,
RP_SHADOW);
shader->addAllTextures(RP_SHADOW);
}, si.m_transparent_shader, si.m_drawing_priority,
si.m_use_alpha_channel, si.m_use_tangents, si.m_srgb);
#endif
return sps;
} // buildSPShader
// ----------------------------------------------------------------------------
void SPShaderManager::addUniformsToShader(SPShader* s,
const std::vector<std::pair<std::string, std::type_index> >& u,
RenderPass rp)
{
for (auto& p : u)
{
s->addUniform(p.first, p.second, rp);
}
} // addUniformsToShader
// ----------------------------------------------------------------------------
void SPShaderManager::addPrefilledTexturesToShader(SPShader* s,
const std::vector<std::tuple<std::string, std::string, bool, SamplerType> >
&t, RenderPass rp)
{
#ifndef SERVER_ONLY
for (auto& p : t)
{
std::string full_path;
const std::string& relative_path =
file_manager->searchTexture(std::get<1>(p)/*filename*/);
if (relative_path.empty())
{
Log::warn("SPShader", "Cannot determine prefilled texture full"
" path: %s", std::get<1>(p).c_str());
}
else
{
full_path = file_manager->getFileSystem()->getAbsolutePath
(relative_path.c_str()).c_str();
}
if (!full_path.empty())
{
std::string cid;
if (!file_manager->searchTextureContainerId(cid, std::get<1>(p)))
{
Log::warn("SPShader", "Missing container id for %s, no texture"
" compression for it will be done.",
std::get<1>(p).c_str());
}
std::shared_ptr<SPTexture> pt = SPTextureManager::get()
->getTexture(full_path, NULL/*material*/, std::get<2>(p), cid);
s->addCustomPrefilledTextures(std::get<3>(p)/*sampler_type*/,
GL_TEXTURE_2D, std::get<0>(p)/*name_in_shader*/, [pt]()->GLuint
{
return pt->getOpenGLTextureName();
}, rp);
}
}
#endif
} // addPrefilledTexturesToShader
// ----------------------------------------------------------------------------
void SPShaderManager::loadSPShaders(const std::string& directory_name)
{
std::set<std::string> shaders;
file_manager->listFiles(shaders, directory_name);
for (auto it = shaders.begin(); it != shaders.end();)
{
if ((*it).find("sps") == std::string::npos ||
(*it).find(".xml") == std::string::npos)
{
it = shaders.erase(it);
}
else
{
it++;
}
}
if (shaders.empty())
{
return;
}
m_shader_directory = file_manager->getFileSystem()->getAbsolutePath
(directory_name.c_str()).c_str();
for (const std::string& file_name : shaders)
{
loadEachShader(m_shader_directory + file_name);
}
m_shader_directory = "";
} // loadSPShaders
// ----------------------------------------------------------------------------
void SPShaderManager::unloadAll()
{
for (auto& p : m_shaders)
{
p.second->unload();
}
} // unloadAll
// ----------------------------------------------------------------------------
void SPShaderManager::initAll()
{
for (auto& p : m_shaders)
{
p.second->init();
}
} // initAll
// ----------------------------------------------------------------------------
void SPShaderManager::removeUnusedShaders()
{
for (auto it = m_shaders.begin(); it != m_shaders.end();)
{
if (it->second.use_count() == 1)
{
it = m_shaders.erase(it);
}
else
{
it++;
}
}
} // removeUnusedShaders
}

View File

@ -0,0 +1,182 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2018 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_SP_SHADER_MANAGER_HPP
#define HEADER_SP_SHADER_MANAGER_HPP
#include <array>
#include <functional>
#include <memory>
#include <string>
#include <typeinfo>
#include <typeindex>
#include <unordered_map>
#include <vector>
#include "utils/no_copy.hpp"
class XMLNode;
namespace SP
{
class SPShader;
class SPUniformAssigner;
enum SamplerType: unsigned int;
enum RenderPass: unsigned int;
class SPShaderManager : public NoCopy
{
public:
struct PassInfo
{
std::function<void()> m_use_function;
std::function<void()> m_unuse_function;
std::string m_vertex_shader;
std::string m_fragment_shader;
std::string m_skinned_mesh_shader;
std::vector<std::pair<std::string, std::type_index> > m_uniforms;
std::vector<std::tuple<std::string, std::string, bool, SamplerType> >
m_prefilled_textures;
};
private:
typedef std::vector<std::pair< std::string, std::function<void
(SPUniformAssigner*)> > > UniformAssigners;
struct ShaderInfo
{
std::string m_shader_name, m_fallback_name;
int m_drawing_priority = 0;
bool m_transparent_shader = false;
bool m_use_alpha_channel = false;
bool m_use_tangents = false;
std::array<bool, 6> m_srgb =
{{
true, true, false, false, false, false
}};
};
static SPShaderManager* m_spsm;
std::unordered_map<std::string, std::shared_ptr<SPShader> > m_shaders;
std::vector<std::shared_ptr<SPShader> > m_official_shaders;
std::unordered_map<std::string, std::type_index> m_official_types;
std::unordered_map<std::string, SamplerType> m_official_sampler_types;
std::unordered_map<std::string, std::function<void(SPUniformAssigner*)> >
m_official_uniform_assigner_functions;
std::unordered_map<std::string, std::function<void()> >
m_official_use_functions;
std::unordered_map<std::string, std::function<void()> >
m_official_unuse_functions;
std::string m_shader_directory;
// ------------------------------------------------------------------------
std::string getShaderFullPath(const std::string& name);
// ------------------------------------------------------------------------
void loadPassInfo(const XMLNode* pass, PassInfo& pi);
// ------------------------------------------------------------------------
void loadEachShader(const std::string& file_name);
// ------------------------------------------------------------------------
std::shared_ptr<SPShader> buildSPShader(const ShaderInfo& si,
const std::array<PassInfo, 2>& pi,
const UniformAssigners& ua,
bool skinned);
// ------------------------------------------------------------------------
static void addUniformsToShader(SPShader* s,
const std::vector<std::pair<std::string, std::type_index> >& u,
RenderPass rp);
// ------------------------------------------------------------------------
static void addPrefilledTexturesToShader(SPShader* s,
const std::vector<std::tuple<std::string, std::string, bool,
SamplerType> >& t, RenderPass rp);
public:
// ------------------------------------------------------------------------
static SPShaderManager* get()
{
if (m_spsm == NULL)
{
m_spsm = new SPShaderManager();
}
return m_spsm;
}
// ------------------------------------------------------------------------
static void destroy()
{
delete m_spsm;
m_spsm = NULL;
}
// ------------------------------------------------------------------------
SPShaderManager();
// ------------------------------------------------------------------------
~SPShaderManager();
// ------------------------------------------------------------------------
std::shared_ptr<SPShader> getSPShader(const std::string& name)
{
auto ret = m_shaders.find(name);
if (ret != m_shaders.end())
{
return ret->second;
}
return NULL;
}
// ------------------------------------------------------------------------
void loadSPShaders(const std::string& directory_name);
// ------------------------------------------------------------------------
void addSPShader(const std::string& name,
std::shared_ptr<SPShader> shader)
{
m_shaders[name] = shader;
}
// ------------------------------------------------------------------------
void unloadAll();
// ------------------------------------------------------------------------
void initAll();
// ------------------------------------------------------------------------
void removeUnusedShaders();
// ------------------------------------------------------------------------
void setOfficialShaders()
{
for (auto& p : m_shaders)
{
m_official_shaders.push_back(p.second);
}
}
};
}
#endif

View File

@ -19,9 +19,10 @@
#include "config/stk_config.hpp"
#include "config/user_config.hpp"
#include "io/file_manager.hpp"
#include "graphics/sp/sp_texture_manager.hpp"
#include "graphics/sp/sp_base.hpp"
#include "graphics/sp/sp_shader.hpp"
#include "graphics/sp/sp_shader_manager.hpp"
#include "graphics/sp/sp_texture_manager.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
@ -121,6 +122,7 @@ std::shared_ptr<video::IImage> SPTexture::getImageFromPath
if (img_loader == NULL)
{
Log::error("SPTexture", "No image loader for %s", path.c_str());
return NULL;
}
io::IReadFile* file = irr::io::createReadFile(path.c_str());
@ -440,17 +442,19 @@ bool SPTexture::threadedLoad()
}
std::shared_ptr<video::IImage> image = getTextureImage();
if (!image)
{
return true;
}
std::shared_ptr<video::IImage> mask = getMask(image->getDimension());
if (mask && image)
if (mask)
{
applyMask(image.get(), mask.get());
}
std::shared_ptr<video::IImage> mipmaps;
if (!m_cache_directory.empty() &&
CVS->isTextureCompressionEnabled() && image &&
image->getDimension().Width >= 4 &&
image->getDimension().Height >= 4)
if (!m_cache_directory.empty() && CVS->isTextureCompressionEnabled() &&
image->getDimension().Width >= 4 && image->getDimension().Height >= 4)
{
auto r = compressTexture(image);
SPTextureManager::get()->increaseGLCommandFunctionCount(1);
@ -469,8 +473,7 @@ bool SPTexture::threadedLoad()
else
{
#ifndef USE_GLES2
if (UserConfigParams::m_hq_mipmap && image &&
image->getDimension().Width > 1 &&
if (UserConfigParams::m_hq_mipmap && image->getDimension().Width > 1 &&
image->getDimension().Height > 1)
{
std::vector<std::pair<core::dimension2du, unsigned> >
@ -522,7 +525,9 @@ std::shared_ptr<video::IImage>
{
// Load colorization mask
std::shared_ptr<video::IImage> mask;
if (SP::getSPShader(m_material->getShaderName())->useAlphaChannel())
std::shared_ptr<SPShader> sps =
SPShaderManager::get()->getSPShader(m_material->getShaderName());
if (sps && sps->useAlphaChannel())
{
Log::debug("SPTexture", "Don't use colorization mask or factor"
" with shader using alpha channel for %s", m_path.c_str());
@ -675,7 +680,7 @@ void SPTexture::generateHQMipmap(void* in,
imMipmapCascade cascade;
imReduceOptions options;
imReduceSetOptions(&options,
m_path.find("_nm.") != std::string::npos ?
m_path.find("_Normal.") != std::string::npos ?
IM_REDUCE_FILTER_NORMALMAP: IM_REDUCE_FILTER_LINEAR/*filter*/,
2/*hopcount*/, 2.0f/*alpha*/, 1.0f/*amplifynormal*/,
0.0f/*normalsustainfactor*/);

View File

@ -77,8 +77,6 @@ private:
// ------------------------------------------------------------------------
void applyMask(video::IImage* texture, video::IImage* mask);
// ------------------------------------------------------------------------
void addTextureHandle();
// ------------------------------------------------------------------------
void createTransparent()
{
#ifndef SERVER_ONLY

View File

@ -88,6 +88,13 @@ SPTextureManager::~SPTextureManager()
t.join();
}
m_threaded_load_obj.clear();
removeUnusedTextures();
#ifdef DEBUG
for (auto p : m_textures)
{
Log::error("SPTextureManager", "%s > 1 ref_count", p.first.c_str());
}
#endif
} // ~SPTextureManager
// ----------------------------------------------------------------------------
@ -169,14 +176,68 @@ void SPTextureManager::removeUnusedTextures()
} // removeUnusedTextures
// ----------------------------------------------------------------------------
void SPTextureManager::dumpAllTexture()
void SPTextureManager::dumpAllTextures()
{
for (auto p : m_textures)
{
Log::info("STKTexManager", "%s size: %0.2fK", p.first.c_str(),
(p.second->getWidth() * p.second->getHeight() * 4) / 1024.0f);
Log::info("SPTextureManager", "%s", p.first.c_str());
}
} // dumpAllTexture
} // dumpAllTextures
// ----------------------------------------------------------------------------
core::stringw SPTextureManager::reloadTexture(const core::stringw& name)
{
core::stringw result;
#ifndef SERVER_ONLY
if (name.empty())
{
for (auto p : m_textures)
{
if (p.second->getPath().empty() ||
p.second->getPath() == "unicolor_white")
{
continue;
}
addThreadedFunction(std::bind(&SPTexture::threadedLoad, p.second));
Log::info("SPTextureManager", "%s reloaded",
p.second->getPath().c_str());
}
return L"All textures reloaded.";
}
core::stringw list = name;
list.make_lower().replace(L'\u005C', L'\u002F');
std::vector<std::string> names =
StringUtils::split(StringUtils::wideToUtf8(list), ';');
for (const std::string& fname : names)
{
for (auto p : m_textures)
{
if (p.second->getPath().empty() ||
p.second->getPath() == "unicolor_white")
{
continue;
}
std::string tex_path =
StringUtils::toLowerCase(p.second->getPath());
std::string tex_name = StringUtils::getBasename(tex_path);
if (fname == tex_name || fname == tex_path)
{
addThreadedFunction(std::bind(&SPTexture::threadedLoad,
p.second));
result += tex_name.c_str();
result += L" ";
break;
}
}
}
if (result.empty())
{
return L"Texture(s) not found!";
}
#endif // !SERVER_ONLY
return result + "reloaded.";
} // reloadTexture
// ----------------------------------------------------------------------------
}

View File

@ -29,12 +29,13 @@
#include <condition_variable>
#include <functional>
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <string>
#include <thread>
#include <unordered_map>
#include "irrString.h"
class Material;
@ -47,7 +48,7 @@ class SPTextureManager : public NoCopy
private:
static SPTextureManager* m_sptm;
std::unordered_map<std::string, std::shared_ptr<SPTexture> > m_textures;
std::map<std::string, std::shared_ptr<SPTexture> > m_textures;
std::atomic_uint m_max_threaded_load_obj;
@ -108,9 +109,9 @@ public:
Material* m, bool undo_srgb,
const std::string& container_id);
// ------------------------------------------------------------------------
int dumpTextureUsage();
void dumpAllTextures();
// ------------------------------------------------------------------------
void dumpAllTexture();
irr::core::stringw reloadTexture(const irr::core::stringw& name);
};

View File

@ -25,6 +25,7 @@
#include "utils/log.hpp"
#endif
#include <typeinfo>
#include <typeindex>
#include <array>
#include <string>
@ -49,7 +50,7 @@ private:
public:
// ------------------------------------------------------------------------
SPUniformAssigner(const std::type_info& ti, GLuint location)
SPUniformAssigner(const std::type_index& ti, GLuint location)
: m_location(location), m_type(ti), m_assigned(false) {}
// ------------------------------------------------------------------------
bool rumtimeChecking(const std::type_info& ti) const
@ -186,6 +187,10 @@ public:
{
glUniform1i(m_location, 0);
}
else if (m_type == typeid(std::array<float, 4>))
{
glUniform4f(m_location, 0.0f, 0.0f, 0.0f,0.0f);
}
#endif
}
}

View File

@ -152,81 +152,6 @@ void STKTexManager::removeTexture(STKTexture* texture, bool remove_all)
#endif
} // removeTexture
// ----------------------------------------------------------------------------
void STKTexManager::dumpAllTexture(bool mesh_texture)
{
for (auto p : m_all_textures)
{
if (!p.second || (mesh_texture && !p.second->isMeshTexture()))
continue;
Log::info("STKTexManager", "%s size: %0.2fK", p.first.c_str(),
float(p.second->getTextureSize()) / 1024);
}
} // dumpAllTexture
// ----------------------------------------------------------------------------
int STKTexManager::dumpTextureUsage()
{
int size = 0;
for (auto p : m_all_textures)
{
if (p.second == NULL)
continue;
size += p.second->getTextureSize() / 1024 / 1024;
}
Log::info("STKTexManager", "Total %dMB", size);
return size;
} // dumpAllTexture
// ----------------------------------------------------------------------------
core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name)
{
core::stringw result;
#ifndef SERVER_ONLY
if (CVS->isTextureCompressionEnabled())
return L"Please disable texture compression for reloading textures.";
if (name.empty())
{
for (auto p : m_all_textures)
{
if (p.second == NULL || !p.second->isMeshTexture())
continue;
p.second->reload();
Log::info("STKTexManager", "%s reloaded",
p.second->getName().getPtr());
}
return L"All textures reloaded.";
}
core::stringw list = name;
list.make_lower().replace(L'\u005C', L'\u002F');
std::vector<std::string> names =
StringUtils::split(StringUtils::wideToUtf8(list), ';');
for (const std::string& fname : names)
{
for (auto p : m_all_textures)
{
if (p.second == NULL || !p.second->isMeshTexture())
continue;
std::string tex_path =
StringUtils::toLowerCase(p.second->getName().getPtr());
std::string tex_name = StringUtils::getBasename(tex_path);
if (fname == tex_name || fname == tex_path)
{
p.second->reload();
result += tex_name.c_str();
result += L" ";
break;
}
}
}
if (result.empty())
return L"Texture(s) not found!";
#endif // !SERVER_ONLY
return result + "reloaded.";
} // reloadTexture
// ----------------------------------------------------------------------------
/** Sets an error message to be displayed when a texture is not found. This
* error message is shown before the "Texture %s not found or invalid"
@ -244,3 +169,17 @@ void STKTexManager::setTextureErrorMessage(const std::string &error,
else
m_texture_error_message = StringUtils::insertValues(error, detail);
} // setTextureErrorMessage
// ----------------------------------------------------------------------------
int STKTexManager::dumpTextureUsage()
{
int size = 0;
for (auto p : m_all_textures)
{
if (p.second == NULL)
continue;
size += p.second->getTextureSize() / 1024 / 1024;
}
Log::info("STKTexManager", "Total %dMB", size);
return size;
} // dumpTextureUsage

View File

@ -83,12 +83,8 @@ public:
// ------------------------------------------------------------------------
void removeTexture(STKTexture* texture, bool remove_all = false);
// ------------------------------------------------------------------------
void dumpAllTexture(bool mesh_texture);
// ------------------------------------------------------------------------
int dumpTextureUsage();
// ------------------------------------------------------------------------
irr::core::stringw reloadTexture(const irr::core::stringw& name);
// ------------------------------------------------------------------------
/** Returns the currently defined texture error message, which is used
* by event_handler.cpp to print additional info about irrlicht
* internal errors or warnings. If no error message is currently

View File

@ -18,8 +18,11 @@
#include "graphics/stk_texture.hpp"
#include "config/user_config.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/stk_tex_manager.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/graphics_restrictions.hpp"
#include "graphics/stk_tex_manager.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
#include "modes/profile_world.hpp"
#include "utils/log.hpp"
#include "utils/string_utils.hpp"
@ -122,6 +125,7 @@ void STKTexture::reload(bool no_upload, uint8_t* preload_data,
return;
}
orig_img = resizeImage(orig_img, &m_orig_size, &m_size);
applyMask(orig_img);
data = orig_img ? (uint8_t*)orig_img->lock() : NULL;
}
@ -235,11 +239,18 @@ video::IImage* STKTexture::resizeImage(video::IImage* orig_img,
#ifndef SERVER_ONLY
if (image == NULL)
assert(orig_size && orig_size->Width > 0 && orig_size->Height > 0);
video::IVideoDriver* driver = irr_driver->getVideoDriver();
core::dimension2du img_size = image ? image->getDimension() : *orig_size;
core::dimension2du tex_size = img_size.getOptimalSize
(!irr_driver->getVideoDriver()->queryFeature(video::EVDF_TEXTURE_NPOT));
const core::dimension2du& max_size = irr_driver->getVideoDriver()
->getDriverAttributes().getAttributeAsDimension2d("MAX_TEXTURE_SIZE");
bool has_npot = !GraphicsRestrictions::isDisabled(
GraphicsRestrictions::GR_NPOT_TEXTURES) &&
driver->queryFeature(video::EVDF_TEXTURE_NPOT);
core::dimension2du tex_size = img_size.getOptimalSize(!has_npot);
const core::dimension2du& max_size = driver->getDriverAttributes().
getAttributeAsDimension2d("MAX_TEXTURE_SIZE");
if (tex_size.Width > max_size.Width)
tex_size.Width = max_size.Width;
@ -257,8 +268,8 @@ video::IImage* STKTexture::resizeImage(video::IImage* orig_img,
if (image->getColorFormat() != video::ECF_A8R8G8B8 ||
tex_size != img_size)
{
video::IImage* new_texture = irr_driver
->getVideoDriver()->createImage(video::ECF_A8R8G8B8, tex_size);
video::IImage* new_texture = driver->createImage(video::ECF_A8R8G8B8,
tex_size);
if (tex_size != img_size)
image->copyToScaling(new_texture);
else
@ -271,6 +282,46 @@ video::IImage* STKTexture::resizeImage(video::IImage* orig_img,
return image;
} // resizeImage
// ----------------------------------------------------------------------------
void STKTexture::applyMask(video::IImage* orig_img)
{
#ifndef SERVER_ONLY
Material* material = NULL;
if (material_manager)
{
material = material_manager->getMaterialFor(this);
}
if (material && !material->getAlphaMask().empty())
{
video::IImage* converted_mask = irr_driver->getVideoDriver()
->createImageFromFile(material->getAlphaMask().c_str());
if (converted_mask == NULL)
{
Log::warn("STKTexture", "Applying mask failed for '%s'!",
material->getAlphaMask().c_str());
return;
}
converted_mask = resizeImage(converted_mask);
if (converted_mask->lock())
{
const core::dimension2du& dim = orig_img->getDimension();
for (unsigned int x = 0; x < dim.Width; x++)
{
for (unsigned int y = 0; y < dim.Height; y++)
{
video::SColor col = orig_img->getPixel(x, y);
video::SColor alpha = converted_mask->getPixel(x, y);
col.setAlpha(alpha.getRed());
orig_img->setPixel(x, y, col, false);
} // for y
} // for x
}
converted_mask->unlock();
converted_mask->drop();
}
#endif // !SERVER_ONLY
} // applyMask
//-----------------------------------------------------------------------------
bool STKTexture::hasMipMaps() const
{

View File

@ -54,6 +54,9 @@ private:
bool isSrgb() const;
// ------------------------------------------------------------------------
bool isPremulAlpha() const;
// ------------------------------------------------------------------------
void applyMask(video::IImage* orig_img);
// ------------------------------------------------------------------------
public:
// ------------------------------------------------------------------------

View File

@ -177,7 +177,6 @@ public:
template<int N, typename... TexIds>
void setTextureUnitsImpl(GLuint tex_id, TexIds... args)
{
static_assert(N != 15, "15 is reserved for skinning texture");
if (CVS->isARBSamplerObjectsUsable())
{
glActiveTexture(GL_TEXTURE0 + m_texture_units[N]);
@ -250,18 +249,6 @@ public:
for (unsigned i = 0; i < m_sampler_ids.size(); i++)
glDeleteSamplers(1, &m_sampler_ids[i]);
} // ~TextureShader
// ------------------------------------------------------------------------
/** For AZDO to remove the old texture handles, according to specification,
* they can only be removed when the underlying texture or sampler objects
* are finally deleted. This deletion will happen only when no handle
* using the texture or sampler object is resident on any context.
*/
void recreateTrilinearSampler(int sampler_id)
{
glDeleteSamplers(1, &m_sampler_ids[sampler_id]);
m_sampler_ids[sampler_id] =
createSamplers(ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // recreateTrilinearSampler
}; // class TextureShader

View File

@ -388,6 +388,16 @@ InputDevice *DeviceManager::mapGamepadInput(Input::InputType type,
if (gPad != NULL)
{
// Ignore deadzone events if this isn't the latest used device in
// single-player mode (allowing the player to switch device at any time)
int dz = static_cast<GamepadConfig*>(gPad->getConfiguration())->getDeadzone();
if (m_single_player != NULL && m_latest_used_device != gPad
&& *value > -dz && *value < dz)
{
*player = NULL;
return NULL;
}
if (gPad->processAndMapInput(type, button_id, mode, action, value))
{
if (m_single_player != NULL)

View File

@ -104,7 +104,8 @@ bool GamePadDevice::isButtonPressed(const int i)
void GamePadDevice::setButtonPressed(const int i, bool isButtonPressed)
{
m_button_pressed[i] = isButtonPressed;
if (i < m_button_pressed.size())
m_button_pressed[i] = isButtonPressed;
} // setButtonPressed
// ----------------------------------------------------------------------------

View File

@ -566,7 +566,8 @@ void Attachment::update(float dt)
// Everything is done in the plugin.
break;
case ATTACH_NOLOKS_SWATTER:
// Should never be called, this symbols is only used as an index for
case ATTACH_SWATTER_ANIM:
// Should never be called, these symbols are only used as an index for
// the model, Nolok's attachment type is ATTACH_SWATTER
assert(false);
break;
@ -597,9 +598,6 @@ void Attachment::update(float dt)
}
}
break;
case ATTACH_TINYTUX:
// Nothing to do for tinytux, this is all handled in EmergencyAnimation
break;
case ATTACH_BUBBLEGUM_SHIELD:
case ATTACH_NOLOK_BUBBLEGUM_SHIELD:
if (m_time_left < 0)

View File

@ -60,10 +60,10 @@ public:
ATTACH_BOMB,
ATTACH_ANVIL,
ATTACH_SWATTER,
// Note that the next symbol is only used as an index into the mesh
// Note that the next 2 symbols are only used as an index into the mesh
// array; it will NEVER be actually assigned as an attachment type
ATTACH_NOLOKS_SWATTER,
ATTACH_TINYTUX,
ATTACH_SWATTER_ANIM,
ATTACH_BUBBLEGUM_SHIELD,
ATTACH_NOLOK_BUBBLEGUM_SHIELD,
ATTACH_MAX,

View File

@ -21,6 +21,7 @@
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/sp/sp_base.hpp"
#include "io/file_manager.hpp"
AttachmentManager *attachment_manager = 0;
@ -53,7 +54,7 @@ static const initAttachmentType iat[]=
{Attachment::ATTACH_ANVIL, "anchor.spm", "anchor-attach-icon.png" },
{Attachment::ATTACH_SWATTER, "swatter.spm", "swatter-icon.png" },
{Attachment::ATTACH_NOLOKS_SWATTER, "swatter_nolok.spm", "swatter-icon.png" },
{Attachment::ATTACH_TINYTUX, "reset-button.spm", "reset-attach-icon.png" },
{Attachment::ATTACH_SWATTER_ANIM, "swatter_anim.spm", "swatter-icon.png" },
{Attachment::ATTACH_BUBBLEGUM_SHIELD, "bubblegum_shield.spm", "shield-icon.png" },
{Attachment::ATTACH_NOLOK_BUBBLEGUM_SHIELD, "bubblegum_shield_nolok.spm", "shield-icon.png" },
{Attachment::ATTACH_MAX, "", "" },
@ -76,23 +77,18 @@ AttachmentManager::~AttachmentManager()
}
} // ~AttachmentManager
//-----------------------------------------------------------------------------
void AttachmentManager::removeTextures()
{
for(int i=0; iat[i].attachment!=Attachment::ATTACH_MAX; i++)
{
// FIXME: free attachment textures
} // for
} // removeTextures
//-----------------------------------------------------------------------------
void AttachmentManager::loadModels()
{
for(int i=0; iat[i].attachment!=Attachment::ATTACH_MAX; i++)
{
std::string full_path = file_manager->getAsset(FileManager::MODEL,iat[i].file);
m_attachments[iat[i].attachment]=irr_driver->getAnimatedMesh(full_path);
m_attachments[iat[i].attachment]->grab();
scene::IAnimatedMesh* mesh = irr_driver->getAnimatedMesh(full_path);
mesh->grab();
#ifndef SERVER_ONLY
SP::uploadSPM(mesh);
#endif
m_attachments[iat[i].attachment] = mesh;
if(iat[i].icon_file)
{
std::string full_icon_path =

View File

@ -39,7 +39,6 @@ private:
public:
AttachmentManager() {};
~AttachmentManager();
void removeTextures ();
void loadModels ();
// ------------------------------------------------------------------------
/** Returns the mest for a certain attachment.

View File

@ -78,7 +78,6 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
debug_name += m_type;
m_node->setName(debug_name.c_str());
#endif
Track::getCurrentTrack()->adjustForFog(m_node);
m_node->setAutomaticCulling(scene::EAC_FRUSTUM_BOX);
m_node->setPosition(xyz.toIrrVector());
Vec3 hpr;
@ -192,8 +191,6 @@ void Item::switchTo(ItemType type, scene::IMesh *mesh, scene::IMesh *lowmesh)
m_original_type = m_type;
setMesh(mesh, lowmesh);
setType(type);
Track::getCurrentTrack()->adjustForFog(m_node);
} // switchTo
//-----------------------------------------------------------------------------
@ -214,7 +211,6 @@ void Item::switchBack()
setType(m_original_type);
m_original_type = ITEM_NONE;
Track::getCurrentTrack()->adjustForFog(m_node);
Vec3 hpr;
hpr.setHPR(m_original_rotation);
m_node->setRotation(hpr.toIrrHPR());

View File

@ -25,8 +25,7 @@
#include "config/stk_config.hpp"
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/sp/sp_base.hpp"
#include "io/file_manager.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/controller/spare_tire_ai.hpp"
@ -36,6 +35,7 @@
#include "tracks/arena_graph.hpp"
#include "tracks/arena_node.hpp"
#include "tracks/track.hpp"
#include "utils/random_generator.hpp"
#include "utils/string_utils.hpp"
#include <IMesh.h>
@ -104,6 +104,9 @@ void ItemManager::loadDefaultItemMeshes()
"- aborting", name.c_str());
exit(-1);
}
#ifndef SERVER_ONLY
SP::uploadSPM(mesh);
#endif
mesh->grab();
m_item_mesh[i] = mesh;
node->get("glow", &(m_glow_color[i]));
@ -114,7 +117,13 @@ void ItemManager::loadDefaultItemMeshes()
? NULL
: irr_driver->getMesh(lowres_model_filename);
if (m_item_lowres_mesh[i]) m_item_lowres_mesh[i]->grab();
if (m_item_lowres_mesh[i])
{
#ifndef SERVER_ONLY
SP::uploadSPM(m_item_lowres_mesh[i]);
#endif
m_item_lowres_mesh[i]->grab();
}
} // for i
delete root;
} // loadDefaultItemMeshes

View File

@ -21,8 +21,8 @@
#include "graphics/central_settings.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/sp/sp_base.hpp"
#include "graphics/sp/sp_dynamic_draw_call.hpp"
#include "graphics/sp/sp_shader_manager.hpp"
#include "items/plunger.hpp"
#include "items/projectile_manager.hpp"
#include "karts/abstract_kart.hpp"
@ -59,8 +59,8 @@ RubberBand::RubberBand(Plunger *plunger, AbstractKart *kart)
color.setBlue(SP::srgb255ToLinear(color.getBlue()));
}
m_dy_dc = std::make_shared<SP::SPDynamicDrawCall>
(scene::EPT_TRIANGLE_STRIP, SP::getSPShader("unlit"),
material_manager->getDefaultSPMaterial("unlit"));
(scene::EPT_TRIANGLE_STRIP, SP::SPShaderManager::get()->getSPShader
("unlit"), material_manager->getDefaultSPMaterial("unlit"));
m_dy_dc->getVerticesVector().resize(4);
// Set the vertex colors properly, as the new pipeline doesn't use the old
// light values

View File

@ -32,7 +32,7 @@
#include "graphics/explosion.hpp"
#include "graphics/irr_driver.hpp"
#include "io/file_manager.hpp"
#include "items/attachment.hpp"
#include "items/attachment_manager.hpp"
#include "items/projectile_manager.hpp"
#include "karts/controller/controller.hpp"
#include "karts/explosion_animation.hpp"
@ -74,8 +74,8 @@ Swatter::Swatter(AbstractKart *kart, bool was_bomb,
if (m_removing_bomb)
{
m_scene_node->setMesh(irr_driver->getAnimatedMesh(
file_manager->getAsset(FileManager::MODEL,"swatter_anim.spm") ) );
m_scene_node->setMesh(attachment_manager
->getMesh(Attachment::ATTACH_SWATTER_ANIM));
m_scene_node->setRotation(core::vector3df(0.0, -180.0, 0.0));
m_scene_node->setAnimationSpeed(0.9f);
m_scene_node->setCurrentFrame(0.0f);

View File

@ -217,8 +217,7 @@ void LocalPlayerController::update(float dt)
}
}
#endif
if (m_kart->getKartAnimation() && m_sound_schedule == false &&
m_kart->getAttachment()->getType() != Attachment::ATTACH_TINYTUX)
if (m_kart->getKartAnimation() && m_sound_schedule == false)
{
m_sound_schedule = true;
}

View File

@ -54,6 +54,7 @@
#include "karts/explosion_animation.hpp"
#include "karts/kart_gfx.hpp"
#include "karts/kart_model.hpp"
#include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp"
#include "karts/kart_rewinder.hpp"
#include "karts/max_speed.hpp"
@ -3019,10 +3020,15 @@ const Vec3& Kart::getNormal() const
} // getNormal
// ------------------------------------------------------------------------
void Kart::playSound(SFXBuffer* buffer)
{
getNextEmitter()->play(getXYZ(), buffer);
}
} // playSound
// ------------------------------------------------------------------------
const video::SColor& Kart::getColor() const
{
return m_kart_properties->getColor();
} // getColor
/* EOF */

View File

@ -30,9 +30,10 @@
#include "items/powerup_manager.hpp" // For PowerupType
#include "karts/abstract_kart.hpp"
#include "karts/kart_properties.hpp"
#include "utils/no_copy.hpp"
#include <SColor.h>
class AbstractKartAnimation;
class Attachment;
class btKart;
@ -347,8 +348,7 @@ public:
virtual btTransform getAlignedTransform(const float customPitch=-1);
// -------------------------------------------------------------------------
/** Returns the color used for this kart. */
const video::SColor &getColor() const
{return m_kart_properties->getColor();}
const irr::video::SColor &getColor() const;
// ------------------------------------------------------------------------
/** Returns the time till full steering is reached for this kart.
* \param steer Current steer value (must be >=0), on which the time till

View File

@ -678,16 +678,7 @@ bool KartModel::loadModels(const KartProperties &kart_properties)
std::string full_name = kart_properties.getKartDir() + obj.getFilename();
obj.setModel(irr_driver->getMesh(full_name));
#ifndef SERVER_ONLY
if (CVS->isGLSL())
{
for (u32 j = 0; j < obj.getModel()->getMeshBufferCount(); j++)
{
SP::SPMeshBuffer* mb = static_cast<SP::SPMeshBuffer*>
(obj.getModel()->getMeshBuffer(j));
// Pre-upload gl meshes and textures for kart screen
mb->uploadGLMesh();
}
}
SP::uploadSPM(obj.getModel());
#endif
obj.getModel()->grab();
irr_driver->grabAllTextures(obj.getModel());
@ -725,16 +716,7 @@ bool KartModel::loadModels(const KartProperties &kart_properties)
kart_properties.getKartDir()+m_wheel_filename[i];
m_wheel_model[i] = irr_driver->getMesh(full_wheel);
#ifndef SERVER_ONLY
if (CVS->isGLSL())
{
for (u32 j = 0; j < m_wheel_model[i]->getMeshBufferCount(); j++)
{
SP::SPMeshBuffer* mb = static_cast<SP::SPMeshBuffer*>
(m_wheel_model[i]->getMeshBuffer(j));
// Pre-upload gl meshes and textures for kart screen
mb->uploadGLMesh();
}
}
SP::uploadSPM(m_wheel_model[i]);
#endif
// Grab all textures. This is done for the master only, so
// the destructor will only free the textures if a master
@ -1135,13 +1117,8 @@ void KartModel::update(float dt, float distance, float steer, float speed,
for (unsigned i = 0; i < spmn->getSPM()->getMeshBufferCount(); i++)
{
auto& ret = spmn->getTextureMatrix(i);
if (!ret[0] || !ret[1])
{
ret[0].reset(new float);
ret[1].reset(new float);
}
*ret[0] = obj.m_texture_cur_offset.X;
*ret[1] = obj.m_texture_cur_offset.Y;
ret[0] = obj.m_texture_cur_offset.X;
ret[1] = obj.m_texture_cur_offset.Y;
}
}
else

View File

@ -21,8 +21,12 @@
#include "addons/addon.hpp"
#include "config/stk_config.hpp"
#include "config/player_manager.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/shader_files_manager.hpp"
#include "graphics/stk_tex_manager.hpp"
#include "graphics/sp/sp_shader_manager.hpp"
#include "graphics/sp/sp_texture_manager.hpp"
#include "io/file_manager.hpp"
#include "karts/cached_characteristic.hpp"
#include "karts/combined_characteristic.hpp"
@ -97,7 +101,10 @@ KartProperties::KartProperties(const std::string &filename)
else
{
for (unsigned int i = 0; i < RaceManager::DIFFICULTY_COUNT; i++)
m_ai_properties[i].reset(new AIProperties((RaceManager::Difficulty) i));
{
m_ai_properties[i] =
std::make_shared<AIProperties>((RaceManager::Difficulty) i);
}
}
} // KartProperties
@ -105,6 +112,15 @@ KartProperties::KartProperties(const std::string &filename)
/** Destructor, dereferences the kart model. */
KartProperties::~KartProperties()
{
#ifndef SERVER_ONLY
if (CVS->isGLSL() && m_kart_model.use_count() == 1)
{
m_kart_model = nullptr;
SP::SPShaderManager::get()->removeUnusedShaders();
ShaderFilesManager::getInstance()->removeUnusedShaderFiles();
SP::SPTextureManager::get()->removeUnusedTextures();
}
#endif
} // ~KartProperties
//-----------------------------------------------------------------------------
@ -125,7 +141,7 @@ void KartProperties::copyForPlayer(const KartProperties *source)
if (source->m_characteristic)
{
// Remove the shared reference by creating a new pointer
m_characteristic.reset(new XmlCharacteristic());
m_characteristic = std::make_shared<XmlCharacteristic>();
m_characteristic->copyFrom(source->getCharacteristic());
// Combine the characteristics for this object. We can't copy it because
@ -149,7 +165,8 @@ void KartProperties::copyFrom(const KartProperties *source)
// (but not for each player).
for (unsigned int i = 0; i < RaceManager::DIFFICULTY_COUNT; i++)
{
m_ai_properties[i].reset(new AIProperties((RaceManager::Difficulty) i));
m_ai_properties[i] =
std::make_shared<AIProperties>((RaceManager::Difficulty) i);
assert(m_ai_properties);
*m_ai_properties[i] = *source->m_ai_properties[i];
}
@ -186,7 +203,7 @@ void KartProperties::load(const std::string &filename, const std::string &node)
// m_kart_model must be initialised after assigning the default
// values from stk_config (otherwise all kart_properties will
// share the same KartModel
m_kart_model.reset(new KartModel(/*is_master*/true));
m_kart_model = std::make_shared<KartModel>(/*is_master*/true);
m_root = StringUtils::getPath(filename)+"/";
m_ident = StringUtils::getBasename(StringUtils::getPath(filename));
@ -206,7 +223,7 @@ void KartProperties::load(const std::string &filename, const std::string &node)
throw std::runtime_error(msg.str());
}
getAllData(root);
m_characteristic.reset(new XmlCharacteristic(root));
m_characteristic = std::make_shared<XmlCharacteristic>(root);
combineCharacteristics();
}
catch(std::exception& err)
@ -227,6 +244,12 @@ void KartProperties::load(const std::string &filename, const std::string &node)
std::string unique_id = StringUtils::insertValues("karts/%s", m_ident.c_str());
file_manager->pushModelSearchPath(m_root);
file_manager->pushTextureSearchPath(m_root, unique_id);
#ifndef SERVER_ONLY
if (CVS->isGLSL())
{
SP::SPShaderManager::get()->loadSPShaders(m_root);
}
#endif
STKTexManager::getInstance()
->setTextureErrorMessage("Error while loading kart '%s':", m_name);
@ -322,7 +345,7 @@ void KartProperties::setHatMeshName(const std::string &hat_name)
//-----------------------------------------------------------------------------
void KartProperties::combineCharacteristics()
{
m_combined_characteristic.reset(new CombinedCharacteristic());
m_combined_characteristic = std::make_shared<CombinedCharacteristic>();
m_combined_characteristic->addCharacteristic(kart_properties_manager->
getBaseCharacteristic());
m_combined_characteristic->addCharacteristic(kart_properties_manager->
@ -340,7 +363,8 @@ void KartProperties::combineCharacteristics()
m_combined_characteristic->addCharacteristic(characteristic);
m_combined_characteristic->addCharacteristic(m_characteristic.get());
m_cached_characteristic.reset(new CachedCharacteristic(m_combined_characteristic.get()));
m_cached_characteristic = std::make_shared<CachedCharacteristic>
(m_combined_characteristic.get());
} // combineCharacteristics
//-----------------------------------------------------------------------------

View File

@ -75,7 +75,8 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue)
// up direction to the right up direction it should have according to
// the last vaild quad of the kart
WorldWithRank* wwr = dynamic_cast<WorldWithRank*>(World::getWorld());
if (DriveGraph::get() && wwr)
if (DriveGraph::get() && wwr &&
wwr->getTrackSector(m_kart->getWorldKartId())->getCurrentGraphNode() > -1)
{
const int sector = wwr->getTrackSector(m_kart->getWorldKartId())
->getCurrentGraphNode();

View File

@ -730,7 +730,6 @@ void ThreeStrikesBattle::loadCustomModels()
m_karts.push_back(sta);
race_manager->addSpareTireKart(sta_list[i]);
Track::getCurrentTrack()->adjustForFog(sta->getNode());
// Copy STA pointer to m_spare_tire_karts array, allowing them
// to respawn easily

View File

@ -215,7 +215,6 @@ void World::init()
race_manager->getKartType(i),
race_manager->getPlayerDifficulty(i));
m_karts.push_back(newkart);
track->adjustForFog(newkart->getNode());
} // for i
@ -730,7 +729,8 @@ void World::resetAllKarts()
for (KartList::iterator i = m_karts.begin(); i != m_karts.end(); i++)
{
if ((*i)->isGhostKart()) continue;
(*i)->getBody()->setGravity((*i)->getMaterial()->hasGravity() ?
(*i)->getBody()->setGravity(
(*i)->getMaterial() && (*i)->getMaterial()->hasGravity() ?
(*i)->getNormal() * -g : Vec3(0, -g, 0));
}
for(int i=0; i<60; i++) Physics::getInstance()->update(1.f/60.f);

View File

@ -25,6 +25,7 @@
#include "graphics/material.hpp"
#include "karts/kart.hpp"
#include "karts/kart_model.hpp"
#include "karts/kart_properties.hpp"
#include "physics/triangle_mesh.hpp"
#include "tracks/terrain_info.hpp"
#include "tracks/track.hpp"

View File

@ -19,6 +19,7 @@
#include "script_kart.hpp"
#include "karts/kart.hpp"
#include "karts/kart_properties.hpp"
#include "modes/world.hpp"
#include "scriptvec3.hpp"

View File

@ -23,8 +23,8 @@
#include "config/user_config.hpp"
#include "graphics/show_curve.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/sp/sp_base.hpp"
#include "graphics/sp/sp_dynamic_draw_call.hpp"
#include "graphics/sp/sp_shader_manager.hpp"
#include "io/xml_node.hpp"
#include "items/flyable.hpp"
#include "karts/abstract_kart.hpp"
@ -68,7 +68,8 @@ CheckCannon::CheckCannon(const XMLNode &node, unsigned int index)
if (UserConfigParams::m_check_debug)
{
m_debug_target_dy_dc = std::make_shared<SP::SPDynamicDrawCall>
(scene::EPT_TRIANGLE_STRIP, SP::getSPShader("additive"),
(scene::EPT_TRIANGLE_STRIP,
SP::SPShaderManager::get()->getSPShader("additive"),
material_manager->getDefaultSPMaterial("additive"));
SP::addDynamicDrawCall(m_debug_target_dy_dc);
m_debug_target_dy_dc->getVerticesVector().resize(4);

View File

@ -21,8 +21,8 @@
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/sp/sp_base.hpp"
#include "graphics/sp/sp_dynamic_draw_call.hpp"
#include "graphics/sp/sp_shader_manager.hpp"
#include "io/xml_node.hpp"
#include "karts/abstract_kart.hpp"
#include "modes/linear_world.hpp"
@ -77,7 +77,8 @@ CheckLine::CheckLine(const XMLNode &node, unsigned int index)
{
#ifndef SERVER_ONLY
m_debug_dy_dc = std::make_shared<SP::SPDynamicDrawCall>
(scene::EPT_TRIANGLE_STRIP, SP::getSPShader("additive"),
(scene::EPT_TRIANGLE_STRIP,
SP::SPShaderManager::get()->getSPShader("additive"),
material_manager->getDefaultSPMaterial("additive"));
SP::addDynamicDrawCall(m_debug_dy_dc);
m_debug_dy_dc->getVerticesVector().resize(4);

Some files were not shown because too many files have changed in this diff Show More