From c6a2cecc05d2a0d19b3839736b7b94f4797a13ad Mon Sep 17 00:00:00 2001 From: auria Date: Thu, 16 Feb 2012 02:25:52 +0000 Subject: [PATCH] Add my own sphere mapping shader, since irrlicht's one is buggy when the model moves around. Bonus, mine uses pixel shading instead of vertex shading, which makes the shadows much smoother git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10859 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/models/materials.xml | 5 +- data/shaders/spheremap.frag | 24 ++++++++ data/shaders/spheremap.vert | 15 +++++ src/graphics/material.cpp | 82 ++++++++++++++++++++++++- src/graphics/material.hpp | 2 + src/states_screens/main_menu_screen.cpp | 17 +++-- 6 files changed, 131 insertions(+), 14 deletions(-) create mode 100644 data/shaders/spheremap.frag create mode 100644 data/shaders/spheremap.vert diff --git a/data/models/materials.xml b/data/models/materials.xml index d8d2af8d0..7c9fa26eb 100644 --- a/data/models/materials.xml +++ b/data/models/materials.xml @@ -3,7 +3,10 @@ - + + + + diff --git a/data/shaders/spheremap.frag b/data/shaders/spheremap.frag new file mode 100644 index 000000000..d6f5c4023 --- /dev/null +++ b/data/shaders/spheremap.frag @@ -0,0 +1,24 @@ + + +uniform sampler2D texture; +varying vec3 normal; +uniform vec3 lightdir; +varying vec4 vertex_color; + +void main() +{ + vec3 forward = vec3(0.0, 0.0, 1.0); + + // get the angle between the forward vector and the horizontal portion of the normal + vec3 normal_x = normalize(vec3(normal.x, 0.0, normal.z)); + float sin_theta_x = length(cross( forward, normal_x )) * normal.x/abs(normal.x); + + // get the angle between the forward vector and the vertical portion of the normal + vec3 normal_y = normalize(vec3(0.0, normal.y, normal.z)); + float sin_theta_y = length(cross( forward, normal_y ))* normal.y/abs(normal.y); + + vec4 detail0 = texture2D(texture, vec2(0.5 + sin_theta_x*0.5, 0.5 + sin_theta_y*0.5)); + + gl_FragColor = detail0 * (0.5 + dot(lightdir, normal)) * vertex_color; // 0.5 is the ambient light. + //gl_FragColor = vec4(sin_theta_y*0.5 + 0.5, 0.0, 1.0 - (sin_theta_y*0.5 + 0.5), 1.0); +} diff --git a/data/shaders/spheremap.vert b/data/shaders/spheremap.vert new file mode 100644 index 000000000..873bf0e42 --- /dev/null +++ b/data/shaders/spheremap.vert @@ -0,0 +1,15 @@ +varying vec3 normal; +varying vec4 vertex_color; + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = ftransform(); + vertex_color = gl_Color; + + //vec3 normal3 = normalize(gl_Normal); + //vec4 normal4 = vec4(normal3.x, normal3.y, normal3.z, 0.0)*gl_ModelViewMatrix; + //normal = normal4.xyz; + + normal = normalize(gl_NormalMatrix*gl_Normal); +} diff --git a/src/graphics/material.cpp b/src/graphics/material.cpp index f9483ba96..d69ee590b 100644 --- a/src/graphics/material.cpp +++ b/src/graphics/material.cpp @@ -70,6 +70,7 @@ public: } }; + //----------------------------------------------------------------------------- class WaterShaderProvider : public video::IShaderConstantSetCallBack @@ -186,6 +187,37 @@ public: } }; +//----------------------------------------------------------------------------- + +#if 0 +#pragma mark - +#endif + +class SphereMapProvider: public video::IShaderConstantSetCallBack +{ + core::vector3df m_light_direction; + +public: + LEAK_CHECK() + + SphereMapProvider() + { + m_light_direction = core::vector3df(-0.6f, -0.5f, -0.63f); + //m_light_direction = core::vector3df(-0.315f, 0.91f, -0.3f); + } + + virtual void OnSetConstants( + irr::video::IMaterialRendererServices *services, + s32 userData) + { + // Irrlicht knows this is actually a GLint and makes the conversion + int texture = 0; + services->setPixelShaderConstant("texture", (float*)&texture, 1); + + services->setVertexShaderConstant("lightdir", &m_light_direction.X, 3); + } +}; + //----------------------------------------------------------------------------- #if 0 #pragma mark - @@ -290,6 +322,7 @@ Material::Material(const XMLNode *node, int index) node->get("alpha", &m_alpha_blending ); node->get("light", &m_lighting ); node->get("sphere", &m_sphere_map ); + node->get("smooth-reflection",&m_smooth_reflection_shader); node->get("high-adhesion", &m_high_tire_adhesion); node->get("reset", &m_drive_reset ); @@ -506,6 +539,7 @@ void Material::init(unsigned int index) m_lighting = true; m_backface_culling = true; m_sphere_map = false; + m_smooth_reflection_shader = false; m_high_tire_adhesion = false; m_below_surface = false; m_falling_effect = false; @@ -806,10 +840,53 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m modes++; } + if (m_smooth_reflection_shader) + { + IVideoDriver* video_driver = irr_driver->getVideoDriver(); + if (UserConfigParams::m_pixel_shaders && + video_driver->queryFeature(video::EVDF_ARB_GLSL) && + video_driver->queryFeature(video::EVDF_PIXEL_SHADER_2_0)) + { + if (m_shaders[SPHERE_MAP] == NULL) + { + m_shaders[SPHERE_MAP] = new SphereMapProvider(); + } + // Material and shaders + IGPUProgrammingServices* gpu = + irr_driver->getVideoDriver()->getGPUProgrammingServices(); + s32 material_type = gpu->addHighLevelShaderMaterialFromFiles( + (file_manager->getDataDir() + + "shaders/spheremap.vert").c_str(), + "main", + video::EVST_VS_2_0, + (file_manager->getDataDir() + + "shaders/spheremap.frag").c_str(), + "main", + video::EPST_PS_2_0, + m_shaders[SPHERE_MAP], + video::EMT_SOLID_2_LAYER ); + m->MaterialType = (E_MATERIAL_TYPE)material_type; + } + else + { + m->MaterialType = video::EMT_SPHERE_MAP; + + // sphere map + alpha blending is a supported combination so in + // this case don't increase mode count + if (m_alpha_blending) + { + m->BlendOperation = video::EBO_ADD; + } + else + { + modes++; + } + } + } if (m_sphere_map) { m->MaterialType = video::EMT_SPHERE_MAP; - + // sphere map + alpha blending is a supported combination so in // this case don't increase mode count if (m_alpha_blending) @@ -853,8 +930,7 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m IVideoDriver* video_driver = irr_driver->getVideoDriver(); if (UserConfigParams::m_pixel_shaders && video_driver->queryFeature(video::EVDF_ARB_GLSL) && - video_driver->queryFeature(video::EVDF_PIXEL_SHADER_2_0) && - video_driver->queryFeature(video::EVDF_RENDER_TO_TARGET)) + video_driver->queryFeature(video::EVDF_PIXEL_SHADER_2_0)) { ITexture* tex = irr_driver->getTexture(m_normal_map_tex); if (m_is_heightmap) diff --git a/src/graphics/material.hpp b/src/graphics/material.hpp index 83e0ef025..1e618f976 100644 --- a/src/graphics/material.hpp +++ b/src/graphics/material.hpp @@ -78,6 +78,7 @@ private: NORMAL_MAP, SPLATTING, WATER_SHADER, + SPHERE_MAP, SHADER_COUNT }; @@ -147,6 +148,7 @@ private: bool m_lighting; bool m_sphere_map; + bool m_smooth_reflection_shader; bool m_alpha_testing; bool m_alpha_blending; bool m_alpha_to_coverage; diff --git a/src/states_screens/main_menu_screen.cpp b/src/states_screens/main_menu_screen.cpp index 2c2716ae8..8b50c4679 100644 --- a/src/states_screens/main_menu_screen.cpp +++ b/src/states_screens/main_menu_screen.cpp @@ -15,7 +15,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#define DEBUG_MENU_ITEM 0 +#define DEBUG_MENU_ITEM 1 #include "states_screens/main_menu_screen.hpp" @@ -189,6 +189,10 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name, FeatureUnlockedCutScene* scene = FeatureUnlockedCutScene::getInstance(); + scene->addTrophy(RaceManager::RD_HARD); + StateManager::get()->pushScreen(scene); + + /* static int i = 1; i++; @@ -221,15 +225,7 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name, ->getScreenshotFile().c_str())); scene->addUnlockedPictures(textures, 1.0, 0.75, L"You did it"); - - /* - scene->addUnlockedPicture( - irr_driver->getTexture( - track_manager->getTrack("lighthouse") - ->getScreenshotFile().c_str()), - 1.0, 0.75, L"You did it"); - */ - + StateManager::get()->pushScreen(scene); } else if (i % 4 == 2) @@ -249,6 +245,7 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name, losers.push_back("wilber"); scene->setKarts( losers ); } + */ } else #endif