Jump to content
  • Advertisement
Sign in to follow this  
x452Alba

OpenGL ThinFilm from HLSL to GLSL

This topic is 4010 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello OpenGl guru's, I am attempting to do a direct conversion from a HLSL shader to a GLSL shader. Well actually it is a HLSL FX shader from the new nVidia shader library and I was hoping for a few pointers of where I have messed up. The shader I am trying to convert is the ThinFilm shader. Below is an image of the output produced by the shader and some simplified HLSL code.
...

struct appData
{
    float4 Position : POSITION;
    float4 Normal   : NORMAL;
};

struct filmyVertexOutput
{
    float4 HPOS      : POSITION;
    float3 diffCol   : COLOR0;
    float3 specCol   : COLOR1;
    float2 filmDepth : TEXCOORD0;
};


/// VS ///
filmyVertexOutput ThinFilmVS(appData IN,uniform float3 LightPos)
{
    filmyVertexOutput OUT = (filmyVertexOutput)0;
    float3 Nn = mul(IN.Normal,WorldITXf).xyz;
    float4 Po = float4(IN.Position.xyz,1.0);
    float3 Pw = mul(Po,WorldXf).xyz;
    OUT.HPOS = mul(Po,WvpXf);
    float3 Ln = normalize(LightPos - Pw);
    float3 Vn = normalize(ViewIXf[3].xyz - Pw);
    float3 Hn = normalize(Ln + Vn);
    float ldn = dot(Ln,Nn);
    float hdn = dot(Hn,Nn);
    float vdn = dot(Vn,Nn);
    OUT.diffCol = max(ldn, 0.0).xxx;
    OUT.specCol = pow(hdn,SpecExpon).xxx;
    // compute the view depth for the thin film
    float viewdepth = FilmDepth.x / vdn;
    OUT.filmDepth = viewdepth.xx;
    return OUT;
}

/// PS ///
float4 ThinFilmPS(filmyVertexOutput IN) : COLOR
{
    // lookup fringe value based on view depth
    float3 fringeCol = (float3)tex2D(FringeMapSampler, IN.filmDepth);
    // modulate specular lighting by fringe color, combine with regular lighting
    float3 rgb = fringeCol*IN.specCol + IN.diffCol*SurfColor;
    return float4(rgb,1);
}

...

Next is the current output from my shader conversion attempt. If you squint you can just see the film effect. :)
...

/// VS ///
varying float texCoord;
varying vec3 specular_color, diffuse_color;

uniform float film_depth, exponent;
uniform vec3 eye_position, light_position;

void main()
{
   film_depth = 0.05; // Hard code some test values...
   exponent = 32.0;
   light_position = vec3(-0.5, 2.0, 1.25);

   vec3 Nn = normalize(gl_NormalMatrix * gl_Normal);
   vec3 Pw = vec3(gl_ModelViewMatrix * gl_Vertex);

   vec3 Ln = normalize(light_position - Pw);
   vec3 Vn = normalize(eye_position   - Pw);
   vec3 Hn = normalize(Ln + Vn);

   float ldn = dot(Ln, Nn);
   float hdn = dot(Hn, Nn);
   float vdn = dot(Vn, Nn);

   float lit = max(ldn, 0.0);

   diffuse_color  = vec3(lit, lit, lit);
   specular_color = vec3(pow(hdn, exponent), pow(hdn, exponent), pow(hdn, exponent));

   texCoord = film_depth / vdn;

   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

/// PS ///

varying float texCoord;
varying vec3 specular_color, diffuse_color;

uniform sampler1D film;
uniform vec3 surface_color;

void main()
{
   surface_color = vec3(1.0, 1.0, 1.0);
   gl_FragColor = vec4(texture1D(film, texCoord) * specular_color + diffuse_color * surface_color, 1.0);
}

...

Thanks in advance.

Share this post


Link to post
Share on other sites
Advertisement
I would recommend you simplify your shader and verify that each calculation is working correctly before moving on the the next bit.

Shader debugging is tricky. Usually it involves sort of a binary search through your shader to see what went wrong. Sometimes you can find it in the code directly, but I would recommend getting use to debugging because the answer won't always be easy to find.

Share this post


Link to post
Share on other sites
Yay. After a few days, joy. Here is the final working shader successfully converted into pure GLSL. It's simpler and has no artefacts, unlike the official nVidia sample. All that was needed was to clamp the texture coordinates for the texture lookup preformed in the fragment shader.

However, my troubles were solved by ensuring h dot n remained in positive space.

So without further ado:


varying float texCoord;
varying float specular, diffuse;

uniform float film_depth, exponent;
uniform vec3 eye_position, light_position;

void main()
{
vec3 Nn = normalize(gl_NormalMatrix * gl_Normal);
vec3 Pw = vec3(gl_ModelViewMatrix * gl_Vertex);

vec3 Ln = normalize(light_position - Pw);
vec3 Vn = normalize(eye_position - Pw);
vec3 Hn = normalize(Ln + Vn);

float ldn = dot(Ln, Nn);
float hdn = dot(Hn, Nn);
float vdn = dot(Vn, Nn);

diffuse = max(ldn, 0.0);
specular = pow(max(hdn, 0.0), exponent);

texCoord = clamp(film_depth / vdn, 0.0, 1.0);

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}



Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!