Page 1 of 2

Relief Mapping

Posted: Fri Sep 20, 2013 11:15 am
by Samuel
#####
EDIT: I made some more changes to this shader. You can now control the depth in real time instead of having to edit it in the material script.
#####

I came across this example while looking for some info on parallax occlusion mapping. In my opinion a POM shader is better, but this one is pretty good too.
I thought it would be a good idea to post it anyways. Just in case somebody might have a use for it.

This requires NVIDIA's Cg-toolkit to be installed on your computer. Here's the link to the toolkit information.
https://developer.nvidia.com/cg-toolkit
The download link is at the bottom of that page.
If you intend to release your apps with this shader. Make sure you include the cg.dll with your app.

A few things about the shader.
It was originally a free example from NVIDIA. Someone from the OGRE site ported it over to cg. I forgot the OGRE link, but I'll post it as soon as I find it.
I did make some small changes on it. It was originally set up for one material. I changed it so you can have multiple materials in the same script.
You can use this for whatever purpose you want. There are no copyright restrictions that I'm aware of.

It's main purpose is to give a 2D texture more depth. Which gives a more realistic appearance.
It supports diffuse,specular, and ambient lighting.
It has shadow support for the texture itself. Which gives it a better depth feeling.

A warning.
This shader along with any shader of this caliber requires quite a bit of power.
It's something that you will have to experiment with to find the proper balance for your app.
Use it too much and your FPS will surely drop. Unless you have a beast of a graphics card.


Now then here's a picture showing it in action.
Image

These next two pictures are the required materials for the shader. One is the texture you want your entity to use.
The other is the Normal Height Map. Which is used for the calculations.
Save them exactly as stated. Otherwise the shader won't be able to find them.
Also don't forget where you save them. You will need to set the path later on in the PB code.

DiffuseMap.png
Image

You will need to load this next one in a program that supports alpha. I personally prefer using GIMP, but Photoshop will work too.
Make sure this one is saved as a png because jpg doesn't support alpha.

EDIT: I changed this Normal Height Image to a different one.
The original had a defect. So, it would show a little gray splotch in the center of each square.
This end result may look slightly different from the original because I smoothed the map a little, but it's better in my opinion.
NormalHeight.png
Image

The GIMP has a nice normal map filter that you can download, but I forgot where the link was. I'll post the link as soon as I find it.
EDIT: Bananenfreak found this link to a NormalMap Plugin for GIMP
http://code.google.com/p/gimp-normalmap/


Now the code.
There are 3 files and the PB code itself. The three files are the cg, material, and program.
Same as the pictures above. Make sure they are saved exactly as stated extension and all.
I mainly use notepad, but use whatever works for you.

First the cg file.
relief_map.CG

Code: Select all

/*********************************************************************NVMH3****
*******************************************************************************
$Revision: #4 $

Copyright NVIDIA Corporation 2008
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS
BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES
WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY
LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

% This material shows and compares results from four popular and
% advanced schemes for emulating displaement mapping.  They are:
% Relief Mapping, Parallax Mapping, Normal Mapping, and Relief
% Mapping with Shadows.  Original File by Fabio Policarpo.

keywords: material bumpmap
date: 071005

Note: Strong discontinuties in the model geometric normal (e.g., very sharp
    differences from the normals in two or more parts of the same triangle)
    can cause unusual overall light-attentuation errors. Re-normalizing the
    rasterized normals in the fragment shader can correct this, but the case
    was considered rare enough that these extra steps were eliminated for
    code efficiency. If you see off lighting near sharp model edges, just
    normalize "IN.normal" in the calculation of the varible "att" (shared
    by all techniques).



To learn more about shading, shaders, and to bounce ideas off other shader
    authors and users, visit the NVIDIA Shader Library Forums at:

    http://developer.nvidia.com/forums/

*******************************************************************************
******************************************************************************/

// Modified for OGRE by mkultra333, 090529
// Got rid of BINORMAL input, now computed in vertex program.
// Changed "- tNorm.y*IN.binormal" to "+ tNorm.y*IN.binormal" in fragment program.
// Removed WorldITXf, WorldXf and ViewIXf 4x4 matrixes that weren't used.


/********** CONNECTOR STRUCTURES *****************/

struct AppVertexData {
    float4 pos      : POSITION;
    float4 color   : COLOR0;
    float3 normal   : NORMAL; // expected to be normalized
    float2 txcoord   : TEXCOORD0;
    float3 tangent   : TANGENT0; // pre-normalized
};

struct VertexOutput {
    float4 hpos      : POSITION;
    float2 UV      : TEXCOORD0;
    float3 vpos      : TEXCOORD1;
    float3 tangent   : TEXCOORD2;
    float3 binormal   : TEXCOORD3;
    float3 normal   : TEXCOORD4;
    float4 lightpos   : TEXCOORD5;
    float4 color   : COLOR0;
};

/*** SHADER FUNCTIONS **********************************************/

VertexOutput view_spaceVS(AppVertexData IN,
   uniform float4x4 WvpXf,
    uniform float4x4 ViewXf,
    uniform float4x4 WorldViewXf,
    uniform float TileCount,
    uniform float3 LampPos
) {
    VertexOutput OUT = (VertexOutput)0;
    // isolate WorldViewXf rotation-only part
    

    float3x3 modelViewRotXf;
    modelViewRotXf[0] = WorldViewXf[0].xyz;
    modelViewRotXf[1] = WorldViewXf[1].xyz;
    modelViewRotXf[2] = WorldViewXf[2].xyz;
    
    float4 Po = float4(IN.pos.xyz,1.0);
    OUT.hpos = mul(WvpXf,Po);
    
    // vertex position in view space (with model transformations)
    OUT.vpos = mul(WorldViewXf,Po).xyz;
    
    // light position in view space
    float4 Lw = float4(LampPos.xyz,1); // this point in world space
    OUT.lightpos = mul(ViewXf,Lw); // this point in view space
    
   // Calculate the binormal (NB we assume both normal and tangent are
   // already normalised)
   // NB looks like nvidia cross params are BACKWARDS to what you'd expect
   // this equates to NxT, not TxN
   float3 binormal = cross(IN.tangent, IN.normal);

    // tangent space vectors in view space (with model transformations)
    OUT.tangent = mul(modelViewRotXf,IN.tangent);
    OUT.binormal = mul(modelViewRotXf,binormal);
    OUT.normal = mul(modelViewRotXf,IN.normal);
    
    // copy color and texture coordinates
    OUT.color = IN.color; // currently ignored by all techniques
    OUT.UV = TileCount * IN.txcoord.xy;
    
    return OUT;
}

//// ray-intersect functions for relief mapping //////////

float ray_intersect_rm(         // use linear and binary search
      in sampler2D reliefmap,
      in float2 dp, 
      in float2 ds)
{
   const int linear_search_steps=40;
   
   // current size of search window
   float size = 1.0/linear_search_steps;
   // current depth position
   float depth = 0.0;
   // search front to back for first point inside object
   for( int i=0;i<linear_search_steps-1;i++ ) {
   float4 t = tex2D(reliefmap,dp+ds*depth);
   if (depth<t.w)
       depth += size;
   }
   const int binary_search_steps=5;
   // recurse around first point (depth) for closest match
   for( int ii=0;ii<binary_search_steps;ii++ ) {
   size*=0.5;
   float4 t = tex2D(reliefmap,dp+ds*depth);
   if (depth<t.w)
       depth += (2*size);
   depth -= size;
   }
   return depth;
}

float ray_intersect_rm_lin(   // only linear search for shadows
      in sampler2D reliefmap,
      in float2 dp, 
      in float2 ds)
{
   const int linear_search_steps=40;
   // current size of search window
   float size = 1.0/linear_search_steps;
   // current depth position
   float depth = 0.0;
   // search front to back for first point inside object
   for( int i=0;i<linear_search_steps-1;i++ ) {
   float4 t = tex2D(reliefmap,dp+ds*depth);
   if (depth<t.w)
       depth += size;
   }
   return depth;
}

float4 relief_mapPS(VertexOutput IN,
          uniform float Depth,
          uniform float3 SurfaceColor,
          uniform sampler2D ColorSampler : register(s1),
          uniform sampler2D ReliefSampler : register(s0),
          uniform float PhongExp,
          uniform float3 SpecColor,
          uniform float3 AmbiColor
) : COLOR
{
    // ray intersect in view direction
    float3 p = IN.vpos;
    float3 Vn = normalize(p);
    float a = dot(IN.normal,-Vn);
    float3 s  = float3(dot(Vn,IN.tangent.xyz), dot(Vn,IN.binormal.xyz), a);
    s  *= Depth/a;
    float2 ds = s.xy;
    float2 dp = IN.UV;
    float d  = ray_intersect_rm(ReliefSampler,dp,ds);
    // get rm and color texture points
    float2 uv = dp+ds*d;
    float3 texCol = tex2D(ColorSampler,uv).xyz;
    float3 tNorm = tex2D(ReliefSampler,uv).xyz - float3(0.5,0.5,0.5);
    tNorm = normalize(tNorm.x*IN.tangent +
        tNorm.y*IN.binormal + 
        tNorm.z*IN.normal);
    // compute light direction
    p += Vn*d/(a*Depth);
    float3 Ln = normalize(p-IN.lightpos.xyz);
    // compute diffuse and specular terms
    float att = saturate(dot(-Ln,IN.normal));
    float diff = saturate(dot(-Ln,tNorm));
    float spec = saturate(dot(normalize(-Ln-Vn),tNorm));
    spec = pow(spec,PhongExp);
    // compute final color
    float3 finalcolor = AmbiColor*texCol + 
       att*(texCol*SurfaceColor*diff+SpecColor*spec);
    return float4(finalcolor.rgb,1.0);
}

float4 relief_map_shadowsPS(VertexOutput IN,
             uniform float Depth,
             uniform float3 SurfaceColor,
             uniform sampler2D ColorSampler : register(s1),
               uniform sampler2D ReliefSampler : register(s0),
             uniform float PhongExp,
             uniform float3 SpecColor,
             uniform float3 AmbiColor
) : COLOR
{
    // ray intersect in view direction
    float3 p = IN.vpos;
    float3 Vn = normalize(p);
    float a = dot(IN.normal,-Vn);
    float3 s = float3(dot(Vn,IN.tangent.xyz), dot(Vn,IN.binormal.xyz), a);
    s  *= Depth/a;
    float2 ds = s.xy;
    float2 dp = IN.UV;
    float d  = ray_intersect_rm(ReliefSampler,dp,ds);
    // get rm and color texture points
    float2 uv = dp+ds*d;
    float3 texCol = tex2D(ColorSampler,uv).xyz;
    float3 tNorm = tex2D(ReliefSampler,uv).xyz - float3(0.5,0.5,0.5);
    tNorm = normalize(tNorm.x*IN.tangent +
          tNorm.y*IN.binormal + 
          tNorm.z*IN.normal);
    // compute light direction
    p += Vn*d/(a*Depth);
    float3 Ln = normalize(p-IN.lightpos.xyz);
    // compute diffuse and specular terms
    float att = saturate(dot(-Ln,IN.normal));
    float diff = saturate(dot(-Ln,tNorm));
    float spec = saturate(dot(normalize(-Ln-Vn),tNorm));
    // ray intersect in light direction
    dp+= ds*d;
    a  = dot(IN.normal,-Ln);
    s  = float3(dot(Ln,IN.tangent.xyz),dot(Ln,IN.binormal.xyz),a);
    s *= Depth/a;
    ds = s.xy;
    dp -= ds*d;
    float dl = ray_intersect_rm_lin(ReliefSampler,dp,s.xy);
    if (dl<d-0.05) {      // if pixel in shadow
      diff *= dot(AmbiColor.xyz,float3(1.0,1.0,1.0))*0.333333;
      spec = 0;
    }
    spec = pow(spec,PhongExp);
    // compute final color
    float3 finalcolor = AmbiColor*texCol + 
       att*(texCol*SurfaceColor*diff+SpecColor*spec);
    return float4(finalcolor.rgb,1.0);
}
Now the material script.
relief_map.MATERIAL

Code: Select all

abstract material ReliefTemplate
{
   technique
   {      
      pass
      {
         vertex_program_ref view_spaceVS
         {
                  param_named_auto   WvpXf               worldviewproj_matrix
                  param_named_auto   ViewXf            view_matrix
                  param_named_auto   WorldViewXf      worldview_matrix
                  param_named            TileCount         float $Tile
                  param_named_auto   LampPos            light_position 0



         }
         fragment_program_ref relief_map_shadowsPS
         {
                  //param_named            Depth               float $Depth ####This is now commented out because the depth has custom control####
                  param_named_auto Depth custom 1
                  param_named_auto   SurfaceColor   light_diffuse_colour 0
                  param_named            PhongExp         float $PhongExp
                  param_named_auto   SpecColor         light_specular_colour 0
                  param_named_auto   AmbiColor         ambient_light_colour 0
         }

        texture_unit NormalMap
        {
           texture $NormalHeight_map
               filtering anisotropic
               max_anisotropy 1
        }

         texture_unit DiffuseMap
        {
            texture $Texture_Map
                filtering anisotropic
                max_anisotropy 1
         }
      }
   }
}
material MaterialOne : ReliefTemplate
{
   set $Tile 1
   //set $Depth 0.09 ####This is now commented out because the depth has custom control####
   set $PhongExp 64.0
   set $Texture_Map DiffuseMap.png
   set $NormalHeight_map NormalHeight.png
}
OK the bottom part of the material script is the part you edit for your own textures. For my example you can leave it as it is.
I'll tell you what each one means for future reference.

Do not use this code because it will not run. It's just for an example.

Code: Select all

material MaterialOne : ReliefTemplate             #### MaterialOne is the name of your material that you will call in PB. ReliefTemplate is the template for your 
                                              #### material. So in other words it takes your variables that you will set below and uses them in the template material 
                                              #### above.
{
   set $Tile 1                                             #### $Tile is how many times the texture is repeated. So, if you set it to 2 it will display your texture twice, but 
                                                          #### they will be half the size.

   set $Depth 0.05                                      #### $Depth is for how much depth you want. The better the Normal Height map the better the depth quality.

   set $PhongExp 64.0                                 #### $PhongExp adjusts your light. The greater the number the smaller the light.

   set $Texture_Map DiffuseMap.png              #### $Texture_Map is your texture variable. Set DiffuseMap.png to whatever your texture is named.

   set $NormalHeight_map NormalHeight.png    #### $NormalHeight_map is your Normal Height variable. Set NormalHeight.png to whatever your Normal Height 
                                                     #### Map is named.
}
Now the Program File.
relief_map.PROGRAM

Code: Select all

vertex_program view_spaceVS cg         
{
   source relief_map.cg
   entry_point view_spaceVS
   profiles arbvp1 vs_3_0 vp40
}

fragment_program relief_mapPS cg         
{
   source relief_map.cg   
   entry_point relief_mapPS
   profiles ps_3_0 arbfp1 fp40
}

fragment_program relief_map_shadowsPS cg         
{
   source relief_map.cg   
   entry_point relief_map_shadowsPS
   profiles ps_3_0 arbfp1 fp40
}
If you've made it this far then your either really bored or your weird like me and this stuff actually interests you. :D

All that's left is setting up the code to run this.
Don't forget to set the paths to the files and pictures.

Code: Select all

UsePNGImageDecoder()
UsePNGImageEncoder()

;####You must Enable CG When Using A CG Shader.####
InitEngine3D(#PB_Engine3D_EnableCG | #PB_Engine3D_DebugLog)
InitSprite()
InitKeyboard()
InitMouse()

;#### (#Depth) Handle Must Equal 1 Because That is What It Was Set To In Script.####
Enumeration 1
  #Depth
  #MainWindow
  #FPS
  #Instructions
  #Font
  #Font2
  #Sphere
  #Camera
  #Light
  #ReliefMat
  #TextureMat
EndEnumeration

Define.f MouseX,MouseY

ExamineDesktops()
DesktopW=DesktopWidth(0)
DesktopH=DesktopHeight(0)

If LoadFont(#Font, "", 10,#PB_Font_Bold)
 SetGadgetFont(#PB_Default, FontID(#Font))
EndIf
If LoadFont(#Font2, "", 14,#PB_Font_Bold)
 SetGadgetFont(#PB_Default, FontID(#Font2))
EndIf
    
If OpenWindow(#MainWindow, 0, 0, DesktopW, DesktopH, "Relief Mapping")
  ;AntialiasingMode(#PB_AntialiasingMode_x6)
  If OpenWindowedScreen(WindowID(#MainWindow), 0, 0, DesktopW, DesktopH, 0, 0, 0)
    
    ;####You'll Have To Comment CPUName() Out If Your Using A Version Previous To 5.2####
    CPU$ = CPUName()
    
    ;####Set Path To Where You Saved The Textures###################################
    Add3DArchive("C:\Users\Bill\Music\Pictures\3D\", #PB_3DArchive_FileSystem)
    ;################################################################################################
    
    ;####Set Path To Where You Saved The CG and Material Files#############################################
    Add3DArchive("C:\Users\Bill\Documents\Purebasic\PurebasicScripts\Relief Mapping",#PB_3DArchive_FileSystem)
    ;################################################################################################
    
    ;####Checking Archives For Material Script####
    Parse3DScripts()
    
    ;####Load The Relief Map Material####
    GetScriptMaterial(#ReliefMat,"MaterialOne")
    
    ;####Create Sprites For Help and Information####
    CreateSprite(#FPS, 350, 210)
    StartDrawing(SpriteOutput(#FPS))
      Box(0,0,400,120,RGB(40,40,40))
    StopDrawing()
    CreateSprite(#Instructions, 350, 260)
    StartDrawing(SpriteOutput(#Instructions))
       Box(0,0,350,260,RGB(40,40,40))
       DrawingFont(FontID(#Font2)) 
       DrawText(2,12,"Press H to Hide/Show Help.",RGB(255,255,255),RGB(40,40,40))
       DrawText(2,42,"Press Arrow Keys To Rotate Entity.",RGB(255,255,255),RGB(40,40,40))
       DrawText(2,72,"Press W To View WireFrame.",RGB(255,255,255),RGB(40,40,40))
       DrawText(2,102,"Press E To View Texture.",RGB(255,255,255),RGB(40,40,40))
       DrawText(2,132,"Press S To Turn Relief Mapping Off.",RGB(255,255,255),RGB(40,40,40))
       DrawText(2,162,"Press D To Turn Relief Mapping On.",RGB(255,255,255),RGB(40,40,40))
       DrawText(2,192,"Press X To Add More Depth.",RGB(255,255,255),RGB(40,40,40))
       DrawText(2,222,"Press C To Subtract Depth.",RGB(255,255,255),RGB(40,40,40))
     StopDrawing()
     
    ;####Load Plain Texture####
    LoadTexture(#TextureMat,"DiffuseMap.png")
    CreateMaterial(#TextureMat,TextureID(#TextureMat))
    SetMaterialColor(#TextureMat, #PB_Material_SpecularColor, RGB(255,255,255))
    MaterialShininess(#TextureMat,64)
    
    ;####Create Mesh And Entity####
    CreateSphere(#Sphere,6,32,32)
    ;CreateCube(#Sphere,12)
    BuildMeshTangents(#Sphere)
    CreateEntity(#Sphere, MeshID(#Sphere), MaterialID(#ReliefMat),0,0,0)
    
    ;####Create Camera And Lights####
    CreateCamera(#Camera, 0,0,100,100)
    MoveCamera(#Camera, 0, 0, 30)
    CameraLookAt(#Camera, 0, 0, 0)
    CameraBackColor(#Camera, RGB(250, 150, 50))
    
    CreateLight(#Light, RGB(50,0,0), 0,5,10);,#PB_Light_Directional)
    SetLightColor(#Light, #PB_Light_DiffuseColor, RGB(250,250,250))
    SetLightColor(#Light, #PB_Light_SpecularColor, RGB(255,255,255))
    LightLookAt(#Light, 0, 0, 0)
    
    ;####Ambient Lighting Does Work. Uncomment It If You Would Like To Give It A Try.####
    ;AmbientColor(RGB(100,100,100))
    
    ;####Set The Depth For the Sphere Entity. Leave The Last 3 Parameters At Zero.####
    Depth.f= 0.04
    EntityCustomParameter(#Sphere,0,#Depth,Depth,0,0,0)

Repeat
  
  ;####Examine Keyboard Input####
     If ExamineKeyboard()
        If KeyboardPushed(#PB_Key_Up)
          RotateEntity(#Sphere,-0.3,0,0,#PB_Relative)
        ElseIf KeyboardPushed(#PB_Key_Down)
          RotateEntity(#Sphere,0.3,0,0,#PB_Relative)
       EndIf
       If KeyboardPushed(#PB_Key_Left)
          RotateEntity(#Sphere,0,-0.3,0,#PB_Relative)
       ElseIf KeyboardPushed(#PB_Key_Right)
          RotateEntity(#Sphere,0,0.3,0,#PB_Relative)
       EndIf
       If KeyboardReleased(#PB_Key_W)
          CameraRenderMode(#Camera, #PB_Camera_Wireframe)
       ElseIf KeyboardReleased(#PB_Key_E)
          CameraRenderMode(#Camera, #PB_Camera_Textured)
       ElseIf KeyboardReleased(#PB_Key_S)
          SetEntityMaterial(#Sphere, MaterialID(#TextureMat))
       ElseIf KeyboardReleased(#PB_Key_D)
          SetEntityMaterial(#Sphere, MaterialID(#ReliefMat))
       ElseIf KeyboardReleased(#PB_Key_H)
         ShowHelp=ShowHelp+1
         If ShowHelp>1
           ShowHelp=0
         EndIf
       EndIf
       
       If KeyboardPushed(#PB_Key_X)
          Depth=Depth+0.001
          If Depth>0.125
            Depth=0.125
          EndIf
          EntityCustomParameter(#Sphere,0,#Depth,Depth,0,0,0)
       ElseIf KeyboardPushed(#PB_Key_C)
          Depth=Depth-0.001
          If Depth<0.01
            Depth=0.01
          EndIf
          EntityCustomParameter(#Sphere,0,#Depth,Depth,0,0,0)
       EndIf
     EndIf

   RenderWorld()
     
   ;####Now That The 3D Has Been Rendered. Display The Sprites.####
     ShowFPS=1
      If ShowFPS=1
        CurrentFPS = Engine3DFrameRate(#PB_Engine3D_Current)
        AverageFPS = Engine3DFrameRate(#PB_Engine3D_Average)
        MaximumFPS = Engine3DFrameRate(#PB_Engine3D_Maximum)
        MinimumFPS = Engine3DFrameRate(#PB_Engine3D_Minimum)
        CountTris=CountRenderedTriangles()
        StartDrawing(SpriteOutput(#FPS))
          Box(0,0,280,120,RGB(40,40,40))
          DrawingFont(FontID(#Font)) 
          DrawText(2,2,CPU$,RGB(255,0,0),RGB(40,40,40))
          DrawText(2,22,"Current FPS : "+Str(CurrentFPS),RGB(0,255,255),RGB(40,40,40))
          DrawText(2,42,"Average FPS : "+Str(AverageFPS),RGB(0,255,255),RGB(40,40,40))
          DrawText(2,62,"Maximum FPS : "+Str(MaximumFPS),RGB(0,255,255),RGB(40,40,40))
          DrawText(2,82,"Minimum FPS : "+Str(MinimumFPS),RGB(0,255,255),RGB(40,40,40))
          DrawText(2,102,"Rendered Triangles : "+Str(CountTris),RGB(0,255,0),RGB(40,40,40))
        StopDrawing()
        DisplayTransparentSprite(#FPS,20,20)
        If ShowHelp=0
          DisplayTransparentSprite(#Instructions,20,150)
        EndIf
        If FirstFrame=0
          Engine3DFrameRate(#PB_Engine3D_Reset)
          FirstFrame=1
        EndIf
      EndIf
    FlipBuffers()

    Until WindowEvent() = #PB_Event_CloseWindow Or KeyboardPushed(#PB_Key_Escape)
    
  EndIf
EndIf
End
I've been working on this post for over a hour and it's officially 3:15 AM.
So, if I made a mistake in setting this up. My excuse is the lack of sleep.
If you do have problems running this. Let me know and I'll see what I can do for ya. After I get my 4 hours of sleep that is. Then I'll be wide awake. :shock:

Re: Relief Mapping

Posted: Fri Sep 20, 2013 4:19 pm
by IdeasVacuum
Brilliant stuff, thanks for sharing :mrgreen:

Re: Relief Mapping

Posted: Fri Sep 20, 2013 5:29 pm
by applePi
Samuel, this is a great demo , thanks. i know nothing yet about shaders, i feel scary when someone said the word shader.
my card is Geforce 210 and it display the sphere like this:
Image
it has no sharp spikes as your picture.

Re: Relief Mapping

Posted: Fri Sep 20, 2013 6:17 pm
by Comtois
Work fine here, nice job.

Re: Relief Mapping

Posted: Fri Sep 20, 2013 7:05 pm
by Samuel
applePi wrote:Samuel, this is a great demo , thanks. i know nothing yet about shaders, i feel scary when someone said the word shader.
my card is Geforce 210 and it display the sphere like this:
it has no sharp spikes as your picture.
Your card should be able to run this.

First I'd check the paths,files,and images to make sure they are all named and set correctly.

Then I'd check the NormalHeight.png. It's supposed to have alpha in the center of each square.
If it's white in the center then you somehow lost the alpha when copying.

Do you get the same result when turning the Relief Mapping on and off? Does it have a white or black texture when you turn the Relief Mapping on?

Have you tried OpenGL and DirectX?

What does your ogre.log say? Are there any noticeable errors in it?

I'm sure it's something small that's causing it not to work. Just let me know what you find I'll see if I can help you.

Re: Relief Mapping

Posted: Fri Sep 20, 2013 8:11 pm
by Samuel
I just realized that I forgot to include Tangent calculations.
I updated the PB code above.

Here is the command for future reference. Just add it after you create your mesh.
BuildMeshTangents(#Mesh)

The only reason this worked before was because it was a sphere. If it was a cube it would have failed.
I don't think this was causing your problem ApplePI, but it might have.

EDIT: Tangents are a new feature to PureBasic 5.2.
So, if your using an older version you'll have to update. That or give your mesh tangents through the OgreXmlConverter, but that's very time consuming.
I recommend updating if you haven't already.

Re: Relief Mapping

Posted: Fri Sep 20, 2013 9:07 pm
by applePi
thanks Samuel, here is the ogre log text file http://www.mediafire.com/?c653fto2pp7be87
the last lines is: material MaterialOne has no supportable Techniques and will be blank. Explanation:
Pass 0: Vertex program view_spaceVS cannot be used - compile error


so it may be the card does not support all features.

the same shape in dx or opengl
when turn the Relief Mapping on it has a white texture like this
Image

the file NormalHeight.png is black at the center of each square when we open it in irfanview
i use purebasic v5.20
PS: the same shape after the updated code above

Re: Relief Mapping

Posted: Fri Sep 20, 2013 10:52 pm
by PMV
@Samuel
I just realized that I forgot to include Tangent calculations.
That took me hours :x ... but i would not blame you for that ...
i'm just glad that i have got it to work with my own meshes now. :lol:
And of course many thanks for your work!

Btw. i have seen, that your way is not clean. You have to make
a "abstract technique" to inherit from. As now, you will get
error lines in the log-file, because the used variables are in a
normal material, that is computed, even so it is not directly used :)
And better put the shader-definition into a separate file with
ending *.program as there they can be used in all material-files.
OGRE will load the *.program files at once, so it is guaranteed
that they are available if referenced by a material-script :wink:


@applePi
Supported Shader Profiles: arbfp1 arbvp1 fp20 fp30 fp40 glsl gp4fp gp4gp gp4vp gpu_fp gpu_gp gpu_vp nvgp4 vp30 vp40
No support for the used DX9 shader (vs_3_0 and ps_3_0), but
it seems the used OpenGL shader are supported. So OpenGL should
work. Be sure to enter "OpenGL" into Subsystem and check your
OGRE.log to be sure, it really uses OpenGL. If it still doesn't work,
strange, but it is your card for sure :)

MFG PMV

Re: Relief Mapping

Posted: Fri Sep 20, 2013 11:24 pm
by Samuel
PMV wrote: That took me hours :x ... but i would not blame you for that ...
My apologies. I was really tired when I put everything together. So, I wasn't thinking clearly.
I changed the material to abstract and added the program file like you said. That should take care of the errors.

@applePi

As PMV said it's most likely the profiles are not set right for your card. I added a few profiles just to see if you can get it working right.
Hopefully that will fix the issue, but it's hard for me to test because I only have an ATI card.

Don't forget the new program file too.

Also you mentioned the Normal Height map being black instead of transparent.
This will cause the depth to not work properly. You should still be able to see the texture while the relief mapping is on though.

Re: Relief Mapping

Posted: Sat Sep 21, 2013 9:21 am
by Bananenfreak

Re: Relief Mapping

Posted: Sat Sep 21, 2013 9:43 am
by Samuel
Thanks for the link Bananenfreak. I believe that's the same one I have.
You may already know this, but a normal map alone isn't enough. If that's the same filter as mine then there should be an alpha channel option.
Set it to inverse height to create a Normal Height Map.

Re: Relief Mapping

Posted: Sat Sep 21, 2013 11:48 am
by Bananenfreak
Hey Samuel,

I tried your example: Very impressive! :shock:
After playing with this thorny ball, i decided to Import that to my Project.
Poorly, my program now stop working by loading the .program-File.

Code: Select all

12:22:22: Creating resource group General
12:22:22: Creating resource group Internal
12:22:22: Creating resource group Autodetect
12:22:22: SceneManagerFactory for type 'DefaultSceneManager' registered.
12:22:22: Registering ResourceManager for type Material
12:22:22: Registering ResourceManager for type Mesh
12:22:22: Registering ResourceManager for type Skeleton
12:22:22: MovableObjectFactory for type 'ParticleSystem' registered.
12:22:22: OverlayElementFactory for type Panel registered.
12:22:22: OverlayElementFactory for type BorderPanel registered.
12:22:22: OverlayElementFactory for type TextArea registered.
12:22:22: Registering ResourceManager for type Font
12:22:22: ArchiveFactory for archive type FileSystem registered.
12:22:22: ArchiveFactory for archive type Zip registered.
12:22:22: ArchiveFactory for archive type EmbeddedZip registered.
12:22:22: DDS codec registering
12:22:22: FreeImage version: 3.10.0
12:22:22: This program uses FreeImage, a free, open source image library supporting all common bitmap formats. See http://freeimage.sourceforge.net for details
12:22:22: Supported formats: bmp,ico,jpg,jif,jpeg,jpe,koa,iff,lbm,pbm,pbm,pcd,pcx,pgm,pgm,png,ppm,ppm,ras,tga,targa,tif,tiff,wap,wbmp,wbm,psd,cut,xbm,xpm,dds,gif,g3,sgi,j2k,j2c,jp2
12:22:22: PVRTC codec registering
12:22:22: Registering ResourceManager for type HighLevelGpuProgram
12:22:22: Registering ResourceManager for type Compositor
12:22:22: MovableObjectFactory for type 'Entity' registered.
12:22:22: MovableObjectFactory for type 'Light' registered.
12:22:22: MovableObjectFactory for type 'BillboardSet' registered.
12:22:22: MovableObjectFactory for type 'ManualObject' registered.
12:22:22: MovableObjectFactory for type 'BillboardChain' registered.
12:22:22: MovableObjectFactory for type 'RibbonTrail' registered.
12:22:22: *-*-* OGRE Initialising
12:22:22: *-*-* Version 1.8.2 (Byatis)
12:22:22: D3D9 : Direct3D9 Rendering Subsystem created.
12:22:22: D3D9: Driver Detection Starts
12:22:22: D3D9: Driver Detection Ends
12:22:22: OpenGL Rendering Subsystem created.
12:22:22: Particle Emitter Type 'Point' registered
12:22:22: Particle Emitter Type 'Box' registered
12:22:22: Particle Emitter Type 'Ellipsoid' registered
12:22:22: Particle Emitter Type 'Cylinder' registered
12:22:22: Particle Emitter Type 'Ring' registered
12:22:22: Particle Emitter Type 'HollowEllipsoid' registered
12:22:22: Particle Affector Type 'LinearForce' registered
12:22:22: Particle Affector Type 'ColourFader' registered
12:22:22: Particle Affector Type 'ColourFader2' registered
12:22:22: Particle Affector Type 'ColourImage' registered
12:22:22: Particle Affector Type 'ColourInterpolator' registered
12:22:22: Particle Affector Type 'Scaler' registered
12:22:22: Particle Affector Type 'Rotator' registered
12:22:22: Particle Affector Type 'DirectionRandomiser' registered
12:22:22: Particle Affector Type 'DeflectorPlane' registered
12:22:22: PCZone Factory Type 'ZoneType_Default' registered
12:22:22: CPU Identifier & Features
12:22:22: -------------------------
12:22:22:  *   CPU ID: AuthenticAMD: AMD Phenom(tm) II X4 B55 Processor
12:22:22:  *      SSE: yes
12:22:22:  *     SSE2: yes
12:22:22:  *     SSE3: yes
12:22:22:  *      MMX: yes
12:22:22:  *   MMXEXT: yes
12:22:22:  *    3DNOW: yes
12:22:22:  * 3DNOWEXT: yes
12:22:22:  *     CMOV: yes
12:22:22:  *      TSC: yes
12:22:22:  *      FPU: yes
12:22:22:  *      PRO: yes
12:22:22:  *       HT: no
12:22:22: -------------------------
12:22:22: D3D9 : Subsystem Initialising
12:22:22: Registering ResourceManager for type Texture
12:22:22: Registering ResourceManager for type GpuProgram
12:22:22: ***************************************
12:22:22: *** D3D9 : Subsystem Initialised OK ***
12:22:22: ***************************************
12:22:22: SceneManagerFactory for type 'OctreeSceneManager' registered.
12:22:22: SceneManagerFactory for type 'BspSceneManager' registered.
12:22:22: Registering ResourceManager for type BspLevel
12:22:22: Added resource location './../Data/Texturen' of type 'FileSystem' to resource group 'General'
12:22:22: Added resource location './../Data/Texturen/Terrain' of type 'FileSystem' to resource group 'General'
12:22:22: Added resource location './../Data/Materialien' of type 'FileSystem' to resource group 'General'
12:22:22: Added resource location './../Data/Objekte/Gebaeude' of type 'FileSystem' to resource group 'General'
12:22:22: Added resource location './../Data/Objekte/Pflanzen' of type 'FileSystem' to resource group 'General'
12:22:22: Added resource location './../Data/Objekte/Pflanzen/Baeume/Linde_0/4' of type 'FileSystem' to resource group 'General'
12:22:22: Added resource location './../Data/Objekte/Sonstiges' of type 'FileSystem' to resource group 'General'
12:22:22: Added resource location './../Data/Programme' of type 'FileSystem' to resource group 'General'
12:22:22: Parsing scripts for resource group Autodetect
12:22:22: Finished parsing scripts for resource group Autodetect
12:22:22: Creating resources for group Autodetect
12:22:22: All done
12:22:22: Parsing scripts for resource group General
12:22:22: Parsing script relief_map.program
It´s the same program like in your example... I edited nothing in this file (Except in relief_map.material... I extruded it to another file with another Name).

EDIT: Still with same .materialfile from your example my program / OGRE stops working with "parsing script".

Re: Relief Mapping

Posted: Sat Sep 21, 2013 3:20 pm
by PMV
If ParseScripts() stops working, then you have an error in one of your scripts. :)
I had a IMA yesterday on ParseScripts() because of an not closing } :lol:

And don't forgett InitEngine3D(#PB_Engine3D_EnableCG | #PB_Engine3D_DebugLog)
as that i had forgotten, too :oops:

MFG PMV

Re: Relief Mapping

Posted: Sat Sep 21, 2013 4:39 pm
by Bananenfreak
Thanks, PMV.

My Problem is solved. You have to call ParseScripts() after (!) you have opened a Screen or WindowedScreen. Before all is working correct except .program files.
(Is this a bug or something similar? It isn´t described in the documentation...)

EDIT:
Could someone tell me what this is?:
Image

I use directional light and yeah, that´s the difference to the example.

Re: Relief Mapping

Posted: Sat Sep 21, 2013 8:28 pm
by Samuel
Bananenfreak wrote: Could someone tell me what this is?
I use directional light and yeah, that´s the difference to the example.
Are you sure the only thing different is the light? On my example directional lighting works fine. So, I think you might have something else wrong.

These are some basic things to check.

Make sure your mesh has tangents.
Make sure nothing was changed in the files.
Also is it possible you edited the Normal Height Map? An improper map can cause strange effects.