[Solved!] Highlights in wrong places.

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

[Solved!] Highlights in wrong places.

Post by Mel »

I've started messing with shaders, and i've found some troubles. To be honest, i'm quite a newbee in the shader programming tasks, so, i simply am cluesless. The shading highlights aren't where they're suposed to be, but the shader works, more or less, right. It is taken and a bit modified directly from the Render Monkey shader tool.

Anyone see something out of place in the shaders, or in the code?

to make a graphical explanation of this:

Image


Here, we see that there should be a little of highlights in the tigh, perhaps but there isn't.

Image

And in this image the light is behind the models, so, little, or no highlight should be present, and there they are.

I've tried some combinations, and none of them gave a satisfactory result, this is the closest stage to what a good phong shader should be, IMO, so, if anyone who knew about shaders a bit could take a peek and say what would be out of place, would be a great help. Thanks!

This is the code.

Code: Select all

#include <iostream>
#include <irrlicht.h>

#pragma comment(lib, "Irrlicht.lib")

using namespace std;
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

//a small and pointy tweak, using the "user data" i give the callback full access to all the irrlicht device :)
//god bless that pointers are still good ol' 32 bits integers ^O^

class bumpPhongCNS : public IShaderConstantSetCallBack{
      public:
      virtual void  OnSetConstants (IMaterialRendererServices *services, s32 userData){

              IrrlichtDevice *dev=(IrrlichtDevice *) userData;
              
              matrix4 matViewProjection=dev->getSceneManager()->getActiveCamera()->getProjectionMatrix();
              matViewProjection*=dev->getVideoDriver()->getTransform(ETS_VIEW);
              matViewProjection*=dev->getVideoDriver()->getTransform(ETS_WORLD);
              
              vector3df lightPos = vector3df(100,100,100);
              
              services->setVertexShaderConstant("fvLightPosition",reinterpret_cast<f32*>(&lightPos),3);
              vector3df camPos = dev->getSceneManager()->getActiveCamera()->getPosition();
              services->setVertexShaderConstant("fvEyePosition",reinterpret_cast<f32*>(&camPos),3);
 
              matrix4 matView=dev->getSceneManager()->getActiveCamera()->getProjectionMatrix();
              matView*=dev->getVideoDriver()->getTransform(ETS_WORLD);
              
              services->setVertexShaderConstant("matView",&matView[0],16);
              services->setVertexShaderConstant("matViewProjection",&matViewProjection[0],16);
              
              SColorf lightAmbient = SColorf(.1,.1,.1,1);
              services->setPixelShaderConstant("fvAmbient",reinterpret_cast<f32*>(&lightAmbient),4);
              SColorf lightDiffuse = SColorf(1,1,1,1);
              services->setPixelShaderConstant("fvDiffuse",reinterpret_cast<f32*>(&lightDiffuse),4);
              
              float specularPower = 25;
              services->setPixelShaderConstant("fSpecularPower",reinterpret_cast<f32*>(&specularPower),1);

              return;
      }
};

int main(int argc, char *argv[])
{

//We create a small direct3d9 device...

IrrlichtDevice *device=0;
ISceneManager *smgr=0;
IVideoDriver *driver=0;
IAnimatedMeshSceneNode *uni=0;
IAnimatedMeshSceneNode *uni2=0;
ISkinnedMesh *uniMesh=0;
IGPUProgrammingServices *gpu=0;
s32 material;
ICameraSceneNode *camara=0;

bumpPhongCNS *cons = new bumpPhongCNS();

device = createDevice(EDT_DIRECT3D9 , dimension2d<s32>(1024, 768),32,false,true,false,0);

if(device){

  smgr=device->getSceneManager();
  driver=device->getVideoDriver();
  
  if(!smgr||!driver){ exit(1);}

//add a camera, two lights

  camara=smgr->addCameraSceneNodeMaya();
  
  camara->setPosition(vector3df(0,1,3));
    
  smgr->addLightSceneNode(0, 
      vector3df(100, 100, 100),  
      SColorf(1, 1, 1),
      2000);
  smgr->addLightSceneNode(0, 
      vector3df(-100, -100, -100),  
      SColorf(.5,.5,.5),
      2000);


//We load a tiny cool mesh, perhaps Uni.

gpu = driver->getGPUProgrammingServices();

//We load the Shader...
//While it doesn't blow up, experiments are welcome! ^^

material = gpu->addHighLevelShaderMaterialFromFiles  (  
  "./datos/BumpPhongV.hlsl",  
  "vs_main",  
  EVST_VS_2_0,  
  "./datos/BumpPhongP.hlsl",  
  "ps_main",  
  EPST_PS_2_0,  
  cons,  
  EMT_SOLID,
  (s32)device
 ); 


uniMesh = (ISkinnedMesh *) smgr->getMesh("./datos/uni.X");
uniMesh->convertMeshToTangents();

if (uniMesh){
  uni = smgr->addAnimatedMeshSceneNode(uniMesh);
}

uni->setMaterialTexture(1,driver->getTexture("./datos/base.body.universe.normals.png"));
uni->getMaterial(0).MaterialType=(E_MATERIAL_TYPE)material;
uni->getMaterial(1).MaterialType=(E_MATERIAL_TYPE)material;
uni->getMaterial(2).MaterialType=(E_MATERIAL_TYPE)material;
uni->getMaterial(3).MaterialType=(E_MATERIAL_TYPE)material;

uni2=smgr->addAnimatedMeshSceneNode(uniMesh);

uni->setPosition(vector3df(-1,0,0));
uni2->setPosition(vector3df(1,0,0));

//We try to put shaders a go go!


  device->getCursorControl()->setVisible(false);
  
  int lastFPS;
  
  while(device->run()){
  
    driver->beginScene(true,true,SColor(0,64,128,160));
    smgr->drawAll();
    driver->endScene();
    
    int fps = driver->getFPS();

		if (lastFPS != fps)
		{
		  core::stringw str = L"PixelShader tests [";
		  str += driver->getName();
		  str += "] FPS:";
		  str += fps;
		  device->setWindowCaption(str.c_str());
		  lastFPS = fps;
		}
  
  }

}
//And That's all folks! :)
return 0;
}


Code: Select all


/////Vertex Shader/////////////////////////////////

float3 fvLightPosition;
float3 fvEyePosition;
float4x4 matView;
float4x4 matViewProjection;

struct VS_INPUT 
{
   float4 Position : POSITION0;
   float2 Texcoord : TEXCOORD0;
   float3 Normal :   NORMAL0;
   float3 Binormal : BINORMAL0;
   float3 Tangent :  TANGENT0;
   
};

struct VS_OUTPUT 
{
   float4 Position :        POSITION0;
   float2 Texcoord :        TEXCOORD0;
   float3 ViewDirection :   TEXCOORD1;
   float3 LightDirection:   TEXCOORD2;
   
};

VS_OUTPUT vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;

   Output.Position         = mul( Input.Position, matViewProjection );
   Output.Texcoord         = Input.Texcoord;
   
   float3 fvObjectPosition = mul( Input.Position, matView );
   
   float3 fvViewDirection  = fvEyePosition - fvObjectPosition;
   float3 fvLightDirection = fvLightPosition - fvObjectPosition ;
     
   float3 fvNormal         = mul( Input.Normal, matView );
   float3 fvBinormal       = mul( Input.Binormal, matView );
   float3 fvTangent        = mul( Input.Tangent, matView );
      
   Output.ViewDirection.x  = dot( fvTangent, fvViewDirection );
   Output.ViewDirection.y  = dot( fvBinormal, fvViewDirection );
   Output.ViewDirection.z  = dot( fvNormal, fvViewDirection );
   
   Output.LightDirection.x  = dot( fvTangent, fvLightDirection );
   Output.LightDirection.y  = dot( fvBinormal, fvLightDirection );
   Output.LightDirection.z  = dot( fvNormal, fvLightDirection );
   
   return( Output );
   
}

Code: Select all

//////Pixel Shader//////////////////////////////////////////////

float4 fvAmbient;
float4 fvDiffuse;
float4 fvLightColor;
float fSpecularPower;

sampler2D baseMap;
sampler2D bumpMap;

struct PS_INPUT 
{
   float2 Texcoord :        TEXCOORD0;
   float3 ViewDirection :   TEXCOORD1;
   float3 LightDirection:   TEXCOORD2;
   
};

float4 ps_main( PS_INPUT Input ) : COLOR0
{      
   float3 fvLightDirection = normalize( Input.LightDirection );
   float3 fvNormal         = normalize( ( tex2D( bumpMap, Input.Texcoord ).xyz * 2.0f ) - 1.0f );
   float  fNDotL           = dot( fvNormal, fvLightDirection ); 
   
   float3 fvReflection     = normalize( ( ( 2.0f * fvNormal ) * ( fNDotL ) ) - fvLightDirection ); 
   float3 fvViewDirection  = normalize( Input.ViewDirection );
   float  fRDotV           = max( 0.0f, dot( fvReflection, fvViewDirection ) );
   
   float4 fvBaseColor      = tex2D( baseMap, Input.Texcoord );
   
   float4 fvTotalAmbient   = fvAmbient * fvBaseColor; 
   float4 fvTotalDiffuse   = fvDiffuse * fNDotL * fvBaseColor ;
   float4 fvTotalSpecular  = tex2D( baseMap, Input.Texcoord ) * pow( fRDotV, fSpecularPower ) ;
   
   return( saturate( fvTotalAmbient + fvTotalDiffuse + fvTotalSpecular ) );
      
}
Last edited by Mel on Thu Nov 20, 2008 4:05 pm, edited 1 time in total.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Code: Select all

matrix4 matView=dev->getSceneManager()->getActiveCamera()->getProjectionMatrix();
              matView*=dev->getVideoDriver()->getTransform(ETS_WORLD);
             
              services->setVertexShaderConstant("matView",&matView[0],16)
What is this? You are supposed to pass the view matrix, not the "world projection" (If there is such a thing :P , I've never seen world and projection being used together...)

That aside, bumpmapping can be a bit tricky to get right and so can specular highlights. I suggest starting from scratch with a basic phong lighting shader so you can wrap your head around the concept easier. There are tons of hlsl tutorials on the net for writing phong lighting shaders. This one looks pretty nice at a glance.

EDIT: Ignore the "technique blocks" thing at the end of tutorial I linked, it's irrelevant.
Last edited by BlindSide on Mon Nov 17, 2008 9:05 pm, edited 2 times in total.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

And in this image the light is behind the models, so, little, or no highlight should be present, and there they are.
Yeah, i know what u mean there. I've seen that show-up in my demo as well. It's annoying as hell to see that show-up and mess-up the render.

I think it's because there is a missing piece of code that should calculate for some kind of raycasting to eliminate that light passing through fragments.

Anyway, I don't know the solution, though I tried writing one up in RenderMonkey but got nowhere with it.

Try playing around with NdotL and see if will take you near a soultion.

Also see if you can calculate for the umbra/penumbra and test if the eye is inside them, then return a different lightvalue.
Image
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

Wait, I should've added this one but there is one solution you can use.

Have you heard of specular map? A texture map containing specular values? They should--at least--take you nearer to the solution.

Or....

Try using an environment map, that one you should not miss. It's awesome!
Image
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

Yeah, i know, but i also want normal mapping, so, the reflections may show a good bumping on them. In fact that is a trick i've used tons of times :) And without the proper shader, it doesn't show well.

@BlindSide. Curious, isn't it? but if i didn't set the matrices like that, the model wouldn't move from 0,0,0. I'll try what you put, thanks!
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

I tried the shaders you recomended me BlindSide, and the result is that it works much better than the rendermonkey ones. The only trouble i have now is that it seem like the effect won't move from the origin of the world, no matter what i do, works for positive angles of light, but don't for negatives... I'm not sure of what goes wrong, but i'm sure it has to see with the callback when setting the constants. Any idea to this newbee in shader programation? ^^U Thanks!

Code: Select all

class bumpPhongCNS : public IShaderConstantSetCallBack{
      public:
      virtual void  OnSetConstants (IMaterialRendererServices *services, s32 userData){

              IrrlichtDevice *dev=(IrrlichtDevice *) userData;
              ISceneManager *smgr=dev->getSceneManager();
//Vertex Shader constants.
              matrix4 matViewProjection=dev->getSceneManager()->getActiveCamera()->getProjectionMatrix();
              matViewProjection*=dev->getVideoDriver()->getTransform(ETS_VIEW);
              matViewProjection*=dev->getVideoDriver()->getTransform(ETS_WORLD);
              services->setVertexShaderConstant("matWorldViewProj",&matViewProjection[0],16);
              matrix4 matWorldInverseTranspose=dev->getVideoDriver()->getTransform(ETS_WORLD);
              services->setVertexShaderConstant("matWorld",&matWorldInverseTranspose[0],16);                            
              matWorldInverseTranspose = matWorldInverseTranspose.getTransposed();
              matWorldInverseTranspose.makeInverse();
              services->setVertexShaderConstant("matWorldIT",&matWorldInverseTranspose[0],16);           

              vector3df camPos = dev->getSceneManager()->getActiveCamera()->getPosition();
              services->setVertexShaderConstant("viewPosition",reinterpret_cast<f32*>(&camPos),3);

//pixel Shader constants.

              vector3df lightDir = smgr->getSceneNodeFromName("Uni")->getPosition()-
                                   smgr->getSceneNodeFromName("luz")->getPosition();
              services->setPixelShaderConstant("dirLightDir",reinterpret_cast<f32*>(&lightDir),3);
              vector3df lightColor = vector3df(0.75,.85,1);//color en formato flotante
              services->setPixelShaderConstant("dirLightColor",reinterpret_cast<f32*>(&lightColor),3);

              return;
      }
};

//PixelShader

// Light direction global-level semantic
float3 dirLightDir;
float3 dirLightColor;

struct PS_INPUT {
	float4 position : POSITION0;
	float2 texCoord : TEXCOORD0;
	float3 normal : TEXCOORD1;
	float3 view : TEXCOORD2;
};

sampler2D baseMap;
sampler2D bumpMap;
 
// Pixel Shader Function
float4 ps_main(PS_INPUT IN) : COLOR {
       
	// Normalize all vectors in pixel shader to get phong shading
	// Normalizing in vertex shader would provide gouraud shading

	float3 light = normalize(-dirLightDir);
	float3 view = normalize(IN.view);
	float3 normal = normalize(IN.normal);
    
    normal= normalize(normal + (tex2D( bumpMap, IN.texCoord ).xyz*2.0)-1.0 );
           
	// Calculate the half vector
	float3 halfway = normalize(light + view);

    float2 texCoord = IN.texCoord;
    float4 texColor = tex2D(baseMap, texCoord);

    float3 emissive = 0.5;
 
	// Calculate the ambient reflection
 
    float3 ambient = 0.1*texColor;
 
	// Calculate the diffuse reflection
 
    float3 diffuse = saturate(dot(light,normal)) * texColor.rgb;
 
    float3 specular = pow(saturate(dot(normal, halfway)),25.0) * texColor.rgb;
 
	// Calculate the specular reflection

	float3 color = saturate(ambient + diffuse + specular) * dirLightColor;

	float alpha = 1.0;
	return float4(color, alpha);
}

//VertexShader

float4x4 matWorldViewProj;
float4x3 matWorldIT;
float4x4 matWorld;
float3 viewPosition;

struct VS_INPUT {
	float4 position : POSITION0;
	float3 normal : NORMAL0;
	float2 texCoord : TEXCOORD0;
};
 

struct VS_OUTPUT {
	float4 position : POSITION0;
	float2 texCoord : TEXCOORD0;
	float3 normal : TEXCOORD1;
	float3 view : TEXCOORD2;
};

#define	PS_INPUT VS_OUTPUT
 

VS_OUTPUT vs_main(VS_INPUT IN) {
	VS_OUTPUT OUT;

	OUT.position = mul(IN.position, matWorldViewProj);

	OUT.texCoord = IN.texCoord;

    OUT.normal = mul(matWorldIT, IN.normal);
    
	float3 worldPos = mul(IN.position, matWorld).xyz;
	OUT.view = viewPosition - worldPos;
 
	return OUT;
}
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

First, just pass the absolute position of the light, you don't need to do object - lightPosition (Or whatever you are doing). Second, transform the like position using the inverse world matrix like so:

Code: Select all

vector3df lightPosition = light->getPosition();
matrix4 invWorld;
driver->getTransform(ETS_WORLD).getInverse(invWorld);
invWorld.transformVect(lightPosition); // Or is it transformVec, can't remember off the top of my head.
Then just pass lightPosition as the shader constant. There might be other problems here but you should get this sorted out first.

Cheers

EDIT: No wait a second, you need to pass in the light position, not direction, and then subtract the vertex position (In world space, you get this by passing ETS_WORLD then multiplying with the stock vertex position), then normalize that vector to get the light direction. Check out the phong shader in XEffects, I admit it's messy (Since I nabbed it off the NVidia shader library aaages ago), but it should be a good reference point to learn from.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

I'll try it then :) A question you may know, or may not... but i'm curious. Why are needed the binormal vectors and the Tangent vectors for normal mapping? takin in consideration normal maps, those, besides the normals are the only needed to achieve the lighting effect, right?
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

From what I read, the space needs to shift to tangent space, which means a matrix is needed, though not all of them use tangent matrix.
Image
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

I wish i knew... very good news!

Image

Not only i have ended a good looking phong shader, also, i've added it fresnel reflections! ^^

After taking a peek to blindside's shaders, i found some very interesting information, and a trick i didn't know. x and y components of a normal vector could be used to place a non cube reflection map in the model ;) His phong shader was... all messed up. But i took the reflection idea from what he had done. Also, took his variable settings, assuming they were written right, and modified them a bit to rewrite the shader i tried last time. And that is the result! :)

I will leave this here for the people who wants to see how it works, source and shaders included.

http://rapidshare.com/files/165674054/S ... resnel.rar

Thank you very much for your great help! :)
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

His phong shader was... all messed up.
Yeah I got it a few years ago from the NVidia shader library and didn't bother cleaning it up. The screenshot looks nice.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

Thanks! Maybe it doesn't have a BumpMap, but it would work really nice for a car paint, perhaps, it could be modified so it interpolated with the normal 2 colours, and then, use it to create more effects. or perhaps, translucency, fake SSS effects.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
jiedi123
Posts: 6
Joined: Thu Dec 16, 2010 9:08 am

Post by jiedi123 »

Mel wrote:I wish i knew... very good news!

Image

Not only i have ended a good looking phong shader, also, i've added it fresnel reflections! ^^

After taking a peek to blindside's shaders, i found some very interesting information, and a trick i didn't know. x and y components of a normal vector could be used to place a non cube reflection map in the model ;) His phong shader was... all messed up. But i took the reflection idea from what he had done. Also, took his variable settings, assuming they were written right, and modified them a bit to rewrite the shader i tried last time. And that is the result! :)

I will leave this here for the people who wants to see how it works, source and shaders included.

http://rapidshare.com/files/165674054/S ... resnel.rar

Thank you very much for your great help! :)

Its cant download; (File not found.)
can you send to me
my email is xiacaojun@gmail.com
thanks
Post Reply