Shaders and Mipmapping
Shaders and Mipmapping
when I, say, on terrain have a road texture (uvcoord1) blended to a terrain texture (uvcoord2) the mipmapping on the terrain texture seems to be controlled by the mipmapping on the road texture. So if the road texture is much smaller than the terrain texture, the terrain will be in the a much lower mip than adjacent non blended terrain. Obviously I can make all textures the same size so they all mip at the same rate but that makes getting a constant pixel density tricky. Is there any other way round this ? sorry this is in openGL btw.
Re: Shaders and Mipmapping
Interesting. try to enable anisotropic filtering only on the road texture and see if that still happens.
OpenGL says that every texture unit should behave according to glTexParameters. so it can be both a bug in mipmap settings of Irrlicht or a wrong implementation of GL of your video card. Have you tried on different PCs? You can still write a sader using a specific mipmap level but that is even trickier.
OpenGL says that every texture unit should behave according to glTexParameters. so it can be both a bug in mipmap settings of Irrlicht or a wrong implementation of GL of your video card. Have you tried on different PCs? You can still write a sader using a specific mipmap level but that is even trickier.
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
Re: Shaders and Mipmapping
You can tell it to use a given mip level (texture2dLod), or add a bias.
Re: Shaders and Mipmapping
it seems to be a bug either in my code or irrlicht, something to do with call driver->getTexture(filename) on a previously loaded texture leaves the previous texture with no mipmaps (hence the terrain in the image the terrain isn't mipping out but the new terrain in the blend is). It works ok if I duplicate the terrain texture and load the copy in the blend.
Re: Shaders and Mipmapping
it seems to be an issue when the new terrain is set as a different texture index on the new material that is
if on the terrain material it would be
mat.setTexture(0,texture);
on the blending material the same texture is set as
mat.setTexture(1,texture);
this will cause loss of mipmaps on the original terrain material
if the terrain texture is set as
mat.setTexture(0,texture);
on the blend there's no loss of mipmaps
the only difference between the two is the top right hand sphere has the displayed texture in the second texture slot. There is a very obvious and easy work around for me (i just need to swap two lines in the max shader, so the terrain texture is defined first). But this sort thing will bug me for ages
if on the terrain material it would be
mat.setTexture(0,texture);
on the blending material the same texture is set as
mat.setTexture(1,texture);
this will cause loss of mipmaps on the original terrain material
if the terrain texture is set as
mat.setTexture(0,texture);
on the blend there's no loss of mipmaps
the only difference between the two is the top right hand sphere has the displayed texture in the second texture slot. There is a very obvious and easy work around for me (i just need to swap two lines in the max shader, so the terrain texture is defined first). But this sort thing will bug me for ages
Re: Shaders and Mipmapping
That does rather sound like an Irrlicht bug.
-
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
Re: Shaders and Mipmapping
Could you please provide a test case which we can use to debug and fix this issue? So do you have a texture set in slot 0 as well? Because right now Irrlicht it might be required to use the texture slots consecutively. IIRC, we break at the first empty slot.
Re: Shaders and Mipmapping
yes there is texture in slot 0 as well. the test case may be a quite a bit of work as It's all custom file format and non standard loader
-
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
Re: Shaders and Mipmapping
Uh, I thought you just created two spheres, a teexture and a plane, and just need to attack the shaders there... As we don't need the terrain obviously, and the spheres can be created with one Irrlicht call, without any loaders.
Re: Shaders and Mipmapping
no the spheres were exported from max, the exporter exports Directx (.fx files) materials assigned to the spheres, along with all params. the loader then finds the appropriate glsl shader and reads out the params which are then passed to the correct extended shadercall back. works really well gives me a perfect wysiwyg between max and irrlicht unfortunately doesn't make for quick and easy test cases for you. I'll try and get round to creating a stand alone test case.
Re: Shaders and Mipmapping
this will generate the same error, I copied straight over "HelloWorld" example with main.cpp and the 4 shaders go in the media folder.
main.cpp
blend_to_terrain.vert
blend_to_terrain.frag
terrain.vert
terrain.frag
main.cpp
Code: Select all
#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
//***********************************************************************
class CCamSpaceLightAnim : public ISceneNodeAnimator
{
public:
CCamSpaceLightAnim(ICameraSceneNode* cam, float offset, bool left)
: camera(cam), csoffset(0.5f * sin(PI/6.0f), 0.5f * cos(PI/6.0f),-cos(PI/6.0f)), doffset(offset)
{
if(left)
csoffset.X *= -1.0f;
}
virtual void animateNode(ISceneNode* node, u32 timeMs)
{
matrix4 camTM, lightTM;
vector3df wsoffset;
camera->getViewMatrix().getInverse(camTM);
camTM.zeroTranslation();
camTM.transformVect(wsoffset,csoffset);
TransformFromDirVector(-wsoffset, lightTM);
node->setRotation(lightTM.getRotationDegrees());
node->setPosition(wsoffset * doffset);
}
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const {}
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) {}
virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_UNKNOWN; }
virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0)
{
return new CCamSpaceLightAnim(camera,doffset,false);
}
private:
void TransformFromDirVector(const vector3df& dir, matrix4& mat)
{
vector3df up(0.0f,1.0f,0.0f), zaxis, xaxis, yaxis;
zaxis = dir;
zaxis.normalize();
xaxis = up.crossProduct(zaxis);
xaxis.normalize();
yaxis = zaxis.crossProduct(xaxis);
mat[0] = xaxis.X; mat[1] = xaxis.Y; mat[2] = xaxis.Z; mat[3] = 0;
mat[4] = yaxis.X; mat[5] = yaxis.Y; mat[6] = yaxis.Z; mat[7] = 0;
mat[8] = zaxis.X; mat[9] = zaxis.Y; mat[10] = zaxis.Z; mat[11] = 0;
mat[12] = 0; mat[13] = 0; mat[14] = 0; mat[15] = 1;
}
vector3df csoffset;
float doffset;
ICameraSceneNode* camera;
};
//***********************************************************************
#define LIGHT_INDEX "glight"
#define AMBIENTCOLOUR "gAmbient"
#define DIFFUSECOLOUR "gDiffuse"
#define DIFFUSEMAP "diffuseMapTexture"
#define BLENDTOMAP "blendtoMapTexture"
class Terrain_Shader : public IShaderConstantSetCallBack
{
u32 light;
SColorf ambient;
SColorf diffuse;
int diffuse_sampler;
public:
Terrain_Shader() : light(0), ambient(0.0f,0.0f,0.0f), diffuse(1.0f,1.0f,1.0f), diffuse_sampler(0) {}
virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData)
{
services->setVertexShaderConstant(LIGHT_INDEX, (float*)(&light), 1);
services->setVertexShaderConstant(AMBIENTCOLOUR, (float*)(&ambient), 4);
services->setVertexShaderConstant(DIFFUSECOLOUR, (float*)(&diffuse), 4);
services->setPixelShaderConstant(DIFFUSEMAP,(float*)(&diffuse_sampler),1);
}
};
//***********************************************************************
class BlendToTerrain_Shader : public IShaderConstantSetCallBack
{
u32 light;
SColorf ambient;
SColorf diffuse;
int diffuse_sampler;
int blend_sampler;
public:
BlendToTerrain_Shader() : light(0), ambient(0.0f,0.0f,0.0f),
diffuse(1.0f,1.0f,1.0f), diffuse_sampler(0) , blend_sampler(1) {}
virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData)
{
services->setVertexShaderConstant(LIGHT_INDEX, (float*)(&light), 1);
services->setVertexShaderConstant(AMBIENTCOLOUR, (float*)(&ambient), 4);
services->setVertexShaderConstant(DIFFUSECOLOUR, (float*)(&diffuse), 4);
services->setPixelShaderConstant(DIFFUSEMAP,(float*)(&diffuse_sampler),1);
services->setPixelShaderConstant(BLENDTOMAP,(float*)(&blend_sampler),1);
}
};
//***********************************************************************
int main()
{
IrrlichtDevice *device = createDevice( video::EDT_OPENGL, dimension2d<u32>(640, 480), 16, false, false, false, 0);
if (!device)
return 1;
device->setWindowCaption(L"Test mipmap");
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
// add spheres
IMeshSceneNode* sphereNode1 = smgr->addSphereSceneNode(50,16,smgr->getRootSceneNode(),999,vector3df(100.0f,0.0,0.0));
IMeshSceneNode* sphereNode2 = smgr->addSphereSceneNode(50,16,smgr->getRootSceneNode(),1000,vector3df(-100.0f,0.0,0.0));
// add camera
ICameraSceneNode* cameraNode = smgr->addCameraSceneNodeMaya();;
// add a light
ILightSceneNode* lightNode = smgr->addLightSceneNode(smgr->getRootSceneNode(),vector3df(0,0,0));
lightNode->setLightType(ELT_DIRECTIONAL);
// add camera space animator
ISceneNodeAnimator* anim = new CCamSpaceLightAnim(cameraNode,100.0f,false);
if(anim)
{
lightNode->addAnimator(anim);
anim->drop();
}
path blendtoVSfname = "../../media/blend_to_terrain.vert";
path blendtoPSfname = "../../media/blend_to_terrain.frag";
path terrainVSfname = "../../media/terrain.vert";
path terrainPSfname = "../../media/terrain.frag";
if (!driver->queryFeature(EVDF_PIXEL_SHADER_1_1) && !driver->queryFeature(EVDF_ARB_FRAGMENT_PROGRAM_1))
{
device->getLogger()->log("WARNING: Pixel shaders disabled ");
blendtoPSfname = "";
terrainVSfname = "";
}
if (!driver->queryFeature(EVDF_VERTEX_SHADER_1_1) && !driver->queryFeature(EVDF_ARB_VERTEX_PROGRAM_1))
{
device->getLogger()->log("WARNING: Vertex shaders disabled ");
blendtoVSfname = "";
terrainPSfname = "";
}
IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();
s32 terrainShaderMat = 0;
s32 blendtoShaderMat = 0;
if (gpu)
{
Terrain_Shader* ts = new Terrain_Shader();
terrainShaderMat = gpu->addHighLevelShaderMaterialFromFiles( terrainVSfname, "main",
EVST_VS_1_1, terrainPSfname, "main", EPST_PS_1_1, ts, EMT_SOLID);
ts->drop();
BlendToTerrain_Shader* bts = new BlendToTerrain_Shader();
blendtoShaderMat = gpu->addHighLevelShaderMaterialFromFiles( blendtoVSfname, "main",
EVST_VS_1_1, blendtoPSfname, "main", EPST_PS_1_1, bts, EMT_SOLID);
bts->drop();
}
sphereNode1->setMaterialType((E_MATERIAL_TYPE)terrainShaderMat);
sphereNode2->setMaterialType((E_MATERIAL_TYPE)blendtoShaderMat);
ITexture* texture;
driver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, true);
texture = driver->getTexture("../../media/wall.jpg");
sphereNode1->setMaterialTexture(0, texture);
texture = driver->getTexture("../../media/wall.bmp");
sphereNode2->setMaterialTexture(0, texture);
texture = driver->getTexture("../../media/wall.jpg");
sphereNode2->setMaterialTexture(1, texture);
// dooo it
while(device->run())
{
driver->beginScene(true, true, SColor(255,127,127,140));
smgr->drawAll();
driver->endScene();
}
device->drop();
return 0;
}
Code: Select all
uniform int glight;
uniform vec4 gAmbient;
uniform vec4 gDiffuse;
void main()
{
gl_Position = ftransform();
vec3 N = gl_NormalMatrix * gl_Normal;
vec3 L = gl_LightSource[glight].position;
float lambert = 0.5 * dot(N,L) + 0.5;
gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
gl_TexCoord[0].zw = gl_MultiTexCoord1.xy;
gl_FrontColor = gl_Color * gl_LightSource[glight].diffuse * gDiffuse * (gAmbient + lambert * lambert);
}
Code: Select all
uniform sampler2D diffuseMapTexture;
uniform sampler2D blendtoMapTexture;
void main()
{
/* normally this but needs second map channel to work
vec4 col = texture2D(diffuseMapTexture, vec2(gl_TexCoord[0].xy));
vec4 bld = texture2D(blendtoMapTexture, vec2(gl_TexCoord[0].zw));
gl_FragColor = gl_Color * lerp(bld,col,gl_Color.a); */
// so we've replaced with this
vec4 bld = texture2D(blendtoMapTexture, vec2(gl_TexCoord[0].xy));
gl_FragColor = gl_Color * bld;
}
Code: Select all
uniform int glight;
uniform vec4 gAmbient;
uniform vec4 gDiffuse;
void main()
{
gl_Position = ftransform();
vec3 N = gl_NormalMatrix * gl_Normal;
vec3 L = gl_LightSource[glight].position;
float lambert = 0.5 * dot(N,L) + 0.5;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_FrontColor = gl_Color * gl_LightSource[glight].diffuse * gDiffuse * (gAmbient + lambert * lambert);
}
Code: Select all
uniform sampler2D diffuseMapTexture;
void main()
{
vec4 col = texture2D(diffuseMapTexture, vec2(gl_TexCoord[0]));
gl_FragColor = col * gl_Color;
}
Re: Shaders and Mipmapping
btw you can correct the issue by changing
and
Code: Select all
texture = driver->getTexture("../../media/wall.bmp");
sphereNode2->setMaterialTexture(0, texture);
texture = driver->getTexture("../../media/wall.jpg");
sphereNode2->setMaterialTexture(1, texture);
Code: Select all
texture = driver->getTexture("../../media/wall.bmp");
sphereNode2->setMaterialTexture(1, texture);
texture = driver->getTexture("../../media/wall.jpg");
sphereNode2->setMaterialTexture(0, texture);
Code: Select all
BlendToTerrain_Shader() : light(0), ambient(0.0f,0.0f,0.0f),
diffuse(1.0f,1.0f,1.0f), diffuse_sampler(0), blend_sampler(1) {}
Code: Select all
BlendToTerrain_Shader() : light(0), ambient(0.0f,0.0f,0.0f),
diffuse(1.0f,1.0f,1.0f), diffuse_sampler(1), blend_sampler(0) {}
Re: Shaders and Mipmapping
is there a fix for this yet ?