diff --git a/data/shaders/normalmap2uv.frag b/data/shaders/normalmap2uv.frag new file mode 100644 index 000000000..9cf590537 --- /dev/null +++ b/data/shaders/normalmap2uv.frag @@ -0,0 +1,26 @@ +// By http://content.gpwiki.org/index.php/OpenGL:Tutorials:GLSL_Bump_Mapping +// Released under GNU FDL license, without invariant (so DFSG-compliant, see +// http://wiki.debian.org/DFSGLicenses#Exception) + +uniform sampler2D BumpTex; //The bump-map + uniform sampler2D DecalTex; //The texture + varying vec4 passcolor; //Receiving the vertex color from the vertex shader + varying vec3 LightDir; //Receiving the transformed light direction + void main() + { + vec4 LightDirTransformed4 = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(LightDir[0], LightDir[1], LightDir[2], 0); + vec3 LightDirTransformed = vec3(LightDirTransformed4[0], LightDirTransformed4[1], LightDirTransformed4[2]); + + //Get the color of the bump-map + vec3 BumpNorm = vec3(texture2D(BumpTex, gl_TexCoord[1].xy)); + //Get the color of the texture + vec3 DecalCol = vec3(texture2D(DecalTex, gl_TexCoord[0].xy)); + //Expand the bump-map into a normalized signed vector + BumpNorm = (BumpNorm -0.5) * 2.0; + //Find the dot product between the light direction and the normal + float NdotL = max(dot(BumpNorm, LightDirTransformed), 0.0) / 3.0 * 2.1 + 0.5; + //Calculate the final color gl_FragColor + vec3 diffuse = NdotL * passcolor.xyz * DecalCol; + //Set the color of the fragment... If you want specular lighting or other types add it here + gl_FragColor = vec4(diffuse, passcolor.w); + } \ No newline at end of file diff --git a/data/shaders/normalmap2uv.vert b/data/shaders/normalmap2uv.vert new file mode 100644 index 000000000..362592f61 --- /dev/null +++ b/data/shaders/normalmap2uv.vert @@ -0,0 +1,25 @@ +// By http://content.gpwiki.org/index.php/OpenGL:Tutorials:GLSL_Bump_Mapping +// Released under GNU FDL license, without invariant (so DFSG-compliant, see +// http://wiki.debian.org/DFSGLicenses#Exception) + +varying vec4 passcolor; //The vertex color passed + varying vec3 LightDir; //The transformed light direction, to pass to the fragment shader + attribute vec3 tangent; //The inverse tangent to the geometry + attribute vec3 binormal; //The inverse binormal to the geometry + uniform vec3 lightdir; //The direction the light is shining + void main() + { + //Put the color in a varying variable + passcolor = gl_Color; + //Put the vertex in the position passed + gl_Position = ftransform(); + //Construct a 3x3 matrix from the geometry’s inverse tangent, binormal, and normal + mat3 rotmat = mat3(tangent,binormal,gl_Normal); + //Rotate the light into tangent space + LightDir = rotmat * normalize(lightdir); + //Normalize the light + normalize(LightDir); + //Use the first set of texture coordinates in the fragment shader + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[1] = gl_MultiTexCoord1; + } diff --git a/src/graphics/material.cpp b/src/graphics/material.cpp index ef1aae46b..9ea0ebbec 100644 --- a/src/graphics/material.cpp +++ b/src/graphics/material.cpp @@ -188,29 +188,47 @@ Material::Material(const XMLNode *node, int index) node->get("crash-reset-particles", &m_crash_reset_particles); } - if (node->get("normal-map", &m_normal_map_tex)) + bool use_normal_map = false; + node->get("use-normal-map", &use_normal_map); + + if (use_normal_map) { - m_normal_map = true; - } - else if (node->get("normal-heightmap", &m_normal_map_tex)) - { - m_is_heightmap = true; - m_normal_map = true; - } - else if (node->get("parallax-map", &m_normal_map_tex)) - { - m_parallax_map = true; - m_parallax_height = 0.2f; - node->get("parallax-height", &m_parallax_height); - } - else if (node->get("parallax-heightmap", &m_normal_map_tex)) - { - m_is_heightmap = true; - m_parallax_map = true; - m_parallax_height = 0.2f; - node->get("parallax-height", &m_parallax_height); - } + if (node->get("normal-map", &m_normal_map_tex)) + { + m_normal_map = true; + } + else + { + fprintf(stderr, "[Material] WARNING: could not find normal map image in materials.xml\n"); + } + + m_normal_map_uv2 = false; + node->get("normal-map-uv2", &m_normal_map_uv2); + + // TODO: add support for parallax maps? + /* + else if (node->get("normal-heightmap", &m_normal_map_tex)) + { + m_is_heightmap = true; + m_normal_map = true; + } + else if (node->get("parallax-map", &m_normal_map_tex)) + { + m_parallax_map = true; + m_parallax_height = 0.2f; + node->get("parallax-height", &m_parallax_height); + } + else if (node->get("parallax-heightmap", &m_normal_map_tex)) + { + m_is_heightmap = true; + m_parallax_map = true; + m_parallax_height = 0.2f; + node->get("parallax-height", &m_parallax_height); + } + */ + } + s=""; node->get("graphical-effect", &s ); @@ -341,6 +359,7 @@ void Material::init(unsigned int index) m_zipper_max_speed_increase = -1.0f; m_zipper_speed_gain = -1.0f; m_normal_map = false; + m_normal_map_uv2 = false; m_parallax_map = false; m_is_heightmap = false; m_alpha_to_coverage = false; @@ -654,17 +673,22 @@ void Material::setMaterialProperties(video::SMaterial *m) { m_normal_map_provider = new NormalMapProvider(); } - + + const char* vertex_shader = (m_normal_map_uv2 ? + "shaders/normalmap2uv.vert" : + "shaders/normalmap.vert"); + const char* pixel_shader = (m_normal_map_uv2 ? + "shaders/normalmap2uv.frag" : + "shaders/normalmap.frag"); + // Material and shaders IGPUProgrammingServices* gpu = video_driver->getGPUProgrammingServices(); s32 material_type = gpu->addHighLevelShaderMaterialFromFiles( - (file_manager->getDataDir() + - "shaders/normalmap.vert").c_str(), + (file_manager->getDataDir() + vertex_shader).c_str(), "main", video::EVST_VS_2_0, - (file_manager->getDataDir() + - "shaders/normalmap.frag").c_str(), + (file_manager->getDataDir() + pixel_shader).c_str(), "main", video::EPST_PS_2_0, m_normal_map_provider, diff --git a/src/graphics/material.hpp b/src/graphics/material.hpp index ef4544bf2..d3b5c4df1 100644 --- a/src/graphics/material.hpp +++ b/src/graphics/material.hpp @@ -101,6 +101,7 @@ private: /** For normal maps */ bool m_normal_map; std::string m_normal_map_tex; + bool m_normal_map_uv2; //!< Whether to use a second UV layer for normal map bool m_is_heightmap; bool m_parallax_map; float m_parallax_height;