Fresnel Shader

Everything related to 3D programming
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 756
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Frensel Shader

Post by Samuel »

I have a Fresnel shader that has been sitting in my collection for some time now. If I remember correctly it was just ripped out of OGRE's Hydrax.
I just need to edit it slightly to support multiple materials, but once that's done I'll post the code for you.

I can remove the texture unit for you if you don't want it. I just need to comment out a few lines to disable it.
As for the compositor I don't think I'll be that much help. Unless you can find an example. I won't have the time to create one for you.

If all goes well I should be able to post the shader later in the day.

Actually, I have one little question for you. Do you plan on using this with the Toon shader you've been working with?
If you do then I need to some tweaking to make the Fresnel and the Toon shader work together. If not then no worry.
User avatar
Lord
Addict
Addict
Posts: 909
Joined: Tue May 26, 2009 2:11 pm

Re: Frensel Shader

Post by Lord »

Please rename your posting from "Frensel Shader" to "Fresnel Shader"
so it can be searched and found. Also rename it in the corresponding
text. Only the picture is correct.
Image
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 756
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Fresnel Shader

Post by Samuel »

For now here's the Fresnel shader.
When I've implemented it into the toon shader I'll PM it to you, Alexi.

First, here's a little sample picture for those who want to see the effect.
At the moment the Fresnel is set to white, but you can change it to whatever you like just by editing the variables in the material script.
Image

For those of you who just want to jump right into it here's a download link.
Fresnel Shader

I'll post the code too. Since the download link will eventually die.
If someone down the line needs the download version let me know and I'll re upload it for you.

For those of you who are new to cg shaders. You need to download Nvidia's cg toolkit.
Here you go.
https://developer.nvidia.com/cg-toolkit-download
The downloads at the bottom of their page.

You'll also need to include the cg.dll (with your app) if you intend to release it to others.
I guess I could have just included the cg.dll with my demo download above. Then you wouldn't need to download it........ :oops:
I'll try to remember to include it next time I create a shader demo.
EDIT:
I re uploaded the download with the required cg.dll. So, the shader should run even if you haven't downloaded Nvidia's cg toolkit.


OK, let's get into the code.
You can save them in pretty much any text editor.

First the material script.

fresnel.material

Code: Select all

//Lines like this one are commented out.

abstract material FresnelTemplate
{
	technique 
	{
		pass
		{
			ambient $ambient
			diffuse $diffuse

			//#### Comment out these next five lines to exclude textures. ####
			texture_unit 
			{
				texture $Texture
				filtering linear linear linear
			}
			//#### ####
		}
		pass 
		{
			scene_blend add
			depth_check on
			lighting on
             
			vertex_program_ref fresnel_vs 
			{
			}
             
			fragment_program_ref fresnel_ps 
			{
				param_named GlowColor float3 $GlowColor
				param_named GlowExpon float  $GlowExpon
				param_named Alpha float $Alpha
			}
		}
	}
}

material FresnelWhite : FresnelTemplate
{
   set $ambient "1.0 1.0 1.0"  //#### Ambient Color. 1.0 equals 255 compared to RGB format. ####
   set $diffuse "1.0 1.0 1.0"  //#### Diffuse Color. 1.0 equals 255 compared to RGB format. ####
   set $GlowColor "1.0 1.0 1.0"//#### Glow Color. 1.0 equals 255 compared to RGB format. ####
   set $GlowExpon 3.0          //#### The smaller the exponent the thicker the effect. ####
   set $Alpha 0.8              //#### Value can be greater then 1, but around 10 it starts to engulf your entities. ####
   set $Texture grass.jpg      //#### Alexi, Comment out this line with the texture unit above to disable textures. ####
}
Now the program file.

fresnel.program

Code: Select all

    vertex_program fresnel_vs cg {
       source fresnel.cg
       entry_point main_vs
       profiles vs_2_0 arbvp1 vs_2_x vs_3_0 vp40
       
       default_params {
          // Leave these
          param_named_auto WorldITXf    inverse_transpose_world_matrix
          param_named_auto WorldXf      world_matrix
          param_named_auto ViewIXf      inverse_view_matrix
          param_named_auto WvpXf        worldviewproj_matrix
       }
    }

    fragment_program fresnel_ps cg {
       source fresnel.cg
       entry_point main_ps
       profiles ps_2_0 arbfp1 ps_2_x ps_3_0 ps_3_x fp40

       default_params {
          //These are default values. No need to change them.
          // Default is white (rgb)
          param_named GlowColor float3 1.0 1.0 1.0
          // Bigger exponent, thinner edges
          param_named GlowExpon float  2.5
          // Set transparency of the fresnel
          param_named Alpha float  1.0
       }
    }
Here's the shader itself.

fresnel.cg

Code: Select all

    void main_vs(float4 Position : POSITION,
            float4 Normal   : NORMAL,
            out float4 HPosition   : POSITION,
            out float3 WorldNormal : TEXCOORD0,
            out float3 WorldView   : TEXCOORD1,

            uniform float4x4 WorldITXf, // our four standard "untweakable" xforms
            uniform float4x4 WorldXf,
            uniform float4x4 ViewIXf,
            uniform float4x4 WvpXf
    ) {
        WorldNormal = mul(WorldITXf, Normal).xyz;
        float4 Po = Position;
       // This just inflates it a tiny bit so we don't get depth fighting
        Po.xyz += 0.01 * Normal;
        float4 Pw = mul(WorldXf, Po);
        WorldView = normalize(float3(ViewIXf[0].w, ViewIXf[1].w, ViewIXf[2].w) - Pw.xyz);
        HPosition = mul(WvpXf, Po);
    }


float4 main_ps(float3 WorldNormal : TEXCOORD0,
         float3 WorldView   : TEXCOORD1,
         
         uniform float3 GlowColor,
         uniform float GlowExpon,
         uniform float Alpha
         ) : COLOR
{
    float3 Nn = normalize(WorldNormal);
    float3 Vn = normalize(WorldView);
    float edge = 1.0 - dot(Nn, Vn);
    edge = pow(edge, GlowExpon) * Alpha;
    float3 result = edge * GlowColor.rgb;
    return float4(result, edge);
}
And last, but not least is the Purebasic code.
You'll need to set the archive to the files you previously saved.

Code: Select all


If InitEngine3D(#PB_Engine3D_EnableCG | #PB_Engine3D_DebugLog)
Else
  End
EndIf
InitSprite()
InitKeyboard()
InitMouse()

Enumeration
  #FPS
EndEnumeration

ExamineDesktops()
screenWidth  = DesktopWidth(0)
screenHeight = DesktopHeight(0)

If LoadFont(0, "", 10,#PB_Font_Bold)
  SetGadgetFont(#PB_Default, FontID(0))
EndIf

If OpenWindow(0, 0, 0, screenWidth, screenHeight, "Fresnel Effect")
  AntialiasingMode(#PB_AntialiasingMode_x6)
  If OpenWindowedScreen(WindowID(0), 0, 0, screenWidth, screenHeight, 0, 0, 0)
    
    ;#### Set this path to the previously saved shader files ####
    Add3DArchive("\", #PB_3DArchive_FileSystem)
    ;#### ####
    Add3DArchive(#PB_Compiler_Home+"\Examples\3D\Data\Packs\Sinbad.zip",#PB_3DArchive_Zip)
    Add3DArchive(#PB_Compiler_Home+"\Examples\3D\Data\Textures",#PB_3DArchive_FileSystem)
    Parse3DScripts()
    
    CPU$ = CPUName()
    CreateSprite(#FPS, 280, 210)
    StartDrawing(SpriteOutput(#FPS))
      Box(0,0,280,120,RGB(0,0,0))
    StopDrawing()
    
    LoadMesh(0,"Sinbad.mesh")
    LoadTexture(0,"ground_diffuse.png")
    
    CreateMaterial(1,TextureID(0))
    ;#### Load Shader Material ####
    GetScriptMaterial(0,"FresnelWhite")
    
    CreateNode(1,0,0,0)
    CreatePlane(4,60,60,1,1,10,10)
    CreateEntity(0, MeshID(0),MaterialID(0),0,5,0)
    CreateEntity(4,MeshID(4),MaterialID(1),0,0,0)

    CreateCamera(0, 0,0,100,100)
    MoveCamera(0, 0, 5, 20)
    CameraLookAt(0, 0, 5, 0)
    CameraBackColor(0, RGB(10, 10, 10))
    AttachNodeObject(1,CameraID(0))
    
    CreateLight(0, RGB(0,0,0), -5,10,4)
    SetLightColor(0, #PB_Light_DiffuseColor, RGB(200,100,0))
    SetLightColor(0, #PB_Light_SpecularColor, RGB(255,155,255))
    
    StartEntityAnimation(0, "IdleTop", #PB_EntityAnimation_Manual)
    StartEntityAnimation(0, "IdleBase", #PB_EntityAnimation_Manual)
    
  Repeat
    If ExamineKeyboard()
      If KeyboardPushed(#PB_Key_Up)
        MoveCamera(0, 0, 0, -0.2)
      ElseIf KeyboardPushed(#PB_Key_Down)
        MoveCamera(0, 0, 0, 0.2)
      EndIf
      If KeyboardPushed(#PB_Key_Left)
        RotateNode(1,0,-1,0,#PB_Relative)
        CameraLookAt(0, 0, 5, 0)
      ElseIf KeyboardPushed(#PB_Key_Right)
        RotateNode(1,0,1,0,#PB_Relative)
        CameraLookAt(0, 0, 5, 0)
      EndIf
      If KeyboardReleased(#PB_Key_W)
         CameraRenderMode(0, #PB_Camera_Wireframe)
      ElseIf KeyboardReleased(#PB_Key_E)
         CameraRenderMode(0, #PB_Camera_Textured)
      EndIf
    EndIf


      AddEntityAnimationTime(0, "IdleTop", LastFrame * 2)
      AddEntityAnimationTime(0, "IdleBase", LastFrame * 2)
      LastFrame=RenderWorld()
      
      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(0)) 
          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 FirstFrame=0
          Engine3DFrameRate(#PB_Engine3D_Reset)
          FirstFrame=1
        EndIf
      EndIf
      FlipBuffers()

    Until WindowEvent() = #PB_Event_CloseWindow Or KeyboardPushed(#PB_Key_Escape)
    
  EndIf
EndIf
End
That's about all there is. If you have any questions or are having trouble let me know and I'll try to help.
Also, if anyone spots any errors let me know and I'll try to fix them.
Good luck. :D
Last edited by Samuel on Wed Nov 27, 2013 7:53 pm, edited 2 times in total.
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: Fresnel Shader

Post by applePi »

thanks Samuel ,the Genie glow are wonderfull , such achievements should not lost inside the questions forum with the dust of time, the free sites like the one made by Joakim Christiansen https://github.com/JoakimCh/JLCs_PB_stuff
and reported here http://www.purebasic.fr/english/viewtop ... 17&t=57435 are good for keeping finished projects in one place , after it is discussed in this 3D forum.
best regards
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 756
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Fresnel Shader

Post by Samuel »

Alexi wrote: @Samuel, maybe the example could be white with some less alpha to show how common fresnel will look like, not mainly purposed for nuclear Genies. :D
I changed it to white. I also increased the exponent and decreased the alpha a little too.
While I was at it I also included the cg.dll with the download. So, the shader should run even if someone doesn't download the Nividia cg toolkit.
Alexi wrote: It's right the Thread will get lost someday, so there should be a pinned Thread beside "Ogre Tools" for Shader and Compositors.
Maybe it would be helpful for some, but to me personally I don't usually look at the pinned threads. Most of them (besides the read mes) have so many posts
in them that it's easier to just use the search bar to find exactly what I need.
At this time this thread is the only Fresnel topic in the 3D section. A simple search on Fresnel turned it right up.
So, as long as the person knows what they are looking for then this shouldn't be an issue.

Maybe one day I could make a guide on using scripts and shaders. I could include all the shader examples I've posted with nice tutorials on how to use them.
If other people would like to contribute. They could just send me their shader and I could include it in the guide.
Of course something like this would take time to create. Time I don't have at the moment, but maybe when my work settles down a little more. I could start
working on this project.
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 756
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Fresnel Shader

Post by Samuel »

I looked around a bit and I think I know what you need. I believe material LOD will solve your problem.

If others wish to try it then just replace the material script from my previous example with this one.
With this script the Fresnel effect should be disabled when the entity is 30 units away from the camera.

fresnel.material

Code: Select all

abstract material FresnelTemplate
{
   lod_strategy Distance 
   lod_values 30
	technique near
	{
		lod_index 0
		pass
		{
			ambient $ambient
			diffuse $diffuse
			texture_unit 
			{
				texture $Texture
				filtering linear linear linear
			}
		}
		pass 
		{
			scene_blend add
			depth_check on
			lighting on
             
			vertex_program_ref fresnel_vs 
			{
			}
             
			fragment_program_ref fresnel_ps 
			{
				param_named GlowColor float3 $GlowColor
				param_named GlowExpon float  $GlowExpon
				param_named Alpha float $Alpha
			}
		}
	}
	technique far
	{
		lod_index 1
		pass
		{
			ambient $ambient
			diffuse $diffuse
			texture_unit 
			{
				texture $Texture
				filtering linear linear linear
			}
		}
	}
}

material FresnelWhite : FresnelTemplate
{
   set $ambient "1.0 1.0 1.0"
   set $diffuse "1.0 1.0 1.0"
   set $GlowColor "1.0 1.0 1.0"
   set $GlowExpon 3.0
   set $Alpha 0.8
   set $Texture grass.jpg
}
Post Reply