It is currently Fri Aug 07, 2020 10:03 am


All times are UTC




Post new topic Reply to topic  [ 12 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Triplanar texturing
PostPosted: Tue Jan 18, 2011 9:20 pm 

Joined: Sat Jan 15, 2011 3:49 pm
Posts: 38
I'm trying to get a triplanar texturing shader to work correctly, has anyone else done this?

Here is some info on the subject:
http://memoirsofatexel.blogspot.com/201 ... pping.html
http://http.developer.nvidia.com/GPUGem ... _ch01.html
http://www.ogre3d.org/forums/viewtopic. ... 587926f89b

edit: got it working, here is the shader incase anyone wants it
http://dl.dropbox.com/u/6281166/triplanar.jpg
http://dl.dropbox.com/u/6281166/triplanar2.jpg
Code:
float4x4 World;
float4x4 View;
float4x4 Projection;
float4 lightDirection = { 1, -0.7, 1, 0};
float textureScale;

texture ColorMap;
sampler ColorMapSampler = sampler_state
{
   Texture = <ColorMap>;
   MinFilter = ANISOTROPIC;
   MagFilter = ANISOTROPIC;
   MipFilter = Linear;   
   AddressU  = Clamp;
   AddressV  = Clamp;
};

// TODO: add effect parameters here.

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float3 Normal : NORMAL0;

    // TODO: add input channels such as texture
    // coordinates and vertex colors here.
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float3 Normal : TEXCOORD0;
    float3 worldPosition : TEXCOORD1;

    // TODO: add vertex shader outputs such as colors and texture
    // coordinates here. These values will automatically be interpolated
    // over the triangle, and provided as input to your pixel shader.
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

   output.worldPosition = input.Position.xyz / input.Position.w;
   output.Normal = normalize(input.Normal);

    // TODO: add your vertex shader code here.

    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
   float3 absNormal = abs(input.Normal);
   float3 blend_weights = absNormal;
   blend_weights = blend_weights - 0.2679f;
   blend_weights = max(blend_weights, 0);
   // force sum to 1.0
   blend_weights /= (blend_weights.x + blend_weights.y + blend_weights.z).xxx;

   float4 blended_color;
   float tex_scale = 0.03f;

   float2 coord1 = input.worldPosition.yz * tex_scale;
   float2 coord2 = input.worldPosition.zx * tex_scale;
   float2 coord3 = input.worldPosition.xy * tex_scale;

   float4 col1 = tex2D(ColorMapSampler, coord1) * 0.01 + float4(1.0,0.0,0.0,1.0); // uncomment to see the blending in red/green/blue only
   float4 col2 = tex2D(ColorMapSampler, coord2) * 0.01 + float4(0.0,1.0,0.0,1.0);
   float4 col3 = tex2D(ColorMapSampler, coord3) * 0.01 + float4(0.0,0.0,1.0,1.0);

   blended_color = col1.xyzw * blend_weights.xxxx + 
               col2.xyzw * blend_weights.yyyy + 
               col3.xyzw * blend_weights.zzzz;

   // directional lighting
   float4 light = -normalize(lightDirection);
   float ldn = max(0, dot(light, input.Normal));
   float ambient = 0.2f;

   return blended_color * (ambient + ldn);
}

technique Technique1
{
    pass Pass1
    {
        // TODO: set renderstates here.

        VertexShader = compile vs_1_1 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}



now for some deferred lighting...


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Triplanar texturing
PostPosted: Thu Mar 17, 2011 1:51 pm 
User avatar

Joined: Wed Jan 26, 2011 3:20 pm
Posts: 203
Location: Germany
ok, I've finally gotten around to try out triplanar texturing.
I'm really lost on how to use your shader (or shaders in general^^)

do you have an example for the result you posted?
Quote:
http://dl.dropbox.com/u/6281166/triplanar2.jpg


I mean with texture file loading and everything?

it looks really great btw :)


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Triplanar texturing
PostPosted: Thu Mar 17, 2011 1:54 pm 

Joined: Fri Feb 18, 2011 8:41 pm
Posts: 173
Oh hey a bug with the triplanar texturing I forgot to mention when I made another thread about it. Now ker brought this up so it's good to say:

Normalize the normal in pixel shader!

Once normals pass from vertex shader to pixel shader they get un-normalized.

a call to:
input.Normal = normalize(input.Normal);

should fix texturing problems and artifacts.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Triplanar texturing
PostPosted: Thu Mar 17, 2011 3:28 pm 
User avatar

Joined: Wed Jan 26, 2011 3:20 pm
Posts: 203
Location: Germany
Shanee, you seem to have gotten the hang of it, texatlas + triplanar texturing...
can you give me some code snippets of your rendering and shader code?


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Triplanar texturing
PostPosted: Thu Mar 17, 2011 3:36 pm 

Joined: Fri Feb 18, 2011 8:41 pm
Posts: 173
ker wrote:
Shanee, you seem to have gotten the hang of it, texatlas + triplanar texturing...
can you give me some code snippets of your rendering and shader code?


Sorry about the mess!
Rendering has nothing special. Also my texture atlas is still buggy ;) mip mapping doesn't work and so does filtering properly.

Also I don't know if my way is the best way, I just wrote this shader in a few seconds to try out more materials.

TextureAtlas.fx
Code:
#ifndef TEXTUREATLAS
#define TEXTUREATLAS

float2 GetAtlasUV(float2 uv, float material, float numMatsX, float numMatsY)
{
   // First make sure u/v are between 0 and 1.
   while (uv.x > 1)
   {
      uv.x -= 1;
   }

   while (uv.x < 0)
   {
      uv.x += 1;
   }

   while (uv.y > 1)
   {
      uv.y -= 1;
   }

   while (uv.y < 0)
   {
      uv.y += 1;
   }

   // Divide by the number of materials to get proper texture UV coordinates
   uv.x /= numMatsX;
   uv.y /= numMatsY;

   float yPos = 0;

   while (material >= numMatsX)
   {
      yPos += 1;
      material -= numMatsX;
   }

   uv.x += 1 / numMatsX * material;
   uv.y += 1 / numMatsY * yPos;

   return uv;
}

#endif


VoxelShaderAtlas.fx
Code:
#include "BlinnPhong.fx"
#include "TextureAtlas.fx"

float4x4 World;
float4x4 View;
float4x4 Projection;
float textureScale;

uniform extern float3 gEyePos;

texture gTex0;
sampler ColorMapSampler = sampler_state
{
   Texture = <gTex0>;
   /*MinFilter = ANISOTROPIC;
   MagFilter = ANISOTROPIC;
   MipFilter = Linear;   */
   MinFilter = NONE;
   MagFilter = NONE;
   MipFilter = NONE;
   AddressU  = Clamp;
   AddressV  = Clamp;
};

// TODO: add effect parameters here.

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float3 Normal : NORMAL0;
   float1 Material : TEXCOORD0;

    // TODO: add input channels such as texture
    // coordinates and vertex colors here.
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float3 Normal : TEXCOORD0;
    float3 worldPosition : TEXCOORD1;
   float1 Material : TEXCOORD2;

    // TODO: add vertex shader outputs such as colors and texture
    // coordinates here. These values will automatically be interpolated
    // over the triangle, and provided as input to your pixel shader.
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

   output.worldPosition = input.Position.xyz / input.Position.w;
   output.Normal = normalize(input.Normal);
   output.Material = input.Material;

    // TODO: add your vertex shader code here.

    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
   float3 Normal = normalize(input.Normal);
   float3 absNormal = abs(Normal);
   float3 blend_weights = absNormal;
   blend_weights = blend_weights - 0.2679f;
   blend_weights = max(blend_weights, 0);
   // force sum to 1.0
   blend_weights /= (blend_weights.x + blend_weights.y + blend_weights.z).xxx;

   float4 blended_color;
   float tex_scale = 0.1f;

   float2 coord1 = GetAtlasUV(input.worldPosition.yz * tex_scale, input.Material, 4, 4);
   float2 coord2 = GetAtlasUV(input.worldPosition.zx * tex_scale, input.Material, 4, 4);
   float2 coord3 = GetAtlasUV(input.worldPosition.xy * tex_scale, input.Material, 4, 4);

   float4 col1 = tex2D(ColorMapSampler, coord1);// * 0.01 + float4(1.0,0.0,0.0,1.0); // uncomment to see the blending in red/green/blue only
   float4 col2 = tex2D(ColorMapSampler, coord2);// * 0.01 + float4(0.0,1.0,0.0,1.0);
   float4 col3 = tex2D(ColorMapSampler, coord3);// * 0.01 + float4(0.0,0.0,1.0,1.0);

   blended_color = col1.xyzw * blend_weights.xxxx + 
               col2.xyzw * blend_weights.yyyy + 
               col3.xyzw * blend_weights.zzzz;



   
   
   // Compute the vector from the vertex to the eye position.
      float3 viewDir = normalize(gEyePos - input.worldPosition);

     Lighting lightColor = GetDirectionalLight(viewDir, -Normal);
    

     float3 finalLight = float3(0,0,0);

     for (int i = 0; i < MAX_LIGHTS; i++)
     {
      float3 lightDir = gLights[i].position - input.worldPosition; // FIND THE VECTOR BETWEEN THE 3D POSITION IN SPACE OF THE SURFACE
      Lighting lightColor2 = GetPointLight(gLights[i], viewDir, -Normal, lightDir);
      lightColor.Diffuse += lightColor2.Diffuse;
      lightColor.Specular += lightColor2.Specular;       
     }

      // Combine texture color with color generated by lighting.
     finalLight += AmbientLight;
     finalLight += lightColor.Diffuse;
    
    
   //return float4((Normal+1)/2, 1);
   return float4(finalLight * blended_color.xyz, 1);
}

technique Technique1
{
    pass Pass1
    {
        // TODO: set renderstates here.
      CULLMODE = CCW;
      ZENABLE = TRUE;
        ZWRITEENABLE = TRUE;
        VertexShader = compile vs_3_0 VertexShaderFunction();
        PixelShader = compile ps_3_0  PixelShaderFunction();
    }
}


BlinnPhong.fx
Code:
#ifndef BLINNPHON_FX
#define BLINNPHON_FX

struct Lighting
{
    float3 Diffuse;
    float3 Specular;
};

struct PointLight
{
   float3 position;
   float3 diffuseColor;
   float diffusePower;
   float3 specularColor;
   float specularPower;
};

struct DirectionalLight
{
   float3 Diffuse;
   float DiffusePower;
   float3 Specular;
   float SpecularPower;
   float3 Direction; 
   
};

struct Mtrl
{
   float4 Diffuse;
   float4 Ambient;
   float4 Specular;
   float4 Emissive;
   float  SpecularPower;
};


/*uniform extern texture  gNormalMap;

sampler NormalMapS = sampler_state
{
   Texture = <gNormalMap>;
   MinFilter = ANISOTROPIC;
   MaxAnisotropy = 8;
   MagFilter = LINEAR;
   MipFilter = LINEAR;
   AddressU  = WRAP;
    AddressV  = WRAP;
};*/

uniform extern Mtrl     Material;

DirectionalLight gDirectionalLight;

#define MAX_LIGHTS 8
uniform extern PointLight gLights[MAX_LIGHTS];
float3 AmbientLight = float3(0.2,0.2,0.2);

static float specularHardness = 25.0f;

Lighting GetPointLightOld(PointLight light, float3 viewDir, float3 normal, float3 lightDir)
{
   Lighting OUT;
   if(light.diffusePower > 0)
   {
   //normal = normalize(normal);
      float distance = length(lightDir); // GET THE DISTANCE OF THIS VECTOR
      distance = distance * distance; // USES INVERSE SQUARE FOR DISTANCE ATTENUATION
      lightDir = normalize(lightDir); // NORMALIZE THE VECTOR

      // INTENSITY OF THE DIFFUSE LIGHT   
                // SATURATE TO KEEP WITHIN THE 0-1 RANGE
                // DOT PRODUCT OF THE LIGHT DIRECTION VECTOR AND THE SURFACE NORMAL
      float i = saturate(dot(lightDir, normal));

      OUT.Diffuse = i * light.diffuseColor * light.diffusePower / distance; // CALCULATE THE DIFFUSE LIGHT FACTORING IN LIGHT COLOUR, POWER AND THE ATTENUATION

                //CALCULATE THE HALF VECTOR BETWEEN THE LIGHT VECTOR AND THE VIEW VECTOR. THIS IS CHEAPER THEN CALCULATING THE ACTUAL REFLECTIVE VECTOR
                float3 h = normalize(lightDir + viewDir);

           // INTENSITY OF THE SPECULAR LIGHT   
                // DOT PRODUCT OF NORMAL VECTOR AND THE HALF VECTOR TO THE POWER OF THE SPECULAR HARDNESS
      i = pow(saturate(dot(normal, h)), specularHardness);   

      OUT.Specular = i * light.specularColor * light.specularPower / distance; // CALCULATE THE SPECULAR LIGHT FACTORING IN LIGHT SPECULAR COLOUR, POWER AND THE ATTENUATION
   }
   return OUT;
}




Lighting GetDirectionalLightOld(float3 viewDir, float3 normal)
{
   Lighting OUT;
   if(gDirectionalLight.DiffusePower > 0)
   {
         normal = normalize(normal);
      float lightDir = normalize(gDirectionalLight.Direction); // NORMALIZE THE VECTOR

      // INTENSITY OF THE DIFFUSE LIGHT   
                // SATURATE TO KEEP WITHIN THE 0-1 RANGE
                // DOT PRODUCT OF THE LIGHT DIRECTION VECTOR AND THE SURFACE NORMAL
      //float i = saturate(dot(lightDir, normal));
      float i = saturate(dot(normal, lightDir));

      OUT.Diffuse = i * gDirectionalLight.Diffuse * gDirectionalLight.DiffusePower ; // CALCULATE THE DIFFUSE LIGHT FACTORING IN LIGHT COLOUR, POWER AND THE ATTENUATION

                //CALCULATE THE HALF VECTOR BETWEEN THE LIGHT VECTOR AND THE VIEW VECTOR. THIS IS CHEAPER THEN CALCULATING THE ACTUAL REFLECTIVE VECTOR
                float3 h = normalize(lightDir + viewDir);

           // INTENSITY OF THE SPECULAR LIGHT   
                // DOT PRODUCT OF NORMAL VECTOR AND THE HALF VECTOR TO THE POWER OF THE SPECULAR HARDNESS
      i = pow(saturate(dot(normal, h)), specularHardness);   

      OUT.Specular = i * gDirectionalLight.Specular * gDirectionalLight.SpecularPower ; // CALCULATE THE SPECULAR LIGHT FACTORING IN LIGHT SPECULAR COLOUR, POWER AND THE ATTENUATION
   }
   return OUT;
}

Lighting GetDirectionalLight(float3 viewDir, float3 normal)
{
   Lighting OUT;
   

   /*normal = normalize(normal);
   float3 lightVec = normalize(gDirectionalLight.Direction);
   float3 halfVec = normalize(lightVec + viewDir);

   OUT.Diffuse = saturate(dot(normal, lightVec)) * gDirectionalLight.Diffuse * gDirectionalLight.DiffusePower;
   OUT.Specular = pow(saturate(dot(normal, halfVec)), 8) * gDirectionalLight.Specular * gDirectionalLight.SpecularPower;*/


   /*normal = normalize(normal);
    float3 lightVec = normalize(gDirectionalLight.Direction);
    float3 ViewDir = normalize(viewDir);
    OUT.Diffuse = saturate(dot(normal, lightVec)); // diffuse component
 
    // R = 2 * (N.L) * N - L
    float3 Reflect = normalize(2 * OUT.Diffuse * normal - lightVec);
    OUT.Specular = pow(saturate(dot(Reflect, ViewDir)), 8); // R.V^n */


   normal = normalize(normal);
   float3 lightVec = normalize(gDirectionalLight.Direction);

   // Compute the reflection vector.
    float3 r = reflect(lightVec, normal);

    // Determine how much (if any) specular light makes it
    // into the eye.
    float t  = pow(max(dot(r, viewDir), 0.0f), gDirectionalLight.SpecularPower);

    // Determine the diffuse light intensity that strikes the vertex.
    float s = max(dot(-lightVec, normal), 0.0f);

    // Compute the ambient, diffuse, and specular terms separately.
    OUT.Specular = t*(gDirectionalLight.Specular).rgb;
    OUT.Diffuse = s*(gDirectionalLight.Diffuse).rgb;
   


   

   return OUT;
}


Lighting GetPointLight(PointLight light, float3 viewDir, float3 normal, float3 lightDir)
{
Lighting OUT;
      normal = normalize(normal);
      float distance = length(lightDir); // GET THE DISTANCE OF THIS VECTOR
      distance = distance * distance; // USES INVERSE SQUARE FOR DISTANCE ATTENUATION
      lightDir = normalize(lightDir); // NORMALIZE THE VECTOR

      float3 halfVec = normalize(lightDir + viewDir);

      OUT.Diffuse = saturate(dot(normal, lightDir)) * light.diffuseColor * light.diffusePower / distance;
      OUT.Specular = pow(saturate(dot(normal, halfVec)), specularHardness) * light.specularColor * light.specularPower / distance;
   return OUT;
}

Lighting GetPointLightNormal(PointLight light, float3 viewDir, float3 normal, float3 lightDir, float3 distance)
{
Lighting OUT;
      normal = normalize(normal);
      distance = length(distance); // GET THE DISTANCE OF THIS VECTOR
      distance = distance * distance; // USES INVERSE SQUARE FOR DISTANCE ATTENUATION
      lightDir = normalize(lightDir); // NORMALIZE THE VECTOR

      float3 halfVec = normalize(lightDir + viewDir);

      OUT.Diffuse = saturate(dot(normal, lightDir)) * light.diffuseColor * light.diffusePower / distance;
      OUT.Specular = pow(saturate(dot(normal, halfVec)), specularHardness) * light.specularColor * light.specularPower / distance;
   return OUT;
}


Lighting GetDirectionalLightBormal(float3 LightDir, float3 viewDir, float3 normal)
{
   Lighting OUT;
   

   /*normal = normalize(normal);
   float3 lightVec = normalize(LightDir);
   float3 halfVec = normalize(lightVec + viewDir);

   OUT.Diffuse = saturate(dot(normal, lightVec)) * gDirectionalLight.Diffuse * gDirectionalLight.DiffusePower;
   OUT.Specular = pow(saturate(dot(normal, halfVec)), 8) * gDirectionalLight.Specular * gDirectionalLight.SpecularPower;*/


   /*normal = normalize(normal);
    float3 lightVec = normalize(LightDir);
    float3 ViewDir = normalize(viewDir);
    OUT.Diffuse = saturate(dot(normal, lightVec)); // diffuse component
 
    // R = 2 * (N.L) * N - L
    float3 Reflect = normalize(2 * OUT.Diffuse * normal - lightVec);
    OUT.Specular = pow(saturate(dot(Reflect, ViewDir)), 8); // R.V^n */


   normal = normalize(normal);
   float3 lightVec = normalize(LightDir);

   // Compute the reflection vector.
    float3 r = reflect(lightVec, normal);

    // Determine how much (if any) specular light makes it
    // into the eye.
    float t  = pow(max(dot(r, viewDir), 0.0f), gDirectionalLight.SpecularPower);

    // Determine the diffuse light intensity that strikes the vertex.
    float s = max(dot(-lightVec, normal), 0.0f);

   if(s <= 0.0f)
        t = 0.0f;

    // Compute the ambient, diffuse, and specular terms separately.
    OUT.Specular = t*(gDirectionalLight.Specular).rgb;
    OUT.Diffuse = s*(gDirectionalLight.Diffuse).rgb;
   


   

   return OUT;
}


#endif


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Triplanar texturing
PostPosted: Thu Mar 17, 2011 3:51 pm 
Developer
User avatar

Joined: Sun May 11, 2008 4:29 pm
Posts: 198
Location: UK
As David mentioned earlier, it would be really great if we could document some of this in the wiki. There's already a start on this topic there but the more information the better.

_________________
Matt Williams
Linux/CMake guy


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Triplanar texturing
PostPosted: Fri Mar 18, 2011 9:23 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
ker wrote:
Shanee, you seem to have gotten the hang of it, texatlas + triplanar texturing...

You should try to get each of these working in isolation before you try to combine them. I would also say that triplanar texturing was significantly simpler that texture atlases so I probably recommend you start there. Hopefully Shanee's code will be useful, but it's usually quite hard to just drop shader code into another project. Even when I've taken code from sources such as GPU Gems you can have to do a lot of work to get it itegrated.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Triplanar texturing
PostPosted: Sat Mar 19, 2011 10:44 am 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
@ Shanee - I moved the post that was here as I think you meant to post it in this topic.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Triplanar texturing
PostPosted: Sun Mar 20, 2011 6:22 am 

Joined: Fri Feb 18, 2011 8:41 pm
Posts: 173
ker wrote:
Shanee, you seem to have gotten the hang of it, texatlas + triplanar texturing...
can you give me some code snippets of your rendering and shader code?


viewtopic.php?f=2&t=177

Here you go :) This time it's working a bit better and has more explanations on how. Hope it will help!


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Triplanar texturing
PostPosted: Wed Mar 23, 2011 12:12 pm 
User avatar

Joined: Wed Jan 26, 2011 3:20 pm
Posts: 203
Location: Germany
ok... I figured out what my problem was (yes I had no clue about what shaders really are until... 1 hour ago)
well now it works, but I'm still trying to figure out why ^^
I converted ape's triplanar texture shaders to glsl...

is the above cg or hlsl? I really can't figure it out :/


Attachments:
screenshot03232011_131025824.jpg
screenshot03232011_131025824.jpg [ 62.6 KiB | Viewed 8923 times ]
Top
Offline Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Theme created StylerBB.net