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
This commit is contained in:
auria 2012-02-16 02:25:52 +00:00
parent 49d190defe
commit c6a2cecc05
6 changed files with 131 additions and 14 deletions

View File

@ -3,7 +3,10 @@
<material name="banana.png"/>
<material name="gift-box.png"/>
<material name="gift-loop.png" sphere="Y"/>
<material name="gold.png" light="Y" sphere="Y"/>
<material name="gold.png" light="Y" smooth-reflection="Y"/>
<material name="silver.png" light="Y" smooth-reflection="Y"/>
<material name="bronze.png" light="Y" smooth-reflection="Y"/>
<material name="nitro-tank.png" transparency="Y"/>
<material name="tank-blue.png" sphere="Y"/>
<material name="tank-green.png" sphere="Y"/>

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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)

View File

@ -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;

View File

@ -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